| // Copyright 2018 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/read-only-serializer.h" |
| |
| #include "src/api/api.h" |
| #include "src/diagnostics/code-tracer.h" |
| #include "src/execution/v8threads.h" |
| #include "src/handles/global-handles.h" |
| #include "src/heap/read-only-heap.h" |
| #include "src/objects/objects-inl.h" |
| #include "src/objects/slots.h" |
| #include "src/snapshot/startup-serializer.h" |
| |
| namespace v8 { |
| namespace internal { |
| |
| ReadOnlySerializer::ReadOnlySerializer(Isolate* isolate, |
| Snapshot::SerializerFlags flags) |
| : RootsSerializer(isolate, flags, RootIndex::kFirstReadOnlyRoot) |
| #ifdef DEBUG |
| , |
| serialized_objects_(isolate->heap()), |
| did_serialize_not_mapped_symbol_(false) |
| #endif |
| { |
| STATIC_ASSERT(RootIndex::kFirstReadOnlyRoot == RootIndex::kFirstRoot); |
| } |
| |
| ReadOnlySerializer::~ReadOnlySerializer() { |
| OutputStatistics("ReadOnlySerializer"); |
| } |
| |
| void ReadOnlySerializer::SerializeObjectImpl(Handle<HeapObject> obj) { |
| CHECK(ReadOnlyHeap::Contains(*obj)); |
| CHECK_IMPLIES(obj->IsString(), obj->IsInternalizedString()); |
| |
| // There should be no references to the not_mapped_symbol except for the entry |
| // in the root table, so don't try to serialize a reference and rely on the |
| // below CHECK(!did_serialize_not_mapped_symbol_) to make sure it doesn't |
| // serialize twice. |
| if (*obj != ReadOnlyRoots(isolate()).not_mapped_symbol()) { |
| if (SerializeHotObject(obj)) return; |
| if (IsRootAndHasBeenSerialized(*obj) && SerializeRoot(obj)) { |
| return; |
| } |
| if (SerializeBackReference(obj)) return; |
| } |
| |
| CheckRehashability(*obj); |
| |
| // Object has not yet been serialized. Serialize it here. |
| ObjectSerializer object_serializer(this, obj, &sink_); |
| object_serializer.Serialize(); |
| #ifdef DEBUG |
| if (*obj == ReadOnlyRoots(isolate()).not_mapped_symbol()) { |
| CHECK(!did_serialize_not_mapped_symbol_); |
| did_serialize_not_mapped_symbol_ = true; |
| } else { |
| CHECK_NULL(serialized_objects_.Find(obj)); |
| // There's no "IdentitySet", so use an IdentityMap with a value that is |
| // later ignored. |
| serialized_objects_.Insert(obj, 0); |
| } |
| #endif |
| } |
| |
| void ReadOnlySerializer::SerializeReadOnlyRoots() { |
| // No active threads. |
| CHECK_NULL(isolate()->thread_manager()->FirstThreadStateInUse()); |
| // No active or weak handles. |
| CHECK_IMPLIES(!allow_active_isolate_for_testing(), |
| isolate()->handle_scope_implementer()->blocks()->empty()); |
| |
| ReadOnlyRoots(isolate()).Iterate(this); |
| } |
| |
| void ReadOnlySerializer::FinalizeSerialization() { |
| // This comes right after serialization of the other snapshots, where we |
| // add entries to the read-only object cache. Add one entry with 'undefined' |
| // to terminate the read-only object cache. |
| Object undefined = ReadOnlyRoots(isolate()).undefined_value(); |
| VisitRootPointer(Root::kReadOnlyObjectCache, nullptr, |
| FullObjectSlot(&undefined)); |
| SerializeDeferredObjects(); |
| Pad(); |
| |
| #ifdef DEBUG |
| // Check that every object on read-only heap is reachable (and was |
| // serialized). |
| ReadOnlyHeapObjectIterator iterator(isolate()->read_only_heap()); |
| for (HeapObject object = iterator.Next(); !object.is_null(); |
| object = iterator.Next()) { |
| if (object == ReadOnlyRoots(isolate()).not_mapped_symbol()) { |
| CHECK(did_serialize_not_mapped_symbol_); |
| } else { |
| CHECK_NOT_NULL(serialized_objects_.Find(object)); |
| } |
| } |
| #endif |
| } |
| |
| bool ReadOnlySerializer::MustBeDeferred(HeapObject object) { |
| if (root_has_been_serialized(RootIndex::kFreeSpaceMap) && |
| root_has_been_serialized(RootIndex::kOnePointerFillerMap) && |
| root_has_been_serialized(RootIndex::kTwoPointerFillerMap)) { |
| // All required root objects are serialized, so any aligned objects can |
| // be saved without problems. |
| return false; |
| } |
| // Defer objects with special alignment requirements until the filler roots |
| // are serialized. |
| return HeapObject::RequiredAlignment(object.map()) != kWordAligned; |
| } |
| |
| bool ReadOnlySerializer::SerializeUsingReadOnlyObjectCache( |
| SnapshotByteSink* sink, Handle<HeapObject> obj) { |
| if (!ReadOnlyHeap::Contains(*obj)) return false; |
| |
| // Get the cache index and serialize it into the read-only snapshot if |
| // necessary. |
| int cache_index = SerializeInObjectCache(obj); |
| |
| // Writing out the cache entry into the calling serializer's sink. |
| sink->Put(kReadOnlyObjectCache, "ReadOnlyObjectCache"); |
| sink->PutInt(cache_index, "read_only_object_cache_index"); |
| |
| return true; |
| } |
| |
| } // namespace internal |
| } // namespace v8 |