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
17 namespace v8 {
18 namespace internal {
19
ReadOnlySerializer(Isolate * isolate,Snapshot::SerializerFlags flags)20 ReadOnlySerializer::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
~ReadOnlySerializer()32 ReadOnlySerializer::~ReadOnlySerializer() {
33 OutputStatistics("ReadOnlySerializer");
34 }
35
SerializeObjectImpl(Handle<HeapObject> obj)36 void 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
SerializeReadOnlyRoots()72 void 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
FinalizeSerialization()86 void 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
MustBeDeferred(HeapObject object)111 bool 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
SerializeUsingReadOnlyObjectCache(SnapshotByteSink * sink,Handle<HeapObject> obj)124 bool 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
ReconstructReadOnlyObjectCacheForTesting()139 void 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