1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-21 15:04:11 -05:00

perf(ext/web): optimize transferArrayBuffer (#16294)

Avoid copying enqueued data + misc optimizations to skip webidl
converter.
This commit is contained in:
Divy Srivastava 2022-10-26 18:28:25 +05:30 committed by GitHub
parent 046ab7dc8a
commit 6cd9343e8b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 50 additions and 27 deletions

View file

@ -60,6 +60,7 @@
WeakMapPrototypeSet, WeakMapPrototypeSet,
} = globalThis.__bootstrap.primordials; } = globalThis.__bootstrap.primordials;
const consoleInternal = window.__bootstrap.console; const consoleInternal = window.__bootstrap.console;
const ops = core.ops;
const { AssertionError, assert } = window.__bootstrap.infra; const { AssertionError, assert } = window.__bootstrap.infra;
/** @template T */ /** @template T */
@ -224,15 +225,9 @@
* @returns {ArrayBufferLike} * @returns {ArrayBufferLike}
*/ */
function transferArrayBuffer(O) { function transferArrayBuffer(O) {
assert(!isDetachedBuffer(O)); const v = ops.op_transfer_arraybuffer(O);
const transferredIshVersion = O.slice(0);
ObjectDefineProperty(O, "byteLength", {
get() {
return 0;
},
});
O[isFakeDetached] = true; O[isFakeDetached] = true;
return transferredIshVersion; return v;
} }
/** /**
@ -4620,26 +4615,32 @@
* @param {UnderlyingSource<R>=} underlyingSource * @param {UnderlyingSource<R>=} underlyingSource
* @param {QueuingStrategy<R>=} strategy * @param {QueuingStrategy<R>=} strategy
*/ */
constructor(underlyingSource = undefined, strategy = {}) { constructor(underlyingSource = undefined, strategy = undefined) {
const prefix = "Failed to construct 'ReadableStream'"; const prefix = "Failed to construct 'ReadableStream'";
if (underlyingSource !== undefined) { if (underlyingSource !== undefined) {
underlyingSource = webidl.converters.object(underlyingSource, { underlyingSource = webidl.converters.object(underlyingSource, {
prefix, prefix,
context: "Argument 1", context: "Argument 1",
}); });
} } else {
strategy = webidl.converters.QueuingStrategy(strategy, {
prefix,
context: "Argument 2",
});
this[webidl.brand] = webidl.brand;
if (underlyingSource === undefined) {
underlyingSource = null; underlyingSource = null;
} }
const underlyingSourceDict = webidl.converters.UnderlyingSource( if (strategy !== undefined) {
underlyingSource, strategy = webidl.converters.QueuingStrategy(strategy, {
{ prefix, context: "underlyingSource" }, prefix,
); context: "Argument 2",
});
} else {
strategy = {};
}
this[webidl.brand] = webidl.brand;
let underlyingSourceDict = {};
if (underlyingSource !== undefined) {
underlyingSourceDict = webidl.converters.UnderlyingSource(
underlyingSource,
{ prefix, context: "underlyingSource" },
);
}
initializeReadableStream(this); initializeReadableStream(this);
if (underlyingSourceDict.type === "bytes") { if (underlyingSourceDict.type === "bytes") {
if (strategy.size !== undefined) { if (strategy.size !== undefined) {
@ -4700,13 +4701,17 @@
* @param {ReadableStreamGetReaderOptions=} options * @param {ReadableStreamGetReaderOptions=} options
* @returns {ReadableStreamDefaultReader<R> | ReadableStreamBYOBReader} * @returns {ReadableStreamDefaultReader<R> | ReadableStreamBYOBReader}
*/ */
getReader(options = {}) { getReader(options = undefined) {
webidl.assertBranded(this, ReadableStreamPrototype); webidl.assertBranded(this, ReadableStreamPrototype);
const prefix = "Failed to execute 'getReader' on 'ReadableStream'"; const prefix = "Failed to execute 'getReader' on 'ReadableStream'";
options = webidl.converters.ReadableStreamGetReaderOptions(options, { if (options !== undefined) {
prefix, options = webidl.converters.ReadableStreamGetReaderOptions(options, {
context: "Argument 1", prefix,
}); context: "Argument 1",
});
} else {
options = {};
}
if (options.mode === undefined) { if (options.mode === undefined) {
return acquireReadableStreamDefaultReader(this); return acquireReadableStreamDefaultReader(this);
} else { } else {

View file

@ -112,6 +112,7 @@ pub fn init<P: TimersPermission + 'static>(
op_timer_handle::decl(), op_timer_handle::decl(),
op_cancel_handle::decl(), op_cancel_handle::decl(),
op_sleep::decl(), op_sleep::decl(),
op_transfer_arraybuffer::decl(),
]) ])
.state(move |state| { .state(move |state| {
state.put(blob_store.clone()); state.put(blob_store.clone());
@ -338,6 +339,23 @@ fn op_encoding_encode_into(
Ok(()) Ok(())
} }
#[op(v8)]
fn op_transfer_arraybuffer<'a>(
scope: &mut v8::HandleScope<'a>,
input: serde_v8::Value<'a>,
) -> Result<serde_v8::Value<'a>, AnyError> {
let ab = v8::Local::<v8::ArrayBuffer>::try_from(input.v8_value)?;
if !ab.is_detachable() {
return Err(type_error("ArrayBuffer is not detachable"));
}
let bs = ab.get_backing_store();
ab.detach();
let ab = v8::ArrayBuffer::with_backing_store(scope, &bs);
Ok(serde_v8::Value {
v8_value: ab.into(),
})
}
#[op] #[op]
fn op_encode_binary_string(s: &[u8]) -> ByteString { fn op_encode_binary_string(s: &[u8]) -> ByteString {
ByteString::from(s) ByteString::from(s)

View file

@ -1302,8 +1302,8 @@
"ReadableStream with byte source: Respond to multiple pull() by separate enqueue()", "ReadableStream with byte source: Respond to multiple pull() by separate enqueue()",
"ReadableStream with byte source: enqueue() discards auto-allocated BYOB request" "ReadableStream with byte source: enqueue() discards auto-allocated BYOB request"
], ],
"non-transferable-buffers.any.html": false, "non-transferable-buffers.any.html": true,
"non-transferable-buffers.any.worker.html": false, "non-transferable-buffers.any.worker.html": true,
"enqueue-with-detached-buffer.window.html": false, "enqueue-with-detached-buffer.window.html": false,
"tee.any.html": true, "tee.any.html": true,
"tee.any.worker.html": true, "tee.any.worker.html": true,