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 GarbageCollected_h | 5 #ifndef GarbageCollected_h |
| 6 #define GarbageCollected_h | 6 #define GarbageCollected_h |
| 7 | 7 |
| 8 #include "platform/heap/ThreadState.h" | 8 #include "platform/heap/ThreadState.h" |
| 9 #include "wtf/Assertions.h" | 9 #include "wtf/Assertions.h" |
| 10 #include "wtf/ListHashSet.h" | 10 #include "wtf/ListHashSet.h" |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 105 // }; | 105 // }; |
| 106 // | 106 // |
| 107 // With the helper, as long as we are using Member<B>, TypeTrait<B> will | 107 // With the helper, as long as we are using Member<B>, TypeTrait<B> will |
| 108 // dispatch adjustAndMark dynamically to find collect addr of the object header. | 108 // dispatch adjustAndMark dynamically to find collect addr of the object header. |
| 109 // Note that this is only enabled for Member<B>. For Member<A> which we can | 109 // Note that this is only enabled for Member<B>. For Member<A> which we can |
| 110 // compute the object header addr statically, this dynamic dispatch is not used. | 110 // compute the object header addr statically, this dynamic dispatch is not used. |
| 111 class PLATFORM_EXPORT GarbageCollectedMixin { | 111 class PLATFORM_EXPORT GarbageCollectedMixin { |
| 112 public: | 112 public: |
| 113 typedef int IsGarbageCollectedMixinMarker; | 113 typedef int IsGarbageCollectedMixinMarker; |
| 114 virtual void adjustAndMark(Visitor*) const = 0; | 114 virtual void adjustAndMark(Visitor*) const = 0; |
| 115 virtual bool isHeapObjectAlive(Visitor*) const = 0; | |
| 116 virtual void trace(Visitor*) { } | 115 virtual void trace(Visitor*) { } |
| 117 virtual void adjustAndMark(InlinedGlobalMarkingVisitor) const = 0; | 116 virtual void adjustAndMark(InlinedGlobalMarkingVisitor) const = 0; |
| 118 virtual bool isHeapObjectAlive(InlinedGlobalMarkingVisitor) const = 0; | |
| 119 virtual void trace(InlinedGlobalMarkingVisitor); | 117 virtual void trace(InlinedGlobalMarkingVisitor); |
| 118 virtual bool isHeapObjectAlive() const = 0; | |
| 120 }; | 119 }; |
| 121 | 120 |
| 122 #define DEFINE_GARBAGE_COLLECTED_MIXIN_METHODS(VISITOR, TYPE) \ | 121 #define DEFINE_GARBAGE_COLLECTED_MIXIN_METHODS(VISITOR, TYPE) \ |
| 123 public: \ | 122 public: \ |
| 124 virtual void adjustAndMark(VISITOR visitor) const override \ | 123 virtual void adjustAndMark(VISITOR visitor) const override \ |
| 125 { \ | 124 { \ |
| 126 typedef WTF::IsSubclassOfTemplate<typename WTF::RemoveConst<TYPE>::Type, blink::GarbageCollected> IsSubclassOfGarbageCollected; \ | 125 typedef WTF::IsSubclassOfTemplate<typename WTF::RemoveConst<TYPE>::Type, blink::GarbageCollected> IsSubclassOfGarbageCollected; \ |
| 127 static_assert(IsSubclassOfGarbageCollected::value, "only garbage collect ed objects can have garbage collected mixins"); \ | 126 static_assert(IsSubclassOfGarbageCollected::value, "only garbage collect ed objects can have garbage collected mixins"); \ |
| 128 if (TraceEagerlyTrait<TYPE>::value) { \ | 127 if (TraceEagerlyTrait<TYPE>::value) { \ |
| 129 if (visitor->ensureMarked(static_cast<const TYPE*>(this))) \ | 128 if (visitor->ensureMarked(static_cast<const TYPE*>(this))) \ |
| 130 TraceTrait<TYPE>::trace(visitor, const_cast<TYPE*>(this)); \ | 129 TraceTrait<TYPE>::trace(visitor, const_cast<TYPE*>(this)); \ |
| 131 return; \ | 130 return; \ |
| 132 } \ | 131 } \ |
| 133 visitor->mark(static_cast<const TYPE*>(this), &blink::TraceTrait<TYPE>:: trace); \ | 132 visitor->mark(static_cast<const TYPE*>(this), &blink::TraceTrait<TYPE>:: trace); \ |
| 134 } \ | 133 } \ |
| 135 virtual bool isHeapObjectAlive(VISITOR visitor) const override \ | 134 private: |
| 136 { \ | |
| 137 return visitor->isHeapObjectAlive(this); \ | |
| 138 } \ | |
| 139 private: | |
| 140 | 135 |
| 141 // A C++ object's vptr will be initialized to its leftmost base's vtable after | 136 // A C++ object's vptr will be initialized to its leftmost base's vtable after |
| 142 // the constructors of all its subclasses have run, so if a subclass constructor | 137 // the constructors of all its subclasses have run, so if a subclass constructor |
| 143 // tries to access any of the vtbl entries of its leftmost base prematurely, | 138 // tries to access any of the vtbl entries of its leftmost base prematurely, |
| 144 // it'll find an as-yet incorrect vptr and fail. Which is exactly what a | 139 // it'll find an as-yet incorrect vptr and fail. Which is exactly what a |
| 145 // garbage collector will try to do if it tries to access the leftmost base | 140 // garbage collector will try to do if it tries to access the leftmost base |
| 146 // while one of the subclass constructors of a GC mixin object triggers a GC. | 141 // while one of the subclass constructors of a GC mixin object triggers a GC. |
| 147 // It is consequently not safe to allow any GCs while these objects are under | 142 // It is consequently not safe to allow any GCs while these objects are under |
| 148 // (sub constructor) construction. | 143 // (sub constructor) construction. |
| 149 // | 144 // |
| 150 // To prevent GCs in that restricted window of a mixin object's construction: | 145 // To prevent GCs in that restricted window of a mixin object's construction: |
| 151 // | 146 // |
| 152 // - The initial allocation of the mixin object will enter a no GC scope. | 147 // - The initial allocation of the mixin object will enter a no GC scope. |
| 153 // This is done by overriding 'operator new' for mixin instances. | 148 // This is done by overriding 'operator new' for mixin instances. |
| 154 // - When the constructor for the mixin is invoked, after all the | 149 // - When the constructor for the mixin is invoked, after all the |
| 155 // derived constructors have run, it will invoke the constructor | 150 // derived constructors have run, it will invoke the constructor |
| 156 // for a field whose only purpose is to leave the GC scope. | 151 // for a field whose only purpose is to leave the GC scope. |
| 157 // GarbageCollectedMixinConstructorMarker's constructor takes care of | 152 // GarbageCollectedMixinConstructorMarker's constructor takes care of |
| 158 // this and the field is declared by way of USING_GARBAGE_COLLECTED_MIXIN(). | 153 // this and the field is declared by way of USING_GARBAGE_COLLECTED_MIXIN(). |
| 159 | 154 |
| 160 #define DEFINE_GARBAGE_COLLECTED_MIXIN_CONSTRUCTOR_MARKER(TYPE) \ | 155 #define DEFINE_GARBAGE_COLLECTED_MIXIN_CONSTRUCTOR_MARKER(TYPE) \ |
| 161 public: \ | 156 public: \ |
|
Yuta Kitamura
2015/06/03 04:58:29
This indent looks wrong; inconsistent with ll. 191
| |
| 162 GC_PLUGIN_IGNORE("crbug.com/456823") NO_SANITIZE_UNRELATED_CAST \ | 157 GC_PLUGIN_IGNORE("crbug.com/456823") NO_SANITIZE_UNRELATED_CAST \ |
| 163 void* operator new(size_t size) \ | 158 void* operator new(size_t size) \ |
| 164 { \ | 159 { \ |
| 165 void* object = TYPE::allocateObject(size); \ | 160 void* object = TYPE::allocateObject(size); \ |
| 166 ThreadState* state = ThreadStateFor<ThreadingTrait<TYPE>::Affinity>::sta te(); \ | 161 ThreadState* state = ThreadStateFor<ThreadingTrait<TYPE>::Affinity>::sta te(); \ |
| 167 state->enterGCForbiddenScopeIfNeeded(&(reinterpret_cast<TYPE*>(object)-> m_mixinConstructorMarker)); \ | 162 state->enterGCForbiddenScopeIfNeeded(&(reinterpret_cast<TYPE*>(object)-> m_mixinConstructorMarker)); \ |
| 168 return object; \ | 163 return object; \ |
| 169 } \ | 164 } \ |
| 170 GarbageCollectedMixinConstructorMarker m_mixinConstructorMarker; \ | 165 GarbageCollectedMixinConstructorMarker m_mixinConstructorMarker; \ |
| 171 private: | 166 private: |
| 172 | 167 |
| 173 // Mixins that wrap/nest others requires extra handling: | 168 // Mixins that wrap/nest others requires extra handling: |
| 174 // | 169 // |
| 175 // class A : public GarbageCollected<A>, public GarbageCollectedMixin { | 170 // class A : public GarbageCollected<A>, public GarbageCollectedMixin { |
| 176 // USING_GARBAGE_COLLECTED_MIXIN(A); | 171 // USING_GARBAGE_COLLECTED_MIXIN(A); |
| 177 // ... | 172 // ... |
| 178 // }' | 173 // }' |
| 179 // public B final : public A, public SomeOtherMixinInterface { | 174 // public B final : public A, public SomeOtherMixinInterface { |
| 180 // USING_GARBAGE_COLLECTED_MIXIN(B); | 175 // USING_GARBAGE_COLLECTED_MIXIN(B); |
| 181 // ... | 176 // ... |
| 182 // }; | 177 // }; |
| 183 // | 178 // |
| 184 // The "operator new" for B will enter the forbidden GC scope, but | 179 // The "operator new" for B will enter the forbidden GC scope, but |
| 185 // upon construction, two GarbageCollectedMixinConstructorMarker constructors | 180 // upon construction, two GarbageCollectedMixinConstructorMarker constructors |
| 186 // will run -- one for A (first) and another for B (secondly). Only | 181 // will run -- one for A (first) and another for B (secondly). Only |
| 187 // the second one should leave the forbidden GC scope. This is realized by | 182 // the second one should leave the forbidden GC scope. This is realized by |
| 188 // recording the address of B's GarbageCollectedMixinConstructorMarker | 183 // recording the address of B's GarbageCollectedMixinConstructorMarker |
| 189 // when the "operator new" for B runs, and leaving the forbidden GC scope | 184 // when the "operator new" for B runs, and leaving the forbidden GC scope |
| 190 // when the constructor of the recorded GarbageCollectedMixinConstructorMarker | 185 // when the constructor of the recorded GarbageCollectedMixinConstructorMarker |
| 191 // runs. | 186 // runs. |
| 192 #define USING_GARBAGE_COLLECTED_MIXIN(TYPE) \ | 187 #define USING_GARBAGE_COLLECTED_MIXIN(TYPE) \ |
| 193 DEFINE_GARBAGE_COLLECTED_MIXIN_METHODS(blink::Visitor*, TYPE) \ | 188 DEFINE_GARBAGE_COLLECTED_MIXIN_METHODS(blink::Visitor*, TYPE) \ |
| 194 DEFINE_GARBAGE_COLLECTED_MIXIN_METHODS(blink::InlinedGlobalMarkingVisitor, T YPE) \ | 189 DEFINE_GARBAGE_COLLECTED_MIXIN_METHODS(blink::InlinedGlobalMarkingVisitor, T YPE) \ |
| 195 DEFINE_GARBAGE_COLLECTED_MIXIN_CONSTRUCTOR_MARKER(TYPE) | 190 DEFINE_GARBAGE_COLLECTED_MIXIN_CONSTRUCTOR_MARKER(TYPE) \ |
| 191 public: \ | |
| 192 virtual bool isHeapObjectAlive() const override \ | |
| 193 { \ | |
| 194 return Heap::isHeapObjectAlive(this); \ | |
| 195 } \ | |
| 196 private: | |
| 196 | 197 |
| 197 #if ENABLE(OILPAN) | 198 #if ENABLE(OILPAN) |
| 198 #define WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TYPE) USING_GARBAGE_COLLECTED_MIXI N(TYPE) | 199 #define WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TYPE) USING_GARBAGE_COLLECTED_MIXI N(TYPE) |
| 199 #else | 200 #else |
| 200 #define WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TYPE) | 201 #define WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TYPE) |
| 201 #endif | 202 #endif |
| 202 | 203 |
| 203 // An empty class with a constructor that's arranged invoked when all derived co nstructors | 204 // An empty class with a constructor that's arranged invoked when all derived co nstructors |
| 204 // of a mixin instance have completed and it is safe to allow GCs again. See | 205 // of a mixin instance have completed and it is safe to allow GCs again. See |
| 205 // AllocateObjectTrait<> comment for more. | 206 // AllocateObjectTrait<> comment for more. |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 396 void* operator new(size_t, NotNullTag, void*) = delete; \ | 397 void* operator new(size_t, NotNullTag, void*) = delete; \ |
| 397 void* operator new(size_t, void*) = delete; | 398 void* operator new(size_t, void*) = delete; |
| 398 | 399 |
| 399 #define GC_PLUGIN_IGNORE(bug) \ | 400 #define GC_PLUGIN_IGNORE(bug) \ |
| 400 __attribute__((annotate("blink_gc_plugin_ignore"))) | 401 __attribute__((annotate("blink_gc_plugin_ignore"))) |
| 401 #else | 402 #else |
| 402 #define STACK_ALLOCATED() DISALLOW_ALLOCATION() | 403 #define STACK_ALLOCATED() DISALLOW_ALLOCATION() |
| 403 #define GC_PLUGIN_IGNORE(bug) | 404 #define GC_PLUGIN_IGNORE(bug) |
| 404 #endif | 405 #endif |
| 405 | 406 |
| 407 template<typename T, bool = WTF::IsSubclassOfTemplate<typename WTF::RemoveConst< T>::Type, GarbageCollected>::value> class NeedsAdjustAndMark; | |
| 408 | |
| 409 template<typename T> | |
| 410 class NeedsAdjustAndMark<T, true> { | |
| 411 static_assert(sizeof(T), "T must be fully defined"); | |
| 412 public: | |
| 413 static const bool value = false; | |
| 414 }; | |
| 415 template <typename T> const bool NeedsAdjustAndMark<T, true>::value; | |
| 416 | |
| 417 template<typename T> | |
| 418 class NeedsAdjustAndMark<T, false> { | |
| 419 static_assert(sizeof(T), "T must be fully defined"); | |
| 420 public: | |
| 421 static const bool value = IsGarbageCollectedMixin<typename WTF::RemoveConst< T>::Type>::value; | |
| 422 }; | |
| 423 template <typename T> const bool NeedsAdjustAndMark<T, false>::value; | |
| 424 | |
| 406 } // namespace blink | 425 } // namespace blink |
| 407 | 426 |
| 408 #endif | 427 #endif |
| OLD | NEW |