Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Wrapper Tracing Reference | 1 # Wrapper Tracing Reference |
| 2 | 2 |
| 3 This document describes wrapper tracing and how its API is supposed to be used. | 3 This document describes wrapper tracing and how its API is supposed to be used. |
| 4 | 4 |
| 5 [TOC] | 5 [TOC] |
| 6 | 6 |
| 7 ## Quickstart guide | 7 ## Quickstart guide |
| 8 | 8 |
| 9 Wrapper tracing is used to represent reachability across V8 and Blink. The | 9 Wrapper tracing is used to represent reachability across V8 and Blink. The |
| 10 following checklist highlights the modifications needed to make a class | 10 following checklist highlights the modifications needed to make a class |
| 11 participate in wrapper tracing. | 11 participate in wrapper tracing. |
| 12 | 12 |
| 13 1. Make sure that objects participating in tracing either inherit from | 13 1. Make sure that objects participating in tracing either inherit from |
| 14 ``ScriptWrappable`` (if they can reference wrappers) or ``TraceWrapperBase`` | 14 ``ScriptWrappable`` (if they can reference wrappers) or ``TraceWrapperBase`` |
| 15 (transitively holding wrappers alive). | 15 (transitively holding wrappers alive). |
| 16 2. Use ``TraceWrapperMember<T>`` to annotate fields that need to be followed to | 16 2. Use ``TraceWrapperMember<T>`` to annotate fields that need to be followed to |
| 17 find other wrappers that this object should keep alive. | 17 find other wrappers that this object should keep alive. |
| 18 3. Use ``TraceWrapperV8Reference<T>`` to annotate references to V8 that this | 18 3. Use ``TraceWrapperV8Reference<T>`` to annotate references to V8 that this |
| 19 object should keep alive. | 19 object should keep alive. |
| 20 4. Declare a method to trace other wrappers using | 20 4. Declare a method to trace other wrappers using |
| 21 ``DECLARE_VIRTUAL_TRACE_WRAPPERS()``. | 21 ``DECLARE_VIRTUAL_TRACE_WRAPPERS()``. |
| 22 5. Define the method using ``DEFINE_TRACE_WRAPPERS(ClassName)``. | 22 5. Define the method using ``DEFINE_TRACE_WRAPPERS(ClassName)``. |
| 23 6. Trace all fields that received a wrapper tracing type in (1) and (2) using | 23 6. Trace all fields that received a wrapper tracing type in (1) and (2) using |
| 24 ``visitor->traceWrapers(<m_field>)`` in the body of ``DEFINE_TRACE_WRAPPERS``. | 24 ``visitor->TraceWrappers(<m_field>)`` in the body of ``DEFINE_TRACE_WRAPPERS``. |
|
Michael Lippautz
2017/04/19 08:49:12
Oh boy :)
Thanks, we could also do this in a sepa
| |
| 25 | 25 |
| 26 The following example illustrates these steps: | 26 The following example illustrates these steps: |
| 27 | 27 |
| 28 ```c++ | 28 ```c++ |
| 29 #include "bindings/core/v8/ScriptWrappable.h" | 29 #include "bindings/core/v8/ScriptWrappable.h" |
| 30 #include "bindings/core/v8/TraceWrapperMember.h" | 30 #include "bindings/core/v8/TraceWrapperMember.h" |
| 31 #include "bindings/core/v8/TraceWrapperV8Reference.h" | 31 #include "bindings/core/v8/TraceWrapperV8Reference.h" |
| 32 | 32 |
| 33 class SomeDOMObject : public ScriptWrappable { // (1) | 33 class SomeDOMObject : public ScriptWrappable { // (1) |
| 34 public: | 34 public: |
| 35 DECLARE_VIRTUAL_TRACE_WRAPPERS(); // (4) | 35 DECLARE_VIRTUAL_TRACE_WRAPPERS(); // (4) |
| 36 | 36 |
| 37 private: | 37 private: |
| 38 TraceWrapperMember<OtherWrappable> m_otherWrappable; // (2) | 38 TraceWrapperMember<OtherWrappable> m_otherWrappable; // (2) |
| 39 Member<NonWrappable> m_nonWrappable; | 39 Member<NonWrappable> m_nonWrappable; |
| 40 TraceWrapperV8Reference<v8::Value> m_v8object; // (3) | 40 TraceWrapperV8Reference<v8::Value> m_v8object; // (3) |
| 41 // ... | 41 // ... |
| 42 }; | 42 }; |
| 43 | 43 |
| 44 DEFINE_TRACE_WRAPPERS(SomeDOMObject) { // (5) | 44 DEFINE_TRACE_WRAPPERS(SomeDOMObject) { // (5) |
| 45 visitor->traceWrappers(m_otherWrappable); // (6) | 45 visitor->TraceWrappers(m_otherWrappable); // (6) |
| 46 visitor->traceWrappers(m_v8object); // (6) | 46 visitor->TraceWrappers(m_v8object); // (6) |
| 47 } | 47 } |
| 48 ``` | 48 ``` |
| 49 | 49 |
| 50 For more in-depth information and how to deal with corner cases continue on read ing. | 50 For more in-depth information and how to deal with corner cases continue on read ing. |
| 51 | 51 |
| 52 ## Background | 52 ## Background |
| 53 | 53 |
| 54 Blink and V8 need to cooperate to collect JavaScript *wrappers*. Each V8 | 54 Blink and V8 need to cooperate to collect JavaScript *wrappers*. Each V8 |
| 55 *wrapper* object (*W*) in JavaScript is assigned a C++ *DOM object* (*D*) in | 55 *wrapper* object (*W*) in JavaScript is assigned a C++ *DOM object* (*D*) in |
| 56 Blink. A single C++ *DOM object* can hold onto one or many *wrapper* objects. | 56 Blink. A single C++ *DOM object* can hold onto one or many *wrapper* objects. |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 75 [object-grouping-slides]: https://docs.google.com/presentation/d/1I6leiRm0ysSTqy 7QWh33Gfp7_y4ngygyM2tDAqdF0fI/ | 75 [object-grouping-slides]: https://docs.google.com/presentation/d/1I6leiRm0ysSTqy 7QWh33Gfp7_y4ngygyM2tDAqdF0fI/ |
| 76 [oilpan-docs]: https://chromium.googlesource.com/chromium/src/+/master/third_par ty/WebKit/Source/platform/heap/BlinkGCAPIReference.md | 76 [oilpan-docs]: https://chromium.googlesource.com/chromium/src/+/master/third_par ty/WebKit/Source/platform/heap/BlinkGCAPIReference.md |
| 77 | 77 |
| 78 ## Basic usage | 78 ## Basic usage |
| 79 | 79 |
| 80 The annotations that are required can be found in the following header files. | 80 The annotations that are required can be found in the following header files. |
| 81 Pick the header file depending on what types are needed. | 81 Pick the header file depending on what types are needed. |
| 82 | 82 |
| 83 ```c++ | 83 ```c++ |
| 84 #include "bindings/core/v8/ScriptWrappable.h" | 84 #include "bindings/core/v8/ScriptWrappable.h" |
| 85 #include "bindings/core/v8/TraceWrapperBase.h" | |
| 86 #include "bindings/core/v8/TraceWrapperMember.h" | 85 #include "bindings/core/v8/TraceWrapperMember.h" |
| 87 #include "bindings/core/v8/TraceWrapperV8Reference.h" | 86 #include "bindings/core/v8/TraceWrapperV8Reference.h" |
| 88 ``` | 87 ``` |
| 89 | 88 |
| 90 The following example will guide through the modifications that are needed to | 89 The following example will guide through the modifications that are needed to |
| 91 adjust a given class ``SomeDOMObject`` to participate in wrapper tracing. | 90 adjust a given class ``SomeDOMObject`` to participate in wrapper tracing. |
| 92 | 91 |
| 93 ```c++ | 92 ```c++ |
| 94 class SomeDOMObject : public ScriptWrappable { | 93 class SomeDOMObject : public ScriptWrappable { |
| 95 // ... | 94 // ... |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 119 class SomeDOMObject : public ScriptWrappable { | 118 class SomeDOMObject : public ScriptWrappable { |
| 120 public: | 119 public: |
| 121 DECLARE_VIRTUAL_TRACE_WRAPPERS(); | 120 DECLARE_VIRTUAL_TRACE_WRAPPERS(); |
| 122 | 121 |
| 123 private: | 122 private: |
| 124 Member<OtherWrappable> m_otherWrappable; | 123 Member<OtherWrappable> m_otherWrappable; |
| 125 Member<NonWrappable> m_nonWrappable; | 124 Member<NonWrappable> m_nonWrappable; |
| 126 }; | 125 }; |
| 127 | 126 |
| 128 DEFINE_TRACE_WRAPPERS(SomeDOMObject) { | 127 DEFINE_TRACE_WRAPPERS(SomeDOMObject) { |
| 129 visitor->traceWrappers(m_otherWrappable); | 128 visitor->TraceWrappers(m_otherWrappable); |
| 130 } | 129 } |
| 131 ``` | 130 ``` |
| 132 | 131 |
| 133 | 132 |
| 134 Blink and V8 implement *incremental* wrapper tracing, which means that marking | 133 Blink and V8 implement *incremental* wrapper tracing, which means that marking |
| 135 can be interleaved with JavaScript or even DOM operations. This poses a | 134 can be interleaved with JavaScript or even DOM operations. This poses a |
| 136 challenge, because already marked objects will not be considered again if they | 135 challenge, because already marked objects will not be considered again if they |
| 137 are reached through some other path. | 136 are reached through some other path. |
| 138 | 137 |
| 139 For example, consider an object ``A`` that has already been marked and a write | 138 For example, consider an object ``A`` that has already been marked and a write |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 152 public: | 151 public: |
| 153 SomeDOMObject() : m_otherWrappable(this, nullptr) {} | 152 SomeDOMObject() : m_otherWrappable(this, nullptr) {} |
| 154 DECLARE_VIRTUAL_TRACE_WRAPPERS(); | 153 DECLARE_VIRTUAL_TRACE_WRAPPERS(); |
| 155 | 154 |
| 156 private: | 155 private: |
| 157 TraceWrapperMember<OtherWrappable> m_otherWrappable; | 156 TraceWrapperMember<OtherWrappable> m_otherWrappable; |
| 158 Member<NonWrappable> m_nonWrappable; | 157 Member<NonWrappable> m_nonWrappable; |
| 159 }; | 158 }; |
| 160 | 159 |
| 161 DEFINE_TRACE_WRAPPERS(SomeDOMObject) { | 160 DEFINE_TRACE_WRAPPERS(SomeDOMObject) { |
| 162 visitor->traceWrappers(m_otherWrappable); | 161 visitor->TraceWrappers(m_otherWrappable); |
| 163 } | 162 } |
| 164 ``` | 163 ``` |
| 165 | 164 |
| 166 ``TraceWrapperMember`` makes sure that any write to ``m_otherWrappable`` will | 165 ``TraceWrapperMember`` makes sure that any write to ``m_otherWrappable`` will |
| 167 consider doing a write barrier. Using the proper type, the write barrier is | 166 consider doing a write barrier. Using the proper type, the write barrier is |
| 168 correct by construction, i.e., it will never be missed. | 167 correct by construction, i.e., it will never be missed. |
| 169 | 168 |
| 170 ## Heap collections | 169 ## Heap collections |
| 171 | 170 |
| 172 The proper type usage for collections, e.g. ``HeapVector`` looks like the | 171 The proper type usage for collections, e.g. ``HeapVector`` looks like the |
| 173 following. | 172 following. |
| 174 | 173 |
| 175 ```c++ | 174 ```c++ |
| 176 class SomeDOMObject : public ScriptWrappable { | 175 class SomeDOMObject : public ScriptWrappable { |
| 177 public: | 176 public: |
| 178 // ... | 177 // ... |
| 179 void AppendNewValue(OtherWrappable* newValue); | 178 void AppendNewValue(OtherWrappable* newValue); |
| 180 DECLARE_VIRTUAL_TRACE_WRAPPERS(); | 179 DECLARE_VIRTUAL_TRACE_WRAPPERS(); |
| 181 | 180 |
| 182 private: | 181 private: |
| 183 HeapVector<TraceWrapperMember<OtherWrappable>> m_otherWrappables; | 182 HeapVector<TraceWrapperMember<OtherWrappable>> m_otherWrappables; |
| 184 }; | 183 }; |
| 185 | 184 |
| 186 DEFINE_TRACE_WRAPPERS(SomeDOMObject) { | 185 DEFINE_TRACE_WRAPPERS(SomeDOMObject) { |
| 187 for (auto other : m_otherWrappables) | 186 for (auto other : m_otherWrappables) |
| 188 visitor->traceWrappers(other); | 187 visitor->TraceWrappers(other); |
| 189 } | 188 } |
| 190 ``` | 189 ``` |
| 191 | 190 |
| 192 Note that this is different to Oilpan which can just trace the whole collection. | 191 Note that this is different to Oilpan which can just trace the whole collection. |
| 193 Whenever an element is added through ``append()`` the value needs to be | 192 Whenever an element is added through ``append()`` the value needs to be |
| 194 constructed using ``TraceWrapperMember``, e.g. | 193 constructed using ``TraceWrapperMember``, e.g. |
| 195 | 194 |
| 196 ```c++ | 195 ```c++ |
| 197 void SomeDOMObject::AppendNewValue(OtherWrappable* newValue) { | 196 void SomeDOMObject::AppendNewValue(OtherWrappable* newValue) { |
| 198 m_otherWrappables.append(TraceWrapperMember(this, newValue)); | 197 m_otherWrappables.append(TraceWrapperMember(this, newValue)); |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 219 m_otherWrappables[i] = other; | 218 m_otherWrappables[i] = other; |
| 220 } | 219 } |
| 221 | 220 |
| 222 DECLARE_VIRTUAL_TRACE_WRAPPERS(); | 221 DECLARE_VIRTUAL_TRACE_WRAPPERS(); |
| 223 private: | 222 private: |
| 224 HeapVector<TraceWrapperMember<OtherWrappable>> m_otherWrappables; | 223 HeapVector<TraceWrapperMember<OtherWrappable>> m_otherWrappables; |
| 225 }; | 224 }; |
| 226 | 225 |
| 227 DEFINE_TRACE_WRAPPERS(SomeDOMObject) { | 226 DEFINE_TRACE_WRAPPERS(SomeDOMObject) { |
| 228 for (auto other : m_otherWrappables) | 227 for (auto other : m_otherWrappables) |
| 229 visitor->traceWrappers(other); | 228 visitor->TraceWrappers(other); |
| 230 } | 229 } |
| 231 ``` | 230 ``` |
| 232 | 231 |
| 233 In this example, the compiler will not warn you on | 232 In this example, the compiler will not warn you on |
| 234 ``m_otherWrappables[i] = other``, but an assertion will throw at runtime as long | 233 ``m_otherWrappables[i] = other``, but an assertion will throw at runtime as long |
| 235 as there exists a test covering that branch. | 234 as there exists a test covering that branch. |
| 236 | 235 |
| 237 The correct assignment looks like | 236 The correct assignment looks like |
| 238 | 237 |
| 239 ```c++ | 238 ```c++ |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 279 DECLARE_VIRTUAL_TRACE_WRAPPERS(); | 278 DECLARE_VIRTUAL_TRACE_WRAPPERS(); |
| 280 private: | 279 private: |
| 281 Member<OtherWrappable>> m_otherWrappable; | 280 Member<OtherWrappable>> m_otherWrappable; |
| 282 }; | 281 }; |
| 283 | 282 |
| 284 DEFINE_TRACE_WRAPPERS(ManualWrappable) { | 283 DEFINE_TRACE_WRAPPERS(ManualWrappable) { |
| 285 for (auto other : m_otherWrappables) | 284 for (auto other : m_otherWrappables) |
| 286 visitor->traceWrappersWithManualWriteBarrier(other); | 285 visitor->traceWrappersWithManualWriteBarrier(other); |
| 287 } | 286 } |
| 288 ``` | 287 ``` |
| OLD | NEW |