[wasm] postMessage of WebAssembly.Module in d8

Supporting postMessage from WebAssembly.Module requires implementing
some logic in the ValueSerializer and ValueDeserializer delegates. This
change implements some simple logic for d8.

This change also fixes a DCHECK that occurs when sending a shared
WebAssembly.Memory object to two Workers.

Bug: chromium:857049
Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng
Change-Id: Idddb23a48175c7175967af3fbc03d8572452a069
Reviewed-on: https://chromium-review.googlesource.com/1117871
Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
Commit-Queue: Ben Smith <binji@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54093}
This commit is contained in:
Ben Smith 2018-06-27 17:39:19 -07:00 committed by Commit Bot
parent 63372e4679
commit c9b4f805a3
7 changed files with 93 additions and 5 deletions

View File

@ -7664,8 +7664,7 @@ v8::ArrayBuffer::Contents v8::ArrayBuffer::Externalize() {
// longer track it.
//
// TODO(eholk): Find a way to track this across externalization
isolate->wasm_engine()->memory_tracker()->ReleaseAllocation(
self->backing_store());
self->StopTrackingWasmMemory(isolate);
}
isolate->heap()->UnregisterArrayBuffer(*self);
@ -7899,8 +7898,7 @@ v8::SharedArrayBuffer::Contents v8::SharedArrayBuffer::Externalize() {
// longer track it.
//
// TODO(eholk): Find a way to track this across externalization
isolate->wasm_engine()->memory_tracker()->ReleaseAllocation(
self->backing_store());
self->StopTrackingWasmMemory(isolate);
}
isolate->heap()->UnregisterArrayBuffer(*self);

View File

@ -3075,6 +3075,21 @@ class Serializer : public ValueSerializer::Delegate {
return Just<uint32_t>(static_cast<uint32_t>(index));
}
Maybe<uint32_t> GetWasmModuleTransferId(
Isolate* isolate, Local<WasmCompiledModule> module) override {
DCHECK_NOT_NULL(data_);
for (size_t index = 0; index < wasm_modules_.size(); ++index) {
if (wasm_modules_[index] == module) {
return Just<uint32_t>(static_cast<uint32_t>(index));
}
}
size_t index = wasm_modules_.size();
wasm_modules_.emplace_back(isolate_, module);
data_->transferrable_modules_.push_back(module->GetTransferrableModule());
return Just<uint32_t>(static_cast<uint32_t>(index));
}
void* ReallocateBufferMemory(void* old_buffer, size_t size,
size_t* actual_size) override {
// Not accurate, because we don't take into account reallocated buffers,
@ -3152,6 +3167,7 @@ class Serializer : public ValueSerializer::Delegate {
std::unique_ptr<SerializationData> data_;
std::vector<Global<ArrayBuffer>> array_buffers_;
std::vector<Global<SharedArrayBuffer>> shared_array_buffers_;
std::vector<Global<WasmCompiledModule>> wasm_modules_;
std::vector<ExternalizedContents> externalized_contents_;
size_t current_memory_usage_;
@ -3195,6 +3211,16 @@ class Deserializer : public ValueDeserializer::Delegate {
return MaybeLocal<SharedArrayBuffer>();
}
MaybeLocal<WasmCompiledModule> GetWasmModuleFromId(
Isolate* isolate, uint32_t transfer_id) override {
DCHECK_NOT_NULL(data_);
if (transfer_id < data_->transferrable_modules().size()) {
return WasmCompiledModule::FromTransferrableModule(
isolate_, data_->transferrable_modules().at(transfer_id));
}
return MaybeLocal<WasmCompiledModule>();
}
private:
Isolate* isolate_;
ValueDeserializer deserializer_;

View File

@ -177,7 +177,10 @@ class SerializationData {
shared_array_buffer_contents() {
return shared_array_buffer_contents_;
}
const std::vector<WasmCompiledModule::TransferrableModule>&
transferrable_modules() {
return transferrable_modules_;
}
private:
struct DataDeleter {
@ -188,6 +191,7 @@ class SerializationData {
size_t size_;
std::vector<ArrayBuffer::Contents> array_buffer_contents_;
std::vector<SharedArrayBuffer::Contents> shared_array_buffer_contents_;
std::vector<WasmCompiledModule::TransferrableModule> transferrable_modules_;
private:
friend class Serializer;

View File

@ -18481,6 +18481,12 @@ void JSArrayBuffer::Neuter() {
}
}
void JSArrayBuffer::StopTrackingWasmMemory(Isolate* isolate) {
DCHECK(is_wasm_memory());
isolate->wasm_engine()->memory_tracker()->ReleaseAllocation(backing_store());
set_is_wasm_memory(false);
}
void JSArrayBuffer::FreeBackingStoreFromMainThread() {
if (allocation_base() == nullptr) {
return;

View File

@ -196,6 +196,10 @@ class JSArrayBuffer : public JSObject {
// Sets whether the buffer is tracked by the WasmMemoryTracker.
void set_is_wasm_memory(bool is_wasm_memory);
// Removes the backing store from the WasmMemoryTracker and sets
// |is_wasm_memory| to false.
void StopTrackingWasmMemory(Isolate* isolate);
void FreeBackingStoreFromMainThread();
static void FreeBackingStore(Isolate* isolate, Allocation allocation);

View File

@ -67,3 +67,19 @@ let workerHelpers =
assertEquals("OK", worker.getMessage());
worker.terminate();
})();
(function TestTwoWorkers() {
let workerScript = workerHelpers +
`onmessage = function(memory) {
assertIsWasmMemory(memory, 65536);
postMessage("OK");
};`;
let workers = [new Worker(workerScript), new Worker(workerScript)];
let memory = new WebAssembly.Memory({initial: 1, maximum: 2, shared: true});
for (let worker of workers) {
worker.postMessage(memory);
assertEquals("OK", worker.getMessage());
worker.terminate();
}
})();

View File

@ -0,0 +1,34 @@
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --no-wasm-disable-structured-cloning
load("test/mjsunit/wasm/wasm-constants.js");
load("test/mjsunit/wasm/wasm-module-builder.js");
function TestCloneModule() {
let builder = new WasmModuleBuilder();
builder.addFunction("add", kSig_i_ii)
.addBody([kExprGetLocal, 0, kExprGetLocal, 1, kExprI32Add])
.exportFunc();
let module = builder.toModule();
let workerScript = `
onmessage = function(module) {
try {
let instance = new WebAssembly.Instance(module);
let result = instance.exports.add(40, 2);
postMessage(result);
} catch(e) {
postMessage('ERROR: ' + e);
}
}
`;
let worker = new Worker(workerScript);
worker.postMessage(module);
assertEquals(42, worker.getMessage());
worker.terminate();
}