| Index: Source/platform/heap/Heap.h
|
| diff --git a/Source/platform/heap/Heap.h b/Source/platform/heap/Heap.h
|
| index 76052f32432746a783d92fe4ed12282d7b68b9d3..bd8def992e69aca263f922d32e3cca2fd9aa6ac7 100644
|
| --- a/Source/platform/heap/Heap.h
|
| +++ b/Source/platform/heap/Heap.h
|
| @@ -920,6 +920,7 @@ public:
|
| static bool weakTableRegistered(const void*);
|
| #endif
|
|
|
| + static inline Address allocateOnHeapIndex(ThreadState*, size_t, int heapIndex, size_t gcInfoIndex);
|
| template<typename T> static Address allocateOnHeapIndex(size_t, int heapIndex, size_t gcInfoIndex);
|
| template<typename T> static Address allocate(size_t);
|
| template<typename T> static Address reallocate(void* previous, size_t);
|
| @@ -1031,6 +1032,82 @@ private:
|
| friend class ThreadState;
|
| };
|
|
|
| +template<typename T>
|
| +struct HeapIndexTrait {
|
| + static int index() { return NormalPageHeapIndex; };
|
| +};
|
| +
|
| +// FIXME: The forward declaration is layering violation.
|
| +#define DEFINE_TYPED_HEAP_TRAIT(Type) \
|
| + class Type; \
|
| + template <> struct HeapIndexTrait<class Type> { \
|
| + static int index() { return Type##HeapIndex; }; \
|
| + };
|
| +FOR_EACH_TYPED_HEAP(DEFINE_TYPED_HEAP_TRAIT)
|
| +#undef DEFINE_TYPED_HEAP_TRAIT
|
| +
|
| +template<typename T, typename Enabled = void>
|
| +class AllocateObjectTrait {
|
| +public:
|
| + static inline Address allocate(size_t size)
|
| + {
|
| + ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state();
|
| + return Heap::allocateOnHeapIndex(state, size, HeapIndexTrait<T>::index(), GCInfoTrait<T>::index());
|
| + }
|
| +
|
| + static inline void constructor()
|
| + {
|
| + }
|
| +};
|
| +
|
| +template<typename T>
|
| +class AllocateObjectTrait<T, typename WTF::EnableIf<blink::IsGarbageCollectedMixin<T>::value>::Type> {
|
| +public:
|
| + // An object which implements GarbageCollectedMixin is marked
|
| + // and traced during GC by first adjusting object references to
|
| + // it to refer to the leftmost base for the object (which would
|
| + // be a GarbageCollected-derived class.) The prefixed object header
|
| + // can be located after that adjustment and its trace() vtbl slot
|
| + // will be used to fully trace the object, if not already marked.
|
| + //
|
| + // A C++ object's vptr will be initialized to its leftmost base's
|
| + // vtable after the constructors of all its subclasses have run,
|
| + // so if a subclass constructor tries to access any of the vtbl
|
| + // entries of its leftmost base prematurely, it'll find an as-yet
|
| + // incorrect vptr and fail. Which is exactly what a garbage collector
|
| + // will try to do if it tries to access the leftmost base while one
|
| + // of the subclass constructors of a GC mixin object triggers a GC.
|
| + // It is consequently not safe to allow any GCs while these objects
|
| + // are under (sub constructor) construction.
|
| + //
|
| + // To achieve that, the construction of mixins are handled in a
|
| + // special manner:
|
| + //
|
| + // - The initial allocation of the mixin object will enter a no GC scope.
|
| + // - The constructor for the leftmost base, which is when the mixin
|
| + // object is in a state ready for a GC, leaves that GC scope.
|
| + // - no-GC scope entering/leaving must support nesting.
|
| + //
|
| + static inline Address allocate(size_t size)
|
| + {
|
| + ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state();
|
| + Address object = Heap::allocateOnHeapIndex(state, size, HeapIndexTrait<T>::index(), GCInfoTrait<T>::index());
|
| + state->enterGCForbiddenScope();
|
| + return object;
|
| + }
|
| +
|
| + static inline void constructor()
|
| + {
|
| + // FIXME: if prompt conservative GCs are needed, forced GCs that
|
| + // were denied while within this scope, could now be performed.
|
| + // For now, assume the next out-of-line allocation request will
|
| + // happen soon enough and take care of it. Mixin objects aren't
|
| + // overly common.
|
| + ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state();
|
| + state->leaveGCForbiddenScope();
|
| + }
|
| +};
|
| +
|
| // Base class for objects allocated in the Blink garbage-collected heap.
|
| //
|
| // Defines a 'new' operator that allocates the memory in the heap. 'delete'
|
| @@ -1079,6 +1156,7 @@ public:
|
| protected:
|
| GarbageCollected()
|
| {
|
| + AllocateObjectTrait<T>::constructor();
|
| }
|
| };
|
|
|
| @@ -1375,32 +1453,23 @@ Address NormalPageHeap::allocate(size_t size, size_t gcInfoIndex)
|
| return allocateObject(allocationSizeFromSize(size), gcInfoIndex);
|
| }
|
|
|
| -template<typename T>
|
| -struct HeapIndexTrait {
|
| - static int index() { return NormalPageHeapIndex; };
|
| -};
|
| -
|
| -// FIXME: The forward declaration is layering violation.
|
| -#define DEFINE_TYPED_HEAP_TRAIT(Type) \
|
| - class Type; \
|
| - template <> struct HeapIndexTrait<class Type> { \
|
| - static int index() { return Type##HeapIndex; }; \
|
| - };
|
| -FOR_EACH_TYPED_HEAP(DEFINE_TYPED_HEAP_TRAIT)
|
| -#undef DEFINE_TYPED_HEAP_TRAIT
|
| +Address Heap::allocateOnHeapIndex(ThreadState* state, size_t size, int heapIndex, size_t gcInfoIndex)
|
| +{
|
| + ASSERT(state->isAllocationAllowed());
|
| + return static_cast<NormalPageHeap*>(state->heap(heapIndex))->allocate(size, gcInfoIndex);
|
| +}
|
|
|
| template<typename T>
|
| Address Heap::allocateOnHeapIndex(size_t size, int heapIndex, size_t gcInfoIndex)
|
| {
|
| ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state();
|
| - ASSERT(state->isAllocationAllowed());
|
| - return static_cast<NormalPageHeap*>(state->heap(heapIndex))->allocate(size, gcInfoIndex);
|
| + return allocateOnHeapIndex(state, size, heapIndex, gcInfoIndex);
|
| }
|
|
|
| template<typename T>
|
| Address Heap::allocate(size_t size)
|
| {
|
| - return allocateOnHeapIndex<T>(size, HeapIndexTrait<T>::index(), GCInfoTrait<T>::index());
|
| + return AllocateObjectTrait<T>::allocate(size);
|
| }
|
|
|
| template<typename T>
|
|
|