diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-08-28 15:28:34 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-08-28 13:54:51 +0000 |
commit | 2a19c63448c84c1805fb1a585c3651318bb86ca7 (patch) | |
tree | eb17888e8531aa6ee5e85721bd553b832a7e5156 /chromium/third_party/blink/renderer/platform/bindings/TraceWrapperReference.md | |
parent | b014812705fc80bff0a5c120dfcef88f349816dc (diff) | |
download | qtwebengine-chromium-2a19c63448c84c1805fb1a585c3651318bb86ca7.tar.gz |
BASELINE: Update Chromium to 69.0.3497.70
Change-Id: I2b7b56e4e7a8b26656930def0d4575dc32b900a0
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/third_party/blink/renderer/platform/bindings/TraceWrapperReference.md')
-rw-r--r-- | chromium/third_party/blink/renderer/platform/bindings/TraceWrapperReference.md | 176 |
1 files changed, 70 insertions, 106 deletions
diff --git a/chromium/third_party/blink/renderer/platform/bindings/TraceWrapperReference.md b/chromium/third_party/blink/renderer/platform/bindings/TraceWrapperReference.md index 23adab6a7ab..d8b0b2c2aac 100644 --- a/chromium/third_party/blink/renderer/platform/bindings/TraceWrapperReference.md +++ b/chromium/third_party/blink/renderer/platform/bindings/TraceWrapperReference.md @@ -1,52 +1,45 @@ # Wrapper Tracing Reference This document describes wrapper tracing and how its API is supposed to be used. +Note that wrapper tracing is based on Oilpan garbage collection infrastructure, which makes [Oilpan's documentation][oilpan-docs] a good first read. [TOC] ## Quickstart guide -Wrapper tracing is used to represent reachability across V8 and Blink. The -following checklist highlights the modifications needed to make a class -participate in wrapper tracing. - -1. Make sure that objects participating in tracing either inherit from -`ScriptWrappable` (if they can reference wrappers) or `TraceWrapperBase` -(transitively holding wrappers alive). -2. Use `TraceWrapperMember<T>` to annotate fields that need to be followed to -find other wrappers that this object should keep alive. -3. Use `TraceWrapperV8Reference<T>` to annotate references to V8 that this -object should keep alive. -4. Declare a `virtual void TraceWrappers(ScriptWrappableVisitor*) const` -method to trace other wrappers. -5. Define the method and trace all fields that received a wrapper tracing type -in (1) and (2) using `visitor->TraceWrappers(<field_>)` in the body. +Wrapper tracing is used to represent reachability across V8 and Blink. +The following checklist highlights the modifications needed to make a class participate in wrapper tracing. + +1. Make sure that objects participating in tracing either inherit from `ScriptWrappable` if they can reference wrappers or are otherwise part of Oilpan's heap, e.g. by making them inherit from `GarbageCollected` or one of its friends. +2. Use `TraceWrapperMember<T>` to annotate fields that need to be followed to find other wrappers that this object should keep alive. +3. Use `TraceWrapperV8Reference<T>` to annotate references to V8 that this object should keep alive. +4. Make sure those fields are properly visited from `T::Trace`, similar to all other garbage collected types. The following example illustrates these steps: ```c++ -#include "platform/bindings/ScriptWrappable.h" -#include "platform/bindings/TraceWrapperMember.h" -#include "platform/bindings/TraceWrapperV8Reference.h" +#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" +#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h" +#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h" class SomeDOMObject : public ScriptWrappable { // (1) DEFINE_WRAPPERTYPEINFO(); public: - virtual void TraceWrappers( - ScriptWrappableVisitor*) const; // (4) + void Trace(Visitor*) override; private: - TraceWrapperMember<OtherWrappable> other_wrappable_; // (2) Member<NonWrappable> non_wrappable_; + TraceWrapperMember<OtherWrappable> other_wrappable_; // (2) TraceWrapperV8Reference<v8::Value> v8object_; // (3) // ... }; -void SomeDOMObject::TraceWrappers( - ScriptWrappableVisitor* visitor) const { // (5) - visitor->TraceWrappers(other_wrappable_); // (5) - visitor->TraceWrappers(v8object_); // (5) +void SomeDOMObject::Trace(Visitor* visitor) { + visitor->Trace(non_wrappable_); + visitor->Trace(other_wrappable_); // (4) + visitor->Trace(v8object_); // (4) + ScriptWrappable::Trace(visitor); } ``` @@ -54,26 +47,19 @@ For more in-depth information and how to deal with corner cases continue on read ## Background -Blink and V8 need to cooperate to collect JavaScript *wrappers*. Each V8 -*wrapper* object (*W*) in JavaScript is assigned a C++ *DOM object* (*D*) in -Blink. A single C++ *DOM object* can hold onto one or many *wrapper* objects. -During a garbage collection initiated from JavaScript, a *wrapper* then keeps -the C++ *DOM object* and all its transitive dependencies, including other -*wrappers*, alive, effectively tracing paths like -*W<sub>x</sub> -> D<sub>1</sub> -> ⋯ -> D<sub>n</sub> -> W<sub>y</sub>*. +Blink and V8 need to cooperate to collect JavaScript *wrappers*. +Each V8 *wrapper* object (*W*) in JavaScript is assigned a C++ *DOM object* (*D*) in Blink. +A single C++ *DOM object* can hold onto one or many *wrapper* objects. +During a garbage collection initiated from JavaScript, a *wrapper* then keeps the C++ *DOM object* and all its transitive dependencies, including other *wrappers*, alive, effectively tracing paths like *W<sub>x</sub> -> D<sub>1</sub> -> ⋯ -> D<sub>n</sub> -> W<sub>y</sub>*. -Previously, this relationship was expressed using so-called object groups, -effectively assigning all C++ *DOM objects* in a given DOM tree the same group. -The group would only die if all objects belonging to the same group die. A brief -introduction on the limitations on this approach can be found in -[this slide deck][object-grouping-slides]. +Previously, this relationship was expressed using so-called object groups, effectively assigning all C++ *DOM objects* in a given DOM tree the same group. +The group would only die if all objects belonging to the same group die. +A brief introduction on the limitations on this approach can be found in [this slide deck][object-grouping-slides]. -Wrapper tracing solves this problem by determining liveness based on -reachability by tracing through the C++ *DOM objects*. The rest of this document -describes how the API is used to keep JavaScript wrapper objects alive. +Wrapper tracing solves this problem by determining liveness based on reachability by tracing through the C++ *DOM objects*. +The rest of this document describes how the API is used to keep JavaScript wrapper objects alive. -Note that *wrappables* have to be *on-heap objects* and thus all -[Oilpan-related rules][oilpan-docs] apply. +Note that *wrappables* have to be part of Oilpan and thus all [Oilpan-related rules][oilpan-docs] apply. [object-grouping-slides]: https://docs.google.com/presentation/d/1I6leiRm0ysSTqy7QWh33Gfp7_y4ngygyM2tDAqdF0fI/ [oilpan-docs]: https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/platform/heap/BlinkGCAPIReference.md @@ -88,108 +74,99 @@ Pick the header file depending on what types are needed. #include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h" ``` -The following example will guide through the modifications that are needed to -adjust a given class `SomeDOMObject` to participate in wrapper tracing. +The following example will guide through the modifications that are needed to adjust a given class `SomeDOMObject` to participate in wrapper tracing. ```c++ class SomeDOMObject : public ScriptWrappable { DEFINE_WRAPPERTYPEINFO(); // ... + private: Member<OtherWrappable /* extending ScriptWrappable */> other_wrappable_; Member<NonWrappable> non_wrappable_; }; ``` -In this scenario `SomeDOMObject` is the object that is wrapped by an object on -the JavaScript side. The next step is to identify the paths that lead to other -wrappables. In this case, only `other_wrappable_` needs to be traced to find -other *wrappers* in V8. +In this scenario `SomeDOMObject` is the object that is wrapped by an object on the JavaScript side. +The next step is to identify the paths that lead to other wrappables. +In this case, only `other_wrappable_` needs to be traced to find other *wrappers* in V8. ```c++ class SomeDOMObject : public ScriptWrappable { DEFINE_WRAPPERTYPEINFO(); public: - virtual void TraceWrappers(ScriptWrappableVisitor*) const; + void Trace(Visitor*) override; private: Member<OtherWrappable> other_wrappable_; Member<NonWrappable> non_wrappable_; }; -void SomeDOMObject::TraceWrappers( - ScriptWrappableVisitor* visitor) const { - visitor->TraceWrappers(other_wrappable_); +void SomeDOMObject::Trace(Visitor* visitor) { + visitor->Trace(other_wrappable_); + visitor->Trace(non_wrappable_); + ScriptWrappable::Trace(visitor); } ``` +Blink and V8 implement *incremental* wrapper tracing, which means that marking can be interleaved with JavaScript or even DOM operations. +This poses a challenge, because already marked objects will not be considered again if they are reached through some other path. -Blink and V8 implement *incremental* wrapper tracing, which means that marking -can be interleaved with JavaScript or even DOM operations. This poses a -challenge, because already marked objects will not be considered again if they -are reached through some other path. - -For example, consider an object `A` that has already been marked and a write -to a field `A.x` setting `x` to an unmarked object `Y`. Since `A.x` is -the only reference keeping `Y`, and `A` has already been marked, the garbage -collector will not find `Y` and reclaim it. +For example, consider an object `A` that has already been marked and a write to a field `A.x` setting `x` to an unmarked object `Y`. +Since `A.x` is the only reference keeping `Y`, and `A` has already been marked, the garbage collector will not find `Y` and reclaim it. -To overcome this problem we require all writes of interesting objects, i.e., -writes to traced fields, to go through a write barrier. -The write barrier will check for the problem case above and make sure -`Y` will be marked. In order to automatically issue a write barrier -`other_wrappable_` needs `TraceWrapperMember` type. +To overcome this problem we require all writes of interesting objects, i.e., writes to traced fields, to go through a write barrier. +The write barrier will check for the problem case above and make sure `Y` will be marked. +In order to automatically issue a write barrier `other_wrappable_` needs `TraceWrapperMember` type. ```c++ class SomeDOMObject : public ScriptWrappable { DEFINE_WRAPPERTYPEINFO(); public: - virtual void TraceWrappers(ScriptWrappableVisitor*) const; + void Trace(Visitor*) override; private: TraceWrapperMember<OtherWrappable> other_wrappable_; Member<NonWrappable> non_wrappable_; }; -void SomeDOMObject::TraceWrappers( - ScriptWrappableVisitor* visitor) const { - visitor->TraceWrappers(other_wrappable_); +void SomeDOMObject::Trace(Visitor* visitor) { + visitor->Trace(other_wrappable_); + visitor->Trace(non_wrappable_); + ScriptWrappable::Trace(visitor); } ``` -`TraceWrapperMember` makes sure that any write to `other_wrappable_` will -consider doing a write barrier. Using the proper type, the write barrier is -correct by construction, i.e., it will never be missed. +`TraceWrapperMember` makes sure that any write to `other_wrappable_` will consider doing a write barrier. +Using the proper type, the write barrier is correct by construction, i.e., it will never be missed. ## Heap collections -The proper type usage for collections, e.g. `HeapVector` looks like the -following. +Wrapper tracing is integrated into Oilpan's support for collections, so there's no additional work needed other than making sure the collection is visited in the corresponding `Trace` method. +The proper type usage for collections, e.g. `HeapVector` looks like the following. ```c++ class SomeDOMObject : public ScriptWrappable { DEFINE_WRAPPERTYPEINFO(); public: - // ... + void Trace(Visitor*) override; + void AppendNewValue(OtherWrappable* newValue); - virtual void TraceWrappers(ScriptWrappableVisitor*) const; private: HeapVector<TraceWrapperMember<OtherWrappable>> other_wrappables_; }; -void SomeDOMObject::TraceWrappers( - ScriptWrappableVisitor* visitor) const { - for (auto other : other_wrappables_) - visitor->TraceWrappers(other); +void SomeDOMObject::Trace(Visitor* visitor) { + visitor->Trace(other_wrappables_); + ScriptWrappable::Trace(visitor); } ``` -Note that this is different to Oilpan which can just trace the whole collection. `TraceWrapperMember` can be constructed in place, so using `append` and friends will work out of the box, e.g. @@ -199,9 +176,6 @@ void SomeDOMObject::AppendNewValue(OtherWrappable* newValue) { } ``` -The compiler will throw an error for each omitted `TraceWrapperMember` -construction. - ### Swapping `HeapVector` containing `TraceWrapperMember` and `Member` It is possible to swap two `HeapVectors` containing `TraceWrapperMember` and @@ -222,44 +196,34 @@ blink::swap(c, temporary); ## Tracing through non-`ScriptWrappable` types -Sometimes it is necessary to trace through types that do not inherit from -`ScriptWrappable`. For example, consider the object graph -`A -> B -> C` where both `A` and `C` are `ScriptWrappable`s that -need to be traced. +Sometimes it is necessary to trace through types that do not inherit from `ScriptWrappable`. +For example, consider the object graph `A -> B -> C` where both `A` and `C` are `ScriptWrappable`s that need to be traced. -In this case, the same rules as with `ScriptWrappables` apply, except for the -difference that these classes need to inherit from `TraceWrapperBase`. - -### Memory-footprint critical uses - -In the case we cannot afford inheriting from `TraceWrapperBase`, which will -add a vtable pointer for tracing wrappers, use -`DEFINE_TRAIT_FOR_TRACE_WRAPPERS(ClassName)` after defining -`ClassName` to define the proper tracing specializations. +In this case, the same rules as with `ScriptWrappables` apply, except for the difference that these classes need to inherit from some other class that is managed by Oilpan, e.g. `GarbageCollected`. ## Explicit write barriers -Sometimes it is necessary to stick with the regular types and issue the write -barriers explicitly. In this case, tracing needs to be adjusted to tell the -system that all barriers will be done manually. +Sometimes it is necessary to stick with the regular types or raw pointers and issue the write barriers explicitly. +In this case, tracing needs to be adjusted to tell the system that all barriers will be done manually. ```c++ class ManualWrappable : public ScriptWrappable { DEFINE_WRAPPERTYPEINFO(); public: - void setNew(OtherWrappable* newValue) { + void Trace(Visitor*) override; + + void SetNew(OtherWrappable* newValue) { other_wrappable_ = newValue; SriptWrappableVisitor::WriteBarrier(other_wrappable_); } - virtual void TraceWrappers(ScriptWrappableVisitor*) const; private: Member<OtherWrappable>> other_wrappable_; }; -void ManualWrappable::TraceWrappers( - ScriptWrappableVisitor* visitor) const { - visitor->TraceWrappersWithManualWriteBarrier(other_wrappable_); +void ManualWrappable::Trace(Visitor* visitor) { + visitor->TraceWithWrappers(other_wrappable_.Get()); + ScriptWrappable::Trace(visitor); } ``` |