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

Side by Side Diff: src/value-serializer.cc

Issue 2748473004: [wasm] Transferrable modules (Closed)
Patch Set: compile error Created 3 years, 9 months 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 unified diff | Download patch
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/value-serializer.h" 5 #include "src/value-serializer.h"
6 6
7 #include <type_traits> 7 #include <type_traits>
8 8
9 #include "src/base/logging.h" 9 #include "src/base/logging.h"
10 #include "src/conversions.h" 10 #include "src/conversions.h"
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 // ObjectReference to one) serialized just before it. This is a quirk arising 119 // ObjectReference to one) serialized just before it. This is a quirk arising
120 // from the previous stack-based implementation. 120 // from the previous stack-based implementation.
121 kArrayBufferView = 'V', 121 kArrayBufferView = 'V',
122 // Shared array buffer. transferID:uint32_t 122 // Shared array buffer. transferID:uint32_t
123 kSharedArrayBuffer = 'u', 123 kSharedArrayBuffer = 'u',
124 // Compiled WebAssembly module. encodingType:(one-byte tag). 124 // Compiled WebAssembly module. encodingType:(one-byte tag).
125 // If encodingType == 'y' (raw bytes): 125 // If encodingType == 'y' (raw bytes):
126 // wasmWireByteLength:uint32_t, then raw data 126 // wasmWireByteLength:uint32_t, then raw data
127 // compiledDataLength:uint32_t, then raw data 127 // compiledDataLength:uint32_t, then raw data
128 kWasmModule = 'W', 128 kWasmModule = 'W',
129 // A wasm module object transfer. next value is its index.
130 kWasmModuleTransfer = 'w',
129 // The delegate is responsible for processing all following data. 131 // The delegate is responsible for processing all following data.
130 // This "escapes" to whatever wire format the delegate chooses. 132 // This "escapes" to whatever wire format the delegate chooses.
131 kHostObject = '\\', 133 kHostObject = '\\',
132 }; 134 };
133 135
134 namespace { 136 namespace {
135 137
136 enum class ArrayBufferViewTag : uint8_t { 138 enum class ArrayBufferViewTag : uint8_t {
137 kInt8Array = 'b', 139 kInt8Array = 'b',
138 kUint8Array = 'B', 140 kUint8Array = 'B',
(...skipping 657 matching lines...) Expand 10 before | Expand all | Expand 10 after
796 DCHECK(view->IsJSDataView()); 798 DCHECK(view->IsJSDataView());
797 tag = ArrayBufferViewTag::kDataView; 799 tag = ArrayBufferViewTag::kDataView;
798 } 800 }
799 WriteVarint(static_cast<uint8_t>(tag)); 801 WriteVarint(static_cast<uint8_t>(tag));
800 WriteVarint(NumberToUint32(view->byte_offset())); 802 WriteVarint(NumberToUint32(view->byte_offset()));
801 WriteVarint(NumberToUint32(view->byte_length())); 803 WriteVarint(NumberToUint32(view->byte_length()));
802 return ThrowIfOutOfMemory(); 804 return ThrowIfOutOfMemory();
803 } 805 }
804 806
805 Maybe<bool> ValueSerializer::WriteWasmModule(Handle<JSObject> object) { 807 Maybe<bool> ValueSerializer::WriteWasmModule(Handle<JSObject> object) {
808 if (delegate_ != nullptr) {
809 Maybe<uint32_t> transfer_id = delegate_->GetWasmModuleTransferId(
810 reinterpret_cast<v8::Isolate*>(isolate_),
811 v8::Local<v8::WasmCompiledModule>::Cast(Utils::ToLocal(object)));
812 uint32_t id = 0;
813 if (transfer_id.To(&id)) {
814 WriteTag(SerializationTag::kWasmModuleTransfer);
815 WriteVarint<uint32_t>(id);
816 return Just(true);
817 }
818 }
819
806 Handle<WasmCompiledModule> compiled_part( 820 Handle<WasmCompiledModule> compiled_part(
807 WasmCompiledModule::cast(object->GetInternalField(0)), isolate_); 821 WasmCompiledModule::cast(object->GetInternalField(0)), isolate_);
808 WasmEncodingTag encoding_tag = WasmEncodingTag::kRawBytes; 822 WasmEncodingTag encoding_tag = WasmEncodingTag::kRawBytes;
809 WriteTag(SerializationTag::kWasmModule); 823 WriteTag(SerializationTag::kWasmModule);
810 WriteRawBytes(&encoding_tag, sizeof(encoding_tag)); 824 WriteRawBytes(&encoding_tag, sizeof(encoding_tag));
811 825
812 Handle<String> wire_bytes(compiled_part->module_bytes(), isolate_); 826 Handle<String> wire_bytes(compiled_part->module_bytes(), isolate_);
813 int wire_bytes_length = wire_bytes->length(); 827 int wire_bytes_length = wire_bytes->length();
814 WriteVarint<uint32_t>(wire_bytes_length); 828 WriteVarint<uint32_t>(wire_bytes_length);
815 uint8_t* destination; 829 uint8_t* destination;
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
1047 Handle<SeededNumberDictionary> new_dictionary = 1061 Handle<SeededNumberDictionary> new_dictionary =
1048 SeededNumberDictionary::AtNumberPut(dictionary, transfer_id, array_buffer, 1062 SeededNumberDictionary::AtNumberPut(dictionary, transfer_id, array_buffer,
1049 not_a_prototype_holder); 1063 not_a_prototype_holder);
1050 if (!new_dictionary.is_identical_to(dictionary)) { 1064 if (!new_dictionary.is_identical_to(dictionary)) {
1051 GlobalHandles::Destroy(Handle<Object>::cast(dictionary).location()); 1065 GlobalHandles::Destroy(Handle<Object>::cast(dictionary).location());
1052 array_buffer_transfer_map_ = Handle<SeededNumberDictionary>::cast( 1066 array_buffer_transfer_map_ = Handle<SeededNumberDictionary>::cast(
1053 isolate_->global_handles()->Create(*new_dictionary)); 1067 isolate_->global_handles()->Create(*new_dictionary));
1054 } 1068 }
1055 } 1069 }
1056 1070
1071 void ValueDeserializer::TransferWasmModule(uint32_t transfer_id,
1072 Handle<WasmModuleObject> module) {
1073 // We don't realistically expect too many wasm modules to be posted around.
1074 // See v8:6106 also.
1075 size_t necessary_size = Max(transferred_wasm_modules_.size(),
1076 static_cast<size_t>(transfer_id + 1));
1077 if (transferred_wasm_modules_.size() < necessary_size) {
1078 transferred_wasm_modules_.resize(necessary_size);
1079 }
1080 transferred_wasm_modules_[transfer_id] = module;
1081 }
1082
1057 MaybeHandle<Object> ValueDeserializer::ReadObject() { 1083 MaybeHandle<Object> ValueDeserializer::ReadObject() {
1058 MaybeHandle<Object> result = ReadObjectInternal(); 1084 MaybeHandle<Object> result = ReadObjectInternal();
1059 1085
1060 // ArrayBufferView is special in that it consumes the value before it, even 1086 // ArrayBufferView is special in that it consumes the value before it, even
1061 // after format version 0. 1087 // after format version 0.
1062 Handle<Object> object; 1088 Handle<Object> object;
1063 SerializationTag tag; 1089 SerializationTag tag;
1064 if (result.ToHandle(&object) && V8_UNLIKELY(object->IsJSArrayBuffer()) && 1090 if (result.ToHandle(&object) && V8_UNLIKELY(object->IsJSArrayBuffer()) &&
1065 PeekTag().To(&tag) && tag == SerializationTag::kArrayBufferView) { 1091 PeekTag().To(&tag) && tag == SerializationTag::kArrayBufferView) {
1066 ConsumeTag(SerializationTag::kArrayBufferView); 1092 ConsumeTag(SerializationTag::kArrayBufferView);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
1143 case SerializationTag::kArrayBufferTransfer: { 1169 case SerializationTag::kArrayBufferTransfer: {
1144 const bool is_shared = false; 1170 const bool is_shared = false;
1145 return ReadTransferredJSArrayBuffer(is_shared); 1171 return ReadTransferredJSArrayBuffer(is_shared);
1146 } 1172 }
1147 case SerializationTag::kSharedArrayBuffer: { 1173 case SerializationTag::kSharedArrayBuffer: {
1148 const bool is_shared = true; 1174 const bool is_shared = true;
1149 return ReadTransferredJSArrayBuffer(is_shared); 1175 return ReadTransferredJSArrayBuffer(is_shared);
1150 } 1176 }
1151 case SerializationTag::kWasmModule: 1177 case SerializationTag::kWasmModule:
1152 return ReadWasmModule(); 1178 return ReadWasmModule();
1179 case SerializationTag::kWasmModuleTransfer:
1180 return ReadWasmModuleTransfer();
1153 case SerializationTag::kHostObject: 1181 case SerializationTag::kHostObject:
1154 return ReadHostObject(); 1182 return ReadHostObject();
1155 default: 1183 default:
1156 // Before there was an explicit tag for host objects, all unknown tags 1184 // Before there was an explicit tag for host objects, all unknown tags
1157 // were delegated to the host. 1185 // were delegated to the host.
1158 if (version_ < 13) { 1186 if (version_ < 13) {
1159 position_--; 1187 position_--;
1160 return ReadHostObject(); 1188 return ReadHostObject();
1161 } 1189 }
1162 return MaybeHandle<Object>(); 1190 return MaybeHandle<Object>();
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after
1588 byte_length % element_size != 0) { 1616 byte_length % element_size != 0) {
1589 return MaybeHandle<JSArrayBufferView>(); 1617 return MaybeHandle<JSArrayBufferView>();
1590 } 1618 }
1591 Handle<JSTypedArray> typed_array = isolate_->factory()->NewJSTypedArray( 1619 Handle<JSTypedArray> typed_array = isolate_->factory()->NewJSTypedArray(
1592 external_array_type, buffer, byte_offset, byte_length / element_size, 1620 external_array_type, buffer, byte_offset, byte_length / element_size,
1593 pretenure_); 1621 pretenure_);
1594 AddObjectWithID(id, typed_array); 1622 AddObjectWithID(id, typed_array);
1595 return typed_array; 1623 return typed_array;
1596 } 1624 }
1597 1625
1626 MaybeHandle<JSObject> ValueDeserializer::ReadWasmModuleTransfer() {
1627 if (FLAG_wasm_disable_structured_cloning || allow_inline_wasm()) {
1628 return MaybeHandle<JSObject>();
1629 }
1630
1631 uint32_t index = 0;
1632 if (ReadVarint<uint32_t>().To(&index) &&
1633 index < transferred_wasm_modules_.size()) {
1634 Handle<JSObject> module = transferred_wasm_modules_[index];
1635 uint32_t id = next_id_++;
1636 AddObjectWithID(id, module);
1637 return module;
1638 } else {
1639 return MaybeHandle<JSObject>();
1640 }
1641 }
1642
1598 MaybeHandle<JSObject> ValueDeserializer::ReadWasmModule() { 1643 MaybeHandle<JSObject> ValueDeserializer::ReadWasmModule() {
1599 if (FLAG_wasm_disable_structured_cloning) return MaybeHandle<JSObject>(); 1644 if (FLAG_wasm_disable_structured_cloning || !allow_inline_wasm()) {
1645 return MaybeHandle<JSObject>();
1646 }
1600 1647
1601 Vector<const uint8_t> encoding_tag; 1648 Vector<const uint8_t> encoding_tag;
1602 if (!ReadRawBytes(sizeof(WasmEncodingTag)).To(&encoding_tag) || 1649 if (!ReadRawBytes(sizeof(WasmEncodingTag)).To(&encoding_tag) ||
1603 encoding_tag[0] != static_cast<uint8_t>(WasmEncodingTag::kRawBytes)) { 1650 encoding_tag[0] != static_cast<uint8_t>(WasmEncodingTag::kRawBytes)) {
1604 return MaybeHandle<JSObject>(); 1651 return MaybeHandle<JSObject>();
1605 } 1652 }
1606 1653
1607 // Extract the data from the buffer: wasm wire bytes, followed by V8 compiled 1654 // Extract the data from the buffer: wasm wire bytes, followed by V8 compiled
1608 // script data. 1655 // script data.
1609 static_assert(sizeof(int) <= sizeof(uint32_t), 1656 static_assert(sizeof(int) <= sizeof(uint32_t),
1610 "max int must fit in uint32_t"); 1657 "max int must fit in uint32_t");
1611 const uint32_t max_valid_size = std::numeric_limits<int>::max(); 1658 const uint32_t max_valid_size = std::numeric_limits<int>::max();
1612 uint32_t wire_bytes_length = 0; 1659 uint32_t wire_bytes_length = 0;
1613 Vector<const uint8_t> wire_bytes; 1660 Vector<const uint8_t> wire_bytes;
1614 uint32_t compiled_bytes_length = 0; 1661 uint32_t compiled_bytes_length = 0;
1615 Vector<const uint8_t> compiled_bytes; 1662 Vector<const uint8_t> compiled_bytes;
1616 if (!ReadVarint<uint32_t>().To(&wire_bytes_length) || 1663 if (!ReadVarint<uint32_t>().To(&wire_bytes_length) ||
1617 wire_bytes_length > max_valid_size || 1664 wire_bytes_length > max_valid_size ||
1618 !ReadRawBytes(wire_bytes_length).To(&wire_bytes) || 1665 !ReadRawBytes(wire_bytes_length).To(&wire_bytes) ||
1619 !ReadVarint<uint32_t>().To(&compiled_bytes_length) || 1666 !ReadVarint<uint32_t>().To(&compiled_bytes_length) ||
1620 compiled_bytes_length > max_valid_size || 1667 compiled_bytes_length > max_valid_size ||
1621 !ReadRawBytes(compiled_bytes_length).To(&compiled_bytes)) { 1668 !ReadRawBytes(compiled_bytes_length).To(&compiled_bytes)) {
1622 return MaybeHandle<JSObject>(); 1669 return MaybeHandle<JSObject>();
1623 } 1670 }
1624 1671
1625 // Try to deserialize the compiled module first. 1672 // Try to deserialize the compiled module first.
1626 ScriptData script_data(compiled_bytes.start(), compiled_bytes.length()); 1673 ScriptData script_data(compiled_bytes.start(), compiled_bytes.length());
1627 Handle<FixedArray> compiled_part; 1674 Handle<FixedArray> compiled_part;
1675 MaybeHandle<JSObject> result;
1628 if (WasmCompiledModuleSerializer::DeserializeWasmModule( 1676 if (WasmCompiledModuleSerializer::DeserializeWasmModule(
1629 isolate_, &script_data, wire_bytes) 1677 isolate_, &script_data, wire_bytes)
1630 .ToHandle(&compiled_part)) { 1678 .ToHandle(&compiled_part)) {
1631 return WasmModuleObject::New( 1679 result = WasmModuleObject::New(
1632 isolate_, Handle<WasmCompiledModule>::cast(compiled_part)); 1680 isolate_, Handle<WasmCompiledModule>::cast(compiled_part));
1633 } 1681 } else {
1634
1635 // If that fails, recompile.
1636 MaybeHandle<JSObject> result;
1637 {
1638 wasm::ErrorThrower thrower(isolate_, "ValueDeserializer::ReadWasmModule"); 1682 wasm::ErrorThrower thrower(isolate_, "ValueDeserializer::ReadWasmModule");
1639 result = wasm::SyncCompile(isolate_, &thrower, 1683 result = wasm::SyncCompile(isolate_, &thrower,
1640 wasm::ModuleWireBytes(wire_bytes)); 1684 wasm::ModuleWireBytes(wire_bytes));
1641 } 1685 }
1642 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate_, JSObject); 1686 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate_, JSObject);
1687 uint32_t id = next_id_++;
1688 if (!result.is_null()) {
1689 AddObjectWithID(id, result.ToHandleChecked());
1690 }
1643 return result; 1691 return result;
1644 } 1692 }
1645 1693
1646 MaybeHandle<JSObject> ValueDeserializer::ReadHostObject() { 1694 MaybeHandle<JSObject> ValueDeserializer::ReadHostObject() {
1647 if (!delegate_) return MaybeHandle<JSObject>(); 1695 if (!delegate_) return MaybeHandle<JSObject>();
1648 STACK_CHECK(isolate_, MaybeHandle<JSObject>()); 1696 STACK_CHECK(isolate_, MaybeHandle<JSObject>());
1649 uint32_t id = next_id_++; 1697 uint32_t id = next_id_++;
1650 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_); 1698 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_);
1651 v8::Local<v8::Object> object; 1699 v8::Local<v8::Object> object;
1652 if (!delegate_->ReadHostObject(v8_isolate).ToLocal(&object)) { 1700 if (!delegate_->ReadHostObject(v8_isolate).ToLocal(&object)) {
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
1969 if (stack.size() != 1) { 2017 if (stack.size() != 1) {
1970 isolate_->Throw(*isolate_->factory()->NewError( 2018 isolate_->Throw(*isolate_->factory()->NewError(
1971 MessageTemplate::kDataCloneDeserializationError)); 2019 MessageTemplate::kDataCloneDeserializationError));
1972 return MaybeHandle<Object>(); 2020 return MaybeHandle<Object>();
1973 } 2021 }
1974 return scope.CloseAndEscape(stack[0]); 2022 return scope.CloseAndEscape(stack[0]);
1975 } 2023 }
1976 2024
1977 } // namespace internal 2025 } // namespace internal
1978 } // namespace v8 2026 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698