Skip to content

Commit e8c7b7a

Browse files
addaleaxBethGriggs
authored andcommitted
deps: V8: cherry-pick b5c917ee80cb
Original commit message: [api] New function for reallocating ArrayBuffer backing store This patch adds a new BackingStore::Reallocate function that internally uses a new ArrayBuffer::Allocator::Reallocate provided by the embedder. The default implementation of the function simply copies the backing store. The embedder can override the function and provide a more efficient implementation e.g. using realloc. Bug: v8:9908, v8:9380 Change-Id: I2179c80ba199c045b6900c620a813916150e7098 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2007274 Commit-Queue: Ulan Degenbaev <[email protected]> Reviewed-by: Andreas Haas <[email protected]> Cr-Commit-Position: refs/heads/master@{#66044} Refs: v8/v8@b5c917e PR-URL: #32885 Reviewed-By: Michaël Zasso <[email protected]> Reviewed-By: Ujjwal Sharma <[email protected]> Reviewed-By: Gerhard Stöbich <[email protected]> Reviewed-By: Beth Griggs <[email protected]>
1 parent 552cee0 commit e8c7b7a

File tree

7 files changed

+162
-3
lines changed

7 files changed

+162
-3
lines changed

common.gypi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535

3636
# Reset this number to 0 on major V8 upgrades.
3737
# Increment by one for each non-official patch applied to deps/v8.
38-
'v8_embedder_string': '-node.24',
38+
'v8_embedder_string': '-node.25',
3939

4040
##### V8 defaults for Node.js #####
4141

deps/v8/include/v8.h

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4930,6 +4930,15 @@ class V8_EXPORT BackingStore : public v8::internal::BackingStoreBase {
49304930
*/
49314931
bool IsShared() const;
49324932

4933+
/**
4934+
* Wrapper around ArrayBuffer::Allocator::Reallocate that preserves IsShared.
4935+
* Assumes that the backing_store was allocated by the ArrayBuffer allocator
4936+
* of the given isolate.
4937+
*/
4938+
static std::unique_ptr<BackingStore> Reallocate(
4939+
v8::Isolate* isolate, std::unique_ptr<BackingStore> backing_store,
4940+
size_t byte_length);
4941+
49334942
private:
49344943
/**
49354944
* See [Shared]ArrayBuffer::GetBackingStore and
@@ -4971,13 +4980,13 @@ class V8_EXPORT ArrayBuffer : public Object {
49714980
virtual ~Allocator() = default;
49724981

49734982
/**
4974-
* Allocate |length| bytes. Return NULL if allocation is not successful.
4983+
* Allocate |length| bytes. Return nullptr if allocation is not successful.
49754984
* Memory should be initialized to zeroes.
49764985
*/
49774986
virtual void* Allocate(size_t length) = 0;
49784987

49794988
/**
4980-
* Allocate |length| bytes. Return NULL if allocation is not successful.
4989+
* Allocate |length| bytes. Return nullptr if allocation is not successful.
49814990
* Memory does not have to be initialized.
49824991
*/
49834992
virtual void* AllocateUninitialized(size_t length) = 0;
@@ -4988,6 +4997,20 @@ class V8_EXPORT ArrayBuffer : public Object {
49884997
*/
49894998
virtual void Free(void* data, size_t length) = 0;
49904999

5000+
/**
5001+
* Reallocate the memory block of size |old_length| to a memory block of
5002+
* size |new_length| by expanding, contracting, or copying the existing
5003+
* memory block. If |new_length| > |old_length|, then the new part of
5004+
* the memory must be initialized to zeros. Return nullptr if reallocation
5005+
* is not successful.
5006+
*
5007+
* The caller guarantees that the memory block was previously allocated
5008+
* using Allocate or AllocateUninitialized.
5009+
*
5010+
* The default implementation allocates a new block and copies data.
5011+
*/
5012+
virtual void* Reallocate(void* data, size_t old_length, size_t new_length);
5013+
49915014
/**
49925015
* ArrayBuffer allocation mode. kNormal is a malloc/free style allocation,
49935016
* while kReservation is for larger allocations with the ability to set

deps/v8/src/api/api.cc

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,21 @@ class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
552552
}
553553

554554
void Free(void* data, size_t) override { free(data); }
555+
556+
void* Reallocate(void* data, size_t old_length, size_t new_length) override {
557+
#if V8_OS_AIX && _LINUX_SOURCE_COMPAT
558+
// Work around for GCC bug on AIX
559+
// See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79839
560+
void* new_data = __linux_realloc(data, new_length);
561+
#else
562+
void* new_data = realloc(data, new_length);
563+
#endif
564+
if (new_length > old_length) {
565+
memset(reinterpret_cast<uint8_t*>(new_data) + old_length, 0,
566+
new_length - old_length);
567+
}
568+
return new_data;
569+
}
555570
};
556571

557572
struct SnapshotCreatorData {
@@ -3759,6 +3774,22 @@ bool v8::BackingStore::IsShared() const {
37593774
return reinterpret_cast<const i::BackingStore*>(this)->is_shared();
37603775
}
37613776

3777+
// static
3778+
std::unique_ptr<v8::BackingStore> v8::BackingStore::Reallocate(
3779+
v8::Isolate* isolate, std::unique_ptr<v8::BackingStore> backing_store,
3780+
size_t byte_length) {
3781+
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
3782+
LOG_API(i_isolate, ArrayBuffer, BackingStore_Reallocate);
3783+
CHECK_LE(byte_length, i::JSArrayBuffer::kMaxByteLength);
3784+
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
3785+
i::BackingStore* i_backing_store =
3786+
reinterpret_cast<i::BackingStore*>(backing_store.get());
3787+
if (!i_backing_store->Reallocate(i_isolate, byte_length)) {
3788+
i::FatalProcessOutOfMemory(i_isolate, "v8::BackingStore::Reallocate");
3789+
}
3790+
return backing_store;
3791+
}
3792+
37623793
std::shared_ptr<v8::BackingStore> v8::ArrayBuffer::GetBackingStore() {
37633794
i::Handle<i::JSArrayBuffer> self = Utils::OpenHandle(this);
37643795
std::shared_ptr<i::BackingStore> backing_store = self->GetBackingStore();
@@ -7204,6 +7235,21 @@ void WasmModuleObjectBuilderStreaming::Finish() {}
72047235

72057236
void WasmModuleObjectBuilderStreaming::Abort(MaybeLocal<Value> exception) {}
72067237

7238+
void* v8::ArrayBuffer::Allocator::Reallocate(void* data, size_t old_length,
7239+
size_t new_length) {
7240+
if (old_length == new_length) return data;
7241+
uint8_t* new_data =
7242+
reinterpret_cast<uint8_t*>(AllocateUninitialized(new_length));
7243+
if (new_data == nullptr) return nullptr;
7244+
size_t bytes_to_copy = std::min(old_length, new_length);
7245+
memcpy(new_data, data, bytes_to_copy);
7246+
if (new_length > bytes_to_copy) {
7247+
memset(new_data + bytes_to_copy, 0, new_length - bytes_to_copy);
7248+
}
7249+
Free(data, old_length);
7250+
return new_data;
7251+
}
7252+
72077253
// static
72087254
v8::ArrayBuffer::Allocator* v8::ArrayBuffer::Allocator::NewDefaultAllocator() {
72097255
return new ArrayBufferAllocator();

deps/v8/src/logging/counters.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,7 @@ class RuntimeCallTimer final {
735735
V(ArrayBuffer_Detach) \
736736
V(ArrayBuffer_New) \
737737
V(ArrayBuffer_NewBackingStore) \
738+
V(ArrayBuffer_BackingStore_Reallocate) \
738739
V(Array_CloneElementAt) \
739740
V(Array_New) \
740741
V(BigInt64Array_New) \

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,21 @@ std::unique_ptr<BackingStore> BackingStore::EmptyBackingStore(
561561
return std::unique_ptr<BackingStore>(result);
562562
}
563563

564+
bool BackingStore::Reallocate(Isolate* isolate, size_t new_byte_length) {
565+
CHECK(!is_wasm_memory_ && !custom_deleter_ && !globally_registered_ &&
566+
free_on_destruct_);
567+
auto allocator = get_v8_api_array_buffer_allocator();
568+
CHECK_EQ(isolate->array_buffer_allocator(), allocator);
569+
CHECK_EQ(byte_length_, byte_capacity_);
570+
void* new_start =
571+
allocator->Reallocate(buffer_start_, byte_length_, new_byte_length);
572+
if (!new_start) return false;
573+
buffer_start_ = new_start;
574+
byte_capacity_ = new_byte_length;
575+
byte_length_ = new_byte_length;
576+
return true;
577+
}
578+
564579
v8::ArrayBuffer::Allocator* BackingStore::get_v8_api_array_buffer_allocator() {
565580
CHECK(!is_wasm_memory_);
566581
auto array_buffer_allocator =

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ class V8_EXPORT_PRIVATE BackingStore : public BackingStoreBase {
8787
bool GrowWasmMemoryInPlace(Isolate* isolate, size_t delta_pages,
8888
size_t max_pages);
8989

90+
// Wrapper around ArrayBuffer::Allocator::Reallocate.
91+
bool Reallocate(Isolate* isolate, size_t new_byte_length);
92+
9093
// Allocate a new, larger, backing store for this Wasm memory and copy the
9194
// contents of this backing store into it.
9295
std::unique_ptr<BackingStore> CopyWasmMemory(Isolate* isolate,

deps/v8/test/cctest/test-api-array-buffer.cc

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,3 +761,74 @@ TEST(BackingStore_HoldAllocatorAlive_AfterIsolateShutdown) {
761761
backing_store.reset();
762762
CHECK(allocator_weak.expired());
763763
}
764+
765+
TEST(BackingStore_ReallocateExpand) {
766+
LocalContext env;
767+
v8::Isolate* isolate = env->GetIsolate();
768+
std::unique_ptr<v8::BackingStore> backing_store =
769+
v8::ArrayBuffer::NewBackingStore(isolate, 10);
770+
{
771+
uint8_t* data = reinterpret_cast<uint8_t*>(
772+
reinterpret_cast<uintptr_t>(backing_store->Data()));
773+
for (uint8_t i = 0; i < 10; i++) {
774+
data[i] = i;
775+
}
776+
}
777+
std::unique_ptr<v8::BackingStore> new_backing_store =
778+
v8::BackingStore::Reallocate(isolate, std::move(backing_store), 20);
779+
CHECK_EQ(new_backing_store->ByteLength(), 20);
780+
CHECK(!new_backing_store->IsShared());
781+
{
782+
uint8_t* data = reinterpret_cast<uint8_t*>(
783+
reinterpret_cast<uintptr_t>(new_backing_store->Data()));
784+
for (uint8_t i = 0; i < 10; i++) {
785+
CHECK_EQ(data[i], i);
786+
}
787+
for (uint8_t i = 10; i < 20; i++) {
788+
CHECK_EQ(data[i], 0);
789+
}
790+
}
791+
}
792+
793+
TEST(BackingStore_ReallocateShrink) {
794+
LocalContext env;
795+
v8::Isolate* isolate = env->GetIsolate();
796+
std::unique_ptr<v8::BackingStore> backing_store =
797+
v8::ArrayBuffer::NewBackingStore(isolate, 20);
798+
{
799+
uint8_t* data = reinterpret_cast<uint8_t*>(backing_store->Data());
800+
for (uint8_t i = 0; i < 20; i++) {
801+
data[i] = i;
802+
}
803+
}
804+
std::unique_ptr<v8::BackingStore> new_backing_store =
805+
v8::BackingStore::Reallocate(isolate, std::move(backing_store), 10);
806+
CHECK_EQ(new_backing_store->ByteLength(), 10);
807+
CHECK(!new_backing_store->IsShared());
808+
{
809+
uint8_t* data = reinterpret_cast<uint8_t*>(new_backing_store->Data());
810+
for (uint8_t i = 0; i < 10; i++) {
811+
CHECK_EQ(data[i], i);
812+
}
813+
}
814+
}
815+
816+
TEST(BackingStore_ReallocateNotShared) {
817+
LocalContext env;
818+
v8::Isolate* isolate = env->GetIsolate();
819+
std::unique_ptr<v8::BackingStore> backing_store =
820+
v8::ArrayBuffer::NewBackingStore(isolate, 20);
821+
std::unique_ptr<v8::BackingStore> new_backing_store =
822+
v8::BackingStore::Reallocate(isolate, std::move(backing_store), 10);
823+
CHECK(!new_backing_store->IsShared());
824+
}
825+
826+
TEST(BackingStore_ReallocateShared) {
827+
LocalContext env;
828+
v8::Isolate* isolate = env->GetIsolate();
829+
std::unique_ptr<v8::BackingStore> backing_store =
830+
v8::SharedArrayBuffer::NewBackingStore(isolate, 20);
831+
std::unique_ptr<v8::BackingStore> new_backing_store =
832+
v8::BackingStore::Reallocate(isolate, std::move(backing_store), 10);
833+
CHECK(new_backing_store->IsShared());
834+
}

0 commit comments

Comments
 (0)