| Index: sky/engine/platform/heap/ThreadState.h
|
| diff --git a/sky/engine/platform/heap/ThreadState.h b/sky/engine/platform/heap/ThreadState.h
|
| deleted file mode 100644
|
| index b07fe3ec0c7cec25bcfe60d54c3137b8ba65e093..0000000000000000000000000000000000000000
|
| --- a/sky/engine/platform/heap/ThreadState.h
|
| +++ /dev/null
|
| @@ -1,742 +0,0 @@
|
| -/*
|
| - * Copyright (C) 2013 Google Inc. All rights reserved.
|
| - *
|
| - * Redistribution and use in source and binary forms, with or without
|
| - * modification, are permitted provided that the following conditions are
|
| - * met:
|
| - *
|
| - * * Redistributions of source code must retain the above copyright
|
| - * notice, this list of conditions and the following disclaimer.
|
| - * * Redistributions in binary form must reproduce the above
|
| - * copyright notice, this list of conditions and the following disclaimer
|
| - * in the documentation and/or other materials provided with the
|
| - * distribution.
|
| - * * Neither the name of Google Inc. nor the names of its
|
| - * contributors may be used to endorse or promote products derived from
|
| - * this software without specific prior written permission.
|
| - *
|
| - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
| - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
| - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
| - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
| - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
| - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
| - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
| - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
| - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| - */
|
| -
|
| -#ifndef ThreadState_h
|
| -#define ThreadState_h
|
| -
|
| -#include "platform/PlatformExport.h"
|
| -#include "platform/heap/AddressSanitizer.h"
|
| -#include "public/platform/WebThread.h"
|
| -#include "wtf/HashSet.h"
|
| -#include "wtf/OwnPtr.h"
|
| -#include "wtf/PassOwnPtr.h"
|
| -#include "wtf/ThreadSpecific.h"
|
| -#include "wtf/Threading.h"
|
| -#include "wtf/ThreadingPrimitives.h"
|
| -#include "wtf/Vector.h"
|
| -
|
| -#if ENABLE(GC_PROFILE_HEAP)
|
| -#include "wtf/HashMap.h"
|
| -#endif
|
| -
|
| -namespace blink {
|
| -
|
| -class BaseHeap;
|
| -class BaseHeapPage;
|
| -class FinalizedHeapObjectHeader;
|
| -struct GCInfo;
|
| -class HeapContainsCache;
|
| -class HeapObjectHeader;
|
| -class PageMemory;
|
| -class PersistentNode;
|
| -class Visitor;
|
| -class SafePointBarrier;
|
| -class SafePointAwareMutexLocker;
|
| -template<typename Header> class ThreadHeap;
|
| -class CallbackStack;
|
| -
|
| -typedef uint8_t* Address;
|
| -
|
| -typedef void (*FinalizationCallback)(void*);
|
| -typedef void (*VisitorCallback)(Visitor*, void* self);
|
| -typedef VisitorCallback TraceCallback;
|
| -typedef VisitorCallback WeakPointerCallback;
|
| -typedef VisitorCallback EphemeronCallback;
|
| -
|
| -// ThreadAffinity indicates which threads objects can be used on. We
|
| -// distinguish between objects that can be used on the main thread
|
| -// only and objects that can be used on any thread.
|
| -//
|
| -// For objects that can only be used on the main thread we avoid going
|
| -// through thread-local storage to get to the thread state.
|
| -//
|
| -// FIXME: We should evaluate the performance gain. Having
|
| -// ThreadAffinity is complicating the implementation and we should get
|
| -// rid of it if it is fast enough to go through thread-local storage
|
| -// always.
|
| -enum ThreadAffinity {
|
| - AnyThread,
|
| - MainThreadOnly,
|
| -};
|
| -
|
| -class Node;
|
| -class CSSValue;
|
| -
|
| -template<typename T, bool derivesNode = WTF::IsSubclass<typename WTF::RemoveConst<T>::Type, Node>::value> struct DefaultThreadingTrait;
|
| -
|
| -template<typename T>
|
| -struct DefaultThreadingTrait<T, false> {
|
| - static const ThreadAffinity Affinity = AnyThread;
|
| -};
|
| -
|
| -template<typename T>
|
| -struct DefaultThreadingTrait<T, true> {
|
| - static const ThreadAffinity Affinity = MainThreadOnly;
|
| -};
|
| -
|
| -template<typename T>
|
| -struct ThreadingTrait {
|
| - static const ThreadAffinity Affinity = DefaultThreadingTrait<T>::Affinity;
|
| -};
|
| -
|
| -// Marks the specified class as being used from multiple threads. When
|
| -// a class is used from multiple threads we go through thread local
|
| -// storage to get the heap in which to allocate an object of that type
|
| -// and when allocating a Persistent handle for an object with that
|
| -// type. Notice that marking the base class does not automatically
|
| -// mark its descendants and they have to be explicitly marked.
|
| -#define USED_FROM_MULTIPLE_THREADS(Class) \
|
| - class Class; \
|
| - template<> struct ThreadingTrait<Class> { \
|
| - static const ThreadAffinity Affinity = AnyThread; \
|
| - }
|
| -
|
| -#define USED_FROM_MULTIPLE_THREADS_NAMESPACE(Namespace, Class) \
|
| - namespace Namespace { \
|
| - class Class; \
|
| - } \
|
| - namespace blink { \
|
| - template<> struct ThreadingTrait<Namespace::Class> { \
|
| - static const ThreadAffinity Affinity = AnyThread; \
|
| - }; \
|
| - }
|
| -
|
| -template<typename U> class ThreadingTrait<const U> : public ThreadingTrait<U> { };
|
| -
|
| -// List of typed heaps. The list is used to generate the implementation
|
| -// of typed heap related methods.
|
| -//
|
| -// To create a new typed heap add a H(<ClassName>) to the
|
| -// FOR_EACH_TYPED_HEAP macro below.
|
| -#define FOR_EACH_TYPED_HEAP(H) \
|
| - H(Node)
|
| -
|
| -#define TypedHeapEnumName(Type) Type##Heap,
|
| -#define TypedHeapEnumNameNonFinalized(Type) Type##HeapNonFinalized,
|
| -
|
| -enum TypedHeaps {
|
| - GeneralHeap = 0,
|
| - CollectionBackingHeap,
|
| - FOR_EACH_TYPED_HEAP(TypedHeapEnumName)
|
| - GeneralHeapNonFinalized,
|
| - CollectionBackingHeapNonFinalized,
|
| - FOR_EACH_TYPED_HEAP(TypedHeapEnumNameNonFinalized)
|
| - // Values used for iteration of heap segments.
|
| - NumberOfHeaps,
|
| - FirstFinalizedHeap = GeneralHeap,
|
| - FirstNonFinalizedHeap = GeneralHeapNonFinalized,
|
| - NumberOfFinalizedHeaps = GeneralHeapNonFinalized,
|
| - NumberOfNonFinalizedHeaps = NumberOfHeaps - NumberOfFinalizedHeaps,
|
| - NonFinalizedHeapOffset = FirstNonFinalizedHeap
|
| -};
|
| -
|
| -// Base implementation for HeapIndexTrait found below.
|
| -template<int heapIndex>
|
| -struct HeapIndexTraitBase {
|
| - typedef FinalizedHeapObjectHeader HeaderType;
|
| - typedef ThreadHeap<HeaderType> HeapType;
|
| - static const int finalizedIndex = heapIndex;
|
| - static const int nonFinalizedIndex = heapIndex + static_cast<int>(NonFinalizedHeapOffset);
|
| - static int index(bool isFinalized)
|
| - {
|
| - return isFinalized ? finalizedIndex : nonFinalizedIndex;
|
| - }
|
| -};
|
| -
|
| -// HeapIndexTrait defines properties for each heap in the TypesHeaps enum.
|
| -template<int index>
|
| -struct HeapIndexTrait;
|
| -
|
| -template<>
|
| -struct HeapIndexTrait<GeneralHeap> : public HeapIndexTraitBase<GeneralHeap> { };
|
| -template<>
|
| -struct HeapIndexTrait<GeneralHeapNonFinalized> : public HeapIndexTrait<GeneralHeap> { };
|
| -
|
| -template<>
|
| -struct HeapIndexTrait<CollectionBackingHeap> : public HeapIndexTraitBase<CollectionBackingHeap> { };
|
| -template<>
|
| -struct HeapIndexTrait<CollectionBackingHeapNonFinalized> : public HeapIndexTrait<CollectionBackingHeap> { };
|
| -
|
| -#define DEFINE_TYPED_HEAP_INDEX_TRAIT(Type) \
|
| - template<> \
|
| - struct HeapIndexTrait<Type##Heap> : public HeapIndexTraitBase<Type##Heap> { \
|
| - typedef HeapObjectHeader HeaderType; \
|
| - typedef ThreadHeap<HeaderType> HeapType; \
|
| - }; \
|
| - template<> \
|
| - struct HeapIndexTrait<Type##HeapNonFinalized> : public HeapIndexTrait<Type##Heap> { };
|
| -FOR_EACH_TYPED_HEAP(DEFINE_TYPED_HEAP_INDEX_TRAIT)
|
| -#undef DEFINE_TYPED_HEAP_INDEX_TRAIT
|
| -
|
| -// HeapTypeTrait defines which heap to use for particular types.
|
| -// By default objects are allocated in the GeneralHeap.
|
| -template<typename T>
|
| -struct HeapTypeTrait : public HeapIndexTrait<GeneralHeap> { };
|
| -
|
| -// We don't have any type-based mappings to the CollectionBackingHeap.
|
| -
|
| -// Each typed-heap maps the respective type to its heap.
|
| -#define DEFINE_TYPED_HEAP_TRAIT(Type) \
|
| - class Type; \
|
| - template<> \
|
| - struct HeapTypeTrait<class Type> : public HeapIndexTrait<Type##Heap> { };
|
| -FOR_EACH_TYPED_HEAP(DEFINE_TYPED_HEAP_TRAIT)
|
| -#undef DEFINE_TYPED_HEAP_TRAIT
|
| -
|
| -// A HeapStats structure keeps track of the amount of memory allocated
|
| -// for a Blink heap and how much of that memory is used for actual
|
| -// Blink objects. These stats are used in the heuristics to determine
|
| -// when to perform garbage collections.
|
| -class HeapStats {
|
| -public:
|
| - HeapStats() : m_totalObjectSpace(0), m_totalAllocatedSpace(0) { }
|
| -
|
| - size_t totalObjectSpace() const { return m_totalObjectSpace; }
|
| - size_t totalAllocatedSpace() const { return m_totalAllocatedSpace; }
|
| -
|
| - void add(HeapStats* other)
|
| - {
|
| - m_totalObjectSpace += other->m_totalObjectSpace;
|
| - m_totalAllocatedSpace += other->m_totalAllocatedSpace;
|
| - }
|
| -
|
| - void inline increaseObjectSpace(size_t newObjectSpace)
|
| - {
|
| - m_totalObjectSpace += newObjectSpace;
|
| - }
|
| -
|
| - void inline decreaseObjectSpace(size_t deadObjectSpace)
|
| - {
|
| - m_totalObjectSpace -= deadObjectSpace;
|
| - }
|
| -
|
| - void inline increaseAllocatedSpace(size_t newAllocatedSpace)
|
| - {
|
| - m_totalAllocatedSpace += newAllocatedSpace;
|
| - }
|
| -
|
| - void inline decreaseAllocatedSpace(size_t deadAllocatedSpace)
|
| - {
|
| - m_totalAllocatedSpace -= deadAllocatedSpace;
|
| - }
|
| -
|
| - void clear()
|
| - {
|
| - m_totalObjectSpace = 0;
|
| - m_totalAllocatedSpace = 0;
|
| - }
|
| -
|
| - bool operator==(const HeapStats& other)
|
| - {
|
| - return m_totalAllocatedSpace == other.m_totalAllocatedSpace
|
| - && m_totalObjectSpace == other.m_totalObjectSpace;
|
| - }
|
| -
|
| -private:
|
| - size_t m_totalObjectSpace; // Actually contains objects that may be live, not including headers.
|
| - size_t m_totalAllocatedSpace; // Allocated from the OS.
|
| -
|
| - friend class HeapTester;
|
| -};
|
| -
|
| -class PLATFORM_EXPORT ThreadState {
|
| - WTF_MAKE_NONCOPYABLE(ThreadState);
|
| -public:
|
| - // When garbage collecting we need to know whether or not there
|
| - // can be pointers to Blink GC managed objects on the stack for
|
| - // each thread. When threads reach a safe point they record
|
| - // whether or not they have pointers on the stack.
|
| - enum StackState {
|
| - NoHeapPointersOnStack,
|
| - HeapPointersOnStack
|
| - };
|
| -
|
| - class NoSweepScope {
|
| - public:
|
| - explicit NoSweepScope(ThreadState* state) : m_state(state)
|
| - {
|
| - ASSERT(!m_state->m_sweepInProgress);
|
| - m_state->m_sweepInProgress = true;
|
| - }
|
| - ~NoSweepScope()
|
| - {
|
| - ASSERT(m_state->m_sweepInProgress);
|
| - m_state->m_sweepInProgress = false;
|
| - }
|
| - private:
|
| - ThreadState* m_state;
|
| - };
|
| -
|
| - // The set of ThreadStates for all threads attached to the Blink
|
| - // garbage collector.
|
| - typedef HashSet<ThreadState*> AttachedThreadStateSet;
|
| - static AttachedThreadStateSet& attachedThreads();
|
| -
|
| - bool isTerminating() { return m_isTerminating; }
|
| -
|
| - // Trace all persistent roots, called when marking the managed heap objects.
|
| - static void visitPersistentRoots(Visitor*);
|
| -
|
| - // Trace all objects found on the stack, used when doing conservative GCs.
|
| - static void visitStackRoots(Visitor*);
|
| -
|
| - // Associate ThreadState object with the current thread. After this
|
| - // call thread can start using the garbage collected heap infrastructure.
|
| - // It also has to periodically check for safepoints.
|
| - static void attach();
|
| -
|
| - // Disassociate attached ThreadState from the current thread. The thread
|
| - // can no longer use the garbage collected heap after this call.
|
| - static void detach();
|
| -
|
| - static ThreadState* mainThreadState()
|
| - {
|
| - return reinterpret_cast<ThreadState*>(s_mainThreadStateStorage);
|
| - }
|
| -
|
| - bool isMainThread() const { return this == mainThreadState(); }
|
| - inline bool checkThread() const
|
| - {
|
| - ASSERT(m_thread == currentThread());
|
| - return true;
|
| - }
|
| -
|
| - // shouldGC and shouldForceConservativeGC implement the heuristics
|
| - // that are used to determine when to collect garbage. If
|
| - // shouldForceConservativeGC returns true, we force the garbage
|
| - // collection immediately. Otherwise, if shouldGC returns true, we
|
| - // record that we should garbage collect the next time we return
|
| - // to the event loop. If both return false, we don't need to
|
| - // collect garbage at this point.
|
| - bool shouldGC();
|
| - bool shouldForceConservativeGC();
|
| - bool increasedEnoughToGC(size_t, size_t);
|
| - bool increasedEnoughToForceConservativeGC(size_t, size_t);
|
| -
|
| - // If gcRequested returns true when a thread returns to its event
|
| - // loop the thread will initiate a garbage collection.
|
| - bool gcRequested();
|
| - void setGCRequested();
|
| - void clearGCRequested();
|
| -
|
| - // Was the last GC forced for testing? This is set when garbage collection
|
| - // is forced for testing and there are pointers on the stack. It remains
|
| - // set until a garbage collection is triggered with no pointers on the stack.
|
| - // This is used for layout tests that trigger GCs and check if objects are
|
| - // dead at a given point in time. That only reliably works when we get
|
| - // precise GCs with no conservative stack scanning.
|
| - void setForcePreciseGCForTesting(bool);
|
| - bool forcePreciseGCForTesting();
|
| -
|
| - bool sweepRequested();
|
| - void setSweepRequested();
|
| - void clearSweepRequested();
|
| - void performPendingSweep();
|
| -
|
| - // Support for disallowing allocation. Mainly used for sanity
|
| - // checks asserts.
|
| - bool isAllocationAllowed() const { return !isAtSafePoint() && !m_noAllocationCount; }
|
| - void enterNoAllocationScope() { m_noAllocationCount++; }
|
| - void leaveNoAllocationScope() { m_noAllocationCount--; }
|
| -
|
| - // Before performing GC the thread-specific heap state should be
|
| - // made consistent for sweeping.
|
| - void makeConsistentForSweeping();
|
| -#if ENABLE(ASSERT)
|
| - bool isConsistentForSweeping();
|
| -#endif
|
| -
|
| - // Is the thread corresponding to this thread state currently
|
| - // performing GC?
|
| - bool isInGC() const { return m_inGC; }
|
| -
|
| - // Is any of the threads registered with the blink garbage collection
|
| - // infrastructure currently performing GC?
|
| - static bool isAnyThreadInGC() { return s_inGC; }
|
| -
|
| - void enterGC()
|
| - {
|
| - ASSERT(!m_inGC);
|
| - ASSERT(!s_inGC);
|
| - m_inGC = true;
|
| - s_inGC = true;
|
| - }
|
| -
|
| - void leaveGC()
|
| - {
|
| - m_inGC = false;
|
| - s_inGC = false;
|
| - }
|
| -
|
| - // Is the thread corresponding to this thread state currently
|
| - // sweeping?
|
| - bool isSweepInProgress() const { return m_sweepInProgress; }
|
| -
|
| - void prepareForGC();
|
| -
|
| - // Safepoint related functionality.
|
| - //
|
| - // When a thread attempts to perform GC it needs to stop all other threads
|
| - // that use the heap or at least guarantee that they will not touch any
|
| - // heap allocated object until GC is complete.
|
| - //
|
| - // We say that a thread is at a safepoint if this thread is guaranteed to
|
| - // not touch any heap allocated object or any heap related functionality until
|
| - // it leaves the safepoint.
|
| - //
|
| - // Notice that a thread does not have to be paused if it is at safepoint it
|
| - // can continue to run and perform tasks that do not require interaction
|
| - // with the heap. It will be paused if it attempts to leave the safepoint and
|
| - // there is a GC in progress.
|
| - //
|
| - // Each thread that has ThreadState attached must:
|
| - // - periodically check if GC is requested from another thread by calling a safePoint() method;
|
| - // - use SafePointScope around long running loops that have no safePoint() invocation inside,
|
| - // such loops must not touch any heap object;
|
| - // - register an Interruptor that can interrupt long running loops that have no calls to safePoint and
|
| - // are not wrapped in a SafePointScope (e.g. Interruptor for JavaScript code)
|
| - //
|
| -
|
| - // Request all other threads to stop. Must only be called if the current thread is at safepoint.
|
| - static bool stopThreads();
|
| - static void resumeThreads();
|
| -
|
| - // Check if GC is requested by another thread and pause this thread if this is the case.
|
| - // Can only be called when current thread is in a consistent state.
|
| - void safePoint(StackState);
|
| -
|
| - // Mark current thread as running inside safepoint.
|
| - void enterSafePointWithoutPointers() { enterSafePoint(NoHeapPointersOnStack, 0); }
|
| - void enterSafePointWithPointers(void* scopeMarker) { enterSafePoint(HeapPointersOnStack, scopeMarker); }
|
| - void leaveSafePoint(SafePointAwareMutexLocker* = 0);
|
| - bool isAtSafePoint() const { return m_atSafePoint; }
|
| -
|
| - // If attached thread enters long running loop that can call back
|
| - // into Blink and leaving and reentering safepoint at every
|
| - // transition between this loop and Blink is deemed too expensive
|
| - // then instead of marking this loop as a GC safepoint thread
|
| - // can provide an interruptor object which would allow GC
|
| - // to temporarily interrupt and pause this long running loop at
|
| - // an arbitrary moment creating a safepoint for a GC.
|
| - class PLATFORM_EXPORT Interruptor {
|
| - public:
|
| - virtual ~Interruptor() { }
|
| -
|
| - // Request the interruptor to interrupt the thread and
|
| - // call onInterrupted on that thread once interruption
|
| - // succeeds.
|
| - virtual void requestInterrupt() = 0;
|
| -
|
| - // Clear previous interrupt request.
|
| - virtual void clearInterrupt() = 0;
|
| -
|
| - protected:
|
| - // This method is called on the interrupted thread to
|
| - // create a safepoint for a GC.
|
| - void onInterrupted();
|
| - };
|
| -
|
| - void addInterruptor(Interruptor*);
|
| - void removeInterruptor(Interruptor*);
|
| -
|
| - // CleanupTasks are executed when ThreadState performs
|
| - // cleanup before detaching.
|
| - class CleanupTask {
|
| - public:
|
| - virtual ~CleanupTask() { }
|
| -
|
| - // Executed before the final GC.
|
| - virtual void preCleanup() { }
|
| -
|
| - // Executed after the final GC. Thread heap is empty at this point.
|
| - virtual void postCleanup() { }
|
| - };
|
| -
|
| - void addCleanupTask(PassOwnPtr<CleanupTask> cleanupTask)
|
| - {
|
| - m_cleanupTasks.append(cleanupTask);
|
| - }
|
| -
|
| - // Should only be called under protection of threadAttachMutex().
|
| - const Vector<Interruptor*>& interruptors() const { return m_interruptors; }
|
| -
|
| - void recordStackEnd(intptr_t* endOfStack)
|
| - {
|
| - m_endOfStack = endOfStack;
|
| - }
|
| -
|
| - // Get one of the heap structures for this thread.
|
| - //
|
| - // The heap is split into multiple heap parts based on object
|
| - // types. To get the index for a given type, use
|
| - // HeapTypeTrait<Type>::index.
|
| - BaseHeap* heap(int index) const { return m_heaps[index]; }
|
| -
|
| - // Infrastructure to determine if an address is within one of the
|
| - // address ranges for the Blink heap. If the address is in the Blink
|
| - // heap the containing heap page is returned.
|
| - HeapContainsCache* heapContainsCache() { return m_heapContainsCache.get(); }
|
| - BaseHeapPage* contains(Address address) { return heapPageFromAddress(address); }
|
| - BaseHeapPage* contains(void* pointer) { return contains(reinterpret_cast<Address>(pointer)); }
|
| - BaseHeapPage* contains(const void* pointer) { return contains(const_cast<void*>(pointer)); }
|
| -
|
| - // List of persistent roots allocated on the given thread.
|
| - PersistentNode* roots() const { return m_persistents.get(); }
|
| -
|
| - // List of global persistent roots not owned by any particular thread.
|
| - // globalRootsMutex must be acquired before any modifications.
|
| - static PersistentNode* globalRoots();
|
| - static Mutex& globalRootsMutex();
|
| -
|
| - // Visit local thread stack and trace all pointers conservatively.
|
| - void visitStack(Visitor*);
|
| -
|
| - // Visit the asan fake stack frame corresponding to a slot on the
|
| - // real machine stack if there is one.
|
| - void visitAsanFakeStackForPointer(Visitor*, Address);
|
| -
|
| - // Visit all persistents allocated on this thread.
|
| - void visitPersistents(Visitor*);
|
| -
|
| - // Checks a given address and if a pointer into the oilpan heap marks
|
| - // the object to which it points.
|
| - bool checkAndMarkPointer(Visitor*, Address);
|
| -
|
| -#if ENABLE(GC_PROFILE_MARKING)
|
| - const GCInfo* findGCInfo(Address);
|
| - static const GCInfo* findGCInfoFromAllThreads(Address);
|
| -#endif
|
| -
|
| -#if ENABLE(GC_PROFILE_HEAP)
|
| - struct SnapshotInfo {
|
| - ThreadState* state;
|
| -
|
| - size_t freeSize;
|
| - size_t pageCount;
|
| -
|
| - // Map from base-classes to a snapshot class-ids (used as index below).
|
| - HashMap<const GCInfo*, size_t> classTags;
|
| -
|
| - // Map from class-id (index) to count/size.
|
| - Vector<int> liveCount;
|
| - Vector<int> deadCount;
|
| - Vector<size_t> liveSize;
|
| - Vector<size_t> deadSize;
|
| -
|
| - // Map from class-id (index) to a vector of generation counts.
|
| - // For i < 7, the count is the number of objects that died after surviving |i| GCs.
|
| - // For i == 7, the count is the number of objects that survived at least 7 GCs.
|
| - Vector<Vector<int, 8> > generations;
|
| -
|
| - explicit SnapshotInfo(ThreadState* state) : state(state), freeSize(0), pageCount(0) { }
|
| -
|
| - size_t getClassTag(const GCInfo*);
|
| - };
|
| -
|
| - void snapshot();
|
| -#endif
|
| -
|
| - void pushWeakObjectPointerCallback(void*, WeakPointerCallback);
|
| - bool popAndInvokeWeakPointerCallback(Visitor*);
|
| -
|
| - void getStats(HeapStats&);
|
| - HeapStats& stats() { return m_stats; }
|
| - HeapStats& statsAfterLastGC() { return m_statsAfterLastGC; }
|
| -
|
| - void setupHeapsForTermination();
|
| -
|
| - void registerSweepingTask();
|
| - void unregisterSweepingTask();
|
| -
|
| - Mutex& sweepMutex() { return m_sweepMutex; }
|
| -
|
| -private:
|
| - explicit ThreadState();
|
| - ~ThreadState();
|
| -
|
| - friend class SafePointBarrier;
|
| -
|
| - void enterSafePoint(StackState, void*);
|
| - NO_SANITIZE_ADDRESS void copyStackUntilSafePointScope();
|
| - void clearSafePointScopeMarker()
|
| - {
|
| - m_safePointStackCopy.clear();
|
| - m_safePointScopeMarker = 0;
|
| - }
|
| -
|
| - void performPendingGC(StackState);
|
| -
|
| - // Finds the Blink HeapPage in this thread-specific heap
|
| - // corresponding to a given address. Return 0 if the address is
|
| - // not contained in any of the pages. This does not consider
|
| - // large objects.
|
| - BaseHeapPage* heapPageFromAddress(Address);
|
| -
|
| - // When ThreadState is detaching from non-main thread its
|
| - // heap is expected to be empty (because it is going away).
|
| - // Perform registered cleanup tasks and garbage collection
|
| - // to sweep away any objects that are left on this heap.
|
| - // We assert that nothing must remain after this cleanup.
|
| - // If assertion does not hold we crash as we are potentially
|
| - // in the dangling pointer situation.
|
| - void cleanup();
|
| - void cleanupPages();
|
| -
|
| - void setLowCollectionRate(bool value) { m_lowCollectionRate = value; }
|
| -
|
| - void waitUntilSweepersDone();
|
| -
|
| - static WTF::ThreadSpecific<ThreadState*>* s_threadSpecific;
|
| - static SafePointBarrier* s_safePointBarrier;
|
| -
|
| - // This variable is flipped to true after all threads are stoped
|
| - // and outermost GC has started.
|
| - static bool s_inGC;
|
| -
|
| - // We can't create a static member of type ThreadState here
|
| - // because it will introduce global constructor and destructor.
|
| - // We would like to manage lifetime of the ThreadState attached
|
| - // to the main thread explicitly instead and still use normal
|
| - // constructor and destructor for the ThreadState class.
|
| - // For this we reserve static storage for the main ThreadState
|
| - // and lazily construct ThreadState in it using placement new.
|
| - static uint8_t s_mainThreadStateStorage[];
|
| -
|
| - ThreadIdentifier m_thread;
|
| - OwnPtr<PersistentNode> m_persistents;
|
| - StackState m_stackState;
|
| - intptr_t* m_startOfStack;
|
| - intptr_t* m_endOfStack;
|
| - void* m_safePointScopeMarker;
|
| - Vector<Address> m_safePointStackCopy;
|
| - bool m_atSafePoint;
|
| - Vector<Interruptor*> m_interruptors;
|
| - bool m_gcRequested;
|
| - bool m_forcePreciseGCForTesting;
|
| - volatile int m_sweepRequested;
|
| - bool m_sweepInProgress;
|
| - size_t m_noAllocationCount;
|
| - bool m_inGC;
|
| - BaseHeap* m_heaps[NumberOfHeaps];
|
| - OwnPtr<HeapContainsCache> m_heapContainsCache;
|
| - HeapStats m_stats;
|
| - HeapStats m_statsAfterLastGC;
|
| -
|
| - Vector<OwnPtr<CleanupTask> > m_cleanupTasks;
|
| - bool m_isTerminating;
|
| -
|
| - bool m_lowCollectionRate;
|
| -
|
| - OwnPtr<blink::WebThread> m_sweeperThread;
|
| - int m_numberOfSweeperTasks;
|
| - Mutex m_sweepMutex;
|
| - ThreadCondition m_sweepThreadCondition;
|
| -
|
| - CallbackStack* m_weakCallbackStack;
|
| -
|
| -#if defined(ADDRESS_SANITIZER)
|
| - void* m_asanFakeStack;
|
| -#endif
|
| -};
|
| -
|
| -template<ThreadAffinity affinity> class ThreadStateFor;
|
| -
|
| -template<> class ThreadStateFor<MainThreadOnly> {
|
| -public:
|
| - static ThreadState* state()
|
| - {
|
| - // This specialization must only be used from the main thread.
|
| - return ThreadState::mainThreadState();
|
| - }
|
| -};
|
| -
|
| -template<> class ThreadStateFor<AnyThread> {
|
| -public:
|
| - static ThreadState* state() { return 0; }
|
| -};
|
| -
|
| -// Common header for heap pages. Needs to be defined before class Visitor.
|
| -class BaseHeapPage {
|
| -public:
|
| - BaseHeapPage(PageMemory*, const GCInfo*, ThreadState*);
|
| - virtual ~BaseHeapPage() { }
|
| -
|
| - // Check if the given address points to an object in this
|
| - // heap page. If so, find the start of that object and mark it
|
| - // using the given Visitor. Otherwise do nothing. The pointer must
|
| - // be within the same aligned blinkPageSize as the this-pointer.
|
| - //
|
| - // This is used during conservative stack scanning to
|
| - // conservatively mark all objects that could be referenced from
|
| - // the stack.
|
| - virtual void checkAndMarkPointer(Visitor*, Address) = 0;
|
| - virtual bool contains(Address) = 0;
|
| -
|
| -#if ENABLE(GC_PROFILE_MARKING)
|
| - virtual const GCInfo* findGCInfo(Address) = 0;
|
| -#endif
|
| -
|
| - Address address() { return reinterpret_cast<Address>(this); }
|
| - PageMemory* storage() const { return m_storage; }
|
| - ThreadState* threadState() const { return m_threadState; }
|
| - const GCInfo* gcInfo() { return m_gcInfo; }
|
| - virtual bool isLargeObject() { return false; }
|
| - virtual void markOrphaned()
|
| - {
|
| - m_threadState = 0;
|
| - m_gcInfo = 0;
|
| - m_terminating = false;
|
| - m_tracedAfterOrphaned = false;
|
| - }
|
| - bool orphaned() { return !m_threadState; }
|
| - bool terminating() { return m_terminating; }
|
| - void setTerminating() { m_terminating = true; }
|
| - bool tracedAfterOrphaned() { return m_tracedAfterOrphaned; }
|
| - void setTracedAfterOrphaned() { m_tracedAfterOrphaned = true; }
|
| - size_t promptlyFreedSize() { return m_promptlyFreedSize; }
|
| - void resetPromptlyFreedSize() { m_promptlyFreedSize = 0; }
|
| - void addToPromptlyFreedSize(size_t size) { m_promptlyFreedSize += size; }
|
| -
|
| -private:
|
| - PageMemory* m_storage;
|
| - const GCInfo* m_gcInfo;
|
| - ThreadState* m_threadState;
|
| - // Pointer sized integer to ensure proper alignment of the
|
| - // HeapPage header. We use some of the bits to determine
|
| - // whether the page is part of a terminting thread or
|
| - // if the page is traced after being terminated (orphaned).
|
| - uintptr_t m_terminating : 1;
|
| - uintptr_t m_tracedAfterOrphaned : 1;
|
| - uintptr_t m_promptlyFreedSize : 17; // == blinkPageSizeLog2
|
| -};
|
| -
|
| -}
|
| -
|
| -#endif // ThreadState_h
|
|
|