From 5cd2ec8bd504b38c9634c33403123938e25070a3 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Tue, 13 Feb 2024 16:38:39 +0100 Subject: [PATCH] src: implement v8 array iteration using the new callback-based API Using this to iterate over an array can be faster than calling Array::Get repeatedly. Local experiment shows that this is faster once the array size is bigger than 2. PR-URL: /~https://github.com/nodejs/node/pull/51758 Reviewed-By: Yagiz Nizipli Reviewed-By: Chengzhong Wu --- src/util-inl.h | 23 +++++++++++++++++++++++ src/util.h | 10 ++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/util-inl.h b/src/util-inl.h index 864f6d86cdf689..80444d73a92fd5 100644 --- a/src/util-inl.h +++ b/src/util-inl.h @@ -401,6 +401,29 @@ inline char* UncheckedCalloc(size_t n) { return UncheckedCalloc(n); } // headers than we really need to. void ThrowErrStringTooLong(v8::Isolate* isolate); +struct ArrayIterationData { + std::vector>* out; + v8::Isolate* isolate = nullptr; +}; + +inline v8::Array::CallbackResult PushItemToVector(uint32_t index, + v8::Local element, + void* data) { + auto vec = static_cast(data)->out; + auto isolate = static_cast(data)->isolate; + vec->push_back(v8::Global(isolate, element)); + return v8::Array::CallbackResult::kContinue; +} + +v8::Maybe FromV8Array(v8::Local context, + v8::Local js_array, + std::vector>* out) { + uint32_t count = js_array->Length(); + out->reserve(count); + ArrayIterationData data{out, context->GetIsolate()}; + return js_array->Iterate(context, PushItemToVector, &data); +} + v8::MaybeLocal ToV8Value(v8::Local context, std::string_view str, v8::Isolate* isolate) { diff --git a/src/util.h b/src/util.h index 83e5d226701b9b..a9d1ec039e8517 100644 --- a/src/util.h +++ b/src/util.h @@ -697,6 +697,16 @@ struct FunctionDeleter { template using DeleteFnPtr = typename FunctionDeleter::Pointer; +// Convert a v8::Array into an std::vector using the callback-based API. +// This can be faster than calling Array::Get() repeatedly when the array +// has more than 2 entries. +// Note that iterating over an array in C++ and performing operations on each +// element in a C++ loop is still slower than iterating over the array in JS +// and calling into native in the JS loop repeatedly on each element, +// as of V8 11.9. +inline v8::Maybe FromV8Array(v8::Local context, + v8::Local js_array, + std::vector>* out); std::vector SplitString(const std::string_view in, const std::string_view delim);