// 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/startup-deserializer.h" #include "src/api.h" #include "src/assembler-inl.h" #include "src/heap/heap-inl.h" #include "src/snapshot/builtin-deserializer.h" #include "src/snapshot/snapshot.h" namespace v8 { namespace internal { void StartupDeserializer::DeserializeInto(Isolate* isolate) { Initialize(isolate); BuiltinDeserializer builtin_deserializer(isolate, builtin_data_); if (!Deserializer::ReserveSpace(this, &builtin_deserializer)) { V8::FatalProcessOutOfMemory("StartupDeserializer"); } // No active threads. DCHECK_NULL(isolate->thread_manager()->FirstThreadStateInUse()); // No active handles. DCHECK(isolate->handle_scope_implementer()->blocks()->empty()); // Partial snapshot cache is not yet populated. DCHECK(isolate->partial_snapshot_cache()->empty()); // Builtins are not yet created. DCHECK(!isolate->builtins()->is_initialized()); { DisallowHeapAllocation no_gc; isolate->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG_ROOT_LIST); isolate->heap()->IterateSmiRoots(this); isolate->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG); isolate->heap()->RepairFreeListsAfterDeserialization(); isolate->heap()->IterateWeakRoots(this, VISIT_ALL); DeserializeDeferredObjects(); RestoreExternalReferenceRedirectors(accessor_infos()); // Deserialize eager builtins from the builtin snapshot. Note that deferred // objects must have been deserialized prior to this. builtin_deserializer.DeserializeEagerBuiltins(); // Flush the instruction cache for the entire code-space. Must happen after // builtins deserialization. FlushICacheForNewIsolate(); } isolate->heap()->set_native_contexts_list(isolate->heap()->undefined_value()); // The allocation site list is build during root iteration, but if no sites // were encountered then it needs to be initialized to undefined. if (isolate->heap()->allocation_sites_list() == Smi::kZero) { isolate->heap()->set_allocation_sites_list( isolate->heap()->undefined_value()); } // Issue code events for newly deserialized code objects. LOG_CODE_EVENT(isolate, LogCodeObjects()); LOG_CODE_EVENT(isolate, LogBytecodeHandlers()); LOG_CODE_EVENT(isolate, LogCompiledFunctions()); isolate->builtins()->MarkInitialized(); // If needed, print the dissassembly of deserialized code objects. // Needs to be called after the builtins are marked as initialized, in order // to display the builtin names. PrintDisassembledCodeObjects(); if (FLAG_rehash_snapshot && can_rehash()) Rehash(); } void StartupDeserializer::FlushICacheForNewIsolate() { DCHECK(!deserializing_user_code()); // The entire isolate is newly deserialized. Simply flush all code pages. for (Page* p : *isolate()->heap()->code_space()) { Assembler::FlushICache(isolate(), p->area_start(), p->area_end() - p->area_start()); } } void StartupDeserializer::PrintDisassembledCodeObjects() { #ifdef ENABLE_DISASSEMBLER if (FLAG_print_builtin_code) { Heap* heap = isolate()->heap(); HeapIterator iterator(heap); DisallowHeapAllocation no_gc; CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer()); OFStream os(tracing_scope.file()); for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { if (obj->IsCode()) { Code::cast(obj)->Disassemble(nullptr, os); } } } #endif } void StartupDeserializer::Rehash() { DCHECK(FLAG_rehash_snapshot && can_rehash()); isolate()->heap()->InitializeHashSeed(); isolate()->heap()->string_table()->Rehash(); isolate()->heap()->weak_object_to_code_table()->Rehash(); SortMapDescriptors(); } } // namespace internal } // namespace v8