Line data Source code
1 : // Copyright 2015 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 <vector>
6 :
7 : #include "src/globals.h"
8 : #include "src/heap/heap-inl.h"
9 : #include "src/heap/spaces-inl.h"
10 : #include "src/objects.h"
11 : #include "test/cctest/cctest.h"
12 :
13 : namespace v8 {
14 : namespace internal {
15 : namespace heap {
16 :
17 30 : static Address AllocateLabBackingStore(Heap* heap, intptr_t size_in_bytes) {
18 : AllocationResult result = heap->old_space()->AllocateRaw(
19 30 : static_cast<int>(size_in_bytes), kDoubleAligned);
20 : Address adr = result.ToObjectChecked()->address();
21 30 : return adr;
22 : }
23 :
24 :
25 30 : static void VerifyIterable(v8::internal::Address base,
26 : v8::internal::Address limit,
27 : std::vector<intptr_t> expected_size) {
28 30 : CHECK_LE(base, limit);
29 30 : HeapObject object;
30 : size_t counter = 0;
31 290 : while (base < limit) {
32 130 : object = HeapObject::FromAddress(base);
33 130 : CHECK(object->IsFiller());
34 130 : CHECK_LT(counter, expected_size.size());
35 390 : CHECK_EQ(expected_size[counter], object->Size());
36 130 : base += object->Size();
37 130 : counter++;
38 : }
39 30 : }
40 :
41 :
42 95 : static bool AllocateFromLab(Heap* heap, LocalAllocationBuffer* lab,
43 : intptr_t size_in_bytes,
44 : AllocationAlignment alignment = kWordAligned) {
45 : HeapObject obj;
46 : AllocationResult result =
47 95 : lab->AllocateRawAligned(static_cast<int>(size_in_bytes), alignment);
48 95 : if (result.To(&obj)) {
49 : heap->CreateFillerObjectAt(obj->address(), static_cast<int>(size_in_bytes),
50 90 : ClearRecordedSlots::kNo);
51 90 : return true;
52 : }
53 : return false;
54 : }
55 :
56 :
57 26644 : TEST(InvalidLab) {
58 : LocalAllocationBuffer lab = LocalAllocationBuffer::InvalidBuffer();
59 5 : CHECK(!lab.IsValid());
60 5 : }
61 :
62 :
63 26644 : TEST(UnusedLabImplicitClose) {
64 5 : CcTest::InitializeVM();
65 5 : Heap* heap = CcTest::heap();
66 : const int kLabSize = 4 * KB;
67 5 : Address base = AllocateLabBackingStore(heap, kLabSize);
68 5 : Address limit = base + kLabSize;
69 5 : intptr_t expected_sizes_raw[1] = {kLabSize};
70 : std::vector<intptr_t> expected_sizes(expected_sizes_raw,
71 : expected_sizes_raw + 1);
72 : {
73 : AllocationResult lab_backing_store(HeapObject::FromAddress(base));
74 : LocalAllocationBuffer lab =
75 5 : LocalAllocationBuffer::FromResult(heap, lab_backing_store, kLabSize);
76 5 : CHECK(lab.IsValid());
77 : }
78 10 : VerifyIterable(base, limit, expected_sizes);
79 5 : }
80 :
81 :
82 26644 : TEST(SimpleAllocate) {
83 5 : CcTest::InitializeVM();
84 5 : Heap* heap = CcTest::heap();
85 : const int kLabSize = 4 * KB;
86 5 : Address base = AllocateLabBackingStore(heap, kLabSize);
87 5 : Address limit = base + kLabSize;
88 5 : intptr_t sizes_raw[1] = {128};
89 5 : intptr_t expected_sizes_raw[2] = {128, kLabSize - 128};
90 : std::vector<intptr_t> sizes(sizes_raw, sizes_raw + 1);
91 : std::vector<intptr_t> expected_sizes(expected_sizes_raw,
92 : expected_sizes_raw + 2);
93 : {
94 : AllocationResult lab_backing_store(HeapObject::FromAddress(base));
95 : LocalAllocationBuffer lab =
96 5 : LocalAllocationBuffer::FromResult(heap, lab_backing_store, kLabSize);
97 5 : CHECK(lab.IsValid());
98 : intptr_t sum = 0;
99 10 : for (auto size : sizes) {
100 5 : if (AllocateFromLab(heap, &lab, size)) {
101 : sum += size;
102 : }
103 : }
104 : }
105 10 : VerifyIterable(base, limit, expected_sizes);
106 5 : }
107 :
108 :
109 26644 : TEST(AllocateUntilLabOOM) {
110 5 : CcTest::InitializeVM();
111 5 : Heap* heap = CcTest::heap();
112 : const int kLabSize = 2 * KB;
113 5 : Address base = AllocateLabBackingStore(heap, kLabSize);
114 5 : Address limit = base + kLabSize;
115 : // The following objects won't fit in {kLabSize}.
116 5 : intptr_t sizes_raw[5] = {512, 512, 128, 512, 512};
117 5 : intptr_t expected_sizes_raw[5] = {512, 512, 128, 512, 384 /* left over */};
118 : std::vector<intptr_t> sizes(sizes_raw, sizes_raw + 5);
119 : std::vector<intptr_t> expected_sizes(expected_sizes_raw,
120 : expected_sizes_raw + 5);
121 : intptr_t sum = 0;
122 : {
123 : AllocationResult lab_backing_store(HeapObject::FromAddress(base));
124 : LocalAllocationBuffer lab =
125 5 : LocalAllocationBuffer::FromResult(heap, lab_backing_store, kLabSize);
126 5 : CHECK(lab.IsValid());
127 30 : for (auto size : sizes) {
128 25 : if (AllocateFromLab(heap, &lab, size)) {
129 20 : sum += size;
130 : }
131 : }
132 5 : CHECK_EQ(kLabSize - sum, 384);
133 : }
134 10 : VerifyIterable(base, limit, expected_sizes);
135 5 : }
136 :
137 :
138 26644 : TEST(AllocateExactlyUntilLimit) {
139 5 : CcTest::InitializeVM();
140 5 : Heap* heap = CcTest::heap();
141 : const int kLabSize = 2 * KB;
142 5 : Address base = AllocateLabBackingStore(heap, kLabSize);
143 5 : Address limit = base + kLabSize;
144 5 : intptr_t sizes_raw[4] = {512, 512, 512, 512};
145 5 : intptr_t expected_sizes_raw[5] = {512, 512, 512, 512, 0};
146 : std::vector<intptr_t> sizes(sizes_raw, sizes_raw + 4);
147 : std::vector<intptr_t> expected_sizes(expected_sizes_raw,
148 : expected_sizes_raw + 5);
149 : {
150 : AllocationResult lab_backing_store(HeapObject::FromAddress(base));
151 : LocalAllocationBuffer lab =
152 5 : LocalAllocationBuffer::FromResult(heap, lab_backing_store, kLabSize);
153 5 : CHECK(lab.IsValid());
154 : intptr_t sum = 0;
155 25 : for (auto size : sizes) {
156 20 : if (AllocateFromLab(heap, &lab, size)) {
157 20 : sum += size;
158 : } else {
159 : break;
160 : }
161 : }
162 5 : CHECK_EQ(kLabSize - sum, 0);
163 : }
164 10 : VerifyIterable(base, limit, expected_sizes);
165 5 : }
166 :
167 :
168 26644 : TEST(MergeSuccessful) {
169 5 : CcTest::InitializeVM();
170 5 : Heap* heap = CcTest::heap();
171 : const int kLabSize = 2 * KB;
172 5 : Address base1 = AllocateLabBackingStore(heap, 2 * kLabSize);
173 5 : Address limit1 = base1 + kLabSize;
174 : Address base2 = limit1;
175 5 : Address limit2 = base2 + kLabSize;
176 :
177 5 : intptr_t sizes1_raw[4] = {512, 512, 512, 256};
178 5 : intptr_t expected_sizes1_raw[5] = {512, 512, 512, 256, 256};
179 : std::vector<intptr_t> sizes1(sizes1_raw, sizes1_raw + 4);
180 : std::vector<intptr_t> expected_sizes1(expected_sizes1_raw,
181 : expected_sizes1_raw + 5);
182 :
183 5 : intptr_t sizes2_raw[5] = {256, 512, 512, 512, 512};
184 : intptr_t expected_sizes2_raw[10] = {512, 512, 512, 256, 256,
185 5 : 512, 512, 512, 512, 0};
186 : std::vector<intptr_t> sizes2(sizes2_raw, sizes2_raw + 5);
187 : std::vector<intptr_t> expected_sizes2(expected_sizes2_raw,
188 : expected_sizes2_raw + 10);
189 :
190 : {
191 : AllocationResult lab_backing_store1(HeapObject::FromAddress(base1));
192 : LocalAllocationBuffer lab1 =
193 5 : LocalAllocationBuffer::FromResult(heap, lab_backing_store1, kLabSize);
194 5 : CHECK(lab1.IsValid());
195 : intptr_t sum = 0;
196 25 : for (auto size : sizes1) {
197 20 : if (AllocateFromLab(heap, &lab1, size)) {
198 20 : sum += size;
199 : } else {
200 : break;
201 : }
202 : }
203 :
204 : AllocationResult lab_backing_store2(HeapObject::FromAddress(base2));
205 : LocalAllocationBuffer lab2 =
206 5 : LocalAllocationBuffer::FromResult(heap, lab_backing_store2, kLabSize);
207 5 : CHECK(lab2.IsValid());
208 5 : CHECK(lab2.TryMerge(&lab1));
209 5 : CHECK(!lab1.IsValid());
210 30 : for (auto size : sizes2) {
211 25 : if (AllocateFromLab(heap, &lab2, size)) {
212 25 : sum += size;
213 : } else {
214 : break;
215 : }
216 : }
217 5 : CHECK_EQ(2 * kLabSize - sum, 0);
218 : }
219 10 : VerifyIterable(base1, limit1, expected_sizes1);
220 10 : VerifyIterable(base1, limit2, expected_sizes2);
221 5 : }
222 :
223 :
224 26644 : TEST(MergeFailed) {
225 5 : CcTest::InitializeVM();
226 5 : Heap* heap = CcTest::heap();
227 : const int kLabSize = 2 * KB;
228 5 : Address base1 = AllocateLabBackingStore(heap, 3 * kLabSize);
229 : Address base2 = base1 + kLabSize;
230 : Address base3 = base2 + kLabSize;
231 :
232 : {
233 : AllocationResult lab_backing_store1(HeapObject::FromAddress(base1));
234 : LocalAllocationBuffer lab1 =
235 5 : LocalAllocationBuffer::FromResult(heap, lab_backing_store1, kLabSize);
236 5 : CHECK(lab1.IsValid());
237 :
238 : AllocationResult lab_backing_store2(HeapObject::FromAddress(base2));
239 : LocalAllocationBuffer lab2 =
240 5 : LocalAllocationBuffer::FromResult(heap, lab_backing_store2, kLabSize);
241 5 : CHECK(lab2.IsValid());
242 :
243 : AllocationResult lab_backing_store3(HeapObject::FromAddress(base3));
244 : LocalAllocationBuffer lab3 =
245 5 : LocalAllocationBuffer::FromResult(heap, lab_backing_store3, kLabSize);
246 5 : CHECK(lab3.IsValid());
247 :
248 5 : CHECK(!lab3.TryMerge(&lab1));
249 : }
250 5 : }
251 :
252 :
253 : #ifdef V8_HOST_ARCH_32_BIT
254 : TEST(AllocateAligned) {
255 : CcTest::InitializeVM();
256 : Heap* heap = CcTest::heap();
257 : const int kLabSize = 2 * KB;
258 : Address base = AllocateLabBackingStore(heap, kLabSize);
259 : Address limit = base + kLabSize;
260 : std::pair<intptr_t, AllocationAlignment> sizes_raw[2] = {
261 : std::make_pair(116, kWordAligned), std::make_pair(64, kDoubleAligned)};
262 : std::vector<std::pair<intptr_t, AllocationAlignment>> sizes(sizes_raw,
263 : sizes_raw + 2);
264 : intptr_t expected_sizes_raw[4] = {116, 4, 64, 1864};
265 : std::vector<intptr_t> expected_sizes(expected_sizes_raw,
266 : expected_sizes_raw + 4);
267 :
268 : {
269 : AllocationResult lab_backing_store(HeapObject::FromAddress(base));
270 : LocalAllocationBuffer lab =
271 : LocalAllocationBuffer::FromResult(heap, lab_backing_store, kLabSize);
272 : CHECK(lab.IsValid());
273 : for (auto pair : sizes) {
274 : if (!AllocateFromLab(heap, &lab, pair.first, pair.second)) {
275 : break;
276 : }
277 : }
278 : }
279 : VerifyIterable(base, limit, expected_sizes);
280 : }
281 : #endif // V8_HOST_ARCH_32_BIT
282 :
283 : } // namespace heap
284 : } // namespace internal
285 79917 : } // namespace v8
|