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/startup-deserializer.h"
6 
7 #include "src/api.h"
8 #include "src/assembler-inl.h"
9 #include "src/code-stubs.h"
10 #include "src/code-tracer.h"
11 #include "src/heap/heap-inl.h"
12 #include "src/snapshot/builtin-deserializer.h"
13 #include "src/snapshot/snapshot.h"
14 
15 namespace v8 {
16 namespace internal {
17 
DeserializeInto(Isolate * isolate)18 void StartupDeserializer::DeserializeInto(Isolate* isolate) {
19   Initialize(isolate);
20 
21   BuiltinDeserializer builtin_deserializer(isolate, builtin_data_);
22 
23   if (!DefaultDeserializerAllocator::ReserveSpace(this,
24                                                   &builtin_deserializer)) {
25     V8::FatalProcessOutOfMemory(isolate, "StartupDeserializer");
26   }
27 
28   // No active threads.
29   DCHECK_NULL(isolate->thread_manager()->FirstThreadStateInUse());
30   // No active handles.
31   DCHECK(isolate->handle_scope_implementer()->blocks()->empty());
32   // Partial snapshot cache is not yet populated.
33   DCHECK(isolate->partial_snapshot_cache()->empty());
34   // Builtins are not yet created.
35   DCHECK(!isolate->builtins()->is_initialized());
36 
37   {
38     DisallowHeapAllocation no_gc;
39     isolate->heap()->IterateSmiRoots(this);
40     isolate->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG);
41     isolate->heap()->RepairFreeListsAfterDeserialization();
42     isolate->heap()->IterateWeakRoots(this, VISIT_FOR_SERIALIZATION);
43     DeserializeDeferredObjects();
44     RestoreExternalReferenceRedirectors(accessor_infos());
45     RestoreExternalReferenceRedirectors(call_handler_infos());
46 
47     // Deserialize eager builtins from the builtin snapshot. Note that deferred
48     // objects must have been deserialized prior to this.
49     builtin_deserializer.DeserializeEagerBuiltinsAndHandlers();
50 
51     // Flush the instruction cache for the entire code-space. Must happen after
52     // builtins deserialization.
53     FlushICacheForNewIsolate();
54   }
55 
56   isolate->heap()->set_native_contexts_list(
57       ReadOnlyRoots(isolate).undefined_value());
58   // The allocation site list is build during root iteration, but if no sites
59   // were encountered then it needs to be initialized to undefined.
60   if (isolate->heap()->allocation_sites_list() == Smi::kZero) {
61     isolate->heap()->set_allocation_sites_list(
62         ReadOnlyRoots(isolate).undefined_value());
63   }
64 
65   // Issue code events for newly deserialized code objects.
66   LOG_CODE_EVENT(isolate, LogCodeObjects());
67   LOG_CODE_EVENT(isolate, LogBytecodeHandlers());
68   LOG_CODE_EVENT(isolate, LogCompiledFunctions());
69 
70   isolate->builtins()->MarkInitialized();
71 
72   // If needed, print the dissassembly of deserialized code objects.
73   // Needs to be called after the builtins are marked as initialized, in order
74   // to display the builtin names.
75   PrintDisassembledCodeObjects();
76 
77   if (FLAG_rehash_snapshot && can_rehash()) RehashHeap();
78 }
79 
FlushICacheForNewIsolate()80 void StartupDeserializer::FlushICacheForNewIsolate() {
81   DCHECK(!deserializing_user_code());
82   // The entire isolate is newly deserialized. Simply flush all code pages.
83   for (Page* p : *isolate()->heap()->code_space()) {
84     Assembler::FlushICache(p->area_start(), p->area_end() - p->area_start());
85   }
86 }
87 
PrintDisassembledCodeObjects()88 void StartupDeserializer::PrintDisassembledCodeObjects() {
89 #ifdef ENABLE_DISASSEMBLER
90   if (FLAG_print_builtin_code) {
91     Heap* heap = isolate()->heap();
92     HeapIterator iterator(heap);
93     DisallowHeapAllocation no_gc;
94 
95     CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer());
96     OFStream os(tracing_scope.file());
97 
98     for (HeapObject* obj = iterator.next(); obj != nullptr;
99          obj = iterator.next()) {
100       if (obj->IsCode()) {
101         Code* code = Code::cast(obj);
102         // Printing of builtins and bytecode handlers is handled during their
103         // deserialization.
104         if (code->kind() != Code::BUILTIN &&
105             code->kind() != Code::BYTECODE_HANDLER) {
106           code->PrintBuiltinCode(isolate(), nullptr);
107         }
108       }
109     }
110   }
111 #endif
112 }
113 
RehashHeap()114 void StartupDeserializer::RehashHeap() {
115   DCHECK(FLAG_rehash_snapshot && can_rehash());
116   isolate()->heap()->InitializeHashSeed();
117   Rehash();
118 }
119 
120 }  // namespace internal
121 }  // namespace v8
122