src: allocate Buffer memory using ArrayBuffer allocator · nodejs/node@84e02b1 (original) (raw)
`@@ -54,17 +54,6 @@
`
54
54
`size_t length = end - start;
`
55
55
``
56
56
`namespace node {
`
57
``
-
58
``
`-
namespace {
`
59
``
-
60
``
`-
inline void* BufferMalloc(size_t length) {
`
61
``
`-
return per_process::cli_options->zero_fill_all_buffers ?
`
62
``
`-
node::UncheckedCalloc(length) :
`
63
``
`-
node::UncheckedMalloc(length);
`
64
``
`-
}
`
65
``
-
66
``
`-
} // namespace
`
67
``
-
68
57
`namespace Buffer {
`
69
58
``
70
59
`using v8::ArrayBuffer;
`
`@@ -260,7 +249,7 @@ MaybeLocal New(Isolate* isolate,
`
260
249
`char* data = nullptr;
`
261
250
``
262
251
`if (length > 0) {
`
263
``
`-
data = static_cast<char*>(BufferMalloc(length));
`
``
252
`+
data = UncheckedMalloc(length);
`
264
253
``
265
254
`if (data == nullptr) {
`
266
255
`THROW_ERR_MEMORY_ALLOCATION_FAILED(isolate);
`
`@@ -278,13 +267,7 @@ MaybeLocal New(Isolate* isolate,
`
278
267
` }
`
279
268
` }
`
280
269
``
281
``
`-
Local buf;
`
282
``
`-
if (New(isolate, data, actual).ToLocal(&buf))
`
283
``
`-
return scope.Escape(buf);
`
284
``
-
285
``
`-
// Object failed to be created. Clean up resources.
`
286
``
`-
free(data);
`
287
``
`-
return Local();
`
``
270
`+
return scope.EscapeMaybe(New(isolate, data, actual));
`
288
271
`}
`
289
272
``
290
273
``
`@@ -311,26 +294,16 @@ MaybeLocal New(Environment* env, size_t length) {
`
311
294
`return Local();
`
312
295
` }
`
313
296
``
314
``
`-
void* data;
`
``
297
`+
AllocatedBuffer ret(env);
`
315
298
`if (length > 0) {
`
316
``
`-
data = BufferMalloc(length);
`
317
``
`-
if (data == nullptr) {
`
``
299
`+
ret = env->AllocateManaged(length, false);
`
``
300
`+
if (ret.data() == nullptr) {
`
318
301
`THROW_ERR_MEMORY_ALLOCATION_FAILED(env);
`
319
302
`return Local();
`
320
303
` }
`
321
``
`-
} else {
`
322
``
`-
data = nullptr;
`
323
304
` }
`
324
305
``
325
``
`-
Local ab =
`
326
``
`-
ArrayBuffer::New(env->isolate(),
`
327
``
`-
data,
`
328
``
`-
length,
`
329
``
`-
ArrayBufferCreationMode::kInternalized);
`
330
``
`-
Local obj;
`
331
``
`-
if (Buffer::New(env, ab, 0, length).ToLocal(&obj))
`
332
``
`-
return scope.Escape(obj);
`
333
``
`-
return Local();
`
``
306
`+
return scope.EscapeMaybe(ret.ToBuffer());
`
334
307
`}
`
335
308
``
336
309
``
`@@ -357,28 +330,18 @@ MaybeLocal Copy(Environment* env, const char* data, size_t length) {
`
357
330
`return Local();
`
358
331
` }
`
359
332
``
360
``
`-
void* new_data;
`
``
333
`+
AllocatedBuffer ret(env);
`
361
334
`if (length > 0) {
`
362
335
`CHECK_NOT_NULL(data);
`
363
``
`-
new_data = node::UncheckedMalloc(length);
`
364
``
`-
if (new_data == nullptr) {
`
``
336
`+
ret = env->AllocateManaged(length, false);
`
``
337
`+
if (ret.data() == nullptr) {
`
365
338
`THROW_ERR_MEMORY_ALLOCATION_FAILED(env);
`
366
339
`return Local();
`
367
340
` }
`
368
``
`-
memcpy(new_data, data, length);
`
369
``
`-
} else {
`
370
``
`-
new_data = nullptr;
`
``
341
`+
memcpy(ret.data(), data, length);
`
371
342
` }
`
372
343
``
373
``
`-
Local ab =
`
374
``
`-
ArrayBuffer::New(env->isolate(),
`
375
``
`-
new_data,
`
376
``
`-
length,
`
377
``
`-
ArrayBufferCreationMode::kInternalized);
`
378
``
`-
Local obj;
`
379
``
`-
if (Buffer::New(env, ab, 0, length).ToLocal(&obj))
`
380
``
`-
return scope.Escape(obj);
`
381
``
`-
return Local();
`
``
344
`+
return scope.EscapeMaybe(ret.ToBuffer());
`
382
345
`}
`
383
346
``
384
347
``
`@@ -425,7 +388,8 @@ MaybeLocal New(Environment* env,
`
425
388
`return scope.Escape(ui.ToLocalChecked());
`
426
389
`}
`
427
390
``
428
``
-
``
391
`` +
// Warning: This function needs data
to be allocated with malloc() and not
``
``
392
`+
// necessarily isolate's ArrayBuffer::Allocator.
`
429
393
`MaybeLocal New(Isolate* isolate, char* data, size_t length) {
`
430
394
` EscapableHandleScope handle_scope(isolate);
`
431
395
` Environment* env = Environment::GetCurrent(isolate);
`
`@@ -435,18 +399,37 @@ MaybeLocal New(Isolate* isolate, char* data, size_t length) {
`
435
399
`return MaybeLocal();
`
436
400
` }
`
437
401
` Local obj;
`
438
``
`-
if (Buffer::New(env, data, length).ToLocal(&obj))
`
``
402
`+
if (Buffer::New(env, data, length, true).ToLocal(&obj))
`
439
403
`return handle_scope.Escape(obj);
`
440
404
`return Local();
`
441
405
`}
`
442
406
``
443
``
-
444
``
`-
MaybeLocal New(Environment* env, char* data, size_t length) {
`
``
407
`+
// Warning: If this call comes through the public node_buffer.h API,
`
``
408
`` +
// the contract for this function is that data
is allocated with malloc()
``
``
409
`+
// and not necessarily isolate's ArrayBuffer::Allocator.
`
``
410
`+
MaybeLocal New(Environment* env,
`
``
411
`+
char* data,
`
``
412
`+
size_t length,
`
``
413
`+
bool uses_malloc) {
`
445
414
`if (length > 0) {
`
446
415
`CHECK_NOT_NULL(data);
`
447
416
`CHECK(length <= kMaxLength);
`
448
417
` }
`
449
418
``
``
419
`+
if (uses_malloc) {
`
``
420
`+
if (env->isolate_data()->uses_node_allocator()) {
`
``
421
`+
// We don't know for sure that the allocator is malloc()-based, so we need
`
``
422
`+
// to fall back to the FreeCallback variant.
`
``
423
`+
auto free_callback = [](char* data, void* hint) { free(data); };
`
``
424
`+
return New(env, data, length, free_callback, nullptr);
`
``
425
`+
} else {
`
``
426
`+
// This is malloc()-based, so we can acquire it into our own
`
``
427
`+
// ArrayBufferAllocator.
`
``
428
`+
CHECK_NOT_NULL(env->isolate_data()->node_allocator());
`
``
429
`+
env->isolate_data()->node_allocator()->RegisterPointer(data, length);
`
``
430
`+
}
`
``
431
`+
}
`
``
432
+
450
433
` Local ab =
`
451
434
`ArrayBuffer::New(env->isolate(),
`
452
435
` data,
`
`@@ -1053,15 +1036,13 @@ static void EncodeUtf8String(const FunctionCallbackInfo& args) {
`
1053
1036
``
1054
1037
` Local str = args[0].As();
`
1055
1038
`size_t length = str->Utf8Length(isolate);
`
1056
``
`-
char* data = node::UncheckedMalloc(length);
`
``
1039
`+
AllocatedBuffer buf = env->AllocateManaged(length);
`
1057
1040
` str->WriteUtf8(isolate,
`
1058
``
`-
data,
`
``
1041
`+
buf.data(),
`
1059
1042
`` -1, // We are certain that data
is sufficiently large
``
1060
1043
`nullptr,
`
1061
1044
` String::NO_NULL_TERMINATION | String::REPLACE_INVALID_UTF8);
`
1062
``
`-
auto array_buf = ArrayBuffer::New(
`
1063
``
`-
isolate, data, length, ArrayBufferCreationMode::kInternalized);
`
1064
``
`-
auto array = Uint8Array::New(array_buf, 0, length);
`
``
1045
`+
auto array = Uint8Array::New(buf.ToArrayBuffer(), 0, length);
`
1065
1046
` args.GetReturnValue().Set(array);
`
1066
1047
`}
`
1067
1048
``
`@@ -1123,7 +1104,8 @@ void Initialize(Local target,
`
1123
1104
``
1124
1105
`// It can be a nullptr when running inside an isolate where we
`
1125
1106
`// do not own the ArrayBuffer allocator.
`
1126
``
`-
if (uint32_t* zero_fill_field = env->isolate_data()->zero_fill_field()) {
`
``
1107
`+
if (ArrayBufferAllocator* allocator = env->isolate_data()->node_allocator()) {
`
``
1108
`+
uint32_t* zero_fill_field = allocator->zero_fill_field();
`
1127
1109
` Local array_buffer = ArrayBuffer::New(
`
1128
1110
` env->isolate(), zero_fill_field, sizeof(*zero_fill_field));
`
1129
1111
`CHECK(target
`