1 /*
2  * Copyright (C) 2013 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include <algorithm>
32 #include <atomic>
33 #include <memory>
34 #include <utility>
35 
36 #include "base/atomic_ref_count.h"
37 #include "base/bind.h"
38 #include "base/location.h"
39 #include "base/memory/ptr_util.h"
40 #include "base/synchronization/waitable_event.h"
41 #include "base/test/scoped_feature_list.h"
42 #include "build/build_config.h"
43 #include "testing/gtest/include/gtest/gtest.h"
44 #include "third_party/blink/public/common/features.h"
45 #include "third_party/blink/public/platform/platform.h"
46 #include "third_party/blink/renderer/platform/bindings/buildflags.h"
47 #include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
48 #include "third_party/blink/renderer/platform/heap/collection_support/heap_linked_stack.h"
49 #include "third_party/blink/renderer/platform/heap/handle.h"
50 #include "third_party/blink/renderer/platform/heap/heap.h"
51 #include "third_party/blink/renderer/platform/heap/heap_stats_collector.h"
52 #include "third_party/blink/renderer/platform/heap/heap_test_utilities.h"
53 #include "third_party/blink/renderer/platform/heap/marking_visitor.h"
54 #include "third_party/blink/renderer/platform/heap/self_keep_alive.h"
55 #include "third_party/blink/renderer/platform/heap/thread_state.h"
56 #include "third_party/blink/renderer/platform/heap/thread_state_scopes.h"
57 #include "third_party/blink/renderer/platform/heap/visitor.h"
58 #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
59 #include "third_party/blink/renderer/platform/scheduler/public/thread.h"
60 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
61 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
62 #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
63 #include "third_party/blink/renderer/platform/wtf/hash_traits.h"
64 #include "third_party/blink/renderer/platform/wtf/linked_hash_set.h"
65 
66 namespace blink {
67 
68 namespace {
69 
70 class HeapTest : public TestSupportingGC {};
71 
72 class IntWrapper : public GarbageCollected<IntWrapper> {
73  public:
~IntWrapper()74   virtual ~IntWrapper() {
75     destructor_calls_.fetch_add(1, std::memory_order_relaxed);
76   }
77 
78   static std::atomic_int destructor_calls_;
Trace(Visitor * visitor)79   void Trace(Visitor* visitor) {}
80 
Value() const81   int Value() const { return x_; }
82 
operator ==(const IntWrapper & other) const83   bool operator==(const IntWrapper& other) const {
84     return other.Value() == Value();
85   }
86 
GetHash()87   unsigned GetHash() { return IntHash<int>::GetHash(x_); }
88 
IntWrapper(int x)89   IntWrapper(int x) : x_(x) {}
90 
91  private:
92   IntWrapper() = delete;
93   int x_;
94 };
95 
96 std::atomic_int IntWrapper::destructor_calls_{0};
97 
98 struct IntWrapperHash {
GetHashblink::__anon08a198100111::IntWrapperHash99   static unsigned GetHash(const IntWrapper& key) {
100     return WTF::HashInt(static_cast<uint32_t>(key.Value()));
101   }
102 
Equalblink::__anon08a198100111::IntWrapperHash103   static bool Equal(const IntWrapper& a, const IntWrapper& b) { return a == b; }
104 };
105 
106 static_assert(WTF::IsTraceable<IntWrapper>::value,
107               "IsTraceable<> template failed to recognize trace method.");
108 static_assert(WTF::IsTraceable<HeapVector<IntWrapper>>::value,
109               "HeapVector<IntWrapper> must be traceable.");
110 static_assert(WTF::IsTraceable<HeapDeque<IntWrapper>>::value,
111               "HeapDeque<IntWrapper> must be traceable.");
112 static_assert(WTF::IsTraceable<HeapHashSet<IntWrapper, IntWrapperHash>>::value,
113               "HeapHashSet<IntWrapper> must be traceable.");
114 static_assert(WTF::IsTraceable<HeapHashMap<int, IntWrapper>>::value,
115               "HeapHashMap<int, IntWrapper> must be traceable.");
116 
117 class KeyWithCopyingMoveConstructor final {
118   DISALLOW_NEW();
119 
120  public:
121   struct Hash final {
122     STATIC_ONLY(Hash);
123 
124    public:
GetHashblink::__anon08a198100111::KeyWithCopyingMoveConstructor::Hash125     static unsigned GetHash(const KeyWithCopyingMoveConstructor& key) {
126       return key.hash_;
127     }
128 
Equalblink::__anon08a198100111::KeyWithCopyingMoveConstructor::Hash129     static bool Equal(const KeyWithCopyingMoveConstructor& x,
130                       const KeyWithCopyingMoveConstructor& y) {
131       return x.hash_ == y.hash_;
132     }
133 
134     static constexpr bool safe_to_compare_to_empty_or_deleted = true;
135   };
136 
137   KeyWithCopyingMoveConstructor() = default;
KeyWithCopyingMoveConstructor(WTF::HashTableDeletedValueType)138   KeyWithCopyingMoveConstructor(WTF::HashTableDeletedValueType) : hash_(-1) {}
139   ~KeyWithCopyingMoveConstructor() = default;
KeyWithCopyingMoveConstructor(unsigned hash,const String & string)140   KeyWithCopyingMoveConstructor(unsigned hash, const String& string)
141       : hash_(hash), string_(string) {
142     DCHECK_NE(hash_, 0);
143     DCHECK_NE(hash_, -1);
144   }
145   KeyWithCopyingMoveConstructor(const KeyWithCopyingMoveConstructor&) = default;
146   // The move constructor delegates to the copy constructor intentionally.
KeyWithCopyingMoveConstructor(KeyWithCopyingMoveConstructor && x)147   KeyWithCopyingMoveConstructor(KeyWithCopyingMoveConstructor&& x)
148       : KeyWithCopyingMoveConstructor(x) {}
149   KeyWithCopyingMoveConstructor& operator=(
150       const KeyWithCopyingMoveConstructor&) = default;
operator ==(const KeyWithCopyingMoveConstructor & x) const151   bool operator==(const KeyWithCopyingMoveConstructor& x) const {
152     return hash_ == x.hash_;
153   }
154 
IsHashTableDeletedValue() const155   bool IsHashTableDeletedValue() const { return hash_ == -1; }
156 
157  private:
158   int hash_ = 0;
159   String string_;
160 };
161 
162 struct SameSizeAsPersistent {
163   void* pointer_[4];
164 #if BUILDFLAG(RAW_HEAP_SNAPSHOTS)
165   PersistentLocation location;
166 #endif  // BUILDFLAG(RAW_HEAP_SNAPSHOTS)
167 };
168 
169 static_assert(sizeof(Persistent<IntWrapper>) <= sizeof(SameSizeAsPersistent),
170               "Persistent handle should stay small");
171 
172 class ThreadMarker {
173   DISALLOW_NEW();
174 
175  public:
ThreadMarker()176   ThreadMarker()
177       : creating_thread_(reinterpret_cast<ThreadState*>(0)), num_(0) {}
ThreadMarker(unsigned i)178   ThreadMarker(unsigned i)
179       : creating_thread_(ThreadState::Current()), num_(i) {}
ThreadMarker(WTF::HashTableDeletedValueType deleted)180   ThreadMarker(WTF::HashTableDeletedValueType deleted)
181       : creating_thread_(reinterpret_cast<ThreadState*>(-1)), num_(0) {}
~ThreadMarker()182   ~ThreadMarker() {
183     EXPECT_TRUE((creating_thread_ == ThreadState::Current()) ||
184                 (creating_thread_ == reinterpret_cast<ThreadState*>(0)) ||
185                 (creating_thread_ == reinterpret_cast<ThreadState*>(-1)));
186   }
IsHashTableDeletedValue() const187   bool IsHashTableDeletedValue() const {
188     return creating_thread_ == reinterpret_cast<ThreadState*>(-1);
189   }
operator ==(const ThreadMarker & other) const190   bool operator==(const ThreadMarker& other) const {
191     return other.creating_thread_ == creating_thread_ && other.num_ == num_;
192   }
193   ThreadState* creating_thread_;
194   unsigned num_;
195 };
196 
197 struct ThreadMarkerHash {
GetHashblink::__anon08a198100111::ThreadMarkerHash198   static unsigned GetHash(const ThreadMarker& key) {
199     return static_cast<unsigned>(
200         reinterpret_cast<uintptr_t>(key.creating_thread_) + key.num_);
201   }
202 
Equalblink::__anon08a198100111::ThreadMarkerHash203   static bool Equal(const ThreadMarker& a, const ThreadMarker& b) {
204     return a == b;
205   }
206 
207   static const bool safe_to_compare_to_empty_or_deleted = false;
208 };
209 
210 }  // namespace
211 
212 }  // namespace blink
213 
214 namespace WTF {
215 
216 template <typename T>
217 struct DefaultHash;
218 template <>
219 struct DefaultHash<blink::ThreadMarker> {
220   typedef blink::ThreadMarkerHash Hash;
221 };
222 
223 // ThreadMarkerHash is the default hash for ThreadMarker
224 template <>
225 struct HashTraits<blink::ThreadMarker>
226     : GenericHashTraits<blink::ThreadMarker> {
227   static const bool kEmptyValueIsZero = true;
ConstructDeletedValueWTF::HashTraits228   static void ConstructDeletedValue(blink::ThreadMarker& slot, bool) {
229     new (NotNull, &slot) blink::ThreadMarker(kHashTableDeletedValue);
230   }
IsDeletedValueWTF::HashTraits231   static bool IsDeletedValue(const blink::ThreadMarker& slot) {
232     return slot.IsHashTableDeletedValue();
233   }
234 };
235 
236 template <>
237 struct DefaultHash<blink::KeyWithCopyingMoveConstructor> {
238   using Hash = blink::KeyWithCopyingMoveConstructor::Hash;
239 };
240 
241 template <>
242 struct HashTraits<blink::KeyWithCopyingMoveConstructor>
243     : public SimpleClassHashTraits<blink::KeyWithCopyingMoveConstructor> {};
244 
245 }  // namespace WTF
246 
247 namespace blink {
248 
249 class TestGCCollectGarbageScope {
250   STACK_ALLOCATED();
251 
252  public:
TestGCCollectGarbageScope(BlinkGC::StackState state)253   explicit TestGCCollectGarbageScope(BlinkGC::StackState state) {
254     DCHECK(ThreadState::Current()->CheckThread());
255   }
256 
~TestGCCollectGarbageScope()257   ~TestGCCollectGarbageScope() { ThreadState::Current()->CompleteSweep(); }
258 };
259 
260 class TestGCScope : public TestGCCollectGarbageScope {
261  public:
TestGCScope(BlinkGC::StackState state)262   explicit TestGCScope(BlinkGC::StackState state)
263       : TestGCCollectGarbageScope(state) {
264     ThreadState::Current()->Heap().stats_collector()->NotifyMarkingStarted(
265         BlinkGC::CollectionType::kMajor,
266         BlinkGC::GCReason::kForcedGCForTesting);
267     ThreadState::Current()->AtomicPauseMarkPrologue(
268         BlinkGC::CollectionType::kMajor, state, BlinkGC::kAtomicMarking,
269         BlinkGC::GCReason::kPreciseGC);
270   }
~TestGCScope()271   ~TestGCScope() {
272     ThreadState::Current()->AtomicPauseMarkEpilogue(BlinkGC::kAtomicMarking);
273     ThreadState::Current()->AtomicPauseSweepAndCompact(
274         BlinkGC::CollectionType::kMajor, BlinkGC::kAtomicMarking,
275         BlinkGC::kEagerSweeping);
276     ThreadState::Current()->AtomicPauseEpilogue();
277   }
278 };
279 
280 class SimpleObject : public GarbageCollected<SimpleObject> {
281  public:
282   SimpleObject() = default;
Trace(Visitor * visitor)283   void Trace(Visitor* visitor) {}
GetPayload(int i)284   char GetPayload(int i) { return payload[i]; }
285   // This virtual method is unused but it is here to make sure
286   // that this object has a vtable. This object is used
287   // as the super class for objects that also have garbage
288   // collected mixins and having a virtual here makes sure
289   // that adjustment is needed both for marking and for isAlive
290   // checks.
VirtualMethod()291   virtual void VirtualMethod() {}
292 
293  protected:
294   char payload[64];
295 };
296 
297 class HeapTestSuperClass : public GarbageCollected<HeapTestSuperClass> {
298  public:
299   HeapTestSuperClass() = default;
~HeapTestSuperClass()300   virtual ~HeapTestSuperClass() { ++destructor_calls_; }
301 
302   static int destructor_calls_;
Trace(Visitor * visitor)303   void Trace(Visitor* visitor) {}
304 };
305 
306 int HeapTestSuperClass::destructor_calls_ = 0;
307 
308 class HeapTestOtherSuperClass {
309  public:
310   int payload;
311 };
312 
313 static const size_t kClassMagic = 0xABCDDBCA;
314 
315 class HeapTestSubClass : public HeapTestOtherSuperClass,
316                          public HeapTestSuperClass {
317  public:
HeapTestSubClass()318   HeapTestSubClass() : magic_(kClassMagic) {}
~HeapTestSubClass()319   ~HeapTestSubClass() override {
320     EXPECT_EQ(kClassMagic, magic_);
321     ++destructor_calls_;
322   }
323 
324   static int destructor_calls_;
325 
326  private:
327   const size_t magic_;
328 };
329 
330 int HeapTestSubClass::destructor_calls_ = 0;
331 
332 class HeapAllocatedArray : public GarbageCollected<HeapAllocatedArray> {
333  public:
HeapAllocatedArray()334   HeapAllocatedArray() {
335     for (int i = 0; i < kArraySize; ++i) {
336       array_[i] = i % 128;
337     }
338   }
339 
at(size_t i)340   int8_t at(size_t i) { return array_[i]; }
Trace(Visitor * visitor)341   void Trace(Visitor* visitor) {}
342 
343  private:
344   static const int kArraySize = 1000;
345   int8_t array_[kArraySize];
346 };
347 
348 class OffHeapInt : public RefCounted<OffHeapInt> {
349   USING_FAST_MALLOC(OffHeapInt);
350 
351  public:
Create(int x)352   static scoped_refptr<OffHeapInt> Create(int x) {
353     return base::AdoptRef(new OffHeapInt(x));
354   }
355 
~OffHeapInt()356   virtual ~OffHeapInt() { ++destructor_calls_; }
357 
358   static int destructor_calls_;
359 
Value() const360   int Value() const { return x_; }
361 
operator ==(const OffHeapInt & other) const362   bool operator==(const OffHeapInt& other) const {
363     return other.Value() == Value();
364   }
365 
GetHash()366   unsigned GetHash() { return IntHash<int>::GetHash(x_); }
VoidFunction()367   void VoidFunction() {}
368 
369  protected:
OffHeapInt(int x)370   OffHeapInt(int x) : x_(x) {}
371 
372  private:
373   OffHeapInt() = delete;
374   int x_;
375 };
376 
377 int OffHeapInt::destructor_calls_ = 0;
378 
379 class ThreadedTesterBase {
380  protected:
Test(ThreadedTesterBase * tester)381   static void Test(ThreadedTesterBase* tester) {
382     std::unique_ptr<Thread> threads[kNumberOfThreads];
383     for (auto& thread : threads) {
384       thread = Platform::Current()->CreateThread(
385           ThreadCreationParams(ThreadType::kTestThread)
386               .SetThreadNameForTest("blink gc testing thread"));
387       PostCrossThreadTask(
388           *thread->GetTaskRunner(), FROM_HERE,
389           CrossThreadBindOnce(ThreadFunc, CrossThreadUnretained(tester)));
390     }
391     tester->done_.Wait();
392     delete tester;
393   }
394 
395   virtual void RunThread() = 0;
396 
397  protected:
398   static const int kNumberOfThreads = 10;
399   static const int kGcPerThread = 5;
400   static const int kNumberOfAllocations = 50;
401 
402   virtual ~ThreadedTesterBase() = default;
403 
Done() const404   inline bool Done() const {
405     return gc_count_.load(std::memory_order_acquire) >=
406            kNumberOfThreads * kGcPerThread;
407   }
408 
409   std::atomic_int gc_count_{0};
410 
411  private:
ThreadFunc(ThreadedTesterBase * tester)412   static void ThreadFunc(ThreadedTesterBase* tester) {
413     ThreadState::AttachCurrentThread();
414     tester->RunThread();
415     ThreadState::DetachCurrentThread();
416     if (!tester->threads_to_finish_.Decrement())
417       tester->done_.Signal();
418   }
419 
420   base::AtomicRefCount threads_to_finish_{kNumberOfThreads};
421   base::WaitableEvent done_;
422 };
423 
424 // Needed to give this variable a definition (the initializer above is only a
425 // declaration), so that subclasses can use it.
426 const int ThreadedTesterBase::kNumberOfThreads;
427 
428 class ThreadedHeapTester : public ThreadedTesterBase {
429  public:
Test()430   static void Test() { ThreadedTesterBase::Test(new ThreadedHeapTester); }
431 
~ThreadedHeapTester()432   ~ThreadedHeapTester() override {
433     // Verify that the threads cleared their CTPs when
434     // terminating, preventing access to a finalized heap.
435     for (auto& global_int_wrapper : cross_persistents_) {
436       DCHECK(global_int_wrapper.get());
437       EXPECT_FALSE(global_int_wrapper.get()->Get());
438     }
439   }
440 
441  protected:
442   using GlobalIntWrapperPersistent = CrossThreadPersistent<IntWrapper>;
443 
444   Mutex mutex_;
445   Vector<std::unique_ptr<GlobalIntWrapperPersistent>> cross_persistents_;
446 
CreateGlobalPersistent(int value)447   std::unique_ptr<GlobalIntWrapperPersistent> CreateGlobalPersistent(
448       int value) {
449     return std::make_unique<GlobalIntWrapperPersistent>(
450         MakeGarbageCollected<IntWrapper>(value));
451   }
452 
AddGlobalPersistent()453   void AddGlobalPersistent() {
454     MutexLocker lock(mutex_);
455     cross_persistents_.push_back(CreateGlobalPersistent(0x2a2a2a2a));
456   }
457 
RunThread()458   void RunThread() override {
459     // Add a cross-thread persistent from this thread; the test object
460     // verifies that it will have been cleared out after the threads
461     // have all detached, running their termination GCs while doing so.
462     AddGlobalPersistent();
463 
464     int gc_count = 0;
465     while (!Done()) {
466       {
467         Persistent<IntWrapper> wrapper;
468 
469         std::unique_ptr<GlobalIntWrapperPersistent> global_persistent =
470             CreateGlobalPersistent(0x0ed0cabb);
471 
472         for (int i = 0; i < kNumberOfAllocations; i++) {
473           wrapper = MakeGarbageCollected<IntWrapper>(0x0bbac0de);
474           if (!(i % 10)) {
475             global_persistent = CreateGlobalPersistent(0x0ed0cabb);
476           }
477           test::YieldCurrentThread();
478         }
479 
480         if (gc_count < kGcPerThread) {
481           TestSupportingGC::PreciselyCollectGarbage();
482           gc_count++;
483           gc_count_.fetch_add(1, std::memory_order_release);
484         }
485 
486         TestSupportingGC::PreciselyCollectGarbage();
487         EXPECT_EQ(wrapper->Value(), 0x0bbac0de);
488         EXPECT_EQ((*global_persistent)->Value(), 0x0ed0cabb);
489       }
490       test::YieldCurrentThread();
491     }
492   }
493 };
494 
495 class ThreadedWeaknessTester : public ThreadedTesterBase {
496  public:
Test()497   static void Test() { ThreadedTesterBase::Test(new ThreadedWeaknessTester); }
498 
499  private:
RunThread()500   void RunThread() override {
501     int gc_count = 0;
502     while (!Done()) {
503       {
504         Persistent<HeapHashMap<ThreadMarker, WeakMember<IntWrapper>>> weak_map =
505             MakeGarbageCollected<
506                 HeapHashMap<ThreadMarker, WeakMember<IntWrapper>>>();
507 
508         for (int i = 0; i < kNumberOfAllocations; i++) {
509           weak_map->insert(static_cast<unsigned>(i),
510                            MakeGarbageCollected<IntWrapper>(0));
511           test::YieldCurrentThread();
512         }
513 
514         if (gc_count < kGcPerThread) {
515           TestSupportingGC::PreciselyCollectGarbage();
516           gc_count++;
517           gc_count_.fetch_add(1, std::memory_order_release);
518         }
519 
520         TestSupportingGC::PreciselyCollectGarbage();
521         EXPECT_TRUE(weak_map->IsEmpty());
522       }
523       test::YieldCurrentThread();
524     }
525   }
526 };
527 
528 class ThreadPersistentHeapTester : public ThreadedTesterBase {
529  public:
Test()530   static void Test() {
531     ThreadedTesterBase::Test(new ThreadPersistentHeapTester);
532   }
533 
534  protected:
535   class Local final : public GarbageCollected<Local> {
536    public:
537     Local() = default;
538 
Trace(Visitor * visitor)539     void Trace(Visitor* visitor) {}
540   };
541 
542   class PersistentChain;
543 
544   class RefCountedChain : public RefCounted<RefCountedChain> {
545    public:
Create(int count)546     static RefCountedChain* Create(int count) {
547       return new RefCountedChain(count);
548     }
549 
550    private:
RefCountedChain(int count)551     explicit RefCountedChain(int count) {
552       if (count > 0) {
553         --count;
554         persistent_chain_ = MakeGarbageCollected<PersistentChain>(count);
555       }
556     }
557 
558     Persistent<PersistentChain> persistent_chain_;
559   };
560 
561   class PersistentChain final : public GarbageCollected<PersistentChain> {
562    public:
PersistentChain(int count)563     explicit PersistentChain(int count) {
564       ref_counted_chain_ = base::AdoptRef(RefCountedChain::Create(count));
565     }
566 
Trace(Visitor * visitor)567     void Trace(Visitor* visitor) {}
568 
569    private:
570     scoped_refptr<RefCountedChain> ref_counted_chain_;
571   };
572 
RunThread()573   void RunThread() override {
574     MakeGarbageCollected<PersistentChain>(100);
575 
576     // Upon thread detach, GCs will run until all persistents have been
577     // released. We verify that the draining of persistents proceeds
578     // as expected by dropping one Persistent<> per GC until there
579     // are none left.
580   }
581 };
582 
583 // The accounting for memory includes the memory used by rounding up object
584 // sizes. This is done in a different way on 32 bit and 64 bit, so we have to
585 // have some slack in the tests.
586 template <typename T>
CheckWithSlack(T expected,T actual,int slack)587 void CheckWithSlack(T expected, T actual, int slack) {
588   EXPECT_LE(expected, actual);
589   EXPECT_GE((intptr_t)expected + slack, (intptr_t)actual);
590 }
591 
592 class TraceCounter final : public GarbageCollected<TraceCounter> {
593  public:
TraceCounter()594   TraceCounter() : trace_count_(0) {}
595 
Trace(Visitor * visitor)596   void Trace(Visitor* visitor) { trace_count_++; }
TraceCount() const597   int TraceCount() const { return trace_count_; }
598 
599  private:
600   int trace_count_;
601 };
602 
TEST_F(HeapTest,IsHeapObjectAliveForConstPointer)603 TEST_F(HeapTest, IsHeapObjectAliveForConstPointer) {
604   // See http://crbug.com/661363.
605   auto* object = MakeGarbageCollected<SimpleObject>();
606   HeapObjectHeader* header = HeapObjectHeader::FromPayload(object);
607   EXPECT_TRUE(header->TryMark());
608   EXPECT_TRUE(ThreadHeap::IsHeapObjectAlive(object));
609   const SimpleObject* const_object = const_cast<const SimpleObject*>(object);
610   EXPECT_TRUE(ThreadHeap::IsHeapObjectAlive(const_object));
611 }
612 
613 class ClassWithMember : public GarbageCollected<ClassWithMember> {
614  public:
ClassWithMember()615   ClassWithMember() : trace_counter_(MakeGarbageCollected<TraceCounter>()) {}
616 
Trace(Visitor * visitor)617   void Trace(Visitor* visitor) { visitor->Trace(trace_counter_); }
TraceCount() const618   int TraceCount() const { return trace_counter_->TraceCount(); }
619 
620  private:
621   Member<TraceCounter> trace_counter_;
622 };
623 
624 class SimpleFinalizedObject final
625     : public GarbageCollected<SimpleFinalizedObject> {
626  public:
627   SimpleFinalizedObject() = default;
~SimpleFinalizedObject()628   ~SimpleFinalizedObject() { ++destructor_calls_; }
629 
630   static int destructor_calls_;
631 
Trace(Visitor * visitor)632   void Trace(Visitor* visitor) {}
633 };
634 
635 int SimpleFinalizedObject::destructor_calls_ = 0;
636 
637 class IntNode : public GarbageCollected<IntNode> {
638  public:
639   // IntNode is used to test typed heap allocation. Instead of
640   // redefining blink::Node to our test version, we keep it separate
641   // so as to avoid possible warnings about linker duplicates.
642   // Override operator new to allocate IntNode subtype objects onto
643   // the dedicated heap for blink::Node.
644   //
645   // TODO(haraken): untangling the heap unit tests from Blink would
646   // simplify and avoid running into this problem - http://crbug.com/425381
647   GC_PLUGIN_IGNORE("crbug.com/443854")
operator new(size_t size)648   void* operator new(size_t size) {
649     ThreadState* state = ThreadState::Current();
650     const char* type_name = WTF_HEAP_PROFILER_TYPE_NAME(IntNode);
651     return state->Heap().AllocateOnArenaIndex(
652         state, size, BlinkGC::kNodeArenaIndex, GCInfoTrait<IntNode>::Index(),
653         type_name);
654   }
655 
Create(int i)656   static IntNode* Create(int i) { return new IntNode(i); }
657 
Trace(Visitor * visitor)658   void Trace(Visitor* visitor) {}
659 
Value()660   int Value() { return value_; }
661 
662  private:
IntNode(int i)663   IntNode(int i) : value_(i) {}
664   int value_;
665 };
666 
667 class Bar : public GarbageCollected<Bar> {
668  public:
Bar()669   Bar() : magic_(kMagic) { live_++; }
670 
FinalizeGarbageCollectedObject()671   void FinalizeGarbageCollectedObject() {
672     EXPECT_TRUE(magic_ == kMagic);
673     magic_ = 0;
674     live_--;
675   }
HasBeenFinalized() const676   bool HasBeenFinalized() const { return !magic_; }
677 
Trace(Visitor * visitor)678   virtual void Trace(Visitor* visitor) {}
679   static unsigned live_;
680 
681  protected:
682   static const int kMagic = 1337;
683   int magic_;
684 };
685 
686 unsigned Bar::live_ = 0;
687 
688 class Baz : public GarbageCollected<Baz> {
689  public:
Baz(Bar * bar)690   explicit Baz(Bar* bar) : bar_(bar) {}
691 
Trace(Visitor * visitor)692   void Trace(Visitor* visitor) { visitor->Trace(bar_); }
693 
Clear()694   void Clear() { bar_.Release(); }
695 
696   // willFinalize is called by FinalizationObserver.
WillFinalize()697   void WillFinalize() { EXPECT_TRUE(!bar_->HasBeenFinalized()); }
698 
699  private:
700   Member<Bar> bar_;
701 };
702 
703 class Foo : public Bar {
704  public:
Foo(Bar * bar)705   Foo(Bar* bar) : Bar(), bar_(bar), points_to_foo_(false) {}
706 
Foo(Foo * foo)707   Foo(Foo* foo) : Bar(), bar_(foo), points_to_foo_(true) {}
708 
Trace(Visitor * visitor)709   void Trace(Visitor* visitor) override {
710     if (points_to_foo_)
711       visitor->Trace(static_cast<const Foo*>(bar_));
712     else
713       visitor->Trace(bar_);
714   }
715 
716  private:
717   const Bar* bar_;
718   const bool points_to_foo_;
719 };
720 
721 class Bars : public Bar {
722  public:
Bars()723   Bars() : width_(0) {
724     for (unsigned i = 0; i < kWidth; i++) {
725       bars_[i] = MakeGarbageCollected<Bar>();
726       width_++;
727     }
728   }
729 
Trace(Visitor * visitor)730   void Trace(Visitor* visitor) override {
731     for (unsigned i = 0; i < width_; i++)
732       visitor->Trace(bars_[i]);
733   }
734 
GetWidth() const735   unsigned GetWidth() const { return width_; }
736 
737   static const unsigned kWidth = 7500;
738 
739  private:
740   unsigned width_;
741   Member<Bar> bars_[kWidth];
742 };
743 
744 class ConstructorAllocation : public GarbageCollected<ConstructorAllocation> {
745  public:
ConstructorAllocation()746   ConstructorAllocation() {
747     int_wrapper_ = MakeGarbageCollected<IntWrapper>(42);
748   }
749 
Trace(Visitor * visitor)750   void Trace(Visitor* visitor) { visitor->Trace(int_wrapper_); }
751 
752  private:
753   Member<IntWrapper> int_wrapper_;
754 };
755 
756 class LargeHeapObject final : public GarbageCollected<LargeHeapObject> {
757  public:
LargeHeapObject()758   LargeHeapObject() { int_wrapper_ = MakeGarbageCollected<IntWrapper>(23); }
~LargeHeapObject()759   ~LargeHeapObject() { destructor_calls_++; }
760 
Get(size_t i)761   char Get(size_t i) { return data_[i]; }
Set(size_t i,char c)762   void Set(size_t i, char c) { data_[i] = c; }
length()763   size_t length() { return kLength; }
Trace(Visitor * visitor)764   void Trace(Visitor* visitor) { visitor->Trace(int_wrapper_); }
765   static int destructor_calls_;
766 
767  private:
768   static const size_t kLength = 1024 * 1024;
769   Member<IntWrapper> int_wrapper_;
770   char data_[kLength];
771 };
772 
773 int LargeHeapObject::destructor_calls_ = 0;
774 
775 // This test class served a more important role while Blink
776 // was transitioned over to using Oilpan. That required classes
777 // that were hybrid, both ref-counted and on the Oilpan heap
778 // (the RefCountedGarbageCollected<> class providing just that.)
779 //
780 // There's no current need for having a ref-counted veneer on
781 // top of a GCed class, but we preserve it here to exercise the
782 // implementation technique that it used -- keeping an internal
783 // "keep alive" persistent reference that is set & cleared across
784 // ref-counting operations.
785 //
786 class RefCountedAndGarbageCollected final
787     : public GarbageCollected<RefCountedAndGarbageCollected> {
788  public:
RefCountedAndGarbageCollected()789   RefCountedAndGarbageCollected() : keep_alive_(PERSISTENT_FROM_HERE) {}
~RefCountedAndGarbageCollected()790   ~RefCountedAndGarbageCollected() { ++destructor_calls_; }
791 
AddRef()792   void AddRef() {
793     if (UNLIKELY(!ref_count_)) {
794 #if DCHECK_IS_ON()
795       DCHECK(ThreadState::Current()->Heap().FindPageFromAddress(
796           reinterpret_cast<Address>(this)));
797 #endif
798       keep_alive_ = this;
799     }
800     ++ref_count_;
801   }
802 
Release()803   void Release() {
804     DCHECK_GT(ref_count_, 0);
805     if (!--ref_count_)
806       keep_alive_.Clear();
807   }
808 
Trace(Visitor * visitor)809   void Trace(Visitor* visitor) {}
810 
811   static int destructor_calls_;
812 
813  private:
814   int ref_count_ = 0;
815   SelfKeepAlive<RefCountedAndGarbageCollected> keep_alive_;
816 };
817 
818 int RefCountedAndGarbageCollected::destructor_calls_ = 0;
819 
820 class RefCountedAndGarbageCollected2 final
821     : public HeapTestOtherSuperClass,
822       public GarbageCollected<RefCountedAndGarbageCollected2> {
823  public:
RefCountedAndGarbageCollected2()824   RefCountedAndGarbageCollected2() : keep_alive_(PERSISTENT_FROM_HERE) {}
~RefCountedAndGarbageCollected2()825   ~RefCountedAndGarbageCollected2() { ++destructor_calls_; }
826 
Ref()827   void Ref() {
828     if (UNLIKELY(!ref_count_)) {
829 #if DCHECK_IS_ON()
830       DCHECK(ThreadState::Current()->Heap().FindPageFromAddress(
831           reinterpret_cast<Address>(this)));
832 #endif
833       keep_alive_ = this;
834     }
835     ++ref_count_;
836   }
837 
Deref()838   void Deref() {
839     DCHECK_GT(ref_count_, 0);
840     if (!--ref_count_)
841       keep_alive_.Clear();
842   }
843 
Trace(Visitor * visitor)844   void Trace(Visitor* visitor) {}
845 
846   static int destructor_calls_;
847 
848  private:
849   int ref_count_ = 0;
850   SelfKeepAlive<RefCountedAndGarbageCollected2> keep_alive_;
851 };
852 
853 int RefCountedAndGarbageCollected2::destructor_calls_ = 0;
854 
855 class Weak : public Bar {
856  public:
Weak(Bar * strong_bar,Bar * weak_bar)857   Weak(Bar* strong_bar, Bar* weak_bar)
858       : Bar(), strong_bar_(strong_bar), weak_bar_(weak_bar) {}
859 
Trace(Visitor * visitor)860   void Trace(Visitor* visitor) override {
861     visitor->Trace(strong_bar_);
862     visitor->template RegisterWeakCallbackMethod<Weak, &Weak::ZapWeakMembers>(
863         this);
864   }
865 
ZapWeakMembers(const WeakCallbackInfo & info)866   void ZapWeakMembers(const WeakCallbackInfo& info) {
867     if (!info.IsHeapObjectAlive(weak_bar_))
868       weak_bar_ = nullptr;
869   }
870 
StrongIsThere()871   bool StrongIsThere() { return !!strong_bar_; }
WeakIsThere()872   bool WeakIsThere() { return !!weak_bar_; }
873 
874  private:
875   Member<Bar> strong_bar_;
876   Bar* weak_bar_;
877 };
878 
879 class WithWeakMember : public Bar {
880  public:
WithWeakMember(Bar * strong_bar,Bar * weak_bar)881   WithWeakMember(Bar* strong_bar, Bar* weak_bar)
882       : Bar(), strong_bar_(strong_bar), weak_bar_(weak_bar) {}
883 
Trace(Visitor * visitor)884   void Trace(Visitor* visitor) override {
885     visitor->Trace(strong_bar_);
886     visitor->Trace(weak_bar_);
887   }
888 
StrongIsThere()889   bool StrongIsThere() { return !!strong_bar_; }
WeakIsThere()890   bool WeakIsThere() { return !!weak_bar_; }
891 
892  private:
893   Member<Bar> strong_bar_;
894   WeakMember<Bar> weak_bar_;
895 };
896 
897 class Observable final : public GarbageCollected<Observable> {
898   USING_PRE_FINALIZER(Observable, WillFinalize);
899 
900  public:
Observable(Bar * bar)901   explicit Observable(Bar* bar) : bar_(bar), was_destructed_(false) {}
~Observable()902   ~Observable() { was_destructed_ = true; }
Trace(Visitor * visitor)903   void Trace(Visitor* visitor) { visitor->Trace(bar_); }
904 
905   // willFinalize is called by FinalizationObserver. willFinalize can touch
906   // other on-heap objects.
WillFinalize()907   void WillFinalize() {
908     EXPECT_FALSE(was_destructed_);
909     EXPECT_FALSE(bar_->HasBeenFinalized());
910     will_finalize_was_called_ = true;
911   }
912   static bool will_finalize_was_called_;
913 
914  private:
915   Member<Bar> bar_;
916   bool was_destructed_;
917 };
918 
919 bool Observable::will_finalize_was_called_ = false;
920 
921 class ObservableWithPreFinalizer final
922     : public GarbageCollected<ObservableWithPreFinalizer> {
923   USING_PRE_FINALIZER(ObservableWithPreFinalizer, Dispose);
924 
925  public:
ObservableWithPreFinalizer()926   ObservableWithPreFinalizer() : was_destructed_(false) {}
~ObservableWithPreFinalizer()927   ~ObservableWithPreFinalizer() { was_destructed_ = true; }
Trace(Visitor * visitor)928   void Trace(Visitor* visitor) {}
Dispose()929   void Dispose() {
930     EXPECT_FALSE(was_destructed_);
931     dispose_was_called_ = true;
932   }
933   static bool dispose_was_called_;
934 
935  protected:
936   bool was_destructed_;
937 };
938 
939 bool ObservableWithPreFinalizer::dispose_was_called_ = false;
940 
941 bool g_dispose_was_called_for_pre_finalizer_base = false;
942 bool g_dispose_was_called_for_pre_finalizer_mixin = false;
943 bool g_dispose_was_called_for_pre_finalizer_sub_class = false;
944 
945 class PreFinalizerBase : public GarbageCollected<PreFinalizerBase> {
946   USING_PRE_FINALIZER(PreFinalizerBase, Dispose);
947 
948  public:
PreFinalizerBase()949   PreFinalizerBase() : was_destructed_(false) {}
~PreFinalizerBase()950   virtual ~PreFinalizerBase() { was_destructed_ = true; }
Trace(Visitor * visitor)951   virtual void Trace(Visitor* visitor) {}
Dispose()952   void Dispose() {
953     EXPECT_FALSE(g_dispose_was_called_for_pre_finalizer_base);
954     EXPECT_TRUE(g_dispose_was_called_for_pre_finalizer_sub_class);
955     EXPECT_TRUE(g_dispose_was_called_for_pre_finalizer_mixin);
956     EXPECT_FALSE(was_destructed_);
957     g_dispose_was_called_for_pre_finalizer_base = true;
958   }
959 
960  protected:
961   bool was_destructed_;
962 };
963 
964 class PreFinalizerMixin : public GarbageCollectedMixin {
965   USING_PRE_FINALIZER(PreFinalizerMixin, Dispose);
966 
967  public:
~PreFinalizerMixin()968   ~PreFinalizerMixin() { was_destructed_ = true; }
Trace(Visitor * visitor)969   void Trace(Visitor* visitor) override {}
Dispose()970   void Dispose() {
971     EXPECT_FALSE(g_dispose_was_called_for_pre_finalizer_base);
972     EXPECT_TRUE(g_dispose_was_called_for_pre_finalizer_sub_class);
973     EXPECT_FALSE(g_dispose_was_called_for_pre_finalizer_mixin);
974     EXPECT_FALSE(was_destructed_);
975     g_dispose_was_called_for_pre_finalizer_mixin = true;
976   }
977 
978  protected:
PreFinalizerMixin()979   PreFinalizerMixin() : was_destructed_(false) {}
980   bool was_destructed_;
981 };
982 
983 class PreFinalizerSubClass : public PreFinalizerBase, public PreFinalizerMixin {
984   USING_GARBAGE_COLLECTED_MIXIN(PreFinalizerSubClass);
985   USING_PRE_FINALIZER(PreFinalizerSubClass, Dispose);
986 
987  public:
PreFinalizerSubClass()988   PreFinalizerSubClass() : was_destructed_(false) {}
~PreFinalizerSubClass()989   ~PreFinalizerSubClass() override { was_destructed_ = true; }
Trace(Visitor * visitor)990   void Trace(Visitor* visitor) override {}
Dispose()991   void Dispose() {
992     EXPECT_FALSE(g_dispose_was_called_for_pre_finalizer_base);
993     EXPECT_FALSE(g_dispose_was_called_for_pre_finalizer_sub_class);
994     EXPECT_FALSE(g_dispose_was_called_for_pre_finalizer_mixin);
995     EXPECT_FALSE(was_destructed_);
996     g_dispose_was_called_for_pre_finalizer_sub_class = true;
997   }
998 
999  protected:
1000   bool was_destructed_;
1001 };
1002 
1003 template <typename T>
1004 class FinalizationObserver : public GarbageCollected<FinalizationObserver<T>> {
1005  public:
FinalizationObserver(T * data)1006   FinalizationObserver(T* data) : data_(data), did_call_will_finalize_(false) {}
1007 
DidCallWillFinalize() const1008   bool DidCallWillFinalize() const { return did_call_will_finalize_; }
1009 
Trace(Visitor * visitor)1010   void Trace(Visitor* visitor) {
1011     visitor->template RegisterWeakCallbackMethod<
1012         FinalizationObserver<T>, &FinalizationObserver<T>::ZapWeakMembers>(
1013         this);
1014   }
1015 
ZapWeakMembers(const WeakCallbackInfo & info)1016   void ZapWeakMembers(const WeakCallbackInfo& info) {
1017     if (data_ && !info.IsHeapObjectAlive(data_)) {
1018       data_->WillFinalize();
1019       data_ = nullptr;
1020       did_call_will_finalize_ = true;
1021     }
1022   }
1023 
1024  private:
1025   WeakMember<T> data_;
1026   bool did_call_will_finalize_;
1027 };
1028 
1029 class FinalizationObserverWithHashMap {
1030  public:
1031   typedef HeapHashMap<WeakMember<Observable>,
1032                       std::unique_ptr<FinalizationObserverWithHashMap>>
1033       ObserverMap;
1034 
FinalizationObserverWithHashMap(Observable & target)1035   explicit FinalizationObserverWithHashMap(Observable& target)
1036       : target_(target) {}
~FinalizationObserverWithHashMap()1037   ~FinalizationObserverWithHashMap() {
1038     target_.WillFinalize();
1039     did_call_will_finalize_ = true;
1040   }
1041 
Observe(Observable & target)1042   static ObserverMap& Observe(Observable& target) {
1043     ObserverMap& map = Observers();
1044     ObserverMap::AddResult result = map.insert(&target, nullptr);
1045     if (result.is_new_entry) {
1046       result.stored_value->value =
1047           std::make_unique<FinalizationObserverWithHashMap>(target);
1048     } else {
1049       DCHECK(result.stored_value->value);
1050     }
1051     return map;
1052   }
1053 
ClearObservers()1054   static void ClearObservers() {
1055     delete observer_map_;
1056     observer_map_ = nullptr;
1057   }
1058 
1059   static bool did_call_will_finalize_;
1060 
1061  private:
Observers()1062   static ObserverMap& Observers() {
1063     if (!observer_map_) {
1064       observer_map_ =
1065           new Persistent<ObserverMap>(MakeGarbageCollected<ObserverMap>());
1066     }
1067     return **observer_map_;
1068   }
1069 
1070   Observable& target_;
1071   static Persistent<ObserverMap>* observer_map_;
1072 };
1073 
1074 bool FinalizationObserverWithHashMap::did_call_will_finalize_ = false;
1075 Persistent<FinalizationObserverWithHashMap::ObserverMap>*
1076     FinalizationObserverWithHashMap::observer_map_;
1077 
1078 class SuperClass;
1079 
1080 class PointsBack final : public GarbageCollected<PointsBack> {
1081  public:
PointsBack()1082   PointsBack() : back_pointer_(nullptr) { ++alive_count_; }
~PointsBack()1083   ~PointsBack() { --alive_count_; }
1084 
SetBackPointer(SuperClass * back_pointer)1085   void SetBackPointer(SuperClass* back_pointer) {
1086     back_pointer_ = back_pointer;
1087   }
1088 
BackPointer() const1089   SuperClass* BackPointer() const { return back_pointer_; }
1090 
Trace(Visitor * visitor)1091   void Trace(Visitor* visitor) { visitor->Trace(back_pointer_); }
1092 
1093   static int alive_count_;
1094 
1095  private:
1096   WeakMember<SuperClass> back_pointer_;
1097 };
1098 
1099 int PointsBack::alive_count_ = 0;
1100 
1101 class SuperClass : public GarbageCollected<SuperClass> {
1102  public:
SuperClass(PointsBack * points_back)1103   explicit SuperClass(PointsBack* points_back) : points_back_(points_back) {
1104     points_back_->SetBackPointer(this);
1105     ++alive_count_;
1106   }
~SuperClass()1107   virtual ~SuperClass() { --alive_count_; }
1108 
DoStuff(SuperClass * target,PointsBack * points_back,int super_class_count)1109   void DoStuff(SuperClass* target,
1110                PointsBack* points_back,
1111                int super_class_count) {
1112     TestSupportingGC::ConservativelyCollectGarbage();
1113     EXPECT_EQ(points_back, target->GetPointsBack());
1114     EXPECT_EQ(super_class_count, SuperClass::alive_count_);
1115   }
1116 
Trace(Visitor * visitor)1117   virtual void Trace(Visitor* visitor) { visitor->Trace(points_back_); }
1118 
GetPointsBack() const1119   PointsBack* GetPointsBack() const { return points_back_.Get(); }
1120 
1121   static int alive_count_;
1122 
1123  private:
1124   Member<PointsBack> points_back_;
1125 };
1126 
1127 int SuperClass::alive_count_ = 0;
1128 class SubData final : public GarbageCollected<SubData> {
1129  public:
SubData()1130   SubData() { ++alive_count_; }
~SubData()1131   ~SubData() { --alive_count_; }
1132 
Trace(Visitor * visitor)1133   void Trace(Visitor* visitor) {}
1134 
1135   static int alive_count_;
1136 };
1137 
1138 int SubData::alive_count_ = 0;
1139 
1140 class SubClass : public SuperClass {
1141  public:
SubClass(PointsBack * points_back)1142   explicit SubClass(PointsBack* points_back)
1143       : SuperClass(points_back), data_(MakeGarbageCollected<SubData>()) {
1144     ++alive_count_;
1145   }
~SubClass()1146   ~SubClass() override { --alive_count_; }
1147 
Trace(Visitor * visitor)1148   void Trace(Visitor* visitor) override {
1149     visitor->Trace(data_);
1150     SuperClass::Trace(visitor);
1151   }
1152 
1153   static int alive_count_;
1154 
1155  private:
1156   Member<SubData> data_;
1157 };
1158 
1159 int SubClass::alive_count_ = 0;
1160 
1161 class Mixin : public GarbageCollectedMixin {
1162  public:
Trace(Visitor * visitor)1163   void Trace(Visitor* visitor) override {}
1164 
GetPayload(int i)1165   virtual char GetPayload(int i) { return padding_[i]; }
1166 
1167  protected:
1168   int padding_[8];
1169 };
1170 
1171 class UseMixin : public SimpleObject, public Mixin {
1172   USING_GARBAGE_COLLECTED_MIXIN(UseMixin);
1173 
1174  public:
UseMixin()1175   UseMixin() {
1176     // Verify that WTF::IsGarbageCollectedType<> works as expected for mixins.
1177     static_assert(WTF::IsGarbageCollectedType<UseMixin>::value,
1178                   "IsGarbageCollectedType<> sanity check failed for GC mixin.");
1179     trace_count_ = 0;
1180   }
1181 
1182   static int trace_count_;
Trace(Visitor * visitor)1183   void Trace(Visitor* visitor) override {
1184     SimpleObject::Trace(visitor);
1185     Mixin::Trace(visitor);
1186     ++trace_count_;
1187   }
1188 };
1189 
1190 int UseMixin::trace_count_ = 0;
1191 
1192 class VectorObject {
1193   DISALLOW_NEW();
1194 
1195  public:
VectorObject()1196   VectorObject() { value_ = MakeGarbageCollected<SimpleFinalizedObject>(); }
1197 
Trace(Visitor * visitor)1198   void Trace(Visitor* visitor) { visitor->Trace(value_); }
1199 
1200  private:
1201   Member<SimpleFinalizedObject> value_;
1202 };
1203 
1204 class VectorObjectInheritedTrace : public VectorObject {};
1205 
1206 class VectorObjectNoTrace {
1207   DISALLOW_NEW();
1208 
1209  public:
VectorObjectNoTrace()1210   VectorObjectNoTrace() {
1211     value_ = MakeGarbageCollected<SimpleFinalizedObject>();
1212   }
1213 
1214  private:
1215   Member<SimpleFinalizedObject> value_;
1216 };
1217 
1218 class TerminatedArrayItem {
1219   DISALLOW_NEW();
1220 
1221  public:
TerminatedArrayItem(IntWrapper * payload)1222   TerminatedArrayItem(IntWrapper* payload)
1223       : payload_(payload), is_last_(false) {}
1224 
Trace(Visitor * visitor)1225   void Trace(Visitor* visitor) { visitor->Trace(payload_); }
1226 
IsLastInArray() const1227   bool IsLastInArray() const { return is_last_; }
SetLastInArray(bool value)1228   void SetLastInArray(bool value) { is_last_ = value; }
1229 
Payload() const1230   IntWrapper* Payload() const { return payload_; }
1231 
1232  private:
1233   Member<IntWrapper> payload_;
1234   bool is_last_;
1235 };
1236 
1237 }  // namespace blink
1238 
1239 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::TerminatedArrayItem)
1240 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::VectorObject)
1241 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(
1242     blink::VectorObjectInheritedTrace)
1243 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::VectorObjectNoTrace)
1244 
1245 namespace blink {
1246 
1247 class OneKiloByteObject final : public GarbageCollected<OneKiloByteObject> {
1248  public:
~OneKiloByteObject()1249   ~OneKiloByteObject() { destructor_calls_++; }
Data()1250   char* Data() { return data_; }
Trace(Visitor * visitor)1251   void Trace(Visitor* visitor) {}
1252   static int destructor_calls_;
1253 
1254  private:
1255   static const size_t kLength = 1024;
1256   char data_[kLength];
1257 };
1258 
1259 int OneKiloByteObject::destructor_calls_ = 0;
1260 
1261 class DynamicallySizedObject : public GarbageCollected<DynamicallySizedObject> {
1262  public:
Create(size_t size)1263   static DynamicallySizedObject* Create(size_t size) {
1264     void* slot = ThreadHeap::Allocate<DynamicallySizedObject>(size);
1265     return new (slot) DynamicallySizedObject();
1266   }
1267 
operator new(std::size_t,void * location)1268   void* operator new(std::size_t, void* location) { return location; }
1269 
Get(int i)1270   uint8_t Get(int i) { return *(reinterpret_cast<uint8_t*>(this) + i); }
1271 
Trace(Visitor * visitor)1272   void Trace(Visitor* visitor) {}
1273 
1274  private:
1275   DynamicallySizedObject() = default;
1276 };
1277 
1278 class FinalizationAllocator final
1279     : public GarbageCollected<FinalizationAllocator> {
1280  public:
FinalizationAllocator(Persistent<IntWrapper> * wrapper)1281   FinalizationAllocator(Persistent<IntWrapper>* wrapper) : wrapper_(wrapper) {}
1282 
~FinalizationAllocator()1283   ~FinalizationAllocator() {
1284     for (int i = 0; i < 10; ++i)
1285       *wrapper_ = MakeGarbageCollected<IntWrapper>(42);
1286     for (int i = 0; i < 512; ++i)
1287       MakeGarbageCollected<OneKiloByteObject>();
1288     for (int i = 0; i < 32; ++i)
1289       MakeGarbageCollected<LargeHeapObject>();
1290   }
1291 
Trace(Visitor * visitor)1292   void Trace(Visitor* visitor) {}
1293 
1294  private:
1295   Persistent<IntWrapper>* wrapper_;
1296 };
1297 
1298 class PreFinalizerBackingShrinkForbidden final
1299     : public GarbageCollected<PreFinalizerBackingShrinkForbidden> {
1300   USING_PRE_FINALIZER(PreFinalizerBackingShrinkForbidden, Dispose);
1301 
1302  public:
PreFinalizerBackingShrinkForbidden()1303   PreFinalizerBackingShrinkForbidden() {
1304     for (int i = 0; i < 32; ++i) {
1305       vector_.push_back(MakeGarbageCollected<IntWrapper>(i));
1306     }
1307     EXPECT_LT(31ul, vector_.capacity());
1308 
1309     for (int i = 0; i < 32; ++i) {
1310       map_.insert(i + 1, MakeGarbageCollected<IntWrapper>(i + 1));
1311     }
1312     EXPECT_LT(31ul, map_.Capacity());
1313   }
1314 
Dispose()1315   void Dispose() {
1316     // Remove all elemets except one so that vector_ will try to shrink.
1317     for (int i = 1; i < 32; ++i) {
1318       vector_.pop_back();
1319     }
1320     // Check that vector_ hasn't shrunk.
1321     EXPECT_LT(31ul, vector_.capacity());
1322     // Just releasing the backing is allowed.
1323     vector_.clear();
1324     EXPECT_EQ(0ul, vector_.capacity());
1325 
1326     // Remove elemets so that map_ will try to shrink.
1327     for (int i = 0; i < 32; ++i) {
1328       map_.erase(i + 1);
1329     }
1330     // Check that map_ hasn't shrunk.
1331     EXPECT_LT(31ul, map_.Capacity());
1332     // Just releasing the backing is allowed.
1333     map_.clear();
1334     EXPECT_EQ(0ul, map_.Capacity());
1335   }
1336 
Trace(Visitor * visitor)1337   void Trace(Visitor* visitor) {
1338     visitor->Trace(vector_);
1339     visitor->Trace(map_);
1340   }
1341 
1342  private:
1343   HeapVector<Member<IntWrapper>> vector_;
1344   HeapHashMap<int, Member<IntWrapper>> map_;
1345 };
1346 
1347 // Following 2 tests check for allocation failures. These failures happen
1348 // only when DCHECK is on.
1349 #if DCHECK_IS_ON()
TEST_F(HeapTest,PreFinalizerBackingShrinkForbidden)1350 TEST_F(HeapTest, PreFinalizerBackingShrinkForbidden) {
1351   MakeGarbageCollected<PreFinalizerBackingShrinkForbidden>();
1352   PreciselyCollectGarbage();
1353 }
1354 
1355 class PreFinalizerVectorBackingExpandForbidden final
1356     : public GarbageCollected<PreFinalizerVectorBackingExpandForbidden> {
1357   USING_PRE_FINALIZER(PreFinalizerVectorBackingExpandForbidden, Dispose);
1358 
1359  public:
PreFinalizerVectorBackingExpandForbidden()1360   PreFinalizerVectorBackingExpandForbidden() {
1361     vector_.push_back(MakeGarbageCollected<IntWrapper>(1));
1362   }
1363 
Dispose()1364   void Dispose() { EXPECT_DEATH(Test(), ""); }
1365 
Test()1366   void Test() {
1367     // vector_'s backing will need to expand.
1368     for (int i = 0; i < 32; ++i) {
1369       vector_.push_back(nullptr);
1370     }
1371   }
1372 
Trace(Visitor * visitor)1373   void Trace(Visitor* visitor) { visitor->Trace(vector_); }
1374 
1375  private:
1376   HeapVector<Member<IntWrapper>> vector_;
1377 };
1378 
TEST(HeapDeathTest,PreFinalizerVectorBackingExpandForbidden)1379 TEST(HeapDeathTest, PreFinalizerVectorBackingExpandForbidden) {
1380   MakeGarbageCollected<PreFinalizerVectorBackingExpandForbidden>();
1381   TestSupportingGC::PreciselyCollectGarbage();
1382 }
1383 
1384 class PreFinalizerHashTableBackingExpandForbidden final
1385     : public GarbageCollected<PreFinalizerHashTableBackingExpandForbidden> {
1386   USING_PRE_FINALIZER(PreFinalizerHashTableBackingExpandForbidden, Dispose);
1387 
1388  public:
PreFinalizerHashTableBackingExpandForbidden()1389   PreFinalizerHashTableBackingExpandForbidden() {
1390     map_.insert(123, MakeGarbageCollected<IntWrapper>(123));
1391   }
1392 
Dispose()1393   void Dispose() { EXPECT_DEATH(Test(), ""); }
1394 
Test()1395   void Test() {
1396     // map_'s backing will need to expand.
1397     for (int i = 1; i < 32; ++i) {
1398       map_.insert(i, nullptr);
1399     }
1400   }
1401 
Trace(Visitor * visitor)1402   void Trace(Visitor* visitor) { visitor->Trace(map_); }
1403 
1404  private:
1405   HeapHashMap<int, Member<IntWrapper>> map_;
1406 };
1407 
TEST(HeapDeathTest,PreFinalizerHashTableBackingExpandForbidden)1408 TEST(HeapDeathTest, PreFinalizerHashTableBackingExpandForbidden) {
1409   MakeGarbageCollected<PreFinalizerHashTableBackingExpandForbidden>();
1410   TestSupportingGC::PreciselyCollectGarbage();
1411 }
1412 #endif  // DCHECK_IS_ON()
1413 
1414 class PreFinalizerAllocationForbidden
1415     : public GarbageCollected<PreFinalizerAllocationForbidden> {
1416   USING_PRE_FINALIZER(PreFinalizerAllocationForbidden, Dispose);
1417 
1418  public:
Dispose()1419   void Dispose() {
1420     EXPECT_FALSE(ThreadState::Current()->IsAllocationAllowed());
1421 #if DCHECK_IS_ON()
1422     EXPECT_DEATH(MakeGarbageCollected<IntWrapper>(1), "");
1423 #endif  // DCHECK_IS_ON()
1424   }
1425 
Trace(Visitor * visitor)1426   void Trace(Visitor* visitor) {}
1427 };
1428 
TEST(HeapDeathTest,PreFinalizerAllocationForbidden)1429 TEST(HeapDeathTest, PreFinalizerAllocationForbidden) {
1430   MakeGarbageCollected<PreFinalizerAllocationForbidden>();
1431   TestSupportingGC::PreciselyCollectGarbage();
1432 }
1433 
1434 #if DCHECK_IS_ON()
1435 namespace {
1436 
1437 class HeapTestResurrectingPreFinalizer
1438     : public GarbageCollected<HeapTestResurrectingPreFinalizer> {
1439   USING_PRE_FINALIZER(HeapTestResurrectingPreFinalizer, Dispose);
1440 
1441  public:
1442   enum TestType {
1443     kHeapVectorMember,
1444     kHeapHashSetMember,
1445     kHeapHashSetWeakMember
1446   };
1447 
1448   class GlobalStorage : public GarbageCollected<GlobalStorage> {
1449    public:
GlobalStorage()1450     GlobalStorage() {
1451       // Reserve storage upfront to avoid allocations during pre-finalizer
1452       // insertion.
1453       vector_member.ReserveCapacity(32);
1454       hash_set_member.ReserveCapacityForSize(32);
1455       hash_set_weak_member.ReserveCapacityForSize(32);
1456     }
1457 
Trace(Visitor * visitor)1458     void Trace(Visitor* visitor) {
1459       visitor->Trace(vector_member);
1460       visitor->Trace(hash_set_member);
1461       visitor->Trace(hash_set_weak_member);
1462     }
1463 
1464     HeapVector<Member<LinkedObject>> vector_member;
1465     HeapHashSet<Member<LinkedObject>> hash_set_member;
1466     HeapHashSet<WeakMember<LinkedObject>> hash_set_weak_member;
1467   };
1468 
HeapTestResurrectingPreFinalizer(TestType test_type,GlobalStorage * storage,LinkedObject * object_that_dies)1469   HeapTestResurrectingPreFinalizer(TestType test_type,
1470                                    GlobalStorage* storage,
1471                                    LinkedObject* object_that_dies)
1472       : test_type_(test_type),
1473         storage_(storage),
1474         object_that_dies_(object_that_dies) {}
1475 
Trace(Visitor * visitor)1476   void Trace(Visitor* visitor) {
1477     visitor->Trace(storage_);
1478     visitor->Trace(object_that_dies_);
1479   }
1480 
1481  private:
Dispose()1482   void Dispose() { EXPECT_DEATH(Test(), ""); }
1483 
Test()1484   void Test() {
1485     switch (test_type_) {
1486       case TestType::kHeapVectorMember:
1487         storage_->vector_member.push_back(object_that_dies_);
1488         break;
1489       case TestType::kHeapHashSetMember:
1490         storage_->hash_set_member.insert(object_that_dies_);
1491         break;
1492       case TestType::kHeapHashSetWeakMember:
1493         storage_->hash_set_weak_member.insert(object_that_dies_);
1494         break;
1495     }
1496   }
1497 
1498   TestType test_type_;
1499   Member<GlobalStorage> storage_;
1500   Member<LinkedObject> object_that_dies_;
1501 };
1502 
1503 }  // namespace
1504 
TEST(HeapDeathTest,DiesOnResurrectedHeapVectorMember)1505 TEST(HeapDeathTest, DiesOnResurrectedHeapVectorMember) {
1506   Persistent<HeapTestResurrectingPreFinalizer::GlobalStorage> storage(
1507       MakeGarbageCollected<HeapTestResurrectingPreFinalizer::GlobalStorage>());
1508   MakeGarbageCollected<HeapTestResurrectingPreFinalizer>(
1509       HeapTestResurrectingPreFinalizer::kHeapVectorMember, storage.Get(),
1510       MakeGarbageCollected<LinkedObject>());
1511   TestSupportingGC::PreciselyCollectGarbage();
1512 }
1513 
TEST(HeapDeathTest,DiesOnResurrectedHeapHashSetMember)1514 TEST(HeapDeathTest, DiesOnResurrectedHeapHashSetMember) {
1515   Persistent<HeapTestResurrectingPreFinalizer::GlobalStorage> storage(
1516       MakeGarbageCollected<HeapTestResurrectingPreFinalizer::GlobalStorage>());
1517   MakeGarbageCollected<HeapTestResurrectingPreFinalizer>(
1518       HeapTestResurrectingPreFinalizer::kHeapHashSetMember, storage.Get(),
1519       MakeGarbageCollected<LinkedObject>());
1520   TestSupportingGC::PreciselyCollectGarbage();
1521 }
1522 
TEST(HeapDeathTest,DiesOnResurrectedHeapHashSetWeakMember)1523 TEST(HeapDeathTest, DiesOnResurrectedHeapHashSetWeakMember) {
1524   Persistent<HeapTestResurrectingPreFinalizer::GlobalStorage> storage(
1525       MakeGarbageCollected<HeapTestResurrectingPreFinalizer::GlobalStorage>());
1526   MakeGarbageCollected<HeapTestResurrectingPreFinalizer>(
1527       HeapTestResurrectingPreFinalizer::kHeapHashSetWeakMember, storage.Get(),
1528       MakeGarbageCollected<LinkedObject>());
1529   TestSupportingGC::PreciselyCollectGarbage();
1530 }
1531 #endif  // DCHECK_IS_ON()
1532 
1533 class LargeMixin : public GarbageCollected<LargeMixin>, public Mixin {
1534   USING_GARBAGE_COLLECTED_MIXIN(LargeMixin);
1535 
1536  private:
1537   char data[65536];
1538 };
1539 
TEST(HeapDeathTest,LargeGarbageCollectedMixin)1540 TEST(HeapDeathTest, LargeGarbageCollectedMixin) {
1541   EXPECT_DEATH(MakeGarbageCollected<LargeMixin>(AdditionalBytes(1)), "");
1542 }
1543 
TEST_F(HeapTest,Transition)1544 TEST_F(HeapTest, Transition) {
1545   {
1546     RefCountedAndGarbageCollected::destructor_calls_ = 0;
1547     Persistent<RefCountedAndGarbageCollected> ref_counted =
1548         MakeGarbageCollected<RefCountedAndGarbageCollected>();
1549     PreciselyCollectGarbage();
1550     EXPECT_EQ(0, RefCountedAndGarbageCollected::destructor_calls_);
1551   }
1552   PreciselyCollectGarbage();
1553   EXPECT_EQ(1, RefCountedAndGarbageCollected::destructor_calls_);
1554   RefCountedAndGarbageCollected::destructor_calls_ = 0;
1555 
1556   Persistent<PointsBack> points_back1 = MakeGarbageCollected<PointsBack>();
1557   Persistent<PointsBack> points_back2 = MakeGarbageCollected<PointsBack>();
1558   Persistent<SuperClass> super_class =
1559       MakeGarbageCollected<SuperClass>(points_back1);
1560   Persistent<SubClass> sub_class = MakeGarbageCollected<SubClass>(points_back2);
1561   EXPECT_EQ(2, PointsBack::alive_count_);
1562   EXPECT_EQ(2, SuperClass::alive_count_);
1563   EXPECT_EQ(1, SubClass::alive_count_);
1564   EXPECT_EQ(1, SubData::alive_count_);
1565 
1566   PreciselyCollectGarbage();
1567   EXPECT_EQ(0, RefCountedAndGarbageCollected::destructor_calls_);
1568   EXPECT_EQ(2, PointsBack::alive_count_);
1569   EXPECT_EQ(2, SuperClass::alive_count_);
1570   EXPECT_EQ(1, SubClass::alive_count_);
1571   EXPECT_EQ(1, SubData::alive_count_);
1572 
1573   super_class->DoStuff(super_class.Release(), points_back1.Get(), 2);
1574   PreciselyCollectGarbage();
1575   EXPECT_EQ(2, PointsBack::alive_count_);
1576   EXPECT_EQ(1, SuperClass::alive_count_);
1577   EXPECT_EQ(1, SubClass::alive_count_);
1578   EXPECT_EQ(1, SubData::alive_count_);
1579   EXPECT_EQ(nullptr, points_back1->BackPointer());
1580 
1581   points_back1.Release();
1582   PreciselyCollectGarbage();
1583   EXPECT_EQ(1, PointsBack::alive_count_);
1584   EXPECT_EQ(1, SuperClass::alive_count_);
1585   EXPECT_EQ(1, SubClass::alive_count_);
1586   EXPECT_EQ(1, SubData::alive_count_);
1587 
1588   sub_class->DoStuff(sub_class.Release(), points_back2.Get(), 1);
1589   PreciselyCollectGarbage();
1590   EXPECT_EQ(1, PointsBack::alive_count_);
1591   EXPECT_EQ(0, SuperClass::alive_count_);
1592   EXPECT_EQ(0, SubClass::alive_count_);
1593   EXPECT_EQ(0, SubData::alive_count_);
1594   EXPECT_EQ(nullptr, points_back2->BackPointer());
1595 
1596   points_back2.Release();
1597   PreciselyCollectGarbage();
1598   EXPECT_EQ(0, PointsBack::alive_count_);
1599   EXPECT_EQ(0, SuperClass::alive_count_);
1600   EXPECT_EQ(0, SubClass::alive_count_);
1601   EXPECT_EQ(0, SubData::alive_count_);
1602 
1603   EXPECT_TRUE(super_class == sub_class);
1604 }
1605 
TEST_F(HeapTest,Threading)1606 TEST_F(HeapTest, Threading) {
1607   ThreadedHeapTester::Test();
1608 }
1609 
TEST_F(HeapTest,ThreadedWeakness)1610 TEST_F(HeapTest, ThreadedWeakness) {
1611   ThreadedWeaknessTester::Test();
1612 }
1613 
TEST_F(HeapTest,ThreadPersistent)1614 TEST_F(HeapTest, ThreadPersistent) {
1615   ThreadPersistentHeapTester::Test();
1616 }
1617 
TEST_F(HeapTest,BasicFunctionality)1618 TEST_F(HeapTest, BasicFunctionality) {
1619   ThreadHeap& heap = ThreadState::Current()->Heap();
1620   ClearOutOldGarbage();
1621   size_t initial_object_payload_size = heap.ObjectPayloadSizeForTesting();
1622   {
1623     wtf_size_t slack = 0;
1624 
1625     // When the test starts there may already have been leaked some memory
1626     // on the heap, so we establish a base line.
1627     size_t base_level = initial_object_payload_size;
1628     bool test_pages_allocated = !base_level;
1629     if (test_pages_allocated)
1630       EXPECT_EQ(0ul, heap.stats_collector()->allocated_space_bytes());
1631 
1632     // This allocates objects on the general heap which should add a page of
1633     // memory.
1634     DynamicallySizedObject* alloc32 = DynamicallySizedObject::Create(32);
1635     slack += 4;
1636     memset(alloc32, 40, 32);
1637     DynamicallySizedObject* alloc64 = DynamicallySizedObject::Create(64);
1638     slack += 4;
1639     memset(alloc64, 27, 64);
1640 
1641     size_t total = 96;
1642 
1643     CheckWithSlack(base_level + total, heap.ObjectPayloadSizeForTesting(),
1644                    slack);
1645     if (test_pages_allocated) {
1646       EXPECT_EQ(kBlinkPageSize * 2,
1647                 heap.stats_collector()->allocated_space_bytes());
1648     }
1649 
1650     EXPECT_EQ(alloc32->Get(0), 40);
1651     EXPECT_EQ(alloc32->Get(31), 40);
1652     EXPECT_EQ(alloc64->Get(0), 27);
1653     EXPECT_EQ(alloc64->Get(63), 27);
1654 
1655     ConservativelyCollectGarbage();
1656 
1657     EXPECT_EQ(alloc32->Get(0), 40);
1658     EXPECT_EQ(alloc32->Get(31), 40);
1659     EXPECT_EQ(alloc64->Get(0), 27);
1660     EXPECT_EQ(alloc64->Get(63), 27);
1661   }
1662 
1663   ClearOutOldGarbage();
1664   size_t total = 0;
1665   wtf_size_t slack = 0;
1666   size_t base_level = heap.ObjectPayloadSizeForTesting();
1667   bool test_pages_allocated = !base_level;
1668   if (test_pages_allocated)
1669     EXPECT_EQ(0ul, heap.stats_collector()->allocated_space_bytes());
1670 
1671   size_t big = 1008;
1672   Persistent<DynamicallySizedObject> big_area =
1673       DynamicallySizedObject::Create(big);
1674   total += big;
1675   slack += 4;
1676 
1677   size_t persistent_count = 0;
1678   const size_t kNumPersistents = 100000;
1679   Persistent<DynamicallySizedObject>* persistents[kNumPersistents];
1680 
1681   for (int i = 0; i < 1000; i++) {
1682     size_t size = 128 + i * 8;
1683     total += size;
1684     persistents[persistent_count++] = new Persistent<DynamicallySizedObject>(
1685         DynamicallySizedObject::Create(size));
1686     slack += 4;
1687     // The allocations in the loop may trigger GC with lazy sweeping.
1688     CompleteSweepingIfNeeded();
1689     CheckWithSlack(base_level + total, heap.ObjectPayloadSizeForTesting(),
1690                    slack);
1691     if (test_pages_allocated) {
1692       EXPECT_EQ(0ul, heap.stats_collector()->allocated_space_bytes() &
1693                          (kBlinkPageSize - 1));
1694     }
1695   }
1696 
1697   {
1698     DynamicallySizedObject* alloc32b(DynamicallySizedObject::Create(32));
1699     slack += 4;
1700     memset(alloc32b, 40, 32);
1701     DynamicallySizedObject* alloc64b(DynamicallySizedObject::Create(64));
1702     slack += 4;
1703     memset(alloc64b, 27, 64);
1704     EXPECT_TRUE(alloc32b != alloc64b);
1705 
1706     total += 96;
1707     CheckWithSlack(base_level + total, heap.ObjectPayloadSizeForTesting(),
1708                    slack);
1709     if (test_pages_allocated) {
1710       EXPECT_EQ(0ul, heap.stats_collector()->allocated_space_bytes() &
1711                          (kBlinkPageSize - 1));
1712     }
1713   }
1714 
1715   ClearOutOldGarbage();
1716   total -= 96;
1717   slack -= 8;
1718   if (test_pages_allocated) {
1719     EXPECT_EQ(0ul, heap.stats_collector()->allocated_space_bytes() &
1720                        (kBlinkPageSize - 1));
1721   }
1722 
1723   // Clear the persistent, so that the big area will be garbage collected.
1724   big_area.Release();
1725   ClearOutOldGarbage();
1726 
1727   total -= big;
1728   slack -= 4;
1729   CheckWithSlack(base_level + total, heap.ObjectPayloadSizeForTesting(), slack);
1730   if (test_pages_allocated) {
1731     EXPECT_EQ(0ul, heap.stats_collector()->allocated_space_bytes() &
1732                        (kBlinkPageSize - 1));
1733   }
1734 
1735   CheckWithSlack(base_level + total, heap.ObjectPayloadSizeForTesting(), slack);
1736   if (test_pages_allocated) {
1737     EXPECT_EQ(0ul, heap.stats_collector()->allocated_space_bytes() &
1738                        (kBlinkPageSize - 1));
1739   }
1740 
1741   for (size_t i = 0; i < persistent_count; i++) {
1742     delete persistents[i];
1743     persistents[i] = nullptr;
1744   }
1745 }
1746 
TEST_F(HeapTest,SimpleAllocation)1747 TEST_F(HeapTest, SimpleAllocation) {
1748   ThreadHeap& heap = ThreadState::Current()->Heap();
1749   ClearOutOldGarbage();
1750   EXPECT_EQ(0ul, heap.ObjectPayloadSizeForTesting());
1751 
1752   // Allocate an object in the heap.
1753   HeapAllocatedArray* array = MakeGarbageCollected<HeapAllocatedArray>();
1754   EXPECT_TRUE(heap.ObjectPayloadSizeForTesting() >= sizeof(HeapAllocatedArray));
1755 
1756   // Sanity check of the contents in the heap.
1757   EXPECT_EQ(0, array->at(0));
1758   EXPECT_EQ(42, array->at(42));
1759   EXPECT_EQ(0, array->at(128));
1760   EXPECT_EQ(999 % 128, array->at(999));
1761 }
1762 
TEST_F(HeapTest,SimplePersistent)1763 TEST_F(HeapTest, SimplePersistent) {
1764   Persistent<TraceCounter> trace_counter = MakeGarbageCollected<TraceCounter>();
1765   EXPECT_EQ(0, trace_counter->TraceCount());
1766   PreciselyCollectGarbage();
1767   int saved_trace_count = trace_counter->TraceCount();
1768   EXPECT_LT(0, saved_trace_count);
1769 
1770   Persistent<ClassWithMember> class_with_member =
1771       MakeGarbageCollected<ClassWithMember>();
1772   EXPECT_EQ(0, class_with_member->TraceCount());
1773   PreciselyCollectGarbage();
1774   EXPECT_LT(0, class_with_member->TraceCount());
1775   EXPECT_LT(saved_trace_count, trace_counter->TraceCount());
1776 }
1777 
TEST_F(HeapTest,SimpleFinalization)1778 TEST_F(HeapTest, SimpleFinalization) {
1779   ClearOutOldGarbage();
1780   {
1781     SimpleFinalizedObject::destructor_calls_ = 0;
1782     Persistent<SimpleFinalizedObject> finalized =
1783         MakeGarbageCollected<SimpleFinalizedObject>();
1784     EXPECT_EQ(0, SimpleFinalizedObject::destructor_calls_);
1785     PreciselyCollectGarbage();
1786     EXPECT_EQ(0, SimpleFinalizedObject::destructor_calls_);
1787   }
1788 
1789   PreciselyCollectGarbage();
1790   EXPECT_EQ(1, SimpleFinalizedObject::destructor_calls_);
1791 }
1792 
1793 #if DCHECK_IS_ON() || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER)
TEST_F(HeapTest,FreelistReuse)1794 TEST_F(HeapTest, FreelistReuse) {
1795   ClearOutOldGarbage();
1796 
1797   for (int i = 0; i < 100; i++)
1798     MakeGarbageCollected<IntWrapper>(i);
1799   IntWrapper* p1 = MakeGarbageCollected<IntWrapper>(100);
1800   PreciselyCollectGarbage();
1801   // In non-production builds, we delay reusing freed memory for at least
1802   // one GC cycle.
1803   for (int i = 0; i < 100; i++) {
1804     IntWrapper* p2 = MakeGarbageCollected<IntWrapper>(i);
1805     EXPECT_NE(p1, p2);
1806   }
1807 
1808   PreciselyCollectGarbage();
1809   PreciselyCollectGarbage();
1810   // Now the freed memory in the first GC should be reused.
1811   bool reused_memory_found = false;
1812   for (int i = 0; i < 10000; i++) {
1813     IntWrapper* p2 = MakeGarbageCollected<IntWrapper>(i);
1814     if (p1 == p2) {
1815       reused_memory_found = true;
1816       break;
1817     }
1818   }
1819   EXPECT_TRUE(reused_memory_found);
1820 }
1821 #endif
1822 
TEST_F(HeapTest,LazySweepingPages)1823 TEST_F(HeapTest, LazySweepingPages) {
1824   ClearOutOldGarbage();
1825 
1826   SimpleFinalizedObject::destructor_calls_ = 0;
1827   EXPECT_EQ(0, SimpleFinalizedObject::destructor_calls_);
1828   for (int i = 0; i < 1000; i++)
1829     MakeGarbageCollected<SimpleFinalizedObject>();
1830   ThreadState::Current()->CollectGarbage(
1831       BlinkGC::CollectionType::kMajor, BlinkGC::kNoHeapPointersOnStack,
1832       BlinkGC::kAtomicMarking, BlinkGC::kConcurrentAndLazySweeping,
1833       BlinkGC::GCReason::kForcedGCForTesting);
1834   EXPECT_EQ(0, SimpleFinalizedObject::destructor_calls_);
1835   for (int i = 0; i < 10000; i++)
1836     MakeGarbageCollected<SimpleFinalizedObject>();
1837   EXPECT_EQ(1000, SimpleFinalizedObject::destructor_calls_);
1838   PreciselyCollectGarbage();
1839   EXPECT_EQ(11000, SimpleFinalizedObject::destructor_calls_);
1840 }
1841 
TEST_F(HeapTest,LazySweepingLargeObjectPages)1842 TEST_F(HeapTest, LazySweepingLargeObjectPages) {
1843   // Disable concurrent sweeping to check lazy sweeping on allocation.
1844   base::test::ScopedFeatureList scoped_feature_list;
1845   scoped_feature_list.InitAndDisableFeature(
1846       blink::features::kBlinkHeapConcurrentSweeping);
1847 
1848   ClearOutOldGarbage();
1849 
1850   // Create free lists that can be reused for IntWrappers created in
1851   // MakeGarbageCollected<LargeHeapObject>().
1852   Persistent<IntWrapper> p1 = MakeGarbageCollected<IntWrapper>(1);
1853   for (int i = 0; i < 100; i++) {
1854     MakeGarbageCollected<IntWrapper>(i);
1855   }
1856   Persistent<IntWrapper> p2 = MakeGarbageCollected<IntWrapper>(2);
1857   PreciselyCollectGarbage();
1858   PreciselyCollectGarbage();
1859 
1860   LargeHeapObject::destructor_calls_ = 0;
1861   EXPECT_EQ(0, LargeHeapObject::destructor_calls_);
1862   for (int i = 0; i < 10; i++)
1863     MakeGarbageCollected<LargeHeapObject>();
1864   ThreadState::Current()->CollectGarbage(
1865       BlinkGC::CollectionType::kMajor, BlinkGC::kNoHeapPointersOnStack,
1866       BlinkGC::kAtomicMarking, BlinkGC::kConcurrentAndLazySweeping,
1867       BlinkGC::GCReason::kForcedGCForTesting);
1868   EXPECT_EQ(0, LargeHeapObject::destructor_calls_);
1869   for (int i = 0; i < 10; i++) {
1870     MakeGarbageCollected<LargeHeapObject>();
1871     EXPECT_EQ(i + 1, LargeHeapObject::destructor_calls_);
1872   }
1873   MakeGarbageCollected<LargeHeapObject>();
1874   MakeGarbageCollected<LargeHeapObject>();
1875   EXPECT_EQ(10, LargeHeapObject::destructor_calls_);
1876   ThreadState::Current()->CollectGarbage(
1877       BlinkGC::CollectionType::kMajor, BlinkGC::kNoHeapPointersOnStack,
1878       BlinkGC::kAtomicMarking, BlinkGC::kConcurrentAndLazySweeping,
1879       BlinkGC::GCReason::kForcedGCForTesting);
1880   EXPECT_EQ(10, LargeHeapObject::destructor_calls_);
1881   PreciselyCollectGarbage();
1882   EXPECT_EQ(22, LargeHeapObject::destructor_calls_);
1883 }
1884 
TEST_F(HeapTest,Finalization)1885 TEST_F(HeapTest, Finalization) {
1886   {
1887     HeapTestSubClass::destructor_calls_ = 0;
1888     HeapTestSuperClass::destructor_calls_ = 0;
1889     auto* t1 = MakeGarbageCollected<HeapTestSubClass>();
1890     auto* t2 = MakeGarbageCollected<HeapTestSubClass>();
1891     auto* t3 = MakeGarbageCollected<HeapTestSuperClass>();
1892     // FIXME(oilpan): Ignore unused variables.
1893     (void)t1;
1894     (void)t2;
1895     (void)t3;
1896   }
1897   // Nothing is marked so the GC should free everything and call
1898   // the finalizer on all three objects.
1899   PreciselyCollectGarbage();
1900   EXPECT_EQ(2, HeapTestSubClass::destructor_calls_);
1901   EXPECT_EQ(3, HeapTestSuperClass::destructor_calls_);
1902   // Destructors not called again when GCing again.
1903   PreciselyCollectGarbage();
1904   EXPECT_EQ(2, HeapTestSubClass::destructor_calls_);
1905   EXPECT_EQ(3, HeapTestSuperClass::destructor_calls_);
1906 }
1907 
TEST_F(HeapTest,TypedArenaSanity)1908 TEST_F(HeapTest, TypedArenaSanity) {
1909   // We use TraceCounter for allocating an object on the general heap.
1910   Persistent<TraceCounter> general_heap_object =
1911       MakeGarbageCollected<TraceCounter>();
1912   Persistent<IntNode> typed_heap_object = IntNode::Create(0);
1913   EXPECT_NE(PageFromObject(general_heap_object.Get()),
1914             PageFromObject(typed_heap_object.Get()));
1915 }
1916 
TEST_F(HeapTest,NoAllocation)1917 TEST_F(HeapTest, NoAllocation) {
1918   ThreadState* state = ThreadState::Current();
1919   EXPECT_TRUE(state->IsAllocationAllowed());
1920   {
1921     // Disallow allocation
1922     ThreadState::NoAllocationScope no_allocation_scope(state);
1923     EXPECT_FALSE(state->IsAllocationAllowed());
1924   }
1925   EXPECT_TRUE(state->IsAllocationAllowed());
1926 }
1927 
TEST_F(HeapTest,Members)1928 TEST_F(HeapTest, Members) {
1929   ClearOutOldGarbage();
1930   Bar::live_ = 0;
1931   {
1932     Persistent<Baz> h1;
1933     Persistent<Baz> h2;
1934     {
1935       h1 = MakeGarbageCollected<Baz>(MakeGarbageCollected<Bar>());
1936       PreciselyCollectGarbage();
1937       EXPECT_EQ(1u, Bar::live_);
1938       h2 = MakeGarbageCollected<Baz>(MakeGarbageCollected<Bar>());
1939       PreciselyCollectGarbage();
1940       EXPECT_EQ(2u, Bar::live_);
1941     }
1942     PreciselyCollectGarbage();
1943     EXPECT_EQ(2u, Bar::live_);
1944     h1->Clear();
1945     PreciselyCollectGarbage();
1946     EXPECT_EQ(1u, Bar::live_);
1947   }
1948   PreciselyCollectGarbage();
1949   EXPECT_EQ(0u, Bar::live_);
1950 }
1951 
TEST_F(HeapTest,MarkTest)1952 TEST_F(HeapTest, MarkTest) {
1953   ClearOutOldGarbage();
1954   {
1955     Bar::live_ = 0;
1956     Persistent<Bar> bar = MakeGarbageCollected<Bar>();
1957 #if DCHECK_IS_ON()
1958     DCHECK(ThreadState::Current()->Heap().FindPageFromAddress(bar));
1959 #endif
1960     EXPECT_EQ(1u, Bar::live_);
1961     {
1962       auto* foo = MakeGarbageCollected<Foo>(bar);
1963 #if DCHECK_IS_ON()
1964       DCHECK(ThreadState::Current()->Heap().FindPageFromAddress(foo));
1965 #endif
1966       EXPECT_EQ(2u, Bar::live_);
1967       EXPECT_TRUE(reinterpret_cast<Address>(foo) !=
1968                   reinterpret_cast<Address>(bar.Get()));
1969       ConservativelyCollectGarbage();
1970       EXPECT_TRUE(foo != bar);  // To make sure foo is kept alive.
1971       EXPECT_EQ(2u, Bar::live_);
1972     }
1973     PreciselyCollectGarbage();
1974     EXPECT_EQ(1u, Bar::live_);
1975   }
1976   PreciselyCollectGarbage();
1977   EXPECT_EQ(0u, Bar::live_);
1978 }
1979 
TEST_F(HeapTest,DeepTest)1980 TEST_F(HeapTest, DeepTest) {
1981   ClearOutOldGarbage();
1982   const unsigned kDepth = 100000;
1983   Bar::live_ = 0;
1984   {
1985     auto* bar = MakeGarbageCollected<Bar>();
1986 #if DCHECK_IS_ON()
1987     DCHECK(ThreadState::Current()->Heap().FindPageFromAddress(bar));
1988 #endif
1989     auto* foo = MakeGarbageCollected<Foo>(bar);
1990 #if DCHECK_IS_ON()
1991     DCHECK(ThreadState::Current()->Heap().FindPageFromAddress(foo));
1992 #endif
1993     EXPECT_EQ(2u, Bar::live_);
1994     for (unsigned i = 0; i < kDepth; i++) {
1995       auto* foo2 = MakeGarbageCollected<Foo>(foo);
1996       foo = foo2;
1997 #if DCHECK_IS_ON()
1998       DCHECK(ThreadState::Current()->Heap().FindPageFromAddress(foo));
1999 #endif
2000     }
2001     EXPECT_EQ(kDepth + 2, Bar::live_);
2002     ConservativelyCollectGarbage();
2003     EXPECT_TRUE(foo != bar);  // To make sure foo and bar are kept alive.
2004     EXPECT_EQ(kDepth + 2, Bar::live_);
2005   }
2006   PreciselyCollectGarbage();
2007   EXPECT_EQ(0u, Bar::live_);
2008 }
2009 
TEST_F(HeapTest,WideTest)2010 TEST_F(HeapTest, WideTest) {
2011   ClearOutOldGarbage();
2012   Bar::live_ = 0;
2013   {
2014     auto* bars = MakeGarbageCollected<Bars>();
2015     unsigned width = Bars::kWidth;
2016     EXPECT_EQ(width + 1, Bar::live_);
2017     ConservativelyCollectGarbage();
2018     EXPECT_EQ(width + 1, Bar::live_);
2019     // Use bars here to make sure that it will be on the stack
2020     // for the conservative stack scan to find.
2021     EXPECT_EQ(width, bars->GetWidth());
2022   }
2023   EXPECT_EQ(Bars::kWidth + 1, Bar::live_);
2024   PreciselyCollectGarbage();
2025   EXPECT_EQ(0u, Bar::live_);
2026 }
2027 
TEST_F(HeapTest,HashMapOfMembers)2028 TEST_F(HeapTest, HashMapOfMembers) {
2029   ClearOutOldGarbage();
2030   ThreadHeap& heap = ThreadState::Current()->Heap();
2031   IntWrapper::destructor_calls_ = 0;
2032   size_t initial_object_payload_size = heap.ObjectPayloadSizeForTesting();
2033   {
2034     typedef HeapHashMap<Member<IntWrapper>, Member<IntWrapper>,
2035                         DefaultHash<Member<IntWrapper>>::Hash,
2036                         HashTraits<Member<IntWrapper>>,
2037                         HashTraits<Member<IntWrapper>>>
2038         HeapObjectIdentityMap;
2039 
2040     Persistent<HeapObjectIdentityMap> map =
2041         MakeGarbageCollected<HeapObjectIdentityMap>();
2042 
2043     map->clear();
2044     size_t after_set_was_created = heap.ObjectPayloadSizeForTesting();
2045     EXPECT_TRUE(after_set_was_created > initial_object_payload_size);
2046 
2047     PreciselyCollectGarbage();
2048     size_t after_gc = heap.ObjectPayloadSizeForTesting();
2049     EXPECT_EQ(after_gc, after_set_was_created);
2050 
2051     // If the additions below cause garbage collections, these
2052     // pointers should be found by conservative stack scanning.
2053     auto* one(MakeGarbageCollected<IntWrapper>(1));
2054     auto* another_one(MakeGarbageCollected<IntWrapper>(1));
2055 
2056     map->insert(one, one);
2057 
2058     size_t after_one_add = heap.ObjectPayloadSizeForTesting();
2059     EXPECT_TRUE(after_one_add > after_gc);
2060 
2061     HeapObjectIdentityMap::iterator it(map->begin());
2062     HeapObjectIdentityMap::iterator it2(map->begin());
2063     ++it;
2064     ++it2;
2065 
2066     map->insert(another_one, one);
2067 
2068     // The addition above can cause an allocation of a new
2069     // backing store. We therefore garbage collect before
2070     // taking the heap stats in order to get rid of the old
2071     // backing store. We make sure to not use conservative
2072     // stack scanning as that could find a pointer to the
2073     // old backing.
2074     PreciselyCollectGarbage();
2075     size_t after_add_and_gc = heap.ObjectPayloadSizeForTesting();
2076     EXPECT_TRUE(after_add_and_gc >= after_one_add);
2077 
2078     EXPECT_EQ(map->size(), 2u);  // Two different wrappings of '1' are distinct.
2079 
2080     PreciselyCollectGarbage();
2081     EXPECT_TRUE(map->Contains(one));
2082     EXPECT_TRUE(map->Contains(another_one));
2083 
2084     IntWrapper* gotten(map->at(one));
2085     EXPECT_EQ(gotten->Value(), one->Value());
2086     EXPECT_EQ(gotten, one);
2087 
2088     size_t after_gc2 = heap.ObjectPayloadSizeForTesting();
2089     EXPECT_EQ(after_gc2, after_add_and_gc);
2090 
2091     IntWrapper* dozen = nullptr;
2092 
2093     for (int i = 1; i < 1000; i++) {  // 999 iterations.
2094       auto* i_wrapper(MakeGarbageCollected<IntWrapper>(i));
2095       auto* i_squared(MakeGarbageCollected<IntWrapper>(i * i));
2096       map->insert(i_wrapper, i_squared);
2097       if (i == 12)
2098         dozen = i_wrapper;
2099     }
2100     size_t after_adding1000 = heap.ObjectPayloadSizeForTesting();
2101     EXPECT_TRUE(after_adding1000 > after_gc2);
2102 
2103     IntWrapper* gross(map->at(dozen));
2104     EXPECT_EQ(gross->Value(), 144);
2105 
2106     // This should clear out any junk backings created by all the adds.
2107     PreciselyCollectGarbage();
2108     size_t after_gc3 = heap.ObjectPayloadSizeForTesting();
2109     EXPECT_TRUE(after_gc3 <= after_adding1000);
2110   }
2111 
2112   PreciselyCollectGarbage();
2113   // The objects 'one', anotherOne, and the 999 other pairs.
2114   EXPECT_EQ(IntWrapper::destructor_calls_, 2000);
2115   size_t after_gc4 = heap.ObjectPayloadSizeForTesting();
2116   EXPECT_EQ(after_gc4, initial_object_payload_size);
2117 }
2118 
TEST_F(HeapTest,NestedAllocation)2119 TEST_F(HeapTest, NestedAllocation) {
2120   ThreadHeap& heap = ThreadState::Current()->Heap();
2121   ClearOutOldGarbage();
2122   size_t initial_object_payload_size = heap.ObjectPayloadSizeForTesting();
2123   {
2124     Persistent<ConstructorAllocation> constructor_allocation =
2125         MakeGarbageCollected<ConstructorAllocation>();
2126   }
2127   ClearOutOldGarbage();
2128   size_t after_free = heap.ObjectPayloadSizeForTesting();
2129   EXPECT_TRUE(initial_object_payload_size == after_free);
2130 }
2131 
TEST_F(HeapTest,LargeHeapObjects)2132 TEST_F(HeapTest, LargeHeapObjects) {
2133   ThreadHeap& heap = ThreadState::Current()->Heap();
2134   ClearOutOldGarbage();
2135   size_t initial_object_payload_size = heap.ObjectPayloadSizeForTesting();
2136   size_t initial_allocated_space =
2137       heap.stats_collector()->allocated_space_bytes();
2138   IntWrapper::destructor_calls_ = 0;
2139   LargeHeapObject::destructor_calls_ = 0;
2140   {
2141     int slack =
2142         8;  // LargeHeapObject points to an IntWrapper that is also allocated.
2143     Persistent<LargeHeapObject> object =
2144         MakeGarbageCollected<LargeHeapObject>();
2145 #if DCHECK_IS_ON()
2146     DCHECK(ThreadState::Current()->Heap().FindPageFromAddress(object));
2147     DCHECK(ThreadState::Current()->Heap().FindPageFromAddress(
2148         reinterpret_cast<char*>(object.Get()) + sizeof(LargeHeapObject) - 1));
2149 #endif
2150     ClearOutOldGarbage();
2151     size_t after_allocation = heap.stats_collector()->allocated_space_bytes();
2152     {
2153       object->Set(0, 'a');
2154       EXPECT_EQ('a', object->Get(0));
2155       object->Set(object->length() - 1, 'b');
2156       EXPECT_EQ('b', object->Get(object->length() - 1));
2157       size_t expected_large_heap_object_payload_size =
2158           ThreadHeap::AllocationSizeFromSize(sizeof(LargeHeapObject)) -
2159           sizeof(HeapObjectHeader);
2160       size_t expected_object_payload_size =
2161           expected_large_heap_object_payload_size + sizeof(IntWrapper);
2162       size_t actual_object_payload_size =
2163           heap.ObjectPayloadSizeForTesting() - initial_object_payload_size;
2164       CheckWithSlack(expected_object_payload_size, actual_object_payload_size,
2165                      slack);
2166       // There is probably space for the IntWrapper in a heap page without
2167       // allocating extra pages. However, the IntWrapper allocation might cause
2168       // the addition of a heap page.
2169       size_t large_object_allocation_size =
2170           sizeof(LargeObjectPage) + expected_large_heap_object_payload_size;
2171       size_t allocated_space_lower_bound =
2172           initial_allocated_space + large_object_allocation_size;
2173       size_t allocated_space_upper_bound =
2174           allocated_space_lower_bound + slack + kBlinkPageSize;
2175       EXPECT_LE(allocated_space_lower_bound, after_allocation);
2176       EXPECT_LE(after_allocation, allocated_space_upper_bound);
2177       EXPECT_EQ(0, IntWrapper::destructor_calls_);
2178       EXPECT_EQ(0, LargeHeapObject::destructor_calls_);
2179       for (int i = 0; i < 10; i++)
2180         object = MakeGarbageCollected<LargeHeapObject>();
2181     }
2182     ClearOutOldGarbage();
2183     EXPECT_EQ(after_allocation,
2184               heap.stats_collector()->allocated_space_bytes());
2185     EXPECT_EQ(10, IntWrapper::destructor_calls_);
2186     EXPECT_EQ(10, LargeHeapObject::destructor_calls_);
2187   }
2188   ClearOutOldGarbage();
2189   EXPECT_TRUE(initial_object_payload_size ==
2190               heap.ObjectPayloadSizeForTesting());
2191   EXPECT_EQ(initial_allocated_space,
2192             heap.stats_collector()->allocated_space_bytes());
2193   EXPECT_EQ(11, IntWrapper::destructor_calls_);
2194   EXPECT_EQ(11, LargeHeapObject::destructor_calls_);
2195   PreciselyCollectGarbage();
2196 }
2197 
2198 // This test often fails on Android (https://crbug.com/843032).
2199 // We run out of memory on Android devices because ReserveCapacityForSize
2200 // actually allocates a much larger backing than specified (in this case 400MB).
2201 #if defined(OS_ANDROID)
2202 #define MAYBE_LargeHashMap DISABLED_LargeHashMap
2203 #else
2204 #define MAYBE_LargeHashMap LargeHashMap
2205 #endif
TEST_F(HeapTest,MAYBE_LargeHashMap)2206 TEST_F(HeapTest, MAYBE_LargeHashMap) {
2207   ClearOutOldGarbage();
2208 
2209   // Try to allocate a HashTable larger than kMaxHeapObjectSize
2210   // (crbug.com/597953).
2211   wtf_size_t size = kMaxHeapObjectSize /
2212                     sizeof(HeapHashMap<int, Member<IntWrapper>>::ValueType);
2213   Persistent<HeapHashMap<int, Member<IntWrapper>>> map =
2214       MakeGarbageCollected<HeapHashMap<int, Member<IntWrapper>>>();
2215   map->ReserveCapacityForSize(size);
2216   EXPECT_LE(size, map->Capacity());
2217 }
2218 
TEST_F(HeapTest,LargeVector)2219 TEST_F(HeapTest, LargeVector) {
2220   ClearOutOldGarbage();
2221 
2222   // Try to allocate a HeapVectors larger than kMaxHeapObjectSize
2223   // (crbug.com/597953).
2224   const wtf_size_t size = kMaxHeapObjectSize / sizeof(Member<IntWrapper>);
2225   Persistent<HeapVector<Member<IntWrapper>>> vector =
2226       MakeGarbageCollected<HeapVector<Member<IntWrapper>>>(size);
2227   EXPECT_LE(size, vector->capacity());
2228 }
2229 
2230 typedef std::pair<Member<IntWrapper>, int> PairWrappedUnwrapped;
2231 typedef std::pair<int, Member<IntWrapper>> PairUnwrappedWrapped;
2232 typedef std::pair<WeakMember<IntWrapper>, Member<IntWrapper>> PairWeakStrong;
2233 typedef std::pair<Member<IntWrapper>, WeakMember<IntWrapper>> PairStrongWeak;
2234 typedef std::pair<WeakMember<IntWrapper>, int> PairWeakUnwrapped;
2235 typedef std::pair<int, WeakMember<IntWrapper>> PairUnwrappedWeak;
2236 
2237 class Container final : public GarbageCollected<Container> {
2238  public:
2239   HeapHashMap<Member<IntWrapper>, Member<IntWrapper>> map;
2240   HeapHashSet<Member<IntWrapper>> set;
2241   HeapHashSet<Member<IntWrapper>> set2;
2242   HeapHashCountedSet<Member<IntWrapper>> set3;
2243   HeapVector<Member<IntWrapper>, 2> vector;
2244   HeapVector<PairWrappedUnwrapped, 2> vector_wu;
2245   HeapVector<PairUnwrappedWrapped, 2> vector_uw;
2246   HeapDeque<Member<IntWrapper>> deque;
Trace(Visitor * visitor)2247   void Trace(Visitor* visitor) {
2248     visitor->Trace(map);
2249     visitor->Trace(set);
2250     visitor->Trace(set2);
2251     visitor->Trace(set3);
2252     visitor->Trace(vector);
2253     visitor->Trace(vector_wu);
2254     visitor->Trace(vector_uw);
2255     visitor->Trace(deque);
2256   }
2257 };
2258 
2259 struct NeedsTracingTrait {
NeedsTracingTraitblink::NeedsTracingTrait2260   explicit NeedsTracingTrait(IntWrapper* wrapper) : wrapper_(wrapper) {}
Traceblink::NeedsTracingTrait2261   void Trace(Visitor* visitor) { visitor->Trace(wrapper_); }
2262   Member<IntWrapper> wrapper_;
2263 };
2264 
TEST_F(HeapTest,HeapVectorFilledWithValue)2265 TEST_F(HeapTest, HeapVectorFilledWithValue) {
2266   auto* val = MakeGarbageCollected<IntWrapper>(1);
2267   HeapVector<Member<IntWrapper>> vector(10, val);
2268   EXPECT_EQ(10u, vector.size());
2269   for (wtf_size_t i = 0; i < vector.size(); i++)
2270     EXPECT_EQ(val, vector[i]);
2271 }
2272 
TEST_F(HeapTest,HeapVectorWithInlineCapacity)2273 TEST_F(HeapTest, HeapVectorWithInlineCapacity) {
2274   auto* one = MakeGarbageCollected<IntWrapper>(1);
2275   auto* two = MakeGarbageCollected<IntWrapper>(2);
2276   auto* three = MakeGarbageCollected<IntWrapper>(3);
2277   auto* four = MakeGarbageCollected<IntWrapper>(4);
2278   auto* five = MakeGarbageCollected<IntWrapper>(5);
2279   auto* six = MakeGarbageCollected<IntWrapper>(6);
2280   {
2281     HeapVector<Member<IntWrapper>, 2> vector;
2282     vector.push_back(one);
2283     vector.push_back(two);
2284     ConservativelyCollectGarbage();
2285     EXPECT_TRUE(vector.Contains(one));
2286     EXPECT_TRUE(vector.Contains(two));
2287 
2288     vector.push_back(three);
2289     vector.push_back(four);
2290     ConservativelyCollectGarbage();
2291     EXPECT_TRUE(vector.Contains(one));
2292     EXPECT_TRUE(vector.Contains(two));
2293     EXPECT_TRUE(vector.Contains(three));
2294     EXPECT_TRUE(vector.Contains(four));
2295 
2296     vector.Shrink(1);
2297     ConservativelyCollectGarbage();
2298     EXPECT_TRUE(vector.Contains(one));
2299     EXPECT_FALSE(vector.Contains(two));
2300     EXPECT_FALSE(vector.Contains(three));
2301     EXPECT_FALSE(vector.Contains(four));
2302   }
2303   {
2304     HeapVector<Member<IntWrapper>, 2> vector1;
2305     HeapVector<Member<IntWrapper>, 2> vector2;
2306 
2307     vector1.push_back(one);
2308     vector2.push_back(two);
2309     vector1.swap(vector2);
2310     ConservativelyCollectGarbage();
2311     EXPECT_TRUE(vector1.Contains(two));
2312     EXPECT_TRUE(vector2.Contains(one));
2313   }
2314   {
2315     HeapVector<Member<IntWrapper>, 2> vector1;
2316     HeapVector<Member<IntWrapper>, 2> vector2;
2317 
2318     vector1.push_back(one);
2319     vector1.push_back(two);
2320     vector2.push_back(three);
2321     vector2.push_back(four);
2322     vector2.push_back(five);
2323     vector2.push_back(six);
2324     vector1.swap(vector2);
2325     ConservativelyCollectGarbage();
2326     EXPECT_TRUE(vector1.Contains(three));
2327     EXPECT_TRUE(vector1.Contains(four));
2328     EXPECT_TRUE(vector1.Contains(five));
2329     EXPECT_TRUE(vector1.Contains(six));
2330     EXPECT_TRUE(vector2.Contains(one));
2331     EXPECT_TRUE(vector2.Contains(two));
2332   }
2333 }
2334 
TEST_F(HeapTest,HeapVectorShrinkCapacity)2335 TEST_F(HeapTest, HeapVectorShrinkCapacity) {
2336   ClearOutOldGarbage();
2337   HeapVector<Member<IntWrapper>> vector1;
2338   HeapVector<Member<IntWrapper>> vector2;
2339   vector1.ReserveCapacity(96);
2340   EXPECT_LE(96u, vector1.capacity());
2341   vector1.Grow(vector1.capacity());
2342 
2343   // Assumes none was allocated just after a vector backing of vector1.
2344   vector1.Shrink(56);
2345   vector1.ShrinkToFit();
2346   EXPECT_GT(96u, vector1.capacity());
2347 
2348   vector2.ReserveCapacity(20);
2349   // Assumes another vector backing was allocated just after the vector
2350   // backing of vector1.
2351   vector1.Shrink(10);
2352   vector1.ShrinkToFit();
2353   EXPECT_GT(56u, vector1.capacity());
2354 
2355   vector1.Grow(192);
2356   EXPECT_LE(192u, vector1.capacity());
2357 }
2358 
TEST_F(HeapTest,HeapVectorShrinkInlineCapacity)2359 TEST_F(HeapTest, HeapVectorShrinkInlineCapacity) {
2360   ClearOutOldGarbage();
2361   const size_t kInlineCapacity = 64;
2362   HeapVector<Member<IntWrapper>, kInlineCapacity> vector1;
2363   vector1.ReserveCapacity(128);
2364   EXPECT_LE(128u, vector1.capacity());
2365   vector1.Grow(vector1.capacity());
2366 
2367   // Shrink the external buffer.
2368   vector1.Shrink(90);
2369   vector1.ShrinkToFit();
2370   EXPECT_GT(128u, vector1.capacity());
2371 
2372 // TODO(sof): if the ASan support for 'contiguous containers' is enabled,
2373 // Vector inline buffers are disabled; that constraint should be attempted
2374 // removed, but until that time, disable testing handling of capacities
2375 // of inline buffers.
2376 #if !defined(ANNOTATE_CONTIGUOUS_CONTAINER)
2377   // Shrinking switches the buffer from the external one to the inline one.
2378   vector1.Shrink(kInlineCapacity - 1);
2379   vector1.ShrinkToFit();
2380   EXPECT_EQ(kInlineCapacity, vector1.capacity());
2381 
2382   // Try to shrink the inline buffer.
2383   vector1.Shrink(1);
2384   vector1.ShrinkToFit();
2385   EXPECT_EQ(kInlineCapacity, vector1.capacity());
2386 #endif
2387 }
2388 
TEST_F(HeapTest,HeapVectorOnStackLargeObjectPageSized)2389 TEST_F(HeapTest, HeapVectorOnStackLargeObjectPageSized) {
2390   ClearOutOldGarbage();
2391   // Try to allocate a vector of a size that will end exactly where the
2392   // LargeObjectPage ends.
2393   using Container = HeapVector<Member<IntWrapper>>;
2394   Container vector;
2395   wtf_size_t size =
2396       (kLargeObjectSizeThreshold + kBlinkGuardPageSize -
2397        static_cast<wtf_size_t>(LargeObjectPage::PageHeaderSize()) -
2398        sizeof(HeapObjectHeader)) /
2399       sizeof(Container::ValueType);
2400   vector.ReserveCapacity(size);
2401   for (unsigned i = 0; i < size; ++i)
2402     vector.push_back(MakeGarbageCollected<IntWrapper>(i));
2403   ConservativelyCollectGarbage();
2404 }
2405 
2406 template <typename T, typename U>
DequeContains(HeapDeque<T> & deque,U u)2407 bool DequeContains(HeapDeque<T>& deque, U u) {
2408   typedef typename HeapDeque<T>::iterator iterator;
2409   for (iterator it = deque.begin(); it != deque.end(); ++it) {
2410     if (*it == u)
2411       return true;
2412   }
2413   return false;
2414 }
2415 
TEST_F(HeapTest,HeapCollectionTypes)2416 TEST_F(HeapTest, HeapCollectionTypes) {
2417   IntWrapper::destructor_calls_ = 0;
2418 
2419   typedef HeapHashMap<Member<IntWrapper>, Member<IntWrapper>> MemberMember;
2420   typedef HeapHashMap<Member<IntWrapper>, int> MemberPrimitive;
2421   typedef HeapHashMap<int, Member<IntWrapper>> PrimitiveMember;
2422 
2423   typedef HeapHashSet<Member<IntWrapper>> MemberSet;
2424   typedef HeapHashCountedSet<Member<IntWrapper>> MemberCountedSet;
2425 
2426   typedef HeapVector<Member<IntWrapper>, 2> MemberVector;
2427   typedef HeapDeque<Member<IntWrapper>> MemberDeque;
2428 
2429   typedef HeapVector<PairWrappedUnwrapped, 2> VectorWU;
2430   typedef HeapVector<PairUnwrappedWrapped, 2> VectorUW;
2431 
2432   Persistent<MemberMember> member_member = MakeGarbageCollected<MemberMember>();
2433   Persistent<MemberMember> member_member2 =
2434       MakeGarbageCollected<MemberMember>();
2435   Persistent<MemberMember> member_member3 =
2436       MakeGarbageCollected<MemberMember>();
2437   Persistent<MemberPrimitive> member_primitive =
2438       MakeGarbageCollected<MemberPrimitive>();
2439   Persistent<PrimitiveMember> primitive_member =
2440       MakeGarbageCollected<PrimitiveMember>();
2441   Persistent<MemberSet> set = MakeGarbageCollected<MemberSet>();
2442   Persistent<MemberSet> set2 = MakeGarbageCollected<MemberSet>();
2443   Persistent<MemberCountedSet> set3 = MakeGarbageCollected<MemberCountedSet>();
2444   Persistent<MemberVector> vector = MakeGarbageCollected<MemberVector>();
2445   Persistent<MemberVector> vector2 = MakeGarbageCollected<MemberVector>();
2446   Persistent<VectorWU> vector_wu = MakeGarbageCollected<VectorWU>();
2447   Persistent<VectorWU> vector_wu2 = MakeGarbageCollected<VectorWU>();
2448   Persistent<VectorUW> vector_uw = MakeGarbageCollected<VectorUW>();
2449   Persistent<VectorUW> vector_uw2 = MakeGarbageCollected<VectorUW>();
2450   Persistent<MemberDeque> deque = MakeGarbageCollected<MemberDeque>();
2451   Persistent<MemberDeque> deque2 = MakeGarbageCollected<MemberDeque>();
2452   Persistent<Container> container = MakeGarbageCollected<Container>();
2453 
2454   ClearOutOldGarbage();
2455   {
2456     Persistent<IntWrapper> one(MakeGarbageCollected<IntWrapper>(1));
2457     Persistent<IntWrapper> two(MakeGarbageCollected<IntWrapper>(2));
2458     Persistent<IntWrapper> one_b(MakeGarbageCollected<IntWrapper>(1));
2459     Persistent<IntWrapper> two_b(MakeGarbageCollected<IntWrapper>(2));
2460     Persistent<IntWrapper> one_c(MakeGarbageCollected<IntWrapper>(1));
2461     Persistent<IntWrapper> one_d(MakeGarbageCollected<IntWrapper>(1));
2462     Persistent<IntWrapper> one_e(MakeGarbageCollected<IntWrapper>(1));
2463     Persistent<IntWrapper> one_f(MakeGarbageCollected<IntWrapper>(1));
2464     {
2465       auto* three_b(MakeGarbageCollected<IntWrapper>(3));
2466       auto* three_c(MakeGarbageCollected<IntWrapper>(3));
2467       auto* three_d(MakeGarbageCollected<IntWrapper>(3));
2468       auto* three_e(MakeGarbageCollected<IntWrapper>(3));
2469       auto* three(MakeGarbageCollected<IntWrapper>(3));
2470       auto* four_b(MakeGarbageCollected<IntWrapper>(4));
2471       auto* four_c(MakeGarbageCollected<IntWrapper>(4));
2472       auto* four_d(MakeGarbageCollected<IntWrapper>(4));
2473       auto* four_e(MakeGarbageCollected<IntWrapper>(4));
2474       auto* four(MakeGarbageCollected<IntWrapper>(4));
2475       auto* five_c(MakeGarbageCollected<IntWrapper>(5));
2476       auto* five_d(MakeGarbageCollected<IntWrapper>(5));
2477 
2478       // Member Collections.
2479       member_member2->insert(one, two);
2480       member_member2->insert(two, three);
2481       member_member2->insert(three, four);
2482       member_member2->insert(four, one);
2483       primitive_member->insert(1, two);
2484       primitive_member->insert(2, three);
2485       primitive_member->insert(3, four);
2486       primitive_member->insert(4, one);
2487       member_primitive->insert(one, 2);
2488       member_primitive->insert(two, 3);
2489       member_primitive->insert(three, 4);
2490       member_primitive->insert(four, 1);
2491       set2->insert(one);
2492       set2->insert(two);
2493       set2->insert(three);
2494       set2->insert(four);
2495       set->insert(one_b);
2496       set3->insert(one_b);
2497       set3->insert(one_b);
2498       vector->push_back(one_b);
2499       deque->push_back(one_b);
2500       vector2->push_back(three_b);
2501       vector2->push_back(four_b);
2502       deque2->push_back(three_e);
2503       deque2->push_back(four_e);
2504       vector_wu->push_back(PairWrappedUnwrapped(&*one_c, 42));
2505       vector_wu2->push_back(PairWrappedUnwrapped(&*three_c, 43));
2506       vector_wu2->push_back(PairWrappedUnwrapped(&*four_c, 44));
2507       vector_wu2->push_back(PairWrappedUnwrapped(&*five_c, 45));
2508       vector_uw->push_back(PairUnwrappedWrapped(1, &*one_d));
2509       vector_uw2->push_back(PairUnwrappedWrapped(103, &*three_d));
2510       vector_uw2->push_back(PairUnwrappedWrapped(104, &*four_d));
2511       vector_uw2->push_back(PairUnwrappedWrapped(105, &*five_d));
2512 
2513       EXPECT_TRUE(DequeContains(*deque, one_b));
2514 
2515       // Collect garbage. This should change nothing since we are keeping
2516       // alive the IntWrapper objects with on-stack pointers.
2517       ConservativelyCollectGarbage();
2518 
2519       EXPECT_TRUE(DequeContains(*deque, one_b));
2520 
2521       EXPECT_EQ(0u, member_member->size());
2522       EXPECT_EQ(4u, member_member2->size());
2523       EXPECT_EQ(4u, primitive_member->size());
2524       EXPECT_EQ(4u, member_primitive->size());
2525       EXPECT_EQ(1u, set->size());
2526       EXPECT_EQ(4u, set2->size());
2527       EXPECT_EQ(1u, set3->size());
2528       EXPECT_EQ(1u, vector->size());
2529       EXPECT_EQ(2u, vector2->size());
2530       EXPECT_EQ(1u, vector_wu->size());
2531       EXPECT_EQ(3u, vector_wu2->size());
2532       EXPECT_EQ(1u, vector_uw->size());
2533       EXPECT_EQ(3u, vector_uw2->size());
2534       EXPECT_EQ(1u, deque->size());
2535       EXPECT_EQ(2u, deque2->size());
2536 
2537       MemberVector& cvec = container->vector;
2538       cvec.swap(*vector.Get());
2539       vector2->swap(cvec);
2540       vector->swap(cvec);
2541 
2542       VectorWU& cvec_wu = container->vector_wu;
2543       cvec_wu.swap(*vector_wu.Get());
2544       vector_wu2->swap(cvec_wu);
2545       vector_wu->swap(cvec_wu);
2546 
2547       VectorUW& cvec_uw = container->vector_uw;
2548       cvec_uw.swap(*vector_uw.Get());
2549       vector_uw2->swap(cvec_uw);
2550       vector_uw->swap(cvec_uw);
2551 
2552       MemberDeque& c_deque = container->deque;
2553       c_deque.Swap(*deque.Get());
2554       deque2->Swap(c_deque);
2555       deque->Swap(c_deque);
2556 
2557       // Swap set and set2 in a roundabout way.
2558       MemberSet& cset1 = container->set;
2559       MemberSet& cset2 = container->set2;
2560       set->swap(cset1);
2561       set2->swap(cset2);
2562       set->swap(cset2);
2563       cset1.swap(cset2);
2564       cset2.swap(*set2);
2565 
2566       MemberCountedSet& c_counted_set = container->set3;
2567       set3->swap(c_counted_set);
2568       EXPECT_EQ(0u, set3->size());
2569       set3->swap(c_counted_set);
2570 
2571       // Triple swap.
2572       container->map.swap(*member_member2);
2573       MemberMember& contained_map = container->map;
2574       member_member3->swap(contained_map);
2575       member_member3->swap(*member_member);
2576 
2577       EXPECT_TRUE(member_member->at(one) == two);
2578       EXPECT_TRUE(member_member->at(two) == three);
2579       EXPECT_TRUE(member_member->at(three) == four);
2580       EXPECT_TRUE(member_member->at(four) == one);
2581       EXPECT_TRUE(primitive_member->at(1) == two);
2582       EXPECT_TRUE(primitive_member->at(2) == three);
2583       EXPECT_TRUE(primitive_member->at(3) == four);
2584       EXPECT_TRUE(primitive_member->at(4) == one);
2585       EXPECT_EQ(1, member_primitive->at(four));
2586       EXPECT_EQ(2, member_primitive->at(one));
2587       EXPECT_EQ(3, member_primitive->at(two));
2588       EXPECT_EQ(4, member_primitive->at(three));
2589       EXPECT_TRUE(set->Contains(one));
2590       EXPECT_TRUE(set->Contains(two));
2591       EXPECT_TRUE(set->Contains(three));
2592       EXPECT_TRUE(set->Contains(four));
2593       EXPECT_TRUE(set2->Contains(one_b));
2594       EXPECT_TRUE(set3->Contains(one_b));
2595       EXPECT_TRUE(vector->Contains(three_b));
2596       EXPECT_TRUE(vector->Contains(four_b));
2597       EXPECT_TRUE(DequeContains(*deque, three_e));
2598       EXPECT_TRUE(DequeContains(*deque, four_e));
2599       EXPECT_TRUE(vector2->Contains(one_b));
2600       EXPECT_FALSE(vector2->Contains(three_b));
2601       EXPECT_TRUE(DequeContains(*deque2, one_b));
2602       EXPECT_FALSE(DequeContains(*deque2, three_e));
2603       EXPECT_TRUE(vector_wu->Contains(PairWrappedUnwrapped(&*three_c, 43)));
2604       EXPECT_TRUE(vector_wu->Contains(PairWrappedUnwrapped(&*four_c, 44)));
2605       EXPECT_TRUE(vector_wu->Contains(PairWrappedUnwrapped(&*five_c, 45)));
2606       EXPECT_TRUE(vector_wu2->Contains(PairWrappedUnwrapped(&*one_c, 42)));
2607       EXPECT_FALSE(vector_wu2->Contains(PairWrappedUnwrapped(&*three_c, 43)));
2608       EXPECT_TRUE(vector_uw->Contains(PairUnwrappedWrapped(103, &*three_d)));
2609       EXPECT_TRUE(vector_uw->Contains(PairUnwrappedWrapped(104, &*four_d)));
2610       EXPECT_TRUE(vector_uw->Contains(PairUnwrappedWrapped(105, &*five_d)));
2611       EXPECT_TRUE(vector_uw2->Contains(PairUnwrappedWrapped(1, &*one_d)));
2612       EXPECT_FALSE(vector_uw2->Contains(PairUnwrappedWrapped(103, &*three_d)));
2613     }
2614 
2615     PreciselyCollectGarbage();
2616 
2617     EXPECT_EQ(4u, member_member->size());
2618     EXPECT_EQ(0u, member_member2->size());
2619     EXPECT_EQ(4u, primitive_member->size());
2620     EXPECT_EQ(4u, member_primitive->size());
2621     EXPECT_EQ(4u, set->size());
2622     EXPECT_EQ(1u, set2->size());
2623     EXPECT_EQ(1u, set3->size());
2624     EXPECT_EQ(2u, vector->size());
2625     EXPECT_EQ(1u, vector2->size());
2626     EXPECT_EQ(3u, vector_uw->size());
2627     EXPECT_EQ(1u, vector2->size());
2628     EXPECT_EQ(2u, deque->size());
2629     EXPECT_EQ(1u, deque2->size());
2630     EXPECT_EQ(1u, deque2->size());
2631 
2632     EXPECT_TRUE(member_member->at(one) == two);
2633     EXPECT_TRUE(primitive_member->at(1) == two);
2634     EXPECT_TRUE(primitive_member->at(4) == one);
2635     EXPECT_EQ(2, member_primitive->at(one));
2636     EXPECT_EQ(3, member_primitive->at(two));
2637     EXPECT_TRUE(set->Contains(one));
2638     EXPECT_TRUE(set->Contains(two));
2639     EXPECT_FALSE(set->Contains(one_b));
2640     EXPECT_TRUE(set2->Contains(one_b));
2641     EXPECT_TRUE(set3->Contains(one_b));
2642     EXPECT_EQ(2u, set3->find(one_b)->value);
2643     EXPECT_EQ(3, vector->at(0)->Value());
2644     EXPECT_EQ(4, vector->at(1)->Value());
2645     EXPECT_EQ(3, deque->begin()->Get()->Value());
2646   }
2647 
2648   PreciselyCollectGarbage();
2649   PreciselyCollectGarbage();
2650 
2651   EXPECT_EQ(4u, member_member->size());
2652   EXPECT_EQ(4u, primitive_member->size());
2653   EXPECT_EQ(4u, member_primitive->size());
2654   EXPECT_EQ(4u, set->size());
2655   EXPECT_EQ(1u, set2->size());
2656   EXPECT_EQ(2u, vector->size());
2657   EXPECT_EQ(1u, vector2->size());
2658   EXPECT_EQ(3u, vector_wu->size());
2659   EXPECT_EQ(1u, vector_wu2->size());
2660   EXPECT_EQ(3u, vector_uw->size());
2661   EXPECT_EQ(1u, vector_uw2->size());
2662   EXPECT_EQ(2u, deque->size());
2663   EXPECT_EQ(1u, deque2->size());
2664 }
2665 
TEST_F(HeapTest,PersistentVector)2666 TEST_F(HeapTest, PersistentVector) {
2667   IntWrapper::destructor_calls_ = 0;
2668 
2669   typedef Vector<Persistent<IntWrapper>> PersistentVector;
2670 
2671   Persistent<IntWrapper> one(MakeGarbageCollected<IntWrapper>(1));
2672   Persistent<IntWrapper> two(MakeGarbageCollected<IntWrapper>(2));
2673   Persistent<IntWrapper> three(MakeGarbageCollected<IntWrapper>(3));
2674   Persistent<IntWrapper> four(MakeGarbageCollected<IntWrapper>(4));
2675   Persistent<IntWrapper> five(MakeGarbageCollected<IntWrapper>(5));
2676   Persistent<IntWrapper> six(MakeGarbageCollected<IntWrapper>(6));
2677   {
2678     PersistentVector vector;
2679     vector.push_back(one);
2680     vector.push_back(two);
2681     ConservativelyCollectGarbage();
2682     EXPECT_TRUE(vector.Contains(one));
2683     EXPECT_TRUE(vector.Contains(two));
2684 
2685     vector.push_back(three);
2686     vector.push_back(four);
2687     ConservativelyCollectGarbage();
2688     EXPECT_TRUE(vector.Contains(one));
2689     EXPECT_TRUE(vector.Contains(two));
2690     EXPECT_TRUE(vector.Contains(three));
2691     EXPECT_TRUE(vector.Contains(four));
2692 
2693     vector.Shrink(1);
2694     ConservativelyCollectGarbage();
2695     EXPECT_TRUE(vector.Contains(one));
2696     EXPECT_FALSE(vector.Contains(two));
2697     EXPECT_FALSE(vector.Contains(three));
2698     EXPECT_FALSE(vector.Contains(four));
2699   }
2700   {
2701     PersistentVector vector1;
2702     PersistentVector vector2;
2703 
2704     vector1.push_back(one);
2705     vector2.push_back(two);
2706     vector1.swap(vector2);
2707     ConservativelyCollectGarbage();
2708     EXPECT_TRUE(vector1.Contains(two));
2709     EXPECT_TRUE(vector2.Contains(one));
2710   }
2711   {
2712     PersistentVector vector1;
2713     PersistentVector vector2;
2714 
2715     vector1.push_back(one);
2716     vector1.push_back(two);
2717     vector2.push_back(three);
2718     vector2.push_back(four);
2719     vector2.push_back(five);
2720     vector2.push_back(six);
2721     vector1.swap(vector2);
2722     ConservativelyCollectGarbage();
2723     EXPECT_TRUE(vector1.Contains(three));
2724     EXPECT_TRUE(vector1.Contains(four));
2725     EXPECT_TRUE(vector1.Contains(five));
2726     EXPECT_TRUE(vector1.Contains(six));
2727     EXPECT_TRUE(vector2.Contains(one));
2728     EXPECT_TRUE(vector2.Contains(two));
2729   }
2730 }
2731 
TEST_F(HeapTest,CrossThreadPersistentVector)2732 TEST_F(HeapTest, CrossThreadPersistentVector) {
2733   IntWrapper::destructor_calls_ = 0;
2734 
2735   typedef Vector<CrossThreadPersistent<IntWrapper>> CrossThreadPersistentVector;
2736 
2737   CrossThreadPersistent<IntWrapper> one(MakeGarbageCollected<IntWrapper>(1));
2738   CrossThreadPersistent<IntWrapper> two(MakeGarbageCollected<IntWrapper>(2));
2739   CrossThreadPersistent<IntWrapper> three(MakeGarbageCollected<IntWrapper>(3));
2740   CrossThreadPersistent<IntWrapper> four(MakeGarbageCollected<IntWrapper>(4));
2741   CrossThreadPersistent<IntWrapper> five(MakeGarbageCollected<IntWrapper>(5));
2742   CrossThreadPersistent<IntWrapper> six(MakeGarbageCollected<IntWrapper>(6));
2743   {
2744     CrossThreadPersistentVector vector;
2745     vector.push_back(one);
2746     vector.push_back(two);
2747     ConservativelyCollectGarbage();
2748     EXPECT_TRUE(vector.Contains(one));
2749     EXPECT_TRUE(vector.Contains(two));
2750 
2751     vector.push_back(three);
2752     vector.push_back(four);
2753     ConservativelyCollectGarbage();
2754     EXPECT_TRUE(vector.Contains(one));
2755     EXPECT_TRUE(vector.Contains(two));
2756     EXPECT_TRUE(vector.Contains(three));
2757     EXPECT_TRUE(vector.Contains(four));
2758 
2759     vector.Shrink(1);
2760     ConservativelyCollectGarbage();
2761     EXPECT_TRUE(vector.Contains(one));
2762     EXPECT_FALSE(vector.Contains(two));
2763     EXPECT_FALSE(vector.Contains(three));
2764     EXPECT_FALSE(vector.Contains(four));
2765   }
2766   {
2767     CrossThreadPersistentVector vector1;
2768     CrossThreadPersistentVector vector2;
2769 
2770     vector1.push_back(one);
2771     vector2.push_back(two);
2772     vector1.swap(vector2);
2773     ConservativelyCollectGarbage();
2774     EXPECT_TRUE(vector1.Contains(two));
2775     EXPECT_TRUE(vector2.Contains(one));
2776   }
2777   {
2778     CrossThreadPersistentVector vector1;
2779     CrossThreadPersistentVector vector2;
2780 
2781     vector1.push_back(one);
2782     vector1.push_back(two);
2783     vector2.push_back(three);
2784     vector2.push_back(four);
2785     vector2.push_back(five);
2786     vector2.push_back(six);
2787     vector1.swap(vector2);
2788     ConservativelyCollectGarbage();
2789     EXPECT_TRUE(vector1.Contains(three));
2790     EXPECT_TRUE(vector1.Contains(four));
2791     EXPECT_TRUE(vector1.Contains(five));
2792     EXPECT_TRUE(vector1.Contains(six));
2793     EXPECT_TRUE(vector2.Contains(one));
2794     EXPECT_TRUE(vector2.Contains(two));
2795   }
2796 }
2797 
TEST_F(HeapTest,PersistentSet)2798 TEST_F(HeapTest, PersistentSet) {
2799   IntWrapper::destructor_calls_ = 0;
2800 
2801   typedef HashSet<Persistent<IntWrapper>> PersistentSet;
2802 
2803   auto* one_raw = MakeGarbageCollected<IntWrapper>(1);
2804   Persistent<IntWrapper> one(one_raw);
2805   Persistent<IntWrapper> one2(one_raw);
2806   Persistent<IntWrapper> two(MakeGarbageCollected<IntWrapper>(2));
2807   Persistent<IntWrapper> three(MakeGarbageCollected<IntWrapper>(3));
2808   Persistent<IntWrapper> four(MakeGarbageCollected<IntWrapper>(4));
2809   Persistent<IntWrapper> five(MakeGarbageCollected<IntWrapper>(5));
2810   Persistent<IntWrapper> six(MakeGarbageCollected<IntWrapper>(6));
2811   {
2812     PersistentSet set;
2813     set.insert(one);
2814     set.insert(two);
2815     ConservativelyCollectGarbage();
2816     EXPECT_TRUE(set.Contains(one));
2817     EXPECT_TRUE(set.Contains(one2));
2818     EXPECT_TRUE(set.Contains(two));
2819 
2820     set.insert(three);
2821     set.insert(four);
2822     ConservativelyCollectGarbage();
2823     EXPECT_TRUE(set.Contains(one));
2824     EXPECT_TRUE(set.Contains(two));
2825     EXPECT_TRUE(set.Contains(three));
2826     EXPECT_TRUE(set.Contains(four));
2827 
2828     set.clear();
2829     ConservativelyCollectGarbage();
2830     EXPECT_FALSE(set.Contains(one));
2831     EXPECT_FALSE(set.Contains(two));
2832     EXPECT_FALSE(set.Contains(three));
2833     EXPECT_FALSE(set.Contains(four));
2834   }
2835   {
2836     PersistentSet set1;
2837     PersistentSet set2;
2838 
2839     set1.insert(one);
2840     set2.insert(two);
2841     set1.swap(set2);
2842     ConservativelyCollectGarbage();
2843     EXPECT_TRUE(set1.Contains(two));
2844     EXPECT_TRUE(set2.Contains(one));
2845     EXPECT_TRUE(set2.Contains(one2));
2846   }
2847 }
2848 
TEST_F(HeapTest,CrossThreadPersistentSet)2849 TEST_F(HeapTest, CrossThreadPersistentSet) {
2850   IntWrapper::destructor_calls_ = 0;
2851 
2852   typedef HashSet<CrossThreadPersistent<IntWrapper>> CrossThreadPersistentSet;
2853 
2854   auto* one_raw = MakeGarbageCollected<IntWrapper>(1);
2855   CrossThreadPersistent<IntWrapper> one(one_raw);
2856   CrossThreadPersistent<IntWrapper> one2(one_raw);
2857   CrossThreadPersistent<IntWrapper> two(MakeGarbageCollected<IntWrapper>(2));
2858   CrossThreadPersistent<IntWrapper> three(MakeGarbageCollected<IntWrapper>(3));
2859   CrossThreadPersistent<IntWrapper> four(MakeGarbageCollected<IntWrapper>(4));
2860   CrossThreadPersistent<IntWrapper> five(MakeGarbageCollected<IntWrapper>(5));
2861   CrossThreadPersistent<IntWrapper> six(MakeGarbageCollected<IntWrapper>(6));
2862   {
2863     CrossThreadPersistentSet set;
2864     set.insert(one);
2865     set.insert(two);
2866     ConservativelyCollectGarbage();
2867     EXPECT_TRUE(set.Contains(one));
2868     EXPECT_TRUE(set.Contains(one2));
2869     EXPECT_TRUE(set.Contains(two));
2870 
2871     set.insert(three);
2872     set.insert(four);
2873     ConservativelyCollectGarbage();
2874     EXPECT_TRUE(set.Contains(one));
2875     EXPECT_TRUE(set.Contains(two));
2876     EXPECT_TRUE(set.Contains(three));
2877     EXPECT_TRUE(set.Contains(four));
2878 
2879     set.clear();
2880     ConservativelyCollectGarbage();
2881     EXPECT_FALSE(set.Contains(one));
2882     EXPECT_FALSE(set.Contains(two));
2883     EXPECT_FALSE(set.Contains(three));
2884     EXPECT_FALSE(set.Contains(four));
2885   }
2886   {
2887     CrossThreadPersistentSet set1;
2888     CrossThreadPersistentSet set2;
2889 
2890     set1.insert(one);
2891     set2.insert(two);
2892     set1.swap(set2);
2893     ConservativelyCollectGarbage();
2894     EXPECT_TRUE(set1.Contains(two));
2895     EXPECT_TRUE(set2.Contains(one));
2896     EXPECT_TRUE(set2.Contains(one2));
2897   }
2898 }
2899 
2900 class NonTrivialObject final {
2901   DISALLOW_NEW();
2902 
2903  public:
2904   NonTrivialObject() = default;
NonTrivialObject(int num)2905   explicit NonTrivialObject(int num) {
2906     deque_.push_back(MakeGarbageCollected<IntWrapper>(num));
2907     vector_.push_back(MakeGarbageCollected<IntWrapper>(num));
2908   }
Trace(Visitor * visitor)2909   void Trace(Visitor* visitor) {
2910     visitor->Trace(deque_);
2911     visitor->Trace(vector_);
2912   }
2913 
2914  private:
2915   HeapDeque<Member<IntWrapper>> deque_;
2916   HeapVector<Member<IntWrapper>> vector_;
2917 };
2918 
TEST_F(HeapTest,HeapHashMapWithInlinedObject)2919 TEST_F(HeapTest, HeapHashMapWithInlinedObject) {
2920   HeapHashMap<int, NonTrivialObject> map;
2921   for (int num = 1; num < 1000; num++) {
2922     NonTrivialObject object(num);
2923     map.insert(num, object);
2924   }
2925 }
2926 
2927 template <typename T>
MapIteratorCheck(T & it,const T & end,int expected)2928 void MapIteratorCheck(T& it, const T& end, int expected) {
2929   int found = 0;
2930   while (it != end) {
2931     found++;
2932     int key = it->key->Value();
2933     int value = it->value->Value();
2934     EXPECT_TRUE(key >= 0 && key < 1100);
2935     EXPECT_TRUE(value >= 0 && value < 1100);
2936     ++it;
2937   }
2938   EXPECT_EQ(expected, found);
2939 }
2940 
2941 template <typename T>
SetIteratorCheck(T & it,const T & end,int expected)2942 void SetIteratorCheck(T& it, const T& end, int expected) {
2943   int found = 0;
2944   while (it != end) {
2945     found++;
2946     int value = (*it)->Value();
2947     EXPECT_TRUE(value >= 0 && value < 1100);
2948     ++it;
2949   }
2950   EXPECT_EQ(expected, found);
2951 }
2952 
TEST_F(HeapTest,HeapWeakCollectionSimple)2953 TEST_F(HeapTest, HeapWeakCollectionSimple) {
2954   ClearOutOldGarbage();
2955   IntWrapper::destructor_calls_ = 0;
2956 
2957   Persistent<HeapVector<Member<IntWrapper>>> keep_numbers_alive =
2958       MakeGarbageCollected<HeapVector<Member<IntWrapper>>>();
2959 
2960   typedef HeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper>> WeakStrong;
2961   typedef HeapHashMap<Member<IntWrapper>, WeakMember<IntWrapper>> StrongWeak;
2962   typedef HeapHashMap<WeakMember<IntWrapper>, WeakMember<IntWrapper>> WeakWeak;
2963   typedef HeapHashSet<WeakMember<IntWrapper>> WeakSet;
2964   typedef HeapHashCountedSet<WeakMember<IntWrapper>> WeakCountedSet;
2965 
2966   Persistent<WeakStrong> weak_strong = MakeGarbageCollected<WeakStrong>();
2967   Persistent<StrongWeak> strong_weak = MakeGarbageCollected<StrongWeak>();
2968   Persistent<WeakWeak> weak_weak = MakeGarbageCollected<WeakWeak>();
2969   Persistent<WeakSet> weak_set = MakeGarbageCollected<WeakSet>();
2970   Persistent<WeakCountedSet> weak_counted_set =
2971       MakeGarbageCollected<WeakCountedSet>();
2972 
2973   Persistent<IntWrapper> two = MakeGarbageCollected<IntWrapper>(2);
2974 
2975   keep_numbers_alive->push_back(MakeGarbageCollected<IntWrapper>(103));
2976   keep_numbers_alive->push_back(MakeGarbageCollected<IntWrapper>(10));
2977 
2978   {
2979     weak_strong->insert(MakeGarbageCollected<IntWrapper>(1), two);
2980     strong_weak->insert(two, MakeGarbageCollected<IntWrapper>(1));
2981     weak_weak->insert(two, MakeGarbageCollected<IntWrapper>(42));
2982     weak_weak->insert(MakeGarbageCollected<IntWrapper>(42), two);
2983     weak_set->insert(MakeGarbageCollected<IntWrapper>(0));
2984     weak_set->insert(two);
2985     weak_set->insert(keep_numbers_alive->at(0));
2986     weak_set->insert(keep_numbers_alive->at(1));
2987     weak_counted_set->insert(MakeGarbageCollected<IntWrapper>(0));
2988     weak_counted_set->insert(two);
2989     weak_counted_set->insert(two);
2990     weak_counted_set->insert(two);
2991     weak_counted_set->insert(keep_numbers_alive->at(0));
2992     weak_counted_set->insert(keep_numbers_alive->at(1));
2993     EXPECT_EQ(1u, weak_strong->size());
2994     EXPECT_EQ(1u, strong_weak->size());
2995     EXPECT_EQ(2u, weak_weak->size());
2996     EXPECT_EQ(4u, weak_set->size());
2997     EXPECT_EQ(4u, weak_counted_set->size());
2998     EXPECT_EQ(3u, weak_counted_set->find(two)->value);
2999     weak_counted_set->erase(two);
3000     EXPECT_EQ(2u, weak_counted_set->find(two)->value);
3001   }
3002 
3003   keep_numbers_alive->at(0) = nullptr;
3004 
3005   PreciselyCollectGarbage();
3006 
3007   EXPECT_EQ(0u, weak_strong->size());
3008   EXPECT_EQ(0u, strong_weak->size());
3009   EXPECT_EQ(0u, weak_weak->size());
3010   EXPECT_EQ(2u, weak_set->size());
3011   EXPECT_EQ(2u, weak_counted_set->size());
3012 }
3013 
3014 template <typename Set>
OrderedSetHelper(bool strong)3015 void OrderedSetHelper(bool strong) {
3016   IntWrapper::destructor_calls_ = 0;
3017 
3018   Persistent<HeapVector<Member<IntWrapper>>> keep_numbers_alive =
3019       MakeGarbageCollected<HeapVector<Member<IntWrapper>>>();
3020 
3021   Persistent<Set> set1 = MakeGarbageCollected<Set>();
3022   Persistent<Set> set2 = MakeGarbageCollected<Set>();
3023 
3024   const Set& const_set = *set1.Get();
3025 
3026   keep_numbers_alive->push_back(MakeGarbageCollected<IntWrapper>(2));
3027   keep_numbers_alive->push_back(MakeGarbageCollected<IntWrapper>(103));
3028   keep_numbers_alive->push_back(MakeGarbageCollected<IntWrapper>(10));
3029 
3030   set1->insert(MakeGarbageCollected<IntWrapper>(0));
3031   set1->insert(keep_numbers_alive->at(0));
3032   set1->insert(keep_numbers_alive->at(1));
3033   set1->insert(keep_numbers_alive->at(2));
3034 
3035   set2->clear();
3036   set2->insert(MakeGarbageCollected<IntWrapper>(42));
3037   set2->clear();
3038 
3039   EXPECT_EQ(4u, set1->size());
3040   typename Set::iterator it(set1->begin());
3041   typename Set::reverse_iterator reverse(set1->rbegin());
3042   typename Set::const_iterator cit(const_set.begin());
3043   typename Set::const_reverse_iterator creverse(const_set.rbegin());
3044 
3045   EXPECT_EQ(0, (*it)->Value());
3046   EXPECT_EQ(0, (*cit)->Value());
3047   ++it;
3048   ++cit;
3049   EXPECT_EQ(2, (*it)->Value());
3050   EXPECT_EQ(2, (*cit)->Value());
3051   --it;
3052   --cit;
3053   EXPECT_EQ(0, (*it)->Value());
3054   EXPECT_EQ(0, (*cit)->Value());
3055   ++it;
3056   ++cit;
3057   ++it;
3058   ++cit;
3059   EXPECT_EQ(103, (*it)->Value());
3060   EXPECT_EQ(103, (*cit)->Value());
3061   ++it;
3062   ++cit;
3063   EXPECT_EQ(10, (*it)->Value());
3064   EXPECT_EQ(10, (*cit)->Value());
3065   ++it;
3066   ++cit;
3067 
3068   EXPECT_EQ(10, (*reverse)->Value());
3069   EXPECT_EQ(10, (*creverse)->Value());
3070   ++reverse;
3071   ++creverse;
3072   EXPECT_EQ(103, (*reverse)->Value());
3073   EXPECT_EQ(103, (*creverse)->Value());
3074   --reverse;
3075   --creverse;
3076   EXPECT_EQ(10, (*reverse)->Value());
3077   EXPECT_EQ(10, (*creverse)->Value());
3078   ++reverse;
3079   ++creverse;
3080   ++reverse;
3081   ++creverse;
3082   EXPECT_EQ(2, (*reverse)->Value());
3083   EXPECT_EQ(2, (*creverse)->Value());
3084   ++reverse;
3085   ++creverse;
3086   EXPECT_EQ(0, (*reverse)->Value());
3087   EXPECT_EQ(0, (*creverse)->Value());
3088   ++reverse;
3089   ++creverse;
3090 
3091   EXPECT_EQ(set1->end(), it);
3092   EXPECT_EQ(const_set.end(), cit);
3093   EXPECT_EQ(set1->rend(), reverse);
3094   EXPECT_EQ(const_set.rend(), creverse);
3095 
3096   typename Set::iterator i_x(set2->begin());
3097   EXPECT_EQ(set2->end(), i_x);
3098 
3099   if (strong)
3100     set1->erase(keep_numbers_alive->at(0));
3101 
3102   keep_numbers_alive->at(0) = nullptr;
3103 
3104   TestSupportingGC::PreciselyCollectGarbage();
3105 
3106   EXPECT_EQ(2u + (strong ? 1u : 0u), set1->size());
3107 
3108   EXPECT_EQ(2 + (strong ? 0 : 1), IntWrapper::destructor_calls_);
3109 
3110   typename Set::iterator i2(set1->begin());
3111   if (strong) {
3112     EXPECT_EQ(0, (*i2)->Value());
3113     ++i2;
3114     EXPECT_NE(set1->end(), i2);
3115   }
3116   EXPECT_EQ(103, (*i2)->Value());
3117   ++i2;
3118   EXPECT_NE(set1->end(), i2);
3119   EXPECT_EQ(10, (*i2)->Value());
3120   ++i2;
3121   EXPECT_EQ(set1->end(), i2);
3122 }
3123 
TEST_F(HeapTest,HeapWeakLinkedHashSet)3124 TEST_F(HeapTest, HeapWeakLinkedHashSet) {
3125   ClearOutOldGarbage();
3126   OrderedSetHelper<HeapLinkedHashSet<Member<IntWrapper>>>(true);
3127   ClearOutOldGarbage();
3128   OrderedSetHelper<HeapLinkedHashSet<WeakMember<IntWrapper>>>(false);
3129   ClearOutOldGarbage();
3130   OrderedSetHelper<HeapListHashSet<Member<IntWrapper>>>(true);
3131   ClearOutOldGarbage();
3132   // TODO(keinakashima): add a test case for WeakMember once it's supported
3133   OrderedSetHelper<HeapNewLinkedHashSet<Member<IntWrapper>>>(true);
3134 }
3135 
3136 class ThingWithDestructor {
3137   DISALLOW_NEW();
3138 
3139  public:
ThingWithDestructor()3140   ThingWithDestructor() : x_(kEmptyValue) { live_things_with_destructor_++; }
3141 
ThingWithDestructor(int x)3142   ThingWithDestructor(int x) : x_(x) { live_things_with_destructor_++; }
3143 
ThingWithDestructor(const ThingWithDestructor & other)3144   ThingWithDestructor(const ThingWithDestructor& other) {
3145     *this = other;
3146     live_things_with_destructor_++;
3147   }
3148 
~ThingWithDestructor()3149   ~ThingWithDestructor() { live_things_with_destructor_--; }
3150 
Value()3151   int Value() { return x_; }
3152 
3153   static int live_things_with_destructor_;
3154 
GetHash()3155   unsigned GetHash() { return IntHash<int>::GetHash(x_); }
3156 
3157  private:
3158   static const int kEmptyValue = 0;
3159   int x_;
3160 };
3161 
3162 int ThingWithDestructor::live_things_with_destructor_;
3163 
HeapMapDestructorHelper(bool clear_maps)3164 static void HeapMapDestructorHelper(bool clear_maps) {
3165   ThingWithDestructor::live_things_with_destructor_ = 0;
3166 
3167   typedef HeapHashMap<WeakMember<IntWrapper>,
3168                       Member<RefCountedAndGarbageCollected>>
3169       RefMap;
3170 
3171   typedef HeapHashMap<WeakMember<IntWrapper>, ThingWithDestructor,
3172                       DefaultHash<WeakMember<IntWrapper>>::Hash,
3173                       HashTraits<WeakMember<IntWrapper>>>
3174       Map;
3175 
3176   Persistent<Map> map(MakeGarbageCollected<Map>());
3177   Persistent<RefMap> ref_map(MakeGarbageCollected<RefMap>());
3178 
3179   Persistent<IntWrapper> luck(MakeGarbageCollected<IntWrapper>(103));
3180 
3181   int base_line, ref_base_line;
3182 
3183   {
3184     Map stack_map;
3185     RefMap stack_ref_map;
3186 
3187     TestSupportingGC::PreciselyCollectGarbage();
3188     TestSupportingGC::PreciselyCollectGarbage();
3189 
3190     stack_map.insert(MakeGarbageCollected<IntWrapper>(42),
3191                      ThingWithDestructor(1729));
3192     stack_map.insert(luck, ThingWithDestructor(8128));
3193     stack_ref_map.insert(MakeGarbageCollected<IntWrapper>(42),
3194                          MakeGarbageCollected<RefCountedAndGarbageCollected>());
3195     stack_ref_map.insert(luck,
3196                          MakeGarbageCollected<RefCountedAndGarbageCollected>());
3197 
3198     base_line = ThingWithDestructor::live_things_with_destructor_;
3199     ref_base_line = RefCountedAndGarbageCollected::destructor_calls_;
3200 
3201     // Although the heap maps are on-stack, we can't expect prompt
3202     // finalization of the elements, so when they go out of scope here we
3203     // will not necessarily have called the relevant destructors.
3204   }
3205 
3206   // The RefCountedAndGarbageCollected things need an extra GC to discover
3207   // that they are no longer ref counted.
3208   TestSupportingGC::PreciselyCollectGarbage();
3209   TestSupportingGC::PreciselyCollectGarbage();
3210   EXPECT_EQ(base_line - 2, ThingWithDestructor::live_things_with_destructor_);
3211   EXPECT_EQ(ref_base_line + 2,
3212             RefCountedAndGarbageCollected::destructor_calls_);
3213 
3214   // Now use maps kept alive with persistents. Here we don't expect any
3215   // destructors to be called before there have been GCs.
3216 
3217   map->insert(MakeGarbageCollected<IntWrapper>(42), ThingWithDestructor(1729));
3218   map->insert(luck, ThingWithDestructor(8128));
3219   ref_map->insert(MakeGarbageCollected<IntWrapper>(42),
3220                   MakeGarbageCollected<RefCountedAndGarbageCollected>());
3221   ref_map->insert(luck, MakeGarbageCollected<RefCountedAndGarbageCollected>());
3222 
3223   base_line = ThingWithDestructor::live_things_with_destructor_;
3224   ref_base_line = RefCountedAndGarbageCollected::destructor_calls_;
3225 
3226   luck.Clear();
3227   if (clear_maps) {
3228     map->clear();      // Clear map.
3229     ref_map->clear();  // Clear map.
3230   } else {
3231     map.Clear();      // Clear Persistent handle, not map.
3232     ref_map.Clear();  // Clear Persistent handle, not map.
3233     TestSupportingGC::PreciselyCollectGarbage();
3234     TestSupportingGC::PreciselyCollectGarbage();
3235   }
3236 
3237   EXPECT_EQ(base_line - 2, ThingWithDestructor::live_things_with_destructor_);
3238 
3239   // Need a GC to make sure that the RefCountedAndGarbageCollected thing
3240   // noticies it's been decremented to zero.
3241   TestSupportingGC::PreciselyCollectGarbage();
3242   EXPECT_EQ(ref_base_line + 2,
3243             RefCountedAndGarbageCollected::destructor_calls_);
3244 }
3245 
TEST_F(HeapTest,HeapMapDestructor)3246 TEST_F(HeapTest, HeapMapDestructor) {
3247   ClearOutOldGarbage();
3248   HeapMapDestructorHelper(true);
3249   ClearOutOldGarbage();
3250   HeapMapDestructorHelper(false);
3251 }
3252 
3253 typedef HeapHashSet<PairWeakStrong> WeakStrongSet;
3254 typedef HeapHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
3255 typedef HeapHashSet<PairStrongWeak> StrongWeakSet;
3256 typedef HeapHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
3257 typedef HeapLinkedHashSet<PairWeakStrong> WeakStrongLinkedSet;
3258 typedef HeapLinkedHashSet<PairWeakUnwrapped> WeakUnwrappedLinkedSet;
3259 typedef HeapLinkedHashSet<PairStrongWeak> StrongWeakLinkedSet;
3260 typedef HeapLinkedHashSet<PairUnwrappedWeak> UnwrappedWeakLinkedSet;
3261 // TODO(bartekn): add HeapNewLinkedHashSet cases once WeakMember is supported
3262 typedef HeapHashCountedSet<PairWeakStrong> WeakStrongCountedSet;
3263 typedef HeapHashCountedSet<PairWeakUnwrapped> WeakUnwrappedCountedSet;
3264 typedef HeapHashCountedSet<PairStrongWeak> StrongWeakCountedSet;
3265 typedef HeapHashCountedSet<PairUnwrappedWeak> UnwrappedWeakCountedSet;
3266 
3267 template <typename T>
IteratorExtractor(WTF::KeyValuePair<T,unsigned> & pair)3268 T& IteratorExtractor(WTF::KeyValuePair<T, unsigned>& pair) {
3269   return pair.key;
3270 }
3271 
3272 template <typename T>
IteratorExtractor(T & not_a_pair)3273 T& IteratorExtractor(T& not_a_pair) {
3274   return not_a_pair;
3275 }
3276 
3277 template <typename WSSet, typename SWSet, typename WUSet, typename UWSet>
CheckPairSets(Persistent<WSSet> & weak_strong,Persistent<SWSet> & strong_weak,Persistent<WUSet> & weak_unwrapped,Persistent<UWSet> & unwrapped_weak,bool ones,Persistent<IntWrapper> & two)3278 void CheckPairSets(Persistent<WSSet>& weak_strong,
3279                    Persistent<SWSet>& strong_weak,
3280                    Persistent<WUSet>& weak_unwrapped,
3281                    Persistent<UWSet>& unwrapped_weak,
3282                    bool ones,
3283                    Persistent<IntWrapper>& two) {
3284   typename WSSet::iterator it_ws = weak_strong->begin();
3285   typename SWSet::iterator it_sw = strong_weak->begin();
3286   typename WUSet::iterator it_wu = weak_unwrapped->begin();
3287   typename UWSet::iterator it_uw = unwrapped_weak->begin();
3288 
3289   EXPECT_EQ(2u, weak_strong->size());
3290   EXPECT_EQ(2u, strong_weak->size());
3291   EXPECT_EQ(2u, weak_unwrapped->size());
3292   EXPECT_EQ(2u, unwrapped_weak->size());
3293 
3294   PairWeakStrong p = IteratorExtractor(*it_ws);
3295   PairStrongWeak p2 = IteratorExtractor(*it_sw);
3296   PairWeakUnwrapped p3 = IteratorExtractor(*it_wu);
3297   PairUnwrappedWeak p4 = IteratorExtractor(*it_uw);
3298   if (p.first == two && p.second == two)
3299     ++it_ws;
3300   if (p2.first == two && p2.second == two)
3301     ++it_sw;
3302   if (p3.first == two && p3.second == 2)
3303     ++it_wu;
3304   if (p4.first == 2 && p4.second == two)
3305     ++it_uw;
3306   p = IteratorExtractor(*it_ws);
3307   p2 = IteratorExtractor(*it_sw);
3308   p3 = IteratorExtractor(*it_wu);
3309   p4 = IteratorExtractor(*it_uw);
3310   IntWrapper* null_wrapper = nullptr;
3311   if (ones) {
3312     EXPECT_EQ(p.first->Value(), 1);
3313     EXPECT_EQ(p2.second->Value(), 1);
3314     EXPECT_EQ(p3.first->Value(), 1);
3315     EXPECT_EQ(p4.second->Value(), 1);
3316   } else {
3317     EXPECT_EQ(p.first, null_wrapper);
3318     EXPECT_EQ(p2.second, null_wrapper);
3319     EXPECT_EQ(p3.first, null_wrapper);
3320     EXPECT_EQ(p4.second, null_wrapper);
3321   }
3322 
3323   EXPECT_EQ(p.second->Value(), 2);
3324   EXPECT_EQ(p2.first->Value(), 2);
3325   EXPECT_EQ(p3.second, 2);
3326   EXPECT_EQ(p4.first, 2);
3327 
3328   EXPECT_TRUE(weak_strong->Contains(PairWeakStrong(&*two, &*two)));
3329   EXPECT_TRUE(strong_weak->Contains(PairStrongWeak(&*two, &*two)));
3330   EXPECT_TRUE(weak_unwrapped->Contains(PairWeakUnwrapped(&*two, 2)));
3331   EXPECT_TRUE(unwrapped_weak->Contains(PairUnwrappedWeak(2, &*two)));
3332 }
3333 
TEST_F(HeapTest,HeapWeakCollectionTypes)3334 TEST_F(HeapTest, HeapWeakCollectionTypes) {
3335   IntWrapper::destructor_calls_ = 0;
3336 
3337   typedef HeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper>> WeakStrong;
3338   typedef HeapHashMap<Member<IntWrapper>, WeakMember<IntWrapper>> StrongWeak;
3339   typedef HeapHashMap<WeakMember<IntWrapper>, WeakMember<IntWrapper>> WeakWeak;
3340   typedef HeapHashSet<WeakMember<IntWrapper>> WeakSet;
3341   typedef HeapLinkedHashSet<WeakMember<IntWrapper>> WeakOrderedSet;
3342   // TODO(bartekn): add HeapNewLinkedHashSet case once WeakMember is supported
3343 
3344   ClearOutOldGarbage();
3345 
3346   const int kWeakStrongIndex = 0;
3347   const int kStrongWeakIndex = 1;
3348   const int kWeakWeakIndex = 2;
3349   const int kNumberOfMapIndices = 3;
3350   const int kWeakSetIndex = 3;
3351   const int kWeakOrderedSetIndex = 4;
3352   const int kNumberOfCollections = 5;
3353 
3354   for (int test_run = 0; test_run < 4; test_run++) {
3355     for (int collection_number = 0; collection_number < kNumberOfCollections;
3356          collection_number++) {
3357       bool delete_afterwards = (test_run == 1);
3358       bool add_afterwards = (test_run == 2);
3359       bool test_that_iterators_make_strong = (test_run == 3);
3360 
3361       // The test doesn't work for strongWeak with deleting because we lost
3362       // the key from the keepNumbersAlive array, so we can't do the lookup.
3363       if (delete_afterwards && collection_number == kStrongWeakIndex)
3364         continue;
3365 
3366       unsigned added = add_afterwards ? 100 : 0;
3367 
3368       Persistent<WeakStrong> weak_strong = MakeGarbageCollected<WeakStrong>();
3369       Persistent<StrongWeak> strong_weak = MakeGarbageCollected<StrongWeak>();
3370       Persistent<WeakWeak> weak_weak = MakeGarbageCollected<WeakWeak>();
3371 
3372       Persistent<WeakSet> weak_set = MakeGarbageCollected<WeakSet>();
3373       Persistent<WeakOrderedSet> weak_ordered_set =
3374           MakeGarbageCollected<WeakOrderedSet>();
3375 
3376       Persistent<HeapVector<Member<IntWrapper>>> keep_numbers_alive =
3377           MakeGarbageCollected<HeapVector<Member<IntWrapper>>>();
3378       for (int i = 0; i < 128; i += 2) {
3379         auto* wrapped = MakeGarbageCollected<IntWrapper>(i);
3380         auto* wrapped2 = MakeGarbageCollected<IntWrapper>(i + 1);
3381         keep_numbers_alive->push_back(wrapped);
3382         keep_numbers_alive->push_back(wrapped2);
3383         weak_strong->insert(wrapped, wrapped2);
3384         strong_weak->insert(wrapped2, wrapped);
3385         weak_weak->insert(wrapped, wrapped2);
3386         weak_set->insert(wrapped);
3387         weak_ordered_set->insert(wrapped);
3388       }
3389 
3390       EXPECT_EQ(64u, weak_strong->size());
3391       EXPECT_EQ(64u, strong_weak->size());
3392       EXPECT_EQ(64u, weak_weak->size());
3393       EXPECT_EQ(64u, weak_set->size());
3394       EXPECT_EQ(64u, weak_ordered_set->size());
3395 
3396       // Collect garbage. This should change nothing since we are keeping
3397       // alive the IntWrapper objects.
3398       PreciselyCollectGarbage();
3399 
3400       EXPECT_EQ(64u, weak_strong->size());
3401       EXPECT_EQ(64u, strong_weak->size());
3402       EXPECT_EQ(64u, weak_weak->size());
3403       EXPECT_EQ(64u, weak_set->size());
3404       EXPECT_EQ(64u, weak_ordered_set->size());
3405 
3406       for (int i = 0; i < 128; i += 2) {
3407         IntWrapper* wrapped = keep_numbers_alive->at(i);
3408         IntWrapper* wrapped2 = keep_numbers_alive->at(i + 1);
3409         EXPECT_EQ(wrapped2, weak_strong->at(wrapped));
3410         EXPECT_EQ(wrapped, strong_weak->at(wrapped2));
3411         EXPECT_EQ(wrapped2, weak_weak->at(wrapped));
3412         EXPECT_TRUE(weak_set->Contains(wrapped));
3413         EXPECT_TRUE(weak_ordered_set->Contains(wrapped));
3414       }
3415 
3416       for (int i = 0; i < 128; i += 3)
3417         keep_numbers_alive->at(i) = nullptr;
3418 
3419       if (collection_number != kWeakStrongIndex)
3420         weak_strong->clear();
3421       if (collection_number != kStrongWeakIndex)
3422         strong_weak->clear();
3423       if (collection_number != kWeakWeakIndex)
3424         weak_weak->clear();
3425       if (collection_number != kWeakSetIndex)
3426         weak_set->clear();
3427       if (collection_number != kWeakOrderedSetIndex)
3428         weak_ordered_set->clear();
3429 
3430       if (test_that_iterators_make_strong) {
3431         WeakStrong::iterator it1 = weak_strong->begin();
3432         StrongWeak::iterator it2 = strong_weak->begin();
3433         WeakWeak::iterator it3 = weak_weak->begin();
3434         WeakSet::iterator it4 = weak_set->begin();
3435         WeakOrderedSet::iterator it5 = weak_ordered_set->begin();
3436         // Collect garbage. This should change nothing since the
3437         // iterators make the collections strong.
3438         ConservativelyCollectGarbage();
3439         if (collection_number == kWeakStrongIndex) {
3440           EXPECT_EQ(64u, weak_strong->size());
3441           MapIteratorCheck(it1, weak_strong->end(), 64);
3442         } else if (collection_number == kStrongWeakIndex) {
3443           EXPECT_EQ(64u, strong_weak->size());
3444           MapIteratorCheck(it2, strong_weak->end(), 64);
3445         } else if (collection_number == kWeakWeakIndex) {
3446           EXPECT_EQ(64u, weak_weak->size());
3447           MapIteratorCheck(it3, weak_weak->end(), 64);
3448         } else if (collection_number == kWeakSetIndex) {
3449           EXPECT_EQ(64u, weak_set->size());
3450           SetIteratorCheck(it4, weak_set->end(), 64);
3451         } else if (collection_number == kWeakOrderedSetIndex) {
3452           EXPECT_EQ(64u, weak_ordered_set->size());
3453           SetIteratorCheck(it5, weak_ordered_set->end(), 64);
3454         }
3455       } else {
3456         // Collect garbage. This causes weak processing to remove
3457         // things from the collections.
3458         PreciselyCollectGarbage();
3459         unsigned count = 0;
3460         for (int i = 0; i < 128; i += 2) {
3461           bool first_alive = keep_numbers_alive->at(i);
3462           bool second_alive = keep_numbers_alive->at(i + 1);
3463           if (first_alive && (collection_number == kWeakStrongIndex ||
3464                               collection_number == kStrongWeakIndex))
3465             second_alive = true;
3466           if (first_alive && second_alive &&
3467               collection_number < kNumberOfMapIndices) {
3468             if (collection_number == kWeakStrongIndex) {
3469               if (delete_afterwards) {
3470                 EXPECT_EQ(
3471                     i + 1,
3472                     weak_strong->Take(keep_numbers_alive->at(i))->Value());
3473               }
3474             } else if (collection_number == kStrongWeakIndex) {
3475               if (delete_afterwards) {
3476                 EXPECT_EQ(
3477                     i,
3478                     strong_weak->Take(keep_numbers_alive->at(i + 1))->Value());
3479               }
3480             } else if (collection_number == kWeakWeakIndex) {
3481               if (delete_afterwards) {
3482                 EXPECT_EQ(i + 1,
3483                           weak_weak->Take(keep_numbers_alive->at(i))->Value());
3484               }
3485             }
3486             if (!delete_afterwards)
3487               count++;
3488           } else if (collection_number == kWeakSetIndex && first_alive) {
3489             ASSERT_TRUE(weak_set->Contains(keep_numbers_alive->at(i)));
3490             if (delete_afterwards)
3491               weak_set->erase(keep_numbers_alive->at(i));
3492             else
3493               count++;
3494           } else if (collection_number == kWeakOrderedSetIndex && first_alive) {
3495             ASSERT_TRUE(weak_ordered_set->Contains(keep_numbers_alive->at(i)));
3496             if (delete_afterwards)
3497               weak_ordered_set->erase(keep_numbers_alive->at(i));
3498             else
3499               count++;
3500           }
3501         }
3502         if (add_afterwards) {
3503           for (int i = 1000; i < 1100; i++) {
3504             auto* wrapped = MakeGarbageCollected<IntWrapper>(i);
3505             keep_numbers_alive->push_back(wrapped);
3506             weak_strong->insert(wrapped, wrapped);
3507             strong_weak->insert(wrapped, wrapped);
3508             weak_weak->insert(wrapped, wrapped);
3509             weak_set->insert(wrapped);
3510             weak_ordered_set->insert(wrapped);
3511           }
3512         }
3513         if (collection_number == kWeakStrongIndex)
3514           EXPECT_EQ(count + added, weak_strong->size());
3515         else if (collection_number == kStrongWeakIndex)
3516           EXPECT_EQ(count + added, strong_weak->size());
3517         else if (collection_number == kWeakWeakIndex)
3518           EXPECT_EQ(count + added, weak_weak->size());
3519         else if (collection_number == kWeakSetIndex)
3520           EXPECT_EQ(count + added, weak_set->size());
3521         else if (collection_number == kWeakOrderedSetIndex)
3522           EXPECT_EQ(count + added, weak_ordered_set->size());
3523         WeakStrong::iterator it1 = weak_strong->begin();
3524         StrongWeak::iterator it2 = strong_weak->begin();
3525         WeakWeak::iterator it3 = weak_weak->begin();
3526         WeakSet::iterator it4 = weak_set->begin();
3527         WeakOrderedSet::iterator it5 = weak_ordered_set->begin();
3528         MapIteratorCheck(
3529             it1, weak_strong->end(),
3530             (collection_number == kWeakStrongIndex ? count : 0) + added);
3531         MapIteratorCheck(
3532             it2, strong_weak->end(),
3533             (collection_number == kStrongWeakIndex ? count : 0) + added);
3534         MapIteratorCheck(
3535             it3, weak_weak->end(),
3536             (collection_number == kWeakWeakIndex ? count : 0) + added);
3537         SetIteratorCheck(
3538             it4, weak_set->end(),
3539             (collection_number == kWeakSetIndex ? count : 0) + added);
3540         SetIteratorCheck(
3541             it5, weak_ordered_set->end(),
3542             (collection_number == kWeakOrderedSetIndex ? count : 0) + added);
3543       }
3544       for (unsigned i = 0; i < 128 + added; i++)
3545         keep_numbers_alive->at(i) = nullptr;
3546       PreciselyCollectGarbage();
3547       EXPECT_EQ(0u, weak_strong->size());
3548       EXPECT_EQ(0u, strong_weak->size());
3549       EXPECT_EQ(0u, weak_weak->size());
3550       EXPECT_EQ(0u, weak_set->size());
3551       EXPECT_EQ(0u, weak_ordered_set->size());
3552     }
3553   }
3554 }
3555 
TEST_F(HeapTest,HeapHashCountedSetToVector)3556 TEST_F(HeapTest, HeapHashCountedSetToVector) {
3557   HeapHashCountedSet<Member<IntWrapper>> set;
3558   HeapVector<Member<IntWrapper>> vector;
3559   set.insert(MakeGarbageCollected<IntWrapper>(1));
3560   set.insert(MakeGarbageCollected<IntWrapper>(1));
3561   set.insert(MakeGarbageCollected<IntWrapper>(2));
3562 
3563   CopyToVector(set, vector);
3564   EXPECT_EQ(3u, vector.size());
3565 
3566   Vector<int> int_vector;
3567   for (const auto& i : vector)
3568     int_vector.push_back(i->Value());
3569   std::sort(int_vector.begin(), int_vector.end());
3570   ASSERT_EQ(3u, int_vector.size());
3571   EXPECT_EQ(1, int_vector[0]);
3572   EXPECT_EQ(1, int_vector[1]);
3573   EXPECT_EQ(2, int_vector[2]);
3574 }
3575 
TEST_F(HeapTest,WeakHeapHashCountedSetToVector)3576 TEST_F(HeapTest, WeakHeapHashCountedSetToVector) {
3577   HeapHashCountedSet<WeakMember<IntWrapper>> set;
3578   HeapVector<Member<IntWrapper>> vector;
3579   set.insert(MakeGarbageCollected<IntWrapper>(1));
3580   set.insert(MakeGarbageCollected<IntWrapper>(1));
3581   set.insert(MakeGarbageCollected<IntWrapper>(2));
3582 
3583   CopyToVector(set, vector);
3584   EXPECT_LE(3u, vector.size());
3585   for (const auto& i : vector)
3586     EXPECT_TRUE(i->Value() == 1 || i->Value() == 2);
3587 }
3588 
TEST_F(HeapTest,RefCountedGarbageCollected)3589 TEST_F(HeapTest, RefCountedGarbageCollected) {
3590   RefCountedAndGarbageCollected::destructor_calls_ = 0;
3591   {
3592     scoped_refptr<RefCountedAndGarbageCollected> ref_ptr3;
3593     {
3594       Persistent<RefCountedAndGarbageCollected> persistent;
3595       {
3596         Persistent<RefCountedAndGarbageCollected> ref_ptr1 =
3597             MakeGarbageCollected<RefCountedAndGarbageCollected>();
3598         Persistent<RefCountedAndGarbageCollected> ref_ptr2 =
3599             MakeGarbageCollected<RefCountedAndGarbageCollected>();
3600         PreciselyCollectGarbage();
3601         EXPECT_EQ(0, RefCountedAndGarbageCollected::destructor_calls_);
3602         persistent = ref_ptr1.Get();
3603       }
3604       // Reference count is zero for both objects but one of
3605       // them is kept alive by a persistent handle.
3606       PreciselyCollectGarbage();
3607       EXPECT_EQ(1, RefCountedAndGarbageCollected::destructor_calls_);
3608       ref_ptr3 = persistent.Get();
3609     }
3610     // The persistent handle is gone but the ref count has been
3611     // increased to 1.
3612     PreciselyCollectGarbage();
3613     EXPECT_EQ(1, RefCountedAndGarbageCollected::destructor_calls_);
3614   }
3615   // Both persistent handle is gone and ref count is zero so the
3616   // object can be collected.
3617   PreciselyCollectGarbage();
3618   EXPECT_EQ(2, RefCountedAndGarbageCollected::destructor_calls_);
3619 }
3620 
TEST_F(HeapTest,WeakMembers)3621 TEST_F(HeapTest, WeakMembers) {
3622   ClearOutOldGarbage();
3623   Bar::live_ = 0;
3624   {
3625     Persistent<Bar> h1 = MakeGarbageCollected<Bar>();
3626     Persistent<Weak> h4;
3627     Persistent<WithWeakMember> h5;
3628     PreciselyCollectGarbage();
3629     ASSERT_EQ(1u, Bar::live_);  // h1 is live.
3630     {
3631       auto* h2 = MakeGarbageCollected<Bar>();
3632       auto* h3 = MakeGarbageCollected<Bar>();
3633       h4 = MakeGarbageCollected<Weak>(h2, h3);
3634       h5 = MakeGarbageCollected<WithWeakMember>(h2, h3);
3635       ConservativelyCollectGarbage();
3636       EXPECT_EQ(5u, Bar::live_);  // The on-stack pointer keeps h3 alive.
3637       EXPECT_FALSE(h3->HasBeenFinalized());
3638       EXPECT_TRUE(h4->StrongIsThere());
3639       EXPECT_TRUE(h4->WeakIsThere());
3640       EXPECT_TRUE(h5->StrongIsThere());
3641       EXPECT_TRUE(h5->WeakIsThere());
3642     }
3643     // h3 is collected, weak pointers from h4 and h5 don't keep it alive.
3644     PreciselyCollectGarbage();
3645     EXPECT_EQ(4u, Bar::live_);
3646     EXPECT_TRUE(h4->StrongIsThere());
3647     EXPECT_FALSE(h4->WeakIsThere());  // h3 is gone from weak pointer.
3648     EXPECT_TRUE(h5->StrongIsThere());
3649     EXPECT_FALSE(h5->WeakIsThere());  // h3 is gone from weak pointer.
3650     h1.Release();                     // Zero out h1.
3651     PreciselyCollectGarbage();
3652     EXPECT_EQ(3u, Bar::live_);         // Only h4, h5 and h2 are left.
3653     EXPECT_TRUE(h4->StrongIsThere());  // h2 is still pointed to from h4.
3654     EXPECT_TRUE(h5->StrongIsThere());  // h2 is still pointed to from h5.
3655   }
3656   // h4 and h5 have gone out of scope now and they were keeping h2 alive.
3657   PreciselyCollectGarbage();
3658   EXPECT_EQ(0u, Bar::live_);  // All gone.
3659 }
3660 
TEST_F(HeapTest,FinalizationObserver)3661 TEST_F(HeapTest, FinalizationObserver) {
3662   Persistent<FinalizationObserver<Observable>> o;
3663   {
3664     auto* foo = MakeGarbageCollected<Observable>(MakeGarbageCollected<Bar>());
3665     // |o| observes |foo|.
3666     o = MakeGarbageCollected<FinalizationObserver<Observable>>(foo);
3667   }
3668   // FinalizationObserver doesn't have a strong reference to |foo|. So |foo|
3669   // and its member will be collected.
3670   PreciselyCollectGarbage();
3671   EXPECT_EQ(0u, Bar::live_);
3672   EXPECT_TRUE(o->DidCallWillFinalize());
3673 
3674   FinalizationObserverWithHashMap::did_call_will_finalize_ = false;
3675   auto* foo = MakeGarbageCollected<Observable>(MakeGarbageCollected<Bar>());
3676   FinalizationObserverWithHashMap::ObserverMap& map =
3677       FinalizationObserverWithHashMap::Observe(*foo);
3678   EXPECT_EQ(1u, map.size());
3679   foo = nullptr;
3680   // FinalizationObserverWithHashMap doesn't have a strong reference to
3681   // |foo|. So |foo| and its member will be collected.
3682   PreciselyCollectGarbage();
3683   EXPECT_EQ(0u, Bar::live_);
3684   EXPECT_EQ(0u, map.size());
3685   EXPECT_TRUE(FinalizationObserverWithHashMap::did_call_will_finalize_);
3686 
3687   FinalizationObserverWithHashMap::ClearObservers();
3688 }
3689 
TEST_F(HeapTest,PreFinalizer)3690 TEST_F(HeapTest, PreFinalizer) {
3691   Observable::will_finalize_was_called_ = false;
3692   { MakeGarbageCollected<Observable>(MakeGarbageCollected<Bar>()); }
3693   PreciselyCollectGarbage();
3694   EXPECT_TRUE(Observable::will_finalize_was_called_);
3695 }
3696 
TEST_F(HeapTest,PreFinalizerUnregistersItself)3697 TEST_F(HeapTest, PreFinalizerUnregistersItself) {
3698   ObservableWithPreFinalizer::dispose_was_called_ = false;
3699   MakeGarbageCollected<ObservableWithPreFinalizer>();
3700   PreciselyCollectGarbage();
3701   EXPECT_TRUE(ObservableWithPreFinalizer::dispose_was_called_);
3702   // Don't crash, and assertions don't fail.
3703 }
3704 
TEST_F(HeapTest,NestedPreFinalizer)3705 TEST_F(HeapTest, NestedPreFinalizer) {
3706   g_dispose_was_called_for_pre_finalizer_base = false;
3707   g_dispose_was_called_for_pre_finalizer_sub_class = false;
3708   g_dispose_was_called_for_pre_finalizer_mixin = false;
3709   MakeGarbageCollected<PreFinalizerSubClass>();
3710   PreciselyCollectGarbage();
3711   EXPECT_TRUE(g_dispose_was_called_for_pre_finalizer_base);
3712   EXPECT_TRUE(g_dispose_was_called_for_pre_finalizer_sub_class);
3713   EXPECT_TRUE(g_dispose_was_called_for_pre_finalizer_mixin);
3714   // Don't crash, and assertions don't fail.
3715 }
3716 
TEST_F(HeapTest,Comparisons)3717 TEST_F(HeapTest, Comparisons) {
3718   Persistent<Bar> bar_persistent = MakeGarbageCollected<Bar>();
3719   Persistent<Foo> foo_persistent = MakeGarbageCollected<Foo>(bar_persistent);
3720   EXPECT_TRUE(bar_persistent != foo_persistent);
3721   bar_persistent = foo_persistent;
3722   EXPECT_TRUE(bar_persistent == foo_persistent);
3723 }
3724 
3725 namespace {
3726 
ExpectObjectMarkedAndUnmark(MarkingWorklist * worklist,void * expected)3727 void ExpectObjectMarkedAndUnmark(MarkingWorklist* worklist, void* expected) {
3728   MarkingItem item;
3729   CHECK(worklist->Pop(0, &item));
3730   CHECK_EQ(expected, item.base_object_payload);
3731   HeapObjectHeader* header =
3732       HeapObjectHeader::FromPayload(item.base_object_payload);
3733   CHECK(header->IsMarked());
3734   header->Unmark();
3735   CHECK(worklist->IsGlobalEmpty());
3736 }
3737 
3738 }  // namespace
3739 
TEST_F(HeapTest,CheckAndMarkPointer)3740 TEST_F(HeapTest, CheckAndMarkPointer) {
3741   // This test ensures that conservative marking primitives can use any address
3742   // contained within an object to mark the corresponding object.
3743 
3744   ThreadHeap& heap = ThreadState::Current()->Heap();
3745   ClearOutOldGarbage();
3746 
3747   Vector<Address> object_addresses;
3748   Vector<Address> end_addresses;
3749   for (int i = 0; i < 10; i++) {
3750     auto* object = MakeGarbageCollected<SimpleObject>();
3751     Address object_address = reinterpret_cast<Address>(object);
3752     object_addresses.push_back(object_address);
3753     end_addresses.push_back(object_address + sizeof(SimpleObject) - 1);
3754   }
3755   Address large_object_address =
3756       reinterpret_cast<Address>(MakeGarbageCollected<LargeHeapObject>());
3757   Address large_object_end_address =
3758       large_object_address + sizeof(LargeHeapObject) - 1;
3759 
3760   {
3761     TestGCScope scope(BlinkGC::kHeapPointersOnStack);
3762     MarkingVisitor visitor(ThreadState::Current(),
3763                            MarkingVisitor::kGlobalMarking);
3764     // Record marking speed as counter generation requires valid marking timings
3765     // for heaps >1MB.
3766     ThreadHeapStatsCollector::Scope stats_scope(
3767         heap.stats_collector(),
3768         ThreadHeapStatsCollector::kAtomicPauseMarkTransitiveClosure);
3769 
3770     // Conservative marker should find the interesting objects by using anything
3771     // between object start and end.
3772     MarkingWorklist* worklist = heap.GetMarkingWorklist();
3773     CHECK(worklist->IsGlobalEmpty());
3774     for (wtf_size_t i = 0; i < object_addresses.size(); i++) {
3775       heap.CheckAndMarkPointer(&visitor, object_addresses[i]);
3776       ExpectObjectMarkedAndUnmark(worklist, object_addresses[i]);
3777       heap.CheckAndMarkPointer(&visitor, end_addresses[i]);
3778       ExpectObjectMarkedAndUnmark(worklist, object_addresses[i]);
3779     }
3780     heap.CheckAndMarkPointer(&visitor, large_object_address);
3781     ExpectObjectMarkedAndUnmark(worklist, large_object_address);
3782     heap.CheckAndMarkPointer(&visitor, large_object_end_address);
3783     ExpectObjectMarkedAndUnmark(worklist, large_object_address);
3784   }
3785 
3786   // This forces a GC without stack scanning which results in the objects
3787   // being collected. This will also rebuild the above mentioned freelists,
3788   // however we don't rely on that below since we don't have any allocations.
3789   ClearOutOldGarbage();
3790 
3791   {
3792     TestGCScope scope(BlinkGC::kHeapPointersOnStack);
3793     MarkingVisitor visitor(ThreadState::Current(),
3794                            MarkingVisitor::kGlobalMarking);
3795     // Record marking speed as counter generation requires valid marking timings
3796     // for heaps >1MB.
3797     ThreadHeapStatsCollector::Scope stats_scope(
3798         heap.stats_collector(),
3799         ThreadHeapStatsCollector::kAtomicPauseMarkTransitiveClosure);
3800 
3801     // After collecting all interesting objects the conservative marker should
3802     // not find them anymore.
3803     MarkingWorklist* worklist = heap.GetMarkingWorklist();
3804     CHECK(worklist->IsGlobalEmpty());
3805     for (wtf_size_t i = 0; i < object_addresses.size(); i++) {
3806       heap.CheckAndMarkPointer(&visitor, object_addresses[i]);
3807       CHECK(worklist->IsGlobalEmpty());
3808       heap.CheckAndMarkPointer(&visitor, end_addresses[i]);
3809       CHECK(worklist->IsGlobalEmpty());
3810     }
3811     heap.CheckAndMarkPointer(&visitor, large_object_address);
3812     CHECK(worklist->IsGlobalEmpty());
3813     heap.CheckAndMarkPointer(&visitor, large_object_end_address);
3814     CHECK(worklist->IsGlobalEmpty());
3815   }
3816 }
3817 
TEST_F(HeapTest,CollectionNesting)3818 TEST_F(HeapTest, CollectionNesting) {
3819   ClearOutOldGarbage();
3820   int k;
3821   int* key = &k;
3822   IntWrapper::destructor_calls_ = 0;
3823   typedef HeapVector<Member<IntWrapper>> IntVector;
3824   typedef HeapDeque<Member<IntWrapper>> IntDeque;
3825   HeapHashMap<void*, IntVector>* map =
3826       MakeGarbageCollected<HeapHashMap<void*, IntVector>>();
3827   HeapHashMap<void*, IntDeque>* map2 =
3828       MakeGarbageCollected<HeapHashMap<void*, IntDeque>>();
3829   static_assert(WTF::IsTraceable<IntVector>::value,
3830                 "Failed to recognize HeapVector as traceable");
3831   static_assert(WTF::IsTraceable<IntDeque>::value,
3832                 "Failed to recognize HeapDeque as traceable");
3833 
3834   map->insert(key, IntVector());
3835   map2->insert(key, IntDeque());
3836 
3837   HeapHashMap<void*, IntVector>::iterator it = map->find(key);
3838   EXPECT_EQ(0u, map->at(key).size());
3839 
3840   HeapHashMap<void*, IntDeque>::iterator it2 = map2->find(key);
3841   EXPECT_EQ(0u, map2->at(key).size());
3842 
3843   it->value.push_back(MakeGarbageCollected<IntWrapper>(42));
3844   EXPECT_EQ(1u, map->at(key).size());
3845 
3846   it2->value.push_back(MakeGarbageCollected<IntWrapper>(42));
3847   EXPECT_EQ(1u, map2->at(key).size());
3848 
3849   Persistent<HeapHashMap<void*, IntVector>> keep_alive(map);
3850   Persistent<HeapHashMap<void*, IntDeque>> keep_alive2(map2);
3851 
3852   for (int i = 0; i < 100; i++) {
3853     map->insert(key + 1 + i, IntVector());
3854     map2->insert(key + 1 + i, IntDeque());
3855   }
3856 
3857   PreciselyCollectGarbage();
3858 
3859   EXPECT_EQ(1u, map->at(key).size());
3860   EXPECT_EQ(1u, map2->at(key).size());
3861   EXPECT_EQ(0, IntWrapper::destructor_calls_);
3862 
3863   keep_alive = nullptr;
3864   PreciselyCollectGarbage();
3865   EXPECT_EQ(1, IntWrapper::destructor_calls_);
3866 }
3867 
TEST_F(HeapTest,GarbageCollectedMixin)3868 TEST_F(HeapTest, GarbageCollectedMixin) {
3869   ClearOutOldGarbage();
3870 
3871   Persistent<UseMixin> usemixin = MakeGarbageCollected<UseMixin>();
3872   EXPECT_EQ(0, UseMixin::trace_count_);
3873   PreciselyCollectGarbage();
3874   EXPECT_EQ(1, UseMixin::trace_count_);
3875 
3876   Persistent<Mixin> mixin = usemixin;
3877   usemixin = nullptr;
3878   PreciselyCollectGarbage();
3879   EXPECT_EQ(2, UseMixin::trace_count_);
3880 
3881   Persistent<HeapHashSet<WeakMember<Mixin>>> weak_map =
3882       MakeGarbageCollected<HeapHashSet<WeakMember<Mixin>>>();
3883   weak_map->insert(MakeGarbageCollected<UseMixin>());
3884   PreciselyCollectGarbage();
3885   EXPECT_EQ(0u, weak_map->size());
3886 }
3887 
TEST_F(HeapTest,CollectionNesting2)3888 TEST_F(HeapTest, CollectionNesting2) {
3889   ClearOutOldGarbage();
3890   void* key = &IntWrapper::destructor_calls_;
3891   IntWrapper::destructor_calls_ = 0;
3892   typedef HeapHashSet<Member<IntWrapper>> IntSet;
3893   HeapHashMap<void*, IntSet>* map =
3894       MakeGarbageCollected<HeapHashMap<void*, IntSet>>();
3895 
3896   map->insert(key, IntSet());
3897 
3898   HeapHashMap<void*, IntSet>::iterator it = map->find(key);
3899   EXPECT_EQ(0u, map->at(key).size());
3900 
3901   it->value.insert(MakeGarbageCollected<IntWrapper>(42));
3902   EXPECT_EQ(1u, map->at(key).size());
3903 
3904   Persistent<HeapHashMap<void*, IntSet>> keep_alive(map);
3905   PreciselyCollectGarbage();
3906   EXPECT_EQ(1u, map->at(key).size());
3907   EXPECT_EQ(0, IntWrapper::destructor_calls_);
3908 }
3909 
TEST_F(HeapTest,CollectionNesting3)3910 TEST_F(HeapTest, CollectionNesting3) {
3911   ClearOutOldGarbage();
3912   IntWrapper::destructor_calls_ = 0;
3913   typedef HeapVector<Member<IntWrapper>> IntVector;
3914   HeapVector<IntVector>* vector = MakeGarbageCollected<HeapVector<IntVector>>();
3915 
3916   vector->push_back(IntVector());
3917 
3918   HeapVector<IntVector>::iterator it = vector->begin();
3919   EXPECT_EQ(0u, it->size());
3920 
3921   it->push_back(MakeGarbageCollected<IntWrapper>(42));
3922   EXPECT_EQ(1u, it->size());
3923 
3924   Persistent<HeapVector<IntVector>> keep_alive(vector);
3925   PreciselyCollectGarbage();
3926   EXPECT_EQ(1u, it->size());
3927   EXPECT_EQ(0, IntWrapper::destructor_calls_);
3928 }
3929 
TEST_F(HeapTest,EmbeddedInVector)3930 TEST_F(HeapTest, EmbeddedInVector) {
3931   ClearOutOldGarbage();
3932   SimpleFinalizedObject::destructor_calls_ = 0;
3933   {
3934     Persistent<HeapVector<VectorObject, 2>> inline_vector =
3935         MakeGarbageCollected<HeapVector<VectorObject, 2>>();
3936     Persistent<HeapVector<VectorObject>> outline_vector =
3937         MakeGarbageCollected<HeapVector<VectorObject>>();
3938     VectorObject i1, i2;
3939     inline_vector->push_back(i1);
3940     inline_vector->push_back(i2);
3941 
3942     VectorObject o1, o2;
3943     outline_vector->push_back(o1);
3944     outline_vector->push_back(o2);
3945 
3946     Persistent<HeapVector<VectorObjectInheritedTrace>> vector_inherited_trace =
3947         MakeGarbageCollected<HeapVector<VectorObjectInheritedTrace>>();
3948     VectorObjectInheritedTrace it1, it2;
3949     vector_inherited_trace->push_back(it1);
3950     vector_inherited_trace->push_back(it2);
3951 
3952     PreciselyCollectGarbage();
3953     EXPECT_EQ(0, SimpleFinalizedObject::destructor_calls_);
3954   }
3955   PreciselyCollectGarbage();
3956   EXPECT_EQ(6, SimpleFinalizedObject::destructor_calls_);
3957 }
3958 
3959 class InlinedVectorObject {
3960   DISALLOW_NEW();
3961 
3962  public:
3963   InlinedVectorObject() = default;
~InlinedVectorObject()3964   ~InlinedVectorObject() { destructor_calls_++; }
Trace(Visitor * visitor)3965   void Trace(Visitor* visitor) {}
3966 
3967   static int destructor_calls_;
3968 };
3969 
3970 int InlinedVectorObject::destructor_calls_ = 0;
3971 
3972 class InlinedVectorObjectWithVtable {
3973   DISALLOW_NEW();
3974 
3975  public:
3976   InlinedVectorObjectWithVtable() = default;
~InlinedVectorObjectWithVtable()3977   virtual ~InlinedVectorObjectWithVtable() { destructor_calls_++; }
VirtualMethod()3978   virtual void VirtualMethod() {}
Trace(Visitor * visitor)3979   void Trace(Visitor* visitor) {}
3980 
3981   static int destructor_calls_;
3982 };
3983 
3984 int InlinedVectorObjectWithVtable::destructor_calls_ = 0;
3985 
3986 }  // namespace blink
3987 
3988 WTF_ALLOW_MOVE_AND_INIT_WITH_MEM_FUNCTIONS(blink::InlinedVectorObject)
3989 
3990 namespace blink {
3991 
3992 class InlinedVectorObjectWrapper final
3993     : public GarbageCollected<InlinedVectorObjectWrapper> {
3994  public:
InlinedVectorObjectWrapper()3995   InlinedVectorObjectWrapper() {
3996     InlinedVectorObject i1, i2;
3997     vector1_.push_back(i1);
3998     vector1_.push_back(i2);
3999     vector2_.push_back(i1);
4000     vector2_.push_back(i2);  // This allocates an out-of-line buffer.
4001     vector3_.push_back(i1);
4002     vector3_.push_back(i2);
4003   }
4004 
Trace(Visitor * visitor)4005   void Trace(Visitor* visitor) {
4006     visitor->Trace(vector1_);
4007     visitor->Trace(vector2_);
4008     visitor->Trace(vector3_);
4009   }
4010 
4011  private:
4012   HeapVector<InlinedVectorObject> vector1_;
4013   HeapVector<InlinedVectorObject, 1> vector2_;
4014   HeapVector<InlinedVectorObject, 2> vector3_;
4015 };
4016 
4017 class InlinedVectorObjectWithVtableWrapper final
4018     : public GarbageCollected<InlinedVectorObjectWithVtableWrapper> {
4019  public:
InlinedVectorObjectWithVtableWrapper()4020   InlinedVectorObjectWithVtableWrapper() {
4021     InlinedVectorObjectWithVtable i1, i2;
4022     vector1_.push_back(i1);
4023     vector1_.push_back(i2);
4024     vector2_.push_back(i1);
4025     vector2_.push_back(i2);  // This allocates an out-of-line buffer.
4026     vector3_.push_back(i1);
4027     vector3_.push_back(i2);
4028   }
4029 
Trace(Visitor * visitor)4030   void Trace(Visitor* visitor) {
4031     visitor->Trace(vector1_);
4032     visitor->Trace(vector2_);
4033     visitor->Trace(vector3_);
4034   }
4035 
4036  private:
4037   HeapVector<InlinedVectorObjectWithVtable> vector1_;
4038   HeapVector<InlinedVectorObjectWithVtable, 1> vector2_;
4039   HeapVector<InlinedVectorObjectWithVtable, 2> vector3_;
4040 };
4041 
TEST_F(HeapTest,VectorDestructors)4042 TEST_F(HeapTest, VectorDestructors) {
4043   ClearOutOldGarbage();
4044   InlinedVectorObject::destructor_calls_ = 0;
4045   {
4046     HeapVector<InlinedVectorObject> vector;
4047     InlinedVectorObject i1, i2;
4048     vector.push_back(i1);
4049     vector.push_back(i2);
4050   }
4051   PreciselyCollectGarbage();
4052   // This is not EXPECT_EQ but EXPECT_LE because a HeapVectorBacking calls
4053   // destructors for all elements in (not the size but) the capacity of
4054   // the vector. Thus the number of destructors called becomes larger
4055   // than the actual number of objects in the vector.
4056   EXPECT_LE(4, InlinedVectorObject::destructor_calls_);
4057 
4058   InlinedVectorObject::destructor_calls_ = 0;
4059   {
4060     HeapVector<InlinedVectorObject, 1> vector;
4061     InlinedVectorObject i1, i2;
4062     vector.push_back(i1);
4063     vector.push_back(i2);  // This allocates an out-of-line buffer.
4064   }
4065   PreciselyCollectGarbage();
4066   EXPECT_LE(4, InlinedVectorObject::destructor_calls_);
4067 
4068   InlinedVectorObject::destructor_calls_ = 0;
4069   {
4070     HeapVector<InlinedVectorObject, 2> vector;
4071     InlinedVectorObject i1, i2;
4072     vector.push_back(i1);
4073     vector.push_back(i2);
4074   }
4075   PreciselyCollectGarbage();
4076   EXPECT_LE(4, InlinedVectorObject::destructor_calls_);
4077 
4078   InlinedVectorObject::destructor_calls_ = 0;
4079   {
4080     Persistent<InlinedVectorObjectWrapper> vector_wrapper =
4081         MakeGarbageCollected<InlinedVectorObjectWrapper>();
4082     ConservativelyCollectGarbage();
4083     EXPECT_EQ(2, InlinedVectorObject::destructor_calls_);
4084   }
4085   PreciselyCollectGarbage();
4086   EXPECT_LE(8, InlinedVectorObject::destructor_calls_);
4087 }
4088 
4089 // TODO(Oilpan): when Vector.h's contiguous container support no longer disables
4090 // Vector<>s with inline capacity, enable this test.
4091 #if !defined(ANNOTATE_CONTIGUOUS_CONTAINER)
TEST_F(HeapTest,VectorDestructorsWithVtable)4092 TEST_F(HeapTest, VectorDestructorsWithVtable) {
4093   ClearOutOldGarbage();
4094   InlinedVectorObjectWithVtable::destructor_calls_ = 0;
4095   {
4096     HeapVector<InlinedVectorObjectWithVtable> vector;
4097     InlinedVectorObjectWithVtable i1, i2;
4098     vector.push_back(i1);
4099     vector.push_back(i2);
4100   }
4101   PreciselyCollectGarbage();
4102   EXPECT_EQ(4, InlinedVectorObjectWithVtable::destructor_calls_);
4103 
4104   InlinedVectorObjectWithVtable::destructor_calls_ = 0;
4105   {
4106     HeapVector<InlinedVectorObjectWithVtable, 1> vector;
4107     InlinedVectorObjectWithVtable i1, i2;
4108     vector.push_back(i1);
4109     vector.push_back(i2);  // This allocates an out-of-line buffer.
4110   }
4111   PreciselyCollectGarbage();
4112   EXPECT_EQ(5, InlinedVectorObjectWithVtable::destructor_calls_);
4113 
4114   InlinedVectorObjectWithVtable::destructor_calls_ = 0;
4115   {
4116     HeapVector<InlinedVectorObjectWithVtable, 2> vector;
4117     InlinedVectorObjectWithVtable i1, i2;
4118     vector.push_back(i1);
4119     vector.push_back(i2);
4120   }
4121   PreciselyCollectGarbage();
4122   EXPECT_EQ(4, InlinedVectorObjectWithVtable::destructor_calls_);
4123 
4124   InlinedVectorObjectWithVtable::destructor_calls_ = 0;
4125   {
4126     Persistent<InlinedVectorObjectWithVtableWrapper> vector_wrapper =
4127         MakeGarbageCollected<InlinedVectorObjectWithVtableWrapper>();
4128     ConservativelyCollectGarbage();
4129     EXPECT_EQ(3, InlinedVectorObjectWithVtable::destructor_calls_);
4130   }
4131   PreciselyCollectGarbage();
4132   EXPECT_EQ(9, InlinedVectorObjectWithVtable::destructor_calls_);
4133 }
4134 #endif
4135 
4136 template <typename Set>
RawPtrInHashHelper()4137 void RawPtrInHashHelper() {
4138   Set set;
4139   set.Add(new int(42));
4140   set.Add(new int(42));
4141   EXPECT_EQ(2u, set.size());
4142   for (typename Set::iterator it = set.begin(); it != set.end(); ++it) {
4143     EXPECT_EQ(42, **it);
4144     delete *it;
4145   }
4146 }
4147 
TEST_F(HeapTest,AllocationDuringFinalization)4148 TEST_F(HeapTest, AllocationDuringFinalization) {
4149   ClearOutOldGarbage();
4150   IntWrapper::destructor_calls_ = 0;
4151   OneKiloByteObject::destructor_calls_ = 0;
4152   LargeHeapObject::destructor_calls_ = 0;
4153 
4154   Persistent<IntWrapper> wrapper;
4155   MakeGarbageCollected<FinalizationAllocator>(&wrapper);
4156 
4157   PreciselyCollectGarbage();
4158   EXPECT_EQ(0, IntWrapper::destructor_calls_);
4159   EXPECT_EQ(0, OneKiloByteObject::destructor_calls_);
4160   EXPECT_EQ(0, LargeHeapObject::destructor_calls_);
4161   // Check that the wrapper allocated during finalization is not
4162   // swept away and zapped later in the same sweeping phase.
4163   EXPECT_EQ(42, wrapper->Value());
4164 
4165   wrapper.Clear();
4166   PreciselyCollectGarbage();
4167   // The 42 IntWrappers were the ones allocated in ~FinalizationAllocator
4168   // and the ones allocated in LargeHeapObject.
4169   EXPECT_EQ(42, IntWrapper::destructor_calls_);
4170   EXPECT_EQ(512, OneKiloByteObject::destructor_calls_);
4171   EXPECT_EQ(32, LargeHeapObject::destructor_calls_);
4172 }
4173 
4174 class SimpleClassWithDestructor {
4175  public:
4176   SimpleClassWithDestructor() = default;
~SimpleClassWithDestructor()4177   ~SimpleClassWithDestructor() { was_destructed_ = true; }
4178   static bool was_destructed_;
4179 };
4180 
4181 bool SimpleClassWithDestructor::was_destructed_;
4182 
4183 class RefCountedWithDestructor : public RefCounted<RefCountedWithDestructor> {
4184  public:
4185   RefCountedWithDestructor() = default;
~RefCountedWithDestructor()4186   ~RefCountedWithDestructor() { was_destructed_ = true; }
4187   static bool was_destructed_;
4188 };
4189 
4190 bool RefCountedWithDestructor::was_destructed_;
4191 
4192 template <typename Set>
DestructorsCalledOnGC(bool add_lots)4193 void DestructorsCalledOnGC(bool add_lots) {
4194   RefCountedWithDestructor::was_destructed_ = false;
4195   {
4196     Set set;
4197     RefCountedWithDestructor* has_destructor = new RefCountedWithDestructor();
4198     set.Add(base::AdoptRef(has_destructor));
4199     EXPECT_FALSE(RefCountedWithDestructor::was_destructed_);
4200 
4201     if (add_lots) {
4202       for (int i = 0; i < 1000; i++) {
4203         set.Add(base::AdoptRef(new RefCountedWithDestructor()));
4204       }
4205     }
4206 
4207     EXPECT_FALSE(RefCountedWithDestructor::was_destructed_);
4208     TestSupportingGC::ConservativelyCollectGarbage();
4209     EXPECT_FALSE(RefCountedWithDestructor::was_destructed_);
4210   }
4211   // The destructors of the sets don't call the destructors of the elements
4212   // in the heap sets. You have to actually remove the elments, call clear()
4213   // or have a GC to get the destructors called.
4214   EXPECT_FALSE(RefCountedWithDestructor::was_destructed_);
4215   TestSupportingGC::PreciselyCollectGarbage();
4216   EXPECT_TRUE(RefCountedWithDestructor::was_destructed_);
4217 }
4218 
4219 template <typename Set>
DestructorsCalledOnClear(bool add_lots)4220 void DestructorsCalledOnClear(bool add_lots) {
4221   RefCountedWithDestructor::was_destructed_ = false;
4222   Set set;
4223   RefCountedWithDestructor* has_destructor = new RefCountedWithDestructor();
4224   set.Add(base::AdoptRef(has_destructor));
4225   EXPECT_FALSE(RefCountedWithDestructor::was_destructed_);
4226 
4227   if (add_lots) {
4228     for (int i = 0; i < 1000; i++) {
4229       set.Add(base::AdoptRef(new RefCountedWithDestructor()));
4230     }
4231   }
4232 
4233   EXPECT_FALSE(RefCountedWithDestructor::was_destructed_);
4234   set.Clear();
4235   EXPECT_TRUE(RefCountedWithDestructor::was_destructed_);
4236 }
4237 
TEST_F(HeapTest,DestructorsCalled)4238 TEST_F(HeapTest, DestructorsCalled) {
4239   HeapHashMap<Member<IntWrapper>, std::unique_ptr<SimpleClassWithDestructor>>
4240       map;
4241   SimpleClassWithDestructor* has_destructor = new SimpleClassWithDestructor();
4242   map.insert(MakeGarbageCollected<IntWrapper>(1),
4243              base::WrapUnique(has_destructor));
4244   SimpleClassWithDestructor::was_destructed_ = false;
4245   map.clear();
4246   EXPECT_TRUE(SimpleClassWithDestructor::was_destructed_);
4247 }
4248 
4249 class MixinA : public GarbageCollectedMixin {
4250  public:
MixinA()4251   MixinA() : obj_(MakeGarbageCollected<IntWrapper>(100)) {}
Trace(Visitor * visitor)4252   void Trace(Visitor* visitor) override {
4253     trace_count_++;
4254     visitor->Trace(obj_);
4255   }
4256 
4257   static int trace_count_;
4258 
4259   Member<IntWrapper> obj_;
4260 };
4261 
4262 int MixinA::trace_count_ = 0;
4263 
4264 class MixinB : public GarbageCollectedMixin {
4265  public:
MixinB()4266   MixinB() : obj_(MakeGarbageCollected<IntWrapper>(101)) {}
Trace(Visitor * visitor)4267   void Trace(Visitor* visitor) override { visitor->Trace(obj_); }
4268   Member<IntWrapper> obj_;
4269 };
4270 
4271 class MultipleMixins : public GarbageCollected<MultipleMixins>,
4272                        public MixinA,
4273                        public MixinB {
4274   USING_GARBAGE_COLLECTED_MIXIN(MultipleMixins);
4275 
4276  public:
MultipleMixins()4277   MultipleMixins() : obj_(MakeGarbageCollected<IntWrapper>(102)) {}
Trace(Visitor * visitor)4278   void Trace(Visitor* visitor) override {
4279     visitor->Trace(obj_);
4280     MixinA::Trace(visitor);
4281     MixinB::Trace(visitor);
4282   }
4283   Member<IntWrapper> obj_;
4284 };
4285 
4286 class DerivedMultipleMixins : public MultipleMixins {
4287  public:
DerivedMultipleMixins()4288   DerivedMultipleMixins() : obj_(MakeGarbageCollected<IntWrapper>(103)) {}
4289 
Trace(Visitor * visitor)4290   void Trace(Visitor* visitor) override {
4291     trace_called_++;
4292     visitor->Trace(obj_);
4293     MultipleMixins::Trace(visitor);
4294   }
4295 
4296   static int trace_called_;
4297 
4298  private:
4299   Member<IntWrapper> obj_;
4300 };
4301 
4302 int DerivedMultipleMixins::trace_called_ = 0;
4303 
4304 static const bool kIsMixinTrue = IsGarbageCollectedMixin<MultipleMixins>::value;
4305 static const bool kIsMixinFalse = IsGarbageCollectedMixin<IntWrapper>::value;
4306 
TEST_F(HeapTest,MultipleMixins)4307 TEST_F(HeapTest, MultipleMixins) {
4308   EXPECT_TRUE(kIsMixinTrue);
4309   EXPECT_FALSE(kIsMixinFalse);
4310 
4311   ClearOutOldGarbage();
4312   IntWrapper::destructor_calls_ = 0;
4313   MultipleMixins* obj = MakeGarbageCollected<MultipleMixins>();
4314   {
4315     Persistent<MixinA> a = obj;
4316     PreciselyCollectGarbage();
4317     EXPECT_EQ(0, IntWrapper::destructor_calls_);
4318   }
4319   {
4320     Persistent<MixinB> b = obj;
4321     PreciselyCollectGarbage();
4322     EXPECT_EQ(0, IntWrapper::destructor_calls_);
4323   }
4324   PreciselyCollectGarbage();
4325   EXPECT_EQ(3, IntWrapper::destructor_calls_);
4326 }
4327 
TEST_F(HeapTest,DerivedMultipleMixins)4328 TEST_F(HeapTest, DerivedMultipleMixins) {
4329   ClearOutOldGarbage();
4330   IntWrapper::destructor_calls_ = 0;
4331   DerivedMultipleMixins::trace_called_ = 0;
4332 
4333   DerivedMultipleMixins* obj = MakeGarbageCollected<DerivedMultipleMixins>();
4334   {
4335     Persistent<MixinA> a = obj;
4336     PreciselyCollectGarbage();
4337     EXPECT_EQ(0, IntWrapper::destructor_calls_);
4338     EXPECT_LT(0, DerivedMultipleMixins::trace_called_);
4339   }
4340   {
4341     Persistent<MixinB> b = obj;
4342     PreciselyCollectGarbage();
4343     EXPECT_EQ(0, IntWrapper::destructor_calls_);
4344     EXPECT_LT(0, DerivedMultipleMixins::trace_called_);
4345   }
4346   PreciselyCollectGarbage();
4347   EXPECT_EQ(4, IntWrapper::destructor_calls_);
4348 }
4349 
4350 class MixinInstanceWithoutTrace
4351     : public GarbageCollected<MixinInstanceWithoutTrace>,
4352       public MixinA {
4353   USING_GARBAGE_COLLECTED_MIXIN(MixinInstanceWithoutTrace);
4354 
4355  public:
4356   MixinInstanceWithoutTrace() = default;
4357 };
4358 
TEST_F(HeapTest,MixinInstanceWithoutTrace)4359 TEST_F(HeapTest, MixinInstanceWithoutTrace) {
4360   // Verify that a mixin instance without any traceable
4361   // references inherits the mixin's trace implementation.
4362   ClearOutOldGarbage();
4363   MixinA::trace_count_ = 0;
4364   MixinInstanceWithoutTrace* obj =
4365       MakeGarbageCollected<MixinInstanceWithoutTrace>();
4366   int saved_trace_count = 0;
4367   {
4368     Persistent<MixinA> a = obj;
4369     PreciselyCollectGarbage();
4370     saved_trace_count = MixinA::trace_count_;
4371     EXPECT_LT(0, saved_trace_count);
4372   }
4373   {
4374     Persistent<MixinInstanceWithoutTrace> b = obj;
4375     PreciselyCollectGarbage();
4376     EXPECT_LT(saved_trace_count, MixinA::trace_count_);
4377     saved_trace_count = MixinA::trace_count_;
4378   }
4379   PreciselyCollectGarbage();
4380   // Oilpan might still call trace on dead objects for various reasons which is
4381   // valid before sweeping started.
4382   EXPECT_LE(saved_trace_count, MixinA::trace_count_);
4383 }
4384 
TEST_F(HeapTest,NeedsAdjustPointer)4385 TEST_F(HeapTest, NeedsAdjustPointer) {
4386   // class Mixin : public GarbageCollectedMixin {};
4387   static_assert(NeedsAdjustPointer<Mixin>::value,
4388                 "A Mixin pointer needs adjustment");
4389   static_assert(NeedsAdjustPointer<const Mixin>::value,
4390                 "A const Mixin pointer needs adjustment");
4391 
4392   // class SimpleObject : public GarbageCollected<SimpleObject> {};
4393   static_assert(!NeedsAdjustPointer<SimpleObject>::value,
4394                 "A SimpleObject pointer does not need adjustment");
4395   static_assert(!NeedsAdjustPointer<const SimpleObject>::value,
4396                 "A const SimpleObject pointer does not need adjustment");
4397 
4398   // class UseMixin : public SimpleObject, public Mixin {};
4399   static_assert(!NeedsAdjustPointer<UseMixin>::value,
4400                 "A UseMixin pointer does not need adjustment");
4401   static_assert(!NeedsAdjustPointer<const UseMixin>::value,
4402                 "A const UseMixin pointer does not need adjustment");
4403 }
4404 
AddElementsToWeakMap(HeapHashMap<int,WeakMember<IntWrapper>> * map)4405 static void AddElementsToWeakMap(
4406     HeapHashMap<int, WeakMember<IntWrapper>>* map) {
4407   // Key cannot be zero in hashmap.
4408   for (int i = 1; i < 11; i++)
4409     map->insert(i, MakeGarbageCollected<IntWrapper>(i));
4410 }
4411 
4412 // crbug.com/402426
4413 // If it doesn't assert a concurrent modification to the map, then it's passing.
TEST_F(HeapTest,RegressNullIsStrongified)4414 TEST_F(HeapTest, RegressNullIsStrongified) {
4415   Persistent<HeapHashMap<int, WeakMember<IntWrapper>>> map =
4416       MakeGarbageCollected<HeapHashMap<int, WeakMember<IntWrapper>>>();
4417   AddElementsToWeakMap(map);
4418   HeapHashMap<int, WeakMember<IntWrapper>>::AddResult result =
4419       map->insert(800, nullptr);
4420   ConservativelyCollectGarbage();
4421   result.stored_value->value = MakeGarbageCollected<IntWrapper>(42);
4422 }
4423 
TEST_F(HeapTest,Bind)4424 TEST_F(HeapTest, Bind) {
4425   base::OnceClosure closure =
4426       WTF::Bind(static_cast<void (Bar::*)(Visitor*)>(&Bar::Trace),
4427                 WrapPersistent(MakeGarbageCollected<Bar>()), nullptr);
4428   // OffHeapInt* should not make Persistent.
4429   base::OnceClosure closure2 =
4430       WTF::Bind(&OffHeapInt::VoidFunction, OffHeapInt::Create(1));
4431   PreciselyCollectGarbage();
4432   // The closure should have a persistent handle to the Bar.
4433   EXPECT_EQ(1u, Bar::live_);
4434 
4435   UseMixin::trace_count_ = 0;
4436   auto* mixin = MakeGarbageCollected<UseMixin>();
4437   base::OnceClosure mixin_closure =
4438       WTF::Bind(static_cast<void (Mixin::*)(Visitor*)>(&Mixin::Trace),
4439                 WrapPersistent(mixin), nullptr);
4440   PreciselyCollectGarbage();
4441   // The closure should have a persistent handle to the mixin.
4442   EXPECT_EQ(1, UseMixin::trace_count_);
4443 }
4444 
4445 typedef HeapHashSet<WeakMember<IntWrapper>> WeakSet;
4446 
TEST_F(HeapTest,EphemeronsInEphemerons)4447 TEST_F(HeapTest, EphemeronsInEphemerons) {
4448   typedef HeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper>> InnerMap;
4449   typedef HeapHashMap<WeakMember<IntWrapper>, InnerMap> OuterMap;
4450 
4451   for (int keep_outer_alive = 0; keep_outer_alive <= 1; keep_outer_alive++) {
4452     for (int keep_inner_alive = 0; keep_inner_alive <= 1; keep_inner_alive++) {
4453       Persistent<OuterMap> outer = MakeGarbageCollected<OuterMap>();
4454       Persistent<IntWrapper> one = MakeGarbageCollected<IntWrapper>(1);
4455       Persistent<IntWrapper> two = MakeGarbageCollected<IntWrapper>(2);
4456       outer->insert(one, InnerMap());
4457       outer->begin()->value.insert(two, MakeGarbageCollected<IntWrapper>(3));
4458       EXPECT_EQ(1u, outer->at(one).size());
4459       if (!keep_outer_alive)
4460         one.Clear();
4461       if (!keep_inner_alive)
4462         two.Clear();
4463       PreciselyCollectGarbage();
4464       if (keep_outer_alive) {
4465         const InnerMap& inner = outer->at(one);
4466         if (keep_inner_alive) {
4467           EXPECT_EQ(1u, inner.size());
4468           IntWrapper* three = inner.at(two);
4469           EXPECT_EQ(3, three->Value());
4470         } else {
4471           EXPECT_EQ(0u, inner.size());
4472         }
4473       } else {
4474         EXPECT_EQ(0u, outer->size());
4475       }
4476       outer->clear();
4477       Persistent<IntWrapper> deep = MakeGarbageCollected<IntWrapper>(42);
4478       Persistent<IntWrapper> home = MakeGarbageCollected<IntWrapper>(103);
4479       Persistent<IntWrapper> composite = MakeGarbageCollected<IntWrapper>(91);
4480       Persistent<HeapVector<Member<IntWrapper>>> keep_alive =
4481           MakeGarbageCollected<HeapVector<Member<IntWrapper>>>();
4482       for (int i = 0; i < 10000; i++) {
4483         auto* value = MakeGarbageCollected<IntWrapper>(i);
4484         keep_alive->push_back(value);
4485         OuterMap::AddResult new_entry = outer->insert(value, InnerMap());
4486         new_entry.stored_value->value.insert(deep, home);
4487         new_entry.stored_value->value.insert(composite, home);
4488       }
4489       composite.Clear();
4490       PreciselyCollectGarbage();
4491       EXPECT_EQ(10000u, outer->size());
4492       for (int i = 0; i < 10000; i++) {
4493         IntWrapper* value = keep_alive->at(i);
4494         EXPECT_EQ(1u,
4495                   outer->at(value)
4496                       .size());  // Other one was deleted by weak handling.
4497         if (i & 1)
4498           keep_alive->at(i) = nullptr;
4499       }
4500       PreciselyCollectGarbage();
4501       EXPECT_EQ(5000u, outer->size());
4502     }
4503   }
4504 }
4505 
4506 class EphemeronWrapper : public GarbageCollected<EphemeronWrapper> {
4507  public:
Trace(Visitor * visitor)4508   void Trace(Visitor* visitor) { visitor->Trace(map_); }
4509 
4510   typedef HeapHashMap<WeakMember<IntWrapper>, Member<EphemeronWrapper>> Map;
GetMap()4511   Map& GetMap() { return map_; }
4512 
4513  private:
4514   Map map_;
4515 };
4516 
TEST_F(HeapTest,EphemeronsPointToEphemerons)4517 TEST_F(HeapTest, EphemeronsPointToEphemerons) {
4518   Persistent<IntWrapper> key = MakeGarbageCollected<IntWrapper>(42);
4519   Persistent<IntWrapper> key2 = MakeGarbageCollected<IntWrapper>(103);
4520 
4521   Persistent<EphemeronWrapper> chain;
4522   for (int i = 0; i < 100; i++) {
4523     EphemeronWrapper* old_head = chain;
4524     chain = MakeGarbageCollected<EphemeronWrapper>();
4525     if (i == 50)
4526       chain->GetMap().insert(key2, old_head);
4527     else
4528       chain->GetMap().insert(key, old_head);
4529     chain->GetMap().insert(MakeGarbageCollected<IntWrapper>(103),
4530                            MakeGarbageCollected<EphemeronWrapper>());
4531   }
4532 
4533   PreciselyCollectGarbage();
4534 
4535   EphemeronWrapper* wrapper = chain;
4536   for (int i = 0; i < 100; i++) {
4537     EXPECT_EQ(1u, wrapper->GetMap().size());
4538     if (i == 49)
4539       wrapper = wrapper->GetMap().at(key2);
4540     else
4541       wrapper = wrapper->GetMap().at(key);
4542   }
4543   EXPECT_EQ(nullptr, wrapper);
4544 
4545   key2.Clear();
4546   PreciselyCollectGarbage();
4547 
4548   wrapper = chain;
4549   for (int i = 0; i < 50; i++) {
4550     EXPECT_EQ(i == 49 ? 0u : 1u, wrapper->GetMap().size());
4551     wrapper = wrapper->GetMap().at(key);
4552   }
4553   EXPECT_EQ(nullptr, wrapper);
4554 
4555   key.Clear();
4556   PreciselyCollectGarbage();
4557   EXPECT_EQ(0u, chain->GetMap().size());
4558 }
4559 
TEST_F(HeapTest,Ephemeron)4560 TEST_F(HeapTest, Ephemeron) {
4561   typedef HeapHashSet<WeakMember<IntWrapper>> Set;
4562 
4563   Persistent<Set> set = MakeGarbageCollected<Set>();
4564 
4565   Persistent<IntWrapper> wp1 = MakeGarbageCollected<IntWrapper>(1);
4566   Persistent<IntWrapper> wp2 = MakeGarbageCollected<IntWrapper>(2);
4567   Persistent<IntWrapper> pw1 = MakeGarbageCollected<IntWrapper>(3);
4568   Persistent<IntWrapper> pw2 = MakeGarbageCollected<IntWrapper>(4);
4569 
4570   set->insert(wp1);
4571   set->insert(wp2);
4572   set->insert(pw1);
4573   set->insert(pw2);
4574 
4575   PreciselyCollectGarbage();
4576 
4577   EXPECT_EQ(4u, set->size());
4578 
4579   wp2.Clear();  // Kills all entries in the weakPairMaps except the first.
4580   pw2.Clear();  // Kills all entries in the pairWeakMaps except the first.
4581 
4582   for (int i = 0; i < 2; i++) {
4583     PreciselyCollectGarbage();
4584 
4585     EXPECT_EQ(2u, set->size());  // wp1 and pw1.
4586   }
4587 
4588   wp1.Clear();
4589   pw1.Clear();
4590 
4591   PreciselyCollectGarbage();
4592 
4593   EXPECT_EQ(0u, set->size());
4594 }
4595 
4596 class Link1 : public GarbageCollected<Link1> {
4597  public:
Link1(IntWrapper * link)4598   Link1(IntWrapper* link) : link_(link) {}
4599 
Trace(Visitor * visitor)4600   void Trace(Visitor* visitor) { visitor->Trace(link_); }
4601 
Link()4602   IntWrapper* Link() { return link_; }
4603 
4604  private:
4605   Member<IntWrapper> link_;
4606 };
4607 
TEST_F(HeapTest,IndirectStrongToWeak)4608 TEST_F(HeapTest, IndirectStrongToWeak) {
4609   typedef HeapHashMap<WeakMember<IntWrapper>, Member<Link1>> Map;
4610   Persistent<Map> map = MakeGarbageCollected<Map>();
4611   Persistent<IntWrapper> dead_object = MakeGarbageCollected<IntWrapper>(
4612       100);  // Named for "Drowning by Numbers" (1988).
4613   Persistent<IntWrapper> life_object = MakeGarbageCollected<IntWrapper>(42);
4614   map->insert(dead_object, MakeGarbageCollected<Link1>(dead_object));
4615   map->insert(life_object, MakeGarbageCollected<Link1>(life_object));
4616   EXPECT_EQ(2u, map->size());
4617   PreciselyCollectGarbage();
4618   EXPECT_EQ(2u, map->size());
4619   EXPECT_EQ(dead_object, map->at(dead_object)->Link());
4620   EXPECT_EQ(life_object, map->at(life_object)->Link());
4621   dead_object.Clear();  // Now it can live up to its name.
4622   PreciselyCollectGarbage();
4623   EXPECT_EQ(1u, map->size());
4624   EXPECT_EQ(life_object, map->at(life_object)->Link());
4625   life_object.Clear();  // Despite its name.
4626   PreciselyCollectGarbage();
4627   EXPECT_EQ(0u, map->size());
4628 }
4629 
AllocateAndReturnBool()4630 static bool AllocateAndReturnBool() {
4631   TestSupportingGC::ConservativelyCollectGarbage();
4632   return true;
4633 }
4634 
4635 template <typename T>
4636 class TraceIfNeededTester final
4637     : public GarbageCollected<TraceIfNeededTester<T>> {
4638  public:
4639   TraceIfNeededTester() = default;
TraceIfNeededTester(const T & obj)4640   explicit TraceIfNeededTester(const T& obj) : obj_(obj) {}
4641 
Trace(Visitor * visitor)4642   void Trace(Visitor* visitor) { TraceIfNeeded<T>::Trace(visitor, obj_); }
Obj()4643   T& Obj() { return obj_; }
4644   ~TraceIfNeededTester() = default;
4645 
4646  private:
4647   T obj_;
4648 };
4649 
4650 class PartObject {
4651   DISALLOW_NEW();
4652 
4653  public:
PartObject()4654   PartObject() : obj_(MakeGarbageCollected<SimpleObject>()) {}
Trace(Visitor * visitor)4655   void Trace(Visitor* visitor) { visitor->Trace(obj_); }
4656 
4657  private:
4658   Member<SimpleObject> obj_;
4659 };
4660 
4661 class AllocatesOnAssignment {
4662  public:
AllocatesOnAssignment(std::nullptr_t)4663   AllocatesOnAssignment(std::nullptr_t) : value_(nullptr) {}
AllocatesOnAssignment(int x)4664   AllocatesOnAssignment(int x) : value_(MakeGarbageCollected<IntWrapper>(x)) {}
AllocatesOnAssignment(IntWrapper * x)4665   AllocatesOnAssignment(IntWrapper* x) : value_(x) {}
4666 
operator =(const AllocatesOnAssignment x)4667   AllocatesOnAssignment& operator=(const AllocatesOnAssignment x) {
4668     value_ = x.value_;
4669     return *this;
4670   }
4671 
4672   enum DeletedMarker { kDeletedValue };
4673 
AllocatesOnAssignment(const AllocatesOnAssignment & other)4674   AllocatesOnAssignment(const AllocatesOnAssignment& other) {
4675     if (!ThreadState::Current()->IsGCForbidden())
4676       TestSupportingGC::ConservativelyCollectGarbage();
4677     value_ = MakeGarbageCollected<IntWrapper>(other.value_->Value());
4678   }
4679 
AllocatesOnAssignment(DeletedMarker)4680   AllocatesOnAssignment(DeletedMarker) : value_(WTF::kHashTableDeletedValue) {}
4681 
IsDeleted() const4682   inline bool IsDeleted() const { return value_.IsHashTableDeletedValue(); }
4683 
Trace(Visitor * visitor)4684   void Trace(Visitor* visitor) { visitor->Trace(value_); }
4685 
Value()4686   int Value() { return value_->Value(); }
4687 
4688  private:
4689   Member<IntWrapper> value_;
4690 
4691   friend bool operator==(const AllocatesOnAssignment&,
4692                          const AllocatesOnAssignment&);
4693   friend void swap(AllocatesOnAssignment&, AllocatesOnAssignment&);
4694 };
4695 
operator ==(const AllocatesOnAssignment & a,const AllocatesOnAssignment & b)4696 bool operator==(const AllocatesOnAssignment& a,
4697                 const AllocatesOnAssignment& b) {
4698   if (a.value_)
4699     return b.value_ && a.value_->Value() == b.value_->Value();
4700   return !b.value_;
4701 }
4702 
swap(AllocatesOnAssignment & a,AllocatesOnAssignment & b)4703 void swap(AllocatesOnAssignment& a, AllocatesOnAssignment& b) {
4704   std::swap(a.value_, b.value_);
4705 }
4706 
4707 struct DegenerateHash {
GetHashblink::DegenerateHash4708   static unsigned GetHash(const AllocatesOnAssignment&) { return 0; }
Equalblink::DegenerateHash4709   static bool Equal(const AllocatesOnAssignment& a,
4710                     const AllocatesOnAssignment& b) {
4711     return !a.IsDeleted() && a == b;
4712   }
4713   static const bool safe_to_compare_to_empty_or_deleted = true;
4714 };
4715 
4716 struct AllocatesOnAssignmentHashTraits
4717     : WTF::GenericHashTraits<AllocatesOnAssignment> {
4718   typedef AllocatesOnAssignment T;
4719   typedef std::nullptr_t EmptyValueType;
EmptyValueblink::AllocatesOnAssignmentHashTraits4720   static EmptyValueType EmptyValue() { return nullptr; }
4721   static const bool kEmptyValueIsZero =
4722       false;  // Can't be zero if it has a vtable.
ConstructDeletedValueblink::AllocatesOnAssignmentHashTraits4723   static void ConstructDeletedValue(T& slot, bool) {
4724     slot = T(AllocatesOnAssignment::kDeletedValue);
4725   }
IsDeletedValueblink::AllocatesOnAssignmentHashTraits4726   static bool IsDeletedValue(const T& value) { return value.IsDeleted(); }
4727 };
4728 
4729 }  // namespace blink
4730 
4731 namespace WTF {
4732 
4733 template <>
4734 struct DefaultHash<blink::AllocatesOnAssignment> {
4735   typedef blink::DegenerateHash Hash;
4736 };
4737 
4738 template <>
4739 struct HashTraits<blink::AllocatesOnAssignment>
4740     : blink::AllocatesOnAssignmentHashTraits {};
4741 
4742 }  // namespace WTF
4743 
4744 namespace blink {
4745 
TEST_F(HeapTest,GCInHashMapOperations)4746 TEST_F(HeapTest, GCInHashMapOperations) {
4747   typedef HeapHashMap<AllocatesOnAssignment, AllocatesOnAssignment> Map;
4748   Map* map = MakeGarbageCollected<Map>();
4749   IntWrapper* key = MakeGarbageCollected<IntWrapper>(42);
4750   map->insert(key, AllocatesOnAssignment(103));
4751   map->erase(key);
4752   for (int i = 0; i < 10; i++)
4753     map->insert(AllocatesOnAssignment(i), AllocatesOnAssignment(i));
4754   for (Map::iterator it = map->begin(); it != map->end(); ++it)
4755     EXPECT_EQ(it->key.Value(), it->value.Value());
4756 }
4757 
4758 class PartObjectWithVirtualMethod {
4759  public:
Trace(Visitor * visitor)4760   virtual void Trace(Visitor* visitor) {}
4761 };
4762 
4763 class ObjectWithVirtualPartObject
4764     : public GarbageCollected<ObjectWithVirtualPartObject> {
4765  public:
ObjectWithVirtualPartObject()4766   ObjectWithVirtualPartObject() : dummy_(AllocateAndReturnBool()) {}
Trace(Visitor * visitor)4767   void Trace(Visitor* visitor) { visitor->Trace(part_); }
4768 
4769  private:
4770   bool dummy_;
4771   PartObjectWithVirtualMethod part_;
4772 };
4773 
TEST_F(HeapTest,PartObjectWithVirtualMethod)4774 TEST_F(HeapTest, PartObjectWithVirtualMethod) {
4775   ObjectWithVirtualPartObject* object =
4776       MakeGarbageCollected<ObjectWithVirtualPartObject>();
4777   EXPECT_TRUE(object);
4778 }
4779 
4780 class AllocInSuperConstructorArgumentSuper
4781     : public GarbageCollected<AllocInSuperConstructorArgumentSuper> {
4782  public:
AllocInSuperConstructorArgumentSuper(bool value)4783   AllocInSuperConstructorArgumentSuper(bool value) : value_(value) {}
4784   virtual ~AllocInSuperConstructorArgumentSuper() = default;
Trace(Visitor * visitor)4785   virtual void Trace(Visitor* visitor) {}
Value()4786   bool Value() { return value_; }
4787 
4788  private:
4789   bool value_;
4790 };
4791 
4792 class AllocInSuperConstructorArgument
4793     : public AllocInSuperConstructorArgumentSuper {
4794  public:
AllocInSuperConstructorArgument()4795   AllocInSuperConstructorArgument()
4796       : AllocInSuperConstructorArgumentSuper(AllocateAndReturnBool()) {}
4797 };
4798 
4799 // Regression test for crbug.com/404511. Tests conservative marking of
4800 // an object with an uninitialized vtable.
TEST_F(HeapTest,AllocationInSuperConstructorArgument)4801 TEST_F(HeapTest, AllocationInSuperConstructorArgument) {
4802   AllocInSuperConstructorArgument* object =
4803       MakeGarbageCollected<AllocInSuperConstructorArgument>();
4804   EXPECT_TRUE(object);
4805   ThreadState::Current()->CollectAllGarbageForTesting();
4806 }
4807 
4808 class NonNodeAllocatingNodeInDestructor final
4809     : public GarbageCollected<NonNodeAllocatingNodeInDestructor> {
4810  public:
~NonNodeAllocatingNodeInDestructor()4811   ~NonNodeAllocatingNodeInDestructor() {
4812     node_ = new Persistent<IntNode>(IntNode::Create(10));
4813   }
4814 
Trace(Visitor * visitor)4815   void Trace(Visitor* visitor) {}
4816 
4817   static Persistent<IntNode>* node_;
4818 };
4819 
4820 Persistent<IntNode>* NonNodeAllocatingNodeInDestructor::node_ = nullptr;
4821 
TEST_F(HeapTest,NonNodeAllocatingNodeInDestructor)4822 TEST_F(HeapTest, NonNodeAllocatingNodeInDestructor) {
4823   MakeGarbageCollected<NonNodeAllocatingNodeInDestructor>();
4824   PreciselyCollectGarbage();
4825   EXPECT_EQ(10, (*NonNodeAllocatingNodeInDestructor::node_)->Value());
4826   delete NonNodeAllocatingNodeInDestructor::node_;
4827   NonNodeAllocatingNodeInDestructor::node_ = nullptr;
4828 }
4829 
4830 class DeepEagerly final : public GarbageCollected<DeepEagerly> {
4831  public:
DeepEagerly(DeepEagerly * next)4832   DeepEagerly(DeepEagerly* next) : next_(next) {}
4833 
Trace(Visitor * visitor)4834   void Trace(Visitor* visitor) {
4835     int calls = ++s_trace_calls_;
4836     if (s_trace_lazy_ <= 2)
4837       visitor->Trace(next_);
4838     if (s_trace_calls_ == calls)
4839       s_trace_lazy_++;
4840   }
4841 
4842   Member<DeepEagerly> next_;
4843 
4844   static int s_trace_calls_;
4845   static int s_trace_lazy_;
4846 };
4847 
4848 int DeepEagerly::s_trace_calls_ = 0;
4849 int DeepEagerly::s_trace_lazy_ = 0;
4850 
TEST_F(HeapTest,TraceDeepEagerly)4851 TEST_F(HeapTest, TraceDeepEagerly) {
4852 // The allocation & GC overhead is considerable for this test,
4853 // straining debug builds and lower-end targets too much to be
4854 // worth running.
4855 #if !DCHECK_IS_ON() && !defined(OS_ANDROID)
4856   DeepEagerly* obj = nullptr;
4857   for (int i = 0; i < 10000000; i++)
4858     obj = MakeGarbageCollected<DeepEagerly>(obj);
4859 
4860   Persistent<DeepEagerly> persistent(obj);
4861   PreciselyCollectGarbage();
4862 
4863   // Verify that the DeepEagerly chain isn't completely unravelled
4864   // by performing eager trace() calls, but the explicit mark
4865   // stack is switched once some nesting limit is exceeded.
4866   EXPECT_GT(DeepEagerly::s_trace_lazy_, 2);
4867 #endif
4868 }
4869 
TEST_F(HeapTest,DequeExpand)4870 TEST_F(HeapTest, DequeExpand) {
4871   // Test expansion of a HeapDeque<>'s buffer.
4872 
4873   typedef HeapDeque<Member<IntWrapper>> IntDeque;
4874 
4875   Persistent<IntDeque> deque = MakeGarbageCollected<IntDeque>();
4876 
4877   // Append a sequence, bringing about repeated expansions of the
4878   // deque's buffer.
4879   int i = 0;
4880   for (; i < 60; ++i)
4881     deque->push_back(MakeGarbageCollected<IntWrapper>(i));
4882 
4883   EXPECT_EQ(60u, deque->size());
4884   i = 0;
4885   for (const auto& int_wrapper : *deque) {
4886     EXPECT_EQ(i, int_wrapper->Value());
4887     i++;
4888   }
4889 
4890   // Remove most of the queued objects and have the buffer's start index
4891   // 'point' somewhere into the buffer, just behind the end index.
4892   for (i = 0; i < 50; ++i)
4893     deque->TakeFirst();
4894 
4895   EXPECT_EQ(10u, deque->size());
4896   i = 0;
4897   for (const auto& int_wrapper : *deque) {
4898     EXPECT_EQ(50 + i, int_wrapper->Value());
4899     i++;
4900   }
4901 
4902   // Append even more, eventually causing an expansion of the underlying
4903   // buffer once the end index wraps around and reaches the start index.
4904   for (i = 0; i < 70; ++i)
4905     deque->push_back(MakeGarbageCollected<IntWrapper>(60 + i));
4906 
4907   // Verify that the final buffer expansion copied the start and end segments
4908   // of the old buffer to both ends of the expanded buffer, along with
4909   // re-adjusting both start&end indices in terms of that expanded buffer.
4910   EXPECT_EQ(80u, deque->size());
4911   i = 0;
4912   for (const auto& int_wrapper : *deque) {
4913     EXPECT_EQ(i + 50, int_wrapper->Value());
4914     i++;
4915   }
4916 }
4917 
4918 class SimpleRefValue : public RefCounted<SimpleRefValue> {
4919  public:
Create(int i)4920   static scoped_refptr<SimpleRefValue> Create(int i) {
4921     return base::AdoptRef(new SimpleRefValue(i));
4922   }
4923 
Value() const4924   int Value() const { return value_; }
4925 
4926  private:
SimpleRefValue(int value)4927   explicit SimpleRefValue(int value) : value_(value) {}
4928 
4929   int value_;
4930 };
4931 
4932 class PartObjectWithRef {
4933   DISALLOW_NEW();
4934 
4935  public:
PartObjectWithRef(int i)4936   PartObjectWithRef(int i) : value_(SimpleRefValue::Create(i)) {}
4937 
Trace(Visitor * visitor)4938   void Trace(Visitor* visitor) {}
4939 
Value() const4940   int Value() const { return value_->Value(); }
4941 
4942  private:
4943   scoped_refptr<SimpleRefValue> value_;
4944 };
4945 
4946 }  // namespace blink
4947 
4948 WTF_ALLOW_INIT_WITH_MEM_FUNCTIONS(blink::PartObjectWithRef)
4949 
4950 namespace blink {
4951 
TEST_F(HeapTest,HeapVectorPartObjects)4952 TEST_F(HeapTest, HeapVectorPartObjects) {
4953   HeapVector<PartObjectWithRef> vector1;
4954   HeapVector<PartObjectWithRef> vector2;
4955 
4956   for (int i = 0; i < 10; ++i) {
4957     vector1.push_back(PartObjectWithRef(i));
4958     vector2.push_back(PartObjectWithRef(i));
4959   }
4960 
4961   vector1.ReserveCapacity(150);
4962   EXPECT_LE(150u, vector1.capacity());
4963   EXPECT_EQ(10u, vector1.size());
4964 
4965   vector2.ReserveCapacity(100);
4966   EXPECT_LE(100u, vector2.capacity());
4967   EXPECT_EQ(10u, vector2.size());
4968 
4969   for (int i = 0; i < 4; ++i) {
4970     vector1.push_back(PartObjectWithRef(10 + i));
4971     vector2.push_back(PartObjectWithRef(10 + i));
4972     vector2.push_back(PartObjectWithRef(10 + i));
4973   }
4974 
4975   // Shrinking heap vector backing stores always succeeds,
4976   // so these two will not currently exercise the code path
4977   // where shrinking causes copying into a new, small buffer.
4978   vector2.ShrinkToReasonableCapacity();
4979   EXPECT_EQ(18u, vector2.size());
4980 
4981   vector1.ShrinkToReasonableCapacity();
4982   EXPECT_EQ(14u, vector1.size());
4983 }
4984 
4985 class TestMixinAllocationA : public GarbageCollected<TestMixinAllocationA>,
4986                              public GarbageCollectedMixin {
4987   USING_GARBAGE_COLLECTED_MIXIN(TestMixinAllocationA);
4988 
4989  public:
4990   TestMixinAllocationA() = default;
4991 
Trace(Visitor * visitor)4992   void Trace(Visitor* visitor) override {}
4993 };
4994 
4995 class TestMixinAllocationB : public TestMixinAllocationA {
4996   USING_GARBAGE_COLLECTED_MIXIN(TestMixinAllocationB);
4997 
4998  public:
TestMixinAllocationB()4999   TestMixinAllocationB()
5000       // Construct object during a mixin construction.
5001       : a_(MakeGarbageCollected<TestMixinAllocationA>()) {}
5002 
Trace(Visitor * visitor)5003   void Trace(Visitor* visitor) override {
5004     visitor->Trace(a_);
5005     TestMixinAllocationA::Trace(visitor);
5006   }
5007 
5008  private:
5009   Member<TestMixinAllocationA> a_;
5010 };
5011 
5012 class TestMixinAllocationC final : public TestMixinAllocationB {
5013   USING_GARBAGE_COLLECTED_MIXIN(TestMixinAllocationC);
5014 
5015  public:
TestMixinAllocationC()5016   TestMixinAllocationC() { DCHECK(!ThreadState::Current()->IsGCForbidden()); }
5017 
Trace(Visitor * visitor)5018   void Trace(Visitor* visitor) override {
5019     TestMixinAllocationB::Trace(visitor);
5020   }
5021 };
5022 
TEST_F(HeapTest,NestedMixinConstruction)5023 TEST_F(HeapTest, NestedMixinConstruction) {
5024   TestMixinAllocationC* object = MakeGarbageCollected<TestMixinAllocationC>();
5025   EXPECT_TRUE(object);
5026 }
5027 
5028 class ObjectWithLargeAmountsOfAllocationInConstructor {
5029  public:
ObjectWithLargeAmountsOfAllocationInConstructor(size_t number_of_large_objects_to_allocate,ClassWithMember * member)5030   ObjectWithLargeAmountsOfAllocationInConstructor(
5031       size_t number_of_large_objects_to_allocate,
5032       ClassWithMember* member) {
5033     // Should a constructor allocate plenty in its constructor,
5034     // and it is a base of GC mixin, GCs will remain locked out
5035     // regardless, as we cannot safely trace the leftmost GC
5036     // mixin base.
5037     DCHECK(ThreadState::Current()->IsGCForbidden());
5038     for (size_t i = 0; i < number_of_large_objects_to_allocate; i++) {
5039       auto* large_object = MakeGarbageCollected<LargeHeapObject>();
5040       EXPECT_TRUE(large_object);
5041       EXPECT_EQ(0, member->TraceCount());
5042     }
5043   }
5044 };
5045 
5046 class WeakPersistentHolder final {
5047  public:
WeakPersistentHolder(IntWrapper * object)5048   explicit WeakPersistentHolder(IntWrapper* object) : object_(object) {}
Object() const5049   IntWrapper* Object() const { return object_; }
5050 
5051  private:
5052   WeakPersistent<IntWrapper> object_;
5053 };
5054 
TEST_F(HeapTest,WeakPersistent)5055 TEST_F(HeapTest, WeakPersistent) {
5056   Persistent<IntWrapper> object = MakeGarbageCollected<IntWrapper>(20);
5057   std::unique_ptr<WeakPersistentHolder> holder =
5058       std::make_unique<WeakPersistentHolder>(object);
5059   PreciselyCollectGarbage();
5060   EXPECT_TRUE(holder->Object());
5061   object = nullptr;
5062   PreciselyCollectGarbage();
5063   EXPECT_FALSE(holder->Object());
5064 }
5065 
5066 namespace {
5067 
5068 class ThreadedClearOnShutdownTester : public ThreadedTesterBase {
5069  public:
Test()5070   static void Test() {
5071     IntWrapper::destructor_calls_ = 0;
5072     ThreadedTesterBase::Test(new ThreadedClearOnShutdownTester);
5073     EXPECT_EQ(kNumberOfThreads, IntWrapper::destructor_calls_);
5074   }
5075 
5076  private:
5077   void RunWhileAttached();
5078 
RunThread()5079   void RunThread() override {
5080     EXPECT_EQ(42, ThreadSpecificIntWrapper().Value());
5081     RunWhileAttached();
5082   }
5083 
5084   class HeapObject;
5085   friend class HeapObject;
5086 
5087   using WeakHeapObjectSet = HeapHashSet<WeakMember<HeapObject>>;
5088 
5089   static WeakHeapObjectSet& GetWeakHeapObjectSet();
5090 
5091   using HeapObjectSet = HeapHashSet<Member<HeapObject>>;
5092   static HeapObjectSet& GetHeapObjectSet();
5093 
ThreadSpecificIntWrapper()5094   static IntWrapper& ThreadSpecificIntWrapper() {
5095     DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<Persistent<IntWrapper>>,
5096                                     int_wrapper, ());
5097     Persistent<IntWrapper>& handle = *int_wrapper;
5098     if (!handle) {
5099       handle = MakeGarbageCollected<IntWrapper>(42);
5100       handle.RegisterAsStaticReference();
5101     }
5102     return *handle;
5103   }
5104 };
5105 
5106 class ThreadedClearOnShutdownTester::HeapObject final
5107     : public GarbageCollected<ThreadedClearOnShutdownTester::HeapObject> {
5108  public:
HeapObject(bool test_destructor)5109   explicit HeapObject(bool test_destructor)
5110       : test_destructor_(test_destructor) {}
~HeapObject()5111   ~HeapObject() {
5112     if (!test_destructor_)
5113       return;
5114 
5115     // Verify that the weak reference is gone.
5116     EXPECT_FALSE(GetWeakHeapObjectSet().Contains(this));
5117 
5118     // Add a new member to the static singleton; this will
5119     // re-initializes the persistent node of the collection
5120     // object. Done while terminating the test thread, so
5121     // verify that this brings about the release of the
5122     // persistent also.
5123     GetHeapObjectSet().insert(MakeGarbageCollected<HeapObject>(false));
5124   }
5125 
Trace(Visitor * visitor)5126   void Trace(Visitor* visitor) {}
5127 
5128  private:
5129   bool test_destructor_;
5130 };
5131 
5132 ThreadedClearOnShutdownTester::WeakHeapObjectSet&
GetWeakHeapObjectSet()5133 ThreadedClearOnShutdownTester::GetWeakHeapObjectSet() {
5134   DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<Persistent<WeakHeapObjectSet>>,
5135                                   singleton, ());
5136   Persistent<WeakHeapObjectSet>& singleton_persistent = *singleton;
5137   if (!singleton_persistent) {
5138     singleton_persistent = MakeGarbageCollected<WeakHeapObjectSet>();
5139     singleton_persistent.RegisterAsStaticReference();
5140   }
5141   return *singleton_persistent;
5142 }
5143 
5144 ThreadedClearOnShutdownTester::HeapObjectSet&
GetHeapObjectSet()5145 ThreadedClearOnShutdownTester::GetHeapObjectSet() {
5146   DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<Persistent<HeapObjectSet>>,
5147                                   singleton, ());
5148   Persistent<HeapObjectSet>& singleton_persistent = *singleton;
5149   if (!singleton_persistent) {
5150     singleton_persistent = MakeGarbageCollected<HeapObjectSet>();
5151     singleton_persistent.RegisterAsStaticReference();
5152   }
5153   return *singleton_persistent;
5154 }
5155 
RunWhileAttached()5156 void ThreadedClearOnShutdownTester::RunWhileAttached() {
5157   EXPECT_EQ(42, ThreadSpecificIntWrapper().Value());
5158   // Creates a thread-specific singleton to a weakly held object.
5159   GetWeakHeapObjectSet().insert(MakeGarbageCollected<HeapObject>(true));
5160 }
5161 
5162 }  // namespace
5163 
TEST_F(HeapTest,TestClearOnShutdown)5164 TEST_F(HeapTest, TestClearOnShutdown) {
5165   ThreadedClearOnShutdownTester::Test();
5166 }
5167 
5168 // Verify that WeakMember<const T> compiles and behaves as expected.
5169 class WithWeakConstObject final : public GarbageCollected<WithWeakConstObject> {
5170  public:
WithWeakConstObject(const IntWrapper * int_wrapper)5171   WithWeakConstObject(const IntWrapper* int_wrapper) : wrapper_(int_wrapper) {}
5172 
Trace(Visitor * visitor)5173   void Trace(Visitor* visitor) { visitor->Trace(wrapper_); }
5174 
Value() const5175   const IntWrapper* Value() const { return wrapper_; }
5176 
5177  private:
5178   WeakMember<const IntWrapper> wrapper_;
5179 };
5180 
TEST_F(HeapTest,TestWeakConstObject)5181 TEST_F(HeapTest, TestWeakConstObject) {
5182   Persistent<WithWeakConstObject> weak_wrapper;
5183   {
5184     const auto* wrapper = MakeGarbageCollected<IntWrapper>(42);
5185     weak_wrapper = MakeGarbageCollected<WithWeakConstObject>(wrapper);
5186     ConservativelyCollectGarbage();
5187     EXPECT_EQ(wrapper, weak_wrapper->Value());
5188     // Stub out any stack reference.
5189     wrapper = nullptr;
5190   }
5191   PreciselyCollectGarbage();
5192   EXPECT_EQ(nullptr, weak_wrapper->Value());
5193 }
5194 
5195 class EmptyMixin : public GarbageCollectedMixin {};
5196 class UseMixinFromLeftmostInherited : public UseMixin, public EmptyMixin {
5197  public:
5198   ~UseMixinFromLeftmostInherited() = default;
5199 };
5200 
TEST_F(HeapTest,IsGarbageCollected)5201 TEST_F(HeapTest, IsGarbageCollected) {
5202   // Static sanity checks covering the correct operation of
5203   // IsGarbageCollectedType<>.
5204 
5205   static_assert(WTF::IsGarbageCollectedType<SimpleObject>::value,
5206                 "GarbageCollected<>");
5207   static_assert(WTF::IsGarbageCollectedType<const SimpleObject>::value,
5208                 "const GarbageCollected<>");
5209   static_assert(WTF::IsGarbageCollectedType<IntWrapper>::value,
5210                 "GarbageCollected<>");
5211   static_assert(WTF::IsGarbageCollectedType<GarbageCollectedMixin>::value,
5212                 "GarbageCollectedMixin");
5213   static_assert(WTF::IsGarbageCollectedType<const GarbageCollectedMixin>::value,
5214                 "const GarbageCollectedMixin");
5215   static_assert(WTF::IsGarbageCollectedType<UseMixin>::value,
5216                 "GarbageCollectedMixin instance");
5217   static_assert(WTF::IsGarbageCollectedType<const UseMixin>::value,
5218                 "const GarbageCollectedMixin instance");
5219   static_assert(
5220       WTF::IsGarbageCollectedType<UseMixinFromLeftmostInherited>::value,
5221       "GarbageCollectedMixin derived instance");
5222   static_assert(WTF::IsGarbageCollectedType<MultipleMixins>::value,
5223                 "GarbageCollectedMixin");
5224 
5225   static_assert(
5226       WTF::IsGarbageCollectedType<HeapHashSet<Member<IntWrapper>>>::value,
5227       "HeapHashSet");
5228   static_assert(
5229       WTF::IsGarbageCollectedType<HeapLinkedHashSet<Member<IntWrapper>>>::value,
5230       "HeapLinkedHashSet");
5231   static_assert(WTF::IsGarbageCollectedType<
5232                     HeapNewLinkedHashSet<Member<IntWrapper>>>::value,
5233                 "HeapNewLinkedHashSet");
5234   static_assert(
5235       WTF::IsGarbageCollectedType<HeapListHashSet<Member<IntWrapper>>>::value,
5236       "HeapListHashSet");
5237   static_assert(WTF::IsGarbageCollectedType<
5238                     HeapHashCountedSet<Member<IntWrapper>>>::value,
5239                 "HeapHashCountedSet");
5240   static_assert(
5241       WTF::IsGarbageCollectedType<HeapHashMap<int, Member<IntWrapper>>>::value,
5242       "HeapHashMap");
5243   static_assert(
5244       WTF::IsGarbageCollectedType<HeapVector<Member<IntWrapper>>>::value,
5245       "HeapVector");
5246   static_assert(
5247       WTF::IsGarbageCollectedType<HeapDeque<Member<IntWrapper>>>::value,
5248       "HeapDeque");
5249 }
5250 
TEST_F(HeapTest,HeapHashMapCallsDestructor)5251 TEST_F(HeapTest, HeapHashMapCallsDestructor) {
5252   String string = "string";
5253   EXPECT_TRUE(string.Impl()->HasOneRef());
5254 
5255   HeapHashMap<KeyWithCopyingMoveConstructor, Member<IntWrapper>> map;
5256 
5257   EXPECT_TRUE(string.Impl()->HasOneRef());
5258 
5259   for (int i = 1; i <= 100; ++i) {
5260     KeyWithCopyingMoveConstructor key(i, string);
5261     map.insert(key, MakeGarbageCollected<IntWrapper>(i));
5262   }
5263 
5264   EXPECT_FALSE(string.Impl()->HasOneRef());
5265   map.clear();
5266 
5267   EXPECT_TRUE(string.Impl()->HasOneRef());
5268 }
5269 
TEST_F(HeapTest,ShrinkVector)5270 TEST_F(HeapTest, ShrinkVector) {
5271   // Regression test: https://crbug.com/823289
5272 
5273   HeapVector<Member<IntWrapper>> vector;
5274   vector.ReserveCapacity(32);
5275   for (int i = 0; i < 4; i++) {
5276     vector.push_back(MakeGarbageCollected<IntWrapper>(i));
5277   }
5278 
5279   ConservativelyCollectGarbage(BlinkGC::kConcurrentAndLazySweeping);
5280 
5281   // The following call tries to promptly free the left overs. In the buggy
5282   // scenario that would create a free HeapObjectHeader that is assumed to be
5283   // black which it is not.
5284   vector.ShrinkToFit();
5285 }
5286 
TEST_F(HeapTest,GarbageCollectedInConstruction)5287 TEST_F(HeapTest, GarbageCollectedInConstruction) {
5288   using O = ObjectWithCallbackBeforeInitializer<IntWrapper>;
5289   MakeGarbageCollected<O>(base::BindOnce([](O* thiz) {
5290     CHECK(HeapObjectHeader::FromPayload(thiz)->IsInConstruction());
5291   }));
5292 }
5293 
TEST_F(HeapTest,GarbageCollectedMixinInConstruction)5294 TEST_F(HeapTest, GarbageCollectedMixinInConstruction) {
5295   using O = ObjectWithMixinWithCallbackBeforeInitializer<IntWrapper>;
5296   MakeGarbageCollected<O>(base::BindOnce([](O::Mixin* thiz) {
5297     const HeapObjectHeader* const header =
5298         HeapObjectHeader::FromInnerAddress(reinterpret_cast<Address>(thiz));
5299     CHECK(header->IsInConstruction());
5300   }));
5301 }
5302 
TEST_F(HeapTest,GarbageCollectedMixinIsAliveDuringConstruction)5303 TEST_F(HeapTest, GarbageCollectedMixinIsAliveDuringConstruction) {
5304   using O = ObjectWithMixinWithCallbackBeforeInitializer<IntWrapper>;
5305   MakeGarbageCollected<O>(base::BindOnce(
5306       [](O::Mixin* thiz) { CHECK(ThreadHeap::IsHeapObjectAlive(thiz)); }));
5307 
5308   using P = HeapVector<Member<HeapLinkedHashSet<Member<IntWrapper>>>>;
5309   MakeGarbageCollected<P>();
5310   using Q = HeapVector<Member<HeapNewLinkedHashSet<Member<IntWrapper>>>>;
5311   MakeGarbageCollected<Q>();
5312 }
5313 
TEST_F(HeapTest,PersistentAssignsDeletedValue)5314 TEST_F(HeapTest, PersistentAssignsDeletedValue) {
5315   // Regression test: https://crbug.com/982313
5316 
5317   Persistent<IntWrapper> deleted(WTF::kHashTableDeletedValue);
5318   Persistent<IntWrapper> pre_initialized(MakeGarbageCollected<IntWrapper>(1));
5319   pre_initialized = deleted;
5320   PreciselyCollectGarbage();
5321 }
5322 
5323 struct HeapHashMapWrapper final : GarbageCollected<HeapHashMapWrapper> {
HeapHashMapWrapperblink::HeapHashMapWrapper5324   HeapHashMapWrapper() {
5325     for (int i = 0; i < 100; ++i) {
5326       map_.insert(MakeGarbageCollected<IntWrapper>(i),
5327                   NonTriviallyDestructible());
5328     }
5329   }
5330   // This should call ~HeapHapMap() -> ~HashMap() -> ~HashTable().
5331   ~HeapHashMapWrapper() = default;
5332 
Traceblink::HeapHashMapWrapper5333   void Trace(Visitor* visitor) { visitor->Trace(map_); }
5334 
5335  private:
5336   struct NonTriviallyDestructible {
~NonTriviallyDestructibleblink::HeapHashMapWrapper::NonTriviallyDestructible5337     ~NonTriviallyDestructible() {}
5338   };
5339   HeapHashMap<Member<IntWrapper>, NonTriviallyDestructible> map_;
5340 };
5341 
TEST_F(HeapTest,AccessDeletedBackingStore)5342 TEST_F(HeapTest, AccessDeletedBackingStore) {
5343   // Regression test: https://crbug.com/985443
5344   base::test::ScopedFeatureList scoped_feature_list;
5345   scoped_feature_list.InitAndDisableFeature(
5346       blink::features::kBlinkHeapConcurrentSweeping);
5347   ClearOutOldGarbage();
5348 
5349   ThreadState* thread_state = ThreadState::Current();
5350 
5351   auto* map = MakeGarbageCollected<HeapHashMapWrapper>();
5352   // Run marking.
5353   PreciselyCollectGarbage(BlinkGC::kConcurrentAndLazySweeping);
5354   // Perform complete sweep on hash_arena.
5355   BaseArena* hash_arena =
5356       thread_state->Heap().Arena(BlinkGC::kHashTableArenaIndex);
5357   {
5358     ThreadState::AtomicPauseScope scope(thread_state);
5359     ScriptForbiddenScope script_forbidden_scope;
5360     ThreadState::SweepForbiddenScope sweep_forbidden(thread_state);
5361     hash_arena->CompleteSweep();
5362   }
5363   BaseArena* map_arena = PageFromObject(map)->Arena();
5364   // Sweep normal arena, but don't call finalizers.
5365   while (!map_arena->ConcurrentSweepOnePage()) {
5366   }
5367   // Now complete sweeping with PerformIdleLazySweep and call finalizers.
5368   while (thread_state->IsSweepingInProgress()) {
5369     thread_state->PerformIdleLazySweep(base::TimeTicks::Max());
5370   }
5371 }
5372 
5373 class GCBase : public GarbageCollected<GCBase> {
5374  public:
Trace(Visitor *)5375   virtual void Trace(Visitor*) {}
5376 };
5377 
5378 class GCDerived final : public GCBase {
5379  public:
5380   static int destructor_called;
Trace(Visitor *)5381   void Trace(Visitor*) override {}
~GCDerived()5382   ~GCDerived() { ++destructor_called; }
5383 };
5384 
5385 int GCDerived::destructor_called = 0;
5386 
TEST_F(HeapTest,CallMostDerivedFinalizer)5387 TEST_F(HeapTest, CallMostDerivedFinalizer) {
5388   MakeGarbageCollected<GCDerived>();
5389   PreciselyCollectGarbage();
5390   EXPECT_EQ(1, GCDerived::destructor_called);
5391 }
5392 
5393 #if defined(ADDRESS_SANITIZER)
TEST(HeapDeathTest,DieOnPoisonedObjectHeaderAccess)5394 TEST(HeapDeathTest, DieOnPoisonedObjectHeaderAccess) {
5395   auto* ptr = MakeGarbageCollected<IntWrapper>(1);
5396   HeapObjectHeader* header = HeapObjectHeader::FromPayload(ptr);
5397   auto* low = reinterpret_cast<uint16_t*>(header);
5398   auto access = [low] {
5399     volatile uint16_t half = WTF::AsAtomicPtr(low)->load();
5400     WTF::AsAtomicPtr(low)->store(half);
5401   };
5402   EXPECT_DEATH(access(), "");
5403 }
5404 
TEST_F(HeapTest,SuccessfulUnsanitizedAccessToObjectHeader)5405 TEST_F(HeapTest, SuccessfulUnsanitizedAccessToObjectHeader) {
5406   auto* ptr = MakeGarbageCollected<IntWrapper>(1);
5407   HeapObjectHeader* header = HeapObjectHeader::FromPayload(ptr);
5408   auto* low = reinterpret_cast<uint16_t*>(header);
5409   volatile uint16_t half = internal::AsUnsanitizedAtomic(low)->load();
5410   internal::AsUnsanitizedAtomic(low)->store(half);
5411 }
5412 #endif  // ADDRESS_SANITIZER
5413 
5414 }  // namespace blink
5415