Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium 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 "bindings/core/v8/ScriptValueSerializer.h" | 5 #include "bindings/core/v8/ScriptValueSerializer.h" |
| 6 | 6 |
| 7 #include "bindings/core/v8/Transferables.h" | 7 #include "bindings/core/v8/Transferables.h" |
| 8 #include "bindings/core/v8/V8ArrayBuffer.h" | 8 #include "bindings/core/v8/V8ArrayBuffer.h" |
| 9 #include "bindings/core/v8/V8ArrayBufferView.h" | 9 #include "bindings/core/v8/V8ArrayBufferView.h" |
| 10 #include "bindings/core/v8/V8Blob.h" | 10 #include "bindings/core/v8/V8Blob.h" |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 101 } | 101 } |
| 102 | 102 |
| 103 void SerializedScriptValueWriter::writeFalse() { | 103 void SerializedScriptValueWriter::writeFalse() { |
| 104 append(FalseTag); | 104 append(FalseTag); |
| 105 } | 105 } |
| 106 | 106 |
| 107 void SerializedScriptValueWriter::writeBooleanObject(bool value) { | 107 void SerializedScriptValueWriter::writeBooleanObject(bool value) { |
| 108 append(value ? TrueObjectTag : FalseObjectTag); | 108 append(value ? TrueObjectTag : FalseObjectTag); |
| 109 } | 109 } |
| 110 | 110 |
| 111 void SerializedScriptValueWriter::writeRawStringBytes( | |
| 112 v8::Local<v8::String>& string) { | |
| 113 int rawLength = string->Length(); | |
| 114 string->WriteOneByte(byteAt(m_position), 0, rawLength, | |
| 115 v8StringWriteOptions()); | |
| 116 m_position += rawLength; | |
| 117 } | |
| 118 | |
| 119 void SerializedScriptValueWriter::writeUtf8String( | |
| 120 v8::Local<v8::String>& string) { | |
| 121 int utf8Length = string->Utf8Length(); | |
| 122 char* buffer = reinterpret_cast<char*>(byteAt(m_position)); | |
| 123 string->WriteUtf8(buffer, utf8Length, 0, v8StringWriteOptions()); | |
| 124 m_position += utf8Length; | |
| 125 } | |
| 126 | |
| 111 void SerializedScriptValueWriter::writeOneByteString( | 127 void SerializedScriptValueWriter::writeOneByteString( |
| 112 v8::Local<v8::String>& string) { | 128 v8::Local<v8::String>& string) { |
| 113 int stringLength = string->Length(); | 129 int stringLength = string->Length(); |
| 114 int utf8Length = string->Utf8Length(); | 130 int utf8Length = string->Utf8Length(); |
| 115 ASSERT(stringLength >= 0 && utf8Length >= 0); | 131 ASSERT(stringLength >= 0 && utf8Length >= 0); |
| 116 | 132 |
| 117 append(StringTag); | 133 append(StringTag); |
| 118 doWriteUint32(static_cast<uint32_t>(utf8Length)); | 134 doWriteUint32(static_cast<uint32_t>(utf8Length)); |
| 119 ensureSpace(utf8Length); | 135 ensureSpace(utf8Length); |
| 120 | 136 |
| 121 // ASCII fast path. | 137 // ASCII fast path. |
| 122 if (stringLength == utf8Length) { | 138 if (stringLength == utf8Length) { |
| 123 string->WriteOneByte(byteAt(m_position), 0, utf8Length, | 139 writeRawStringBytes(string); |
| 124 v8StringWriteOptions()); | |
| 125 } else { | 140 } else { |
| 126 char* buffer = reinterpret_cast<char*>(byteAt(m_position)); | 141 writeUtf8String(string); |
| 127 string->WriteUtf8(buffer, utf8Length, 0, v8StringWriteOptions()); | |
| 128 } | 142 } |
| 129 m_position += utf8Length; | |
| 130 } | 143 } |
| 131 | 144 |
| 132 void SerializedScriptValueWriter::writeUCharString( | 145 void SerializedScriptValueWriter::writeUCharString( |
| 133 v8::Local<v8::String>& string) { | 146 v8::Local<v8::String>& string) { |
| 134 int length = string->Length(); | 147 int length = string->Length(); |
| 135 ASSERT(length >= 0); | 148 ASSERT(length >= 0); |
| 136 | 149 |
| 137 int size = length * sizeof(UChar); | 150 int size = length * sizeof(UChar); |
| 138 int bytes = bytesNeededToWireEncode(static_cast<uint32_t>(size)); | 151 int bytes = bytesNeededToWireEncode(static_cast<uint32_t>(size)); |
| 139 if ((m_position + 1 + bytes) & 1) | 152 if ((m_position + 1 + bytes) & 1) |
| (...skipping 1109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1249 return nullptr; | 1262 return nullptr; |
| 1250 } | 1263 } |
| 1251 | 1264 |
| 1252 ScriptValueSerializer::StateBase* | 1265 ScriptValueSerializer::StateBase* |
| 1253 ScriptValueSerializer::writeWasmCompiledModule(v8::Local<v8::Object> object, | 1266 ScriptValueSerializer::writeWasmCompiledModule(v8::Local<v8::Object> object, |
| 1254 StateBase* next) { | 1267 StateBase* next) { |
| 1255 CHECK(RuntimeEnabledFeatures::webAssemblySerializationEnabled()); | 1268 CHECK(RuntimeEnabledFeatures::webAssemblySerializationEnabled()); |
| 1256 // TODO (mtrofin): explore mechanism avoiding data copying / buffer resizing. | 1269 // TODO (mtrofin): explore mechanism avoiding data copying / buffer resizing. |
| 1257 v8::Local<v8::WasmCompiledModule> wasmModule = | 1270 v8::Local<v8::WasmCompiledModule> wasmModule = |
| 1258 object.As<v8::WasmCompiledModule>(); | 1271 object.As<v8::WasmCompiledModule>(); |
| 1272 v8::Local<v8::String> uncompiledBytes = wasmModule->GetUncompiledBytes(); | |
|
titzer
2016/10/12 15:09:53
UncompiledBytes isn't a very good name. These are
Mircea Trofin
2016/10/12 16:01:07
I wanted to draw the compiled vs uncompiled distin
titzer
2016/10/12 16:15:30
"Uncompiled" doesn't suggest to me that this is en
Mircea Trofin
2016/10/14 06:20:18
Done.
| |
| 1273 DCHECK(uncompiledBytes->IsOneByte()); | |
| 1274 | |
| 1259 v8::WasmCompiledModule::SerializedModule data = wasmModule->Serialize(); | 1275 v8::WasmCompiledModule::SerializedModule data = wasmModule->Serialize(); |
| 1260 m_writer.append(WasmModuleTag); | 1276 m_writer.append(WasmModuleTag); |
| 1277 uint32_t uncompiledBytesLength = | |
| 1278 static_cast<uint32_t>(uncompiledBytes->Length()); | |
| 1279 // We place a tag so we may evolve the format in which we store the | |
| 1280 // uncompiled bytes. We plan to move them to a blob. | |
| 1281 // We want to control how we write the string, though, so we explicitly | |
| 1282 // call writeRawStringBytes. | |
| 1283 m_writer.append(StringTag); | |
|
jbroman
2016/10/12 15:05:38
At the moment, StringTag generally means a UTF-8 s
Mircea Trofin
2016/10/12 16:01:07
OK, and we're OK with later using the blob tag if
Mircea Trofin
2016/10/14 06:20:18
Done.
| |
| 1284 m_writer.doWriteUint32(uncompiledBytesLength); | |
| 1285 m_writer.ensureSpace(uncompiledBytesLength); | |
| 1286 m_writer.writeRawStringBytes(uncompiledBytes); | |
| 1261 m_writer.doWriteUint32(static_cast<uint32_t>(data.second)); | 1287 m_writer.doWriteUint32(static_cast<uint32_t>(data.second)); |
| 1262 m_writer.append(data.first.get(), static_cast<int>(data.second)); | 1288 m_writer.append(data.first.get(), static_cast<int>(data.second)); |
| 1263 return nullptr; | 1289 return nullptr; |
| 1264 } | 1290 } |
| 1265 | 1291 |
| 1266 ScriptValueSerializer::StateBase* | 1292 ScriptValueSerializer::StateBase* |
| 1267 ScriptValueSerializer::writeAndGreyArrayBuffer(v8::Local<v8::Object> object, | 1293 ScriptValueSerializer::writeAndGreyArrayBuffer(v8::Local<v8::Object> object, |
| 1268 StateBase* next) { | 1294 StateBase* next) { |
| 1269 DOMArrayBuffer* arrayBuffer = V8ArrayBuffer::toImpl(object); | 1295 DOMArrayBuffer* arrayBuffer = V8ArrayBuffer::toImpl(object); |
| 1270 if (!arrayBuffer) | 1296 if (!arrayBuffer) |
| (...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1946 if (m_position + byteLength > m_length) | 1972 if (m_position + byteLength > m_length) |
| 1947 return nullptr; | 1973 return nullptr; |
| 1948 const void* bufferStart = m_buffer + m_position; | 1974 const void* bufferStart = m_buffer + m_position; |
| 1949 m_position += byteLength; | 1975 m_position += byteLength; |
| 1950 return DOMArrayBuffer::create(bufferStart, byteLength); | 1976 return DOMArrayBuffer::create(bufferStart, byteLength); |
| 1951 } | 1977 } |
| 1952 | 1978 |
| 1953 bool SerializedScriptValueReader::readWasmCompiledModule( | 1979 bool SerializedScriptValueReader::readWasmCompiledModule( |
| 1954 v8::Local<v8::Value>* value) { | 1980 v8::Local<v8::Value>* value) { |
| 1955 CHECK(RuntimeEnabledFeatures::webAssemblySerializationEnabled()); | 1981 CHECK(RuntimeEnabledFeatures::webAssemblySerializationEnabled()); |
| 1956 uint32_t size = 0; | 1982 // First, read the tag of the uncompiled bytes. |
| 1957 if (!doReadUint32(&size)) | 1983 SerializationTag uncompiledBytesFormat = InvalidTag; |
| 1984 if (!readTag(&uncompiledBytesFormat)) | |
| 1958 return false; | 1985 return false; |
| 1959 if (m_position + size > m_length) | 1986 DCHECK(uncompiledBytesFormat == StringTag); |
| 1987 // Just like when writing, we don't rely on the default string serialization | |
| 1988 // mechanics for the uncompiled bytes. We don't even want a string, because | |
| 1989 // that would lead to a memory copying API implementation on the V8 side. | |
| 1990 uint32_t uncompiledBytesSize = 0; | |
| 1991 uint32_t compiledBytesSize = 0; | |
| 1992 if (!doReadUint32(&uncompiledBytesSize)) | |
| 1960 return false; | 1993 return false; |
| 1961 const uint8_t* buf = m_buffer + m_position; | 1994 if (m_position + uncompiledBytesSize > m_length) |
| 1995 return false; | |
| 1996 const uint8_t* uncompiledBytesStart = m_buffer + m_position; | |
| 1997 m_position += uncompiledBytesSize; | |
| 1998 | |
| 1999 if (!doReadUint32(&compiledBytesSize)) | |
| 2000 return false; | |
| 2001 if (m_position + compiledBytesSize > m_length) | |
| 2002 return false; | |
| 2003 const uint8_t* compiledBytesStart = m_buffer + m_position; | |
| 2004 m_position += compiledBytesSize; | |
| 2005 | |
| 2006 v8::WasmCompiledModule::UncompiledBytes uncompiledBytes = { | |
| 2007 std::unique_ptr<const uint8_t[]>(uncompiledBytesStart), | |
|
jbroman
2016/10/12 15:05:38
Not new to this CL, but please don't put unowned d
Mircea Trofin
2016/10/12 16:01:07
I saw the todo here, I'll update on the v8 side an
Mircea Trofin
2016/10/14 06:20:17
Done.
| |
| 2008 static_cast<size_t>(uncompiledBytesSize)}; | |
| 2009 | |
| 1962 // TODO(mtrofin): simplify deserializer API. const uint8_t* + size_t should | 2010 // TODO(mtrofin): simplify deserializer API. const uint8_t* + size_t should |
| 1963 // be sufficient. | 2011 // be sufficient. |
| 1964 v8::WasmCompiledModule::SerializedModule data = { | 2012 v8::WasmCompiledModule::SerializedModule compiledBytes = { |
| 1965 std::unique_ptr<const uint8_t[]>(buf), static_cast<size_t>(size)}; | 2013 std::unique_ptr<const uint8_t[]>(compiledBytesStart), |
| 2014 static_cast<size_t>(compiledBytesSize)}; | |
| 2015 | |
| 1966 v8::MaybeLocal<v8::WasmCompiledModule> retval = | 2016 v8::MaybeLocal<v8::WasmCompiledModule> retval = |
| 1967 v8::WasmCompiledModule::Deserialize(isolate(), data); | 2017 v8::WasmCompiledModule::DeserializeOrCompile(isolate(), compiledBytes, |
| 1968 data.first.release(); | 2018 uncompiledBytes); |
| 1969 m_position += size; | |
| 1970 | 2019 |
| 1971 // TODO(mtrofin): right now, we'll return undefined if the deserialization | 2020 compiledBytes.first.release(); |
| 1972 // fails, which is what may happen when v8's version changes. Update when | 2021 uncompiledBytes.first.release(); |
| 1973 // spec settles. crbug.com/639090 | 2022 |
| 2023 // Even if deserialization fails, due to chrome upgrade, for instance, | |
| 2024 // recompilation must succeed. | |
| 2025 // Technically, there is a way to fail in that case, too: downgrade | |
| 2026 // chrome after persisting a wasm module using new features. The wasm | |
| 2027 // evolution story guarantees backwards-compatibility (Vx works in Vx+1), | |
| 2028 // no guarantees are made for Vx+1 in a pre- x+1 environment. Applications | |
| 2029 // are expected to feature-detect on the browser side and request from | |
| 2030 // server the appropriate wasm binary version, or to patch the binary | |
| 2031 // on the browser side. | |
| 2032 // We fail because this is explicitly unsupported. | |
| 2033 CHECK(!retval.IsEmpty()); | |
|
jochen (gone - plz use gerrit)
2016/10/12 09:34:59
I don't think we should crash here. Downgrading is
Mircea Trofin
2016/10/12 16:01:07
Is it an exception, or is it just returning "false
Mircea Trofin
2016/10/14 06:20:17
Done.
| |
| 1974 return retval.ToLocal(value); | 2034 return retval.ToLocal(value); |
| 1975 } | 2035 } |
| 1976 | 2036 |
| 1977 bool SerializedScriptValueReader::readArrayBuffer(v8::Local<v8::Value>* value) { | 2037 bool SerializedScriptValueReader::readArrayBuffer(v8::Local<v8::Value>* value) { |
| 1978 DOMArrayBuffer* arrayBuffer = doReadArrayBuffer(); | 2038 DOMArrayBuffer* arrayBuffer = doReadArrayBuffer(); |
| 1979 if (!arrayBuffer) | 2039 if (!arrayBuffer) |
| 1980 return false; | 2040 return false; |
| 1981 *value = toV8(arrayBuffer, m_scriptState->context()->Global(), isolate()); | 2041 *value = toV8(arrayBuffer, m_scriptState->context()->Global(), isolate()); |
| 1982 return !value->IsEmpty(); | 2042 return !value->IsEmpty(); |
| 1983 } | 2043 } |
| (...skipping 651 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2635 m_openCompositeReferenceStack[m_openCompositeReferenceStack.size() - 1]; | 2695 m_openCompositeReferenceStack[m_openCompositeReferenceStack.size() - 1]; |
| 2636 m_openCompositeReferenceStack.shrink(m_openCompositeReferenceStack.size() - | 2696 m_openCompositeReferenceStack.shrink(m_openCompositeReferenceStack.size() - |
| 2637 1); | 2697 1); |
| 2638 if (objectReference >= m_objectPool.size()) | 2698 if (objectReference >= m_objectPool.size()) |
| 2639 return false; | 2699 return false; |
| 2640 *object = m_objectPool[objectReference]; | 2700 *object = m_objectPool[objectReference]; |
| 2641 return true; | 2701 return true; |
| 2642 } | 2702 } |
| 2643 | 2703 |
| 2644 } // namespace blink | 2704 } // namespace blink |
| OLD | NEW |