From 33e7f6e9535bffe999d7d98de08150bfcd949787 Mon Sep 17 00:00:00 2001 From: Refael Ackermann <refack@gmail.com> Date: Sun, 21 Oct 2018 14:11:50 -0400 Subject: [PATCH] src: add AliasedBuffer::reserve refactor grow_async_ids_stack PR-URL: https://github.com/nodejs/node/pull/23808 Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Matheus Marchini <mat@mmarchini.me> --- src/aliased_buffer.h | 48 +++++++++++++++++++++++++++++++++++++++----- src/env.cc | 9 +-------- 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/aliased_buffer.h b/src/aliased_buffer.h index 2642b2b2a744f0..cdfd90765fcd86 100644 --- a/src/aliased_buffer.h +++ b/src/aliased_buffer.h @@ -4,7 +4,7 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include "v8.h" -#include "util-inl.h" +#include "util.h" namespace node { @@ -22,7 +22,9 @@ namespace node { * The encapsulation herein provides a placeholder where such writes can be * observed. Any notification APIs will be left as a future exercise. */ -template <class NativeT, class V8T> +template <class NativeT, class V8T, + // SFINAE NativeT to be scalar + typename = std::enable_if_t<std::is_scalar<NativeT>::value>> class AliasedBuffer { public: AliasedBuffer(v8::Isolate* isolate, const size_t count) @@ -33,14 +35,14 @@ class AliasedBuffer { CHECK_GT(count, 0); const v8::HandleScope handle_scope(isolate_); - const size_t sizeInBytes = sizeof(NativeT) * count; + const size_t size_in_bytes = sizeof(NativeT) * count; // allocate native buffer buffer_ = Calloc<NativeT>(count); // allocate v8 ArrayBuffer v8::Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New( - isolate_, buffer_, sizeInBytes); + isolate_, buffer_, size_in_bytes); // allocate v8 TypedArray v8::Local<V8T> js_array = V8T::New(ab, byte_offset_, count); @@ -55,6 +57,7 @@ class AliasedBuffer { * * Note that byte_offset must by aligned by sizeof(NativeT). */ + // TODO(refack): refactor into a non-owning `AliasedBufferView` AliasedBuffer(v8::Isolate* isolate, const size_t byte_offset, const size_t count, @@ -96,7 +99,7 @@ class AliasedBuffer { js_array_.Reset(); } - AliasedBuffer& operator=(AliasedBuffer&& that) { + AliasedBuffer& operator=(AliasedBuffer&& that) noexcept { this->~AliasedBuffer(); isolate_ = that.isolate_; count_ = that.count_; @@ -226,6 +229,41 @@ class AliasedBuffer { return count_; } + // Should only be used to extend the array. + // Should only be used on an owning array, not one created as a sub array of + // an owning `AliasedBuffer`. + void reserve(size_t new_capacity) { +#if defined(DEBUG) && DEBUG + CHECK_GE(new_capacity, count_); + CHECK_EQ(byte_offset_, 0); + CHECK(free_buffer_); +#endif + const v8::HandleScope handle_scope(isolate_); + + const size_t old_size_in_bytes = sizeof(NativeT) * count_; + const size_t new_size_in_bytes = sizeof(NativeT) * new_capacity; + + // allocate new native buffer + NativeT* new_buffer = Calloc<NativeT>(new_capacity); + // copy old content + memcpy(new_buffer, buffer_, old_size_in_bytes); + + // allocate v8 new ArrayBuffer + v8::Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New( + isolate_, new_buffer, new_size_in_bytes); + + // allocate v8 TypedArray + v8::Local<V8T> js_array = V8T::New(ab, byte_offset_, new_capacity); + + // move over old v8 TypedArray + js_array_ = std::move(v8::Global<V8T>(isolate_, js_array)); + + // Free old buffer and set new values + free(buffer_); + buffer_ = new_buffer; + count_ = new_capacity; + } + private: v8::Isolate* isolate_; size_t count_; diff --git a/src/env.cc b/src/env.cc index a1b24a2f15b9fe..4fdfcafaa142b6 100644 --- a/src/env.cc +++ b/src/env.cc @@ -828,14 +828,7 @@ void Environment::CollectUVExceptionInfo(v8::Local<v8::Value> object, void Environment::AsyncHooks::grow_async_ids_stack() { - const uint32_t old_capacity = async_ids_stack_.Length() / 2; - const uint32_t new_capacity = old_capacity * 1.5; - AliasedBuffer<double, v8::Float64Array> new_buffer( - env()->isolate(), new_capacity * 2); - - for (uint32_t i = 0; i < old_capacity * 2; ++i) - new_buffer[i] = async_ids_stack_[i]; - async_ids_stack_ = std::move(new_buffer); + async_ids_stack_.reserve(async_ids_stack_.Length() * 3); env()->async_hooks_binding()->Set( env()->context(),