OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium 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 "platform/heap/HeapCompact.h" | 5 #include "platform/heap/HeapCompact.h" |
6 | 6 |
7 #include "platform/heap/Handle.h" | 7 #include "platform/heap/Handle.h" |
8 #include "platform/heap/SparseHeapBitmap.h" | 8 #include "platform/heap/SparseHeapBitmap.h" |
9 #include "platform/wtf/Deque.h" | 9 #include "platform/wtf/Deque.h" |
10 #include "platform/wtf/HashMap.h" | 10 #include "platform/wtf/HashMap.h" |
11 #include "platform/wtf/LinkedHashSet.h" | 11 #include "platform/wtf/LinkedHashSet.h" |
12 #include "platform/wtf/Vector.h" | 12 #include "platform/wtf/Vector.h" |
13 #include "testing/gtest/include/gtest/gtest.h" | 13 #include "testing/gtest/include/gtest/gtest.h" |
14 | 14 |
15 #include <memory> | 15 #include <memory> |
16 | 16 |
17 namespace { | 17 namespace { |
18 | 18 |
| 19 enum VerifyArenaCompaction { |
| 20 NoVerify, |
| 21 VectorsAreCompacted, |
| 22 HashTablesAreCompacted, |
| 23 }; |
| 24 |
19 class IntWrapper : public blink::GarbageCollectedFinalized<IntWrapper> { | 25 class IntWrapper : public blink::GarbageCollectedFinalized<IntWrapper> { |
20 public: | 26 public: |
21 static IntWrapper* Create(int x) { return new IntWrapper(x); } | 27 static IntWrapper* Create(int x, VerifyArenaCompaction verify = NoVerify) { |
| 28 return new IntWrapper(x, verify); |
| 29 } |
22 | 30 |
23 virtual ~IntWrapper() {} | 31 virtual ~IntWrapper() {} |
24 | 32 |
25 DEFINE_INLINE_TRACE() {} | 33 DEFINE_INLINE_TRACE() { |
| 34 // Verify if compaction is indeed activated. |
| 35 // |
| 36 // What arenas end up being compacted is dependent on residency, |
| 37 // so approximate the arena checks to fit. |
| 38 blink::HeapCompact* compaction = visitor->Heap().Compaction(); |
| 39 switch (verify_) { |
| 40 case NoVerify: |
| 41 return; |
| 42 case HashTablesAreCompacted: |
| 43 CHECK(compaction->IsCompactingArena( |
| 44 blink::BlinkGC::kHashTableArenaIndex)); |
| 45 return; |
| 46 case VectorsAreCompacted: |
| 47 CHECK(compaction->IsCompactingVectorArenas()); |
| 48 return; |
| 49 } |
| 50 } |
26 | 51 |
27 int Value() const { return x_; } | 52 int Value() const { return x_; } |
28 | 53 |
29 bool operator==(const IntWrapper& other) const { | 54 bool operator==(const IntWrapper& other) const { |
30 return other.Value() == Value(); | 55 return other.Value() == Value(); |
31 } | 56 } |
32 | 57 |
33 unsigned GetHash() { return IntHash<int>::GetHash(x_); } | 58 unsigned GetHash() { return IntHash<int>::GetHash(x_); } |
34 | 59 |
35 IntWrapper(int x) : x_(x) {} | 60 IntWrapper(int x, VerifyArenaCompaction verify) : x_(x), verify_(verify) {} |
36 | 61 |
37 private: | 62 private: |
38 IntWrapper(); | 63 IntWrapper(); |
| 64 |
39 int x_; | 65 int x_; |
| 66 VerifyArenaCompaction verify_; |
40 }; | 67 }; |
41 static_assert(WTF::IsTraceable<IntWrapper>::value, | 68 static_assert(WTF::IsTraceable<IntWrapper>::value, |
42 "IsTraceable<> template failed to recognize trace method."); | 69 "IsTraceable<> template failed to recognize trace method."); |
43 | 70 |
44 } // namespace | 71 } // namespace |
45 | 72 |
46 using IntVector = blink::HeapVector<blink::Member<IntWrapper>>; | 73 using IntVector = blink::HeapVector<blink::Member<IntWrapper>>; |
47 using IntDeque = blink::HeapDeque<blink::Member<IntWrapper>>; | 74 using IntDeque = blink::HeapDeque<blink::Member<IntWrapper>>; |
48 using IntMap = blink::HeapHashMap<blink::Member<IntWrapper>, int>; | 75 using IntMap = blink::HeapHashMap<blink::Member<IntWrapper>, int>; |
49 // TODO(sof): decide if this ought to be a global trait specialization. | 76 // TODO(sof): decide if this ought to be a global trait specialization. |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 size_t used = heap.ObjectPayloadSizeForTesting(); | 237 size_t used = heap.ObjectPayloadSizeForTesting(); |
211 PreciselyCollectGarbage(); | 238 PreciselyCollectGarbage(); |
212 if (heap.ObjectPayloadSizeForTesting() >= used) | 239 if (heap.ObjectPayloadSizeForTesting() >= used) |
213 break; | 240 break; |
214 } | 241 } |
215 } | 242 } |
216 | 243 |
217 TEST(HeapCompactTest, CompactVector) { | 244 TEST(HeapCompactTest, CompactVector) { |
218 ClearOutOldGarbage(); | 245 ClearOutOldGarbage(); |
219 | 246 |
220 IntWrapper* val = IntWrapper::Create(1); | 247 IntWrapper* val = IntWrapper::Create(1, VectorsAreCompacted); |
221 Persistent<IntVector> vector = new IntVector(10, val); | 248 Persistent<IntVector> vector = new IntVector(10, val); |
222 EXPECT_EQ(10u, vector->size()); | 249 EXPECT_EQ(10u, vector->size()); |
223 | 250 |
224 for (size_t i = 0; i < vector->size(); ++i) | 251 for (size_t i = 0; i < vector->size(); ++i) |
225 EXPECT_EQ(val, (*vector)[i]); | 252 EXPECT_EQ(val, (*vector)[i]); |
226 | 253 |
227 PerformHeapCompaction(); | 254 PerformHeapCompaction(); |
228 | 255 |
229 for (size_t i = 0; i < vector->size(); ++i) | 256 for (size_t i = 0; i < vector->size(); ++i) |
230 EXPECT_EQ(val, (*vector)[i]); | 257 EXPECT_EQ(val, (*vector)[i]); |
231 } | 258 } |
232 | 259 |
233 TEST(HeapCompactTest, CompactHashMap) { | 260 TEST(HeapCompactTest, CompactHashMap) { |
234 ClearOutOldGarbage(); | 261 ClearOutOldGarbage(); |
235 | 262 |
236 Persistent<IntMap> int_map = new IntMap(); | 263 Persistent<IntMap> int_map = new IntMap(); |
237 for (size_t i = 0; i < 100; ++i) { | 264 for (size_t i = 0; i < 100; ++i) { |
238 IntWrapper* val = IntWrapper::Create(i); | 265 IntWrapper* val = IntWrapper::Create(i, HashTablesAreCompacted); |
239 int_map->insert(val, 100 - i); | 266 int_map->insert(val, 100 - i); |
240 } | 267 } |
241 | 268 |
242 EXPECT_EQ(100u, int_map->size()); | 269 EXPECT_EQ(100u, int_map->size()); |
243 for (auto k : *int_map) | 270 for (auto k : *int_map) |
244 EXPECT_EQ(k.key->Value(), 100 - k.value); | 271 EXPECT_EQ(k.key->Value(), 100 - k.value); |
245 | 272 |
246 PerformHeapCompaction(); | 273 PerformHeapCompaction(); |
247 | 274 |
248 for (auto k : *int_map) | 275 for (auto k : *int_map) |
249 EXPECT_EQ(k.key->Value(), 100 - k.value); | 276 EXPECT_EQ(k.key->Value(), 100 - k.value); |
250 } | 277 } |
251 | 278 |
252 TEST(HeapCompactTest, CompactVectorPartHashMap) { | 279 TEST(HeapCompactTest, CompactVectorPartHashMap) { |
253 ClearOutOldGarbage(); | 280 ClearOutOldGarbage(); |
254 | 281 |
255 using IntMapVector = HeapVector<IntMap>; | 282 using IntMapVector = HeapVector<IntMap>; |
256 | 283 |
257 Persistent<IntMapVector> int_map_vector = new IntMapVector(); | 284 Persistent<IntMapVector> int_map_vector = new IntMapVector(); |
258 for (size_t i = 0; i < 10; ++i) { | 285 for (size_t i = 0; i < 10; ++i) { |
259 IntMap map; | 286 IntMap map; |
260 for (size_t j = 0; j < 10; ++j) { | 287 for (size_t j = 0; j < 10; ++j) { |
261 IntWrapper* val = IntWrapper::Create(j); | 288 IntWrapper* val = IntWrapper::Create(j, VectorsAreCompacted); |
262 map.insert(val, 10 - j); | 289 map.insert(val, 10 - j); |
263 } | 290 } |
264 int_map_vector->push_back(map); | 291 int_map_vector->push_back(map); |
265 } | 292 } |
266 | 293 |
267 EXPECT_EQ(10u, int_map_vector->size()); | 294 EXPECT_EQ(10u, int_map_vector->size()); |
268 for (auto map : *int_map_vector) { | 295 for (auto map : *int_map_vector) { |
269 EXPECT_EQ(10u, map.size()); | 296 EXPECT_EQ(10u, map.size()); |
270 for (auto k : map) { | 297 for (auto k : map) { |
271 EXPECT_EQ(k.key->Value(), 10 - k.value); | 298 EXPECT_EQ(k.key->Value(), 10 - k.value); |
(...skipping 13 matching lines...) Expand all Loading... |
285 | 312 |
286 TEST(HeapCompactTest, CompactHashPartVector) { | 313 TEST(HeapCompactTest, CompactHashPartVector) { |
287 ClearOutOldGarbage(); | 314 ClearOutOldGarbage(); |
288 | 315 |
289 using IntVectorMap = HeapHashMap<int, IntVector>; | 316 using IntVectorMap = HeapHashMap<int, IntVector>; |
290 | 317 |
291 Persistent<IntVectorMap> int_vector_map = new IntVectorMap(); | 318 Persistent<IntVectorMap> int_vector_map = new IntVectorMap(); |
292 for (size_t i = 0; i < 10; ++i) { | 319 for (size_t i = 0; i < 10; ++i) { |
293 IntVector vector; | 320 IntVector vector; |
294 for (size_t j = 0; j < 10; ++j) { | 321 for (size_t j = 0; j < 10; ++j) { |
295 vector.push_back(IntWrapper::Create(j)); | 322 vector.push_back(IntWrapper::Create(j, HashTablesAreCompacted)); |
296 } | 323 } |
297 int_vector_map->insert(1 + i, vector); | 324 int_vector_map->insert(1 + i, vector); |
298 } | 325 } |
299 | 326 |
300 EXPECT_EQ(10u, int_vector_map->size()); | 327 EXPECT_EQ(10u, int_vector_map->size()); |
301 for (const IntVector& int_vector : int_vector_map->Values()) { | 328 for (const IntVector& int_vector : int_vector_map->Values()) { |
302 EXPECT_EQ(10u, int_vector.size()); | 329 EXPECT_EQ(10u, int_vector.size()); |
303 for (size_t i = 0; i < int_vector.size(); ++i) { | 330 for (size_t i = 0; i < int_vector.size(); ++i) { |
304 EXPECT_EQ(static_cast<int>(i), int_vector[i]->Value()); | 331 EXPECT_EQ(static_cast<int>(i), int_vector[i]->Value()); |
305 } | 332 } |
306 } | 333 } |
307 | 334 |
308 PerformHeapCompaction(); | 335 PerformHeapCompaction(); |
309 | 336 |
310 EXPECT_EQ(10u, int_vector_map->size()); | 337 EXPECT_EQ(10u, int_vector_map->size()); |
311 for (const IntVector& int_vector : int_vector_map->Values()) { | 338 for (const IntVector& int_vector : int_vector_map->Values()) { |
312 EXPECT_EQ(10u, int_vector.size()); | 339 EXPECT_EQ(10u, int_vector.size()); |
313 for (size_t i = 0; i < int_vector.size(); ++i) { | 340 for (size_t i = 0; i < int_vector.size(); ++i) { |
314 EXPECT_EQ(static_cast<int>(i), int_vector[i]->Value()); | 341 EXPECT_EQ(static_cast<int>(i), int_vector[i]->Value()); |
315 } | 342 } |
316 } | 343 } |
317 } | 344 } |
318 | 345 |
319 TEST(HeapCompactTest, CompactDeques) { | 346 TEST(HeapCompactTest, CompactDeques) { |
320 Persistent<IntDeque> deque = new IntDeque; | 347 Persistent<IntDeque> deque = new IntDeque; |
321 for (int i = 0; i < 8; ++i) { | 348 for (int i = 0; i < 8; ++i) { |
322 deque->push_front(IntWrapper::Create(i)); | 349 deque->push_front(IntWrapper::Create(i, VectorsAreCompacted)); |
323 } | 350 } |
324 EXPECT_EQ(8u, deque->size()); | 351 EXPECT_EQ(8u, deque->size()); |
325 | 352 |
326 for (size_t i = 0; i < deque->size(); ++i) | 353 for (size_t i = 0; i < deque->size(); ++i) |
327 EXPECT_EQ(static_cast<int>(7 - i), deque->at(i)->Value()); | 354 EXPECT_EQ(static_cast<int>(7 - i), deque->at(i)->Value()); |
328 | 355 |
329 PerformHeapCompaction(); | 356 PerformHeapCompaction(); |
330 | 357 |
331 for (size_t i = 0; i < deque->size(); ++i) | 358 for (size_t i = 0; i < deque->size(); ++i) |
332 EXPECT_EQ(static_cast<int>(7 - i), deque->at(i)->Value()); | 359 EXPECT_EQ(static_cast<int>(7 - i), deque->at(i)->Value()); |
333 } | 360 } |
334 | 361 |
335 TEST(HeapCompactTest, CompactDequeVectors) { | 362 TEST(HeapCompactTest, CompactDequeVectors) { |
336 Persistent<HeapDeque<IntVector>> deque = new HeapDeque<IntVector>; | 363 Persistent<HeapDeque<IntVector>> deque = new HeapDeque<IntVector>; |
337 for (int i = 0; i < 8; ++i) { | 364 for (int i = 0; i < 8; ++i) { |
338 IntWrapper* value = IntWrapper::Create(i); | 365 IntWrapper* value = IntWrapper::Create(i, VectorsAreCompacted); |
339 IntVector vector = IntVector(8, value); | 366 IntVector vector = IntVector(8, value); |
340 deque->push_front(vector); | 367 deque->push_front(vector); |
341 } | 368 } |
342 EXPECT_EQ(8u, deque->size()); | 369 EXPECT_EQ(8u, deque->size()); |
343 | 370 |
344 for (size_t i = 0; i < deque->size(); ++i) | 371 for (size_t i = 0; i < deque->size(); ++i) |
345 EXPECT_EQ(static_cast<int>(7 - i), deque->at(i).at(i)->Value()); | 372 EXPECT_EQ(static_cast<int>(7 - i), deque->at(i).at(i)->Value()); |
346 | 373 |
347 PerformHeapCompaction(); | 374 PerformHeapCompaction(); |
348 | 375 |
349 for (size_t i = 0; i < deque->size(); ++i) | 376 for (size_t i = 0; i < deque->size(); ++i) |
350 EXPECT_EQ(static_cast<int>(7 - i), deque->at(i).at(i)->Value()); | 377 EXPECT_EQ(static_cast<int>(7 - i), deque->at(i).at(i)->Value()); |
351 } | 378 } |
352 | 379 |
353 TEST(HeapCompactTest, CompactLinkedHashSet) { | 380 TEST(HeapCompactTest, CompactLinkedHashSet) { |
354 using OrderedHashSet = HeapLinkedHashSet<Member<IntWrapper>>; | 381 using OrderedHashSet = HeapLinkedHashSet<Member<IntWrapper>>; |
355 Persistent<OrderedHashSet> set = new OrderedHashSet; | 382 Persistent<OrderedHashSet> set = new OrderedHashSet; |
356 for (int i = 0; i < 13; ++i) { | 383 for (int i = 0; i < 13; ++i) { |
357 IntWrapper* value = IntWrapper::Create(i); | 384 IntWrapper* value = IntWrapper::Create(i, HashTablesAreCompacted); |
358 set->insert(value); | 385 set->insert(value); |
359 } | 386 } |
360 EXPECT_EQ(13u, set->size()); | 387 EXPECT_EQ(13u, set->size()); |
361 | 388 |
362 int expected = 0; | 389 int expected = 0; |
363 for (IntWrapper* v : *set) { | 390 for (IntWrapper* v : *set) { |
364 EXPECT_EQ(expected, v->Value()); | 391 EXPECT_EQ(expected, v->Value()); |
365 expected++; | 392 expected++; |
366 } | 393 } |
367 | 394 |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
453 | 480 |
454 expected = 0; | 481 expected = 0; |
455 for (const Inner* v : *set) { | 482 for (const Inner* v : *set) { |
456 EXPECT_EQ(1u, v->size()); | 483 EXPECT_EQ(1u, v->size()); |
457 EXPECT_EQ(expected, (*v->begin())->Value()); | 484 EXPECT_EQ(expected, (*v->begin())->Value()); |
458 expected++; | 485 expected++; |
459 } | 486 } |
460 } | 487 } |
461 #endif | 488 #endif |
462 } // namespace blink | 489 } // namespace blink |
OLD | NEW |