1// Copyright 2018 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "src/snapshot/read-only-serializer.h" 6 7#include "src/api/api.h" 8#include "src/diagnostics/code-tracer.h" 9#include "src/execution/v8threads.h" 10#include "src/handles/global-handles.h" 11#include "src/heap/read-only-heap.h" 12#include "src/objects/objects-inl.h" 13#include "src/objects/slots.h" 14#include "src/snapshot/serializer-inl.h" 15#include "src/snapshot/startup-serializer.h" 16 17namespace v8 { 18namespace internal { 19 20ReadOnlySerializer::ReadOnlySerializer(Isolate* isolate, 21 Snapshot::SerializerFlags flags) 22 : RootsSerializer(isolate, flags, RootIndex::kFirstReadOnlyRoot) 23#ifdef DEBUG 24 , 25 serialized_objects_(isolate->heap()), 26 did_serialize_not_mapped_symbol_(false) 27#endif 28{ 29 STATIC_ASSERT(RootIndex::kFirstReadOnlyRoot == RootIndex::kFirstRoot); 30} 31 32ReadOnlySerializer::~ReadOnlySerializer() { 33 OutputStatistics("ReadOnlySerializer"); 34} 35 36void ReadOnlySerializer::SerializeObjectImpl(Handle<HeapObject> obj) { 37 CHECK(ReadOnlyHeap::Contains(*obj)); 38 CHECK_IMPLIES(obj->IsString(), obj->IsInternalizedString()); 39 40 // There should be no references to the not_mapped_symbol except for the entry 41 // in the root table, so don't try to serialize a reference and rely on the 42 // below CHECK(!did_serialize_not_mapped_symbol_) to make sure it doesn't 43 // serialize twice. 44 { 45 DisallowGarbageCollection no_gc; 46 HeapObject raw = *obj; 47 if (!IsNotMappedSymbol(raw)) { 48 if (SerializeHotObject(raw)) return; 49 if (IsRootAndHasBeenSerialized(raw) && SerializeRoot(raw)) return; 50 if (SerializeBackReference(raw)) return; 51 } 52 53 CheckRehashability(raw); 54 } 55 56 // Object has not yet been serialized. Serialize it here. 57 ObjectSerializer object_serializer(this, obj, &sink_); 58 object_serializer.Serialize(); 59#ifdef DEBUG 60 if (IsNotMappedSymbol(*obj)) { 61 CHECK(!did_serialize_not_mapped_symbol_); 62 did_serialize_not_mapped_symbol_ = true; 63 } else { 64 CHECK_NULL(serialized_objects_.Find(obj)); 65 // There's no "IdentitySet", so use an IdentityMap with a value that is 66 // later ignored. 67 serialized_objects_.Insert(obj, 0); 68 } 69#endif 70} 71 72void ReadOnlySerializer::SerializeReadOnlyRoots() { 73 // No active threads. 74 CHECK_NULL(isolate()->thread_manager()->FirstThreadStateInUse()); 75 // No active or weak handles. 76 CHECK_IMPLIES(!allow_active_isolate_for_testing(), 77 isolate()->handle_scope_implementer()->blocks()->empty()); 78 79 ReadOnlyRoots(isolate()).Iterate(this); 80 81 if (reconstruct_read_only_and_shared_object_caches_for_testing()) { 82 ReconstructReadOnlyObjectCacheForTesting(); 83 } 84} 85 86void ReadOnlySerializer::FinalizeSerialization() { 87 // This comes right after serialization of the other snapshots, where we 88 // add entries to the read-only object cache. Add one entry with 'undefined' 89 // to terminate the read-only object cache. 90 Object undefined = ReadOnlyRoots(isolate()).undefined_value(); 91 VisitRootPointer(Root::kReadOnlyObjectCache, nullptr, 92 FullObjectSlot(&undefined)); 93 SerializeDeferredObjects(); 94 Pad(); 95 96#ifdef DEBUG 97 // Check that every object on read-only heap is reachable (and was 98 // serialized). 99 ReadOnlyHeapObjectIterator iterator(isolate()->read_only_heap()); 100 for (HeapObject object = iterator.Next(); !object.is_null(); 101 object = iterator.Next()) { 102 if (IsNotMappedSymbol(object)) { 103 CHECK(did_serialize_not_mapped_symbol_); 104 } else { 105 CHECK_NOT_NULL(serialized_objects_.Find(object)); 106 } 107 } 108#endif 109} 110 111bool ReadOnlySerializer::MustBeDeferred(HeapObject object) { 112 if (root_has_been_serialized(RootIndex::kFreeSpaceMap) && 113 root_has_been_serialized(RootIndex::kOnePointerFillerMap) && 114 root_has_been_serialized(RootIndex::kTwoPointerFillerMap)) { 115 // All required root objects are serialized, so any aligned objects can 116 // be saved without problems. 117 return false; 118 } 119 // Defer objects with special alignment requirements until the filler roots 120 // are serialized. 121 return HeapObject::RequiredAlignment(object.map()) != kTaggedAligned; 122} 123 124bool ReadOnlySerializer::SerializeUsingReadOnlyObjectCache( 125 SnapshotByteSink* sink, Handle<HeapObject> obj) { 126 if (!ReadOnlyHeap::Contains(*obj)) return false; 127 128 // Get the cache index and serialize it into the read-only snapshot if 129 // necessary. 130 int cache_index = SerializeInObjectCache(obj); 131 132 // Writing out the cache entry into the calling serializer's sink. 133 sink->Put(kReadOnlyObjectCache, "ReadOnlyObjectCache"); 134 sink->PutInt(cache_index, "read_only_object_cache_index"); 135 136 return true; 137} 138 139void ReadOnlySerializer::ReconstructReadOnlyObjectCacheForTesting() { 140 ReadOnlyHeap* ro_heap = isolate()->read_only_heap(); 141 DCHECK(ro_heap->read_only_object_cache_is_initialized()); 142 for (size_t i = 0, size = ro_heap->read_only_object_cache_size(); i < size; 143 i++) { 144 Handle<HeapObject> obj( 145 HeapObject::cast(ro_heap->cached_read_only_object(i)), isolate()); 146 int cache_index = SerializeInObjectCache(obj); 147 USE(cache_index); 148 DCHECK_EQ(cache_index, i); 149 } 150} 151 152} // namespace internal 153} // namespace v8 154