Line data Source code
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/contexts.h"
10 : #include "src/deoptimizer.h"
11 : #include "src/global-handles.h"
12 : #include "src/heap/heap-inl.h"
13 : #include "src/heap/read-only-heap.h"
14 : #include "src/objects-inl.h"
15 : #include "src/objects/foreign-inl.h"
16 : #include "src/objects/slots.h"
17 : #include "src/snapshot/read-only-serializer.h"
18 : #include "src/v8threads.h"
19 :
20 : namespace v8 {
21 : namespace internal {
22 :
23 261 : StartupSerializer::StartupSerializer(Isolate* isolate,
24 : ReadOnlySerializer* read_only_serializer)
25 : : RootsSerializer(isolate, RootIndex::kFirstStrongRoot),
26 261 : read_only_serializer_(read_only_serializer) {
27 261 : InitializeCodeAddressMap();
28 261 : }
29 :
30 522 : StartupSerializer::~StartupSerializer() {
31 261 : RestoreExternalReferenceRedirectors(accessor_infos_);
32 261 : RestoreExternalReferenceRedirectors(call_handler_infos_);
33 261 : OutputStatistics("StartupSerializer");
34 261 : }
35 :
36 : #ifdef DEBUG
37 : namespace {
38 :
39 : bool IsUnexpectedCodeObject(Isolate* isolate, HeapObject obj) {
40 : if (!obj->IsCode()) return false;
41 :
42 : Code code = Code::cast(obj);
43 :
44 : // TODO(v8:8768): Deopt entry code should not be serialized.
45 : if (code->kind() == Code::STUB && isolate->deoptimizer_data() != nullptr) {
46 : if (isolate->deoptimizer_data()->IsDeoptEntryCode(code)) return false;
47 : }
48 :
49 : if (code->kind() == Code::REGEXP) return false;
50 : if (!code->is_builtin()) return true;
51 : if (!FLAG_embedded_builtins) return false;
52 : if (code->is_off_heap_trampoline()) return false;
53 :
54 : // An on-heap builtin. We only expect this for the interpreter entry
55 : // trampoline copy stored on the root list and transitively called builtins.
56 : // See Heap::interpreter_entry_trampoline_for_profiling.
57 :
58 : switch (code->builtin_index()) {
59 : case Builtins::kAbort:
60 : case Builtins::kCEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit:
61 : case Builtins::kInterpreterEntryTrampoline:
62 : case Builtins::kRecordWrite:
63 : return false;
64 : default:
65 : return true;
66 : }
67 :
68 : UNREACHABLE();
69 : }
70 :
71 : } // namespace
72 : #endif // DEBUG
73 :
74 5176296 : void StartupSerializer::SerializeObject(HeapObject obj) {
75 : DCHECK(!obj->IsJSFunction());
76 : DCHECK(!IsUnexpectedCodeObject(isolate(), obj));
77 :
78 9204117 : if (SerializeHotObject(obj)) return;
79 3740411 : if (IsRootAndHasBeenSerialized(obj) && SerializeRoot(obj)) return;
80 3385836 : if (SerializeUsingReadOnlyObjectCache(&sink_, obj)) return;
81 1578376 : if (SerializeBackReference(obj)) return;
82 :
83 : bool use_simulator = false;
84 : #ifdef USE_SIMULATOR
85 : use_simulator = true;
86 : #endif
87 :
88 : if (use_simulator && obj->IsAccessorInfo()) {
89 : // Wipe external reference redirects in the accessor info.
90 : AccessorInfo info = AccessorInfo::cast(obj);
91 : Address original_address = Foreign::cast(info->getter())->foreign_address();
92 : Foreign::cast(info->js_getter())->set_foreign_address(original_address);
93 : accessor_infos_.push_back(info);
94 : } else if (use_simulator && obj->IsCallHandlerInfo()) {
95 : CallHandlerInfo info = CallHandlerInfo::cast(obj);
96 : Address original_address =
97 : Foreign::cast(info->callback())->foreign_address();
98 : Foreign::cast(info->js_callback())->set_foreign_address(original_address);
99 : call_handler_infos_.push_back(info);
100 1148475 : } else if (obj->IsScript() && Script::cast(obj)->IsUserJavaScript()) {
101 230 : Script::cast(obj)->set_context_data(
102 345 : ReadOnlyRoots(isolate()).uninitialized_symbol());
103 1148360 : } else if (obj->IsSharedFunctionInfo()) {
104 : // Clear inferred name for native functions.
105 178596 : SharedFunctionInfo shared = SharedFunctionInfo::cast(obj);
106 178596 : if (!shared->IsSubjectToDebugging() && shared->HasUncompiledData()) {
107 3708 : shared->uncompiled_data()->set_inferred_name(
108 1854 : ReadOnlyRoots(isolate()).empty_string());
109 : }
110 : }
111 :
112 1148475 : CheckRehashability(obj);
113 :
114 : // Object has not yet been serialized. Serialize it here.
115 : DCHECK(!ReadOnlyHeap::Contains(obj));
116 : ObjectSerializer object_serializer(this, obj, &sink_);
117 1148475 : object_serializer.Serialize();
118 : }
119 :
120 261 : void StartupSerializer::SerializeWeakReferencesAndDeferred() {
121 : // This comes right after serialization of the partial snapshot, where we
122 : // add entries to the partial snapshot cache of the startup snapshot. Add
123 : // one entry with 'undefined' to terminate the partial snapshot cache.
124 261 : Object undefined = ReadOnlyRoots(isolate()).undefined_value();
125 522 : VisitRootPointer(Root::kPartialSnapshotCache, nullptr,
126 522 : FullObjectSlot(&undefined));
127 261 : isolate()->heap()->IterateWeakRoots(this, VISIT_FOR_SERIALIZATION);
128 261 : SerializeDeferredObjects();
129 261 : Pad();
130 261 : }
131 :
132 261 : void StartupSerializer::SerializeStrongReferences() {
133 : Isolate* isolate = this->isolate();
134 : // No active threads.
135 261 : CHECK_NULL(isolate->thread_manager()->FirstThreadStateInUse());
136 : // No active or weak handles.
137 261 : CHECK(isolate->handle_scope_implementer()->blocks()->empty());
138 :
139 : // Visit smi roots.
140 : // Clear the stack limits to make the snapshot reproducible.
141 : // Reset it again afterwards.
142 261 : isolate->heap()->ClearStackLimits();
143 261 : isolate->heap()->IterateSmiRoots(this);
144 261 : isolate->heap()->SetStackLimits();
145 : // First visit immortal immovables to make sure they end up in the first page.
146 261 : isolate->heap()->IterateStrongRoots(this, VISIT_FOR_SERIALIZATION);
147 261 : }
148 :
149 196 : SerializedHandleChecker::SerializedHandleChecker(Isolate* isolate,
150 : std::vector<Context>* contexts)
151 392 : : isolate_(isolate) {
152 196 : AddToSet(isolate->heap()->serialized_objects());
153 427 : for (auto const& context : *contexts) {
154 231 : AddToSet(context->serialized_objects());
155 : }
156 196 : }
157 :
158 1050771 : bool StartupSerializer::SerializeUsingReadOnlyObjectCache(
159 : SnapshotByteSink* sink, HeapObject obj) {
160 2743689 : return read_only_serializer_->SerializeUsingReadOnlyObjectCache(sink, obj);
161 : }
162 :
163 502891 : void StartupSerializer::SerializeUsingPartialSnapshotCache(
164 : SnapshotByteSink* sink, HeapObject obj) {
165 502891 : int cache_index = SerializeInObjectCache(obj);
166 : sink->Put(kPartialSnapshotCache, "PartialSnapshotCache");
167 502891 : sink->PutInt(cache_index, "partial_snapshot_cache_index");
168 502891 : }
169 :
170 427 : void SerializedHandleChecker::AddToSet(FixedArray serialized) {
171 : int length = serialized->length();
172 682 : for (int i = 0; i < length; i++) serialized_.insert(serialized->get(i));
173 427 : }
174 :
175 20 : void SerializedHandleChecker::VisitRootPointers(Root root,
176 : const char* description,
177 : FullObjectSlot start,
178 : FullObjectSlot end) {
179 60 : for (FullObjectSlot p = start; p < end; ++p) {
180 40 : if (serialized_.find(*p) != serialized_.end()) continue;
181 0 : PrintF("%s handle not serialized: ",
182 0 : root == Root::kGlobalHandles ? "global" : "eternal");
183 0 : (*p)->Print();
184 0 : ok_ = false;
185 : }
186 20 : }
187 :
188 196 : bool SerializedHandleChecker::CheckGlobalAndEternalHandles() {
189 196 : isolate_->global_handles()->IterateAllRoots(this);
190 196 : isolate_->eternal_handles()->IterateAllRoots(this);
191 196 : return ok_;
192 : }
193 :
194 : } // namespace internal
195 121996 : } // namespace v8
|