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

Side by Side Diff: third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp

Issue 2405153003: [wasm] support for recompilation if deserialization fails (Closed)
Patch Set: behavior when breaking changes Created 4 years, 2 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
« no previous file with comments | « third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698