Commit 55f6e945 authored by Marja Hölttä's avatar Marja Hölttä Committed by V8 LUCI CQ

[web snapshot] Serialize leaf objects first

This generates snapshots which are quicker to deserialize since
there are less forward references (item referring to another item with
a greater ID).

Bug: v8:11525
Change-Id: Ib5dce296fca57dae4c0d9bc98f97fe8440c9be8a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3483657Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Commit-Queue: Marja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/main@{#79224}
parent c2374f90
...@@ -300,26 +300,29 @@ bool WebSnapshotSerializer::TakeSnapshot(v8::Local<v8::Context> context, ...@@ -300,26 +300,29 @@ bool WebSnapshotSerializer::TakeSnapshot(v8::Local<v8::Context> context,
} }
void WebSnapshotSerializer::SerializePendingItems() { void WebSnapshotSerializer::SerializePendingItems() {
for (int i = 0; i < contexts_->Length(); ++i) { // Serialize the items in the reverse order. The items at the end of the
// contexts_ etc get lower IDs and vice versa. IDs which items use for
// referring to each other are reversed by Get<item>Id functions().
for (int i = contexts_->Length() - 1; i >= 0; --i) {
Handle<Context> context = Handle<Context> context =
handle(Context::cast(contexts_->Get(i)), isolate_); handle(Context::cast(contexts_->Get(i)), isolate_);
SerializeContext(context); SerializeContext(context);
} }
for (int i = 0; i < functions_->Length(); ++i) { for (int i = functions_->Length() - 1; i >= 0; --i) {
Handle<JSFunction> function = Handle<JSFunction> function =
handle(JSFunction::cast(functions_->Get(i)), isolate_); handle(JSFunction::cast(functions_->Get(i)), isolate_);
SerializeFunction(function); SerializeFunction(function);
} }
for (int i = 0; i < classes_->Length(); ++i) { for (int i = classes_->Length() - 1; i >= 0; --i) {
Handle<JSFunction> function = Handle<JSFunction> function =
handle(JSFunction::cast(classes_->Get(i)), isolate_); handle(JSFunction::cast(classes_->Get(i)), isolate_);
SerializeClass(function); SerializeClass(function);
} }
for (int i = 0; i < arrays_->Length(); ++i) { for (int i = arrays_->Length() - 1; i >= 0; --i) {
Handle<JSArray> array = handle(JSArray::cast(arrays_->Get(i)), isolate_); Handle<JSArray> array = handle(JSArray::cast(arrays_->Get(i)), isolate_);
SerializeArray(array); SerializeArray(array);
} }
for (int i = 0; i < objects_->Length(); ++i) { for (int i = objects_->Length() - 1; i >= 0; --i) {
Handle<JSObject> object = Handle<JSObject> object =
handle(JSObject::cast(objects_->Get(i)), isolate_); handle(JSObject::cast(objects_->Get(i)), isolate_);
SerializeObject(object); SerializeObject(object);
...@@ -623,7 +626,6 @@ void WebSnapshotSerializer::Discover(Handle<HeapObject> start_object) { ...@@ -623,7 +626,6 @@ void WebSnapshotSerializer::Discover(Handle<HeapObject> start_object) {
// e.g., we know all functions upfront and can construct the source code that // e.g., we know all functions upfront and can construct the source code that
// covers them before serializing the functions. // covers them before serializing the functions.
// TODO(v8:11525): Serialize leaf objects first.
discovery_queue_.push(start_object); discovery_queue_.push(start_object);
while (!discovery_queue_.empty()) { while (!discovery_queue_.empty()) {
...@@ -708,12 +710,6 @@ void WebSnapshotSerializer::DiscoverContextAndPrototype( ...@@ -708,12 +710,6 @@ void WebSnapshotSerializer::DiscoverContextAndPrototype(
} }
void WebSnapshotSerializer::DiscoverContext(Handle<Context> context) { void WebSnapshotSerializer::DiscoverContext(Handle<Context> context) {
// Ensure that parent contexts get a lower ID.
if (!context->previous().IsNativeContext() &&
!context->previous().IsScriptContext()) {
DiscoverContext(handle(context->previous(), isolate_));
}
uint32_t id; uint32_t id;
if (InsertIntoIndexMap(context_ids_, *context, id)) return; if (InsertIntoIndexMap(context_ids_, *context, id)) return;
...@@ -731,6 +727,11 @@ void WebSnapshotSerializer::DiscoverContext(Handle<Context> context) { ...@@ -731,6 +727,11 @@ void WebSnapshotSerializer::DiscoverContext(Handle<Context> context) {
if (!value.IsHeapObject()) continue; if (!value.IsHeapObject()) continue;
discovery_queue_.push(handle(HeapObject::cast(value), isolate_)); discovery_queue_.push(handle(HeapObject::cast(value), isolate_));
} }
if (!context->previous().IsNativeContext() &&
!context->previous().IsScriptContext()) {
DiscoverContext(handle(context->previous(), isolate_));
}
} }
void WebSnapshotSerializer::DiscoverSource(Handle<JSFunction> function) { void WebSnapshotSerializer::DiscoverSource(Handle<JSFunction> function) {
...@@ -1035,7 +1036,7 @@ uint32_t WebSnapshotSerializer::GetFunctionId(JSFunction function) { ...@@ -1035,7 +1036,7 @@ uint32_t WebSnapshotSerializer::GetFunctionId(JSFunction function) {
bool return_value = function_ids_.Lookup(function, &id); bool return_value = function_ids_.Lookup(function, &id);
DCHECK(return_value); DCHECK(return_value);
USE(return_value); USE(return_value);
return static_cast<uint32_t>(id); return static_cast<uint32_t>(function_ids_.size() - 1 - id);
} }
uint32_t WebSnapshotSerializer::GetClassId(JSFunction function) { uint32_t WebSnapshotSerializer::GetClassId(JSFunction function) {
...@@ -1043,7 +1044,7 @@ uint32_t WebSnapshotSerializer::GetClassId(JSFunction function) { ...@@ -1043,7 +1044,7 @@ uint32_t WebSnapshotSerializer::GetClassId(JSFunction function) {
bool return_value = class_ids_.Lookup(function, &id); bool return_value = class_ids_.Lookup(function, &id);
DCHECK(return_value); DCHECK(return_value);
USE(return_value); USE(return_value);
return static_cast<uint32_t>(id); return static_cast<uint32_t>(class_ids_.size() - 1 - id);
} }
uint32_t WebSnapshotSerializer::GetContextId(Context context) { uint32_t WebSnapshotSerializer::GetContextId(Context context) {
...@@ -1051,7 +1052,7 @@ uint32_t WebSnapshotSerializer::GetContextId(Context context) { ...@@ -1051,7 +1052,7 @@ uint32_t WebSnapshotSerializer::GetContextId(Context context) {
bool return_value = context_ids_.Lookup(context, &id); bool return_value = context_ids_.Lookup(context, &id);
DCHECK(return_value); DCHECK(return_value);
USE(return_value); USE(return_value);
return static_cast<uint32_t>(id); return static_cast<uint32_t>(context_ids_.size() - 1 - id);
} }
uint32_t WebSnapshotSerializer::GetArrayId(JSArray array) { uint32_t WebSnapshotSerializer::GetArrayId(JSArray array) {
...@@ -1059,7 +1060,7 @@ uint32_t WebSnapshotSerializer::GetArrayId(JSArray array) { ...@@ -1059,7 +1060,7 @@ uint32_t WebSnapshotSerializer::GetArrayId(JSArray array) {
bool return_value = array_ids_.Lookup(array, &id); bool return_value = array_ids_.Lookup(array, &id);
DCHECK(return_value); DCHECK(return_value);
USE(return_value); USE(return_value);
return static_cast<uint32_t>(id); return static_cast<uint32_t>(array_ids_.size() - 1 - id);
} }
uint32_t WebSnapshotSerializer::GetObjectId(JSObject object) { uint32_t WebSnapshotSerializer::GetObjectId(JSObject object) {
...@@ -1067,7 +1068,7 @@ uint32_t WebSnapshotSerializer::GetObjectId(JSObject object) { ...@@ -1067,7 +1068,7 @@ uint32_t WebSnapshotSerializer::GetObjectId(JSObject object) {
bool return_value = object_ids_.Lookup(object, &id); bool return_value = object_ids_.Lookup(object, &id);
DCHECK(return_value); DCHECK(return_value);
USE(return_value); USE(return_value);
return static_cast<uint32_t>(id); return static_cast<uint32_t>(object_ids_.size() - 1 - id);
} }
uint32_t WebSnapshotSerializer::GetExternalId(HeapObject object) { uint32_t WebSnapshotSerializer::GetExternalId(HeapObject object) {
......
...@@ -215,10 +215,13 @@ class V8_EXPORT WebSnapshotSerializer ...@@ -215,10 +215,13 @@ class V8_EXPORT WebSnapshotSerializer
Handle<ArrayList> objects_; Handle<ArrayList> objects_;
// IndexMap to keep track of explicitly blocked external objects and // IndexMap to keep track of explicitly blocked external objects and
// non-serializable/not-supporte objects (e.g. API Objects). // non-serializable/not-supported objects (e.g. API Objects).
ObjectCacheIndexMap external_objects_ids_; ObjectCacheIndexMap external_objects_ids_;
// ObjectCacheIndexMap implements fast lookup item -> id. // ObjectCacheIndexMap implements fast lookup item -> id. Some items (context,
// function, class, array, object) can point to other items and we serialize
// them in the reverse order. This ensures that the items this item points to
// have a lower ID and will be deserialized first.
ObjectCacheIndexMap string_ids_; ObjectCacheIndexMap string_ids_;
ObjectCacheIndexMap map_ids_; ObjectCacheIndexMap map_ids_;
ObjectCacheIndexMap context_ids_; ObjectCacheIndexMap context_ids_;
......
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