From 7328b6f8111f2fdc7c676cb90c25eb5e421f0a79 Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Mon, 29 Jul 2024 07:30:54 +0200 Subject: [PATCH] fixup: fast call --- lib/buffer.js | 14 ++++---------- src/node_buffer.cc | 41 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/lib/buffer.js b/lib/buffer.js index 54fa97202057c4..23149e09d64a0c 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -58,7 +58,7 @@ const { byteLengthUtf8, compare: _compare, compareOffset, - copyArrayBuffer, + copy: _copy, createFromString, fill: bindingFill, isAscii: bindingIsAscii, @@ -204,7 +204,7 @@ function toInteger(n, defaultVal) { return defaultVal; } -function _copy(source, target, targetStart, sourceStart, sourceEnd) { +function copyImpl(source, target, targetStart, sourceStart, sourceEnd) { if (!isUint8Array(source)) throw new ERR_INVALID_ARG_TYPE('source', ['Buffer', 'Uint8Array'], source); if (!isUint8Array(target)) @@ -253,13 +253,7 @@ function _copyActual(source, target, targetStart, sourceStart, sourceEnd) { return 0; if (sourceStart !== 0 || sourceEnd < source.length) { - copyArrayBuffer( - target.buffer, - target.byteOffset + targetStart, - source.buffer, - source.byteOffset + sourceStart, - nb, - ); + _copy(source, target, targetStart, sourceStart, sourceEnd); } else { TypedArrayPrototypeSet(target, source, targetStart); } @@ -816,7 +810,7 @@ ObjectDefineProperty(Buffer.prototype, 'offset', { Buffer.prototype.copy = function copy(target, targetStart, sourceStart, sourceEnd) { - return _copy(this, target, targetStart, sourceStart, sourceEnd); + return copyImpl(this, target, targetStart, sourceStart, sourceEnd); }; // No need to verify that "buf.length <= MAX_UINT32" since it's a read-only diff --git a/src/node_buffer.cc b/src/node_buffer.cc index 300060f9d24290..def87d226fce70 100644 --- a/src/node_buffer.cc +++ b/src/node_buffer.cc @@ -569,7 +569,7 @@ void StringSlice(const FunctionCallbackInfo& args) { } // bytesCopied = copy(buffer, target[, targetStart][, sourceStart][, sourceEnd]) -void Copy(const FunctionCallbackInfo &args) { +void SlowCopy(const FunctionCallbackInfo &args) { Environment* env = Environment::GetCurrent(args); THROW_AND_RETURN_UNLESS_BUFFER(env, args[0]); @@ -606,6 +606,39 @@ void Copy(const FunctionCallbackInfo &args) { args.GetReturnValue().Set(to_copy); } +size_t FastCopy(Local receiver, + Local source_obj, + Local target_obj, + size_t target_start, + size_t source_start, + size_t source_end) { + ArrayBufferViewContents source(source_obj); + SPREAD_BUFFER_ARG(target_obj, target); + + // Copy 0 bytes; we're done + if (target_start >= target_length || source_start >= source_end) + return 0; + + if (source_start > source.length()) { + // TODO (fix): V8 12.8 allows throwing in fast call. + assert(false); + return 0; + } + + if (source_end - source_start > target_length - target_start) + source_end = source_start + target_length - target_start; + + uint32_t to_copy = std::min( + std::min(source_end - source_start, target_length - target_start), + source.length() - source_start); + + memmove(target_data + target_start, source.data() + source_start, to_copy); + + return to_copy; +} + +static v8::CFunction fast_copy( + v8::CFunction::Make(FastCopy)); void Fill(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); @@ -1275,7 +1308,7 @@ void Initialize(Local target, "byteLengthUtf8", SlowByteLengthUtf8, &fast_byte_length_utf8); - SetMethod(context, target, "copy", Copy); + SetFastMethod(context, target, "copy", SlowCopy, &fast_copy); SetMethodNoSideEffect(context, target, "compare", Compare); SetMethodNoSideEffect(context, target, "compareOffset", CompareOffset); SetMethod(context, target, "fill", Fill); @@ -1334,7 +1367,9 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) { registry->Register(SlowByteLengthUtf8); registry->Register(fast_byte_length_utf8.GetTypeInfo()); registry->Register(FastByteLengthUtf8); - registry->Register(Copy); + registry->Register(SlowCopy); + registry->Register(fast_copy.GetTypeInfo()); + registry->Register(FastCopy); registry->Register(Compare); registry->Register(CompareOffset); registry->Register(Fill);