Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
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: #46616
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Robert Nagy <ronagy@icloud.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
joyeecheung authored and aduh95 committed Feb 26, 2023
commit ee1ce1872ff38fc5a2fd3b2e3a97600e5d6b2e14
28 changes: 25 additions & 3 deletions src/node_buffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 <cstring>
Expand Down Expand Up @@ -786,14 +787,29 @@ void StringWrite(const FunctionCallbackInfo<Value>& args) {
args.GetReturnValue().Set(written);
}

void ByteLengthUtf8(const FunctionCallbackInfo<Value> &args) {
void SlowByteLengthUtf8(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
CHECK(args[0]->IsString());

// Fast case: avoid StringBytes on UTF8 string. Jump to v8.
args.GetReturnValue().Set(args[0].As<String>()->Utf8Length(env->isolate()));
}

uint32_t FastByteLengthUtf8(Local<Value> receiver,
const v8::FastOneByteString& source) {
uint32_t result = 0;
uint32_t length = source.length;
const uint8_t* data = reinterpret_cast<const uint8_t*>(source.data);
for (uint32_t i = 0; i < length; ++i) {
result += (data[i] >> 7);
}
Comment thread
ronag marked this conversation as resolved.
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) {
Expand Down Expand Up @@ -1368,7 +1384,11 @@ void Initialize(Local<Object> 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);
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions src/node_external_reference.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

namespace node {

using CFunctionCallbackWithOneByteString =
uint32_t (*)(v8::Local<v8::Value>, const v8::FastOneByteString&);
using CFunctionCallback = void (*)(v8::Local<v8::Value> receiver);

// This class manages the external references from the V8 heap
Expand All @@ -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) \
Expand Down