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     IterateStartupObjectCache(isolate(), this);
35 
36     isolate()->heap()->IterateWeakRoots(
37         this, base::EnumSet<SkipRoot>{SkipRoot::kUnserializable});
38     DeserializeDeferredObjects();
39     for (Handle<AccessorInfo> info : accessor_infos()) {
40       RestoreExternalReferenceRedirector(isolate(), *info);
41     }
42     for (Handle<CallHandlerInfo> info : call_handler_infos()) {
43       RestoreExternalReferenceRedirector(isolate(), *info);
44     }
45 
46     // Flush the instruction cache for the entire code-space. Must happen after
47     // builtins deserialization.
48     FlushICache();
49   }
50 
51   CheckNoArrayBufferBackingStores();
52 
53   isolate()->heap()->set_native_contexts_list(
54       ReadOnlyRoots(isolate()).undefined_value());
55   // The allocation site list is build during root iteration, but if no sites
56   // were encountered then it needs to be initialized to undefined.
57   if (isolate()->heap()->allocation_sites_list() == Smi::zero()) {
58     isolate()->heap()->set_allocation_sites_list(
59         ReadOnlyRoots(isolate()).undefined_value());
60   }
61   isolate()->heap()->set_dirty_js_finalization_registries_list(
62       ReadOnlyRoots(isolate()).undefined_value());
63   isolate()->heap()->set_dirty_js_finalization_registries_list_tail(
64       ReadOnlyRoots(isolate()).undefined_value());
65 
66   isolate()->builtins()->MarkInitialized();
67 
68   LogNewMapEvents();
69   WeakenDescriptorArrays();
70 
71   if (should_rehash()) {
72     // Hash seed was initialized in ReadOnlyDeserializer.
73     Rehash();
74   }
75 }
76 
LogNewMapEvents()77 void StartupDeserializer::LogNewMapEvents() {
78   if (FLAG_log_maps) LOG(isolate(), LogAllMaps());
79 }
80 
FlushICache()81 void StartupDeserializer::FlushICache() {
82   DCHECK(!deserializing_user_code());
83   // The entire isolate is newly deserialized. Simply flush all code pages.
84   for (Page* p : *isolate()->heap()->code_space()) {
85     FlushInstructionCache(p->area_start(), p->area_end() - p->area_start());
86   }
87 }
88 
89 }  // namespace internal
90 }  // namespace v8
91