Skip to content

Commit 0e3addd

Browse files
committed
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: #26525 Reviewed-By: Gireesh Punathil <[email protected]> Reviewed-By: Joyee Cheung <[email protected]>
1 parent 17ab2ed commit 0e3addd

File tree

7 files changed

+49
-17
lines changed

7 files changed

+49
-17
lines changed

src/api/environment.cc

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ static void OnMessage(Local<Message> message, Local<Value> error) {
6868
}
6969
}
7070

71-
void* ArrayBufferAllocator::Allocate(size_t size) {
71+
void* NodeArrayBufferAllocator::Allocate(size_t size) {
7272
if (zero_fill_field_ || per_process::cli_options->zero_fill_all_buffers)
7373
return UncheckedCalloc(size);
7474
else
@@ -81,29 +81,29 @@ DebuggingArrayBufferAllocator::~DebuggingArrayBufferAllocator() {
8181

8282
void* DebuggingArrayBufferAllocator::Allocate(size_t size) {
8383
Mutex::ScopedLock lock(mutex_);
84-
void* data = ArrayBufferAllocator::Allocate(size);
84+
void* data = NodeArrayBufferAllocator::Allocate(size);
8585
RegisterPointerInternal(data, size);
8686
return data;
8787
}
8888

8989
void* DebuggingArrayBufferAllocator::AllocateUninitialized(size_t size) {
9090
Mutex::ScopedLock lock(mutex_);
91-
void* data = ArrayBufferAllocator::AllocateUninitialized(size);
91+
void* data = NodeArrayBufferAllocator::AllocateUninitialized(size);
9292
RegisterPointerInternal(data, size);
9393
return data;
9494
}
9595

9696
void DebuggingArrayBufferAllocator::Free(void* data, size_t size) {
9797
Mutex::ScopedLock lock(mutex_);
9898
UnregisterPointerInternal(data, size);
99-
ArrayBufferAllocator::Free(data, size);
99+
NodeArrayBufferAllocator::Free(data, size);
100100
}
101101

102102
void* DebuggingArrayBufferAllocator::Reallocate(void* data,
103103
size_t old_size,
104104
size_t size) {
105105
Mutex::ScopedLock lock(mutex_);
106-
void* ret = ArrayBufferAllocator::Reallocate(data, old_size, size);
106+
void* ret = NodeArrayBufferAllocator::Reallocate(data, old_size, size);
107107
if (ret == nullptr) {
108108
if (size == 0) // i.e. equivalent to free().
109109
UnregisterPointerInternal(data, old_size);
@@ -146,11 +146,15 @@ void DebuggingArrayBufferAllocator::RegisterPointerInternal(void* data,
146146
allocations_[data] = size;
147147
}
148148

149-
ArrayBufferAllocator* CreateArrayBufferAllocator() {
150-
if (per_process::cli_options->debug_arraybuffer_allocations)
151-
return new DebuggingArrayBufferAllocator();
149+
std::unique_ptr<ArrayBufferAllocator> ArrayBufferAllocator::Create(bool debug) {
150+
if (debug || per_process::cli_options->debug_arraybuffer_allocations)
151+
return std::make_unique<DebuggingArrayBufferAllocator>();
152152
else
153-
return new ArrayBufferAllocator();
153+
return std::make_unique<NodeArrayBufferAllocator>();
154+
}
155+
156+
ArrayBufferAllocator* CreateArrayBufferAllocator() {
157+
return ArrayBufferAllocator::Create().release();
154158
}
155159

156160
void FreeArrayBufferAllocator(ArrayBufferAllocator* allocator) {

src/env-inl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ inline v8::ArrayBuffer::Allocator* IsolateData::allocator() const {
5757
return allocator_;
5858
}
5959

60-
inline ArrayBufferAllocator* IsolateData::node_allocator() const {
60+
inline NodeArrayBufferAllocator* IsolateData::node_allocator() const {
6161
return node_allocator_;
6262
}
6363

src/env.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ IsolateData::IsolateData(Isolate* isolate,
8080
: isolate_(isolate),
8181
event_loop_(event_loop),
8282
allocator_(isolate->GetArrayBufferAllocator()),
83-
node_allocator_(node_allocator),
83+
node_allocator_(node_allocator == nullptr ?
84+
nullptr : node_allocator->GetImpl()),
8485
uses_node_allocator_(allocator_ == node_allocator_),
8586
platform_(platform) {
8687
CHECK_NOT_NULL(allocator_);

src/env.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ class IsolateData {
408408

409409
inline bool uses_node_allocator() const;
410410
inline v8::ArrayBuffer::Allocator* allocator() const;
411-
inline ArrayBufferAllocator* node_allocator() const;
411+
inline NodeArrayBufferAllocator* node_allocator() const;
412412

413413
#define VP(PropertyName, StringValue) V(v8::Private, PropertyName)
414414
#define VY(PropertyName, StringValue) V(v8::Symbol, PropertyName)
@@ -443,7 +443,7 @@ class IsolateData {
443443
v8::Isolate* const isolate_;
444444
uv_loop_t* const event_loop_;
445445
v8::ArrayBuffer::Allocator* const allocator_;
446-
ArrayBufferAllocator* const node_allocator_;
446+
NodeArrayBufferAllocator* const node_allocator_;
447447
const bool uses_node_allocator_;
448448
MultiIsolatePlatform* platform_;
449449
std::shared_ptr<PerIsolateOptions> options_;

src/node.h

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@
6464
#include "v8-platform.h" // NOLINT(build/include_order)
6565
#include "node_version.h" // NODE_MODULE_VERSION
6666

67+
#include <memory>
68+
6769
#define NODE_MAKE_VERSION(major, minor, patch) \
6870
((major) * 0x1000 + (minor) * 0x100 + (patch))
6971

@@ -210,8 +212,30 @@ NODE_EXTERN void Init(int* argc,
210212
int* exec_argc,
211213
const char*** exec_argv);
212214

213-
class ArrayBufferAllocator;
215+
class NodeArrayBufferAllocator;
216+
217+
// An ArrayBuffer::Allocator class with some Node.js-specific tweaks. If you do
218+
// not have to use another allocator, using this class is recommended:
219+
// - It supports Buffer.allocUnsafe() and Buffer.allocUnsafeSlow() with
220+
// uninitialized memory.
221+
// - It supports transferring, rather than copying, ArrayBuffers when using
222+
// MessagePorts.
223+
class NODE_EXTERN ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
224+
public:
225+
// If `always_debug` is true, create an ArrayBuffer::Allocator instance
226+
// that performs additional integrity checks (e.g. make sure that only memory
227+
// that was allocated by the it is also freed by it).
228+
// This can also be set using the --debug-arraybuffer-allocations flag.
229+
static std::unique_ptr<ArrayBufferAllocator> Create(
230+
bool always_debug = false);
231+
232+
private:
233+
virtual NodeArrayBufferAllocator* GetImpl() = 0;
234+
235+
friend class IsolateData;
236+
};
214237

238+
// Legacy equivalents for ArrayBufferAllocator::Create().
215239
NODE_EXTERN ArrayBufferAllocator* CreateArrayBufferAllocator();
216240
NODE_EXTERN void FreeArrayBufferAllocator(ArrayBufferAllocator* allocator);
217241

src/node_buffer.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1104,7 +1104,8 @@ void Initialize(Local<Object> target,
11041104

11051105
// It can be a nullptr when running inside an isolate where we
11061106
// do not own the ArrayBuffer allocator.
1107-
if (ArrayBufferAllocator* allocator = env->isolate_data()->node_allocator()) {
1107+
if (NodeArrayBufferAllocator* allocator =
1108+
env->isolate_data()->node_allocator()) {
11081109
uint32_t* zero_fill_field = allocator->zero_fill_field();
11091110
Local<ArrayBuffer> array_buffer = ArrayBuffer::New(
11101111
env->isolate(), zero_fill_field, sizeof(*zero_fill_field));

src/node_internals.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ namespace task_queue {
101101
void PromiseRejectCallback(v8::PromiseRejectMessage message);
102102
} // namespace task_queue
103103

104-
class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
104+
class NodeArrayBufferAllocator : public ArrayBufferAllocator {
105105
public:
106106
inline uint32_t* zero_fill_field() { return &zero_fill_field_; }
107107

@@ -116,11 +116,13 @@ class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
116116
virtual void RegisterPointer(void* data, size_t size) {}
117117
virtual void UnregisterPointer(void* data, size_t size) {}
118118

119+
NodeArrayBufferAllocator* GetImpl() final { return this; }
120+
119121
private:
120122
uint32_t zero_fill_field_ = 1; // Boolean but exposed as uint32 to JS land.
121123
};
122124

123-
class DebuggingArrayBufferAllocator final : public ArrayBufferAllocator {
125+
class DebuggingArrayBufferAllocator final : public NodeArrayBufferAllocator {
124126
public:
125127
~DebuggingArrayBufferAllocator() override;
126128
void* Allocate(size_t size) override;

0 commit comments

Comments
 (0)