| // 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/code-stubs.h" |
| #include "src/code-tracer.h" |
| #include "src/heap/heap-inl.h" |
| #include "src/snapshot/read-only-deserializer.h" |
| #include "src/snapshot/snapshot.h" |
| |
| namespace v8 { |
| namespace internal { |
| |
| void StartupDeserializer::DeserializeInto(Isolate* isolate) { |
| Initialize(isolate); |
| |
| ReadOnlyDeserializer read_only_deserializer(read_only_data_); |
| read_only_deserializer.SetRehashability(can_rehash()); |
| read_only_deserializer.DeserializeInto(isolate); |
| |
| if (!allocator()->ReserveSpace()) { |
| V8::FatalProcessOutOfMemory(isolate, "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()->IterateSmiRoots(this); |
| isolate->heap()->IterateStrongRoots(this, VISIT_FOR_SERIALIZATION); |
| Iterate(isolate, this); |
| isolate->heap()->IterateWeakRoots(this, VISIT_FOR_SERIALIZATION); |
| DeserializeDeferredObjects(); |
| RestoreExternalReferenceRedirectors(accessor_infos()); |
| RestoreExternalReferenceRedirectors(call_handler_infos()); |
| |
| // Flush the instruction cache for the entire code-space. Must happen after |
| // builtins deserialization. |
| FlushICacheForNewIsolate(); |
| } |
| |
| isolate->heap()->set_native_contexts_list( |
| ReadOnlyRoots(isolate).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( |
| ReadOnlyRoots(isolate).undefined_value()); |
| } |
| |
| // Issue code events for newly deserialized code objects. |
| LOG_CODE_EVENT(isolate, LogCodeObjects()); |
| 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()) { |
| isolate->heap()->InitializeHashSeed(); |
| read_only_deserializer.RehashHeap(); |
| 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(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 != nullptr; |
| obj = iterator.next()) { |
| if (obj->IsCode()) { |
| Code code = Code::cast(obj); |
| // Printing of builtins and bytecode handlers is handled during their |
| // deserialization. |
| if (code->kind() != Code::BUILTIN && |
| code->kind() != Code::BYTECODE_HANDLER) { |
| code->PrintBuiltinCode(isolate(), nullptr); |
| } |
| } |
| } |
| } |
| #endif |
| } |
| |
| } // namespace internal |
| } // namespace v8 |