Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnna Henningsen <anna@addaleax.net>2019-02-19 00:58:27 +0300
committerAnna Henningsen <anna@addaleax.net>2019-02-25 04:01:11 +0300
commit84e02b178ad14fae0df2a514e8a39bfa50ffdc2d (patch)
treeddc0435b6bd0b7811e0bf47687777c56b2857fd0 /src/node_buffer.cc
parent6c257cdf271384555d0ced77104a1d6b0480e246 (diff)
src: allocate Buffer memory using ArrayBuffer allocator
Always use the right allocator for memory that is turned into an `ArrayBuffer` at a later point. This enables embedders to use their own `ArrayBuffer::Allocator`s, and is inspired by Electron’s electron/node@f61bae3440e. It should render their downstream patch unnecessary. Refs: https://github.com/electron/node/commit/f61bae3440e1bfcc83bba6ff0785adfb89b4045e PR-URL: https://github.com/nodejs/node/pull/26207 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Diffstat (limited to 'src/node_buffer.cc')
-rw-r--r--src/node_buffer.cc98
1 files changed, 40 insertions, 58 deletions
diff --git a/src/node_buffer.cc b/src/node_buffer.cc
index 9fed15622e0..aca1842c30b 100644
--- a/src/node_buffer.cc
+++ b/src/node_buffer.cc
@@ -54,17 +54,6 @@
size_t length = end - start;
namespace node {
-
-namespace {
-
-inline void* BufferMalloc(size_t length) {
- return per_process::cli_options->zero_fill_all_buffers ?
- node::UncheckedCalloc(length) :
- node::UncheckedMalloc(length);
-}
-
-} // namespace
-
namespace Buffer {
using v8::ArrayBuffer;
@@ -260,7 +249,7 @@ MaybeLocal<Object> New(Isolate* isolate,
char* data = nullptr;
if (length > 0) {
- data = static_cast<char*>(BufferMalloc(length));
+ data = UncheckedMalloc(length);
if (data == nullptr) {
THROW_ERR_MEMORY_ALLOCATION_FAILED(isolate);
@@ -278,13 +267,7 @@ MaybeLocal<Object> New(Isolate* isolate,
}
}
- Local<Object> buf;
- if (New(isolate, data, actual).ToLocal(&buf))
- return scope.Escape(buf);
-
- // Object failed to be created. Clean up resources.
- free(data);
- return Local<Object>();
+ return scope.EscapeMaybe(New(isolate, data, actual));
}
@@ -311,26 +294,16 @@ MaybeLocal<Object> New(Environment* env, size_t length) {
return Local<Object>();
}
- void* data;
+ AllocatedBuffer ret(env);
if (length > 0) {
- data = BufferMalloc(length);
- if (data == nullptr) {
+ ret = env->AllocateManaged(length, false);
+ if (ret.data() == nullptr) {
THROW_ERR_MEMORY_ALLOCATION_FAILED(env);
return Local<Object>();
}
- } else {
- data = nullptr;
}
- Local<ArrayBuffer> ab =
- ArrayBuffer::New(env->isolate(),
- data,
- length,
- ArrayBufferCreationMode::kInternalized);
- Local<Object> obj;
- if (Buffer::New(env, ab, 0, length).ToLocal(&obj))
- return scope.Escape(obj);
- return Local<Object>();
+ return scope.EscapeMaybe(ret.ToBuffer());
}
@@ -357,28 +330,18 @@ MaybeLocal<Object> Copy(Environment* env, const char* data, size_t length) {
return Local<Object>();
}
- void* new_data;
+ AllocatedBuffer ret(env);
if (length > 0) {
CHECK_NOT_NULL(data);
- new_data = node::UncheckedMalloc(length);
- if (new_data == nullptr) {
+ ret = env->AllocateManaged(length, false);
+ if (ret.data() == nullptr) {
THROW_ERR_MEMORY_ALLOCATION_FAILED(env);
return Local<Object>();
}
- memcpy(new_data, data, length);
- } else {
- new_data = nullptr;
+ memcpy(ret.data(), data, length);
}
- Local<ArrayBuffer> ab =
- ArrayBuffer::New(env->isolate(),
- new_data,
- length,
- ArrayBufferCreationMode::kInternalized);
- Local<Object> obj;
- if (Buffer::New(env, ab, 0, length).ToLocal(&obj))
- return scope.Escape(obj);
- return Local<Object>();
+ return scope.EscapeMaybe(ret.ToBuffer());
}
@@ -425,7 +388,8 @@ MaybeLocal<Object> New(Environment* env,
return scope.Escape(ui.ToLocalChecked());
}
-
+// Warning: This function needs `data` to be allocated with malloc() and not
+// necessarily isolate's ArrayBuffer::Allocator.
MaybeLocal<Object> New(Isolate* isolate, char* data, size_t length) {
EscapableHandleScope handle_scope(isolate);
Environment* env = Environment::GetCurrent(isolate);
@@ -435,18 +399,37 @@ MaybeLocal<Object> New(Isolate* isolate, char* data, size_t length) {
return MaybeLocal<Object>();
}
Local<Object> obj;
- if (Buffer::New(env, data, length).ToLocal(&obj))
+ if (Buffer::New(env, data, length, true).ToLocal(&obj))
return handle_scope.Escape(obj);
return Local<Object>();
}
-
-MaybeLocal<Object> New(Environment* env, char* data, size_t length) {
+// Warning: If this call comes through the public node_buffer.h API,
+// the contract for this function is that `data` is allocated with malloc()
+// and not necessarily isolate's ArrayBuffer::Allocator.
+MaybeLocal<Object> New(Environment* env,
+ char* data,
+ size_t length,
+ bool uses_malloc) {
if (length > 0) {
CHECK_NOT_NULL(data);
CHECK(length <= kMaxLength);
}
+ if (uses_malloc) {
+ if (env->isolate_data()->uses_node_allocator()) {
+ // We don't know for sure that the allocator is malloc()-based, so we need
+ // to fall back to the FreeCallback variant.
+ auto free_callback = [](char* data, void* hint) { free(data); };
+ return New(env, data, length, free_callback, nullptr);
+ } else {
+ // This is malloc()-based, so we can acquire it into our own
+ // ArrayBufferAllocator.
+ CHECK_NOT_NULL(env->isolate_data()->node_allocator());
+ env->isolate_data()->node_allocator()->RegisterPointer(data, length);
+ }
+ }
+
Local<ArrayBuffer> ab =
ArrayBuffer::New(env->isolate(),
data,
@@ -1053,15 +1036,13 @@ static void EncodeUtf8String(const FunctionCallbackInfo<Value>& args) {
Local<String> str = args[0].As<String>();
size_t length = str->Utf8Length(isolate);
- char* data = node::UncheckedMalloc(length);
+ AllocatedBuffer buf = env->AllocateManaged(length);
str->WriteUtf8(isolate,
- data,
+ buf.data(),
-1, // We are certain that `data` is sufficiently large
nullptr,
String::NO_NULL_TERMINATION | String::REPLACE_INVALID_UTF8);
- auto array_buf = ArrayBuffer::New(
- isolate, data, length, ArrayBufferCreationMode::kInternalized);
- auto array = Uint8Array::New(array_buf, 0, length);
+ auto array = Uint8Array::New(buf.ToArrayBuffer(), 0, length);
args.GetReturnValue().Set(array);
}
@@ -1123,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 (uint32_t* zero_fill_field = env->isolate_data()->zero_fill_field()) {
+ if (ArrayBufferAllocator* 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));
CHECK(target