Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef TraceTraits_h | 5 #ifndef TraceTraits_h |
| 6 #define TraceTraits_h | 6 #define TraceTraits_h |
| 7 | 7 |
| 8 #include "platform/heap/GCInfo.h" | 8 #include "platform/heap/GCInfo.h" |
| 9 #include "platform/heap/Heap.h" | 9 #include "platform/heap/Heap.h" |
| 10 #include "platform/heap/InlinedGlobalMarkingVisitor.h" | 10 #include "platform/heap/InlinedGlobalMarkingVisitor.h" |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 40 class WeakPersistent; | 40 class WeakPersistent; |
| 41 | 41 |
| 42 template <typename T, bool = NeedsAdjustAndMark<T>::value> | 42 template <typename T, bool = NeedsAdjustAndMark<T>::value> |
| 43 class AdjustAndMarkTrait; | 43 class AdjustAndMarkTrait; |
| 44 | 44 |
| 45 template <typename T> | 45 template <typename T> |
| 46 class AdjustAndMarkTrait<T, false> { | 46 class AdjustAndMarkTrait<T, false> { |
| 47 STATIC_ONLY(AdjustAndMarkTrait); | 47 STATIC_ONLY(AdjustAndMarkTrait); |
| 48 | 48 |
| 49 public: | 49 public: |
| 50 static void markAndTraceWrapper(const WrapperVisitor* visitor, const T* t) { | |
| 51 if (visitor->markWrapperHeader(heapObjectHeader(t))) { | |
| 52 visitor->markWrappersInAllWorlds(t); | |
| 53 visitor->dispatchTraceWrappers(t); | |
| 54 } | |
| 55 } | |
| 56 static void markWrapperNoTracing(const WrapperVisitor* visitor, const T* t) { | |
| 57 DCHECK(!heapObjectHeader(t)->isWrapperHeaderMarked()); | |
| 58 visitor->markWrapperHeader(heapObjectHeader(t)); | |
| 59 } | |
| 60 static void traceMarkedWrapper(const WrapperVisitor* visitor, const T* t) { | |
| 61 DCHECK(heapObjectHeader(t)->isWrapperHeaderMarked()); | |
| 62 // The term *mark* is misleading here as we effectively trace through the | |
| 63 // API boundary, i.e., tell V8 that an object is alive. Actual marking | |
| 64 // will be done in V8. | |
| 65 visitor->markWrappersInAllWorlds(t); | |
| 66 visitor->dispatchTraceWrappers(t); | |
| 67 } | |
| 68 static HeapObjectHeader* heapObjectHeader(const T* t) { | |
| 69 return HeapObjectHeader::fromPayload(t); | |
| 70 } | |
| 71 | |
| 72 template <typename VisitorDispatcher> | 50 template <typename VisitorDispatcher> |
| 73 static void mark(VisitorDispatcher visitor, const T* t) { | 51 static void mark(VisitorDispatcher visitor, const T* t) { |
| 74 #if ENABLE(ASSERT) | 52 #if ENABLE(ASSERT) |
| 75 assertObjectHasGCInfo(const_cast<T*>(t), GCInfoTrait<T>::index()); | 53 assertObjectHasGCInfo(const_cast<T*>(t), GCInfoTrait<T>::index()); |
| 76 #endif | 54 #endif |
| 77 // Default mark method of the trait just calls the two-argument mark | 55 // Default mark method of the trait just calls the two-argument mark |
| 78 // method on the visitor. The second argument is the static trace method | 56 // method on the visitor. The second argument is the static trace method |
| 79 // of the trait, which by default calls the instance method | 57 // of the trait, which by default calls the instance method |
| 80 // trace(Visitor*) on the object. | 58 // trace(Visitor*) on the object. |
| 81 // | 59 // |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 104 } | 82 } |
| 105 visitor->mark(const_cast<T*>(t), &TraceTrait<T>::trace); | 83 visitor->mark(const_cast<T*>(t), &TraceTrait<T>::trace); |
| 106 } | 84 } |
| 107 }; | 85 }; |
| 108 | 86 |
| 109 template <typename T> | 87 template <typename T> |
| 110 class AdjustAndMarkTrait<T, true> { | 88 class AdjustAndMarkTrait<T, true> { |
| 111 STATIC_ONLY(AdjustAndMarkTrait); | 89 STATIC_ONLY(AdjustAndMarkTrait); |
| 112 | 90 |
| 113 public: | 91 public: |
| 114 static void markAndTraceWrapper(const WrapperVisitor* visitor, const T* t) { | |
| 115 t->adjustAndMarkAndTraceWrapper(visitor); | |
| 116 } | |
| 117 static void markWrapperNoTracing(const WrapperVisitor* visitor, const T* t) { | |
| 118 t->adjustAndMarkWrapperNoTracing(visitor); | |
| 119 } | |
| 120 static void traceMarkedWrapper(const WrapperVisitor* visitor, const T* t) { | |
| 121 t->adjustAndTraceMarkedWrapper(visitor); | |
| 122 } | |
| 123 static HeapObjectHeader* heapObjectHeader(const T* t) { | |
| 124 return t->adjustAndGetHeapObjectHeader(); | |
| 125 } | |
| 126 | |
| 127 template <typename VisitorDispatcher> | 92 template <typename VisitorDispatcher> |
| 128 static void mark(VisitorDispatcher visitor, const T* self) { | 93 static void mark(VisitorDispatcher visitor, const T* self) { |
| 129 if (!self) | 94 if (!self) |
| 130 return; | 95 return; |
| 131 | 96 |
| 132 // If you hit this ASSERT, it means that there is a dangling pointer | 97 // If you hit this ASSERT, it means that there is a dangling pointer |
| 133 // from a live thread heap to a dead thread heap. We must eliminate | 98 // from a live thread heap to a dead thread heap. We must eliminate |
| 134 // the dangling pointer. | 99 // the dangling pointer. |
| 135 // Release builds don't have the ASSERT, but it is OK because | 100 // Release builds don't have the ASSERT, but it is OK because |
| 136 // release builds will crash at the following self->adjustAndMark | 101 // release builds will crash at the following self->adjustAndMark |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 216 // to the start of the object in the Blink garbage-collected heap. In | 181 // to the start of the object in the Blink garbage-collected heap. In |
| 217 // that case the pointer has to be adjusted before marking. | 182 // that case the pointer has to be adjusted before marking. |
| 218 template <typename T> | 183 template <typename T> |
| 219 class TraceTrait { | 184 class TraceTrait { |
| 220 STATIC_ONLY(TraceTrait); | 185 STATIC_ONLY(TraceTrait); |
| 221 | 186 |
| 222 public: | 187 public: |
| 223 static void trace(Visitor*, void* self); | 188 static void trace(Visitor*, void* self); |
| 224 static void trace(InlinedGlobalMarkingVisitor, void* self); | 189 static void trace(InlinedGlobalMarkingVisitor, void* self); |
| 225 | 190 |
| 226 static void markAndTraceWrapper(const WrapperVisitor* visitor, | 191 static void markAndTraceWrapper(const WrapperVisitor*, const void*); |
| 227 const void* t) { | 192 static void markWrapperNoTracing(const WrapperVisitor*, const void*); |
| 228 static_assert(CanTraceWrappers<T>::value, | 193 static void traceMarkedWrapper(const WrapperVisitor*, const void*); |
| 229 "T should be able to trace wrappers. See " | 194 static HeapObjectHeader* heapObjectHeader(const void*); |
| 230 "dispatchTraceWrappers in WrapperVisitor.h"); | |
| 231 AdjustAndMarkTrait<T>::markAndTraceWrapper(visitor, | |
| 232 reinterpret_cast<const T*>(t)); | |
| 233 } | |
| 234 static void markWrapperNoTracing(const WrapperVisitor* visitor, | |
| 235 const void* t) { | |
| 236 static_assert(CanTraceWrappers<T>::value, | |
| 237 "T should be able to trace wrappers. See " | |
| 238 "dispatchTraceWrappers in WrapperVisitor.h"); | |
| 239 AdjustAndMarkTrait<T>::markWrapperNoTracing(visitor, | |
| 240 reinterpret_cast<const T*>(t)); | |
| 241 } | |
| 242 static void traceMarkedWrapper(const WrapperVisitor* visitor, const void* t) { | |
| 243 static_assert(CanTraceWrappers<T>::value, | |
| 244 "T should be able to trace wrappers. See " | |
| 245 "dispatchTraceWrappers in WrapperVisitor.h"); | |
| 246 AdjustAndMarkTrait<T>::traceMarkedWrapper(visitor, | |
| 247 reinterpret_cast<const T*>(t)); | |
| 248 } | |
| 249 static HeapObjectHeader* heapObjectHeader(const void* t) { | |
| 250 static_assert(CanTraceWrappers<T>::value, | |
| 251 "T should be able to trace wrappers. See " | |
| 252 "dispatchTraceWrappers in WrapperVisitor.h"); | |
| 253 return AdjustAndMarkTrait<T>::heapObjectHeader( | |
| 254 reinterpret_cast<const T*>(t)); | |
| 255 } | |
| 256 | 195 |
| 257 template <typename VisitorDispatcher> | 196 template <typename VisitorDispatcher> |
| 258 static void mark(VisitorDispatcher visitor, const T* t) { | 197 static void mark(VisitorDispatcher visitor, const T* t) { |
| 259 AdjustAndMarkTrait<T>::mark(visitor, t); | 198 AdjustAndMarkTrait<T>::mark(visitor, t); |
| 260 } | 199 } |
| 200 | |
| 201 private: | |
| 202 static const T* ToWrapperTracingType(const void* t) { | |
| 203 static_assert(CanTraceWrappers<T>::value, | |
| 204 "T should be able to trace wrappers. See " | |
| 205 "dispatchTraceWrappers in WrapperVisitor.h"); | |
| 206 static_assert(!NeedsAdjustAndMark<T>::value, | |
|
Michael Lippautz
2016/12/21 17:22:14
This static_assert makes sure we don't trace T for
sof
2016/12/21 18:57:28
IsGarbageCollectedMixin<T>::value is the more read
Michael Lippautz
2016/12/22 08:45:23
Done.
| |
| 207 "wrapper tracing is not supported within mixins"); | |
| 208 return reinterpret_cast<const T*>(t); | |
|
haraken
2016/12/22 00:50:07
Also we can add DCHECK(t->checkHeader()).
Michael Lippautz
2016/12/22 08:45:23
Done.
| |
| 209 } | |
| 261 }; | 210 }; |
| 262 | 211 |
| 263 template <typename T> | 212 template <typename T> |
| 264 class TraceTrait<const T> : public TraceTrait<T> {}; | 213 class TraceTrait<const T> : public TraceTrait<T> {}; |
| 265 | 214 |
| 266 template <typename T> | 215 template <typename T> |
| 267 void TraceTrait<T>::trace(Visitor* visitor, void* self) { | 216 void TraceTrait<T>::trace(Visitor* visitor, void* self) { |
| 268 static_assert(WTF::IsTraceable<T>::value, "T should not be traced"); | 217 static_assert(WTF::IsTraceable<T>::value, "T should not be traced"); |
| 269 if (visitor->isGlobalMarking()) { | 218 if (visitor->isGlobalMarking()) { |
| 270 // Switch to inlined global marking dispatch. | 219 // Switch to inlined global marking dispatch. |
| 271 static_cast<T*>(self)->trace(InlinedGlobalMarkingVisitor( | 220 static_cast<T*>(self)->trace(InlinedGlobalMarkingVisitor( |
| 272 visitor->state(), visitor->getMarkingMode())); | 221 visitor->state(), visitor->getMarkingMode())); |
| 273 } else { | 222 } else { |
| 274 static_cast<T*>(self)->trace(visitor); | 223 static_cast<T*>(self)->trace(visitor); |
| 275 } | 224 } |
| 276 } | 225 } |
| 277 | 226 |
| 278 template <typename T> | 227 template <typename T> |
| 279 void TraceTrait<T>::trace(InlinedGlobalMarkingVisitor visitor, void* self) { | 228 void TraceTrait<T>::trace(InlinedGlobalMarkingVisitor visitor, void* self) { |
| 280 static_assert(WTF::IsTraceable<T>::value, "T should not be traced"); | 229 static_assert(WTF::IsTraceable<T>::value, "T should not be traced"); |
| 281 static_cast<T*>(self)->trace(visitor); | 230 static_cast<T*>(self)->trace(visitor); |
| 282 } | 231 } |
| 283 | 232 |
| 233 template <typename T> | |
| 234 void TraceTrait<T>::markAndTraceWrapper(const WrapperVisitor* visitor, | |
| 235 const void* t) { | |
| 236 const T* traceable = ToWrapperTracingType(t); | |
| 237 if (visitor->markWrapperHeader(heapObjectHeader(traceable))) { | |
| 238 visitor->markWrappersInAllWorlds(traceable); | |
| 239 visitor->dispatchTraceWrappers(traceable); | |
| 240 } | |
| 241 } | |
| 242 | |
| 243 template <typename T> | |
| 244 void TraceTrait<T>::markWrapperNoTracing(const WrapperVisitor* visitor, | |
| 245 const void* t) { | |
| 246 const T* traceable = ToWrapperTracingType(t); | |
| 247 DCHECK(!heapObjectHeader(traceable)->isWrapperHeaderMarked()); | |
| 248 visitor->markWrapperHeader(heapObjectHeader(traceable)); | |
| 249 } | |
| 250 | |
| 251 template <typename T> | |
| 252 void TraceTrait<T>::traceMarkedWrapper(const WrapperVisitor* visitor, | |
| 253 const void* t) { | |
| 254 const T* traceable = ToWrapperTracingType(t); | |
| 255 DCHECK(heapObjectHeader(t)->isWrapperHeaderMarked()); | |
| 256 // The term *mark* is misleading here as we effectively trace through the | |
| 257 // API boundary, i.e., tell V8 that an object is alive. Actual marking | |
| 258 // will be done in V8. | |
| 259 visitor->markWrappersInAllWorlds(traceable); | |
| 260 visitor->dispatchTraceWrappers(traceable); | |
| 261 } | |
| 262 | |
| 263 template <typename T> | |
| 264 HeapObjectHeader* TraceTrait<T>::heapObjectHeader(const void* t) { | |
| 265 return HeapObjectHeader::fromPayload(ToWrapperTracingType(t)); | |
| 266 } | |
| 267 | |
| 284 template <typename T, typename Traits> | 268 template <typename T, typename Traits> |
| 285 struct TraceTrait<HeapVectorBacking<T, Traits>> { | 269 struct TraceTrait<HeapVectorBacking<T, Traits>> { |
| 286 STATIC_ONLY(TraceTrait); | 270 STATIC_ONLY(TraceTrait); |
| 287 using Backing = HeapVectorBacking<T, Traits>; | 271 using Backing = HeapVectorBacking<T, Traits>; |
| 288 | 272 |
| 289 template <typename VisitorDispatcher> | 273 template <typename VisitorDispatcher> |
| 290 static void trace(VisitorDispatcher visitor, void* self) { | 274 static void trace(VisitorDispatcher visitor, void* self) { |
| 291 static_assert(!WTF::IsWeak<T>::value, | 275 static_assert(!WTF::IsWeak<T>::value, |
| 292 "weakness in HeapVectors and HeapDeques are not supported"); | 276 "weakness in HeapVectors and HeapDeques are not supported"); |
| 293 if (WTF::IsTraceableInCollectionTrait<Traits>::value) | 277 if (WTF::IsTraceableInCollectionTrait<Traits>::value) |
| (...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 815 // since iterating over the hash table backing will find the whole | 799 // since iterating over the hash table backing will find the whole |
| 816 // chain. | 800 // chain. |
| 817 visitor->markNoTracing(node); | 801 visitor->markNoTracing(node); |
| 818 return false; | 802 return false; |
| 819 } | 803 } |
| 820 }; | 804 }; |
| 821 | 805 |
| 822 } // namespace WTF | 806 } // namespace WTF |
| 823 | 807 |
| 824 #endif | 808 #endif |
| OLD | NEW |