Skip to content

Commit

Permalink
deps: V8: cherry-pick bba5f1f
Browse files Browse the repository at this point in the history
Original commit message:

    [api] Add API functions for constructing standalone BackingStores

    These are useful for the cases when an embedder works with backing
    stores without creating JS ArrayBuffer objects.

    Bug: v8:9380
    Change-Id: I452bd911e7b20fb38568f18f9d15ea1a7ffb5a57
    Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1825339
    Commit-Queue: Ulan Degenbaev <ulan@chromium.org>
    Reviewed-by: Andreas Haas <ahaas@chromium.org>
    Cr-Commit-Position: refs/heads/master@{#64460}

Refs: v8/v8@bba5f1f

PR-URL: nodejs#30020
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Jiawen Geng <technicalcute@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
  • Loading branch information
targos committed Nov 8, 2019
1 parent d56f9a9 commit 7484a38
Show file tree
Hide file tree
Showing 7 changed files with 242 additions and 15 deletions.
2 changes: 1 addition & 1 deletion common.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@

# Reset this number to 0 on major V8 upgrades.
# Increment by one for each non-official patch applied to deps/v8.
'v8_embedder_string': '-node.11',
'v8_embedder_string': '-node.12',

##### V8 defaults for Node.js #####

Expand Down
54 changes: 54 additions & 0 deletions deps/v8/include/v8.h
Original file line number Diff line number Diff line change
Expand Up @@ -4849,6 +4849,14 @@ class V8_EXPORT BackingStore : public v8::internal::BackingStoreBase {
BackingStore();
};

/**
* This callback is used only if the memory block for this backing store cannot
* be allocated with an ArrayBuffer::Allocator. In such cases the destructor
* of this backing store object invokes the callback to free the memory block.
*/
using BackingStoreDeleterCallback = void (*)(void* data, size_t length,
void* deleter_data);

/**
* An instance of the built-in ArrayBuffer constructor (ES6 draft 15.13.5).
*/
Expand Down Expand Up @@ -4999,6 +5007,29 @@ class V8_EXPORT ArrayBuffer : public Object {
static Local<ArrayBuffer> New(Isolate* isolate,
std::shared_ptr<BackingStore> backing_store);

/**
* Returns a new standalone BackingStore that is allocated using the array
* buffer allocator of the isolate. The result can be later passed to
* ArrayBuffer::New.
*
* If the allocator returns nullptr, then the function may cause GCs in the
* given isolate and re-try the allocation. If GCs do not help, then the
* function will crash with an out-of-memory error.
*/
static std::unique_ptr<BackingStore> NewBackingStore(Isolate* isolate,
size_t byte_length);
/**
* Returns a new standalone BackingStore that takes over the ownership of
* the given buffer. The destructor of the BackingStore invokes the given
* deleter callback.
*
* The result can be later passed to ArrayBuffer::New. The raw pointer
* to the buffer must not be passed again to any V8 API function.
*/
static std::unique_ptr<BackingStore> NewBackingStore(
void* data, size_t byte_length, BackingStoreDeleterCallback deleter,
void* deleter_data);

/**
* Returns true if ArrayBuffer is externalized, that is, does not
* own its memory block.
Expand Down Expand Up @@ -5449,6 +5480,29 @@ class V8_EXPORT SharedArrayBuffer : public Object {
static Local<SharedArrayBuffer> New(
Isolate* isolate, std::shared_ptr<BackingStore> backing_store);

/**
* Returns a new standalone BackingStore that is allocated using the array
* buffer allocator of the isolate. The result can be later passed to
* SharedArrayBuffer::New.
*
* If the allocator returns nullptr, then the function may cause GCs in the
* given isolate and re-try the allocation. If GCs do not help, then the
* function will crash with an out-of-memory error.
*/
static std::unique_ptr<BackingStore> NewBackingStore(Isolate* isolate,
size_t byte_length);
/**
* Returns a new standalone BackingStore that takes over the ownership of
* the given buffer. The destructor of the BackingStore invokes the given
* deleter callback.
*
* The result can be later passed to SharedArrayBuffer::New. The raw pointer
* to the buffer must not be passed again to any V8 functions.
*/
static std::unique_ptr<BackingStore> NewBackingStore(
void* data, size_t byte_length, BackingStoreDeleterCallback deleter,
void* deleter_data);

/**
* Create a new SharedArrayBuffer over an existing memory block. Propagate
* flags to indicate whether the underlying buffer can be grown.
Expand Down
52 changes: 52 additions & 0 deletions deps/v8/src/api/api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7452,6 +7452,32 @@ Local<ArrayBuffer> v8::ArrayBuffer::New(
return Utils::ToLocal(obj);
}

std::unique_ptr<v8::BackingStore> v8::ArrayBuffer::NewBackingStore(
Isolate* isolate, size_t byte_length) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
LOG_API(i_isolate, ArrayBuffer, NewBackingStore);
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
std::unique_ptr<i::BackingStoreBase> backing_store =
i::BackingStore::Allocate(i_isolate, byte_length,
i::SharedFlag::kNotShared,
i::InitializedFlag::kZeroInitialized);
if (!backing_store) {
i::FatalProcessOutOfMemory(i_isolate, "v8::ArrayBuffer::NewBackingStore");
}
return std::unique_ptr<v8::BackingStore>(
static_cast<v8::BackingStore*>(backing_store.release()));
}

std::unique_ptr<v8::BackingStore> v8::ArrayBuffer::NewBackingStore(
void* data, size_t byte_length, BackingStoreDeleterCallback deleter,
void* deleter_data) {
std::unique_ptr<i::BackingStoreBase> backing_store =
i::BackingStore::WrapAllocation(data, byte_length, deleter, deleter_data,
i::SharedFlag::kNotShared);
return std::unique_ptr<v8::BackingStore>(
static_cast<v8::BackingStore*>(backing_store.release()));
}

Local<ArrayBuffer> v8::ArrayBufferView::Buffer() {
i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
i::Handle<i::JSArrayBuffer> buffer;
Expand Down Expand Up @@ -7753,6 +7779,32 @@ Local<SharedArrayBuffer> v8::SharedArrayBuffer::New(
return Utils::ToLocalShared(buffer);
}

std::unique_ptr<v8::BackingStore> v8::SharedArrayBuffer::NewBackingStore(
Isolate* isolate, size_t byte_length) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
LOG_API(i_isolate, SharedArrayBuffer, NewBackingStore);
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
std::unique_ptr<i::BackingStoreBase> backing_store =
i::BackingStore::Allocate(i_isolate, byte_length, i::SharedFlag::kShared,
i::InitializedFlag::kZeroInitialized);
if (!backing_store) {
i::FatalProcessOutOfMemory(i_isolate,
"v8::SharedArrayBuffer::NewBackingStore");
}
return std::unique_ptr<v8::BackingStore>(
static_cast<v8::BackingStore*>(backing_store.release()));
}

std::unique_ptr<v8::BackingStore> v8::SharedArrayBuffer::NewBackingStore(
void* data, size_t byte_length, BackingStoreDeleterCallback deleter,
void* deleter_data) {
std::unique_ptr<i::BackingStoreBase> backing_store =
i::BackingStore::WrapAllocation(data, byte_length, deleter, deleter_data,
i::SharedFlag::kShared);
return std::unique_ptr<v8::BackingStore>(
static_cast<v8::BackingStore*>(backing_store.release()));
}

Local<Symbol> v8::Symbol::New(Isolate* isolate, Local<String> name) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
LOG_API(i_isolate, Symbol, New);
Expand Down
2 changes: 2 additions & 0 deletions deps/v8/src/logging/counters.h
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,7 @@ class RuntimeCallTimer final {
V(ArrayBuffer_Cast) \
V(ArrayBuffer_Detach) \
V(ArrayBuffer_New) \
V(ArrayBuffer_NewBackingStore) \
V(Array_CloneElementAt) \
V(Array_New) \
V(BigInt64Array_New) \
Expand Down Expand Up @@ -850,6 +851,7 @@ class RuntimeCallTimer final {
V(Set_Has) \
V(Set_New) \
V(SharedArrayBuffer_New) \
V(SharedArrayBuffer_NewBackingStore) \
V(String_Concat) \
V(String_NewExternalOneByte) \
V(String_NewExternalTwoByte) \
Expand Down
51 changes: 45 additions & 6 deletions deps/v8/src/objects/backing-store.cc
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ BackingStore::~BackingStore() {

if (is_wasm_memory_) {
DCHECK(free_on_destruct_);
DCHECK(!custom_deleter_);
TRACE_BS("BSw:free bs=%p mem=%p (length=%zu, capacity=%zu)\n", this,
buffer_start_, byte_length(), byte_capacity_);
if (is_shared_) {
Expand All @@ -149,6 +150,14 @@ BackingStore::~BackingStore() {
Clear();
return;
}
if (custom_deleter_) {
DCHECK(free_on_destruct_);
TRACE_BS("BS:custome deleter bs=%p mem=%p (length=%zu, capacity=%zu)\n",
this, buffer_start_, byte_length(), byte_capacity_);
type_specific_data_.deleter(buffer_start_, byte_length_, deleter_data_);
Clear();
return;
}
if (free_on_destruct_) {
// JSArrayBuffer backing store. Deallocate through the embedder's allocator.
auto allocator = reinterpret_cast<v8::ArrayBuffer::Allocator*>(
Expand Down Expand Up @@ -210,7 +219,8 @@ std::unique_ptr<BackingStore> BackingStore::Allocate(
shared, // shared
false, // is_wasm_memory
true, // free_on_destruct
false); // has_guard_regions
false, // has_guard_regions
false); // custom_deleter

TRACE_BS("BS:alloc bs=%p mem=%p (length=%zu)\n", result,
result->buffer_start(), byte_length);
Expand Down Expand Up @@ -321,7 +331,8 @@ std::unique_ptr<BackingStore> BackingStore::TryAllocateWasmMemory(
shared, // shared
true, // is_wasm_memory
true, // free_on_destruct
guards); // has_guard_regions
guards, // has_guard_regions
false); // custom_deleter

TRACE_BS("BSw:alloc bs=%p mem=%p (length=%zu, capacity=%zu)\n", result,
result->buffer_start(), byte_length, byte_capacity);
Expand Down Expand Up @@ -451,16 +462,40 @@ void BackingStore::UpdateSharedWasmMemoryObjects(Isolate* isolate) {
std::unique_ptr<BackingStore> BackingStore::WrapAllocation(
Isolate* isolate, void* allocation_base, size_t allocation_length,
SharedFlag shared, bool free_on_destruct) {
auto result =
new BackingStore(allocation_base, allocation_length, allocation_length,
shared, false, free_on_destruct, false);
auto result = new BackingStore(allocation_base, // start
allocation_length, // length
allocation_length, // capacity
shared, // shared
false, // is_wasm_memory
free_on_destruct, // free_on_destruct
false, // has_guard_regions
false); // custom_deleter
result->type_specific_data_.v8_api_array_buffer_allocator =
isolate->array_buffer_allocator();
TRACE_BS("BS:wrap bs=%p mem=%p (length=%zu)\n", result,
result->buffer_start(), result->byte_length());
return std::unique_ptr<BackingStore>(result);
}

std::unique_ptr<BackingStore> BackingStore::WrapAllocation(
void* allocation_base, size_t allocation_length,
v8::BackingStoreDeleterCallback deleter, void* deleter_data,
SharedFlag shared) {
auto result = new BackingStore(allocation_base, // start
allocation_length, // length
allocation_length, // capacity
shared, // shared
false, // is_wasm_memory
true, // free_on_destruct
false, // has_guard_regions
true); // custom_deleter
result->type_specific_data_.deleter = deleter;
result->deleter_data_ = deleter_data;
TRACE_BS("BS:wrap bs=%p mem=%p (length=%zu)\n", result,
result->buffer_start(), result->byte_length());
return std::unique_ptr<BackingStore>(result);
}

std::unique_ptr<BackingStore> BackingStore::EmptyBackingStore(
SharedFlag shared) {
auto result = new BackingStore(nullptr, // start
Expand All @@ -469,7 +504,8 @@ std::unique_ptr<BackingStore> BackingStore::EmptyBackingStore(
shared, // shared
false, // is_wasm_memory
false, // free_on_destruct
false); // has_guard_regions
false, // has_guard_regions
false); // custom_deleter

return std::unique_ptr<BackingStore>(result);
}
Expand Down Expand Up @@ -512,6 +548,9 @@ void GlobalBackingStoreRegistry::Register(
// then we don't have to guarantee that there is single unique
// BackingStore per buffer_start() because the destructor of
// of the BackingStore will be a no-op in that case.

// All WASM memory has to be registered.
CHECK(!backing_store->is_wasm_memory());
return;
}

Expand Down
31 changes: 23 additions & 8 deletions deps/v8/src/objects/backing-store.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <memory>

#include "include/v8-internal.h"
#include "include/v8.h"
#include "src/handles/handles.h"

namespace v8 {
Expand Down Expand Up @@ -63,6 +64,11 @@ class V8_EXPORT_PRIVATE BackingStore : public BackingStoreBase {
SharedFlag shared,
bool free_on_destruct);

static std::unique_ptr<BackingStore> WrapAllocation(
void* allocation_base, size_t allocation_length,
v8::BackingStoreDeleterCallback deleter, void* deleter_data,
SharedFlag shared);

// Create an empty backing store.
static std::unique_ptr<BackingStore> EmptyBackingStore(SharedFlag shared);

Expand Down Expand Up @@ -116,27 +122,23 @@ class V8_EXPORT_PRIVATE BackingStore : public BackingStoreBase {

BackingStore(void* buffer_start, size_t byte_length, size_t byte_capacity,
SharedFlag shared, bool is_wasm_memory, bool free_on_destruct,
bool has_guard_regions)
bool has_guard_regions, bool custom_deleter)
: buffer_start_(buffer_start),
byte_length_(byte_length),
byte_capacity_(byte_capacity),
is_shared_(shared == SharedFlag::kShared),
is_wasm_memory_(is_wasm_memory),
free_on_destruct_(free_on_destruct),
has_guard_regions_(has_guard_regions),
globally_registered_(false) {
globally_registered_(false),
custom_deleter_(custom_deleter) {
type_specific_data_.v8_api_array_buffer_allocator = nullptr;
deleter_data_ = nullptr;
}

void* buffer_start_ = nullptr;
std::atomic<size_t> byte_length_{0};
size_t byte_capacity_ = 0;
bool is_shared_ : 1;
bool is_wasm_memory_ : 1;
bool free_on_destruct_ : 1;
bool has_guard_regions_ : 1;
bool globally_registered_ : 1;

union {
// If this backing store was allocated through the ArrayBufferAllocator API,
// this is a direct pointer to the API object for freeing the backing
Expand All @@ -148,8 +150,21 @@ class V8_EXPORT_PRIVATE BackingStore : public BackingStoreBase {
// For shared Wasm memories, this is a list of all the attached memory
// objects, which is needed to grow shared backing stores.
SharedWasmMemoryData* shared_wasm_memory_data;

// Custom deleter for the backing stores that wrap memory blocks that are
// allocated with a custom allocator.
v8::BackingStoreDeleterCallback deleter;
} type_specific_data_;

void* deleter_data_;

bool is_shared_ : 1;
bool is_wasm_memory_ : 1;
bool free_on_destruct_ : 1;
bool has_guard_regions_ : 1;
bool globally_registered_ : 1;
bool custom_deleter_ : 1;

// Accessors for type-specific data.
void* get_v8_api_array_buffer_allocator();
SharedWasmMemoryData* get_shared_wasm_memory_data();
Expand Down
Loading

0 comments on commit 7484a38

Please sign in to comment.