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/global-handles.h"
11 : #include "src/objects-inl.h"
12 : #include "src/objects/foreign-inl.h"
13 : #include "src/objects/slots.h"
14 : #include "src/snapshot/read-only-serializer.h"
15 : #include "src/v8threads.h"
16 :
17 : namespace v8 {
18 : namespace internal {
19 :
20 251 : StartupSerializer::StartupSerializer(Isolate* isolate,
21 : ReadOnlySerializer* read_only_serializer)
22 : : RootsSerializer(isolate, RootIndex::kFirstStrongRoot),
23 251 : read_only_serializer_(read_only_serializer) {
24 251 : InitializeCodeAddressMap();
25 251 : }
26 :
27 251 : StartupSerializer::~StartupSerializer() {
28 251 : RestoreExternalReferenceRedirectors(accessor_infos_);
29 251 : RestoreExternalReferenceRedirectors(call_handler_infos_);
30 251 : OutputStatistics("StartupSerializer");
31 251 : }
32 :
33 : namespace {
34 :
35 : // Due to how we currently create the embedded blob, we may encounter both
36 : // off-heap trampolines and old, outdated full Code objects during
37 : // serialization. This ensures that we only serialize the canonical version of
38 : // each builtin.
39 : // See also CreateOffHeapTrampolines().
40 4944775 : HeapObject MaybeCanonicalizeBuiltin(Isolate* isolate, HeapObject obj) {
41 4944775 : if (!obj->IsCode()) return obj;
42 :
43 : const int builtin_index = Code::cast(obj)->builtin_index();
44 481550 : if (!Builtins::IsBuiltinId(builtin_index)) return obj;
45 :
46 481522 : return isolate->builtins()->builtin(builtin_index);
47 : }
48 :
49 : } // namespace
50 :
51 4944775 : void StartupSerializer::SerializeObject(HeapObject obj, HowToCode how_to_code,
52 : WhereToPoint where_to_point, int skip) {
53 : DCHECK(!obj->IsJSFunction());
54 :
55 : // TODO(jgruber): Remove canonicalization once off-heap trampoline creation
56 : // moves to Isolate::Init().
57 4946649 : obj = MaybeCanonicalizeBuiltin(isolate(), obj);
58 :
59 8790912 : if (SerializeHotObject(obj, how_to_code, where_to_point, skip)) return;
60 5536104 : if (IsRootAndHasBeenSerialized(obj) &&
61 1959949 : SerializeRoot(obj, how_to_code, where_to_point, skip))
62 : return;
63 1616206 : if (SerializeUsingReadOnlyObjectCache(&sink_, obj, how_to_code,
64 1616206 : where_to_point, skip))
65 : return;
66 1507732 : if (SerializeBackReference(obj, how_to_code, where_to_point, skip)) return;
67 :
68 : FlushSkip(skip);
69 : bool use_simulator = false;
70 : #ifdef USE_SIMULATOR
71 : use_simulator = true;
72 : #endif
73 :
74 : if (use_simulator && obj->IsAccessorInfo()) {
75 : // Wipe external reference redirects in the accessor info.
76 : AccessorInfo info = AccessorInfo::cast(obj);
77 : Address original_address = Foreign::cast(info->getter())->foreign_address();
78 : Foreign::cast(info->js_getter())->set_foreign_address(original_address);
79 : accessor_infos_.push_back(info);
80 : } else if (use_simulator && obj->IsCallHandlerInfo()) {
81 : CallHandlerInfo info = CallHandlerInfo::cast(obj);
82 : Address original_address =
83 : Foreign::cast(info->callback())->foreign_address();
84 : Foreign::cast(info->js_callback())->set_foreign_address(original_address);
85 : call_handler_infos_.push_back(info);
86 1099391 : } else if (obj->IsScript() && Script::cast(obj)->IsUserJavaScript()) {
87 : Script::cast(obj)->set_context_data(
88 220 : ReadOnlyRoots(isolate()).uninitialized_symbol());
89 1098528 : } else if (obj->IsSharedFunctionInfo()) {
90 : // Clear inferred name for native functions.
91 169999 : SharedFunctionInfo shared = SharedFunctionInfo::cast(obj);
92 169999 : if (!shared->IsSubjectToDebugging() && shared->HasUncompiledData()) {
93 : shared->uncompiled_data()->set_inferred_name(
94 1764 : ReadOnlyRoots(isolate()).empty_string());
95 : }
96 : }
97 :
98 1098638 : CheckRehashability(obj);
99 :
100 : // Object has not yet been serialized. Serialize it here.
101 : DCHECK(!isolate()->heap()->read_only_space()->Contains(obj));
102 : ObjectSerializer object_serializer(this, obj, &sink_, how_to_code,
103 : where_to_point);
104 1098638 : object_serializer.Serialize();
105 : }
106 :
107 251 : void StartupSerializer::SerializeWeakReferencesAndDeferred() {
108 : // This comes right after serialization of the partial snapshot, where we
109 : // add entries to the partial snapshot cache of the startup snapshot. Add
110 : // one entry with 'undefined' to terminate the partial snapshot cache.
111 753 : Object undefined = ReadOnlyRoots(isolate()).undefined_value();
112 : VisitRootPointer(Root::kPartialSnapshotCache, nullptr,
113 502 : FullObjectSlot(&undefined));
114 251 : isolate()->heap()->IterateWeakRoots(this, VISIT_FOR_SERIALIZATION);
115 251 : SerializeDeferredObjects();
116 251 : Pad();
117 251 : }
118 :
119 251 : void StartupSerializer::SerializeStrongReferences() {
120 502 : Isolate* isolate = this->isolate();
121 : // No active threads.
122 251 : CHECK_NULL(isolate->thread_manager()->FirstThreadStateInUse());
123 : // No active or weak handles.
124 251 : CHECK(isolate->handle_scope_implementer()->blocks()->empty());
125 :
126 : // Visit smi roots.
127 : // Clear the stack limits to make the snapshot reproducible.
128 : // Reset it again afterwards.
129 251 : isolate->heap()->ClearStackLimits();
130 251 : isolate->heap()->IterateSmiRoots(this);
131 251 : isolate->heap()->SetStackLimits();
132 : // First visit immortal immovables to make sure they end up in the first page.
133 251 : isolate->heap()->IterateStrongRoots(this, VISIT_FOR_SERIALIZATION);
134 251 : }
135 :
136 186 : SerializedHandleChecker::SerializedHandleChecker(Isolate* isolate,
137 : std::vector<Context>* contexts)
138 372 : : isolate_(isolate) {
139 186 : AddToSet(isolate->heap()->serialized_objects());
140 593 : for (auto const& context : *contexts) {
141 221 : AddToSet(context->serialized_objects());
142 : }
143 186 : }
144 :
145 997802 : bool StartupSerializer::SerializeUsingReadOnlyObjectCache(
146 : SnapshotByteSink* sink, HeapObject obj, HowToCode how_to_code,
147 : WhereToPoint where_to_point, int skip) {
148 : return read_only_serializer_->SerializeUsingReadOnlyObjectCache(
149 2614008 : sink, obj, how_to_code, where_to_point, skip);
150 : }
151 :
152 481210 : void StartupSerializer::SerializeUsingPartialSnapshotCache(
153 : SnapshotByteSink* sink, HeapObject obj, HowToCode how_to_code,
154 : WhereToPoint where_to_point, int skip) {
155 481210 : FlushSkip(sink, skip);
156 :
157 481210 : int cache_index = SerializeInObjectCache(obj);
158 : sink->Put(kPartialSnapshotCache + how_to_code + where_to_point,
159 481210 : "PartialSnapshotCache");
160 481210 : sink->PutInt(cache_index, "partial_snapshot_cache_index");
161 481210 : }
162 :
163 407 : void SerializedHandleChecker::AddToSet(FixedArray serialized) {
164 : int length = serialized->length();
165 577 : for (int i = 0; i < length; i++) serialized_.insert(serialized->get(i));
166 407 : }
167 :
168 20 : void SerializedHandleChecker::VisitRootPointers(Root root,
169 : const char* description,
170 : FullObjectSlot start,
171 : FullObjectSlot end) {
172 60 : for (FullObjectSlot p = start; p < end; ++p) {
173 40 : if (serialized_.find(*p) != serialized_.end()) continue;
174 : PrintF("%s handle not serialized: ",
175 0 : root == Root::kGlobalHandles ? "global" : "eternal");
176 0 : (*p)->Print();
177 0 : ok_ = false;
178 : }
179 20 : }
180 :
181 186 : bool SerializedHandleChecker::CheckGlobalAndEternalHandles() {
182 372 : isolate_->global_handles()->IterateAllRoots(this);
183 372 : isolate_->eternal_handles()->IterateAllRoots(this);
184 186 : return ok_;
185 : }
186 :
187 : } // namespace internal
188 183867 : } // namespace v8
|