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/deserializer-allocator.h"
6 :
7 : #include "src/heap/heap-inl.h" // crbug.com/v8/8499
8 :
9 : namespace v8 {
10 : namespace internal {
11 :
12 : // We know the space requirements before deserialization and can
13 : // pre-allocate that reserved space. During deserialization, all we need
14 : // to do is to bump up the pointer for each space in the reserved
15 : // space. This is also used for fixing back references.
16 : // We may have to split up the pre-allocation into several chunks
17 : // because it would not fit onto a single page. We do not have to keep
18 : // track of when to move to the next chunk. An opcode will signal this.
19 : // Since multiple large objects cannot be folded into one large object
20 : // space allocation, we have to do an actual allocation when deserializing
21 : // each large object. Instead of tracking offset for back references, we
22 : // reference large objects by index.
23 441589221 : Address DeserializerAllocator::AllocateRaw(AllocationSpace space, int size) {
24 441589221 : if (space == LO_SPACE) {
25 60 : AlwaysAllocateScope scope(heap_);
26 : // Note that we currently do not support deserialization of large code
27 : // objects.
28 60 : LargeObjectSpace* lo_space = heap_->lo_space();
29 60 : AllocationResult result = lo_space->AllocateRaw(size);
30 60 : HeapObject obj = result.ToObjectChecked();
31 60 : deserialized_large_objects_.push_back(obj);
32 : return obj->address();
33 441589161 : } else if (space == MAP_SPACE) {
34 : DCHECK_EQ(Map::kSize, size);
35 45897908 : return allocated_maps_[next_map_index_++];
36 : } else {
37 : DCHECK_LT(space, kNumberOfPreallocatedSpaces);
38 418640207 : Address address = high_water_[space];
39 : DCHECK_NE(address, kNullAddress);
40 418640207 : high_water_[space] += size;
41 : #ifdef DEBUG
42 : // Assert that the current reserved chunk is still big enough.
43 : const Heap::Reservation& reservation = reservations_[space];
44 : int chunk_index = current_chunk_[space];
45 : DCHECK_LE(high_water_[space], reservation[chunk_index].end);
46 : #endif
47 418640207 : if (space == CODE_SPACE) SkipList::Update(address, size);
48 : return address;
49 : }
50 : }
51 :
52 441585799 : Address DeserializerAllocator::Allocate(AllocationSpace space, int size) {
53 : Address address;
54 : HeapObject obj;
55 :
56 441585799 : if (next_alignment_ != kWordAligned) {
57 0 : const int reserved = size + Heap::GetMaximumFillToAlign(next_alignment_);
58 0 : address = AllocateRaw(space, reserved);
59 : obj = HeapObject::FromAddress(address);
60 : // If one of the following assertions fails, then we are deserializing an
61 : // aligned object when the filler maps have not been deserialized yet.
62 : // We require filler maps as padding to align the object.
63 : DCHECK(ReadOnlyRoots(heap_).free_space_map()->IsMap());
64 : DCHECK(ReadOnlyRoots(heap_).one_pointer_filler_map()->IsMap());
65 : DCHECK(ReadOnlyRoots(heap_).two_pointer_filler_map()->IsMap());
66 0 : obj = heap_->AlignWithFiller(obj, size, reserved, next_alignment_);
67 : address = obj->address();
68 0 : next_alignment_ = kWordAligned;
69 0 : return address;
70 : } else {
71 441585799 : return AllocateRaw(space, size);
72 : }
73 : }
74 :
75 2295440 : void DeserializerAllocator::MoveToNextChunk(AllocationSpace space) {
76 : DCHECK_LT(space, kNumberOfPreallocatedSpaces);
77 2295440 : uint32_t chunk_index = current_chunk_[space];
78 2295440 : const Heap::Reservation& reservation = reservations_[space];
79 : // Make sure the current chunk is indeed exhausted.
80 4590880 : CHECK_EQ(reservation[chunk_index].end, high_water_[space]);
81 : // Move to next reserved chunk.
82 2295440 : chunk_index = ++current_chunk_[space];
83 2295440 : CHECK_LT(chunk_index, reservation.size());
84 2295440 : high_water_[space] = reservation[chunk_index].start;
85 2295440 : }
86 :
87 12378409 : HeapObject DeserializerAllocator::GetMap(uint32_t index) {
88 : DCHECK_LT(index, next_map_index_);
89 37135227 : return HeapObject::FromAddress(allocated_maps_[index]);
90 : }
91 :
92 10 : HeapObject DeserializerAllocator::GetLargeObject(uint32_t index) {
93 : DCHECK_LT(index, deserialized_large_objects_.size());
94 20 : return deserialized_large_objects_[index];
95 : }
96 :
97 175213426 : HeapObject DeserializerAllocator::GetObject(AllocationSpace space,
98 : uint32_t chunk_index,
99 : uint32_t chunk_offset) {
100 : DCHECK_LT(space, kNumberOfPreallocatedSpaces);
101 : DCHECK_LE(chunk_index, current_chunk_[space]);
102 350426852 : Address address = reservations_[space][chunk_index].start + chunk_offset;
103 175213426 : if (next_alignment_ != kWordAligned) {
104 0 : int padding = Heap::GetFillToAlign(address, next_alignment_);
105 0 : next_alignment_ = kWordAligned;
106 : DCHECK(padding == 0 || HeapObject::FromAddress(address)->IsFiller());
107 0 : address += padding;
108 : }
109 175213426 : return HeapObject::FromAddress(address);
110 : }
111 :
112 216608 : void DeserializerAllocator::DecodeReservation(
113 : const std::vector<SerializedData::Reservation>& res) {
114 : DCHECK_EQ(0, reservations_[FIRST_SPACE].size());
115 : int current_space = FIRST_SPACE;
116 3811663 : for (auto& r : res) {
117 7190109 : reservations_[current_space].push_back(
118 : {r.chunk_size(), kNullAddress, kNullAddress});
119 3595055 : if (r.is_last()) current_space++;
120 : }
121 : DCHECK_EQ(kNumberOfSpaces, current_space);
122 1083045 : for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) current_chunk_[i] = 0;
123 216609 : }
124 :
125 216611 : bool DeserializerAllocator::ReserveSpace() {
126 : #ifdef DEBUG
127 : for (int i = FIRST_SPACE; i < kNumberOfSpaces; ++i) {
128 : DCHECK_GT(reservations_[i].size(), 0);
129 : }
130 : #endif // DEBUG
131 : DCHECK(allocated_maps_.empty());
132 216611 : if (!heap_->ReserveSpace(reservations_, &allocated_maps_)) {
133 : return false;
134 : }
135 1949500 : for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) {
136 866444 : high_water_[i] = reservations_[i][0].start;
137 : }
138 : return true;
139 : }
140 :
141 0 : bool DeserializerAllocator::ReservationsAreFullyUsed() const {
142 0 : for (int space = 0; space < kNumberOfPreallocatedSpaces; space++) {
143 0 : const uint32_t chunk_index = current_chunk_[space];
144 0 : if (reservations_[space].size() != chunk_index + 1) {
145 : return false;
146 : }
147 0 : if (reservations_[space][chunk_index].end != high_water_[space]) {
148 : return false;
149 : }
150 : }
151 0 : return (allocated_maps_.size() == next_map_index_);
152 : }
153 :
154 91871 : void DeserializerAllocator::RegisterDeserializedObjectsForBlackAllocation() {
155 91871 : heap_->RegisterDeserializedObjectsForBlackAllocation(
156 91871 : reservations_, deserialized_large_objects_, allocated_maps_);
157 91872 : }
158 :
159 : } // namespace internal
160 122004 : } // namespace v8
|