Skip to content

Commit ebef1b2

Browse files
targosMylesBorins
authored andcommitted
deps: V8: cherry-pick bba5f1f
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 Backport-PR-URL: #30513 PR-URL: #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>
1 parent 28ca44c commit ebef1b2

File tree

7 files changed

+242
-15
lines changed

7 files changed

+242
-15
lines changed

common.gypi

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939

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

4444
##### V8 defaults for Node.js #####
4545

deps/v8/include/v8.h

+54
Original file line numberDiff line numberDiff line change
@@ -4849,6 +4849,14 @@ class V8_EXPORT BackingStore : public v8::internal::BackingStoreBase {
48494849
BackingStore();
48504850
};
48514851

4852+
/**
4853+
* This callback is used only if the memory block for this backing store cannot
4854+
* be allocated with an ArrayBuffer::Allocator. In such cases the destructor
4855+
* of this backing store object invokes the callback to free the memory block.
4856+
*/
4857+
using BackingStoreDeleterCallback = void (*)(void* data, size_t length,
4858+
void* deleter_data);
4859+
48524860
/**
48534861
* An instance of the built-in ArrayBuffer constructor (ES6 draft 15.13.5).
48544862
*/
@@ -4999,6 +5007,29 @@ class V8_EXPORT ArrayBuffer : public Object {
49995007
static Local<ArrayBuffer> New(Isolate* isolate,
50005008
std::shared_ptr<BackingStore> backing_store);
50015009

5010+
/**
5011+
* Returns a new standalone BackingStore that is allocated using the array
5012+
* buffer allocator of the isolate. The result can be later passed to
5013+
* ArrayBuffer::New.
5014+
*
5015+
* If the allocator returns nullptr, then the function may cause GCs in the
5016+
* given isolate and re-try the allocation. If GCs do not help, then the
5017+
* function will crash with an out-of-memory error.
5018+
*/
5019+
static std::unique_ptr<BackingStore> NewBackingStore(Isolate* isolate,
5020+
size_t byte_length);
5021+
/**
5022+
* Returns a new standalone BackingStore that takes over the ownership of
5023+
* the given buffer. The destructor of the BackingStore invokes the given
5024+
* deleter callback.
5025+
*
5026+
* The result can be later passed to ArrayBuffer::New. The raw pointer
5027+
* to the buffer must not be passed again to any V8 API function.
5028+
*/
5029+
static std::unique_ptr<BackingStore> NewBackingStore(
5030+
void* data, size_t byte_length, BackingStoreDeleterCallback deleter,
5031+
void* deleter_data);
5032+
50025033
/**
50035034
* Returns true if ArrayBuffer is externalized, that is, does not
50045035
* own its memory block.
@@ -5449,6 +5480,29 @@ class V8_EXPORT SharedArrayBuffer : public Object {
54495480
static Local<SharedArrayBuffer> New(
54505481
Isolate* isolate, std::shared_ptr<BackingStore> backing_store);
54515482

5483+
/**
5484+
* Returns a new standalone BackingStore that is allocated using the array
5485+
* buffer allocator of the isolate. The result can be later passed to
5486+
* SharedArrayBuffer::New.
5487+
*
5488+
* If the allocator returns nullptr, then the function may cause GCs in the
5489+
* given isolate and re-try the allocation. If GCs do not help, then the
5490+
* function will crash with an out-of-memory error.
5491+
*/
5492+
static std::unique_ptr<BackingStore> NewBackingStore(Isolate* isolate,
5493+
size_t byte_length);
5494+
/**
5495+
* Returns a new standalone BackingStore that takes over the ownership of
5496+
* the given buffer. The destructor of the BackingStore invokes the given
5497+
* deleter callback.
5498+
*
5499+
* The result can be later passed to SharedArrayBuffer::New. The raw pointer
5500+
* to the buffer must not be passed again to any V8 functions.
5501+
*/
5502+
static std::unique_ptr<BackingStore> NewBackingStore(
5503+
void* data, size_t byte_length, BackingStoreDeleterCallback deleter,
5504+
void* deleter_data);
5505+
54525506
/**
54535507
* Create a new SharedArrayBuffer over an existing memory block. Propagate
54545508
* flags to indicate whether the underlying buffer can be grown.

deps/v8/src/api/api.cc

+52
Original file line numberDiff line numberDiff line change
@@ -7452,6 +7452,32 @@ Local<ArrayBuffer> v8::ArrayBuffer::New(
74527452
return Utils::ToLocal(obj);
74537453
}
74547454

7455+
std::unique_ptr<v8::BackingStore> v8::ArrayBuffer::NewBackingStore(
7456+
Isolate* isolate, size_t byte_length) {
7457+
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7458+
LOG_API(i_isolate, ArrayBuffer, NewBackingStore);
7459+
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7460+
std::unique_ptr<i::BackingStoreBase> backing_store =
7461+
i::BackingStore::Allocate(i_isolate, byte_length,
7462+
i::SharedFlag::kNotShared,
7463+
i::InitializedFlag::kZeroInitialized);
7464+
if (!backing_store) {
7465+
i::FatalProcessOutOfMemory(i_isolate, "v8::ArrayBuffer::NewBackingStore");
7466+
}
7467+
return std::unique_ptr<v8::BackingStore>(
7468+
static_cast<v8::BackingStore*>(backing_store.release()));
7469+
}
7470+
7471+
std::unique_ptr<v8::BackingStore> v8::ArrayBuffer::NewBackingStore(
7472+
void* data, size_t byte_length, BackingStoreDeleterCallback deleter,
7473+
void* deleter_data) {
7474+
std::unique_ptr<i::BackingStoreBase> backing_store =
7475+
i::BackingStore::WrapAllocation(data, byte_length, deleter, deleter_data,
7476+
i::SharedFlag::kNotShared);
7477+
return std::unique_ptr<v8::BackingStore>(
7478+
static_cast<v8::BackingStore*>(backing_store.release()));
7479+
}
7480+
74557481
Local<ArrayBuffer> v8::ArrayBufferView::Buffer() {
74567482
i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
74577483
i::Handle<i::JSArrayBuffer> buffer;
@@ -7753,6 +7779,32 @@ Local<SharedArrayBuffer> v8::SharedArrayBuffer::New(
77537779
return Utils::ToLocalShared(buffer);
77547780
}
77557781

7782+
std::unique_ptr<v8::BackingStore> v8::SharedArrayBuffer::NewBackingStore(
7783+
Isolate* isolate, size_t byte_length) {
7784+
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
7785+
LOG_API(i_isolate, SharedArrayBuffer, NewBackingStore);
7786+
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
7787+
std::unique_ptr<i::BackingStoreBase> backing_store =
7788+
i::BackingStore::Allocate(i_isolate, byte_length, i::SharedFlag::kShared,
7789+
i::InitializedFlag::kZeroInitialized);
7790+
if (!backing_store) {
7791+
i::FatalProcessOutOfMemory(i_isolate,
7792+
"v8::SharedArrayBuffer::NewBackingStore");
7793+
}
7794+
return std::unique_ptr<v8::BackingStore>(
7795+
static_cast<v8::BackingStore*>(backing_store.release()));
7796+
}
7797+
7798+
std::unique_ptr<v8::BackingStore> v8::SharedArrayBuffer::NewBackingStore(
7799+
void* data, size_t byte_length, BackingStoreDeleterCallback deleter,
7800+
void* deleter_data) {
7801+
std::unique_ptr<i::BackingStoreBase> backing_store =
7802+
i::BackingStore::WrapAllocation(data, byte_length, deleter, deleter_data,
7803+
i::SharedFlag::kShared);
7804+
return std::unique_ptr<v8::BackingStore>(
7805+
static_cast<v8::BackingStore*>(backing_store.release()));
7806+
}
7807+
77567808
Local<Symbol> v8::Symbol::New(Isolate* isolate, Local<String> name) {
77577809
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
77587810
LOG_API(i_isolate, Symbol, New);

deps/v8/src/logging/counters.h

+2
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,7 @@ class RuntimeCallTimer final {
733733
V(ArrayBuffer_Cast) \
734734
V(ArrayBuffer_Detach) \
735735
V(ArrayBuffer_New) \
736+
V(ArrayBuffer_NewBackingStore) \
736737
V(Array_CloneElementAt) \
737738
V(Array_New) \
738739
V(BigInt64Array_New) \
@@ -850,6 +851,7 @@ class RuntimeCallTimer final {
850851
V(Set_Has) \
851852
V(Set_New) \
852853
V(SharedArrayBuffer_New) \
854+
V(SharedArrayBuffer_NewBackingStore) \
853855
V(String_Concat) \
854856
V(String_NewExternalOneByte) \
855857
V(String_NewExternalTwoByte) \

deps/v8/src/objects/backing-store.cc

+45-6
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ BackingStore::~BackingStore() {
124124

125125
if (is_wasm_memory_) {
126126
DCHECK(free_on_destruct_);
127+
DCHECK(!custom_deleter_);
127128
TRACE_BS("BSw:free bs=%p mem=%p (length=%zu, capacity=%zu)\n", this,
128129
buffer_start_, byte_length(), byte_capacity_);
129130
if (is_shared_) {
@@ -149,6 +150,14 @@ BackingStore::~BackingStore() {
149150
Clear();
150151
return;
151152
}
153+
if (custom_deleter_) {
154+
DCHECK(free_on_destruct_);
155+
TRACE_BS("BS:custome deleter bs=%p mem=%p (length=%zu, capacity=%zu)\n",
156+
this, buffer_start_, byte_length(), byte_capacity_);
157+
type_specific_data_.deleter(buffer_start_, byte_length_, deleter_data_);
158+
Clear();
159+
return;
160+
}
152161
if (free_on_destruct_) {
153162
// JSArrayBuffer backing store. Deallocate through the embedder's allocator.
154163
auto allocator = reinterpret_cast<v8::ArrayBuffer::Allocator*>(
@@ -210,7 +219,8 @@ std::unique_ptr<BackingStore> BackingStore::Allocate(
210219
shared, // shared
211220
false, // is_wasm_memory
212221
true, // free_on_destruct
213-
false); // has_guard_regions
222+
false, // has_guard_regions
223+
false); // custom_deleter
214224

215225
TRACE_BS("BS:alloc bs=%p mem=%p (length=%zu)\n", result,
216226
result->buffer_start(), byte_length);
@@ -321,7 +331,8 @@ std::unique_ptr<BackingStore> BackingStore::TryAllocateWasmMemory(
321331
shared, // shared
322332
true, // is_wasm_memory
323333
true, // free_on_destruct
324-
guards); // has_guard_regions
334+
guards, // has_guard_regions
335+
false); // custom_deleter
325336

326337
TRACE_BS("BSw:alloc bs=%p mem=%p (length=%zu, capacity=%zu)\n", result,
327338
result->buffer_start(), byte_length, byte_capacity);
@@ -451,16 +462,40 @@ void BackingStore::UpdateSharedWasmMemoryObjects(Isolate* isolate) {
451462
std::unique_ptr<BackingStore> BackingStore::WrapAllocation(
452463
Isolate* isolate, void* allocation_base, size_t allocation_length,
453464
SharedFlag shared, bool free_on_destruct) {
454-
auto result =
455-
new BackingStore(allocation_base, allocation_length, allocation_length,
456-
shared, false, free_on_destruct, false);
465+
auto result = new BackingStore(allocation_base, // start
466+
allocation_length, // length
467+
allocation_length, // capacity
468+
shared, // shared
469+
false, // is_wasm_memory
470+
free_on_destruct, // free_on_destruct
471+
false, // has_guard_regions
472+
false); // custom_deleter
457473
result->type_specific_data_.v8_api_array_buffer_allocator =
458474
isolate->array_buffer_allocator();
459475
TRACE_BS("BS:wrap bs=%p mem=%p (length=%zu)\n", result,
460476
result->buffer_start(), result->byte_length());
461477
return std::unique_ptr<BackingStore>(result);
462478
}
463479

480+
std::unique_ptr<BackingStore> BackingStore::WrapAllocation(
481+
void* allocation_base, size_t allocation_length,
482+
v8::BackingStoreDeleterCallback deleter, void* deleter_data,
483+
SharedFlag shared) {
484+
auto result = new BackingStore(allocation_base, // start
485+
allocation_length, // length
486+
allocation_length, // capacity
487+
shared, // shared
488+
false, // is_wasm_memory
489+
true, // free_on_destruct
490+
false, // has_guard_regions
491+
true); // custom_deleter
492+
result->type_specific_data_.deleter = deleter;
493+
result->deleter_data_ = deleter_data;
494+
TRACE_BS("BS:wrap bs=%p mem=%p (length=%zu)\n", result,
495+
result->buffer_start(), result->byte_length());
496+
return std::unique_ptr<BackingStore>(result);
497+
}
498+
464499
std::unique_ptr<BackingStore> BackingStore::EmptyBackingStore(
465500
SharedFlag shared) {
466501
auto result = new BackingStore(nullptr, // start
@@ -469,7 +504,8 @@ std::unique_ptr<BackingStore> BackingStore::EmptyBackingStore(
469504
shared, // shared
470505
false, // is_wasm_memory
471506
false, // free_on_destruct
472-
false); // has_guard_regions
507+
false, // has_guard_regions
508+
false); // custom_deleter
473509

474510
return std::unique_ptr<BackingStore>(result);
475511
}
@@ -512,6 +548,9 @@ void GlobalBackingStoreRegistry::Register(
512548
// then we don't have to guarantee that there is single unique
513549
// BackingStore per buffer_start() because the destructor of
514550
// of the BackingStore will be a no-op in that case.
551+
552+
// All WASM memory has to be registered.
553+
CHECK(!backing_store->is_wasm_memory());
515554
return;
516555
}
517556

deps/v8/src/objects/backing-store.h

+23-8
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <memory>
99

1010
#include "include/v8-internal.h"
11+
#include "include/v8.h"
1112
#include "src/handles/handles.h"
1213

1314
namespace v8 {
@@ -63,6 +64,11 @@ class V8_EXPORT_PRIVATE BackingStore : public BackingStoreBase {
6364
SharedFlag shared,
6465
bool free_on_destruct);
6566

67+
static std::unique_ptr<BackingStore> WrapAllocation(
68+
void* allocation_base, size_t allocation_length,
69+
v8::BackingStoreDeleterCallback deleter, void* deleter_data,
70+
SharedFlag shared);
71+
6672
// Create an empty backing store.
6773
static std::unique_ptr<BackingStore> EmptyBackingStore(SharedFlag shared);
6874

@@ -116,27 +122,23 @@ class V8_EXPORT_PRIVATE BackingStore : public BackingStoreBase {
116122

117123
BackingStore(void* buffer_start, size_t byte_length, size_t byte_capacity,
118124
SharedFlag shared, bool is_wasm_memory, bool free_on_destruct,
119-
bool has_guard_regions)
125+
bool has_guard_regions, bool custom_deleter)
120126
: buffer_start_(buffer_start),
121127
byte_length_(byte_length),
122128
byte_capacity_(byte_capacity),
123129
is_shared_(shared == SharedFlag::kShared),
124130
is_wasm_memory_(is_wasm_memory),
125131
free_on_destruct_(free_on_destruct),
126132
has_guard_regions_(has_guard_regions),
127-
globally_registered_(false) {
133+
globally_registered_(false),
134+
custom_deleter_(custom_deleter) {
128135
type_specific_data_.v8_api_array_buffer_allocator = nullptr;
136+
deleter_data_ = nullptr;
129137
}
130138

131139
void* buffer_start_ = nullptr;
132140
std::atomic<size_t> byte_length_{0};
133141
size_t byte_capacity_ = 0;
134-
bool is_shared_ : 1;
135-
bool is_wasm_memory_ : 1;
136-
bool free_on_destruct_ : 1;
137-
bool has_guard_regions_ : 1;
138-
bool globally_registered_ : 1;
139-
140142
union {
141143
// If this backing store was allocated through the ArrayBufferAllocator API,
142144
// this is a direct pointer to the API object for freeing the backing
@@ -148,8 +150,21 @@ class V8_EXPORT_PRIVATE BackingStore : public BackingStoreBase {
148150
// For shared Wasm memories, this is a list of all the attached memory
149151
// objects, which is needed to grow shared backing stores.
150152
SharedWasmMemoryData* shared_wasm_memory_data;
153+
154+
// Custom deleter for the backing stores that wrap memory blocks that are
155+
// allocated with a custom allocator.
156+
v8::BackingStoreDeleterCallback deleter;
151157
} type_specific_data_;
152158

159+
void* deleter_data_;
160+
161+
bool is_shared_ : 1;
162+
bool is_wasm_memory_ : 1;
163+
bool free_on_destruct_ : 1;
164+
bool has_guard_regions_ : 1;
165+
bool globally_registered_ : 1;
166+
bool custom_deleter_ : 1;
167+
153168
// Accessors for type-specific data.
154169
void* get_v8_api_array_buffer_allocator();
155170
SharedWasmMemoryData* get_shared_wasm_memory_data();

0 commit comments

Comments
 (0)