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/api.h"
8 #include "src/codegen/assembler-inl.h"
9 #include "src/execution/v8threads.h"
10 #include "src/heap/heap-inl.h"
11 #include "src/logging/log.h"
12 #include "src/snapshot/snapshot.h"
13
14 namespace v8 {
15 namespace internal {
16
DeserializeIntoIsolate()17 void StartupDeserializer::DeserializeIntoIsolate() {
18 HandleScope scope(isolate());
19
20 // No active threads.
21 DCHECK_NULL(isolate()->thread_manager()->FirstThreadStateInUse());
22 // No active handles.
23 DCHECK(isolate()->handle_scope_implementer()->blocks()->empty());
24 // Startup object cache is not yet populated.
25 DCHECK(isolate()->startup_object_cache()->empty());
26 // Builtins are not yet created.
27 DCHECK(!isolate()->builtins()->is_initialized());
28
29 {
30 isolate()->heap()->IterateSmiRoots(this);
31 isolate()->heap()->IterateRoots(
32 this,
33 base::EnumSet<SkipRoot>{SkipRoot::kUnserializable, SkipRoot::kWeak});
34 Iterate(isolate(), this);
35 DeserializeStringTable();
36
37 isolate()->heap()->IterateWeakRoots(
38 this, base::EnumSet<SkipRoot>{SkipRoot::kUnserializable});
39 DeserializeDeferredObjects();
40 for (Handle<AccessorInfo> info : accessor_infos()) {
41 RestoreExternalReferenceRedirector(isolate(), info);
42 }
43 for (Handle<CallHandlerInfo> info : call_handler_infos()) {
44 RestoreExternalReferenceRedirector(isolate(), info);
45 }
46
47 // Flush the instruction cache for the entire code-space. Must happen after
48 // builtins deserialization.
49 FlushICache();
50 }
51
52 CheckNoArrayBufferBackingStores();
53
54 isolate()->heap()->set_native_contexts_list(
55 ReadOnlyRoots(isolate()).undefined_value());
56 // The allocation site list is build during root iteration, but if no sites
57 // were encountered then it needs to be initialized to undefined.
58 if (isolate()->heap()->allocation_sites_list() == Smi::zero()) {
59 isolate()->heap()->set_allocation_sites_list(
60 ReadOnlyRoots(isolate()).undefined_value());
61 }
62 isolate()->heap()->set_dirty_js_finalization_registries_list(
63 ReadOnlyRoots(isolate()).undefined_value());
64 isolate()->heap()->set_dirty_js_finalization_registries_list_tail(
65 ReadOnlyRoots(isolate()).undefined_value());
66
67 isolate()->builtins()->MarkInitialized();
68
69 LogNewMapEvents();
70 WeakenDescriptorArrays();
71
72 if (FLAG_rehash_snapshot && can_rehash()) {
73 // Hash seed was initalized in ReadOnlyDeserializer.
74 Rehash();
75 }
76 }
77
DeserializeStringTable()78 void StartupDeserializer::DeserializeStringTable() {
79 // See StartupSerializer::SerializeStringTable.
80
81 // Get the string table size.
82 int string_table_size = source()->GetInt();
83
84 // Add each string to the Isolate's string table.
85 // TODO(leszeks): Consider pre-sizing the string table.
86 for (int i = 0; i < string_table_size; ++i) {
87 Handle<String> string = Handle<String>::cast(ReadObject());
88 StringTableInsertionKey key(string);
89 Handle<String> result =
90 isolate()->string_table()->LookupKey(isolate(), &key);
91 USE(result);
92
93 // This is startup, so there should be no duplicate entries in the string
94 // table, and the lookup should unconditionally add the given string.
95 DCHECK_EQ(*result, *string);
96 }
97
98 DCHECK_EQ(string_table_size, isolate()->string_table()->NumberOfElements());
99 }
100
LogNewMapEvents()101 void StartupDeserializer::LogNewMapEvents() {
102 if (FLAG_trace_maps) LOG(isolate(), LogAllMaps());
103 }
104
FlushICache()105 void StartupDeserializer::FlushICache() {
106 DCHECK(!deserializing_user_code());
107 // The entire isolate is newly deserialized. Simply flush all code pages.
108 for (Page* p : *isolate()->heap()->code_space()) {
109 FlushInstructionCache(p->area_start(), p->area_end() - p->area_start());
110 }
111 }
112
113 } // namespace internal
114 } // namespace v8
115