Add a contents based constructor to the SharedArrayBuffer API

The motivation of this change was originally to preserve is_growable
flag over PostMessage in d8. Adding a more general constructor that
uses SharedArrayBuffer::Contents.

Change-Id: Ib8f6c36d659e91f6cfb6487f56de34fa7e8841a9
Bug: v8:8564
Reviewed-on: https://chromium-review.googlesource.com/c/1383093
Commit-Queue: Deepti Gandluri <gdeepti@chromium.org>
Reviewed-by: Ben Smith <binji@chromium.org>
Reviewed-by: Adam Klein <adamk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59184}
This commit is contained in:
Deepti Gandluri 2019-01-29 11:06:38 -08:00 committed by Commit Bot
parent 76c9368593
commit 4089299494
4 changed files with 55 additions and 23 deletions

View File

@ -5177,7 +5177,8 @@ class V8_EXPORT SharedArrayBuffer : public Object {
allocation_length_(0),
allocation_mode_(Allocator::AllocationMode::kNormal),
deleter_(nullptr),
deleter_data_(nullptr) {}
deleter_data_(nullptr),
is_growable_(false) {}
void* AllocationBase() const { return allocation_base_; }
size_t AllocationLength() const { return allocation_length_; }
@ -5189,12 +5190,13 @@ class V8_EXPORT SharedArrayBuffer : public Object {
size_t ByteLength() const { return byte_length_; }
DeleterCallback Deleter() const { return deleter_; }
void* DeleterData() const { return deleter_data_; }
bool IsGrowable() const { return is_growable_; }
private:
Contents(void* data, size_t byte_length, void* allocation_base,
size_t allocation_length,
Allocator::AllocationMode allocation_mode, DeleterCallback deleter,
void* deleter_data);
void* deleter_data, bool is_growable);
void* data_;
size_t byte_length_;
@ -5203,6 +5205,7 @@ class V8_EXPORT SharedArrayBuffer : public Object {
Allocator::AllocationMode allocation_mode_;
DeleterCallback deleter_;
void* deleter_data_;
bool is_growable_;
friend class SharedArrayBuffer;
};
@ -5230,6 +5233,14 @@ class V8_EXPORT SharedArrayBuffer : public Object {
Isolate* isolate, void* data, size_t byte_length,
ArrayBufferCreationMode mode = ArrayBufferCreationMode::kExternalized);
/**
* Create a new SharedArrayBuffer over an existing memory block. Propagate
* flags to indicate whether the underlying buffer can be grown.
*/
static Local<SharedArrayBuffer> New(
Isolate* isolate, const SharedArrayBuffer::Contents&,
ArrayBufferCreationMode mode = ArrayBufferCreationMode::kExternalized);
/**
* Returns true if SharedArrayBuffer is externalized, that is, does not
* own its memory block.

View File

@ -7718,6 +7718,27 @@ Local<DataView> DataView::New(Local<SharedArrayBuffer> shared_array_buffer,
return Utils::ToLocal(obj);
}
namespace {
i::Handle<i::JSArrayBuffer> SetupSharedArrayBuffer(
Isolate* isolate, void* data, size_t byte_length,
ArrayBufferCreationMode mode) {
CHECK(i::FLAG_harmony_sharedarraybuffer);
// Embedders must guarantee that the external backing store is valid.
CHECK(byte_length == 0 || data != nullptr);
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
LOG_API(i_isolate, SharedArrayBuffer, New);
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
i::Handle<i::JSArrayBuffer> obj =
i_isolate->factory()->NewJSArrayBuffer(i::SharedFlag::kShared);
bool is_wasm_memory =
i_isolate->wasm_engine()->memory_tracker()->IsWasmMemory(data);
i::JSArrayBuffer::Setup(obj, i_isolate,
mode == ArrayBufferCreationMode::kExternalized, data,
byte_length, i::SharedFlag::kShared, is_wasm_memory);
return obj;
}
} // namespace
bool v8::SharedArrayBuffer::IsExternal() const {
return Utils::OpenHandle(this)->is_external();
@ -7740,14 +7761,15 @@ v8::SharedArrayBuffer::Contents v8::SharedArrayBuffer::Externalize() {
v8::SharedArrayBuffer::Contents::Contents(
void* data, size_t byte_length, void* allocation_base,
size_t allocation_length, Allocator::AllocationMode allocation_mode,
DeleterCallback deleter, void* deleter_data)
DeleterCallback deleter, void* deleter_data, bool is_growable)
: data_(data),
byte_length_(byte_length),
allocation_base_(allocation_base),
allocation_length_(allocation_length),
allocation_mode_(allocation_mode),
deleter_(deleter),
deleter_data_(deleter_data) {
deleter_data_(deleter_data),
is_growable_(is_growable) {
DCHECK_LE(allocation_base_, data_);
DCHECK_LE(byte_length_, allocation_length_);
}
@ -7765,7 +7787,8 @@ v8::SharedArrayBuffer::Contents v8::SharedArrayBuffer::GetContents() {
: reinterpret_cast<Contents::DeleterCallback>(ArrayBufferDeleter),
self->is_wasm_memory()
? static_cast<void*>(self->GetIsolate()->wasm_engine())
: static_cast<void*>(self->GetIsolate()->array_buffer_allocator()));
: static_cast<void*>(self->GetIsolate()->array_buffer_allocator()),
self->is_growable());
return contents;
}
@ -7795,22 +7818,19 @@ Local<SharedArrayBuffer> v8::SharedArrayBuffer::New(Isolate* isolate,
Local<SharedArrayBuffer> v8::SharedArrayBuffer::New(
Isolate* isolate, void* data, size_t byte_length,
ArrayBufferCreationMode mode) {
CHECK(i::FLAG_harmony_sharedarraybuffer);
// Embedders must guarantee that the external backing store is valid.
CHECK(byte_length == 0 || data != nullptr);
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
LOG_API(i_isolate, SharedArrayBuffer, New);
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
i::Handle<i::JSArrayBuffer> obj =
i_isolate->factory()->NewJSArrayBuffer(i::SharedFlag::kShared);
bool is_wasm_memory =
i_isolate->wasm_engine()->memory_tracker()->IsWasmMemory(data);
i::JSArrayBuffer::Setup(obj, i_isolate,
mode == ArrayBufferCreationMode::kExternalized, data,
byte_length, i::SharedFlag::kShared, is_wasm_memory);
return Utils::ToLocalShared(obj);
i::Handle<i::JSArrayBuffer> buffer =
SetupSharedArrayBuffer(isolate, data, byte_length, mode);
return Utils::ToLocalShared(buffer);
}
Local<SharedArrayBuffer> v8::SharedArrayBuffer::New(
Isolate* isolate, const SharedArrayBuffer::Contents& contents,
ArrayBufferCreationMode mode) {
i::Handle<i::JSArrayBuffer> buffer = SetupSharedArrayBuffer(
isolate, contents.Data(), contents.ByteLength(), mode);
buffer->set_is_growable(contents.IsGrowable());
return Utils::ToLocalShared(buffer);
}
Local<Symbol> v8::Symbol::New(Isolate* isolate, Local<String> name) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);

View File

@ -3244,10 +3244,9 @@ class Deserializer : public ValueDeserializer::Delegate {
Isolate* isolate, uint32_t clone_id) override {
DCHECK_NOT_NULL(data_);
if (clone_id < data_->shared_array_buffer_contents().size()) {
SharedArrayBuffer::Contents contents =
const SharedArrayBuffer::Contents contents =
data_->shared_array_buffer_contents().at(clone_id);
return SharedArrayBuffer::New(isolate_, contents.Data(),
contents.ByteLength());
return SharedArrayBuffer::New(isolate_, contents);
}
return MaybeLocal<SharedArrayBuffer>();
}

View File

@ -1055,7 +1055,9 @@ int32_t WasmMemoryObject::Grow(Isolate* isolate,
uint32_t pages) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"), "GrowMemory");
Handle<JSArrayBuffer> old_buffer(memory_object->array_buffer(), isolate);
if (!old_buffer->is_growable()) return -1;
// TODO(gdeepti): Remove check for is_shared when Growing Shared memory
// is supported.
if (!old_buffer->is_growable() || old_buffer->is_shared()) return -1;
// Checks for maximum memory size, compute new size.
uint32_t maximum_pages = wasm::max_mem_pages();