From 6b117f7ef3662891759c029db043dc939b78b793 Mon Sep 17 00:00:00 2001 From: Renegade334 Date: Tue, 29 Sep 2026 23:14:59 +0200 Subject: [PATCH] src: use native CopyArrayBufferBytes for webstream buffer copy Signed-off-by: Renegade334 --- src/node_buffer.cc | 80 +++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 43 deletions(-) diff --git a/src/node_buffer.cc b/src/node_buffer.cc index 67ba73dd488..c04c9d4c8f2 100644 --- a/src/node_buffer.cc +++ b/src/node_buffer.cc @@ -1655,27 +1655,16 @@ static void SetDetachKey(const FunctionCallbackInfo& args) { ab->SetDetachKey(key); } -namespace { - -std::pair DecomposeBufferToParts(Local buffer) { - void* pointer; - size_t byte_length; - if (buffer->IsArrayBuffer()) { - Local ab = buffer.As(); - pointer = ab->Data(); - byte_length = ab->ByteLength(); - } else if (buffer->IsSharedArrayBuffer()) { - Local ab = buffer.As(); - pointer = ab->Data(); - byte_length = ab->ByteLength(); - } else { - UNREACHABLE(); // Caller must validate. - } - return {pointer, byte_length}; +void CopyArrayBufferImpl(Local target, + uint32_t target_start, + Local source, + uint32_t source_start, + uint32_t bytes_to_copy) { + uint32_t bytes_copied = source->CopyArrayBufferBytes( + source_start, bytes_to_copy, target, target_start); + CHECK_EQ(bytes_copied, bytes_to_copy); } -} // namespace - void CopyArrayBuffer(const FunctionCallbackInfo& args) { // args[0] == Destination ArrayBuffer // args[1] == Destination ArrayBuffer Offset @@ -1683,37 +1672,37 @@ void CopyArrayBuffer(const FunctionCallbackInfo& args) { // args[3] == Source ArrayBuffer Offset // args[4] == bytesToCopy - CHECK(args[0]->IsArrayBuffer() || args[0]->IsSharedArrayBuffer()); + CHECK(args[0]->IsArrayBuffer()); CHECK(args[1]->IsUint32()); - CHECK(args[2]->IsArrayBuffer() || args[2]->IsSharedArrayBuffer()); + CHECK(args[2]->IsArrayBuffer()); CHECK(args[3]->IsUint32()); CHECK(args[4]->IsUint32()); - void* destination; - size_t destination_byte_length; - std::tie(destination, destination_byte_length) = - DecomposeBufferToParts(args[0]); - - void* source; - size_t source_byte_length; - std::tie(source, source_byte_length) = DecomposeBufferToParts(args[2]); - - uint32_t destination_offset = args[1].As()->Value(); - uint32_t source_offset = args[3].As()->Value(); - size_t bytes_to_copy = args[4].As()->Value(); + CopyArrayBufferImpl(args[0].As(), + args[1].As()->Value(), + args[2].As(), + args[3].As()->Value(), + args[4].As()->Value()); +} - // Assert the offsets are within bounds before the subtractions below, which - // would otherwise underflow and defeat the bytes_to_copy bounds checks. - CHECK_LE(destination_offset, destination_byte_length); - CHECK_LE(source_offset, source_byte_length); - CHECK_GE(destination_byte_length - destination_offset, bytes_to_copy); - CHECK_GE(source_byte_length - source_offset, bytes_to_copy); +void FastCopyArrayBuffer(Local receiver, + Local target, + uint32_t target_start, + Local source, + uint32_t source_start, + uint32_t bytes_to_copy) { + CHECK(target->IsArrayBuffer()); + CHECK(source->IsArrayBuffer()); - uint8_t* dest = static_cast(destination) + destination_offset; - uint8_t* src = static_cast(source) + source_offset; - memcpy(dest, src, bytes_to_copy); + CopyArrayBufferImpl(target.As(), + target_start, + source.As(), + source_start, + bytes_to_copy); } +static CFunction fast_copy_array_buffer(CFunction::Make(FastCopyArrayBuffer)); + // Converts a number parameter to size_t suitable for ArrayBuffer sizes // Could be larger than uint32_t // See v8::internal::TryNumberToSize and v8::internal::NumberToSize @@ -1937,7 +1926,11 @@ void Initialize(Local target, &fast_index_of_number); SetMethodNoSideEffect(context, target, "indexOfString", IndexOfString); - SetMethod(context, target, "copyArrayBuffer", CopyArrayBuffer); + SetFastMethod(context, + target, + "copyArrayBuffer", + CopyArrayBuffer, + &fast_copy_array_buffer); SetMethodNoSideEffect( context, target, "createUnsafeArrayBuffer", CreateUnsafeArrayBuffer); SetMethodNoSideEffect( @@ -2060,6 +2053,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) { registry->Register(StringWrite); registry->Register(CopyArrayBuffer); + registry->Register(fast_copy_array_buffer); registry->Register(CreateUnsafeArrayBuffer); registry->Register(ArrayBufferAlignedOffset);