| OLD | NEW |
| 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 Loading... |
| 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', | |
| 131 // The delegate is responsible for processing all following data. | 129 // The delegate is responsible for processing all following data. |
| 132 // This "escapes" to whatever wire format the delegate chooses. | 130 // This "escapes" to whatever wire format the delegate chooses. |
| 133 kHostObject = '\\', | 131 kHostObject = '\\', |
| 134 }; | 132 }; |
| 135 | 133 |
| 136 namespace { | 134 namespace { |
| 137 | 135 |
| 138 enum class ArrayBufferViewTag : uint8_t { | 136 enum class ArrayBufferViewTag : uint8_t { |
| 139 kInt8Array = 'b', | 137 kInt8Array = 'b', |
| 140 kUint8Array = 'B', | 138 kUint8Array = 'B', |
| (...skipping 657 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 798 DCHECK(view->IsJSDataView()); | 796 DCHECK(view->IsJSDataView()); |
| 799 tag = ArrayBufferViewTag::kDataView; | 797 tag = ArrayBufferViewTag::kDataView; |
| 800 } | 798 } |
| 801 WriteVarint(static_cast<uint8_t>(tag)); | 799 WriteVarint(static_cast<uint8_t>(tag)); |
| 802 WriteVarint(NumberToUint32(view->byte_offset())); | 800 WriteVarint(NumberToUint32(view->byte_offset())); |
| 803 WriteVarint(NumberToUint32(view->byte_length())); | 801 WriteVarint(NumberToUint32(view->byte_length())); |
| 804 return ThrowIfOutOfMemory(); | 802 return ThrowIfOutOfMemory(); |
| 805 } | 803 } |
| 806 | 804 |
| 807 Maybe<bool> ValueSerializer::WriteWasmModule(Handle<JSObject> object) { | 805 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 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate_, Nothing<bool>()); | |
| 813 uint32_t id = 0; | |
| 814 if (transfer_id.To(&id)) { | |
| 815 WriteTag(SerializationTag::kWasmModuleTransfer); | |
| 816 WriteVarint<uint32_t>(id); | |
| 817 return Just(true); | |
| 818 } | |
| 819 } | |
| 820 | |
| 821 Handle<WasmCompiledModule> compiled_part( | 806 Handle<WasmCompiledModule> compiled_part( |
| 822 WasmCompiledModule::cast(object->GetEmbedderField(0)), isolate_); | 807 WasmCompiledModule::cast(object->GetEmbedderField(0)), isolate_); |
| 823 WasmEncodingTag encoding_tag = WasmEncodingTag::kRawBytes; | 808 WasmEncodingTag encoding_tag = WasmEncodingTag::kRawBytes; |
| 824 WriteTag(SerializationTag::kWasmModule); | 809 WriteTag(SerializationTag::kWasmModule); |
| 825 WriteRawBytes(&encoding_tag, sizeof(encoding_tag)); | 810 WriteRawBytes(&encoding_tag, sizeof(encoding_tag)); |
| 826 | 811 |
| 827 Handle<String> wire_bytes(compiled_part->module_bytes(), isolate_); | 812 Handle<String> wire_bytes(compiled_part->module_bytes(), isolate_); |
| 828 int wire_bytes_length = wire_bytes->length(); | 813 int wire_bytes_length = wire_bytes->length(); |
| 829 WriteVarint<uint32_t>(wire_bytes_length); | 814 WriteVarint<uint32_t>(wire_bytes_length); |
| 830 uint8_t* destination; | 815 uint8_t* destination; |
| (...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1158 case SerializationTag::kArrayBufferTransfer: { | 1143 case SerializationTag::kArrayBufferTransfer: { |
| 1159 const bool is_shared = false; | 1144 const bool is_shared = false; |
| 1160 return ReadTransferredJSArrayBuffer(is_shared); | 1145 return ReadTransferredJSArrayBuffer(is_shared); |
| 1161 } | 1146 } |
| 1162 case SerializationTag::kSharedArrayBuffer: { | 1147 case SerializationTag::kSharedArrayBuffer: { |
| 1163 const bool is_shared = true; | 1148 const bool is_shared = true; |
| 1164 return ReadTransferredJSArrayBuffer(is_shared); | 1149 return ReadTransferredJSArrayBuffer(is_shared); |
| 1165 } | 1150 } |
| 1166 case SerializationTag::kWasmModule: | 1151 case SerializationTag::kWasmModule: |
| 1167 return ReadWasmModule(); | 1152 return ReadWasmModule(); |
| 1168 case SerializationTag::kWasmModuleTransfer: | |
| 1169 return ReadWasmModuleTransfer(); | |
| 1170 case SerializationTag::kHostObject: | 1153 case SerializationTag::kHostObject: |
| 1171 return ReadHostObject(); | 1154 return ReadHostObject(); |
| 1172 default: | 1155 default: |
| 1173 // Before there was an explicit tag for host objects, all unknown tags | 1156 // Before there was an explicit tag for host objects, all unknown tags |
| 1174 // were delegated to the host. | 1157 // were delegated to the host. |
| 1175 if (version_ < 13) { | 1158 if (version_ < 13) { |
| 1176 position_--; | 1159 position_--; |
| 1177 return ReadHostObject(); | 1160 return ReadHostObject(); |
| 1178 } | 1161 } |
| 1179 return MaybeHandle<Object>(); | 1162 return MaybeHandle<Object>(); |
| (...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1605 byte_length % element_size != 0) { | 1588 byte_length % element_size != 0) { |
| 1606 return MaybeHandle<JSArrayBufferView>(); | 1589 return MaybeHandle<JSArrayBufferView>(); |
| 1607 } | 1590 } |
| 1608 Handle<JSTypedArray> typed_array = isolate_->factory()->NewJSTypedArray( | 1591 Handle<JSTypedArray> typed_array = isolate_->factory()->NewJSTypedArray( |
| 1609 external_array_type, buffer, byte_offset, byte_length / element_size, | 1592 external_array_type, buffer, byte_offset, byte_length / element_size, |
| 1610 pretenure_); | 1593 pretenure_); |
| 1611 AddObjectWithID(id, typed_array); | 1594 AddObjectWithID(id, typed_array); |
| 1612 return typed_array; | 1595 return typed_array; |
| 1613 } | 1596 } |
| 1614 | 1597 |
| 1615 MaybeHandle<JSObject> ValueDeserializer::ReadWasmModuleTransfer() { | |
| 1616 if (FLAG_wasm_disable_structured_cloning || expect_inline_wasm()) { | |
| 1617 return MaybeHandle<JSObject>(); | |
| 1618 } | |
| 1619 | |
| 1620 uint32_t transfer_id = 0; | |
| 1621 Local<Value> module_value; | |
| 1622 if (!ReadVarint<uint32_t>().To(&transfer_id) || delegate_ == nullptr || | |
| 1623 !delegate_ | |
| 1624 ->GetWasmModuleFromId(reinterpret_cast<v8::Isolate*>(isolate_), | |
| 1625 transfer_id) | |
| 1626 .ToLocal(&module_value)) { | |
| 1627 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate_, JSObject); | |
| 1628 return MaybeHandle<JSObject>(); | |
| 1629 } | |
| 1630 uint32_t id = next_id_++; | |
| 1631 Handle<JSObject> module = | |
| 1632 Handle<JSObject>::cast(Utils::OpenHandle(*module_value)); | |
| 1633 AddObjectWithID(id, module); | |
| 1634 return module; | |
| 1635 } | |
| 1636 | |
| 1637 MaybeHandle<JSObject> ValueDeserializer::ReadWasmModule() { | 1598 MaybeHandle<JSObject> ValueDeserializer::ReadWasmModule() { |
| 1638 if (FLAG_wasm_disable_structured_cloning || !expect_inline_wasm()) { | 1599 if (FLAG_wasm_disable_structured_cloning) return MaybeHandle<JSObject>(); |
| 1639 return MaybeHandle<JSObject>(); | |
| 1640 } | |
| 1641 | 1600 |
| 1642 Vector<const uint8_t> encoding_tag; | 1601 Vector<const uint8_t> encoding_tag; |
| 1643 if (!ReadRawBytes(sizeof(WasmEncodingTag)).To(&encoding_tag) || | 1602 if (!ReadRawBytes(sizeof(WasmEncodingTag)).To(&encoding_tag) || |
| 1644 encoding_tag[0] != static_cast<uint8_t>(WasmEncodingTag::kRawBytes)) { | 1603 encoding_tag[0] != static_cast<uint8_t>(WasmEncodingTag::kRawBytes)) { |
| 1645 return MaybeHandle<JSObject>(); | 1604 return MaybeHandle<JSObject>(); |
| 1646 } | 1605 } |
| 1647 | 1606 |
| 1648 // Extract the data from the buffer: wasm wire bytes, followed by V8 compiled | 1607 // Extract the data from the buffer: wasm wire bytes, followed by V8 compiled |
| 1649 // script data. | 1608 // script data. |
| 1650 static_assert(sizeof(int) <= sizeof(uint32_t), | 1609 static_assert(sizeof(int) <= sizeof(uint32_t), |
| 1651 "max int must fit in uint32_t"); | 1610 "max int must fit in uint32_t"); |
| 1652 const uint32_t max_valid_size = std::numeric_limits<int>::max(); | 1611 const uint32_t max_valid_size = std::numeric_limits<int>::max(); |
| 1653 uint32_t wire_bytes_length = 0; | 1612 uint32_t wire_bytes_length = 0; |
| 1654 Vector<const uint8_t> wire_bytes; | 1613 Vector<const uint8_t> wire_bytes; |
| 1655 uint32_t compiled_bytes_length = 0; | 1614 uint32_t compiled_bytes_length = 0; |
| 1656 Vector<const uint8_t> compiled_bytes; | 1615 Vector<const uint8_t> compiled_bytes; |
| 1657 if (!ReadVarint<uint32_t>().To(&wire_bytes_length) || | 1616 if (!ReadVarint<uint32_t>().To(&wire_bytes_length) || |
| 1658 wire_bytes_length > max_valid_size || | 1617 wire_bytes_length > max_valid_size || |
| 1659 !ReadRawBytes(wire_bytes_length).To(&wire_bytes) || | 1618 !ReadRawBytes(wire_bytes_length).To(&wire_bytes) || |
| 1660 !ReadVarint<uint32_t>().To(&compiled_bytes_length) || | 1619 !ReadVarint<uint32_t>().To(&compiled_bytes_length) || |
| 1661 compiled_bytes_length > max_valid_size || | 1620 compiled_bytes_length > max_valid_size || |
| 1662 !ReadRawBytes(compiled_bytes_length).To(&compiled_bytes)) { | 1621 !ReadRawBytes(compiled_bytes_length).To(&compiled_bytes)) { |
| 1663 return MaybeHandle<JSObject>(); | 1622 return MaybeHandle<JSObject>(); |
| 1664 } | 1623 } |
| 1665 | 1624 |
| 1666 // Try to deserialize the compiled module first. | 1625 // Try to deserialize the compiled module first. |
| 1667 ScriptData script_data(compiled_bytes.start(), compiled_bytes.length()); | 1626 ScriptData script_data(compiled_bytes.start(), compiled_bytes.length()); |
| 1668 Handle<FixedArray> compiled_part; | 1627 Handle<FixedArray> compiled_part; |
| 1669 MaybeHandle<JSObject> result; | |
| 1670 if (WasmCompiledModuleSerializer::DeserializeWasmModule( | 1628 if (WasmCompiledModuleSerializer::DeserializeWasmModule( |
| 1671 isolate_, &script_data, wire_bytes) | 1629 isolate_, &script_data, wire_bytes) |
| 1672 .ToHandle(&compiled_part)) { | 1630 .ToHandle(&compiled_part)) { |
| 1673 result = WasmModuleObject::New( | 1631 return WasmModuleObject::New( |
| 1674 isolate_, Handle<WasmCompiledModule>::cast(compiled_part)); | 1632 isolate_, Handle<WasmCompiledModule>::cast(compiled_part)); |
| 1675 } else { | 1633 } |
| 1634 |
| 1635 // If that fails, recompile. |
| 1636 MaybeHandle<JSObject> result; |
| 1637 { |
| 1676 wasm::ErrorThrower thrower(isolate_, "ValueDeserializer::ReadWasmModule"); | 1638 wasm::ErrorThrower thrower(isolate_, "ValueDeserializer::ReadWasmModule"); |
| 1677 result = wasm::SyncCompile(isolate_, &thrower, | 1639 result = wasm::SyncCompile(isolate_, &thrower, |
| 1678 wasm::ModuleWireBytes(wire_bytes)); | 1640 wasm::ModuleWireBytes(wire_bytes)); |
| 1679 } | 1641 } |
| 1680 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate_, JSObject); | 1642 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate_, JSObject); |
| 1681 uint32_t id = next_id_++; | |
| 1682 if (!result.is_null()) { | |
| 1683 AddObjectWithID(id, result.ToHandleChecked()); | |
| 1684 } | |
| 1685 return result; | 1643 return result; |
| 1686 } | 1644 } |
| 1687 | 1645 |
| 1688 MaybeHandle<JSObject> ValueDeserializer::ReadHostObject() { | 1646 MaybeHandle<JSObject> ValueDeserializer::ReadHostObject() { |
| 1689 if (!delegate_) return MaybeHandle<JSObject>(); | 1647 if (!delegate_) return MaybeHandle<JSObject>(); |
| 1690 STACK_CHECK(isolate_, MaybeHandle<JSObject>()); | 1648 STACK_CHECK(isolate_, MaybeHandle<JSObject>()); |
| 1691 uint32_t id = next_id_++; | 1649 uint32_t id = next_id_++; |
| 1692 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_); | 1650 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_); |
| 1693 v8::Local<v8::Object> object; | 1651 v8::Local<v8::Object> object; |
| 1694 if (!delegate_->ReadHostObject(v8_isolate).ToLocal(&object)) { | 1652 if (!delegate_->ReadHostObject(v8_isolate).ToLocal(&object)) { |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2011 if (stack.size() != 1) { | 1969 if (stack.size() != 1) { |
| 2012 isolate_->Throw(*isolate_->factory()->NewError( | 1970 isolate_->Throw(*isolate_->factory()->NewError( |
| 2013 MessageTemplate::kDataCloneDeserializationError)); | 1971 MessageTemplate::kDataCloneDeserializationError)); |
| 2014 return MaybeHandle<Object>(); | 1972 return MaybeHandle<Object>(); |
| 2015 } | 1973 } |
| 2016 return scope.CloseAndEscape(stack[0]); | 1974 return scope.CloseAndEscape(stack[0]); |
| 2017 } | 1975 } |
| 2018 | 1976 |
| 2019 } // namespace internal | 1977 } // namespace internal |
| 2020 } // namespace v8 | 1978 } // namespace v8 |
| OLD | NEW |