1 /* 2 * Copyright 2017 The Chromium Authors. All rights reserved. 3 * Use of this source code is governed by a BSD-style license that can be 4 * found in the LICENSE file. 5 */ 6 7 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HEAP_TEST_UTILITIES_H_ 8 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HEAP_TEST_UTILITIES_H_ 9 10 #include "base/callback.h" 11 #include "base/test/task_environment.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 #include "third_party/blink/renderer/platform/heap/blink_gc.h" 14 #include "third_party/blink/renderer/platform/heap/garbage_collected.h" 15 #include "third_party/blink/renderer/platform/heap/handle.h" 16 #include "third_party/blink/renderer/platform/heap/heap.h" 17 #include "third_party/blink/renderer/platform/heap/impl/trace_traits.h" 18 #include "third_party/blink/renderer/platform/heap/visitor.h" 19 20 namespace blink { 21 22 class TestSupportingGC : public testing::Test { 23 public: 24 // Performs a precise garbage collection with eager sweeping. 25 static void PreciselyCollectGarbage( 26 BlinkGC::SweepingType sweeping_type = BlinkGC::kEagerSweeping); 27 28 // Performs a conservative garbage collection. 29 static void ConservativelyCollectGarbage( 30 BlinkGC::SweepingType sweeping_type = BlinkGC::kEagerSweeping); 31 32 ~TestSupportingGC() override; 33 34 // Performs multiple rounds of garbage collections until no more memory can be 35 // freed. This is useful to avoid other garbage collections having to deal 36 // with stale memory. 37 void ClearOutOldGarbage(); 38 39 // Completes sweeping if it is currently running. 40 void CompleteSweepingIfNeeded(); 41 42 protected: 43 base::test::TaskEnvironment task_environment_; 44 }; 45 46 template <typename T> 47 class ObjectWithCallbackBeforeInitializer 48 : public GarbageCollected<ObjectWithCallbackBeforeInitializer<T>> { 49 public: ObjectWithCallbackBeforeInitializer(base::OnceCallback<void (ObjectWithCallbackBeforeInitializer<T> *)> && cb,T * value)50 ObjectWithCallbackBeforeInitializer( 51 base::OnceCallback<void(ObjectWithCallbackBeforeInitializer<T>*)>&& cb, 52 T* value) 53 : bool_(ExecuteCallbackReturnTrue(this, std::move(cb))), value_(value) {} 54 ObjectWithCallbackBeforeInitializer(base::OnceCallback<void (ObjectWithCallbackBeforeInitializer<T> *)> && cb)55 ObjectWithCallbackBeforeInitializer( 56 base::OnceCallback<void(ObjectWithCallbackBeforeInitializer<T>*)>&& cb) 57 : bool_(ExecuteCallbackReturnTrue(this, std::move(cb))) {} 58 Trace(Visitor * visitor)59 virtual void Trace(Visitor* visitor) const { visitor->Trace(value_); } 60 value()61 T* value() const { return value_.Get(); } 62 63 private: ExecuteCallbackReturnTrue(ObjectWithCallbackBeforeInitializer * thiz,base::OnceCallback<void (ObjectWithCallbackBeforeInitializer<T> *)> && cb)64 static bool ExecuteCallbackReturnTrue( 65 ObjectWithCallbackBeforeInitializer* thiz, 66 base::OnceCallback<void(ObjectWithCallbackBeforeInitializer<T>*)>&& cb) { 67 std::move(cb).Run(thiz); 68 return true; 69 } 70 71 bool bool_; 72 Member<T> value_; 73 }; 74 75 template <typename T> 76 class MixinWithCallbackBeforeInitializer : public GarbageCollectedMixin { 77 public: MixinWithCallbackBeforeInitializer(base::OnceCallback<void (MixinWithCallbackBeforeInitializer<T> *)> && cb,T * value)78 MixinWithCallbackBeforeInitializer( 79 base::OnceCallback<void(MixinWithCallbackBeforeInitializer<T>*)>&& cb, 80 T* value) 81 : bool_(ExecuteCallbackReturnTrue(this, std::move(cb))), value_(value) {} 82 MixinWithCallbackBeforeInitializer(base::OnceCallback<void (MixinWithCallbackBeforeInitializer<T> *)> && cb)83 MixinWithCallbackBeforeInitializer( 84 base::OnceCallback<void(MixinWithCallbackBeforeInitializer<T>*)>&& cb) 85 : bool_(ExecuteCallbackReturnTrue(this, std::move(cb))) {} 86 Trace(Visitor * visitor)87 void Trace(Visitor* visitor) const override { visitor->Trace(value_); } 88 value()89 T* value() const { return value_.Get(); } 90 91 private: ExecuteCallbackReturnTrue(MixinWithCallbackBeforeInitializer * thiz,base::OnceCallback<void (MixinWithCallbackBeforeInitializer<T> *)> && cb)92 static bool ExecuteCallbackReturnTrue( 93 MixinWithCallbackBeforeInitializer* thiz, 94 base::OnceCallback<void(MixinWithCallbackBeforeInitializer<T>*)>&& cb) { 95 std::move(cb).Run(thiz); 96 return true; 97 } 98 99 bool bool_; 100 Member<T> value_; 101 }; 102 103 class BoolMixin { 104 protected: 105 bool bool_ = false; 106 }; 107 108 template <typename T> 109 class ObjectWithMixinWithCallbackBeforeInitializer 110 : public GarbageCollected<ObjectWithMixinWithCallbackBeforeInitializer<T>>, 111 public BoolMixin, 112 public MixinWithCallbackBeforeInitializer<T> { 113 public: 114 using Mixin = MixinWithCallbackBeforeInitializer<T>; 115 ObjectWithMixinWithCallbackBeforeInitializer(base::OnceCallback<void (Mixin *)> && cb,T * value)116 ObjectWithMixinWithCallbackBeforeInitializer( 117 base::OnceCallback<void(Mixin*)>&& cb, 118 T* value) 119 : Mixin(std::move(cb), value) {} 120 ObjectWithMixinWithCallbackBeforeInitializer(base::OnceCallback<void (Mixin *)> && cb)121 ObjectWithMixinWithCallbackBeforeInitializer( 122 base::OnceCallback<void(Mixin*)>&& cb) 123 : Mixin(std::move(cb)) {} 124 Trace(Visitor * visitor)125 void Trace(Visitor* visitor) const override { Mixin::Trace(visitor); } 126 }; 127 128 // Simple linked object to be used in tests. 129 class LinkedObject : public GarbageCollected<LinkedObject> { 130 public: 131 LinkedObject() = default; LinkedObject(LinkedObject * next)132 explicit LinkedObject(LinkedObject* next) : next_(next) {} 133 set_next(LinkedObject * next)134 void set_next(LinkedObject* next) { next_ = next; } next()135 LinkedObject* next() const { return next_; } next_ref()136 Member<LinkedObject>& next_ref() { return next_; } 137 Trace(Visitor * visitor)138 virtual void Trace(Visitor* visitor) const { visitor->Trace(next_); } 139 140 private: 141 Member<LinkedObject> next_; 142 }; 143 144 // Test driver for incremental marking. Assumes that no stack handling is 145 // required. 146 class IncrementalMarkingTestDriver { 147 public: IncrementalMarkingTestDriver(ThreadState * thread_state)148 explicit IncrementalMarkingTestDriver(ThreadState* thread_state) 149 : thread_state_(thread_state) {} 150 ~IncrementalMarkingTestDriver(); 151 152 void Start(); 153 bool SingleStep(BlinkGC::StackState stack_state = 154 BlinkGC::StackState::kNoHeapPointersOnStack); 155 void FinishSteps(BlinkGC::StackState stack_state = 156 BlinkGC::StackState::kNoHeapPointersOnStack); 157 void FinishGC(bool complete_sweep = true); 158 159 // Methods for forcing a concurrent marking step without any assistance from 160 // mutator thread (i.e. without incremental marking on the mutator thread). 161 bool SingleConcurrentStep(BlinkGC::StackState stack_state = 162 BlinkGC::StackState::kNoHeapPointersOnStack); 163 void FinishConcurrentSteps(BlinkGC::StackState stack_state = 164 BlinkGC::StackState::kNoHeapPointersOnStack); 165 166 size_t GetHeapCompactLastFixupCount() const; 167 168 private: 169 ThreadState* const thread_state_; 170 }; 171 172 class IntegerObject : public GarbageCollected<IntegerObject> { 173 public: 174 static std::atomic_int destructor_calls; 175 IntegerObject(int x)176 explicit IntegerObject(int x) : x_(x) {} 177 ~IntegerObject()178 virtual ~IntegerObject() { 179 destructor_calls.fetch_add(1, std::memory_order_relaxed); 180 } 181 Trace(Visitor * visitor)182 virtual void Trace(Visitor* visitor) const {} 183 Value()184 int Value() const { return x_; } 185 186 bool operator==(const IntegerObject& other) const { 187 return other.Value() == Value(); 188 } 189 GetHash()190 unsigned GetHash() { return IntHash<int>::GetHash(x_); } 191 192 private: 193 int x_; 194 }; 195 196 struct IntegerObjectHash { GetHashIntegerObjectHash197 static unsigned GetHash(const IntegerObject& key) { 198 return WTF::HashInt(static_cast<uint32_t>(key.Value())); 199 } 200 EqualIntegerObjectHash201 static bool Equal(const IntegerObject& a, const IntegerObject& b) { 202 return a == b; 203 } 204 }; 205 206 } // namespace blink 207 208 #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HEAP_TEST_UTILITIES_H_ 209