Commit d836b693 authored by Camillo Bruni's avatar Camillo Bruni Committed by V8 LUCI CQ

[web snapshot] Make ValueSerializer an inline member

We can avoid a pointer deref if the ValueSerializer is inlined in
WebSnapshotDeserializer.

Bug: v8:11525
Change-Id: I92d8cac37af3fdbe04a66465f97761bf5a9fd705
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3417433Reviewed-by: 's avatarMarja Hölttä <marja@chromium.org>
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78830}
parent 874b21f8
...@@ -2087,8 +2087,10 @@ MaybeLocal<Value> Script::Run(Local<Context> context, ...@@ -2087,8 +2087,10 @@ MaybeLocal<Value> Script::Run(Local<Context> context,
handle(fun->shared().script(), isolate); handle(fun->shared().script(), isolate);
if (maybe_script->IsScript() && if (maybe_script->IsScript() &&
i::Script::cast(*maybe_script).type() == i::Script::TYPE_WEB_SNAPSHOT) { i::Script::cast(*maybe_script).type() == i::Script::TYPE_WEB_SNAPSHOT) {
i::WebSnapshotDeserializer deserializer(v8_isolate); i::WebSnapshotDeserializer deserializer(
deserializer.UseWebSnapshot(i::Handle<i::Script>::cast(maybe_script)); reinterpret_cast<i::Isolate*>(v8_isolate),
i::Handle<i::Script>::cast(maybe_script));
deserializer.Deserialize();
RETURN_ON_FAILED_EXECUTION(Value); RETURN_ON_FAILED_EXECUTION(Value);
Local<Value> result = v8::Undefined(v8_isolate); Local<Value> result = v8::Undefined(v8_isolate);
RETURN_ESCAPED(result); RETURN_ESCAPED(result);
......
...@@ -1443,9 +1443,9 @@ bool Shell::ExecuteWebSnapshot(Isolate* isolate, const char* file_name) { ...@@ -1443,9 +1443,9 @@ bool Shell::ExecuteWebSnapshot(Isolate* isolate, const char* file_name) {
if (length == 0) { if (length == 0) {
isolate->ThrowError("Could not read the web snapshot file"); isolate->ThrowError("Could not read the web snapshot file");
} else { } else {
i::WebSnapshotDeserializer deserializer(isolate); i::WebSnapshotDeserializer deserializer(isolate, snapshot_data.get(),
success = deserializer.UseWebSnapshot(snapshot_data.get(),
static_cast<size_t>(length)); static_cast<size_t>(length));
success = deserializer.Deserialize();
} }
if (!success) { if (!success) {
CHECK(try_catch.HasCaught()); CHECK(try_catch.HasCaught());
...@@ -2003,9 +2003,10 @@ void Shell::RealmUseWebSnapshot( ...@@ -2003,9 +2003,10 @@ void Shell::RealmUseWebSnapshot(
// Deserialize the snapshot in the specified Realm. // Deserialize the snapshot in the specified Realm.
{ {
PerIsolateData::ExplicitRealmScope realm_scope(data, index); PerIsolateData::ExplicitRealmScope realm_scope(data, index);
i::WebSnapshotDeserializer deserializer(isolate); i::WebSnapshotDeserializer deserializer(isolate,
bool success = deserializer.UseWebSnapshot( snapshot_data_shared->buffer,
snapshot_data_shared->buffer, snapshot_data_shared->buffer_size); snapshot_data_shared->buffer_size);
bool success = deserializer.Deserialize();
args.GetReturnValue().Set(success); args.GetReturnValue().Set(success);
} }
} }
......
...@@ -1028,63 +1028,51 @@ uint32_t WebSnapshotSerializer::GetObjectId(JSObject object) { ...@@ -1028,63 +1028,51 @@ uint32_t WebSnapshotSerializer::GetObjectId(JSObject object) {
return static_cast<uint32_t>(id); return static_cast<uint32_t>(id);
} }
WebSnapshotDeserializer::WebSnapshotDeserializer(v8::Isolate* isolate) WebSnapshotDeserializer::WebSnapshotDeserializer(v8::Isolate* isolate,
: WebSnapshotSerializerDeserializer( const uint8_t* data,
reinterpret_cast<v8::internal::Isolate*>(isolate)) {} size_t buffer_size)
: WebSnapshotDeserializer(reinterpret_cast<i::Isolate*>(isolate),
WebSnapshotDeserializer::~WebSnapshotDeserializer() {} Handle<Object>(), {data, buffer_size}) {}
void WebSnapshotDeserializer::Throw(const char* message) { WebSnapshotDeserializer::WebSnapshotDeserializer(
string_count_ = 0; Isolate* isolate, Handle<Script> snapshot_as_script)
map_count_ = 0; : WebSnapshotDeserializer(
context_count_ = 0; isolate, handle(snapshot_as_script->name(), isolate),
class_count_ = 0; ExtractScriptBuffer(isolate, snapshot_as_script)) {}
function_count_ = 0;
object_count_ = 0; WebSnapshotDeserializer::WebSnapshotDeserializer(
deferred_references_->SetLength(0); Isolate* isolate, Handle<Object> script_name,
base::Vector<const uint8_t> buffer)
// Make sure we don't read any more data : WebSnapshotSerializerDeserializer(isolate),
deserializer_->position_ = deserializer_->end_; script_name_(script_name),
deserializer_(isolate_, buffer.data(), buffer.length()) {}
WebSnapshotSerializerDeserializer::Throw(message);
} // static
base::Vector<const uint8_t> WebSnapshotDeserializer::ExtractScriptBuffer(
bool WebSnapshotDeserializer::UseWebSnapshot(const uint8_t* data, Isolate* isolate, Handle<Script> snapshot_as_script) {
size_t buffer_size) {
deserializer_.reset(new ValueDeserializer(isolate_, data, buffer_size));
return Deserialize();
}
bool WebSnapshotDeserializer::UseWebSnapshot(
Handle<Script> snapshot_as_script) {
Handle<String> source = Handle<String> source =
handle(String::cast(snapshot_as_script->source()), isolate_); handle(String::cast(snapshot_as_script->source()), isolate);
script_name_ = handle(snapshot_as_script->name(), isolate_);
if (source->IsExternalOneByteString()) { if (source->IsExternalOneByteString()) {
const v8::String::ExternalOneByteStringResource* resource = const v8::String::ExternalOneByteStringResource* resource =
ExternalOneByteString::cast(*source).resource(); ExternalOneByteString::cast(*source).resource();
deserializer_.reset(new ValueDeserializer( return {reinterpret_cast<const uint8_t*>(resource->data()),
isolate_, reinterpret_cast<const uint8_t*>(resource->data()), resource->length()};
resource->length()));
return Deserialize();
} else if (source->IsSeqOneByteString()) { } else if (source->IsSeqOneByteString()) {
SeqOneByteString source_as_seq = SeqOneByteString::cast(*source); SeqOneByteString source_as_seq = SeqOneByteString::cast(*source);
auto length = source_as_seq.length(); size_t length = source_as_seq.length();
std::unique_ptr<uint8_t[]> data_copy(new uint8_t[length]); std::unique_ptr<uint8_t[]> data_copy(new uint8_t[length]);
{ {
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
uint8_t* data = source_as_seq.GetChars(no_gc); uint8_t* data = source_as_seq.GetChars(no_gc);
memcpy(data_copy.get(), data, length); memcpy(data_copy.get(), data, length);
} }
deserializer_.reset( return {data_copy.get(), length};
new ValueDeserializer(isolate_, data_copy.get(), length));
return Deserialize();
} else if (source->IsExternalTwoByteString()) { } else if (source->IsExternalTwoByteString()) {
// TODO(v8:11525): Implement end-to-end snapshot processing which gets rid // TODO(v8:11525): Implement end-to-end snapshot processing which gets rid
// of the need to copy the data here. // of the need to copy the data here.
const v8::String::ExternalStringResource* resource = const v8::String::ExternalStringResource* resource =
ExternalTwoByteString::cast(*source).resource(); ExternalTwoByteString::cast(*source).resource();
auto length = resource->length(); size_t length = resource->length();
std::unique_ptr<uint8_t[]> data_copy(new uint8_t[length]); std::unique_ptr<uint8_t[]> data_copy(new uint8_t[length]);
{ {
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
...@@ -1094,27 +1082,39 @@ bool WebSnapshotDeserializer::UseWebSnapshot( ...@@ -1094,27 +1082,39 @@ bool WebSnapshotDeserializer::UseWebSnapshot(
data_copy_ptr[i] = static_cast<uint8_t>(data[i]); data_copy_ptr[i] = static_cast<uint8_t>(data[i]);
} }
} }
deserializer_.reset( return {data_copy.get(), length};
new ValueDeserializer(isolate_, data_copy.get(), length));
return Deserialize();
} else if (source->IsSeqTwoByteString()) { } else if (source->IsSeqTwoByteString()) {
SeqTwoByteString source_as_seq = SeqTwoByteString::cast(*source); SeqTwoByteString source_as_seq = SeqTwoByteString::cast(*source);
auto length = source_as_seq.length(); size_t length = source_as_seq.length();
std::unique_ptr<uint8_t[]> data_copy(new uint8_t[length]); std::unique_ptr<uint8_t[]> data_copy(new uint8_t[length]);
{ {
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
uint16_t* data = source_as_seq.GetChars(no_gc); uint16_t* data = source_as_seq.GetChars(no_gc);
uint8_t* data_copy_ptr = data_copy.get(); uint8_t* data_copy_ptr = data_copy.get();
for (int i = 0; i < length; ++i) { for (size_t i = 0; i < length; ++i) {
data_copy_ptr[i] = static_cast<uint8_t>(data[i]); data_copy_ptr[i] = static_cast<uint8_t>(data[i]);
} }
} }
deserializer_.reset( return {data_copy.get(), length};
new ValueDeserializer(isolate_, data_copy.get(), length));
return Deserialize();
} }
UNREACHABLE(); UNREACHABLE();
} }
WebSnapshotDeserializer::~WebSnapshotDeserializer() {}
void WebSnapshotDeserializer::Throw(const char* message) {
string_count_ = 0;
map_count_ = 0;
context_count_ = 0;
class_count_ = 0;
function_count_ = 0;
object_count_ = 0;
deferred_references_->SetLength(0);
// Make sure we don't read any more data
deserializer_.position_ = deserializer_.end_;
WebSnapshotSerializerDeserializer::Throw(message);
}
bool WebSnapshotDeserializer::Deserialize() { bool WebSnapshotDeserializer::Deserialize() {
RCS_SCOPE(isolate_, RuntimeCallCounterId::kWebSnapshotDeserialize); RCS_SCOPE(isolate_, RuntimeCallCounterId::kWebSnapshotDeserialize);
...@@ -1123,7 +1123,7 @@ bool WebSnapshotDeserializer::Deserialize() { ...@@ -1123,7 +1123,7 @@ bool WebSnapshotDeserializer::Deserialize() {
return false; return false;
} }
deserialized_ = true; deserialized_ = true;
auto buffer_size = deserializer_->end_ - deserializer_->position_; auto buffer_size = deserializer_.end_ - deserializer_.position_;
base::ElapsedTimer timer; base::ElapsedTimer timer;
if (FLAG_trace_web_snapshot) { if (FLAG_trace_web_snapshot) {
...@@ -1148,7 +1148,7 @@ bool WebSnapshotDeserializer::DeserializeSnapshot() { ...@@ -1148,7 +1148,7 @@ bool WebSnapshotDeserializer::DeserializeSnapshot() {
deferred_references_ = ArrayList::New(isolate_, 30); deferred_references_ = ArrayList::New(isolate_, 30);
const void* magic_bytes; const void* magic_bytes;
if (!deserializer_->ReadRawBytes(sizeof(kMagicNumber), &magic_bytes) || if (!deserializer_.ReadRawBytes(sizeof(kMagicNumber), &magic_bytes) ||
memcmp(magic_bytes, kMagicNumber, sizeof(kMagicNumber)) != 0) { memcmp(magic_bytes, kMagicNumber, sizeof(kMagicNumber)) != 0) {
Throw("Invalid magic number"); Throw("Invalid magic number");
return false; return false;
...@@ -1170,13 +1170,13 @@ bool WebSnapshotDeserializer::DeserializeSnapshot() { ...@@ -1170,13 +1170,13 @@ bool WebSnapshotDeserializer::DeserializeSnapshot() {
bool WebSnapshotDeserializer::DeserializeScript() { bool WebSnapshotDeserializer::DeserializeScript() {
// If there is more data, treat it as normal JavaScript. // If there is more data, treat it as normal JavaScript.
DCHECK_LE(deserializer_->position_, deserializer_->end_); DCHECK_LE(deserializer_.position_, deserializer_.end_);
auto remaining_bytes = deserializer_->end_ - deserializer_->position_; auto remaining_bytes = deserializer_.end_ - deserializer_.position_;
if (remaining_bytes > 0 && remaining_bytes < v8::String::kMaxLength) { if (remaining_bytes > 0 && remaining_bytes < v8::String::kMaxLength) {
v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_); v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_);
v8::Local<v8::String> source = v8::Local<v8::String> source =
v8::String::NewFromUtf8( v8::String::NewFromUtf8(
v8_isolate, reinterpret_cast<const char*>(deserializer_->position_), v8_isolate, reinterpret_cast<const char*>(deserializer_.position_),
NewStringType::kNormal, static_cast<int>(remaining_bytes)) NewStringType::kNormal, static_cast<int>(remaining_bytes))
.ToLocalChecked(); .ToLocalChecked();
...@@ -1206,7 +1206,7 @@ bool WebSnapshotDeserializer::DeserializeScript() { ...@@ -1206,7 +1206,7 @@ bool WebSnapshotDeserializer::DeserializeScript() {
void WebSnapshotDeserializer::DeserializeStrings() { void WebSnapshotDeserializer::DeserializeStrings() {
RCS_SCOPE(isolate_, RuntimeCallCounterId::kWebSnapshotDeserialize_Strings); RCS_SCOPE(isolate_, RuntimeCallCounterId::kWebSnapshotDeserialize_Strings);
if (!deserializer_->ReadUint32(&string_count_) || if (!deserializer_.ReadUint32(&string_count_) ||
string_count_ > kMaxItemCount) { string_count_ > kMaxItemCount) {
Throw("Malformed string table"); Throw("Malformed string table");
return; return;
...@@ -1214,7 +1214,7 @@ void WebSnapshotDeserializer::DeserializeStrings() { ...@@ -1214,7 +1214,7 @@ void WebSnapshotDeserializer::DeserializeStrings() {
STATIC_ASSERT(kMaxItemCount <= FixedArray::kMaxLength); STATIC_ASSERT(kMaxItemCount <= FixedArray::kMaxLength);
strings_ = isolate_->factory()->NewFixedArray(string_count_); strings_ = isolate_->factory()->NewFixedArray(string_count_);
for (uint32_t i = 0; i < string_count_; ++i) { for (uint32_t i = 0; i < string_count_; ++i) {
MaybeHandle<String> maybe_string = deserializer_->ReadUtf8String(); MaybeHandle<String> maybe_string = deserializer_.ReadUtf8String();
Handle<String> string; Handle<String> string;
if (!maybe_string.ToHandle(&string)) { if (!maybe_string.ToHandle(&string)) {
Throw("Malformed string"); Throw("Malformed string");
...@@ -1227,7 +1227,7 @@ void WebSnapshotDeserializer::DeserializeStrings() { ...@@ -1227,7 +1227,7 @@ void WebSnapshotDeserializer::DeserializeStrings() {
Handle<String> WebSnapshotDeserializer::ReadString(bool internalize) { Handle<String> WebSnapshotDeserializer::ReadString(bool internalize) {
DCHECK(!strings_->is_null()); DCHECK(!strings_->is_null());
uint32_t string_id; uint32_t string_id;
if (!deserializer_->ReadUint32(&string_id) || string_id >= string_count_) { if (!deserializer_.ReadUint32(&string_id) || string_id >= string_count_) {
Throw("malformed string id\n"); Throw("malformed string id\n");
return isolate_->factory()->empty_string(); return isolate_->factory()->empty_string();
} }
...@@ -1242,7 +1242,7 @@ Handle<String> WebSnapshotDeserializer::ReadString(bool internalize) { ...@@ -1242,7 +1242,7 @@ Handle<String> WebSnapshotDeserializer::ReadString(bool internalize) {
void WebSnapshotDeserializer::DeserializeMaps() { void WebSnapshotDeserializer::DeserializeMaps() {
RCS_SCOPE(isolate_, RuntimeCallCounterId::kWebSnapshotDeserialize_Maps); RCS_SCOPE(isolate_, RuntimeCallCounterId::kWebSnapshotDeserialize_Maps);
if (!deserializer_->ReadUint32(&map_count_) || map_count_ > kMaxItemCount) { if (!deserializer_.ReadUint32(&map_count_) || map_count_ > kMaxItemCount) {
Throw("Malformed shape table"); Throw("Malformed shape table");
return; return;
} }
...@@ -1250,7 +1250,7 @@ void WebSnapshotDeserializer::DeserializeMaps() { ...@@ -1250,7 +1250,7 @@ void WebSnapshotDeserializer::DeserializeMaps() {
maps_ = isolate_->factory()->NewFixedArray(map_count_); maps_ = isolate_->factory()->NewFixedArray(map_count_);
for (uint32_t i = 0; i < map_count_; ++i) { for (uint32_t i = 0; i < map_count_; ++i) {
uint32_t map_type; uint32_t map_type;
if (!deserializer_->ReadUint32(&map_type)) { if (!deserializer_.ReadUint32(&map_type)) {
Throw("Malformed shape"); Throw("Malformed shape");
return; return;
} }
...@@ -1268,14 +1268,14 @@ void WebSnapshotDeserializer::DeserializeMaps() { ...@@ -1268,14 +1268,14 @@ void WebSnapshotDeserializer::DeserializeMaps() {
} }
uint32_t prototype_id; uint32_t prototype_id;
if (!deserializer_->ReadUint32(&prototype_id) || if (!deserializer_.ReadUint32(&prototype_id) ||
prototype_id > kMaxItemCount) { prototype_id > kMaxItemCount) {
Throw("Malformed shape"); Throw("Malformed shape");
return; return;
} }
uint32_t property_count; uint32_t property_count;
if (!deserializer_->ReadUint32(&property_count)) { if (!deserializer_.ReadUint32(&property_count)) {
Throw("Malformed shape"); Throw("Malformed shape");
return; return;
} }
...@@ -1301,7 +1301,7 @@ void WebSnapshotDeserializer::DeserializeMaps() { ...@@ -1301,7 +1301,7 @@ void WebSnapshotDeserializer::DeserializeMaps() {
PropertyAttributes attributes = PropertyAttributes::NONE; PropertyAttributes attributes = PropertyAttributes::NONE;
if (has_custom_property_attributes) { if (has_custom_property_attributes) {
uint32_t flags; uint32_t flags;
if (!deserializer_->ReadUint32(&flags)) { if (!deserializer_.ReadUint32(&flags)) {
Throw("Malformed shape"); Throw("Malformed shape");
return; return;
} }
...@@ -1345,7 +1345,7 @@ void WebSnapshotDeserializer::DeserializeMaps() { ...@@ -1345,7 +1345,7 @@ void WebSnapshotDeserializer::DeserializeMaps() {
void WebSnapshotDeserializer::DeserializeContexts() { void WebSnapshotDeserializer::DeserializeContexts() {
RCS_SCOPE(isolate_, RuntimeCallCounterId::kWebSnapshotDeserialize_Contexts); RCS_SCOPE(isolate_, RuntimeCallCounterId::kWebSnapshotDeserialize_Contexts);
if (!deserializer_->ReadUint32(&context_count_) || if (!deserializer_.ReadUint32(&context_count_) ||
context_count_ > kMaxItemCount) { context_count_ > kMaxItemCount) {
Throw("Malformed context table"); Throw("Malformed context table");
return; return;
...@@ -1354,7 +1354,7 @@ void WebSnapshotDeserializer::DeserializeContexts() { ...@@ -1354,7 +1354,7 @@ void WebSnapshotDeserializer::DeserializeContexts() {
contexts_ = isolate_->factory()->NewFixedArray(context_count_); contexts_ = isolate_->factory()->NewFixedArray(context_count_);
for (uint32_t i = 0; i < context_count_; ++i) { for (uint32_t i = 0; i < context_count_; ++i) {
uint32_t context_type; uint32_t context_type;
if (!deserializer_->ReadUint32(&context_type)) { if (!deserializer_.ReadUint32(&context_type)) {
Throw("Malformed context type"); Throw("Malformed context type");
return; return;
} }
...@@ -1362,14 +1362,14 @@ void WebSnapshotDeserializer::DeserializeContexts() { ...@@ -1362,14 +1362,14 @@ void WebSnapshotDeserializer::DeserializeContexts() {
uint32_t parent_context_id; uint32_t parent_context_id;
// Parent context is serialized before child context. Note: not >= on // Parent context is serialized before child context. Note: not >= on
// purpose, we're going to subtract 1 later. // purpose, we're going to subtract 1 later.
if (!deserializer_->ReadUint32(&parent_context_id) || if (!deserializer_.ReadUint32(&parent_context_id) ||
parent_context_id > i) { parent_context_id > i) {
Throw("Malformed context"); Throw("Malformed context");
return; return;
} }
uint32_t variable_count; uint32_t variable_count;
if (!deserializer_->ReadUint32(&variable_count)) { if (!deserializer_.ReadUint32(&variable_count)) {
Throw("Malformed context"); Throw("Malformed context");
return; return;
} }
...@@ -1551,7 +1551,7 @@ Handle<JSFunction> WebSnapshotDeserializer::CreateJSFunction( ...@@ -1551,7 +1551,7 @@ Handle<JSFunction> WebSnapshotDeserializer::CreateJSFunction(
void WebSnapshotDeserializer::DeserializeFunctions() { void WebSnapshotDeserializer::DeserializeFunctions() {
RCS_SCOPE(isolate_, RuntimeCallCounterId::kWebSnapshotDeserialize_Functions); RCS_SCOPE(isolate_, RuntimeCallCounterId::kWebSnapshotDeserialize_Functions);
if (!deserializer_->ReadUint32(&function_count_) || if (!deserializer_.ReadUint32(&function_count_) ||
function_count_ > kMaxItemCount) { function_count_ > kMaxItemCount) {
Throw("Malformed function table"); Throw("Malformed function table");
return; return;
...@@ -1576,8 +1576,7 @@ void WebSnapshotDeserializer::DeserializeFunctions() { ...@@ -1576,8 +1576,7 @@ void WebSnapshotDeserializer::DeserializeFunctions() {
for (; current_function_count_ < function_count_; ++current_function_count_) { for (; current_function_count_ < function_count_; ++current_function_count_) {
uint32_t context_id; uint32_t context_id;
// Note: > (not >= on purpose, we will subtract 1). // Note: > (not >= on purpose, we will subtract 1).
if (!deserializer_->ReadUint32(&context_id) || if (!deserializer_.ReadUint32(&context_id) || context_id > context_count_) {
context_id > context_count_) {
Throw("Malformed function"); Throw("Malformed function");
return; return;
} }
...@@ -1594,10 +1593,10 @@ void WebSnapshotDeserializer::DeserializeFunctions() { ...@@ -1594,10 +1593,10 @@ void WebSnapshotDeserializer::DeserializeFunctions() {
uint32_t length; uint32_t length;
uint32_t parameter_count; uint32_t parameter_count;
uint32_t flags; uint32_t flags;
if (!deserializer_->ReadUint32(&start_position) || if (!deserializer_.ReadUint32(&start_position) ||
!deserializer_->ReadUint32(&length) || !deserializer_.ReadUint32(&length) ||
!deserializer_->ReadUint32(&parameter_count) || !deserializer_.ReadUint32(&parameter_count) ||
!deserializer_->ReadUint32(&flags)) { !deserializer_.ReadUint32(&flags)) {
Throw("Malformed function"); Throw("Malformed function");
return; return;
} }
...@@ -1615,7 +1614,7 @@ void WebSnapshotDeserializer::DeserializeFunctions() { ...@@ -1615,7 +1614,7 @@ void WebSnapshotDeserializer::DeserializeFunctions() {
void WebSnapshotDeserializer::DeserializeClasses() { void WebSnapshotDeserializer::DeserializeClasses() {
RCS_SCOPE(isolate_, RuntimeCallCounterId::kWebSnapshotDeserialize_Classes); RCS_SCOPE(isolate_, RuntimeCallCounterId::kWebSnapshotDeserialize_Classes);
if (!deserializer_->ReadUint32(&class_count_) || if (!deserializer_.ReadUint32(&class_count_) ||
class_count_ > kMaxItemCount) { class_count_ > kMaxItemCount) {
Throw("Malformed class table"); Throw("Malformed class table");
return; return;
...@@ -1632,8 +1631,7 @@ void WebSnapshotDeserializer::DeserializeClasses() { ...@@ -1632,8 +1631,7 @@ void WebSnapshotDeserializer::DeserializeClasses() {
for (; current_class_count_ < class_count_; ++current_class_count_) { for (; current_class_count_ < class_count_; ++current_class_count_) {
uint32_t context_id; uint32_t context_id;
// Note: > (not >= on purpose, we will subtract 1). // Note: > (not >= on purpose, we will subtract 1).
if (!deserializer_->ReadUint32(&context_id) || if (!deserializer_.ReadUint32(&context_id) || context_id > context_count_) {
context_id > context_count_) {
Throw("Malformed class"); Throw("Malformed class");
return; return;
} }
...@@ -1650,10 +1648,10 @@ void WebSnapshotDeserializer::DeserializeClasses() { ...@@ -1650,10 +1648,10 @@ void WebSnapshotDeserializer::DeserializeClasses() {
uint32_t length; uint32_t length;
uint32_t parameter_count; uint32_t parameter_count;
uint32_t flags; uint32_t flags;
if (!deserializer_->ReadUint32(&start_position) || if (!deserializer_.ReadUint32(&start_position) ||
!deserializer_->ReadUint32(&length) || !deserializer_.ReadUint32(&length) ||
!deserializer_->ReadUint32(&parameter_count) || !deserializer_.ReadUint32(&parameter_count) ||
!deserializer_->ReadUint32(&flags)) { !deserializer_.ReadUint32(&flags)) {
Throw("Malformed class"); Throw("Malformed class");
return; return;
} }
...@@ -1671,7 +1669,7 @@ void WebSnapshotDeserializer::DeserializeClasses() { ...@@ -1671,7 +1669,7 @@ void WebSnapshotDeserializer::DeserializeClasses() {
void WebSnapshotDeserializer::DeserializeObjects() { void WebSnapshotDeserializer::DeserializeObjects() {
RCS_SCOPE(isolate_, RuntimeCallCounterId::kWebSnapshotDeserialize_Objects); RCS_SCOPE(isolate_, RuntimeCallCounterId::kWebSnapshotDeserialize_Objects);
if (!deserializer_->ReadUint32(&object_count_) || if (!deserializer_.ReadUint32(&object_count_) ||
object_count_ > kMaxItemCount) { object_count_ > kMaxItemCount) {
Throw("Malformed objects table"); Throw("Malformed objects table");
return; return;
...@@ -1680,7 +1678,7 @@ void WebSnapshotDeserializer::DeserializeObjects() { ...@@ -1680,7 +1678,7 @@ void WebSnapshotDeserializer::DeserializeObjects() {
objects_ = isolate_->factory()->NewFixedArray(object_count_); objects_ = isolate_->factory()->NewFixedArray(object_count_);
for (; current_object_count_ < object_count_; ++current_object_count_) { for (; current_object_count_ < object_count_; ++current_object_count_) {
uint32_t map_id; uint32_t map_id;
if (!deserializer_->ReadUint32(&map_id) || map_id >= map_count_) { if (!deserializer_.ReadUint32(&map_id) || map_id >= map_count_) {
Throw("Malformed object"); Throw("Malformed object");
return; return;
} }
...@@ -1718,7 +1716,7 @@ void WebSnapshotDeserializer::DeserializeObjects() { ...@@ -1718,7 +1716,7 @@ void WebSnapshotDeserializer::DeserializeObjects() {
void WebSnapshotDeserializer::DeserializeArrays() { void WebSnapshotDeserializer::DeserializeArrays() {
RCS_SCOPE(isolate_, RuntimeCallCounterId::kWebSnapshotDeserialize_Arrays); RCS_SCOPE(isolate_, RuntimeCallCounterId::kWebSnapshotDeserialize_Arrays);
if (!deserializer_->ReadUint32(&array_count_) || if (!deserializer_.ReadUint32(&array_count_) ||
object_count_ > kMaxItemCount) { object_count_ > kMaxItemCount) {
Throw("Malformed array table"); Throw("Malformed array table");
return; return;
...@@ -1727,7 +1725,7 @@ void WebSnapshotDeserializer::DeserializeArrays() { ...@@ -1727,7 +1725,7 @@ void WebSnapshotDeserializer::DeserializeArrays() {
arrays_ = isolate_->factory()->NewFixedArray(array_count_); arrays_ = isolate_->factory()->NewFixedArray(array_count_);
for (; current_array_count_ < array_count_; ++current_array_count_) { for (; current_array_count_ < array_count_; ++current_array_count_) {
uint32_t length; uint32_t length;
if (!deserializer_->ReadUint32(&length) || length > kMaxItemCount) { if (!deserializer_.ReadUint32(&length) || length > kMaxItemCount) {
Throw("Malformed array"); Throw("Malformed array");
return; return;
} }
...@@ -1752,7 +1750,7 @@ void WebSnapshotDeserializer::DeserializeArrays() { ...@@ -1752,7 +1750,7 @@ void WebSnapshotDeserializer::DeserializeArrays() {
void WebSnapshotDeserializer::DeserializeExports() { void WebSnapshotDeserializer::DeserializeExports() {
RCS_SCOPE(isolate_, RuntimeCallCounterId::kWebSnapshotDeserialize_Exports); RCS_SCOPE(isolate_, RuntimeCallCounterId::kWebSnapshotDeserialize_Exports);
uint32_t count; uint32_t count;
if (!deserializer_->ReadUint32(&count) || count > kMaxItemCount) { if (!deserializer_.ReadUint32(&count) || count > kMaxItemCount) {
Throw("Malformed export table"); Throw("Malformed export table");
return; return;
} }
...@@ -1808,7 +1806,7 @@ void WebSnapshotDeserializer::ReadValue( ...@@ -1808,7 +1806,7 @@ void WebSnapshotDeserializer::ReadValue(
uint32_t value_type; uint32_t value_type;
Factory* factory = isolate_->factory(); Factory* factory = isolate_->factory();
// TODO(v8:11525): Consider adding a ReadByte. // TODO(v8:11525): Consider adding a ReadByte.
if (!deserializer_->ReadUint32(&value_type)) { if (!deserializer_.ReadUint32(&value_type)) {
Throw("Malformed variable"); Throw("Malformed variable");
// Set "value" here so that the "keep on trucking" error handling won't fail // Set "value" here so that the "keep on trucking" error handling won't fail
// when dereferencing the handle. // when dereferencing the handle.
...@@ -1838,7 +1836,7 @@ void WebSnapshotDeserializer::ReadValue( ...@@ -1838,7 +1836,7 @@ void WebSnapshotDeserializer::ReadValue(
break; break;
} }
case ValueType::INTEGER: { case ValueType::INTEGER: {
Maybe<int32_t> number = deserializer_->ReadZigZag<int32_t>(); Maybe<int32_t> number = deserializer_.ReadZigZag<int32_t>();
if (number.IsNothing()) { if (number.IsNothing()) {
Throw("Malformed integer"); Throw("Malformed integer");
return; return;
...@@ -1849,7 +1847,7 @@ void WebSnapshotDeserializer::ReadValue( ...@@ -1849,7 +1847,7 @@ void WebSnapshotDeserializer::ReadValue(
} }
case ValueType::DOUBLE: { case ValueType::DOUBLE: {
double number; double number;
if (!deserializer_->ReadDouble(&number)) { if (!deserializer_.ReadDouble(&number)) {
Throw("Malformed double"); Throw("Malformed double");
return; return;
} }
...@@ -1864,7 +1862,7 @@ void WebSnapshotDeserializer::ReadValue( ...@@ -1864,7 +1862,7 @@ void WebSnapshotDeserializer::ReadValue(
} }
case ValueType::ARRAY_ID: case ValueType::ARRAY_ID:
uint32_t array_id; uint32_t array_id;
if (!deserializer_->ReadUint32(&array_id) || array_id >= kMaxItemCount) { if (!deserializer_.ReadUint32(&array_id) || array_id >= kMaxItemCount) {
Throw("Malformed variable"); Throw("Malformed variable");
return; return;
} }
...@@ -1884,7 +1882,7 @@ void WebSnapshotDeserializer::ReadValue( ...@@ -1884,7 +1882,7 @@ void WebSnapshotDeserializer::ReadValue(
break; break;
case ValueType::OBJECT_ID: case ValueType::OBJECT_ID:
uint32_t object_id; uint32_t object_id;
if (!deserializer_->ReadUint32(&object_id) || object_id > kMaxItemCount) { if (!deserializer_.ReadUint32(&object_id) || object_id > kMaxItemCount) {
Throw("Malformed variable"); Throw("Malformed variable");
return; return;
} }
...@@ -1905,7 +1903,7 @@ void WebSnapshotDeserializer::ReadValue( ...@@ -1905,7 +1903,7 @@ void WebSnapshotDeserializer::ReadValue(
break; break;
case ValueType::FUNCTION_ID: { case ValueType::FUNCTION_ID: {
uint32_t function_id; uint32_t function_id;
if (!deserializer_->ReadUint32(&function_id) || if (!deserializer_.ReadUint32(&function_id) ||
function_id >= function_count_) { function_id >= function_count_) {
Throw("Malformed object property"); Throw("Malformed object property");
return; return;
...@@ -1928,7 +1926,7 @@ void WebSnapshotDeserializer::ReadValue( ...@@ -1928,7 +1926,7 @@ void WebSnapshotDeserializer::ReadValue(
} }
case ValueType::CLASS_ID: { case ValueType::CLASS_ID: {
uint32_t class_id; uint32_t class_id;
if (!deserializer_->ReadUint32(&class_id) || class_id >= kMaxItemCount) { if (!deserializer_.ReadUint32(&class_id) || class_id >= kMaxItemCount) {
Throw("Malformed object property"); Throw("Malformed object property");
return; return;
} }
...@@ -1976,7 +1974,7 @@ void WebSnapshotDeserializer::ReadFunctionPrototype( ...@@ -1976,7 +1974,7 @@ void WebSnapshotDeserializer::ReadFunctionPrototype(
Handle<JSFunction> function) { Handle<JSFunction> function) {
uint32_t object_id; uint32_t object_id;
if (!deserializer_->ReadUint32(&object_id) || object_id > kMaxItemCount + 1) { if (!deserializer_.ReadUint32(&object_id) || object_id > kMaxItemCount + 1) {
Throw("Malformed class / function"); Throw("Malformed class / function");
return; return;
} }
......
...@@ -228,10 +228,11 @@ class V8_EXPORT WebSnapshotSerializer ...@@ -228,10 +228,11 @@ class V8_EXPORT WebSnapshotSerializer
class V8_EXPORT WebSnapshotDeserializer class V8_EXPORT WebSnapshotDeserializer
: public WebSnapshotSerializerDeserializer { : public WebSnapshotSerializerDeserializer {
public: public:
explicit WebSnapshotDeserializer(v8::Isolate* v8_isolate); WebSnapshotDeserializer(v8::Isolate* v8_isolate, const uint8_t* data,
size_t buffer_size);
WebSnapshotDeserializer(Isolate* isolate, Handle<Script> snapshot_as_script);
~WebSnapshotDeserializer(); ~WebSnapshotDeserializer();
bool UseWebSnapshot(const uint8_t* data, size_t buffer_size); bool Deserialize();
bool UseWebSnapshot(Handle<Script> snapshot_as_script);
// For inspecting the state after deserializing a snapshot. // For inspecting the state after deserializing a snapshot.
uint32_t string_count() const { return string_count_; } uint32_t string_count() const { return string_count_; }
...@@ -243,7 +244,10 @@ class V8_EXPORT WebSnapshotDeserializer ...@@ -243,7 +244,10 @@ class V8_EXPORT WebSnapshotDeserializer
uint32_t object_count() const { return object_count_; } uint32_t object_count() const { return object_count_; }
private: private:
bool Deserialize(); WebSnapshotDeserializer(Isolate* isolate, Handle<Object> script_name,
base::Vector<const uint8_t> buffer);
base::Vector<const uint8_t> ExtractScriptBuffer(
Isolate* isolate, Handle<Script> snapshot_as_script);
bool DeserializeSnapshot(); bool DeserializeSnapshot();
bool DeserializeScript(); bool DeserializeScript();
...@@ -305,7 +309,7 @@ class V8_EXPORT WebSnapshotDeserializer ...@@ -305,7 +309,7 @@ class V8_EXPORT WebSnapshotDeserializer
uint32_t object_count_ = 0; uint32_t object_count_ = 0;
uint32_t current_object_count_ = 0; uint32_t current_object_count_ = 0;
std::unique_ptr<ValueDeserializer> deserializer_; ValueDeserializer deserializer_;
bool deserialized_ = false; bool deserialized_ = false;
}; };
......
...@@ -47,9 +47,9 @@ void TestWebSnapshotExtensive( ...@@ -47,9 +47,9 @@ void TestWebSnapshotExtensive(
v8::HandleScope scope(isolate); v8::HandleScope scope(isolate);
v8::Local<v8::Context> new_context = CcTest::NewContext(); v8::Local<v8::Context> new_context = CcTest::NewContext();
v8::Context::Scope context_scope(new_context); v8::Context::Scope context_scope(new_context);
WebSnapshotDeserializer deserializer(isolate); WebSnapshotDeserializer deserializer(isolate, snapshot_data.buffer,
CHECK(deserializer.UseWebSnapshot(snapshot_data.buffer, snapshot_data.buffer_size);
snapshot_data.buffer_size)); CHECK(deserializer.Deserialize());
CHECK(!deserializer.has_error()); CHECK(!deserializer.has_error());
tester(isolate, new_context); tester(isolate, new_context);
CHECK_EQ(string_count, deserializer.string_count()); CHECK_EQ(string_count, deserializer.string_count());
...@@ -343,9 +343,9 @@ TEST(SFIDeduplication) { ...@@ -343,9 +343,9 @@ TEST(SFIDeduplication) {
{ {
v8::Local<v8::Context> new_context = CcTest::NewContext(); v8::Local<v8::Context> new_context = CcTest::NewContext();
v8::Context::Scope context_scope(new_context); v8::Context::Scope context_scope(new_context);
WebSnapshotDeserializer deserializer(isolate); WebSnapshotDeserializer deserializer(isolate, snapshot_data.buffer,
CHECK(deserializer.UseWebSnapshot(snapshot_data.buffer, snapshot_data.buffer_size);
snapshot_data.buffer_size)); CHECK(deserializer.Deserialize());
CHECK(!deserializer.has_error()); CHECK(!deserializer.has_error());
const char* get_inner = "foo.inner"; const char* get_inner = "foo.inner";
...@@ -399,9 +399,9 @@ TEST(SFIDeduplicationClasses) { ...@@ -399,9 +399,9 @@ TEST(SFIDeduplicationClasses) {
{ {
v8::Local<v8::Context> new_context = CcTest::NewContext(); v8::Local<v8::Context> new_context = CcTest::NewContext();
v8::Context::Scope context_scope(new_context); v8::Context::Scope context_scope(new_context);
WebSnapshotDeserializer deserializer(isolate); WebSnapshotDeserializer deserializer(isolate, snapshot_data.buffer,
CHECK(deserializer.UseWebSnapshot(snapshot_data.buffer, snapshot_data.buffer_size);
snapshot_data.buffer_size)); CHECK(deserializer.Deserialize());
CHECK(!deserializer.has_error()); CHECK(!deserializer.has_error());
const char* get_class = "foo.class"; const char* get_class = "foo.class";
...@@ -464,9 +464,9 @@ TEST(SFIDeduplicationAfterBytecodeFlushing) { ...@@ -464,9 +464,9 @@ TEST(SFIDeduplicationAfterBytecodeFlushing) {
v8::HandleScope scope(isolate); v8::HandleScope scope(isolate);
v8::Local<v8::Context> new_context = CcTest::NewContext(); v8::Local<v8::Context> new_context = CcTest::NewContext();
v8::Context::Scope context_scope(new_context); v8::Context::Scope context_scope(new_context);
WebSnapshotDeserializer deserializer(isolate); WebSnapshotDeserializer deserializer(isolate, snapshot_data.buffer,
CHECK(deserializer.UseWebSnapshot(snapshot_data.buffer, snapshot_data.buffer_size);
snapshot_data.buffer_size)); CHECK(deserializer.Deserialize());
CHECK(!deserializer.has_error()); CHECK(!deserializer.has_error());
const char* get_outer = "foo.outer"; const char* get_outer = "foo.outer";
...@@ -549,9 +549,9 @@ TEST(SFIDeduplicationAfterBytecodeFlushingClasses) { ...@@ -549,9 +549,9 @@ TEST(SFIDeduplicationAfterBytecodeFlushingClasses) {
v8::HandleScope scope(isolate); v8::HandleScope scope(isolate);
v8::Local<v8::Context> new_context = CcTest::NewContext(); v8::Local<v8::Context> new_context = CcTest::NewContext();
v8::Context::Scope context_scope(new_context); v8::Context::Scope context_scope(new_context);
WebSnapshotDeserializer deserializer(isolate); WebSnapshotDeserializer deserializer(isolate, snapshot_data.buffer,
CHECK(deserializer.UseWebSnapshot(snapshot_data.buffer, snapshot_data.buffer_size);
snapshot_data.buffer_size)); CHECK(deserializer.Deserialize());
CHECK(!deserializer.has_error()); CHECK(!deserializer.has_error());
const char* get_create = "foo.create"; const char* get_create = "foo.create";
...@@ -626,9 +626,9 @@ TEST(SFIDeduplicationOfFunctionsNotInSnapshot) { ...@@ -626,9 +626,9 @@ TEST(SFIDeduplicationOfFunctionsNotInSnapshot) {
{ {
v8::Local<v8::Context> new_context = CcTest::NewContext(); v8::Local<v8::Context> new_context = CcTest::NewContext();
v8::Context::Scope context_scope(new_context); v8::Context::Scope context_scope(new_context);
WebSnapshotDeserializer deserializer(isolate); WebSnapshotDeserializer deserializer(isolate, snapshot_data.buffer,
CHECK(deserializer.UseWebSnapshot(snapshot_data.buffer, snapshot_data.buffer_size);
snapshot_data.buffer_size)); CHECK(deserializer.Deserialize());
CHECK(!deserializer.has_error()); CHECK(!deserializer.has_error());
const char* create_new_inner = "foo.outer()"; const char* create_new_inner = "foo.outer()";
...@@ -738,8 +738,8 @@ TEST(Concatenation) { ...@@ -738,8 +738,8 @@ TEST(Concatenation) {
v8::HandleScope scope(isolate); v8::HandleScope scope(isolate);
v8::Local<v8::Context> new_context = CcTest::NewContext(); v8::Local<v8::Context> new_context = CcTest::NewContext();
v8::Context::Scope context_scope(new_context); v8::Context::Scope context_scope(new_context);
WebSnapshotDeserializer deserializer(isolate); WebSnapshotDeserializer deserializer(isolate, buffer.get(), buffer_size);
CHECK(deserializer.UseWebSnapshot(buffer.get(), buffer_size)); CHECK(deserializer.Deserialize());
CHECK(!deserializer.has_error()); CHECK(!deserializer.has_error());
CHECK_EQ(kObjectCount, deserializer.object_count()); CHECK_EQ(kObjectCount, deserializer.object_count());
...@@ -785,8 +785,8 @@ TEST(ConcatenationErrors) { ...@@ -785,8 +785,8 @@ TEST(ConcatenationErrors) {
v8::HandleScope scope(isolate); v8::HandleScope scope(isolate);
v8::Local<v8::Context> new_context = CcTest::NewContext(); v8::Local<v8::Context> new_context = CcTest::NewContext();
v8::Context::Scope context_scope(new_context); v8::Context::Scope context_scope(new_context);
WebSnapshotDeserializer deserializer(isolate); WebSnapshotDeserializer deserializer(isolate, buffer.get(), buffer_size);
CHECK(!deserializer.UseWebSnapshot(buffer.get(), buffer_size)); CHECK(!deserializer.Deserialize());
} }
} }
...@@ -819,9 +819,9 @@ TEST(CompactedSourceCode) { ...@@ -819,9 +819,9 @@ TEST(CompactedSourceCode) {
{ {
v8::Local<v8::Context> new_context = CcTest::NewContext(); v8::Local<v8::Context> new_context = CcTest::NewContext();
v8::Context::Scope context_scope(new_context); v8::Context::Scope context_scope(new_context);
WebSnapshotDeserializer deserializer(isolate); WebSnapshotDeserializer deserializer(isolate, snapshot_data.buffer,
CHECK(deserializer.UseWebSnapshot(snapshot_data.buffer, snapshot_data.buffer_size);
snapshot_data.buffer_size)); CHECK(deserializer.Deserialize());
CHECK(!deserializer.has_error()); CHECK(!deserializer.has_error());
const char* get_function = "e[0]"; const char* get_function = "e[0]";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment