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

Unified 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp
index 16e3ae1e50969e8fb8c9109ed4bb4c8a7a5686d3..8de6ed568f05fa2a9a36cdd0f9bd8710f4d587b1 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp
@@ -108,6 +108,22 @@ void SerializedScriptValueWriter::writeBooleanObject(bool value) {
append(value ? TrueObjectTag : FalseObjectTag);
}
+void SerializedScriptValueWriter::writeRawStringBytes(
+ v8::Local<v8::String>& string) {
+ int rawLength = string->Length();
+ string->WriteOneByte(byteAt(m_position), 0, rawLength,
+ v8StringWriteOptions());
+ m_position += rawLength;
+}
+
+void SerializedScriptValueWriter::writeUtf8String(
+ v8::Local<v8::String>& string) {
+ int utf8Length = string->Utf8Length();
+ char* buffer = reinterpret_cast<char*>(byteAt(m_position));
+ string->WriteUtf8(buffer, utf8Length, 0, v8StringWriteOptions());
+ m_position += utf8Length;
+}
+
void SerializedScriptValueWriter::writeOneByteString(
v8::Local<v8::String>& string) {
int stringLength = string->Length();
@@ -120,13 +136,10 @@ void SerializedScriptValueWriter::writeOneByteString(
// ASCII fast path.
if (stringLength == utf8Length) {
- string->WriteOneByte(byteAt(m_position), 0, utf8Length,
- v8StringWriteOptions());
+ writeRawStringBytes(string);
} else {
- char* buffer = reinterpret_cast<char*>(byteAt(m_position));
- string->WriteUtf8(buffer, utf8Length, 0, v8StringWriteOptions());
+ writeUtf8String(string);
}
- m_position += utf8Length;
}
void SerializedScriptValueWriter::writeUCharString(
@@ -1256,8 +1269,21 @@ ScriptValueSerializer::writeWasmCompiledModule(v8::Local<v8::Object> object,
// TODO (mtrofin): explore mechanism avoiding data copying / buffer resizing.
v8::Local<v8::WasmCompiledModule> wasmModule =
object.As<v8::WasmCompiledModule>();
+ 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.
+ DCHECK(uncompiledBytes->IsOneByte());
+
v8::WasmCompiledModule::SerializedModule data = wasmModule->Serialize();
m_writer.append(WasmModuleTag);
+ uint32_t uncompiledBytesLength =
+ static_cast<uint32_t>(uncompiledBytes->Length());
+ // We place a tag so we may evolve the format in which we store the
+ // uncompiled bytes. We plan to move them to a blob.
+ // We want to control how we write the string, though, so we explicitly
+ // call writeRawStringBytes.
+ 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.
+ m_writer.doWriteUint32(uncompiledBytesLength);
+ m_writer.ensureSpace(uncompiledBytesLength);
+ m_writer.writeRawStringBytes(uncompiledBytes);
m_writer.doWriteUint32(static_cast<uint32_t>(data.second));
m_writer.append(data.first.get(), static_cast<int>(data.second));
return nullptr;
@@ -1953,24 +1979,58 @@ DOMArrayBuffer* SerializedScriptValueReader::doReadArrayBuffer() {
bool SerializedScriptValueReader::readWasmCompiledModule(
v8::Local<v8::Value>* value) {
CHECK(RuntimeEnabledFeatures::webAssemblySerializationEnabled());
- uint32_t size = 0;
- if (!doReadUint32(&size))
+ // First, read the tag of the uncompiled bytes.
+ SerializationTag uncompiledBytesFormat = InvalidTag;
+ if (!readTag(&uncompiledBytesFormat))
return false;
- if (m_position + size > m_length)
+ DCHECK(uncompiledBytesFormat == StringTag);
+ // Just like when writing, we don't rely on the default string serialization
+ // mechanics for the uncompiled bytes. We don't even want a string, because
+ // that would lead to a memory copying API implementation on the V8 side.
+ uint32_t uncompiledBytesSize = 0;
+ uint32_t compiledBytesSize = 0;
+ if (!doReadUint32(&uncompiledBytesSize))
return false;
- const uint8_t* buf = m_buffer + m_position;
+ if (m_position + uncompiledBytesSize > m_length)
+ return false;
+ const uint8_t* uncompiledBytesStart = m_buffer + m_position;
+ m_position += uncompiledBytesSize;
+
+ if (!doReadUint32(&compiledBytesSize))
+ return false;
+ if (m_position + compiledBytesSize > m_length)
+ return false;
+ const uint8_t* compiledBytesStart = m_buffer + m_position;
+ m_position += compiledBytesSize;
+
+ v8::WasmCompiledModule::UncompiledBytes uncompiledBytes = {
+ 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.
+ static_cast<size_t>(uncompiledBytesSize)};
+
// TODO(mtrofin): simplify deserializer API. const uint8_t* + size_t should
// be sufficient.
- v8::WasmCompiledModule::SerializedModule data = {
- std::unique_ptr<const uint8_t[]>(buf), static_cast<size_t>(size)};
- v8::MaybeLocal<v8::WasmCompiledModule> retval =
- v8::WasmCompiledModule::Deserialize(isolate(), data);
- data.first.release();
- m_position += size;
+ v8::WasmCompiledModule::SerializedModule compiledBytes = {
+ std::unique_ptr<const uint8_t[]>(compiledBytesStart),
+ static_cast<size_t>(compiledBytesSize)};
- // TODO(mtrofin): right now, we'll return undefined if the deserialization
- // fails, which is what may happen when v8's version changes. Update when
- // spec settles. crbug.com/639090
+ v8::MaybeLocal<v8::WasmCompiledModule> retval =
+ v8::WasmCompiledModule::DeserializeOrCompile(isolate(), compiledBytes,
+ uncompiledBytes);
+
+ compiledBytes.first.release();
+ uncompiledBytes.first.release();
+
+ // Even if deserialization fails, due to chrome upgrade, for instance,
+ // recompilation must succeed.
+ // Technically, there is a way to fail in that case, too: downgrade
+ // chrome after persisting a wasm module using new features. The wasm
+ // evolution story guarantees backwards-compatibility (Vx works in Vx+1),
+ // no guarantees are made for Vx+1 in a pre- x+1 environment. Applications
+ // are expected to feature-detect on the browser side and request from
+ // server the appropriate wasm binary version, or to patch the binary
+ // on the browser side.
+ // We fail because this is explicitly unsupported.
+ 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.
return retval.ToLocal(value);
}
« 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