1 // Copyright 2016 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/startup-serializer.h"
6 
7 #include "src/api.h"
8 #include "src/code-tracer.h"
9 #include "src/global-handles.h"
10 #include "src/objects-inl.h"
11 #include "src/v8threads.h"
12 
13 namespace v8 {
14 namespace internal {
15 
StartupSerializer(Isolate * isolate)16 StartupSerializer::StartupSerializer(Isolate* isolate)
17     : Serializer(isolate), can_be_rehashed_(true) {
18   InitializeCodeAddressMap();
19 }
20 
~StartupSerializer()21 StartupSerializer::~StartupSerializer() {
22   RestoreExternalReferenceRedirectors(accessor_infos_);
23   RestoreExternalReferenceRedirectors(call_handler_infos_);
24   OutputStatistics("StartupSerializer");
25 }
26 
SerializeObject(HeapObject * obj,HowToCode how_to_code,WhereToPoint where_to_point,int skip)27 void StartupSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
28                                         WhereToPoint where_to_point, int skip) {
29   DCHECK(!ObjectIsBytecodeHandler(obj));  // Only referenced in dispatch table.
30   DCHECK(!obj->IsJSFunction());
31 
32   if (SerializeBuiltinReference(obj, how_to_code, where_to_point, skip)) {
33     return;
34   }
35   if (SerializeHotObject(obj, how_to_code, where_to_point, skip)) return;
36 
37   int root_index = root_index_map()->Lookup(obj);
38   // We can only encode roots as such if it has already been serialized.
39   // That applies to root indices below the wave front.
40   if (root_index != RootIndexMap::kInvalidRootIndex) {
41     if (root_has_been_serialized(root_index)) {
42       PutRoot(root_index, obj, how_to_code, where_to_point, skip);
43       return;
44     }
45   }
46 
47   if (SerializeBackReference(obj, how_to_code, where_to_point, skip)) return;
48 
49   FlushSkip(skip);
50   bool use_simulator = false;
51 #ifdef USE_SIMULATOR
52   use_simulator = true;
53 #endif
54 
55   if (use_simulator && obj->IsAccessorInfo()) {
56     // Wipe external reference redirects in the accessor info.
57     AccessorInfo* info = AccessorInfo::cast(obj);
58     Address original_address = Foreign::cast(info->getter())->foreign_address();
59     Foreign::cast(info->js_getter())->set_foreign_address(original_address);
60     accessor_infos_.push_back(info);
61   } else if (use_simulator && obj->IsCallHandlerInfo()) {
62     CallHandlerInfo* info = CallHandlerInfo::cast(obj);
63     Address original_address =
64         Foreign::cast(info->callback())->foreign_address();
65     Foreign::cast(info->js_callback())->set_foreign_address(original_address);
66     call_handler_infos_.push_back(info);
67   } else if (obj->IsScript() && Script::cast(obj)->IsUserJavaScript()) {
68     Script::cast(obj)->set_context_data(
69         ReadOnlyRoots(isolate()).uninitialized_symbol());
70   } else if (obj->IsSharedFunctionInfo()) {
71     // Clear inferred name for native functions.
72     SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
73     if (!shared->IsSubjectToDebugging() && shared->HasUncompiledData()) {
74       shared->uncompiled_data()->set_inferred_name(
75           ReadOnlyRoots(isolate()).empty_string());
76     }
77   }
78 
79   CheckRehashability(obj);
80 
81   // Object has not yet been serialized.  Serialize it here.
82   ObjectSerializer object_serializer(this, obj, &sink_, how_to_code,
83                                      where_to_point);
84   object_serializer.Serialize();
85 }
86 
SerializeWeakReferencesAndDeferred()87 void StartupSerializer::SerializeWeakReferencesAndDeferred() {
88   // This comes right after serialization of the partial snapshot, where we
89   // add entries to the partial snapshot cache of the startup snapshot. Add
90   // one entry with 'undefined' to terminate the partial snapshot cache.
91   Object* undefined = ReadOnlyRoots(isolate()).undefined_value();
92   VisitRootPointer(Root::kPartialSnapshotCache, nullptr, &undefined);
93   isolate()->heap()->IterateWeakRoots(this, VISIT_FOR_SERIALIZATION);
94   SerializeDeferredObjects();
95   Pad();
96 }
97 
PartialSnapshotCacheIndex(HeapObject * heap_object)98 int StartupSerializer::PartialSnapshotCacheIndex(HeapObject* heap_object) {
99   int index;
100   if (!partial_cache_index_map_.LookupOrInsert(heap_object, &index)) {
101     // This object is not part of the partial snapshot cache yet. Add it to the
102     // startup snapshot so we can refer to it via partial snapshot index from
103     // the partial snapshot.
104     VisitRootPointer(Root::kPartialSnapshotCache, nullptr,
105                      reinterpret_cast<Object**>(&heap_object));
106   }
107   return index;
108 }
109 
Synchronize(VisitorSynchronization::SyncTag tag)110 void StartupSerializer::Synchronize(VisitorSynchronization::SyncTag tag) {
111   sink_.Put(kSynchronize, "Synchronize");
112 }
113 
SerializeStrongReferences()114 void StartupSerializer::SerializeStrongReferences() {
115   Isolate* isolate = this->isolate();
116   // No active threads.
117   CHECK_NULL(isolate->thread_manager()->FirstThreadStateInUse());
118   // No active or weak handles.
119   CHECK(isolate->handle_scope_implementer()->blocks()->empty());
120 
121   // Visit smi roots.
122   // Clear the stack limits to make the snapshot reproducible.
123   // Reset it again afterwards.
124   isolate->heap()->ClearStackLimits();
125   isolate->heap()->IterateSmiRoots(this);
126   isolate->heap()->SetStackLimits();
127   // First visit immortal immovables to make sure they end up in the first page.
128   isolate->heap()->IterateStrongRoots(this, VISIT_FOR_SERIALIZATION);
129 }
130 
VisitRootPointers(Root root,const char * description,Object ** start,Object ** end)131 void StartupSerializer::VisitRootPointers(Root root, const char* description,
132                                           Object** start, Object** end) {
133   if (start == isolate()->heap()->roots_array_start()) {
134     // Serializing the root list needs special handling:
135     // - Only root list elements that have been fully serialized can be
136     //   referenced using kRootArray bytecodes.
137     for (Object** current = start; current < end; current++) {
138       SerializeRootObject(*current);
139       int root_index = static_cast<int>(current - start);
140       root_has_been_serialized_.set(root_index);
141     }
142   } else {
143     Serializer::VisitRootPointers(root, description, start, end);
144   }
145 }
146 
CheckRehashability(HeapObject * obj)147 void StartupSerializer::CheckRehashability(HeapObject* obj) {
148   if (!can_be_rehashed_) return;
149   if (!obj->NeedsRehashing()) return;
150   if (obj->CanBeRehashed()) return;
151   can_be_rehashed_ = false;
152 }
153 
MustBeDeferred(HeapObject * object)154 bool StartupSerializer::MustBeDeferred(HeapObject* object) {
155   if (root_has_been_serialized_.test(Heap::kFreeSpaceMapRootIndex) &&
156       root_has_been_serialized_.test(Heap::kOnePointerFillerMapRootIndex) &&
157       root_has_been_serialized_.test(Heap::kTwoPointerFillerMapRootIndex)) {
158     // All required root objects are serialized, so any aligned objects can
159     // be saved without problems.
160     return false;
161   }
162   // Just defer everything except of Map objects until all required roots are
163   // serialized. Some objects may have special alignment requirements, that may
164   // not be fulfilled during deserialization until few first root objects are
165   // serialized. But we must serialize Map objects since deserializer checks
166   // that these root objects are indeed Maps.
167   return !object->IsMap();
168 }
169 
SerializedHandleChecker(Isolate * isolate,std::vector<Context * > * contexts)170 SerializedHandleChecker::SerializedHandleChecker(
171     Isolate* isolate, std::vector<Context*>* contexts)
172     : isolate_(isolate) {
173   AddToSet(isolate->heap()->serialized_objects());
174   for (auto const& context : *contexts) {
175     AddToSet(context->serialized_objects());
176   }
177 }
178 
AddToSet(FixedArray * serialized)179 void SerializedHandleChecker::AddToSet(FixedArray* serialized) {
180   int length = serialized->length();
181   for (int i = 0; i < length; i++) serialized_.insert(serialized->get(i));
182 }
183 
VisitRootPointers(Root root,const char * description,Object ** start,Object ** end)184 void SerializedHandleChecker::VisitRootPointers(Root root,
185                                                 const char* description,
186                                                 Object** start, Object** end) {
187   for (Object** p = start; p < end; p++) {
188     if (serialized_.find(*p) != serialized_.end()) continue;
189     PrintF("%s handle not serialized: ",
190            root == Root::kGlobalHandles ? "global" : "eternal");
191     (*p)->Print();
192     ok_ = false;
193   }
194 }
195 
CheckGlobalAndEternalHandles()196 bool SerializedHandleChecker::CheckGlobalAndEternalHandles() {
197   isolate_->global_handles()->IterateAllRoots(this);
198   isolate_->eternal_handles()->IterateAllRoots(this);
199   return ok_;
200 }
201 
202 }  // namespace internal
203 }  // namespace v8
204