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/builtin-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 :
11 : namespace v8 {
12 : namespace internal {
13 :
14 155730 : BuiltinDeserializerAllocator::BuiltinDeserializerAllocator(
15 : Deserializer<BuiltinDeserializerAllocator>* deserializer)
16 155730 : : deserializer_(deserializer) {}
17 :
18 25042057 : Address BuiltinDeserializerAllocator::Allocate(AllocationSpace space,
19 : int size) {
20 25042057 : const int builtin_id = deserializer()->CurrentBuiltinId();
21 : DCHECK_EQ(CODE_SPACE, space);
22 : DCHECK_EQ(deserializer()->ExtractBuiltinSize(builtin_id), size);
23 : #ifdef DEBUG
24 : RegisterBuiltinAllocation(builtin_id);
25 : #endif
26 : Object* obj = isolate()->builtins()->builtin(builtin_id);
27 : DCHECK(Internals::HasHeapObjectTag(obj));
28 25042057 : return HeapObject::cast(obj)->address();
29 : }
30 :
31 : Heap::Reservation
32 54968 : BuiltinDeserializerAllocator::CreateReservationsForEagerBuiltins() {
33 : Heap::Reservation result;
34 :
35 : // DeserializeLazy is always the first reservation (to simplify logic in
36 : // InitializeBuiltinsTable).
37 : {
38 : DCHECK(!Builtins::IsLazy(Builtins::kDeserializeLazy));
39 : uint32_t builtin_size =
40 54968 : deserializer()->ExtractBuiltinSize(Builtins::kDeserializeLazy);
41 : DCHECK_LE(builtin_size, MemoryAllocator::PageAreaSize(CODE_SPACE));
42 109947 : result.push_back({builtin_size, nullptr, nullptr});
43 : }
44 :
45 38587156 : for (int i = 0; i < Builtins::builtin_count; i++) {
46 38532188 : if (i == Builtins::kDeserializeLazy) continue;
47 :
48 : // Skip lazy builtins. These will be replaced by the DeserializeLazy code
49 : // object in InitializeBuiltinsTable and thus require no reserved space.
50 38477240 : if (deserializer()->IsLazyDeserializationEnabled() && Builtins::IsLazy(i)) {
51 : continue;
52 : }
53 :
54 24886338 : uint32_t builtin_size = deserializer()->ExtractBuiltinSize(i);
55 : DCHECK_LE(builtin_size, MemoryAllocator::PageAreaSize(CODE_SPACE));
56 49772659 : result.push_back({builtin_size, nullptr, nullptr});
57 : }
58 :
59 54968 : return result;
60 : }
61 :
62 24941077 : void BuiltinDeserializerAllocator::InitializeBuiltinFromReservation(
63 : const Heap::Chunk& chunk, int builtin_id) {
64 : DCHECK_EQ(deserializer()->ExtractBuiltinSize(builtin_id), chunk.size);
65 : DCHECK_EQ(chunk.size, chunk.end - chunk.start);
66 :
67 24941077 : SkipList::Update(chunk.start, chunk.size);
68 : isolate()->builtins()->set_builtin(builtin_id,
69 49882332 : HeapObject::FromAddress(chunk.start));
70 :
71 : #ifdef DEBUG
72 : RegisterBuiltinReservation(builtin_id);
73 : #endif
74 24941034 : }
75 :
76 54968 : void BuiltinDeserializerAllocator::InitializeBuiltinsTable(
77 24941046 : const Heap::Reservation& reservation) {
78 : DCHECK(!AllowHeapAllocation::IsAllowed());
79 :
80 54968 : Builtins* builtins = isolate()->builtins();
81 : int reservation_index = 0;
82 :
83 : // Other builtins can be replaced by DeserializeLazy so it may not be lazy.
84 : // It always occupies the first reservation slot.
85 : {
86 : DCHECK(!Builtins::IsLazy(Builtins::kDeserializeLazy));
87 : InitializeBuiltinFromReservation(reservation[reservation_index],
88 54968 : Builtins::kDeserializeLazy);
89 : reservation_index++;
90 : }
91 :
92 : Code* deserialize_lazy = builtins->builtin(Builtins::kDeserializeLazy);
93 :
94 38586689 : for (int i = 0; i < Builtins::builtin_count; i++) {
95 38531721 : if (i == Builtins::kDeserializeLazy) continue;
96 :
97 38476732 : if (deserializer()->IsLazyDeserializationEnabled() && Builtins::IsLazy(i)) {
98 13591086 : builtins->set_builtin(i, deserialize_lazy);
99 : } else {
100 49772156 : InitializeBuiltinFromReservation(reservation[reservation_index], i);
101 24886083 : reservation_index++;
102 : }
103 : }
104 :
105 : DCHECK_EQ(reservation.size(), reservation_index);
106 54968 : }
107 :
108 100762 : void BuiltinDeserializerAllocator::ReserveAndInitializeBuiltinsTableForBuiltin(
109 : int builtin_id) {
110 : DCHECK(AllowHeapAllocation::IsAllowed());
111 : DCHECK(isolate()->builtins()->is_initialized());
112 : DCHECK(Builtins::IsBuiltinId(builtin_id));
113 : DCHECK_NE(Builtins::kDeserializeLazy, builtin_id);
114 : DCHECK_EQ(Builtins::kDeserializeLazy,
115 : isolate()->builtins()->builtin(builtin_id)->builtin_index());
116 :
117 100762 : const uint32_t builtin_size = deserializer()->ExtractBuiltinSize(builtin_id);
118 : DCHECK_LE(builtin_size, MemoryAllocator::PageAreaSize(CODE_SPACE));
119 :
120 : Handle<HeapObject> o =
121 100762 : isolate()->factory()->NewCodeForDeserialization(builtin_size);
122 :
123 : // Note: After this point and until deserialization finishes, heap allocation
124 : // is disallowed. We currently can't safely assert this since we'd need to
125 : // pass the DisallowHeapAllocation scope out of this function.
126 :
127 : // Write the allocated filler object into the builtins table. It will be
128 : // returned by our custom Allocate method below once needed.
129 :
130 100762 : isolate()->builtins()->set_builtin(builtin_id, *o);
131 :
132 : #ifdef DEBUG
133 : RegisterBuiltinReservation(builtin_id);
134 : #endif
135 100762 : }
136 :
137 : #ifdef DEBUG
138 : void BuiltinDeserializerAllocator::RegisterBuiltinReservation(int builtin_id) {
139 : const auto result = unused_reservations_.emplace(builtin_id);
140 : CHECK(result.second); // False, iff builtin_id was already present in set.
141 : }
142 :
143 : void BuiltinDeserializerAllocator::RegisterBuiltinAllocation(int builtin_id) {
144 : const size_t removed_elems = unused_reservations_.erase(builtin_id);
145 : CHECK_EQ(removed_elems, 1);
146 : }
147 :
148 : bool BuiltinDeserializerAllocator::ReservationsAreFullyUsed() const {
149 : // Not 100% precise but should be good enough.
150 : return unused_reservations_.empty();
151 : }
152 : #endif // DEBUG
153 :
154 0 : Isolate* BuiltinDeserializerAllocator::isolate() const {
155 50239715 : return deserializer()->isolate();
156 : }
157 :
158 0 : BuiltinDeserializer* BuiltinDeserializerAllocator::deserializer() const {
159 152235755 : return static_cast<BuiltinDeserializer*>(deserializer_);
160 : }
161 :
162 : } // namespace internal
163 : } // namespace v8
|