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/startup-serializer.h"
15 
16 namespace v8 {
17 namespace internal {
18 
ReadOnlySerializer(Isolate * isolate)19 ReadOnlySerializer::ReadOnlySerializer(Isolate* isolate)
20     : RootsSerializer(isolate, RootIndex::kFirstReadOnlyRoot) {
21   STATIC_ASSERT(RootIndex::kFirstReadOnlyRoot == RootIndex::kFirstRoot);
22   allocator()->UseCustomChunkSize(FLAG_serialization_chunk_size);
23 }
24 
~ReadOnlySerializer()25 ReadOnlySerializer::~ReadOnlySerializer() {
26   OutputStatistics("ReadOnlySerializer");
27 }
28 
SerializeObject(HeapObject obj)29 void ReadOnlySerializer::SerializeObject(HeapObject obj) {
30   CHECK(ReadOnlyHeap::Contains(obj));
31   CHECK_IMPLIES(obj.IsString(), obj.IsInternalizedString());
32 
33   if (SerializeHotObject(obj)) return;
34   if (IsRootAndHasBeenSerialized(obj) && SerializeRoot(obj)) {
35     return;
36   }
37   if (SerializeBackReference(obj)) return;
38 
39   CheckRehashability(obj);
40 
41   // Object has not yet been serialized.  Serialize it here.
42   ObjectSerializer object_serializer(this, obj, &sink_);
43   object_serializer.Serialize();
44 #ifdef DEBUG
45   serialized_objects_.insert(obj);
46 #endif
47 }
48 
SerializeReadOnlyRoots()49 void ReadOnlySerializer::SerializeReadOnlyRoots() {
50   // No active threads.
51   CHECK_NULL(isolate()->thread_manager()->FirstThreadStateInUse());
52   // No active or weak handles.
53   CHECK(isolate()->handle_scope_implementer()->blocks()->empty());
54 
55   ReadOnlyRoots(isolate()).Iterate(this);
56 }
57 
FinalizeSerialization()58 void ReadOnlySerializer::FinalizeSerialization() {
59   // This comes right after serialization of the other snapshots, where we
60   // add entries to the read-only object cache. Add one entry with 'undefined'
61   // to terminate the read-only object cache.
62   Object undefined = ReadOnlyRoots(isolate()).undefined_value();
63   VisitRootPointer(Root::kReadOnlyObjectCache, nullptr,
64                    FullObjectSlot(&undefined));
65   SerializeDeferredObjects();
66   Pad();
67 
68 #ifdef DEBUG
69   // Check that every object on read-only heap is reachable (and was
70   // serialized).
71   ReadOnlyHeapObjectIterator iterator(isolate()->read_only_heap());
72   for (HeapObject object = iterator.Next(); !object.is_null();
73        object = iterator.Next()) {
74     CHECK(serialized_objects_.count(object));
75   }
76 #endif
77 }
78 
MustBeDeferred(HeapObject object)79 bool ReadOnlySerializer::MustBeDeferred(HeapObject object) {
80   if (root_has_been_serialized(RootIndex::kFreeSpaceMap) &&
81       root_has_been_serialized(RootIndex::kOnePointerFillerMap) &&
82       root_has_been_serialized(RootIndex::kTwoPointerFillerMap)) {
83     // All required root objects are serialized, so any aligned objects can
84     // be saved without problems.
85     return false;
86   }
87   // Just defer everything except for Map objects until all required roots are
88   // serialized. Some objects may have special alignment requirements, that may
89   // not be fulfilled during deserialization until few first root objects are
90   // serialized. But we must serialize Map objects since deserializer checks
91   // that these root objects are indeed Maps.
92   return !object.IsMap();
93 }
94 
SerializeUsingReadOnlyObjectCache(SnapshotByteSink * sink,HeapObject obj)95 bool ReadOnlySerializer::SerializeUsingReadOnlyObjectCache(
96     SnapshotByteSink* sink, HeapObject obj) {
97   if (!ReadOnlyHeap::Contains(obj)) return false;
98 
99   // Get the cache index and serialize it into the read-only snapshot if
100   // necessary.
101   int cache_index = SerializeInObjectCache(obj);
102 
103   // Writing out the cache entry into the calling serializer's sink.
104   sink->Put(kReadOnlyObjectCache, "ReadOnlyObjectCache");
105   sink->PutInt(cache_index, "read_only_object_cache_index");
106 
107   return true;
108 }
109 
110 }  // namespace internal
111 }  // namespace v8
112