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