Line data Source code
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/default-deserializer-allocator.h"
6 :
7 : #include "src/heap/heap-inl.h"
8 : #include "src/snapshot/builtin-deserializer.h"
9 : #include "src/snapshot/deserializer.h"
10 : #include "src/snapshot/startup-deserializer.h"
11 :
12 : namespace v8 {
13 : namespace internal {
14 :
15 138819 : DefaultDeserializerAllocator::DefaultDeserializerAllocator(
16 : Deserializer<DefaultDeserializerAllocator>* deserializer)
17 971733 : : deserializer_(deserializer) {}
18 :
19 : // We know the space requirements before deserialization and can
20 : // pre-allocate that reserved space. During deserialization, all we need
21 : // to do is to bump up the pointer for each space in the reserved
22 : // space. This is also used for fixing back references.
23 : // We may have to split up the pre-allocation into several chunks
24 : // because it would not fit onto a single page. We do not have to keep
25 : // track of when to move to the next chunk. An opcode will signal this.
26 : // Since multiple large objects cannot be folded into one large object
27 : // space allocation, we have to do an actual allocation when deserializing
28 : // each large object. Instead of tracking offset for back references, we
29 : // reference large objects by index.
30 443044876 : Address DefaultDeserializerAllocator::AllocateRaw(AllocationSpace space,
31 : int size) {
32 443044876 : if (space == LO_SPACE) {
33 : AlwaysAllocateScope scope(isolate());
34 40 : LargeObjectSpace* lo_space = isolate()->heap()->lo_space();
35 : // TODO(jgruber): May be cleaner to pass in executability as an argument.
36 : Executability exec =
37 40 : static_cast<Executability>(deserializer_->source()->Get());
38 40 : AllocationResult result = lo_space->AllocateRaw(size, exec);
39 40 : HeapObject* obj = result.ToObjectChecked();
40 40 : deserialized_large_objects_.push_back(obj);
41 40 : return obj->address();
42 443044836 : } else if (space == MAP_SPACE) {
43 : DCHECK_EQ(Map::kSize, size);
44 58437734 : return allocated_maps_[next_map_index_++];
45 : } else {
46 : DCHECK_LT(space, kNumberOfPreallocatedSpaces);
47 413825969 : Address address = high_water_[space];
48 : DCHECK_NOT_NULL(address);
49 413825969 : high_water_[space] += size;
50 : #ifdef DEBUG
51 : // Assert that the current reserved chunk is still big enough.
52 : const Heap::Reservation& reservation = reservations_[space];
53 : int chunk_index = current_chunk_[space];
54 : DCHECK_LE(high_water_[space], reservation[chunk_index].end);
55 : #endif
56 413825969 : if (space == CODE_SPACE) SkipList::Update(address, size);
57 413827415 : return address;
58 : }
59 : }
60 :
61 443043252 : Address DefaultDeserializerAllocator::Allocate(AllocationSpace space,
62 : int size) {
63 : Address address;
64 : HeapObject* obj;
65 :
66 443043252 : if (next_alignment_ != kWordAligned) {
67 0 : const int reserved = size + Heap::GetMaximumFillToAlign(next_alignment_);
68 0 : address = AllocateRaw(space, reserved);
69 0 : obj = HeapObject::FromAddress(address);
70 : // If one of the following assertions fails, then we are deserializing an
71 : // aligned object when the filler maps have not been deserialized yet.
72 : // We require filler maps as padding to align the object.
73 0 : Heap* heap = isolate()->heap();
74 : DCHECK(heap->free_space_map()->IsMap());
75 : DCHECK(heap->one_pointer_filler_map()->IsMap());
76 : DCHECK(heap->two_pointer_filler_map()->IsMap());
77 0 : obj = heap->AlignWithFiller(obj, size, reserved, next_alignment_);
78 : address = obj->address();
79 0 : next_alignment_ = kWordAligned;
80 0 : return address;
81 : } else {
82 443043252 : return AllocateRaw(space, size);
83 : }
84 : }
85 :
86 55 : void DefaultDeserializerAllocator::MoveToNextChunk(AllocationSpace space) {
87 : DCHECK_LT(space, kNumberOfPreallocatedSpaces);
88 55 : uint32_t chunk_index = current_chunk_[space];
89 165 : const Heap::Reservation& reservation = reservations_[space];
90 : // Make sure the current chunk is indeed exhausted.
91 110 : CHECK_EQ(reservation[chunk_index].end, high_water_[space]);
92 : // Move to next reserved chunk.
93 55 : chunk_index = ++current_chunk_[space];
94 55 : CHECK_LT(chunk_index, reservation.size());
95 55 : high_water_[space] = reservation[chunk_index].start;
96 55 : }
97 :
98 18272643 : HeapObject* DefaultDeserializerAllocator::GetMap(uint32_t index) {
99 : DCHECK_LT(index, next_map_index_);
100 36545286 : return HeapObject::FromAddress(allocated_maps_[index]);
101 : }
102 :
103 5 : HeapObject* DefaultDeserializerAllocator::GetLargeObject(uint32_t index) {
104 : DCHECK_LT(index, deserialized_large_objects_.size());
105 10 : return deserialized_large_objects_[index];
106 : }
107 :
108 243483453 : HeapObject* DefaultDeserializerAllocator::GetObject(AllocationSpace space,
109 : uint32_t chunk_index,
110 : uint32_t chunk_offset) {
111 : DCHECK_LT(space, kNumberOfPreallocatedSpaces);
112 : DCHECK_LE(chunk_index, current_chunk_[space]);
113 486966906 : Address address = reservations_[space][chunk_index].start + chunk_offset;
114 243483453 : if (next_alignment_ != kWordAligned) {
115 0 : int padding = Heap::GetFillToAlign(address, next_alignment_);
116 0 : next_alignment_ = kWordAligned;
117 : DCHECK(padding == 0 || HeapObject::FromAddress(address)->IsFiller());
118 0 : address += padding;
119 : }
120 243483453 : return HeapObject::FromAddress(address);
121 : }
122 :
123 138819 : void DefaultDeserializerAllocator::DecodeReservation(
124 : Vector<const SerializedData::Reservation> res) {
125 : DCHECK_EQ(0, reservations_[NEW_SPACE].size());
126 : STATIC_ASSERT(NEW_SPACE == 0);
127 : int current_space = NEW_SPACE;
128 832969 : for (auto& r : res) {
129 1388300 : reservations_[current_space].push_back({r.chunk_size(), NULL, NULL});
130 694150 : if (r.is_last()) current_space++;
131 : }
132 : DCHECK_EQ(kNumberOfSpaces, current_space);
133 416457 : for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) current_chunk_[i] = 0;
134 138819 : }
135 :
136 83851 : bool DefaultDeserializerAllocator::ReserveSpace() {
137 : #ifdef DEBUG
138 : for (int i = NEW_SPACE; i < kNumberOfSpaces; ++i) {
139 : DCHECK_GT(reservations_[i].size(), 0);
140 : }
141 : #endif // DEBUG
142 : DCHECK(allocated_maps_.empty());
143 167702 : if (!isolate()->heap()->ReserveSpace(reservations_, &allocated_maps_)) {
144 : return false;
145 : }
146 251553 : for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) {
147 251553 : high_water_[i] = reservations_[i][0].start;
148 : }
149 : return true;
150 : }
151 :
152 : // static
153 54968 : bool DefaultDeserializerAllocator::ReserveSpace(
154 : StartupDeserializer* startup_deserializer,
155 : BuiltinDeserializer* builtin_deserializer) {
156 : const int first_space = NEW_SPACE;
157 : const int last_space = SerializerDeserializer::kNumberOfSpaces;
158 54968 : Isolate* isolate = startup_deserializer->isolate();
159 :
160 : // Create a set of merged reservations to reserve space in one go.
161 : // The BuiltinDeserializer's reservations are ignored, since our actual
162 : // requirements vary based on whether lazy deserialization is enabled.
163 : // Instead, we manually determine the required code-space.
164 :
165 329808 : Heap::Reservation merged_reservations[kNumberOfSpaces];
166 274840 : for (int i = first_space; i < last_space; i++) {
167 274840 : merged_reservations[i] =
168 274840 : startup_deserializer->allocator()->reservations_[i];
169 : }
170 :
171 : Heap::Reservation builtin_reservations =
172 54968 : builtin_deserializer->allocator()->CreateReservationsForEagerBuiltins();
173 : DCHECK(!builtin_reservations.empty());
174 :
175 25051062 : for (const auto& c : builtin_reservations) {
176 24941117 : merged_reservations[CODE_SPACE].push_back(c);
177 : }
178 :
179 54968 : if (!isolate->heap()->ReserveSpace(
180 : merged_reservations,
181 54968 : &startup_deserializer->allocator()->allocated_maps_)) {
182 : return false;
183 : }
184 :
185 : DisallowHeapAllocation no_allocation;
186 :
187 : // Distribute the successful allocations between both deserializers.
188 : // There's nothing to be done here except for code space.
189 :
190 : {
191 : const int num_builtin_reservations =
192 109936 : static_cast<int>(builtin_reservations.size());
193 24995948 : for (int i = num_builtin_reservations - 1; i >= 0; i--) {
194 : const auto& c = merged_reservations[CODE_SPACE].back();
195 : DCHECK_EQ(c.size, builtin_reservations[i].size);
196 : DCHECK_EQ(c.size, c.end - c.start);
197 49881960 : builtin_reservations[i].start = c.start;
198 24940980 : builtin_reservations[i].end = c.end;
199 : merged_reservations[CODE_SPACE].pop_back();
200 : }
201 :
202 : builtin_deserializer->allocator()->InitializeBuiltinsTable(
203 54968 : builtin_reservations);
204 : }
205 :
206 : // Write back startup reservations.
207 :
208 329808 : for (int i = first_space; i < last_space; i++) {
209 : startup_deserializer->allocator()->reservations_[i].swap(
210 274840 : merged_reservations[i]);
211 : }
212 :
213 164904 : for (int i = first_space; i < kNumberOfPreallocatedSpaces; i++) {
214 : startup_deserializer->allocator()->high_water_[i] =
215 164904 : startup_deserializer->allocator()->reservations_[i][0].start;
216 : }
217 :
218 329808 : return true;
219 : }
220 :
221 0 : bool DefaultDeserializerAllocator::ReservationsAreFullyUsed() const {
222 0 : for (int space = 0; space < kNumberOfPreallocatedSpaces; space++) {
223 0 : const uint32_t chunk_index = current_chunk_[space];
224 0 : if (reservations_[space].size() != chunk_index + 1) {
225 : return false;
226 : }
227 0 : if (reservations_[space][chunk_index].end != high_water_[space]) {
228 : return false;
229 : }
230 : }
231 0 : return (allocated_maps_.size() == next_map_index_);
232 : }
233 :
234 83851 : void DefaultDeserializerAllocator::
235 : RegisterDeserializedObjectsForBlackAllocation() {
236 : isolate()->heap()->RegisterDeserializedObjectsForBlackAllocation(
237 167702 : reservations_, deserialized_large_objects_, allocated_maps_);
238 83851 : }
239 :
240 0 : Isolate* DefaultDeserializerAllocator::isolate() const {
241 167782 : return deserializer_->isolate();
242 : }
243 :
244 : } // namespace internal
245 : } // namespace v8
|