Skip to content

Commit 27e84dd

Browse files
committed
lib,src: clean up ArrayBufferAllocator
Remove the direct dependency on node::Environment (which is per-context) from node::ArrayBufferAllocator (which is per-isolate.) Contexts that want to toggle the zero fill flag, now do so through a field that is owned by ArrayBufferAllocator. Better, still not great. PR-URL: #7082 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Trevor Norris <[email protected]>
1 parent 334ef4f commit 27e84dd

7 files changed

+39
-91
lines changed

lib/buffer.js

+8-10
Original file line numberDiff line numberDiff line change
@@ -59,18 +59,16 @@ Buffer.prototype.swap32 = function swap32() {
5959
return swap32n.apply(this);
6060
};
6161

62-
const flags = bindingObj.flags;
63-
const kNoZeroFill = 0;
62+
// |binding.zeroFill| can be undefined when running inside an isolate where we
63+
// do not own the ArrayBuffer allocator. Zero fill is always on in that case.
64+
const zeroFill = bindingObj.zeroFill || [0];
6465

6566
function createBuffer(size, noZeroFill) {
66-
flags[kNoZeroFill] = noZeroFill ? 1 : 0;
67-
try {
68-
const ui8 = new Uint8Array(size);
69-
Object.setPrototypeOf(ui8, Buffer.prototype);
70-
return ui8;
71-
} finally {
72-
flags[kNoZeroFill] = 0;
73-
}
67+
if (noZeroFill)
68+
zeroFill[0] = 0; // Reset by the runtime.
69+
const ui8 = new Uint8Array(size);
70+
Object.setPrototypeOf(ui8, Buffer.prototype);
71+
return ui8;
7472
}
7573

7674
function createPool() {

src/debug-agent.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,8 @@ void Agent::WorkerRun() {
169169
Isolate::Scope isolate_scope(isolate);
170170

171171
HandleScope handle_scope(isolate);
172-
IsolateData isolate_data(isolate, &child_loop_);
172+
IsolateData isolate_data(isolate, &child_loop_,
173+
array_buffer_allocator.zero_fill_field());
173174
Local<Context> context = Context::New(isolate);
174175

175176
Context::Scope context_scope(context);

src/env-inl.h

+8-28
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ namespace node {
2424
//
2525
// One byte because our strings are ASCII and we can safely skip V8's UTF-8
2626
// decoding step. It's a one-time cost, but why pay it when you don't have to?
27-
inline IsolateData::IsolateData(v8::Isolate* isolate, uv_loop_t* event_loop)
27+
inline IsolateData::IsolateData(v8::Isolate* isolate, uv_loop_t* event_loop,
28+
uint32_t* zero_fill_field)
2829
:
2930
#define V(PropertyName, StringValue) \
3031
PropertyName ## _( \
@@ -48,12 +49,17 @@ inline IsolateData::IsolateData(v8::Isolate* isolate, uv_loop_t* event_loop)
4849
sizeof(StringValue) - 1).ToLocalChecked()),
4950
PER_ISOLATE_STRING_PROPERTIES(V)
5051
#undef V
51-
isolate_(isolate), event_loop_(event_loop) {}
52+
isolate_(isolate), event_loop_(event_loop),
53+
zero_fill_field_(zero_fill_field) {}
5254

5355
inline uv_loop_t* IsolateData::event_loop() const {
5456
return event_loop_;
5557
}
5658

59+
inline uint32_t* IsolateData::zero_fill_field() const {
60+
return zero_fill_field_;
61+
}
62+
5763
inline Environment::AsyncHooks::AsyncHooks() {
5864
for (int i = 0; i < kFieldsCount; i++) fields_[i] = 0;
5965
}
@@ -128,27 +134,6 @@ inline void Environment::TickInfo::set_index(uint32_t value) {
128134
fields_[kIndex] = value;
129135
}
130136

131-
inline Environment::ArrayBufferAllocatorInfo::ArrayBufferAllocatorInfo() {
132-
for (int i = 0; i < kFieldsCount; ++i)
133-
fields_[i] = 0;
134-
}
135-
136-
inline uint32_t* Environment::ArrayBufferAllocatorInfo::fields() {
137-
return fields_;
138-
}
139-
140-
inline int Environment::ArrayBufferAllocatorInfo::fields_count() const {
141-
return kFieldsCount;
142-
}
143-
144-
inline bool Environment::ArrayBufferAllocatorInfo::no_zero_fill() const {
145-
return fields_[kNoZeroFill] != 0;
146-
}
147-
148-
inline void Environment::ArrayBufferAllocatorInfo::reset_fill_flag() {
149-
fields_[kNoZeroFill] = 0;
150-
}
151-
152137
inline Environment* Environment::New(IsolateData* isolate_data,
153138
v8::Local<v8::Context> context) {
154139
Environment* env = new Environment(isolate_data, context);
@@ -318,11 +303,6 @@ inline Environment::TickInfo* Environment::tick_info() {
318303
return &tick_info_;
319304
}
320305

321-
inline Environment::ArrayBufferAllocatorInfo*
322-
Environment::array_buffer_allocator_info() {
323-
return &array_buffer_allocator_info_;
324-
}
325-
326306
inline uint64_t Environment::timer_base() const {
327307
return timer_base_;
328308
}

src/env.h

+5-25
Original file line numberDiff line numberDiff line change
@@ -304,8 +304,10 @@ RB_HEAD(ares_task_list, ares_task_t);
304304

305305
class IsolateData {
306306
public:
307-
inline IsolateData(v8::Isolate* isolate, uv_loop_t* event_loop);
307+
inline IsolateData(v8::Isolate* isolate, uv_loop_t* event_loop,
308+
uint32_t* zero_fill_field = nullptr);
308309
inline uv_loop_t* event_loop() const;
310+
inline uint32_t* zero_fill_field() const;
309311

310312
#define VP(PropertyName, StringValue) V(v8::Private, PropertyName, StringValue)
311313
#define VS(PropertyName, StringValue) V(v8::String, PropertyName, StringValue)
@@ -330,6 +332,7 @@ class IsolateData {
330332

331333
v8::Isolate* const isolate_;
332334
uv_loop_t* const event_loop_;
335+
uint32_t* const zero_fill_field_;
333336

334337
DISALLOW_COPY_AND_ASSIGN(IsolateData);
335338
};
@@ -414,27 +417,6 @@ class Environment {
414417
DISALLOW_COPY_AND_ASSIGN(TickInfo);
415418
};
416419

417-
class ArrayBufferAllocatorInfo {
418-
public:
419-
inline uint32_t* fields();
420-
inline int fields_count() const;
421-
inline bool no_zero_fill() const;
422-
inline void reset_fill_flag();
423-
424-
private:
425-
friend class Environment; // So we can call the constructor.
426-
inline ArrayBufferAllocatorInfo();
427-
428-
enum Fields {
429-
kNoZeroFill,
430-
kFieldsCount
431-
};
432-
433-
uint32_t fields_[kFieldsCount];
434-
435-
DISALLOW_COPY_AND_ASSIGN(ArrayBufferAllocatorInfo);
436-
};
437-
438420
typedef void (*HandleCleanupCb)(Environment* env,
439421
uv_handle_t* handle,
440422
void* arg);
@@ -497,14 +479,14 @@ class Environment {
497479
inline AsyncHooks* async_hooks();
498480
inline DomainFlag* domain_flag();
499481
inline TickInfo* tick_info();
500-
inline ArrayBufferAllocatorInfo* array_buffer_allocator_info();
501482
inline uint64_t timer_base() const;
502483

503484
static inline Environment* from_cares_timer_handle(uv_timer_t* handle);
504485
inline uv_timer_t* cares_timer_handle();
505486
inline ares_channel cares_channel();
506487
inline ares_channel* cares_channel_ptr();
507488
inline ares_task_list* cares_task_list();
489+
inline IsolateData* isolate_data() const;
508490

509491
inline bool using_domains() const;
510492
inline void set_using_domains(bool value);
@@ -602,7 +584,6 @@ class Environment {
602584
private:
603585
inline Environment(IsolateData* isolate_data, v8::Local<v8::Context> context);
604586
inline ~Environment();
605-
inline IsolateData* isolate_data() const;
606587

607588
v8::Isolate* const isolate_;
608589
IsolateData* const isolate_data_;
@@ -613,7 +594,6 @@ class Environment {
613594
AsyncHooks async_hooks_;
614595
DomainFlag domain_flag_;
615596
TickInfo tick_info_;
616-
ArrayBufferAllocatorInfo array_buffer_allocator_info_;
617597
const uint64_t timer_base_;
618598
uv_timer_t cares_timer_handle_;
619599
ares_channel cares_channel_;

src/node.cc

+6-11
Original file line numberDiff line numberDiff line change
@@ -971,11 +971,9 @@ Local<Value> WinapiErrnoException(Isolate* isolate,
971971

972972

973973
void* ArrayBufferAllocator::Allocate(size_t size) {
974-
if (env_ == nullptr ||
975-
!env_->array_buffer_allocator_info()->no_zero_fill() ||
976-
zero_fill_all_buffers)
974+
if (zero_fill_field_ || zero_fill_all_buffers)
977975
return calloc(size, 1);
978-
env_->array_buffer_allocator_info()->reset_fill_flag();
976+
zero_fill_field_ = 1;
979977
return malloc(size);
980978
}
981979

@@ -4363,8 +4361,8 @@ Environment* CreateEnvironment(IsolateData* isolate_data,
43634361
static void StartNodeInstance(void* arg) {
43644362
NodeInstanceData* instance_data = static_cast<NodeInstanceData*>(arg);
43654363
Isolate::CreateParams params;
4366-
ArrayBufferAllocator* array_buffer_allocator = new ArrayBufferAllocator();
4367-
params.array_buffer_allocator = array_buffer_allocator;
4364+
ArrayBufferAllocator array_buffer_allocator;
4365+
params.array_buffer_allocator = &array_buffer_allocator;
43684366
#ifdef NODE_ENABLE_VTUNE_PROFILING
43694367
params.code_event_handler = vTune::GetVtuneCodeEventHandler();
43704368
#endif
@@ -4385,7 +4383,8 @@ static void StartNodeInstance(void* arg) {
43854383
Locker locker(isolate);
43864384
Isolate::Scope isolate_scope(isolate);
43874385
HandleScope handle_scope(isolate);
4388-
IsolateData isolate_data(isolate, instance_data->event_loop());
4386+
IsolateData isolate_data(isolate, instance_data->event_loop(),
4387+
array_buffer_allocator.zero_fill_field());
43894388
Local<Context> context = Context::New(isolate);
43904389
Context::Scope context_scope(context);
43914390
Environment* env = CreateEnvironment(&isolate_data,
@@ -4395,8 +4394,6 @@ static void StartNodeInstance(void* arg) {
43954394
instance_data->exec_argc(),
43964395
instance_data->exec_argv());
43974396

4398-
array_buffer_allocator->set_env(env);
4399-
44004397
isolate->SetAbortOnUncaughtExceptionCallback(
44014398
ShouldAbortOnUncaughtException);
44024399

@@ -4464,7 +4461,6 @@ static void StartNodeInstance(void* arg) {
44644461
__lsan_do_leak_check();
44654462
#endif
44664463

4467-
array_buffer_allocator->set_env(nullptr);
44684464
env->Dispose();
44694465
env = nullptr;
44704466
}
@@ -4477,7 +4473,6 @@ static void StartNodeInstance(void* arg) {
44774473
CHECK_NE(isolate, nullptr);
44784474
isolate->Dispose();
44794475
isolate = nullptr;
4480-
delete array_buffer_allocator;
44814476
}
44824477

44834478
int Start(int argc, char** argv) {

src/node_buffer.cc

+8-12
Original file line numberDiff line numberDiff line change
@@ -1224,18 +1224,14 @@ void SetupBufferJS(const FunctionCallbackInfo<Value>& args) {
12241224

12251225
env->SetMethod(proto, "copy", Copy);
12261226

1227-
CHECK(args[1]->IsObject());
1228-
Local<Object> bObj = args[1].As<Object>();
1229-
1230-
uint32_t* const fields = env->array_buffer_allocator_info()->fields();
1231-
uint32_t const fields_count =
1232-
env->array_buffer_allocator_info()->fields_count();
1233-
1234-
Local<ArrayBuffer> array_buffer =
1235-
ArrayBuffer::New(env->isolate(), fields, sizeof(*fields) * fields_count);
1236-
1237-
bObj->Set(String::NewFromUtf8(env->isolate(), "flags"),
1238-
Uint32Array::New(array_buffer, 0, fields_count));
1227+
if (auto zero_fill_field = env->isolate_data()->zero_fill_field()) {
1228+
CHECK(args[1]->IsObject());
1229+
auto binding_object = args[1].As<Object>();
1230+
auto array_buffer = ArrayBuffer::New(env->isolate(), zero_fill_field, 1);
1231+
auto name = FIXED_ONE_BYTE_STRING(env->isolate(), "zeroFill");
1232+
auto value = Uint32Array::New(array_buffer, 0, 1);
1233+
CHECK(binding_object->Set(env->context(), name, value).FromJust());
1234+
}
12391235
}
12401236

12411237

src/node_internals.h

+2-4
Original file line numberDiff line numberDiff line change
@@ -204,16 +204,14 @@ void ThrowUVException(v8::Isolate* isolate,
204204

205205
class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
206206
public:
207-
ArrayBufferAllocator() : env_(nullptr) { }
208-
209-
inline void set_env(Environment* env) { env_ = env; }
207+
inline uint32_t* zero_fill_field() { return &zero_fill_field_; }
210208

211209
virtual void* Allocate(size_t size); // Defined in src/node.cc
212210
virtual void* AllocateUninitialized(size_t size) { return malloc(size); }
213211
virtual void Free(void* data, size_t) { free(data); }
214212

215213
private:
216-
Environment* env_;
214+
uint32_t zero_fill_field_ = 1; // Boolean but exposed as uint32 to JS land.
217215
};
218216

219217
// Clear any domain and/or uncaughtException handlers to force the error's

0 commit comments

Comments
 (0)