5 #include "src/snapshot/partial-serializer.h" 6 #include "src/snapshot/startup-serializer.h" 8 #include "src/api-inl.h" 9 #include "src/math-random.h" 10 #include "src/microtask-queue.h" 11 #include "src/objects-inl.h" 12 #include "src/objects/slots.h" 17 PartialSerializer::PartialSerializer(
18 Isolate* isolate, StartupSerializer* startup_serializer,
19 v8::SerializeEmbedderFieldsCallback callback)
20 : Serializer(isolate),
21 startup_serializer_(startup_serializer),
22 serialize_embedder_fields_(callback),
23 can_be_rehashed_(true) {
24 InitializeCodeAddressMap();
25 allocator()->UseCustomChunkSize(FLAG_serialization_chunk_size);
28 PartialSerializer::~PartialSerializer() {
29 OutputStatistics(
"PartialSerializer");
32 void PartialSerializer::Serialize(Context* o,
bool include_global_proxy) {
34 DCHECK(context_->IsNativeContext());
35 reference_map()->AddAttachedReference(context_->global_proxy());
41 context_->set(Context::NEXT_CONTEXT_LINK,
42 ReadOnlyRoots(isolate()).undefined_value());
43 DCHECK(!context_->global_object()->IsUndefined());
45 MathRandom::ResetContext(context_);
47 DCHECK_EQ(0, context_->native_context()->microtask_queue()->size());
48 context_->native_context()->set_microtask_queue(
nullptr);
50 VisitRootPointer(Root::kPartialSnapshotCache,
nullptr, ObjectSlot(o));
51 SerializeDeferredObjects();
54 if (!embedder_fields_sink_.data()->empty()) {
55 sink_.Put(kEmbedderFieldsData,
"embedder fields data");
56 sink_.Append(embedder_fields_sink_);
57 sink_.Put(kSynchronize,
"Finished with embedder fields data");
63 void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
64 WhereToPoint where_to_point,
int skip) {
65 DCHECK(!ObjectIsBytecodeHandler(obj));
67 if (SerializeHotObject(obj, how_to_code, where_to_point, skip))
return;
69 if (SerializeRoot(obj, how_to_code, where_to_point, skip))
return;
71 if (SerializeBackReference(obj, how_to_code, where_to_point, skip))
return;
73 if (startup_serializer_->SerializeUsingReadOnlyObjectCache(
74 &sink_, obj, how_to_code, where_to_point, skip)) {
78 if (ShouldBeInThePartialSnapshotCache(obj)) {
79 startup_serializer_->SerializeUsingPartialSnapshotCache(
80 &sink_, obj, how_to_code, where_to_point, skip);
87 DCHECK(!startup_serializer_->ReferenceMapContains(obj));
90 DCHECK(!obj->IsInternalizedString());
92 DCHECK(!obj->IsTemplateInfo());
94 DCHECK_IMPLIES(obj != context_, !obj->IsNativeContext());
99 if (obj->IsFeedbackVector()) FeedbackVector::cast(obj)->ClearSlots(isolate());
101 if (SerializeJSObjectWithEmbedderFields(obj, how_to_code, where_to_point)) {
105 if (obj->IsJSFunction()) {
108 JSFunction* closure = JSFunction::cast(obj);
109 if (closure->is_compiled()) closure->set_code(closure->shared()->GetCode());
112 CheckRehashability(obj);
115 ObjectSerializer serializer(
this, obj, &sink_, how_to_code, where_to_point);
116 serializer.Serialize();
119 bool PartialSerializer::ShouldBeInThePartialSnapshotCache(HeapObject* o) {
124 DCHECK(!o->IsScript());
125 return o->IsName() || o->IsSharedFunctionInfo() || o->IsHeapNumber() ||
126 o->IsCode() || o->IsScopeInfo() || o->IsAccessorInfo() ||
127 o->IsTemplateInfo() ||
128 o->map() == ReadOnlyRoots(startup_serializer_->isolate())
129 .fixed_cow_array_map();
133 bool DataIsEmpty(
const StartupData& data) {
return data.raw_size == 0; }
136 bool PartialSerializer::SerializeJSObjectWithEmbedderFields(
137 Object* obj, HowToCode how_to_code, WhereToPoint where_to_point) {
138 if (!obj->IsJSObject())
return false;
139 JSObject* js_obj = JSObject::cast(obj);
140 int embedder_fields_count = js_obj->GetEmbedderFieldCount();
141 if (embedder_fields_count == 0)
return false;
142 CHECK_GT(embedder_fields_count, 0);
143 DCHECK_NOT_NULL(serialize_embedder_fields_.callback);
144 DCHECK(!js_obj->NeedsRehashing());
146 DisallowHeapAllocation no_gc;
147 DisallowJavascriptExecution no_js(isolate());
148 DisallowCompilation no_compile(isolate());
150 HandleScope scope(isolate());
151 Handle<JSObject> obj_handle(js_obj, isolate());
154 std::vector<EmbedderDataSlot::RawData> original_embedder_values;
155 std::vector<StartupData> serialized_data;
161 for (
int i = 0;
i < embedder_fields_count;
i++) {
162 EmbedderDataSlot embedder_data_slot(js_obj,
i);
163 original_embedder_values.emplace_back(embedder_data_slot.load_raw(no_gc));
164 Object*
object = embedder_data_slot.load_tagged();
165 if (object->IsHeapObject()) {
166 DCHECK(isolate()->heap()->Contains(HeapObject::cast(
object)));
167 serialized_data.push_back({
nullptr, 0});
169 StartupData data = serialize_embedder_fields_.callback(
170 api_obj,
i, serialize_embedder_fields_.data);
171 serialized_data.push_back(data);
180 for (
int i = 0;
i < embedder_fields_count;
i++) {
181 if (!DataIsEmpty(serialized_data[
i])) {
182 EmbedderDataSlot(js_obj,
i).store_raw({kNullAddress}, no_gc);
188 ObjectSerializer(
this, js_obj, &sink_, how_to_code, where_to_point)
192 SerializerReference reference = reference_map()->LookupReference(js_obj);
193 DCHECK(reference.is_back_reference());
197 for (
int i = 0;
i < embedder_fields_count;
i++) {
198 StartupData data = serialized_data[
i];
199 if (DataIsEmpty(data))
continue;
201 EmbedderDataSlot(js_obj,
i).store_raw(original_embedder_values[
i], no_gc);
202 embedder_fields_sink_.Put(kNewObject + reference.space(),
203 "embedder field holder");
204 embedder_fields_sink_.PutInt(reference.chunk_index(),
"BackRefChunkIndex");
205 embedder_fields_sink_.PutInt(reference.chunk_offset(),
206 "BackRefChunkOffset");
207 embedder_fields_sink_.PutInt(
i,
"embedder field index");
208 embedder_fields_sink_.PutInt(data.raw_size,
"embedder fields data size");
209 embedder_fields_sink_.PutRaw(reinterpret_cast<const byte*>(data.data),
210 data.raw_size,
"embedder fields data");
221 void PartialSerializer::CheckRehashability(HeapObject* obj) {
222 if (!can_be_rehashed_)
return;
223 if (!obj->NeedsRehashing())
return;
224 if (obj->CanBeRehashed())
return;
225 can_be_rehashed_ =
false;