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