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
17namespace v8 {
18namespace internal {
19
20ObjectDeserializer::ObjectDeserializer(Isolate* isolate,
21                                       const SerializedCodeData* data)
22    : Deserializer(isolate, data->Payload(), data->GetMagicNumber(), true,
23                   false) {}
24
25MaybeHandle<SharedFunctionInfo>
26ObjectDeserializer::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
38MaybeHandle<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
56void 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
79void 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
98OffThreadObjectDeserializer::OffThreadObjectDeserializer(
99    LocalIsolate* isolate, const SerializedCodeData* data)
100    : Deserializer(isolate, data->Payload(), data->GetMagicNumber(), true,
101                   false) {}
102
103MaybeHandle<SharedFunctionInfo>
104OffThreadObjectDeserializer::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
119MaybeHandle<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