Commit 71dbb03e authored by Marja Hölttä's avatar Marja Hölttä Committed by V8 LUCI CQ

[web snapshot] Recognize builtins

Builtins are not snapshotted, but instead we insert "builtin wrappers"
into the snapshot, and create references to the corresponding builtin
when deserializing.

Subclassing builtins will be implemented in a follow-up CL.

Bug: v8:11525,v8:12820
Change-Id: If72695d46bdfc8bf7e477471be1264b668551854
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3630080Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Commit-Queue: Marja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80419}
parent 40136c1b
......@@ -42,7 +42,7 @@ BUILTIN(WebSnapshotSerialize) {
}
if (!block_list_js_array.is_null() &&
static_cast<uint32_t>(block_list->length()) <
serializer.external_objects_count()) {
serializer.external_object_count()) {
Handle<FixedArray> externals = serializer.GetExternals();
Handle<Map> map = JSObject::GetElementsTransitionMap(block_list_js_array,
PACKED_ELEMENTS);
......
......@@ -483,6 +483,7 @@ class RuntimeCallTimer final {
V(UpdateProtector) \
V(WebSnapshotDeserialize) \
V(WebSnapshotDeserialize_Arrays) \
V(WebSnapshotDeserialize_BuiltinObjects) \
V(WebSnapshotDeserialize_Classes) \
V(WebSnapshotDeserialize_Contexts) \
V(WebSnapshotDeserialize_Exports) \
......
This diff is collapsed.
......@@ -57,6 +57,7 @@ class WebSnapshotSerializerDeserializer {
CLASS_ID,
SYMBOL_ID,
EXTERNAL_ID,
BUILTIN_OBJECT_ID,
IN_PLACE_STRING_ID
};
......@@ -94,6 +95,10 @@ class WebSnapshotSerializerDeserializer {
// Not virtual, on purpose (because it doesn't need to be).
void Throw(const char* message);
void IterateBuiltinObjects(std::function<void(String, HeapObject)> func);
static constexpr int kBuiltinObjectCount = 2;
inline Factory* factory() const { return isolate_->factory(); }
Isolate* isolate_;
......@@ -146,6 +151,10 @@ class V8_EXPORT WebSnapshotSerializer
uint32_t map_count() const { return static_cast<uint32_t>(map_ids_.size()); }
uint32_t builtin_object_count() const {
return static_cast<uint32_t>(builtin_object_ids_.size());
}
uint32_t context_count() const {
return static_cast<uint32_t>(context_ids_.size());
}
......@@ -166,8 +175,8 @@ class V8_EXPORT WebSnapshotSerializer
return static_cast<uint32_t>(object_ids_.size());
}
uint32_t external_objects_count() const {
return static_cast<uint32_t>(external_objects_ids_.size());
uint32_t external_object_count() const {
return static_cast<uint32_t>(external_object_ids_.size());
}
Handle<FixedArray> GetExternals();
......@@ -191,6 +200,7 @@ class V8_EXPORT WebSnapshotSerializer
uint32_t& id);
void ShallowDiscoverExternals(FixedArray externals);
void ShallowDiscoverBuiltinObjects(v8::Local<v8::Context> context);
void Discover(Handle<HeapObject> object);
void DiscoverString(Handle<String> string,
AllowInPlace can_be_in_place = AllowInPlace::No);
......@@ -202,6 +212,7 @@ class V8_EXPORT WebSnapshotSerializer
void DiscoverContext(Handle<Context> context);
void DiscoverArray(Handle<JSArray> array);
void DiscoverObject(Handle<JSObject> object);
bool DiscoverIfBuiltinObject(Handle<HeapObject> object);
void DiscoverSource(Handle<JSFunction> function);
template <typename T>
void DiscoverObjectPropertiesWithDictionaryMap(T dict);
......@@ -213,6 +224,7 @@ class V8_EXPORT WebSnapshotSerializer
void SerializeString(Handle<String> string, ValueSerializer& serializer);
void SerializeSymbol(Handle<Symbol> symbol);
void SerializeMap(Handle<Map> map);
void SerializeBuiltinObject(uint32_t name_id);
void SerializeObjectPrototype(Handle<Map> map, ValueSerializer& serializer);
template <typename T>
......@@ -237,11 +249,15 @@ class V8_EXPORT WebSnapshotSerializer
uint32_t GetContextId(Context context);
uint32_t GetArrayId(JSArray array);
uint32_t GetObjectId(JSObject object);
uint32_t GetExternalId(HeapObject object);
bool GetExternalId(HeapObject object, uint32_t* id = nullptr);
// Returns index into builtin_object_name_strings_.
bool GetBuiltinObjectNameIndex(HeapObject object, uint32_t& index);
bool GetBuiltinObjectId(HeapObject object, uint32_t& id);
ValueSerializer string_serializer_;
ValueSerializer symbol_serializer_;
ValueSerializer map_serializer_;
ValueSerializer builtin_object_serializer_;
ValueSerializer context_serializer_;
ValueSerializer function_serializer_;
ValueSerializer class_serializer_;
......@@ -261,7 +277,7 @@ class V8_EXPORT WebSnapshotSerializer
// IndexMap to keep track of explicitly blocked external objects and
// non-serializable/not-supported objects (e.g. API Objects).
ObjectCacheIndexMap external_objects_ids_;
ObjectCacheIndexMap external_object_ids_;
// ObjectCacheIndexMap implements fast lookup item -> id. Some items (context,
// function, class, array, object) can point to other items and we serialize
......@@ -277,6 +293,24 @@ class V8_EXPORT WebSnapshotSerializer
ObjectCacheIndexMap object_ids_;
uint32_t export_count_ = 0;
// For handling references to builtin objects:
// --------------------------------
// String objects for the names of all known builtins.
Handle<FixedArray> builtin_object_name_strings_;
// Map object -> index in builtin_name_strings_ for all known builtins.
ObjectCacheIndexMap builtin_object_to_name_;
// Map object -> index in builtins_. Includes only builtins which will be
// incluced in the snapshot.
ObjectCacheIndexMap builtin_object_ids_;
// For creating the Builtin wrappers in the snapshot. Includes only builtins
// which will be incluced in the snapshot. Each element is the id of the
// builtin name string in the snapshot.
std::vector<uint32_t> builtin_objects_;
// --------------------------------
std::queue<Handle<HeapObject>> discovery_queue_;
// For keeping track of which strings have exactly one reference. Strings are
......@@ -310,6 +344,7 @@ class V8_EXPORT WebSnapshotDeserializer
uint32_t string_count() const { return string_count_; }
uint32_t symbol_count() const { return symbol_count_; }
uint32_t map_count() const { return map_count_; }
uint32_t builtin_object_count() const { return builtin_object_count_; }
uint32_t context_count() const { return context_count_; }
uint32_t function_count() const { return function_count_; }
uint32_t class_count() const { return class_count_; }
......@@ -337,6 +372,7 @@ class V8_EXPORT WebSnapshotDeserializer
base::Vector<const uint8_t> ExtractScriptBuffer(
Isolate* isolate, Handle<Script> snapshot_as_script);
bool DeserializeSnapshot(bool skip_exports);
void CollectBuiltinObjects();
bool DeserializeScript();
WebSnapshotDeserializer(const WebSnapshotDeserializer&) = delete;
......@@ -345,6 +381,7 @@ class V8_EXPORT WebSnapshotDeserializer
void DeserializeStrings();
void DeserializeSymbols();
void DeserializeMaps();
void DeserializeBuiltinObjects();
void DeserializeContexts();
Handle<ScopeInfo> CreateScopeInfo(uint32_t variable_count, bool has_parent,
ContextType context_type,
......@@ -381,6 +418,7 @@ class V8_EXPORT WebSnapshotDeserializer
Object ReadFunction(Handle<HeapObject> container, uint32_t container_index);
Object ReadClass(Handle<HeapObject> container, uint32_t container_index);
Object ReadRegexp();
Object ReadBuiltinObjectReference();
Object ReadExternalReference();
bool ReadMapType();
......@@ -400,6 +438,9 @@ class V8_EXPORT WebSnapshotDeserializer
Handle<FixedArray> symbols_handle_;
FixedArray symbols_;
Handle<FixedArray> builtin_objects_handle_;
FixedArray builtin_objects_;
Handle<FixedArray> maps_handle_;
FixedArray maps_;
......@@ -421,6 +462,9 @@ class V8_EXPORT WebSnapshotDeserializer
Handle<FixedArray> external_references_handle_;
FixedArray external_references_;
// Map: String -> builtin object.
Handle<ObjectHashTable> builtin_object_name_to_object_;
Handle<ArrayList> deferred_references_;
Handle<WeakFixedArray> shared_function_infos_handle_;
......@@ -436,6 +480,7 @@ class V8_EXPORT WebSnapshotDeserializer
uint32_t string_count_ = 0;
uint32_t symbol_count_ = 0;
uint32_t map_count_ = 0;
uint32_t builtin_object_count_ = 0;
uint32_t context_count_ = 0;
uint32_t function_count_ = 0;
uint32_t current_function_count_ = 0;
......
This diff is collapsed.
// Copyright 2022 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --experimental-d8-web-snapshot-api --allow-natives-syntax
'use strict';
d8.file.execute('test/mjsunit/web-snapshot/web-snapshot-helpers.js');
(function TestBuiltin() {
function createObjects() {
globalThis.obj1 = {'a': Error};
globalThis.obj2 = {'b': Error.prototype};
}
const realm = Realm.create();
const {obj1, obj2} = takeAndUseWebSnapshot(
createObjects, ['obj1', 'obj2'], realm);
assertTrue(obj1.a === Realm.eval(realm, "Error"));
assertTrue(obj2.b === Realm.eval(realm, "Error.prototype"));
})();
......@@ -8,13 +8,14 @@ function use(exports) {
return result;
}
function takeAndUseWebSnapshot(createObjects, exports) {
function takeAndUseWebSnapshot(createObjects, exports, realmForDeserializing) {
// Take a snapshot in Realm r1.
const r1 = Realm.create();
Realm.eval(r1, createObjects, { type: 'function' });
const snapshot = Realm.takeWebSnapshot(r1, exports);
// Use the snapshot in Realm r2.
const r2 = Realm.create();
const r2 = realmForDeserializing != undefined ?
realmForDeserializing : Realm.create();
const success = Realm.useWebSnapshot(r2, snapshot);
assertTrue(success);
const result =
......
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