// Copyright 2017 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. #include "src/snapshot/builtin-serializer.h" #include "src/objects-inl.h" #include "src/snapshot/startup-serializer.h" namespace v8 { namespace internal { BuiltinSerializer::BuiltinSerializer(Isolate* isolate, StartupSerializer* startup_serializer) : Serializer(isolate), startup_serializer_(startup_serializer) {} BuiltinSerializer::~BuiltinSerializer() { OutputStatistics("BuiltinSerializer"); } void BuiltinSerializer::SerializeBuiltins() { for (int i = 0; i < Builtins::builtin_count; i++) { builtin_offsets_[i] = sink_.Position(); SerializeBuiltin(isolate()->builtins()->builtin(i)); } Pad(); // Pad with kNop since GetInt() might read too far. // Append the offset table. During deserialization, the offset table is // extracted by BuiltinSnapshotData. const byte* data = reinterpret_cast(&builtin_offsets_[0]); int data_length = static_cast(sizeof(builtin_offsets_)); sink_.PutRaw(data, data_length, "BuiltinOffsets"); } void BuiltinSerializer::VisitRootPointers(Root root, Object** start, Object** end) { UNREACHABLE(); // We iterate manually in SerializeBuiltins. } void BuiltinSerializer::SerializeBuiltin(Code* code) { DCHECK_GE(code->builtin_index(), 0); // All builtins are serialized unconditionally when the respective builtin is // reached while iterating the builtins list. A builtin seen at any other // time (e.g. startup snapshot creation, or while iterating a builtin code // object during builtin serialization) is serialized by reference - see // BuiltinSerializer::SerializeObject below. ObjectSerializer object_serializer(this, code, &sink_, kPlain, kStartOfObject); object_serializer.Serialize(); } void BuiltinSerializer::SerializeObject(HeapObject* o, HowToCode how_to_code, WhereToPoint where_to_point, int skip) { DCHECK(!o->IsSmi()); // Roots can simply be serialized as root references. int root_index = root_index_map()->Lookup(o); if (root_index != RootIndexMap::kInvalidRootIndex) { DCHECK(startup_serializer_->root_has_been_serialized(root_index)); PutRoot(root_index, o, how_to_code, where_to_point, skip); return; } // Builtins are serialized using a dedicated bytecode. We only reach this // point if encountering a Builtin e.g. while iterating the body of another // builtin. if (SerializeBuiltinReference(o, how_to_code, where_to_point, skip)) return; // Embedded objects are serialized as part of the partial snapshot cache. // Currently we expect to see: // * Code: Jump targets. // * ByteArrays: Relocation infos. // * FixedArrays: Handler tables. // * Strings: CSA_ASSERTs in debug builds, various other string constants. // * HeapNumbers: Embedded constants. // TODO(6624): Jump targets should never trigger content serialization, it // should always result in a reference instead. Reloc infos and handler // tables should not end up in the partial snapshot cache. FlushSkip(skip); int cache_index = startup_serializer_->PartialSnapshotCacheIndex(o); sink_.Put(kPartialSnapshotCache + how_to_code + where_to_point, "PartialSnapshotCache"); sink_.PutInt(cache_index, "partial_snapshot_cache_index"); } } // namespace internal } // namespace v8