Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(139)

Unified Diff: src/value-serializer.cc

Issue 2471923002: Support structured clone of compiled WebAssembly modules. (Closed)
Patch Set: override FLAG_expose_wasm earlier in the test Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/value-serializer.h ('k') | test/unittests/value-serializer-unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/value-serializer.cc
diff --git a/src/value-serializer.cc b/src/value-serializer.cc
index c3328f1bcade58ff0a69970226af8331f393af87..86c96dac16b430ab7a5bc433a1a8f607d52267da 100644
--- a/src/value-serializer.cc
+++ b/src/value-serializer.cc
@@ -9,11 +9,15 @@
#include "src/base/logging.h"
#include "src/conversions.h"
#include "src/factory.h"
+#include "src/flags.h"
#include "src/handles-inl.h"
#include "src/isolate.h"
#include "src/objects-inl.h"
#include "src/objects.h"
+#include "src/snapshot/code-serializer.h"
#include "src/transitions.h"
+#include "src/wasm/wasm-module.h"
+#include "src/wasm/wasm-result.h"
namespace v8 {
namespace internal {
@@ -107,6 +111,11 @@ enum class SerializationTag : uint8_t {
kArrayBufferView = 'V',
// Shared array buffer (transferred). transferID:uint32_t
kSharedArrayBufferTransfer = 'u',
+ // Compiled WebAssembly module. encodingType:(one-byte tag).
+ // If encodingType == 'y' (raw bytes):
+ // wasmWireByteLength:uint32_t, then raw data
+ // compiledDataLength:uint32_t, then raw data
+ kWasmModule = 'W',
};
namespace {
@@ -124,6 +133,10 @@ enum class ArrayBufferViewTag : uint8_t {
kDataView = '?',
};
+enum class WasmEncodingTag : uint8_t {
+ kRawBytes = 'y',
+};
+
} // namespace
ValueSerializer::ValueSerializer(Isolate* isolate,
@@ -365,8 +378,16 @@ Maybe<bool> ValueSerializer::WriteJSReceiver(Handle<JSReceiver> receiver) {
case JS_OBJECT_TYPE:
case JS_API_OBJECT_TYPE: {
Handle<JSObject> js_object = Handle<JSObject>::cast(receiver);
- return js_object->GetInternalFieldCount() ? WriteHostObject(js_object)
- : WriteJSObject(js_object);
+ Map* map = js_object->map();
+ if (FLAG_expose_wasm &&
+ map->GetConstructor() ==
+ isolate_->native_context()->wasm_module_constructor()) {
+ return WriteWasmModule(js_object);
+ } else if (JSObject::GetInternalFieldCount(map)) {
+ return WriteHostObject(js_object);
+ } else {
+ return WriteJSObject(js_object);
+ }
}
case JS_SPECIAL_API_OBJECT_TYPE:
return WriteHostObject(Handle<JSObject>::cast(receiver));
@@ -717,6 +738,29 @@ Maybe<bool> ValueSerializer::WriteJSArrayBufferView(JSArrayBufferView* view) {
return Just(true);
}
+Maybe<bool> ValueSerializer::WriteWasmModule(Handle<JSObject> object) {
+ Handle<wasm::WasmCompiledModule> compiled_part(
+ wasm::WasmCompiledModule::cast(object->GetInternalField(0)), isolate_);
+ WasmEncodingTag encoding_tag = WasmEncodingTag::kRawBytes;
+ WriteTag(SerializationTag::kWasmModule);
+ WriteRawBytes(&encoding_tag, sizeof(encoding_tag));
+
+ Handle<String> wire_bytes = compiled_part->module_bytes();
+ int wire_bytes_length = wire_bytes->length();
+ WriteVarint<uint32_t>(wire_bytes_length);
+ uint8_t* destination = ReserveRawBytes(wire_bytes_length);
+ String::WriteToFlat(*wire_bytes, destination, 0, wire_bytes_length);
+
+ std::unique_ptr<ScriptData> script_data =
+ WasmCompiledModuleSerializer::SerializeWasmModule(isolate_,
+ compiled_part);
+ int script_data_length = script_data->length();
+ WriteVarint<uint32_t>(script_data_length);
+ WriteRawBytes(script_data->data(), script_data_length);
+
+ return Just(true);
+}
+
Maybe<bool> ValueSerializer::WriteHostObject(Handle<JSObject> object) {
if (!delegate_) {
isolate_->Throw(*isolate_->factory()->NewError(
@@ -1027,6 +1071,8 @@ MaybeHandle<Object> ValueDeserializer::ReadObjectInternal() {
const bool is_shared = true;
return ReadTransferredJSArrayBuffer(is_shared);
}
+ case SerializationTag::kWasmModule:
+ return ReadWasmModule();
default:
// TODO(jbroman): Introduce an explicit tag for host objects to avoid
// having to treat every unknown tag as a potential host object.
@@ -1429,6 +1475,52 @@ MaybeHandle<JSArrayBufferView> ValueDeserializer::ReadJSArrayBufferView(
return typed_array;
}
+MaybeHandle<JSObject> ValueDeserializer::ReadWasmModule() {
+ if (!FLAG_expose_wasm) return MaybeHandle<JSObject>();
+
+ Vector<const uint8_t> encoding_tag;
+ if (!ReadRawBytes(sizeof(WasmEncodingTag)).To(&encoding_tag) ||
+ encoding_tag[0] != static_cast<uint8_t>(WasmEncodingTag::kRawBytes)) {
+ return MaybeHandle<JSObject>();
+ }
+
+ // Extract the data from the buffer: wasm wire bytes, followed by V8 compiled
+ // script data.
+ static_assert(sizeof(int) <= sizeof(uint32_t),
+ "max int must fit in uint32_t");
+ const uint32_t max_valid_size = std::numeric_limits<int>::max();
+ uint32_t wire_bytes_length = 0;
+ Vector<const uint8_t> wire_bytes;
+ uint32_t compiled_bytes_length = 0;
+ Vector<const uint8_t> compiled_bytes;
+ if (!ReadVarint<uint32_t>().To(&wire_bytes_length) ||
+ wire_bytes_length > max_valid_size ||
+ !ReadRawBytes(wire_bytes_length).To(&wire_bytes) ||
+ !ReadVarint<uint32_t>().To(&compiled_bytes_length) ||
+ compiled_bytes_length > max_valid_size ||
+ !ReadRawBytes(compiled_bytes_length).To(&compiled_bytes)) {
+ return MaybeHandle<JSObject>();
+ }
+
+ // Try to deserialize the compiled module first.
+ ScriptData script_data(compiled_bytes.start(), compiled_bytes.length());
+ Handle<FixedArray> compiled_part;
+ if (WasmCompiledModuleSerializer::DeserializeWasmModule(
+ isolate_, &script_data, wire_bytes)
+ .ToHandle(&compiled_part)) {
+ return wasm::CreateWasmModuleObject(
+ isolate_, Handle<wasm::WasmCompiledModule>::cast(compiled_part),
+ wasm::ModuleOrigin::kWasmOrigin);
+ }
+
+ // If that fails, recompile.
+ wasm::ErrorThrower thrower(isolate_, "ValueDeserializer::ReadWasmModule");
+ return wasm::CreateModuleObjectFromBytes(
+ isolate_, wire_bytes.begin(), wire_bytes.end(), &thrower,
+ wasm::ModuleOrigin::kWasmOrigin, Handle<Script>::null(), nullptr,
+ nullptr);
+}
+
MaybeHandle<JSObject> ValueDeserializer::ReadHostObject() {
if (!delegate_) return MaybeHandle<JSObject>();
STACK_CHECK(isolate_, MaybeHandle<JSObject>());
« no previous file with comments | « src/value-serializer.h ('k') | test/unittests/value-serializer-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698