OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/snapshot/startup-serializer.h" | 5 #include "src/snapshot/startup-serializer.h" |
6 | 6 |
7 #include "src/objects-inl.h" | 7 #include "src/objects-inl.h" |
8 #include "src/v8threads.h" | 8 #include "src/v8threads.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
11 namespace internal { | 11 namespace internal { |
12 | 12 |
13 StartupSerializer::StartupSerializer( | 13 StartupSerializer::StartupSerializer( |
14 Isolate* isolate, SnapshotByteSink* sink, | 14 Isolate* isolate, SnapshotByteSink* sink, |
15 FunctionCodeHandling function_code_handling) | 15 FunctionCodeHandling function_code_handling) |
16 : Serializer(isolate, sink), | 16 : Serializer(isolate, sink), |
17 root_index_wave_front_(0), | 17 function_code_handling_(function_code_handling), |
18 serializing_builtins_(false), | 18 serializing_builtins_(false) { |
19 function_code_handling_(function_code_handling) { | |
20 InitializeCodeAddressMap(); | 19 InitializeCodeAddressMap(); |
21 } | 20 } |
22 | 21 |
23 StartupSerializer::~StartupSerializer() { | 22 StartupSerializer::~StartupSerializer() { |
24 OutputStatistics("StartupSerializer"); | 23 OutputStatistics("StartupSerializer"); |
25 } | 24 } |
26 | 25 |
27 void StartupSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, | 26 void StartupSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, |
28 WhereToPoint where_to_point, int skip) { | 27 WhereToPoint where_to_point, int skip) { |
29 DCHECK(!obj->IsJSFunction()); | 28 DCHECK(!obj->IsJSFunction()); |
30 | 29 |
31 if (obj->IsCode()) { | 30 if (obj->IsCode()) { |
32 Code* code = Code::cast(obj); | 31 Code* code = Code::cast(obj); |
33 // If the function code is compiled (either as native code or bytecode), | 32 // If the function code is compiled (either as native code or bytecode), |
34 // replace it with lazy-compile builtin. Only exception is when we are | 33 // replace it with lazy-compile builtin. Only exception is when we are |
35 // serializing the canonical interpreter-entry-trampoline builtin. | 34 // serializing the canonical interpreter-entry-trampoline builtin. |
36 if (function_code_handling_ == CLEAR_FUNCTION_CODE && | 35 if (function_code_handling_ == CLEAR_FUNCTION_CODE && |
37 (code->kind() == Code::FUNCTION || | 36 (code->kind() == Code::FUNCTION || |
38 (!serializing_builtins_ && code->is_interpreter_entry_trampoline()))) { | 37 (!serializing_builtins_ && code->is_interpreter_entry_trampoline()))) { |
39 obj = isolate()->builtins()->builtin(Builtins::kCompileLazy); | 38 obj = isolate()->builtins()->builtin(Builtins::kCompileLazy); |
40 } | 39 } |
41 } else if (obj->IsBytecodeArray()) { | 40 } else if (obj->IsBytecodeArray()) { |
42 obj = isolate()->heap()->undefined_value(); | 41 obj = isolate()->heap()->undefined_value(); |
43 } | 42 } |
44 | 43 |
45 int root_index = root_index_map_.Lookup(obj); | 44 int root_index = root_index_map_.Lookup(obj); |
46 bool is_immortal_immovable_root = false; | |
47 // We can only encode roots as such if it has already been serialized. | 45 // We can only encode roots as such if it has already been serialized. |
48 // That applies to root indices below the wave front. | 46 // That applies to root indices below the wave front. |
49 if (root_index != RootIndexMap::kInvalidRootIndex) { | 47 if (root_index != RootIndexMap::kInvalidRootIndex) { |
50 if (root_index < root_index_wave_front_) { | 48 if (root_has_been_serialized_.test(root_index)) { |
51 PutRoot(root_index, obj, how_to_code, where_to_point, skip); | 49 PutRoot(root_index, obj, how_to_code, where_to_point, skip); |
52 return; | 50 return; |
53 } else { | |
54 is_immortal_immovable_root = Heap::RootIsImmortalImmovable(root_index); | |
55 } | 51 } |
56 } | 52 } |
57 | 53 |
58 if (SerializeKnownObject(obj, how_to_code, where_to_point, skip)) return; | 54 if (SerializeKnownObject(obj, how_to_code, where_to_point, skip)) return; |
59 | 55 |
60 FlushSkip(skip); | 56 FlushSkip(skip); |
61 | 57 |
62 // Object has not yet been serialized. Serialize it here. | 58 // Object has not yet been serialized. Serialize it here. |
63 ObjectSerializer object_serializer(this, obj, sink_, how_to_code, | 59 ObjectSerializer object_serializer(this, obj, sink_, how_to_code, |
64 where_to_point); | 60 where_to_point); |
65 object_serializer.Serialize(); | 61 object_serializer.Serialize(); |
66 | 62 |
67 if (is_immortal_immovable_root) { | 63 if (serializing_immortal_immovables_roots_ && |
| 64 root_index != RootIndexMap::kInvalidRootIndex) { |
68 // Make sure that the immortal immovable root has been included in the first | 65 // Make sure that the immortal immovable root has been included in the first |
69 // chunk of its reserved space , so that it is deserialized onto the first | 66 // chunk of its reserved space , so that it is deserialized onto the first |
70 // page of its space and stays immortal immovable. | 67 // page of its space and stays immortal immovable. |
71 BackReference ref = back_reference_map_.Lookup(obj); | 68 BackReference ref = back_reference_map_.Lookup(obj); |
72 CHECK(ref.is_valid() && ref.chunk_index() == 0); | 69 CHECK(ref.is_valid() && ref.chunk_index() == 0); |
73 } | 70 } |
74 } | 71 } |
75 | 72 |
76 void StartupSerializer::SerializeWeakReferencesAndDeferred() { | 73 void StartupSerializer::SerializeWeakReferencesAndDeferred() { |
77 // This comes right after serialization of the partial snapshot, where we | 74 // This comes right after serialization of the partial snapshot, where we |
(...skipping 16 matching lines...) Expand all Loading... |
94 void StartupSerializer::SerializeStrongReferences() { | 91 void StartupSerializer::SerializeStrongReferences() { |
95 Isolate* isolate = this->isolate(); | 92 Isolate* isolate = this->isolate(); |
96 // No active threads. | 93 // No active threads. |
97 CHECK_NULL(isolate->thread_manager()->FirstThreadStateInUse()); | 94 CHECK_NULL(isolate->thread_manager()->FirstThreadStateInUse()); |
98 // No active or weak handles. | 95 // No active or weak handles. |
99 CHECK(isolate->handle_scope_implementer()->blocks()->is_empty()); | 96 CHECK(isolate->handle_scope_implementer()->blocks()->is_empty()); |
100 CHECK_EQ(0, isolate->global_handles()->NumberOfWeakHandles()); | 97 CHECK_EQ(0, isolate->global_handles()->NumberOfWeakHandles()); |
101 CHECK_EQ(0, isolate->eternal_handles()->NumberOfHandles()); | 98 CHECK_EQ(0, isolate->eternal_handles()->NumberOfHandles()); |
102 // We don't support serializing installed extensions. | 99 // We don't support serializing installed extensions. |
103 CHECK(!isolate->has_installed_extensions()); | 100 CHECK(!isolate->has_installed_extensions()); |
| 101 // First visit immortal immovables to make sure they end up in the first page. |
| 102 serializing_immortal_immovables_roots_ = true; |
| 103 isolate->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG_ROOT_LIST); |
| 104 // Check that immortal immovable roots are allocated on the first page. |
| 105 CHECK(HasNotExceededFirstPageOfEachSpace()); |
| 106 serializing_immortal_immovables_roots_ = false; |
| 107 // Visit the rest of the strong roots. |
104 isolate->heap()->IterateSmiRoots(this); | 108 isolate->heap()->IterateSmiRoots(this); |
105 isolate->heap()->IterateStrongRoots(this, | 109 isolate->heap()->IterateStrongRoots(this, |
106 VISIT_ONLY_STRONG_FOR_SERIALIZATION); | 110 VISIT_ONLY_STRONG_FOR_SERIALIZATION); |
107 } | 111 } |
108 | 112 |
109 void StartupSerializer::VisitPointers(Object** start, Object** end) { | 113 void StartupSerializer::VisitPointers(Object** start, Object** end) { |
110 for (Object** current = start; current < end; current++) { | 114 if (start == isolate()->heap()->roots_array_start()) { |
111 if (start == isolate()->heap()->roots_array_start()) { | 115 // Serializing the root list needs special handling: |
112 root_index_wave_front_ = | 116 // - The first pass over the root list only serializes immortal immovables. |
113 Max(root_index_wave_front_, static_cast<intptr_t>(current - start)); | 117 // - The second pass over the root list serializes the rest. |
| 118 // - Only root list elements that have been fully serialized can be |
| 119 // referenced via as root by using kRootArray bytecodes. |
| 120 int skip = 0; |
| 121 for (Object** current = start; current < end; current++) { |
| 122 int root_index = static_cast<int>(current - start); |
| 123 if (RootShouldBeSkipped(root_index)) { |
| 124 skip += kPointerSize; |
| 125 continue; |
| 126 } else { |
| 127 if ((*current)->IsSmi()) { |
| 128 FlushSkip(skip); |
| 129 PutSmi(Smi::cast(*current)); |
| 130 } else { |
| 131 SerializeObject(HeapObject::cast(*current), kPlain, kStartOfObject, |
| 132 skip); |
| 133 } |
| 134 root_has_been_serialized_.set(root_index); |
| 135 skip = 0; |
| 136 } |
114 } | 137 } |
115 if (ShouldBeSkipped(current)) { | 138 FlushSkip(skip); |
116 sink_->Put(kSkip, "Skip"); | 139 } else { |
117 sink_->PutInt(kPointerSize, "SkipOneWord"); | 140 Serializer::VisitPointers(start, end); |
118 } else if ((*current)->IsSmi()) { | |
119 sink_->Put(kOnePointerRawData, "Smi"); | |
120 for (int i = 0; i < kPointerSize; i++) { | |
121 sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte"); | |
122 } | |
123 } else { | |
124 SerializeObject(HeapObject::cast(*current), kPlain, kStartOfObject, 0); | |
125 } | |
126 } | 141 } |
127 } | 142 } |
128 | 143 |
| 144 bool StartupSerializer::RootShouldBeSkipped(int root_index) { |
| 145 if (root_index == Heap::kStoreBufferTopRootIndex || |
| 146 root_index == Heap::kStackLimitRootIndex || |
| 147 root_index == Heap::kRealStackLimitRootIndex) { |
| 148 return true; |
| 149 } |
| 150 return Heap::RootIsImmortalImmovable(root_index) != |
| 151 serializing_immortal_immovables_roots_; |
| 152 } |
| 153 |
129 } // namespace internal | 154 } // namespace internal |
130 } // namespace v8 | 155 } // namespace v8 |
OLD | NEW |