diff options
author | Anna Henningsen <anna@addaleax.net> | 2019-03-08 16:19:33 +0100 |
---|---|---|
committer | Anna Henningsen <anna@addaleax.net> | 2019-03-13 09:14:14 +0000 |
commit | 0e3adddd0d6e5d90b5224c62ef26b561320d1cff (patch) | |
tree | 919a9a4555026d9d04395f8695c2aebd2c380424 /src | |
parent | 17ab2ed3c885d75ee13286cd31c14ea136d00918 (diff) | |
download | android-node-v8-0e3adddd0d6e5d90b5224c62ef26b561320d1cff.tar.gz android-node-v8-0e3adddd0d6e5d90b5224c62ef26b561320d1cff.tar.bz2 android-node-v8-0e3adddd0d6e5d90b5224c62ef26b561320d1cff.zip |
embedding: refactor public `ArrayBufferAllocator` API
Use a RAII approach by default, and make it possible for embedders
to use the `ArrayBufferAllocator` directly as a V8
`ArrayBuffer::Allocator`, e.g. when passing to `Isolate::CreateParams`
manually.
PR-URL: https://github.com/nodejs/node/pull/26525
Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/api/environment.cc | 22 | ||||
-rw-r--r-- | src/env-inl.h | 2 | ||||
-rw-r--r-- | src/env.cc | 3 | ||||
-rw-r--r-- | src/env.h | 4 | ||||
-rw-r--r-- | src/node.h | 26 | ||||
-rw-r--r-- | src/node_buffer.cc | 3 | ||||
-rw-r--r-- | src/node_internals.h | 6 |
7 files changed, 49 insertions, 17 deletions
diff --git a/src/api/environment.cc b/src/api/environment.cc index 35d93f1cc8..421735a82a 100644 --- a/src/api/environment.cc +++ b/src/api/environment.cc @@ -68,7 +68,7 @@ static void OnMessage(Local<Message> message, Local<Value> error) { } } -void* ArrayBufferAllocator::Allocate(size_t size) { +void* NodeArrayBufferAllocator::Allocate(size_t size) { if (zero_fill_field_ || per_process::cli_options->zero_fill_all_buffers) return UncheckedCalloc(size); else @@ -81,14 +81,14 @@ DebuggingArrayBufferAllocator::~DebuggingArrayBufferAllocator() { void* DebuggingArrayBufferAllocator::Allocate(size_t size) { Mutex::ScopedLock lock(mutex_); - void* data = ArrayBufferAllocator::Allocate(size); + void* data = NodeArrayBufferAllocator::Allocate(size); RegisterPointerInternal(data, size); return data; } void* DebuggingArrayBufferAllocator::AllocateUninitialized(size_t size) { Mutex::ScopedLock lock(mutex_); - void* data = ArrayBufferAllocator::AllocateUninitialized(size); + void* data = NodeArrayBufferAllocator::AllocateUninitialized(size); RegisterPointerInternal(data, size); return data; } @@ -96,14 +96,14 @@ void* DebuggingArrayBufferAllocator::AllocateUninitialized(size_t size) { void DebuggingArrayBufferAllocator::Free(void* data, size_t size) { Mutex::ScopedLock lock(mutex_); UnregisterPointerInternal(data, size); - ArrayBufferAllocator::Free(data, size); + NodeArrayBufferAllocator::Free(data, size); } void* DebuggingArrayBufferAllocator::Reallocate(void* data, size_t old_size, size_t size) { Mutex::ScopedLock lock(mutex_); - void* ret = ArrayBufferAllocator::Reallocate(data, old_size, size); + void* ret = NodeArrayBufferAllocator::Reallocate(data, old_size, size); if (ret == nullptr) { if (size == 0) // i.e. equivalent to free(). UnregisterPointerInternal(data, old_size); @@ -146,11 +146,15 @@ void DebuggingArrayBufferAllocator::RegisterPointerInternal(void* data, allocations_[data] = size; } -ArrayBufferAllocator* CreateArrayBufferAllocator() { - if (per_process::cli_options->debug_arraybuffer_allocations) - return new DebuggingArrayBufferAllocator(); +std::unique_ptr<ArrayBufferAllocator> ArrayBufferAllocator::Create(bool debug) { + if (debug || per_process::cli_options->debug_arraybuffer_allocations) + return std::make_unique<DebuggingArrayBufferAllocator>(); else - return new ArrayBufferAllocator(); + return std::make_unique<NodeArrayBufferAllocator>(); +} + +ArrayBufferAllocator* CreateArrayBufferAllocator() { + return ArrayBufferAllocator::Create().release(); } void FreeArrayBufferAllocator(ArrayBufferAllocator* allocator) { diff --git a/src/env-inl.h b/src/env-inl.h index 3426393901..8c37b393dc 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -57,7 +57,7 @@ inline v8::ArrayBuffer::Allocator* IsolateData::allocator() const { return allocator_; } -inline ArrayBufferAllocator* IsolateData::node_allocator() const { +inline NodeArrayBufferAllocator* IsolateData::node_allocator() const { return node_allocator_; } diff --git a/src/env.cc b/src/env.cc index d791e41f92..a1870785a8 100644 --- a/src/env.cc +++ b/src/env.cc @@ -80,7 +80,8 @@ IsolateData::IsolateData(Isolate* isolate, : isolate_(isolate), event_loop_(event_loop), allocator_(isolate->GetArrayBufferAllocator()), - node_allocator_(node_allocator), + node_allocator_(node_allocator == nullptr ? + nullptr : node_allocator->GetImpl()), uses_node_allocator_(allocator_ == node_allocator_), platform_(platform) { CHECK_NOT_NULL(allocator_); @@ -408,7 +408,7 @@ class IsolateData { inline bool uses_node_allocator() const; inline v8::ArrayBuffer::Allocator* allocator() const; - inline ArrayBufferAllocator* node_allocator() const; + inline NodeArrayBufferAllocator* node_allocator() const; #define VP(PropertyName, StringValue) V(v8::Private, PropertyName) #define VY(PropertyName, StringValue) V(v8::Symbol, PropertyName) @@ -443,7 +443,7 @@ class IsolateData { v8::Isolate* const isolate_; uv_loop_t* const event_loop_; v8::ArrayBuffer::Allocator* const allocator_; - ArrayBufferAllocator* const node_allocator_; + NodeArrayBufferAllocator* const node_allocator_; const bool uses_node_allocator_; MultiIsolatePlatform* platform_; std::shared_ptr<PerIsolateOptions> options_; diff --git a/src/node.h b/src/node.h index 9ccab2e0f8..3aaaf43668 100644 --- a/src/node.h +++ b/src/node.h @@ -64,6 +64,8 @@ #include "v8-platform.h" // NOLINT(build/include_order) #include "node_version.h" // NODE_MODULE_VERSION +#include <memory> + #define NODE_MAKE_VERSION(major, minor, patch) \ ((major) * 0x1000 + (minor) * 0x100 + (patch)) @@ -210,8 +212,30 @@ NODE_EXTERN void Init(int* argc, int* exec_argc, const char*** exec_argv); -class ArrayBufferAllocator; +class NodeArrayBufferAllocator; + +// An ArrayBuffer::Allocator class with some Node.js-specific tweaks. If you do +// not have to use another allocator, using this class is recommended: +// - It supports Buffer.allocUnsafe() and Buffer.allocUnsafeSlow() with +// uninitialized memory. +// - It supports transferring, rather than copying, ArrayBuffers when using +// MessagePorts. +class NODE_EXTERN ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { + public: + // If `always_debug` is true, create an ArrayBuffer::Allocator instance + // that performs additional integrity checks (e.g. make sure that only memory + // that was allocated by the it is also freed by it). + // This can also be set using the --debug-arraybuffer-allocations flag. + static std::unique_ptr<ArrayBufferAllocator> Create( + bool always_debug = false); + + private: + virtual NodeArrayBufferAllocator* GetImpl() = 0; + + friend class IsolateData; +}; +// Legacy equivalents for ArrayBufferAllocator::Create(). NODE_EXTERN ArrayBufferAllocator* CreateArrayBufferAllocator(); NODE_EXTERN void FreeArrayBufferAllocator(ArrayBufferAllocator* allocator); diff --git a/src/node_buffer.cc b/src/node_buffer.cc index 10b8f4098f..baf3ff5010 100644 --- a/src/node_buffer.cc +++ b/src/node_buffer.cc @@ -1104,7 +1104,8 @@ void Initialize(Local<Object> target, // It can be a nullptr when running inside an isolate where we // do not own the ArrayBuffer allocator. - if (ArrayBufferAllocator* allocator = env->isolate_data()->node_allocator()) { + if (NodeArrayBufferAllocator* allocator = + env->isolate_data()->node_allocator()) { uint32_t* zero_fill_field = allocator->zero_fill_field(); Local<ArrayBuffer> array_buffer = ArrayBuffer::New( env->isolate(), zero_fill_field, sizeof(*zero_fill_field)); diff --git a/src/node_internals.h b/src/node_internals.h index 2e492727bb..355e4ae9fd 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -101,7 +101,7 @@ namespace task_queue { void PromiseRejectCallback(v8::PromiseRejectMessage message); } // namespace task_queue -class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { +class NodeArrayBufferAllocator : public ArrayBufferAllocator { public: inline uint32_t* zero_fill_field() { return &zero_fill_field_; } @@ -116,11 +116,13 @@ class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { virtual void RegisterPointer(void* data, size_t size) {} virtual void UnregisterPointer(void* data, size_t size) {} + NodeArrayBufferAllocator* GetImpl() final { return this; } + private: uint32_t zero_fill_field_ = 1; // Boolean but exposed as uint32 to JS land. }; -class DebuggingArrayBufferAllocator final : public ArrayBufferAllocator { +class DebuggingArrayBufferAllocator final : public NodeArrayBufferAllocator { public: ~DebuggingArrayBufferAllocator() override; void* Allocate(size_t size) override; |