blob: ae2ef2e55a5ee29f92c128a3908c2c75451fa834 [file] [log] [blame] [view]
Omer Katzfc07752082022-01-07 11:42:351# Oilpan - Blink GC
yutakd5604862015-10-19 10:26:442
Michael Lippautz17bf72b2023-10-09 20:05:183Oilpan is a garbage collector (GC) for Blink objects.
Omer Katzfc07752082022-01-07 11:42:354This document explores the design, API and usage of the GC.
yutakd5604862015-10-19 10:26:445
6[TOC]
7
Michael Lippautz17bf72b2023-10-09 20:05:188
Omer Katzfc07752082022-01-07 11:42:359## Overview
yutakd5604862015-10-19 10:26:4410
Victor Costan9df64f22022-01-15 03:07:4311The general design of Oilpan is explained in the [Oilpan README](https://chromium.googlesource.com/v8/v8/+/main/include/cppgc/README.md).
Omer Katzfc07752082022-01-07 11:42:3512This section focuses on the Blink specific extensions to that design.
yutakd5604862015-10-19 10:26:4413
Omer Katzfc07752082022-01-07 11:42:3514## Threading model
15
16Oilpan assumes heaps are not shared among threads.
Omer Katzfc07752082022-01-07 11:42:3517
18Threads that want to allocate Oilpan objects must be *attached* to Oilpan, by calling either `blink::ThreadState::AttachMainThread()` or `blink::ThreadState::AttachCurrentThread()`.
19
Michael Lippautz17bf72b2023-10-09 20:05:1820Blink creates heaps and root sets (that directly refer to objects) per thread.
21Matching a thread to its relevant heap is maintained by `blink::ThreadState`.
22
23An object belongs to the thread it is allocated on.
24
25Oilpan allows referring to objects from the same thread and cross-thread in various ways.
26See [Handles](#Handles) for details.
27
Omer Katzfc07752082022-01-07 11:42:3528## Heap partitioning
29
30Blink assigns the following types to custom spaces in Oilpan's heap:
31- Objects that are a collection backing are allocated in one of the collection backing *compactable* custom spaces.
32- Objects that are a Node, a CSSValue or a LayoutObject are allocated in one of the typed custom spaces.
33
34## Mode of operation
35
36- Blink uses concurrent garbage collection (marking and sweeping), except for during thread termination and heap destruction.
Michael Lippautz17bf72b2023-10-09 20:05:1837- Blink tries to schedule GCs through the message loop where it is known that no objects are referred to from the native stack.
38- When under memory pressure, Blink triggers a conservative GC on allocations.
Omer Katzfc07752082022-01-07 11:42:3539
40# Oilpan API reference
yutakd5604862015-10-19 10:26:4441
42## Base class templates
43
44### GarbageCollected
Omer Katzfc07752082022-01-07 11:42:3545<small>**Declared in:** `third_party/blink/renderer/platform/heap/garbage_collected.h`</small>
yutakd5604862015-10-19 10:26:4446
Omer Katzfc07752082022-01-07 11:42:3547A class that wants the lifetime of its instances to be managed by Oilpan must inherit from `GarbageCollected<T>`.
yutakd5604862015-10-19 10:26:4448
49```c++
50class YourClass : public GarbageCollected<YourClass> {
Mounir Lamouri17426a82019-01-11 14:08:5551 // ...
yutakd5604862015-10-19 10:26:4452};
53```
54
Michael Lippautz0173f0a52019-11-11 12:47:2555Instances of such classes are said to be *on Oilpan heap*, or *on heap* for short, while instances of other classes are called *off heap*.
Omer Katzfc07752082022-01-07 11:42:3556In the rest of this document, the terms *on heap*, *on-heap objects* or *garbage-collected objects* are used to mean the objects on Oilpan heap instead of on normal (default) dynamic allocator's heap space.
yutakd5604862015-10-19 10:26:4457
Omer Katzfc07752082022-01-07 11:42:3558Instances of a garbage-collected class can be created/allocated through `MakeGarbageCollected<T>`.
59Declaring a class as garbage collected disallows the use of `operator new`.
60It is not allowed to free garbage-collected object with `delete`, as Oilpan is responsible for deallocating the object once it determines the object is unreachable.
yutakd5604862015-10-19 10:26:4461
Omer Katzfc07752082022-01-07 11:42:3562Garbage-collected objects may not be allocated on stack. See [STACK_ALLOCATED](#STACK_ALLOCATED) and [Heap collections](#Heap-collections) for exceptions to this rule.
yutakd5604862015-10-19 10:26:4463
Omer Katzfc07752082022-01-07 11:42:3564Garbage-collected class may need to have a tracing method. See [Tracing](#Tracing) for details.
yutakd5604862015-10-19 10:26:4465
Omer Katzfc07752082022-01-07 11:42:3566Non-trivially destructible classes will be automatically finalized.
Omer Katzfdc3ad92019-11-20 16:19:4967Non-final classes that are not trivially destructible are required to have a virtual destructor.
Omer Katzfc07752082022-01-07 11:42:3568Trivially destructible classes should not have a destructor.
69Adding a destructor to such classes would make them non-trivially destructible and would hinder performance.
Anton Bikineeve18d8762019-09-10 15:43:0470Note that finalization is done at an arbitrary time after the object becomes unreachable.
Michael Lippautz0173f0a52019-11-11 12:47:2571Any destructor executed within the finalization period *must not* touch any other on-heap object because destructors can be executed in any order.
Anton Bikineeve18d8762019-09-10 15:43:0472
Michael Lippautz0173f0a52019-11-11 12:47:2573`GarbageCollected<T>` or any class deriving from `GarbageCollected<T>`, directly or indirectly, must be the first element in its base class list (called "leftmost derivation rule").
74This rule is needed to assure each on-heap object has its own canonical address.
yutakd5604862015-10-19 10:26:4475
76```c++
Michael Lippautz0173f0a52019-11-11 12:47:2577class A : public GarbageCollected<A>, public P {
78 // OK: GarbageCollected<A> is leftmost.
yutakd5604862015-10-19 10:26:4479};
80
Michael Lippautz0173f0a52019-11-11 12:47:2581class B : public A, public Q {
82 // OK: A is leftmost.
yutakd5604862015-10-19 10:26:4483};
84
Michael Lippautz0173f0a52019-11-11 12:47:2585// class C : public R, public A {
86// BAD: A must be the first base class.
Omer Katzfdc3ad92019-11-20 16:19:4987// If R is also garbage collected, A should be [GarbageCollectedMixin](#GarbageCollectedMixin).
yutakd5604862015-10-19 10:26:4488// };
89```
90
Omer Katzfc07752082022-01-07 11:42:3591If a non-leftmost base class needs to retain an on-heap object, that base class needs to inherit from [GarbageCollectedMixin](#GarbageCollectedMixin).
92It's generally recommended to make *any* non-leftmost base class inherit from `GarbageCollectedMixin` because it's dangerous to save a pointer to a non-leftmost non-`GarbageCollectedMixin` subclass of an on-heap object.
yutakd8f2cc22015-11-25 05:14:3293
Omer Katzfdc3ad92019-11-20 16:19:4994```c++
95P* raw_pointer;
96void someFunction(P* p) {
97 ...
98 raw_pointer = p;
99 ...
100}
101
102class A : public GarbageCollected<A>, public P {
103public:
104 void someMemberFunction()
105 {
106 someFunction(this); // DANGEROUS, a raw pointer to an on-heap object. Object might be collected, resulting in a dangling pointer and possible memory corruption.
107 }
108};
109```
110
yutakd5604862015-10-19 10:26:44111### GarbageCollectedMixin
Omer Katzfc07752082022-01-07 11:42:35112<small>**Declared in:** `third_party/blink/renderer/platform/heap/garbage_collected.h`</small>
yutakd5604862015-10-19 10:26:44113
Michael Lippautz0173f0a52019-11-11 12:47:25114A non-leftmost base class of a garbage-collected class should derive from `GarbageCollectedMixin`.
yutakd8f2cc22015-11-25 05:14:32115
Michael Lippautz0173f0a52019-11-11 12:47:25116A class deriving from `GarbageCollectedMixin` can be treated similarly as garbage-collected classes.
117Specifically, it can have `Member<T>`s and `WeakMember<T>`s, and a tracing method.
118A pointer to such a class must be retained in the same smart pointer wrappers as a pointer to a garbage-collected class, such as `Member<T>` or `Persistent<T>`.
Omer Katzfdc3ad92019-11-20 16:19:49119The [tracing](#Tracing) method of a garbage-collected class, if any, must contain a delegating call for each mixin base class.
yutakd8f2cc22015-11-25 05:14:32120
121```c++
122class P : public GarbageCollectedMixin {
Daniel Cheng0b5fcde2017-10-23 10:29:05123 public:
Michael Lippautz0173f0a52019-11-11 12:47:25124 // OK: Needs to trace q_.
Omer Katz052831f2020-05-17 03:54:06125 virtual void Trace(Visitor* visitor) const { visitor->Trace(q_); }
Daniel Cheng0b5fcde2017-10-23 10:29:05126 private:
Michael Lippautz0173f0a52019-11-11 12:47:25127 // OK: Allowed to have Member<T>.
Daniel Cheng0b5fcde2017-10-23 10:29:05128 Member<Q> q_;
yutakd8f2cc22015-11-25 05:14:32129};
130
Michael Lippautz0173f0a52019-11-11 12:47:25131class A final : public GarbageCollected<A>, public P {
Daniel Cheng0b5fcde2017-10-23 10:29:05132 public:
133 // Delegating call for P is needed.
Omer Katz052831f2020-05-17 03:54:06134 virtual void Trace(Visitor* visitor) const { P::Trace(visitor); }
yutakd8f2cc22015-11-25 05:14:32135};
136```
137
Omer Katzfc07752082022-01-07 11:42:35138A class that is a descendant of `GarbageCollectedMixin` but not a descendant of `GarbageCollected<T>` cannot be instantiated..
yutakd8f2cc22015-11-25 05:14:32139
140```c++
141class P : public GarbageCollectedMixin { };
142class Q : public GarbageCollectedMixin { };
143class R : public Q { };
144
145class A : public GarbageCollected<A>, public P, public R {
Michael Lippautz0173f0a52019-11-11 12:47:25146 // OK: Resolving pure virtual functions of P and R.
yutakd8f2cc22015-11-25 05:14:32147};
148
149class B : public GarbageCollected<B>, public P {
Michael Lippautz0173f0a52019-11-11 12:47:25150 // OK: Different garbage-collected classes may inherit from the same mixin (P).
yutakd8f2cc22015-11-25 05:14:32151};
152
Michael Lippautz0173f0a52019-11-11 12:47:25153void foo() {
154 MakeGarbageCollected<A>(); // OK: A can be instantiated.
155 // MakeGarbageCollected<R>(); // BAD: R has pure virtual functions.
yutakd8f2cc22015-11-25 05:14:32156}
157```
158
Michael Lippautz17bf72b2023-10-09 20:05:18159
yutakd5604862015-10-19 10:26:44160## Class properties
161
yutak8779f5542015-10-29 04:15:23162### USING_PRE_FINALIZER
Omer Katzfc07752082022-01-07 11:42:35163<small>**Declared in:** `third_party/blink/renderer/platform/heap/prefinalizer.h`</small>
yutak8779f5542015-10-29 04:15:23164
Michael Lippautz0173f0a52019-11-11 12:47:25165`USING_PRE_FINALIZER(ClassName, FunctionName)` in a class declaration declares the class has a *pre-finalizer* of name `FunctionName`.
Michael Lippautzc5eedf302019-07-11 09:13:41166A pre-finalizer must have the function signature `void()` but can have any name.
yutak8779f5542015-10-29 04:15:23167
Michael Lippautzc5eedf302019-07-11 09:13:41168A pre-finalizer is a user-defined member function of a garbage-collected class that is called when the object is going to be reclaimed.
169It is invoked before the sweeping phase starts to allow a pre-finalizer to touch any other on-heap objects which is forbidden from destructors.
170It is useful for doing cleanups that cannot be done with a destructor.
yutak8779f5542015-10-29 04:15:23171
172```c++
Anton Bikineeve18d8762019-09-10 15:43:04173class YourClass : public GarbageCollected<YourClass> {
Michael Lippautzc5eedf302019-07-11 09:13:41174 USING_PRE_FINALIZER(YourClass, Dispose);
yutak8779f5542015-10-29 04:15:23175public:
Michael Lippautzc5eedf302019-07-11 09:13:41176 void Dispose() {
177 // OK: Other on-heap objects can be touched in a pre-finalizer.
178 other_->Dispose();
Mounir Lamouri17426a82019-01-11 14:08:55179 }
Michael Lippautzc5eedf302019-07-11 09:13:41180
181 ~YourClass() {
182 // BAD: Not allowed.
183 // other_->Dispose();
Mounir Lamouri17426a82019-01-11 14:08:55184 }
yutak8779f5542015-10-29 04:15:23185
186private:
Mounir Lamouri17426a82019-01-11 14:08:55187 Member<OtherClass> other_;
yutak8779f5542015-10-29 04:15:23188};
189```
Michael Lippautzc5eedf302019-07-11 09:13:41190Sometimes it is necessary to further delegate pre-finalizers up the class hierarchy, similar to how destructors destruct in reverse order wrt. to construction.
191It is possible to construct such delegations using virtual methods.
yutak8779f5542015-10-29 04:15:23192
Michael Lippautzc5eedf302019-07-11 09:13:41193```c++
Anton Bikineeve18d8762019-09-10 15:43:04194class Parent : public GarbageCollected<Parent> {
Michael Lippautzc5eedf302019-07-11 09:13:41195 USING_PRE_FINALIZER(Parent, Dispose);
196 public:
197 void Dispose() { DisposeImpl(); }
198
199 virtual void DisposeImpl() {
200 // Pre-finalizer for {Parent}.
201 }
202 // ...
203};
204
205class Child : public Parent {
206 public:
207 void DisposeImpl() {
208 // Pre-finalizer for {Child}.
209 Parent::DisposeImpl();
210 }
211 // ...
212};
213```
214
Omer Katzfc07752082022-01-07 11:42:35215Alternatively, several classes in the same hierarchy may have pre-finalizers and these will also be executed in reverse order wrt. to construction.
216
217```c++
218class Parent : public GarbageCollected<Parent> {
219 USING_PRE_FINALIZER(Parent, Dispose);
220 public:
221 void Dispose() {
222 // Pre-finalizer for {Parent}.
223 }
224 // ...
225};
226
227class Child : public Parent {
228 USING_PRE_FINALIZER(Child, Dispose);
229 public:
230 void Dispose() {
231 // Pre-finalizer for {Child}.
232 }
233 // ...
234};
235```
236
Michael Lippautzc5eedf302019-07-11 09:13:41237*Notes*
Omer Katzfc07752082022-01-07 11:42:35238- Pre-finalizers are not allowed to resurrect objects (i.e. they are not allowed to relink dead objects into the object graph).
Michael Lippautzc5eedf302019-07-11 09:13:41239- Pre-finalizers have some implications on the garbage collector's performance: the garbage-collector needs to iterate all registered pre-finalizers at every GC.
240Therefore, a pre-finalizer should be avoided unless it is really necessary.
Omer Katzfc07752082022-01-07 11:42:35241Especially, avoid defining a pre-finalizer in a class that might be allocated a lot.
Keishi Hattorifde0d112017-10-03 07:31:03242
Michael Lippautzc5eedf302019-07-11 09:13:41243### DISALLOW_NEW
Omer Katzfc07752082022-01-07 11:42:35244<small>**Declared in:** `third_party/blink/renderer/platform/wtf/allocator/allocator.h`</small>
sigbjornf218c4082017-02-06 12:03:11245
Omer Katzfc07752082022-01-07 11:42:35246Class-level annotation declaring the class cannot be separately allocated using `operator new` or `MakeGarbageCollected<T>`.
247It can be used on stack, as an embedded part of some other object, or as a value in a heap collection.
248If the class has `Member<T>` references, it needs a `Trace()` method, which must be called by the embedding object (e.g. the collection or the object that this class is a part of).
sigbjornf218c4082017-02-06 12:03:11249
Keishi Hattorifde0d112017-10-03 07:31:03250Classes with this annotation need a `Trace()` method, but should not inherit a garbage collected class.
251
Omer Katzfc07752082022-01-07 11:42:35252### STACK_ALLOCATED
253<small>**Declared in:** `third_party/blink/renderer/platform/wtf/allocator/allocator.h`</small>
254
255Class level annotation that should be used if the class is only stack allocated.
256Any fields holding garbage-collected objects should use raw pointers or references.
257
258Classes with this annotation do not need to define a `Trace()` method as they are on the stack, and are automatically traced and kept alive should a conservative GC be required.
259
260Stack allocated classes must not inherit a on-heap garbage collected class.
261
262Marking a class as STACK_ALLOCATED implicitly implies [DISALLOW_NEW](#DISALLOW_NEW), and thus disallow the use of `operator new` and `MakeGarbageCollected<T>`.
sigbjornf218c4082017-02-06 12:03:11263
Michael Lippautz17bf72b2023-10-09 20:05:18264
yutakd5604862015-10-19 10:26:44265## Handles
266
Michael Lippautz17bf72b2023-10-09 20:05:18267Class templates in this section are smart pointers, each carrying a pointer to an on-heap object (think of `scoped_refptr<T>` for `RefCounted<T>`, or `std::unique_ptr`).
Omer Katzfc07752082022-01-07 11:42:35268Collectively, they are called *handles*.
yutakd5604862015-10-19 10:26:44269
yutak49a81802015-10-20 12:24:04270On-heap objects must be retained by any of these, depending on the situation.
yutakd5604862015-10-19 10:26:44271
Michael Lippautz17bf72b2023-10-09 20:05:18272### Raw pointers
273
274Using raw pointers to garbage-collected objects on-heap is forbidden and will yield in memory corruptions.
275On-stack references to garbage-collected object (including function parameters and return types), on the other hand, must use raw pointers.
276This is the only case where raw pointers to on-heap objects should be used.
277
278```c++
279void Foo() {
280 SomeGarbageCollectedClass* object = MakeGarbageCollected<SomeGarbageCollectedClass>(); // OK, retained by a raw pointer.
281 // ...
282}
283// OK to leave the object behind. The GC will reclaim it when it becomes unused.
284```
285
yutak49a81802015-10-20 12:24:04286### Member, WeakMember
Omer Katzfc07752082022-01-07 11:42:35287<small>**Declared in:** `third_party/blink/renderer/platform/heap/member.h`</small>
yutak49a81802015-10-20 12:24:04288
Michael Lippautz17bf72b2023-10-09 20:05:18289In a garbage-collected class, on-heap objects must be retained by `Member<T>` or `WeakMember<T>`, for strong or weak traced semantics, respectively.
290Both references may only refer to objects that are owned by the same thread.
yutak49a81802015-10-20 12:24:04291
Michael Lippautz17bf72b2023-10-09 20:05:18292`Member<T>` represents a *strong* reference to an object of type `T`, which means that the referred object is kept alive as long as the owner class instance is alive.
293Unlike `scoped_refptr<T>`, it is okay to form a reference cycle with members (in on-heap objects) and raw pointers (on stack).
yutak49a81802015-10-20 12:24:04294
Omer Katzfc07752082022-01-07 11:42:35295`WeakMember<T>` is a *weak* reference to an object of type `T`.
Michael Lippautz17bf72b2023-10-09 20:05:18296Unlike `Member<T>`, `WeakMember<T>` does not keep the pointed object alive.
Omer Katzfc07752082022-01-07 11:42:35297The pointer in a `WeakMember<T>` can become `nullptr` when the object gets garbage-collected.
Michael Lippautz17bf72b2023-10-09 20:05:18298It may take some time for the pointer in a `WeakMember<T>` to become `nullptr` after the object actually becomes unreachable, because this rewrite is only done within Oilpan's garbage collection cycle.
yutak49a81802015-10-20 12:24:04299
300```c++
Johann Koenig0ccf6422020-11-12 13:22:04301class SomeGarbageCollectedClass : public GarbageCollected<SomeGarbageCollectedClass> {
Mounir Lamouri17426a82019-01-11 14:08:55302 ...
yutak49a81802015-10-20 12:24:04303private:
Mounir Lamouri17426a82019-01-11 14:08:55304 Member<AnotherGarbageCollectedClass> another_; // OK, retained by Member<T>.
305 WeakMember<AnotherGarbageCollectedClass> anotherWeak_; // OK, weak reference.
yutak49a81802015-10-20 12:24:04306};
307```
Michael Lippautz17bf72b2023-10-09 20:05:18308It is required that every `Member<T>` and `WeakMember<T>` in a garbage-collected class be traced. See [Tracing](#Tracing).
yutak49a81802015-10-20 12:24:04309
Omer Katzfc07752082022-01-07 11:42:35310The use of `WeakMember<T>` incurs some overhead in garbage collector's performance.
311Use it sparingly.
312Usually, weak members are not necessary at all, because reference cycles with members are allowed.
yutak49a81802015-10-20 12:24:04313More specifically, `WeakMember<T>` should be used only if the owner of a weak member can outlive the pointed object.
314Otherwise, `Member<T>` should be used.
315
Michael Lippautz17bf72b2023-10-09 20:05:18316Generally `WeakMember<T>` requires to be converted into a strong reference to avoid reclamation until access.
317The following example uses a raw pointer to create a strong reference on stack.
318```c++
319void Foo(WeakMember<T>& weak_object) {
320 T* proxy = weak_object.Get(); // OK, proxy will keep weak_object alive.
321 if (proxy) {
322 GC();
323 proxy->Bar();
324 }
325}
326```
yutak49a81802015-10-20 12:24:04327
Omer Katzfdc3ad92019-11-20 16:19:49328### UntracedMember
Omer Katzfc07752082022-01-07 11:42:35329<small>**Declared in:** `third_party/blink/renderer/platform/heap/member.h`</small>
Omer Katzfdc3ad92019-11-20 16:19:49330
331`UntracedMember<T>` represents a reference to a garbage collected object which is ignored by Oilpan.
Michael Lippautz17bf72b2023-10-09 20:05:18332The reference may only refer to objects that are owned by the same thread.
Omer Katzfdc3ad92019-11-20 16:19:49333
Omer Katzfc07752082022-01-07 11:42:35334Unlike `Member<T>`, `UntracedMember<T>` will not keep an object alive.
335However, unlike `WeakMember<T>`, the reference will not be cleared (i.e. set to `nullptr`) if the referenced object dies.
Jacobo Aragunde Pérezb524e472021-05-27 13:21:13336Furthermore, class fields of type `UntracedMember<T>` should not be traced by the class' tracing method.
Omer Katzfdc3ad92019-11-20 16:19:49337
Omer Katzfc07752082022-01-07 11:42:35338Users should avoid using `UntracedMember<T>` in any case other than when implementing [custom weakness semantics](#Custom-weak-callbacks).
Omer Katzfdc3ad92019-11-20 16:19:49339
Michael Lippautz17bf72b2023-10-09 20:05:18340### Persistent, WeakPersistent
Omer Katzfc07752082022-01-07 11:42:35341<small>**Declared in:** `third_party/blink/renderer/platform/heap/persistent.h`</small>
yutak49a81802015-10-20 12:24:04342
Michael Lippautz17bf72b2023-10-09 20:05:18343In a non-garbage-collected class, on-heap objects must be retained by `Persistent<T>`, or `WeakPersistent<T>`.
344Both references may only refer to objects that are owned by the same thread.
yutak49a81802015-10-20 12:24:04345
346`Persistent<T>` is the most basic handle in the persistent family, which makes the referred object alive
347unconditionally, as long as the persistent handle is alive.
348
Omer Katzfc07752082022-01-07 11:42:35349`WeakPersistent<T>` does not keep the referred object alive, and becomes `nullptr` when the object gets
yutak49a81802015-10-20 12:24:04350garbage-collected, just like `WeakMember<T>`.
351
yutak49a81802015-10-20 12:24:04352```c++
Kent Tamuraecf8ccc2018-09-12 02:13:43353#include "third_party/blink/renderer/platform/heap/persistent.h"
354...
yutak49a81802015-10-20 12:24:04355class NonGarbageCollectedClass {
Mounir Lamouri17426a82019-01-11 14:08:55356 ...
yutak49a81802015-10-20 12:24:04357private:
Mounir Lamouri17426a82019-01-11 14:08:55358 Persistent<SomeGarbageCollectedClass> something_; // OK, the object will be alive while this persistent is alive.
yutak49a81802015-10-20 12:24:04359};
360```
361
Omer Katzfc07752082022-01-07 11:42:35362Persistents have a small unavoidable overhead because they require maintaining a list of all persistents.
363Therefore, creating or keeping a lot of persistents at once would have performance implications and should be avoided when possible.
yutak49a81802015-10-20 12:24:04364
Omer Katzfc07752082022-01-07 11:42:35365Weak variants have overhead just like `WeakMember<T>`.
366Use them sparingly.
yutak49a81802015-10-20 12:24:04367
Michael Lippautz17bf72b2023-10-09 20:05:18368***
369**Warning:** `Persistent<T>` is vulnerable to reference cycles.
370If a reference cycle is formed with `Persistent`s, `Member`s, `RefPtr`s and `OwnPtr`s, all the objects in the cycle **will leak**, since
371no object in the cycle can be aware of whether they are ever referred to from outside the cycle.
372
373Be careful not to create a reference cycle when adding a new persistent.
374If a cycle is inevitable, make sure the cycle is eventually cut and objects become reclaimable.
375***
376
377### CrossThreadPersistent, CrossThreadWeakPersistent
378<small>**Declared in:** `third_party/blink/renderer/platform/heap/cross_thread_persistent.h`</small>
379
380`CrossThreadPersistent<T>` and `CrossThreadWeakPersistent<T>` are cross-thread variants of `Persistent<T>` and
381`WeakPersistent<T>`, respectively, which can point to an object owned by a different thread (i.e. in a different heap).
382
383In general, Blink does not support shared-memory concurrency designs.
Omer Katzfc07752082022-01-07 11:42:35384The need of cross-thread persistents may indicate a poor design in multi-thread object ownership.
385Think twice if they are really necessary.
386
Michael Lippautz17bf72b2023-10-09 20:05:18387Similar to `Persistent<T>`, `CrossThreadPersistent<T>` is prone to creating cycles that results in memory leaks.
Omer Katzfc07752082022-01-07 11:42:35388
Michael Lippautz17bf72b2023-10-09 20:05:18389### CrossThreadHandle, CrossThreadWeakHandle
390<small>**Declared in:** `third_party/blink/renderer/platform/heap/cross_thread_handle.h`</small>
Omer Katzfc07752082022-01-07 11:42:35391
Michael Lippautz17bf72b2023-10-09 20:05:18392`CrossThreadHandle<T>` and `CrossThreadWeakHandle<T>` are cross-thread variants of `Persistent<T>` and
393`WeakPersistent<T>`, respectively, which can point to an object owned by a different thread (i.e. in a different heap).
394The difference to `CrossThreadPersistent<T>` is that these handles prohibit deref on any thread except the thread that owns the object pointed to.
395In other words, CrossThreadHandle<T> only support thread-safe copy, move, and destruction.
396
397The main use case for `CrossThreadHandle<T>` is delegating work to some other thread while retaining callbacks or other objects that are eventually used from the originating thread.
398
399Similar to `Persistent<T>`, `CrossThreadHandle<T>` is prone to creating cycles that results in memory leaks.
400
yutakd5604862015-10-19 10:26:44401
402## Tracing
403
Omer Katzfc07752082022-01-07 11:42:35404A garbage-collected class is required to have *a tracing method*, which lists all the references to on-heap objects it has.
Michael Lippautz0173f0a52019-11-11 12:47:25405The tracing method is called when the garbage collector needs to determine (1) all the on-heap objects referred from a
406live object, and (2) all the weak handles that may be filled with `nullptr` later.
yutak7f3d7d92015-10-26 11:20:49407
408The basic form of tracing is illustrated below:
409
410```c++
411// In a header file:
Michael Lippautz0173f0a52019-11-11 12:47:25412class SomeGarbageCollectedClass final
Daniel Cheng0b5fcde2017-10-23 10:29:05413 : public GarbageCollected<SomeGarbageCollectedClass> {
414 public:
Omer Katz052831f2020-05-17 03:54:06415 void Trace(Visitor*) const;
yutak7f3d7d92015-10-26 11:20:49416
417private:
Daniel Cheng0b5fcde2017-10-23 10:29:05418 Member<AnotherGarbageCollectedClass> another_;
yutak7f3d7d92015-10-26 11:20:49419};
420
421// In an implementation file:
Omer Katz052831f2020-05-17 03:54:06422void SomeGarbageCollectedClass::Trace(Visitor* visitor) const {
Daniel Cheng0b5fcde2017-10-23 10:29:05423 visitor->Trace(another_);
yutak7f3d7d92015-10-26 11:20:49424}
425```
426
Omer Katzfc07752082022-01-07 11:42:35427Specifically, if a class needs a tracing method, declaring and defining a `Trace(Visitor*) const` method is required.
Michael Lippautz0173f0a52019-11-11 12:47:25428This method is normally declared in the header file and defined once in the implementation file, but there are variations.
Omer Katzfc07752082022-01-07 11:42:35429A common variation is to declare a virtual `Trace()` for base classes that will be subclassed.
yutak7f3d7d92015-10-26 11:20:49430
431The function implementation must contain:
Omer Katzfc07752082022-01-07 11:42:35432- For each reference tp an on-heap object `object` in the class, a tracing call: `visitor->Trace(object);`.
433- For each embedded `DISALLOW_NEW` object `object` in the class, a tracing call: `visitor->Trace(object);`.
434- For each base class of the class `BaseClass` that is a descendant of `GarbageCollected<T>` or `GarbageCollectedMixin`, a delegation call to base class: `BaseClass::Trace(visitor)`.
yutak7f3d7d92015-10-26 11:20:49435It is recommended that the delegation call, if any, is put at the end of a tracing method.
Michael Lippautz0173f0a52019-11-11 12:47:25436- See [Advanced weak handling](#Advanced%20Weak%20Handling) for implementing non-trivial weakness.
yutak7f3d7d92015-10-26 11:20:49437
yutak7f3d7d92015-10-26 11:20:49438The following example shows more involved usage:
439
440```c++
441class A : public GarbageCollected<A> {
Daniel Cheng0b5fcde2017-10-23 10:29:05442 public:
Omer Katz052831f2020-05-17 03:54:06443 virtual void Trace(Visitor*) const {} // Nothing to trace here.
yutak7f3d7d92015-10-26 11:20:49444};
445
446class B : public A {
Daniel Cheng0b5fcde2017-10-23 10:29:05447 // Nothing to trace here; exempted from having a tracing method.
yutak7f3d7d92015-10-26 11:20:49448};
449
Michael Lippautz0173f0a52019-11-11 12:47:25450class C final : public B {
Daniel Cheng0b5fcde2017-10-23 10:29:05451 public:
Omer Katz052831f2020-05-17 03:54:06452 void Trace(Visitor*) const final;
yutak7f3d7d92015-10-26 11:20:49453
Daniel Cheng0b5fcde2017-10-23 10:29:05454 private:
455 Member<X> x_;
456 WeakMember<Y> y_;
457 HeapVector<Member<Z>> z_;
yutak7f3d7d92015-10-26 11:20:49458};
459
Omer Katz052831f2020-05-17 03:54:06460void C::Trace(Visitor* visitor) const {
Mounir Lamouri17426a82019-01-11 14:08:55461 visitor->Trace(x_);
462 visitor->Trace(y_); // Weak member needs to be traced.
463 visitor->Trace(z_); // Heap collection does, too.
464 B::Trace(visitor); // Delegate to the parent. In this case it's empty, but this is required.
yutak7f3d7d92015-10-26 11:20:49465}
466```
467
Omer Katza7566392022-04-06 18:15:20468Generally, a `Trace()` method would be just a sequence of delegations of the form `visitor->Trace(object);` for fields or `BaseClass::Trace(visitor)` for base classes.
469It should avoid more complex logic such as branches or iterations.
470In case a branch is unavoidable, the branch condition should depend only on const fields of the object.
471In case an iteration is unavoidable, the number of iterations and the location of the buffer that is iterated should also depend only on const fields of the object.
472Using non-const fields in `Trace()` methods may cause data races and other issues in the GC.
473
yutakd5604862015-10-19 10:26:44474## Heap collections
keishid4658a22016-12-05 03:28:46475
Michael Lippautz0173f0a52019-11-11 12:47:25476Oilpan, like any other managed runtime library, provides basic support for collections that integrate its managed types `Member<T>` and `WeakMember<T>`.
L. David Baron9379d0c82023-07-08 06:59:37477Do not use heap collection with persistent types (e.g. `HeapVector<Persistent<T>>`).
keishid4658a22016-12-05 03:28:46478
Michael Lippautz0173f0a52019-11-11 12:47:25479Collections compared to other libraries used in Blink:
keishid4658a22016-12-05 03:28:46480
Michael Lippautz0173f0a52019-11-11 12:47:25481| stdlib | WTF | Oilpan |
482| ------------------ | ------------------- | ------------------------- |
483| std::vector | WTF::Vector | blink::HeapVector |
484| std::deque | WTF::Deque | blink::HeapDeque |
485| std::unordered_map | WTF::HashMap | blink::HeapHashMap |
486| std::unordered_set | WTF::HashSet | blink::HeapHashSet |
487| - | WTF::LinkedHashSet | blink::HeapLinkedHashSet |
Michael Lippautz0173f0a52019-11-11 12:47:25488| - | WTF::HashCountedSet | blink::HeapHashCountedSet |
keishid4658a22016-12-05 03:28:46489
Michael Lippautz0173f0a52019-11-11 12:47:25490These heap collections work mostly the same way as their stdlib or WTF collection counterparts but there are some things to keep in mind.
Matthew Denton678f25f2021-07-21 14:05:31491Heap collections are regular heap objects and thus must be properly traced from a `Trace` method.
492They can also be inlined into other objects for performance reasons and are allowed to be directly used on stack.
keishid4658a22016-12-05 03:28:46493
494```c++
Michael Lippautz0173f0a52019-11-11 12:47:25495class A final : public GarbageCollected<A> {
Daniel Cheng0b5fcde2017-10-23 10:29:05496 public:
Omer Katz052831f2020-05-17 03:54:06497 void Trace(Visitor* visitor) const { visitor->Trace(vec_); }
Daniel Cheng0b5fcde2017-10-23 10:29:05498 private:
Michael Lippautz0173f0a52019-11-11 12:47:25499 HeapVector<Member<B>> vec_;
keishid4658a22016-12-05 03:28:46500};
501```
502
Michael Lippautz0173f0a52019-11-11 12:47:25503Like any other object, they may be referred to from a non-garbage-collected class using `Persistent`.
keishid4658a22016-12-05 03:28:46504
505```c++
Michael Lippautz0173f0a52019-11-11 12:47:25506class NonGCed final {
Daniel Cheng0b5fcde2017-10-23 10:29:05507 private:
Michael Lippautz0173f0a52019-11-11 12:47:25508 Persistent<HeapVector<Member<B>>> vec_;
keishid4658a22016-12-05 03:28:46509};
510```
511
Michael Lippautz0173f0a52019-11-11 12:47:25512## Advanced weak handling
Keishi Hattori15659fa2018-05-24 03:59:39513
Michael Lippautz0173f0a52019-11-11 12:47:25514In addition to basic weak handling using `WeakMember<T>` Oilpan also supports:
515- Weak collections
516- Custom weak callbacks
keishid4658a22016-12-05 03:28:46517
518### Weak collections
519
Michael Lippautz0173f0a52019-11-11 12:47:25520Like regular weakness, collections support weakness by putting references in `WeakMember<T>`.
keishid4658a22016-12-05 03:28:46521
Michael Lippautz0173f0a52019-11-11 12:47:25522In associative containers such as `HeapHashMap` or `HeapHashSet` Oilpan distinguishes between *pure weakness* and *mixed weakness*:
523- Pure weakness: All entries in such containers are wrapped in `WeakMember<T>`.
524 Examples are `HeapHashSet<WeakMember<T>>` and `HeapHashMap<WeakMember<T>, WeakMember<U>>`.
525- Mixed weakness: Only some entries in such containers are wrapped in `WeakMember<T>`.
526 This can only happen in `HeapHashMap`.
Omer Katzfdc3ad92019-11-20 16:19:49527 Examples are `HeapHashMap<WeakMember<T>, Member<U>>, HeapHashMap<Member<T>, WeakMember<U>>, HeapHashMap<WeakMember<T>, int>, and HeapHashMap<int, WeakMember<T>>.
Michael Lippautz0173f0a52019-11-11 12:47:25528 Note that in the last example the type `int` is traced even though it does not support tracing.
529
530The semantics then are as follows:
531- Pure weakness: Oilpan will automatically remove the entries from the container if any of its declared `WeakMember<T>` fields points to a dead object.
Michael Lippautz17bf72b2023-10-09 20:05:18532- Mixed weakness: Oilpan applies ephemeron semantics for mixed weakness with `WeakMember<T>` and `Member<T>`. Mixing `WeakMember<T>` with non-tracable types results in pure weakness treatment for the corresponding entry.
Michael Lippautz0173f0a52019-11-11 12:47:25533
Omer Katzfc07752082022-01-07 11:42:35534Weak references (e.g. `WeakMember<T>`) are not supported in sequential containers such as `HeapVector` or `HeapDeque`.
535
Michael Lippautz17bf72b2023-10-09 20:05:18536Iterators to weak collections keep their collections alive strongly.
537This allows for the GC to kick in during weak collection iteration.
538
539```c++
540template <typename Callback>
541void IterateAndCall(HeapHashMapM<WeakMember<T>, WeakMember<U>>* hash_map, Callback callback) {
542 for (auto pair& : *hash_map) {
543 callback(pair.first, pair.second); // OK, will invoke callback(WeakMember<T>, WeakMember<U>).
544 }
545}
546```
547
Michael Lippautz0173f0a52019-11-11 12:47:25548### Custom weak callbacks
549
550In case very specific weakness semantics are required Oilpan allows adding custom weakness callbacks through its tracing method.
551
552There exist two helper methods on `blink::Visitor` to add such callbacks:
Michael Lippautzf025c01d72020-04-21 09:47:20553- `RegisterWeakCallback`: Used to add custom weak callbacks of the form `void(void*, const blink::LivenessBroker&)`.
Michael Lippautz0173f0a52019-11-11 12:47:25554- `RegisterWeakCallbackMethod`: Helper for adding an instance method.
555
Omer Katzfdc3ad92019-11-20 16:19:49556Note that custom weak callbacks should not be used to clear `WeakMember<T>` fields as such fields are automatically handled by Oilpan.
557Instead, for managed fields that require custom weakness semantics, users should wrap such fields in `UntracedMember<T>` indicating that Oilpan is ignoring those fields.
Michael Lippautz0173f0a52019-11-11 12:47:25558
559The following example shows how this can be used:
560
561```c++
562
563class W final : public GarbageCollected<W> {
564 public:
Omer Katz052831f2020-05-17 03:54:06565 virtual void Trace(Visitor*) const;
Michael Lippautz0173f0a52019-11-11 12:47:25566 private:
Michael Lippautzf025c01d72020-04-21 09:47:20567 void ProcessCustomWeakness(const LivenessBroker&);
Michael Lippautz0173f0a52019-11-11 12:47:25568
569 UntracedMember<C> other_;
570};
571
Omer Katz052831f2020-05-17 03:54:06572void W::Trace(Visitor* visitor) const {
Michael Lippautz0173f0a52019-11-11 12:47:25573 visitor->template RegisterCustomWeakMethod<W, &W::ProcessCustomWeakness>(this);
574}
575
Michael Lippautzf025c01d72020-04-21 09:47:20576void W::ProcessCustomWeakness(const LivenessBroker& info) {
Michael Lippautz0173f0a52019-11-11 12:47:25577 if (info.IsHeapObjectAlive(other_)) {
578 // Do something with other_.
579 }
580 other_ = nullptr;
581}
582```
583
584Note that the custom weakness callback in this example is only executed if `W` is alive and properly traced.
585If `W` itself dies than the callback will not be executed.
586Operations that must always happen should instead go into destructors or pre-finalizers.
Raphael Kubo da Costa3146ed32018-01-15 15:34:07587
588## Traits helpers
Omer Katzfc07752082022-01-07 11:42:35589<small>**Declared in:** `third_party/blink/renderer/platform/heap/heap_traits.h`</small>
Raphael Kubo da Costa3146ed32018-01-15 15:34:07590
Michael Lippautz0173f0a52019-11-11 12:47:25591At times, one may be working on code that needs to deal with both, off heap and on heap, objects.
592The following helpers can aid in writing code that needs to use different wrappers and containers based on whether a type is managed by Oilpan.
Raphael Kubo da Costa3146ed32018-01-15 15:34:07593
594### AddMemberIfNeeded<T>
595
Michael Lippautz0173f0a52019-11-11 12:47:25596Given a type `T`, defines a type alias that is either `Member<T>` or `T` depending on whether `T` is a type managed by Oilpan.
Raphael Kubo da Costa3146ed32018-01-15 15:34:07597
598```c++
Michael Lippautz0173f0a52019-11-11 12:47:25599class A final : public GarbageCollected<A> {};
600class B final {};
Raphael Kubo da Costa3146ed32018-01-15 15:34:07601
Michael Lippautz0173f0a52019-11-11 12:47:25602AddMemberIfNeeded<B> v1; // B v1;
603AddMemberIfNeeded<int32_t> v2; // int32_t v2;
604AddMemberIfNeeded<A> v3; // Member<A> v3;
Raphael Kubo da Costa3146ed32018-01-15 15:34:07605```
606
607### VectorOf<T>
608
609Given a type `T`, defines a type alias that is either `HeapVector<T>`, `HeapVector<Member<T>>` or `Vector<T>` based on the following rules:
610
Omer Katzfc07752082022-01-07 11:42:35611* `T` is a garbage collected type managed by Oilpan → `HeapVector<Member<T>>`
612* `T` has a `Trace()` method but is not managed by Oilpan → `HeapVector<T>` (this is a rare case; IDL unions and dictionaries fall in this category, for example)
Raphael Kubo da Costa3146ed32018-01-15 15:34:07613* All other cases → `Vector<T>`
614
615```c++
616class MyGarbageCollectedClass : public GarbageCollected<MyGarbageCollectedClass> {
617 // ...
618};
619
620class MyNonGCButTraceableClass {
621 public:
Omer Katz052831f2020-05-17 03:54:06622 void Trace(Visitor* visitor) const {
Raphael Kubo da Costa3146ed32018-01-15 15:34:07623 // ...
624 }
625};
626
627class MyNotGarbageCollectedClass {
628 // ...
629};
630
631VectorOf<float> v1; // Vector<float> v1;
632VectorOf<MyNotGarbageCollectedClass> v2; // Vector<MyNotGarbageCollectedClass> v2;
633VectorOf<MyNonGCButTraceableClass> v3; // HeapVector<MyNonGCButTraceableClass> v3;
634VectorOf<MyGarbageCollectedClass> v4; // HeapVector<Member<MyGarbageCollectedClass>> v4;
635```
636
637### VectorOfPairs<T, U>
638
639Similar to `VectorOf<T>`, but defines a type alias that is either `HeapVector<std::pair<V, X>>` (where `V` is either `T` or `Member<T>` and `X` is either `U` or `Member<U>`) or `Vector<std::pair<T, U>>`.
640
Omer Katzfc07752082022-01-07 11:42:35641In other words, if either `T` or `U` needs to be wrapped in a `HeapVector` instead of a `Vector`, `VectorOfPairs` will use a `HeapVector<std::pair<>>` and wrap them with `Member<>` appropriately.
642Otherwise, a `Vector<std::pair<>>` will be used.
Raphael Kubo da Costa3146ed32018-01-15 15:34:07643
644```c++
645class MyGarbageCollectedClass : public GarbageCollected<MyGarbageCollectedClass> {
646 // ...
647};
648
649class MyNonGCButTraceableClass {
650 public:
Omer Katz052831f2020-05-17 03:54:06651 void Trace(Visitor* visitor) const {
Raphael Kubo da Costa3146ed32018-01-15 15:34:07652 // ...
653 }
654};
655
656class MyNotGarbageCollectedClass {
657 // ...
658};
659
660// Vector<std::pair<double, int8_t>> v1;
661VectorOfPairs<double, int8_t> v1;
662
663// Vector<std::pair<MyNotGarbageCollectedClass, String>> v2;
664VectorOfPairs<MyNotGarbageCollectedClass, String> v2;
665
666// HeapVector<std::pair<float, MyNonGCButTraceableClass>> v3;
667VectorOfPairs<float, MyNonGCButTraceableClass> v3;
668
669// HeapVector<std::pair<MyNonGCButTraceableClass, Member<MyGarbageCollectedClass>>> v4;
670VectorOfPairs<MyNonGCButTraceableClass, MyGarbageCollectedClass> v4;
671```