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