Commit e60edd95 authored by Ben Smith's avatar Ben Smith Committed by Commit Bot

Support postMessage of shared WebAssembly.Memory

This is only enabled when --experimental-wasm-threads is enabled.

In addition, only shared WebAssembly.Memory may be sent, as specified
here: https://github.com/WebAssembly/design/pull/1074/files#diff-8e85308ab5cc1e83e91ef59233648be2R227

Bug: v8:6895
Change-Id: Id009a7f890d15fa6c98e93f03806f7e7eff30c2a
Reviewed-on: https://chromium-review.googlesource.com/719417
Commit-Queue: Brad Nelson <bradnelson@chromium.org>
Reviewed-by: 's avatarDeepti Gandluri <gdeepti@chromium.org>
Reviewed-by: 's avatarBrad Nelson <bradnelson@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48609}
parent 4213af64
......@@ -143,6 +143,9 @@ enum class SerializationTag : uint8_t {
// The delegate is responsible for processing all following data.
// This "escapes" to whatever wire format the delegate chooses.
kHostObject = '\\',
// A transferred WebAssembly.Memory object. maximumPages:int32_t, then by
// SharedArrayBuffer tag and its data.
kWasmMemoryTransfer = 'm',
};
namespace {
......@@ -479,7 +482,16 @@ Maybe<bool> ValueSerializer::WriteJSReceiver(Handle<JSReceiver> receiver) {
if (!FLAG_wasm_disable_structured_cloning) {
// Only write WebAssembly modules if not disabled by a flag.
return WriteWasmModule(Handle<WasmModuleObject>::cast(receiver));
} // fall through to error case
}
goto error;
case WASM_MEMORY_TYPE:
if (FLAG_experimental_wasm_threads) {
// Only write WebAssembly modules if not disabled by a flag.
return WriteWasmMemory(Handle<WasmMemoryObject>::cast(receiver));
}
goto error;
error:
default:
ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver);
return Nothing<bool>();
......@@ -855,6 +867,17 @@ Maybe<bool> ValueSerializer::WriteWasmModule(Handle<WasmModuleObject> object) {
return ThrowIfOutOfMemory();
}
Maybe<bool> ValueSerializer::WriteWasmMemory(Handle<WasmMemoryObject> object) {
if (!object->array_buffer()->is_shared()) {
ThrowDataCloneError(MessageTemplate::kDataCloneError, object);
return Nothing<bool>();
}
WriteTag(SerializationTag::kWasmMemoryTransfer);
WriteZigZag<int32_t>(object->maximum_pages());
return WriteJSReceiver(Handle<JSReceiver>(object->array_buffer(), isolate_));
}
Maybe<bool> ValueSerializer::WriteHostObject(Handle<JSObject> object) {
WriteTag(SerializationTag::kHostObject);
if (!delegate_) {
......@@ -1177,6 +1200,8 @@ MaybeHandle<Object> ValueDeserializer::ReadObjectInternal() {
return ReadWasmModule();
case SerializationTag::kWasmModuleTransfer:
return ReadWasmModuleTransfer();
case SerializationTag::kWasmMemoryTransfer:
return ReadWasmMemory();
case SerializationTag::kHostObject:
return ReadHostObject();
default:
......@@ -1710,6 +1735,30 @@ MaybeHandle<JSObject> ValueDeserializer::ReadWasmModule() {
return result;
}
MaybeHandle<JSObject> ValueDeserializer::ReadWasmMemory() {
if (!FLAG_experimental_wasm_threads) {
return MaybeHandle<JSObject>();
}
int32_t maximum_pages;
if (!ReadZigZag<int32_t>().To(&maximum_pages)) {
return MaybeHandle<JSObject>();
}
SerializationTag tag;
if (!ReadTag().To(&tag) || tag != SerializationTag::kSharedArrayBuffer) {
return MaybeHandle<JSObject>();
}
const bool is_shared = true;
Handle<JSArrayBuffer> buffer;
if (!ReadTransferredJSArrayBuffer(is_shared).ToHandle(&buffer)) {
return MaybeHandle<JSObject>();
}
return WasmMemoryObject::New(isolate_, buffer, maximum_pages);
}
MaybeHandle<JSObject> ValueDeserializer::ReadHostObject() {
if (!delegate_) return MaybeHandle<JSObject>();
STACK_CHECK(isolate_, MaybeHandle<JSObject>());
......
......@@ -31,6 +31,7 @@ class JSValue;
class Object;
class Oddball;
class Smi;
class WasmMemoryObject;
class WasmModuleObject;
enum class SerializationTag : uint8_t;
......@@ -127,6 +128,8 @@ class ValueSerializer {
Maybe<bool> WriteJSArrayBufferView(JSArrayBufferView* array_buffer);
Maybe<bool> WriteWasmModule(Handle<WasmModuleObject> object)
WARN_UNUSED_RESULT;
Maybe<bool> WriteWasmMemory(Handle<WasmMemoryObject> object)
WARN_UNUSED_RESULT;
Maybe<bool> WriteHostObject(Handle<JSObject> object) WARN_UNUSED_RESULT;
/*
......@@ -270,6 +273,7 @@ class ValueDeserializer {
Handle<JSArrayBuffer> buffer) WARN_UNUSED_RESULT;
MaybeHandle<JSObject> ReadWasmModule() WARN_UNUSED_RESULT;
MaybeHandle<JSObject> ReadWasmModuleTransfer() WARN_UNUSED_RESULT;
MaybeHandle<JSObject> ReadWasmMemory() WARN_UNUSED_RESULT;
MaybeHandle<JSObject> ReadHostObject() WARN_UNUSED_RESULT;
/*
......
// Copyright 2017 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: --experimental-wasm-threads
(function TestPostMessageUnsharedMemory() {
let worker = new Worker('');
let memory = new WebAssembly.Memory({initial: 1, maximum: 2});
assertThrows(() => worker.postMessage(memory), Error);
})();
(function TestPostMessageSharedMemory() {
let workerScript =
`onmessage = function(memory) {
// Can't use assert in a worker.
if (!(memory instanceof WebAssembly.Memory)) {
postMessage("Error: memory is not a WebAssembly.Memory");
return;
}
if (!(memory.buffer instanceof SharedArrayBuffer)) {
postMessage("Error: memory.buffer is not a SharedArrayBuffer");
return;
}
if (memory.buffer.byteLength != 65536) {
postMessage("Error: memory.buffer.byteLength is not 1 page");
return;
}
postMessage("OK");
};`;
let worker = new Worker(workerScript);
let memory = new WebAssembly.Memory({initial: 1, maximum: 2, shared: true});
worker.postMessage(memory);
assertEquals("OK", worker.getMessage());
worker.terminate();
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment