• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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