From b3e103466085312f5431253af8a1cb6f41629dc5 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Sat, 11 Feb 2023 17:49:32 +0100 Subject: [PATCH] buffer: use v8 fast API calls for `Buffer.byteLength` implementation Use v8 fast API calls for Buffer.byteLength with sequential one-byte strings. PR-URL: https://github.com/nodejs/node/pull/46616 Reviewed-By: Anna Henningsen Reviewed-By: Robert Nagy Reviewed-By: Yagiz Nizipli Reviewed-By: James M Snell --- src/node_buffer.cc | 28 +++++++++++++++++++++++++--- src/node_external_reference.h | 3 +++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/node_buffer.cc b/src/node_buffer.cc index 4bc7336e8d6033..fae5b8431926ee 100644 --- a/src/node_buffer.cc +++ b/src/node_buffer.cc @@ -32,6 +32,7 @@ #include "string_bytes.h" #include "string_search.h" #include "util-inl.h" +#include "v8-fast-api-calls.h" #include "v8.h" #include @@ -786,7 +787,7 @@ void StringWrite(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(written); } -void ByteLengthUtf8(const FunctionCallbackInfo &args) { +void SlowByteLengthUtf8(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); CHECK(args[0]->IsString()); @@ -794,6 +795,21 @@ void ByteLengthUtf8(const FunctionCallbackInfo &args) { args.GetReturnValue().Set(args[0].As()->Utf8Length(env->isolate())); } +uint32_t FastByteLengthUtf8(Local receiver, + const v8::FastOneByteString& source) { + uint32_t result = 0; + uint32_t length = source.length; + const uint8_t* data = reinterpret_cast(source.data); + for (uint32_t i = 0; i < length; ++i) { + result += (data[i] >> 7); + } + result += length; + return result; +} + +static v8::CFunction fast_byte_length_utf8( + v8::CFunction::Make(FastByteLengthUtf8)); + // Normalize val to be an integer in the range of [1, -1] since // implementations of memcmp() can vary by platform. static int normalizeCompareVal(int val, size_t a_length, size_t b_length) { @@ -1368,7 +1384,11 @@ void Initialize(Local target, SetMethodNoSideEffect(context, target, "createFromString", CreateFromString); SetMethodNoSideEffect(context, target, "decodeUTF8", DecodeUTF8); - SetMethodNoSideEffect(context, target, "byteLengthUtf8", ByteLengthUtf8); + SetFastMethodNoSideEffect(context, + target, + "byteLengthUtf8", + SlowByteLengthUtf8, + &fast_byte_length_utf8); SetMethod(context, target, "copy", Copy); SetMethodNoSideEffect(context, target, "compare", Compare); SetMethodNoSideEffect(context, target, "compareOffset", CompareOffset); @@ -1429,7 +1449,9 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) { registry->Register(CreateFromString); registry->Register(DecodeUTF8); - registry->Register(ByteLengthUtf8); + registry->Register(SlowByteLengthUtf8); + registry->Register(fast_byte_length_utf8.GetTypeInfo()); + registry->Register(FastByteLengthUtf8); registry->Register(Copy); registry->Register(Compare); registry->Register(CompareOffset); diff --git a/src/node_external_reference.h b/src/node_external_reference.h index 38ba3b21a74a69..063dd4cb794422 100644 --- a/src/node_external_reference.h +++ b/src/node_external_reference.h @@ -10,6 +10,8 @@ namespace node { +using CFunctionCallbackWithOneByteString = + uint32_t (*)(v8::Local, const v8::FastOneByteString&); using CFunctionCallback = void (*)(v8::Local receiver); // This class manages the external references from the V8 heap @@ -20,6 +22,7 @@ class ExternalReferenceRegistry { #define ALLOWED_EXTERNAL_REFERENCE_TYPES(V) \ V(CFunctionCallback) \ + V(CFunctionCallbackWithOneByteString) \ V(const v8::CFunctionInfo*) \ V(v8::FunctionCallback) \ V(v8::AccessorGetterCallback) \