1 // Copyright 2017 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/object-deserializer.h"
6
7 #include "src/codegen/assembler-inl.h"
8 #include "src/execution/isolate.h"
9 #include "src/heap/heap-inl.h"
10 #include "src/heap/local-factory-inl.h"
11 #include "src/objects/allocation-site-inl.h"
12 #include "src/objects/js-array-buffer-inl.h"
13 #include "src/objects/objects.h"
14 #include "src/objects/slots.h"
15 #include "src/snapshot/code-serializer.h"
16
17 namespace v8 {
18 namespace internal {
19
ObjectDeserializer(Isolate * isolate,const SerializedCodeData * data)20 ObjectDeserializer::ObjectDeserializer(Isolate* isolate,
21 const SerializedCodeData* data)
22 : Deserializer(isolate, data->Payload(), data->GetMagicNumber(), true,
23 false) {}
24
25 MaybeHandle<SharedFunctionInfo>
DeserializeSharedFunctionInfo(Isolate * isolate,const SerializedCodeData * data,Handle<String> source)26 ObjectDeserializer::DeserializeSharedFunctionInfo(
27 Isolate* isolate, const SerializedCodeData* data, Handle<String> source) {
28 ObjectDeserializer d(isolate, data);
29
30 d.AddAttachedObject(source);
31
32 Handle<HeapObject> result;
33 return d.Deserialize().ToHandle(&result)
34 ? Handle<SharedFunctionInfo>::cast(result)
35 : MaybeHandle<SharedFunctionInfo>();
36 }
37
Deserialize()38 MaybeHandle<HeapObject> ObjectDeserializer::Deserialize() {
39 DCHECK(deserializing_user_code());
40 HandleScope scope(isolate());
41 Handle<HeapObject> result;
42 {
43 result = ReadObject();
44 DeserializeDeferredObjects();
45 CHECK(new_code_objects().empty());
46 LinkAllocationSites();
47 CHECK(new_maps().empty());
48 WeakenDescriptorArrays();
49 }
50
51 Rehash();
52 CommitPostProcessedObjects();
53 return scope.CloseAndEscape(result);
54 }
55
CommitPostProcessedObjects()56 void ObjectDeserializer::CommitPostProcessedObjects() {
57 for (Handle<JSArrayBuffer> buffer : new_off_heap_array_buffers()) {
58 uint32_t store_index = buffer->GetBackingStoreRefForDeserialization();
59 auto bs = backing_store(store_index);
60 SharedFlag shared =
61 bs && bs->is_shared() ? SharedFlag::kShared : SharedFlag::kNotShared;
62 // TODO(v8:11111): Support RAB / GSAB.
63 CHECK(!bs || !bs->is_resizable());
64 buffer->Setup(shared, ResizableFlag::kNotResizable, bs);
65 }
66
67 for (Handle<Script> script : new_scripts()) {
68 // Assign a new script id to avoid collision.
69 script->set_id(isolate()->GetNextScriptId());
70 LogScriptEvents(*script);
71 // Add script to list.
72 Handle<WeakArrayList> list = isolate()->factory()->script_list();
73 list = WeakArrayList::AddToEnd(isolate(), list,
74 MaybeObjectHandle::Weak(script));
75 isolate()->heap()->SetRootScriptList(*list);
76 }
77 }
78
LinkAllocationSites()79 void ObjectDeserializer::LinkAllocationSites() {
80 DisallowGarbageCollection no_gc;
81 Heap* heap = isolate()->heap();
82 // Allocation sites are present in the snapshot, and must be linked into
83 // a list at deserialization time.
84 for (Handle<AllocationSite> site : new_allocation_sites()) {
85 if (!site->HasWeakNext()) continue;
86 // TODO(mvstanton): consider treating the heap()->allocation_sites_list()
87 // as a (weak) root. If this root is relocated correctly, this becomes
88 // unnecessary.
89 if (heap->allocation_sites_list() == Smi::zero()) {
90 site->set_weak_next(ReadOnlyRoots(heap).undefined_value());
91 } else {
92 site->set_weak_next(heap->allocation_sites_list());
93 }
94 heap->set_allocation_sites_list(*site);
95 }
96 }
97
OffThreadObjectDeserializer(LocalIsolate * isolate,const SerializedCodeData * data)98 OffThreadObjectDeserializer::OffThreadObjectDeserializer(
99 LocalIsolate* isolate, const SerializedCodeData* data)
100 : Deserializer(isolate, data->Payload(), data->GetMagicNumber(), true,
101 false) {}
102
103 MaybeHandle<SharedFunctionInfo>
DeserializeSharedFunctionInfo(LocalIsolate * isolate,const SerializedCodeData * data,std::vector<Handle<Script>> * deserialized_scripts)104 OffThreadObjectDeserializer::DeserializeSharedFunctionInfo(
105 LocalIsolate* isolate, const SerializedCodeData* data,
106 std::vector<Handle<Script>>* deserialized_scripts) {
107 OffThreadObjectDeserializer d(isolate, data);
108
109 // Attach the empty string as the source.
110 d.AddAttachedObject(isolate->factory()->empty_string());
111
112 Handle<HeapObject> result;
113 if (!d.Deserialize(deserialized_scripts).ToHandle(&result)) {
114 return MaybeHandle<SharedFunctionInfo>();
115 }
116 return Handle<SharedFunctionInfo>::cast(result);
117 }
118
Deserialize(std::vector<Handle<Script>> * deserialized_scripts)119 MaybeHandle<HeapObject> OffThreadObjectDeserializer::Deserialize(
120 std::vector<Handle<Script>>* deserialized_scripts) {
121 DCHECK(deserializing_user_code());
122 LocalHandleScope scope(isolate());
123 Handle<HeapObject> result;
124 {
125 result = ReadObject();
126 DeserializeDeferredObjects();
127 CHECK(new_code_objects().empty());
128 CHECK(new_allocation_sites().empty());
129 CHECK(new_maps().empty());
130 WeakenDescriptorArrays();
131 }
132
133 Rehash();
134 CHECK(new_off_heap_array_buffers().empty());
135
136 // TODO(leszeks): Figure out a better way of dealing with scripts.
137 CHECK_EQ(new_scripts().size(), 1);
138 for (Handle<Script> script : new_scripts()) {
139 // Assign a new script id to avoid collision.
140 script->set_id(isolate()->GetNextScriptId());
141 LogScriptEvents(*script);
142 deserialized_scripts->push_back(
143 isolate()->heap()->NewPersistentHandle(script));
144 }
145
146 return scope.CloseAndEscape(result);
147 }
148
149 } // namespace internal
150 } // namespace v8
151