blob: 63a0cfca175557ff67ca85c295eb6962aa68e67f [file] [log] [blame]
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/snapshot/object-deserializer.h"
#include "src/codegen/assembler-inl.h"
#include "src/execution/isolate.h"
#include "src/heap/heap-inl.h"
#include "src/objects/allocation-site-inl.h"
#include "src/objects/objects.h"
#include "src/objects/slots.h"
#include "src/snapshot/code-serializer.h"
namespace v8 {
namespace internal {
ObjectDeserializer::ObjectDeserializer(const SerializedCodeData* data)
: Deserializer(data, true) {}
MaybeHandle<SharedFunctionInfo>
ObjectDeserializer::DeserializeSharedFunctionInfo(
Isolate* isolate, const SerializedCodeData* data, Handle<String> source) {
ObjectDeserializer d(data);
d.AddAttachedObject(source);
Handle<HeapObject> result;
return d.Deserialize(isolate).ToHandle(&result)
? Handle<SharedFunctionInfo>::cast(result)
: MaybeHandle<SharedFunctionInfo>();
}
MaybeHandle<HeapObject> ObjectDeserializer::Deserialize(Isolate* isolate) {
Initialize(isolate);
if (!allocator()->ReserveSpace()) return MaybeHandle<HeapObject>();
DCHECK(deserializing_user_code());
HandleScope scope(isolate);
Handle<HeapObject> result;
{
DisallowHeapAllocation no_gc;
Object root;
VisitRootPointer(Root::kPartialSnapshotCache, nullptr,
FullObjectSlot(&root));
DeserializeDeferredObjects();
FlushICache();
LinkAllocationSites();
LogNewMapEvents();
result = handle(HeapObject::cast(root), isolate);
Rehash();
allocator()->RegisterDeserializedObjectsForBlackAllocation();
}
CommitPostProcessedObjects();
return scope.CloseAndEscape(result);
}
void ObjectDeserializer::FlushICache() {
DCHECK(deserializing_user_code());
for (Code code : new_code_objects()) {
// Record all references to embedded objects in the new code object.
WriteBarrierForCode(code);
FlushInstructionCache(code.raw_instruction_start(),
code.raw_instruction_size());
}
}
void ObjectDeserializer::CommitPostProcessedObjects() {
CHECK_LE(new_internalized_strings().size(), kMaxInt);
StringTable::EnsureCapacityForDeserialization(
isolate(), static_cast<int>(new_internalized_strings().size()));
for (Handle<String> string : new_internalized_strings()) {
DisallowHeapAllocation no_gc;
StringTableInsertionKey key(*string);
StringTable::AddKeyNoResize(isolate(), &key);
}
Heap* heap = isolate()->heap();
Factory* factory = isolate()->factory();
for (Handle<Script> script : new_scripts()) {
// Assign a new script id to avoid collision.
script->set_id(isolate()->heap()->NextScriptId());
LogScriptEvents(*script);
// Add script to list.
Handle<WeakArrayList> list = factory->script_list();
list = WeakArrayList::AddToEnd(isolate(), list,
MaybeObjectHandle::Weak(script));
heap->SetRootScriptList(*list);
}
}
void ObjectDeserializer::LinkAllocationSites() {
DisallowHeapAllocation no_gc;
Heap* heap = isolate()->heap();
// Allocation sites are present in the snapshot, and must be linked into
// a list at deserialization time.
for (AllocationSite site : new_allocation_sites()) {
if (!site.HasWeakNext()) continue;
// TODO(mvstanton): consider treating the heap()->allocation_sites_list()
// as a (weak) root. If this root is relocated correctly, this becomes
// unnecessary.
if (heap->allocation_sites_list() == Smi::kZero) {
site.set_weak_next(ReadOnlyRoots(heap).undefined_value());
} else {
site.set_weak_next(heap->allocation_sites_list());
}
heap->set_allocation_sites_list(site);
}
}
} // namespace internal
} // namespace v8