Home | History | Annotate | Download | only in heap
      1 /*
      2  * Copyright (C) 2013 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #ifndef ThreadState_h
     32 #define ThreadState_h
     33 
     34 #include "platform/PlatformExport.h"
     35 #include "platform/heap/AddressSanitizer.h"
     36 #include "public/platform/WebThread.h"
     37 #include "wtf/HashSet.h"
     38 #include "wtf/OwnPtr.h"
     39 #include "wtf/PassOwnPtr.h"
     40 #include "wtf/ThreadSpecific.h"
     41 #include "wtf/Threading.h"
     42 #include "wtf/ThreadingPrimitives.h"
     43 #include "wtf/Vector.h"
     44 
     45 #if ENABLE(GC_PROFILE_HEAP)
     46 #include "wtf/HashMap.h"
     47 #endif
     48 
     49 namespace blink {
     50 
     51 class BaseHeap;
     52 class BaseHeapPage;
     53 class FinalizedHeapObjectHeader;
     54 struct GCInfo;
     55 class HeapContainsCache;
     56 class HeapObjectHeader;
     57 class PageMemory;
     58 class PersistentNode;
     59 class WrapperPersistentRegion;
     60 class Visitor;
     61 class SafePointBarrier;
     62 class SafePointAwareMutexLocker;
     63 template<typename Header> class ThreadHeap;
     64 class CallbackStack;
     65 
     66 typedef uint8_t* Address;
     67 
     68 typedef void (*FinalizationCallback)(void*);
     69 typedef void (*VisitorCallback)(Visitor*, void* self);
     70 typedef VisitorCallback TraceCallback;
     71 typedef VisitorCallback WeakPointerCallback;
     72 typedef VisitorCallback EphemeronCallback;
     73 
     74 // ThreadAffinity indicates which threads objects can be used on. We
     75 // distinguish between objects that can be used on the main thread
     76 // only and objects that can be used on any thread.
     77 //
     78 // For objects that can only be used on the main thread we avoid going
     79 // through thread-local storage to get to the thread state.
     80 //
     81 // FIXME: We should evaluate the performance gain. Having
     82 // ThreadAffinity is complicating the implementation and we should get
     83 // rid of it if it is fast enough to go through thread-local storage
     84 // always.
     85 enum ThreadAffinity {
     86     AnyThread,
     87     MainThreadOnly,
     88 };
     89 
     90 class Node;
     91 class CSSValue;
     92 
     93 template<typename T, bool derivesNode = WTF::IsSubclass<typename WTF::RemoveConst<T>::Type, Node>::value> struct DefaultThreadingTrait;
     94 
     95 template<typename T>
     96 struct DefaultThreadingTrait<T, false> {
     97     static const ThreadAffinity Affinity = AnyThread;
     98 };
     99 
    100 template<typename T>
    101 struct DefaultThreadingTrait<T, true> {
    102     static const ThreadAffinity Affinity = MainThreadOnly;
    103 };
    104 
    105 template<typename T>
    106 struct ThreadingTrait {
    107     static const ThreadAffinity Affinity = DefaultThreadingTrait<T>::Affinity;
    108 };
    109 
    110 // Marks the specified class as being used from multiple threads. When
    111 // a class is used from multiple threads we go through thread local
    112 // storage to get the heap in which to allocate an object of that type
    113 // and when allocating a Persistent handle for an object with that
    114 // type. Notice that marking the base class does not automatically
    115 // mark its descendants and they have to be explicitly marked.
    116 #define USED_FROM_MULTIPLE_THREADS(Class)                 \
    117     class Class;                                          \
    118     template<> struct ThreadingTrait<Class> {             \
    119         static const ThreadAffinity Affinity = AnyThread; \
    120     }
    121 
    122 #define USED_FROM_MULTIPLE_THREADS_NAMESPACE(Namespace, Class)          \
    123     namespace Namespace {                                               \
    124         class Class;                                                    \
    125     }                                                                   \
    126     namespace blink {                                                 \
    127         template<> struct ThreadingTrait<Namespace::Class> {            \
    128             static const ThreadAffinity Affinity = AnyThread;           \
    129         };                                                              \
    130     }
    131 
    132 template<typename U> class ThreadingTrait<const U> : public ThreadingTrait<U> { };
    133 
    134 // List of typed heaps. The list is used to generate the implementation
    135 // of typed heap related methods.
    136 //
    137 // To create a new typed heap add a H(<ClassName>) to the
    138 // FOR_EACH_TYPED_HEAP macro below.
    139 #define FOR_EACH_TYPED_HEAP(H)  \
    140     H(Node)
    141 
    142 #define TypedHeapEnumName(Type) Type##Heap,
    143 #define TypedHeapEnumNameNonFinalized(Type) Type##HeapNonFinalized,
    144 
    145 enum TypedHeaps {
    146     GeneralHeap = 0,
    147     CollectionBackingHeap,
    148     FOR_EACH_TYPED_HEAP(TypedHeapEnumName)
    149     GeneralHeapNonFinalized,
    150     CollectionBackingHeapNonFinalized,
    151     FOR_EACH_TYPED_HEAP(TypedHeapEnumNameNonFinalized)
    152     // Values used for iteration of heap segments.
    153     NumberOfHeaps,
    154     FirstFinalizedHeap = GeneralHeap,
    155     FirstNonFinalizedHeap = GeneralHeapNonFinalized,
    156     NumberOfFinalizedHeaps = GeneralHeapNonFinalized,
    157     NumberOfNonFinalizedHeaps = NumberOfHeaps - NumberOfFinalizedHeaps,
    158     NonFinalizedHeapOffset = FirstNonFinalizedHeap
    159 };
    160 
    161 // Base implementation for HeapIndexTrait found below.
    162 template<int heapIndex>
    163 struct HeapIndexTraitBase {
    164     typedef FinalizedHeapObjectHeader HeaderType;
    165     typedef ThreadHeap<HeaderType> HeapType;
    166     static const int finalizedIndex = heapIndex;
    167     static const int nonFinalizedIndex = heapIndex + static_cast<int>(NonFinalizedHeapOffset);
    168     static int index(bool isFinalized)
    169     {
    170         return isFinalized ? finalizedIndex : nonFinalizedIndex;
    171     }
    172 };
    173 
    174 // HeapIndexTrait defines properties for each heap in the TypesHeaps enum.
    175 template<int index>
    176 struct HeapIndexTrait;
    177 
    178 template<>
    179 struct HeapIndexTrait<GeneralHeap> : public HeapIndexTraitBase<GeneralHeap> { };
    180 template<>
    181 struct HeapIndexTrait<GeneralHeapNonFinalized> : public HeapIndexTrait<GeneralHeap> { };
    182 
    183 template<>
    184 struct HeapIndexTrait<CollectionBackingHeap> : public HeapIndexTraitBase<CollectionBackingHeap> { };
    185 template<>
    186 struct HeapIndexTrait<CollectionBackingHeapNonFinalized> : public HeapIndexTrait<CollectionBackingHeap> { };
    187 
    188 #define DEFINE_TYPED_HEAP_INDEX_TRAIT(Type)                                     \
    189     template<>                                                                  \
    190     struct HeapIndexTrait<Type##Heap> : public HeapIndexTraitBase<Type##Heap> { \
    191         typedef HeapObjectHeader HeaderType;                                    \
    192         typedef ThreadHeap<HeaderType> HeapType;                                \
    193     };                                                                          \
    194     template<>                                                                  \
    195     struct HeapIndexTrait<Type##HeapNonFinalized> : public HeapIndexTrait<Type##Heap> { };
    196 FOR_EACH_TYPED_HEAP(DEFINE_TYPED_HEAP_INDEX_TRAIT)
    197 #undef DEFINE_TYPED_HEAP_INDEX_TRAIT
    198 
    199 // HeapTypeTrait defines which heap to use for particular types.
    200 // By default objects are allocated in the GeneralHeap.
    201 template<typename T>
    202 struct HeapTypeTrait : public HeapIndexTrait<GeneralHeap> { };
    203 
    204 // We don't have any type-based mappings to the CollectionBackingHeap.
    205 
    206 // Each typed-heap maps the respective type to its heap.
    207 #define DEFINE_TYPED_HEAP_TRAIT(Type)                                   \
    208     class Type;                                                         \
    209     template<>                                                          \
    210     struct HeapTypeTrait<class Type> : public HeapIndexTrait<Type##Heap> { };
    211 FOR_EACH_TYPED_HEAP(DEFINE_TYPED_HEAP_TRAIT)
    212 #undef DEFINE_TYPED_HEAP_TRAIT
    213 
    214 // A HeapStats structure keeps track of the amount of memory allocated
    215 // for a Blink heap and how much of that memory is used for actual
    216 // Blink objects. These stats are used in the heuristics to determine
    217 // when to perform garbage collections.
    218 class HeapStats {
    219 public:
    220     HeapStats() : m_totalObjectSpace(0), m_totalAllocatedSpace(0) { }
    221 
    222     size_t totalObjectSpace() const { return m_totalObjectSpace; }
    223     size_t totalAllocatedSpace() const { return m_totalAllocatedSpace; }
    224 
    225     void add(HeapStats* other)
    226     {
    227         m_totalObjectSpace += other->m_totalObjectSpace;
    228         m_totalAllocatedSpace += other->m_totalAllocatedSpace;
    229     }
    230 
    231     void inline increaseObjectSpace(size_t newObjectSpace)
    232     {
    233         m_totalObjectSpace += newObjectSpace;
    234     }
    235 
    236     void inline decreaseObjectSpace(size_t deadObjectSpace)
    237     {
    238         m_totalObjectSpace -= deadObjectSpace;
    239     }
    240 
    241     void inline increaseAllocatedSpace(size_t newAllocatedSpace)
    242     {
    243         m_totalAllocatedSpace += newAllocatedSpace;
    244     }
    245 
    246     void inline decreaseAllocatedSpace(size_t deadAllocatedSpace)
    247     {
    248         m_totalAllocatedSpace -= deadAllocatedSpace;
    249     }
    250 
    251     void clear()
    252     {
    253         m_totalObjectSpace = 0;
    254         m_totalAllocatedSpace = 0;
    255     }
    256 
    257     bool operator==(const HeapStats& other)
    258     {
    259         return m_totalAllocatedSpace == other.m_totalAllocatedSpace
    260             && m_totalObjectSpace == other.m_totalObjectSpace;
    261     }
    262 
    263 private:
    264     size_t m_totalObjectSpace; // Actually contains objects that may be live, not including headers.
    265     size_t m_totalAllocatedSpace; // Allocated from the OS.
    266 
    267     friend class HeapTester;
    268 };
    269 
    270 class PLATFORM_EXPORT ThreadState {
    271     WTF_MAKE_NONCOPYABLE(ThreadState);
    272 public:
    273     // When garbage collecting we need to know whether or not there
    274     // can be pointers to Blink GC managed objects on the stack for
    275     // each thread. When threads reach a safe point they record
    276     // whether or not they have pointers on the stack.
    277     enum StackState {
    278         NoHeapPointersOnStack,
    279         HeapPointersOnStack
    280     };
    281 
    282     // When profiling we would like to identify forced GC requests.
    283     enum CauseOfGC {
    284         NormalGC,
    285         ForcedGC
    286     };
    287 
    288     class NoSweepScope {
    289     public:
    290         explicit NoSweepScope(ThreadState* state) : m_state(state)
    291         {
    292             ASSERT(!m_state->m_sweepInProgress);
    293             m_state->m_sweepInProgress = true;
    294         }
    295         ~NoSweepScope()
    296         {
    297             ASSERT(m_state->m_sweepInProgress);
    298             m_state->m_sweepInProgress = false;
    299         }
    300     private:
    301         ThreadState* m_state;
    302     };
    303 
    304     // The set of ThreadStates for all threads attached to the Blink
    305     // garbage collector.
    306     typedef HashSet<ThreadState*> AttachedThreadStateSet;
    307     static AttachedThreadStateSet& attachedThreads();
    308 
    309     // Initialize threading infrastructure. Should be called from the main
    310     // thread.
    311     static void init();
    312     static void shutdown();
    313     static void shutdownHeapIfNecessary();
    314     bool isTerminating() { return m_isTerminating; }
    315 
    316     static void attachMainThread();
    317     static void detachMainThread();
    318 
    319     // Trace all persistent roots, called when marking the managed heap objects.
    320     static void visitPersistentRoots(Visitor*);
    321 
    322     // Trace all objects found on the stack, used when doing conservative GCs.
    323     static void visitStackRoots(Visitor*);
    324 
    325     // Associate ThreadState object with the current thread. After this
    326     // call thread can start using the garbage collected heap infrastructure.
    327     // It also has to periodically check for safepoints.
    328     static void attach();
    329 
    330     // Disassociate attached ThreadState from the current thread. The thread
    331     // can no longer use the garbage collected heap after this call.
    332     static void detach();
    333 
    334     static ThreadState* current() { return **s_threadSpecific; }
    335     static ThreadState* mainThreadState()
    336     {
    337         return reinterpret_cast<ThreadState*>(s_mainThreadStateStorage);
    338     }
    339 
    340     bool isMainThread() const { return this == mainThreadState(); }
    341     inline bool checkThread() const
    342     {
    343         ASSERT(m_thread == currentThread());
    344         return true;
    345     }
    346 
    347     // shouldGC and shouldForceConservativeGC implement the heuristics
    348     // that are used to determine when to collect garbage. If
    349     // shouldForceConservativeGC returns true, we force the garbage
    350     // collection immediately. Otherwise, if shouldGC returns true, we
    351     // record that we should garbage collect the next time we return
    352     // to the event loop. If both return false, we don't need to
    353     // collect garbage at this point.
    354     bool shouldGC();
    355     bool shouldForceConservativeGC();
    356     bool increasedEnoughToGC(size_t, size_t);
    357     bool increasedEnoughToForceConservativeGC(size_t, size_t);
    358 
    359     // If gcRequested returns true when a thread returns to its event
    360     // loop the thread will initiate a garbage collection.
    361     bool gcRequested();
    362     void setGCRequested();
    363     void clearGCRequested();
    364 
    365     // Was the last GC forced for testing? This is set when garbage collection
    366     // is forced for testing and there are pointers on the stack. It remains
    367     // set until a garbage collection is triggered with no pointers on the stack.
    368     // This is used for layout tests that trigger GCs and check if objects are
    369     // dead at a given point in time. That only reliably works when we get
    370     // precise GCs with no conservative stack scanning.
    371     void setForcePreciseGCForTesting(bool);
    372     bool forcePreciseGCForTesting();
    373 
    374     bool sweepRequested();
    375     void setSweepRequested();
    376     void clearSweepRequested();
    377     void performPendingSweep();
    378 
    379     // Support for disallowing allocation. Mainly used for sanity
    380     // checks asserts.
    381     bool isAllocationAllowed() const { return !isAtSafePoint() && !m_noAllocationCount; }
    382     void enterNoAllocationScope() { m_noAllocationCount++; }
    383     void leaveNoAllocationScope() { m_noAllocationCount--; }
    384 
    385     // Before performing GC the thread-specific heap state should be
    386     // made consistent for sweeping.
    387     void makeConsistentForSweeping();
    388 #if ENABLE(ASSERT)
    389     bool isConsistentForSweeping();
    390 #endif
    391 
    392     // Is the thread corresponding to this thread state currently
    393     // performing GC?
    394     bool isInGC() const { return m_inGC; }
    395 
    396     // Is any of the threads registered with the blink garbage collection
    397     // infrastructure currently performing GC?
    398     static bool isAnyThreadInGC() { return s_inGC; }
    399 
    400     void enterGC()
    401     {
    402         ASSERT(!m_inGC);
    403         ASSERT(!s_inGC);
    404         m_inGC = true;
    405         s_inGC = true;
    406     }
    407 
    408     void leaveGC()
    409     {
    410         m_inGC = false;
    411         s_inGC = false;
    412     }
    413 
    414     // Is the thread corresponding to this thread state currently
    415     // sweeping?
    416     bool isSweepInProgress() const { return m_sweepInProgress; }
    417 
    418     void prepareForGC();
    419 
    420     // Safepoint related functionality.
    421     //
    422     // When a thread attempts to perform GC it needs to stop all other threads
    423     // that use the heap or at least guarantee that they will not touch any
    424     // heap allocated object until GC is complete.
    425     //
    426     // We say that a thread is at a safepoint if this thread is guaranteed to
    427     // not touch any heap allocated object or any heap related functionality until
    428     // it leaves the safepoint.
    429     //
    430     // Notice that a thread does not have to be paused if it is at safepoint it
    431     // can continue to run and perform tasks that do not require interaction
    432     // with the heap. It will be paused if it attempts to leave the safepoint and
    433     // there is a GC in progress.
    434     //
    435     // Each thread that has ThreadState attached must:
    436     //   - periodically check if GC is requested from another thread by calling a safePoint() method;
    437     //   - use SafePointScope around long running loops that have no safePoint() invocation inside,
    438     //     such loops must not touch any heap object;
    439     //   - register an Interruptor that can interrupt long running loops that have no calls to safePoint and
    440     //     are not wrapped in a SafePointScope (e.g. Interruptor for JavaScript code)
    441     //
    442 
    443     // Request all other threads to stop. Must only be called if the current thread is at safepoint.
    444     static bool stopThreads();
    445     static void resumeThreads();
    446 
    447     // Check if GC is requested by another thread and pause this thread if this is the case.
    448     // Can only be called when current thread is in a consistent state.
    449     void safePoint(StackState);
    450 
    451     // Mark current thread as running inside safepoint.
    452     void enterSafePointWithoutPointers() { enterSafePoint(NoHeapPointersOnStack, 0); }
    453     void enterSafePointWithPointers(void* scopeMarker) { enterSafePoint(HeapPointersOnStack, scopeMarker); }
    454     void leaveSafePoint(SafePointAwareMutexLocker* = 0);
    455     bool isAtSafePoint() const { return m_atSafePoint; }
    456 
    457     class SafePointScope {
    458     public:
    459         enum ScopeNesting {
    460             NoNesting,
    461             AllowNesting
    462         };
    463 
    464         explicit SafePointScope(StackState stackState, ScopeNesting nesting = NoNesting)
    465             : m_state(ThreadState::current())
    466         {
    467             if (m_state->isAtSafePoint()) {
    468                 RELEASE_ASSERT(nesting == AllowNesting);
    469                 // We can ignore stackState because there should be no heap object
    470                 // pointers manipulation after outermost safepoint was entered.
    471                 m_state = 0;
    472             } else {
    473                 m_state->enterSafePoint(stackState, this);
    474             }
    475         }
    476 
    477         ~SafePointScope()
    478         {
    479             if (m_state)
    480                 m_state->leaveSafePoint();
    481         }
    482 
    483     private:
    484         ThreadState* m_state;
    485     };
    486 
    487     // If attached thread enters long running loop that can call back
    488     // into Blink and leaving and reentering safepoint at every
    489     // transition between this loop and Blink is deemed too expensive
    490     // then instead of marking this loop as a GC safepoint thread
    491     // can provide an interruptor object which would allow GC
    492     // to temporarily interrupt and pause this long running loop at
    493     // an arbitrary moment creating a safepoint for a GC.
    494     class PLATFORM_EXPORT Interruptor {
    495     public:
    496         virtual ~Interruptor() { }
    497 
    498         // Request the interruptor to interrupt the thread and
    499         // call onInterrupted on that thread once interruption
    500         // succeeds.
    501         virtual void requestInterrupt() = 0;
    502 
    503         // Clear previous interrupt request.
    504         virtual void clearInterrupt() = 0;
    505 
    506     protected:
    507         // This method is called on the interrupted thread to
    508         // create a safepoint for a GC.
    509         void onInterrupted();
    510     };
    511 
    512     void addInterruptor(Interruptor*);
    513     void removeInterruptor(Interruptor*);
    514 
    515     // CleanupTasks are executed when ThreadState performs
    516     // cleanup before detaching.
    517     class CleanupTask {
    518     public:
    519         virtual ~CleanupTask() { }
    520 
    521         // Executed before the final GC.
    522         virtual void preCleanup() { }
    523 
    524         // Executed after the final GC. Thread heap is empty at this point.
    525         virtual void postCleanup() { }
    526     };
    527 
    528     void addCleanupTask(PassOwnPtr<CleanupTask> cleanupTask)
    529     {
    530         m_cleanupTasks.append(cleanupTask);
    531     }
    532 
    533     // Should only be called under protection of threadAttachMutex().
    534     const Vector<Interruptor*>& interruptors() const { return m_interruptors; }
    535 
    536     void recordStackEnd(intptr_t* endOfStack)
    537     {
    538         m_endOfStack = endOfStack;
    539     }
    540 
    541     // Get one of the heap structures for this thread.
    542     //
    543     // The heap is split into multiple heap parts based on object
    544     // types. To get the index for a given type, use
    545     // HeapTypeTrait<Type>::index.
    546     BaseHeap* heap(int index) const { return m_heaps[index]; }
    547 
    548     // Infrastructure to determine if an address is within one of the
    549     // address ranges for the Blink heap. If the address is in the Blink
    550     // heap the containing heap page is returned.
    551     HeapContainsCache* heapContainsCache() { return m_heapContainsCache.get(); }
    552     BaseHeapPage* contains(Address address) { return heapPageFromAddress(address); }
    553     BaseHeapPage* contains(void* pointer) { return contains(reinterpret_cast<Address>(pointer)); }
    554     BaseHeapPage* contains(const void* pointer) { return contains(const_cast<void*>(pointer)); }
    555 
    556     WrapperPersistentRegion* wrapperRoots() const
    557     {
    558         ASSERT(m_liveWrapperPersistents);
    559         return m_liveWrapperPersistents;
    560     }
    561     WrapperPersistentRegion* takeWrapperPersistentRegion();
    562     void freeWrapperPersistentRegion(WrapperPersistentRegion*);
    563 
    564     // List of persistent roots allocated on the given thread.
    565     PersistentNode* roots() const { return m_persistents.get(); }
    566 
    567     // List of global persistent roots not owned by any particular thread.
    568     // globalRootsMutex must be acquired before any modifications.
    569     static PersistentNode* globalRoots();
    570     static Mutex& globalRootsMutex();
    571 
    572     // Visit local thread stack and trace all pointers conservatively.
    573     void visitStack(Visitor*);
    574 
    575     // Visit the asan fake stack frame corresponding to a slot on the
    576     // real machine stack if there is one.
    577     void visitAsanFakeStackForPointer(Visitor*, Address);
    578 
    579     // Visit all persistents allocated on this thread.
    580     void visitPersistents(Visitor*);
    581 
    582     // Checks a given address and if a pointer into the oilpan heap marks
    583     // the object to which it points.
    584     bool checkAndMarkPointer(Visitor*, Address);
    585 
    586 #if ENABLE(GC_PROFILE_MARKING)
    587     const GCInfo* findGCInfo(Address);
    588     static const GCInfo* findGCInfoFromAllThreads(Address);
    589 #endif
    590 
    591 #if ENABLE(GC_PROFILE_HEAP)
    592     struct SnapshotInfo {
    593         ThreadState* state;
    594 
    595         size_t freeSize;
    596         size_t pageCount;
    597 
    598         // Map from base-classes to a snapshot class-ids (used as index below).
    599         HashMap<const GCInfo*, size_t> classTags;
    600 
    601         // Map from class-id (index) to count/size.
    602         Vector<int> liveCount;
    603         Vector<int> deadCount;
    604         Vector<size_t> liveSize;
    605         Vector<size_t> deadSize;
    606 
    607         // Map from class-id (index) to a vector of generation counts.
    608         // For i < 7, the count is the number of objects that died after surviving |i| GCs.
    609         // For i == 7, the count is the number of objects that survived at least 7 GCs.
    610         Vector<Vector<int, 8> > generations;
    611 
    612         explicit SnapshotInfo(ThreadState* state) : state(state), freeSize(0), pageCount(0) { }
    613 
    614         size_t getClassTag(const GCInfo*);
    615     };
    616 
    617     void snapshot();
    618 #endif
    619 
    620     void pushWeakObjectPointerCallback(void*, WeakPointerCallback);
    621     bool popAndInvokeWeakPointerCallback(Visitor*);
    622 
    623     void getStats(HeapStats&);
    624     HeapStats& stats() { return m_stats; }
    625     HeapStats& statsAfterLastGC() { return m_statsAfterLastGC; }
    626 
    627     void setupHeapsForTermination();
    628 
    629     void registerSweepingTask();
    630     void unregisterSweepingTask();
    631 
    632     Mutex& sweepMutex() { return m_sweepMutex; }
    633 
    634 private:
    635     explicit ThreadState();
    636     ~ThreadState();
    637 
    638     friend class SafePointBarrier;
    639     friend class SafePointAwareMutexLocker;
    640 
    641     void enterSafePoint(StackState, void*);
    642     NO_SANITIZE_ADDRESS void copyStackUntilSafePointScope();
    643     void clearSafePointScopeMarker()
    644     {
    645         m_safePointStackCopy.clear();
    646         m_safePointScopeMarker = 0;
    647     }
    648 
    649     void performPendingGC(StackState);
    650 
    651     // Finds the Blink HeapPage in this thread-specific heap
    652     // corresponding to a given address. Return 0 if the address is
    653     // not contained in any of the pages. This does not consider
    654     // large objects.
    655     BaseHeapPage* heapPageFromAddress(Address);
    656 
    657     // When ThreadState is detaching from non-main thread its
    658     // heap is expected to be empty (because it is going away).
    659     // Perform registered cleanup tasks and garbage collection
    660     // to sweep away any objects that are left on this heap.
    661     // We assert that nothing must remain after this cleanup.
    662     // If assertion does not hold we crash as we are potentially
    663     // in the dangling pointer situation.
    664     void cleanup();
    665     void cleanupPages();
    666 
    667     void setLowCollectionRate(bool value) { m_lowCollectionRate = value; }
    668 
    669     void waitUntilSweepersDone();
    670 
    671     static WTF::ThreadSpecific<ThreadState*>* s_threadSpecific;
    672     static SafePointBarrier* s_safePointBarrier;
    673 
    674     // This variable is flipped to true after all threads are stoped
    675     // and outermost GC has started.
    676     static bool s_inGC;
    677 
    678     // We can't create a static member of type ThreadState here
    679     // because it will introduce global constructor and destructor.
    680     // We would like to manage lifetime of the ThreadState attached
    681     // to the main thread explicitly instead and still use normal
    682     // constructor and destructor for the ThreadState class.
    683     // For this we reserve static storage for the main ThreadState
    684     // and lazily construct ThreadState in it using placement new.
    685     static uint8_t s_mainThreadStateStorage[];
    686 
    687     ThreadIdentifier m_thread;
    688     WrapperPersistentRegion* m_liveWrapperPersistents;
    689     WrapperPersistentRegion* m_pooledWrapperPersistents;
    690     size_t m_pooledWrapperPersistentRegionCount;
    691     OwnPtr<PersistentNode> m_persistents;
    692     StackState m_stackState;
    693     intptr_t* m_startOfStack;
    694     intptr_t* m_endOfStack;
    695     void* m_safePointScopeMarker;
    696     Vector<Address> m_safePointStackCopy;
    697     bool m_atSafePoint;
    698     Vector<Interruptor*> m_interruptors;
    699     bool m_gcRequested;
    700     bool m_forcePreciseGCForTesting;
    701     volatile int m_sweepRequested;
    702     bool m_sweepInProgress;
    703     size_t m_noAllocationCount;
    704     bool m_inGC;
    705     BaseHeap* m_heaps[NumberOfHeaps];
    706     OwnPtr<HeapContainsCache> m_heapContainsCache;
    707     HeapStats m_stats;
    708     HeapStats m_statsAfterLastGC;
    709 
    710     Vector<OwnPtr<CleanupTask> > m_cleanupTasks;
    711     bool m_isTerminating;
    712 
    713     bool m_lowCollectionRate;
    714 
    715     OwnPtr<blink::WebThread> m_sweeperThread;
    716     int m_numberOfSweeperTasks;
    717     Mutex m_sweepMutex;
    718     ThreadCondition m_sweepThreadCondition;
    719 
    720     CallbackStack* m_weakCallbackStack;
    721 
    722 #if defined(ADDRESS_SANITIZER)
    723     void* m_asanFakeStack;
    724 #endif
    725 };
    726 
    727 template<ThreadAffinity affinity> class ThreadStateFor;
    728 
    729 template<> class ThreadStateFor<MainThreadOnly> {
    730 public:
    731     static ThreadState* state()
    732     {
    733         // This specialization must only be used from the main thread.
    734         ASSERT(ThreadState::current()->isMainThread());
    735         return ThreadState::mainThreadState();
    736     }
    737 };
    738 
    739 template<> class ThreadStateFor<AnyThread> {
    740 public:
    741     static ThreadState* state() { return ThreadState::current(); }
    742 };
    743 
    744 // The SafePointAwareMutexLocker is used to enter a safepoint while waiting for
    745 // a mutex lock. It also ensures that the lock is not held while waiting for a GC
    746 // to complete in the leaveSafePoint method, by releasing the lock if the
    747 // leaveSafePoint method cannot complete without blocking, see
    748 // SafePointBarrier::checkAndPark.
    749 class SafePointAwareMutexLocker {
    750     WTF_MAKE_NONCOPYABLE(SafePointAwareMutexLocker);
    751 public:
    752     explicit SafePointAwareMutexLocker(MutexBase& mutex, ThreadState::StackState stackState = ThreadState::HeapPointersOnStack)
    753         : m_mutex(mutex)
    754         , m_locked(false)
    755     {
    756         ThreadState* state = ThreadState::current();
    757         do {
    758             bool leaveSafePoint = false;
    759             // We cannot enter a safepoint if we are currently sweeping. In that
    760             // case we just try to acquire the lock without being at a safepoint.
    761             // If another thread tries to do a GC at that time it might time out
    762             // due to this thread not being at a safepoint and waiting on the lock.
    763             if (!state->isSweepInProgress() && !state->isAtSafePoint()) {
    764                 state->enterSafePoint(stackState, this);
    765                 leaveSafePoint = true;
    766             }
    767             m_mutex.lock();
    768             m_locked = true;
    769             if (leaveSafePoint) {
    770                 // When leaving the safepoint we might end up release the mutex
    771                 // if another thread is requesting a GC, see
    772                 // SafePointBarrier::checkAndPark. This is the case where we
    773                 // loop around to reacquire the lock.
    774                 state->leaveSafePoint(this);
    775             }
    776         } while (!m_locked);
    777     }
    778 
    779     ~SafePointAwareMutexLocker()
    780     {
    781         ASSERT(m_locked);
    782         m_mutex.unlock();
    783     }
    784 
    785 private:
    786     friend class SafePointBarrier;
    787 
    788     void reset()
    789     {
    790         ASSERT(m_locked);
    791         m_mutex.unlock();
    792         m_locked = false;
    793     }
    794 
    795     MutexBase& m_mutex;
    796     bool m_locked;
    797 };
    798 
    799 // Common header for heap pages. Needs to be defined before class Visitor.
    800 class BaseHeapPage {
    801 public:
    802     BaseHeapPage(PageMemory*, const GCInfo*, ThreadState*);
    803     virtual ~BaseHeapPage() { }
    804 
    805     // Check if the given address points to an object in this
    806     // heap page. If so, find the start of that object and mark it
    807     // using the given Visitor. Otherwise do nothing. The pointer must
    808     // be within the same aligned blinkPageSize as the this-pointer.
    809     //
    810     // This is used during conservative stack scanning to
    811     // conservatively mark all objects that could be referenced from
    812     // the stack.
    813     virtual void checkAndMarkPointer(Visitor*, Address) = 0;
    814     virtual bool contains(Address) = 0;
    815 
    816 #if ENABLE(GC_PROFILE_MARKING)
    817     virtual const GCInfo* findGCInfo(Address) = 0;
    818 #endif
    819 
    820     Address address() { return reinterpret_cast<Address>(this); }
    821     PageMemory* storage() const { return m_storage; }
    822     ThreadState* threadState() const { return m_threadState; }
    823     const GCInfo* gcInfo() { return m_gcInfo; }
    824     virtual bool isLargeObject() { return false; }
    825     virtual void markOrphaned()
    826     {
    827         m_threadState = 0;
    828         m_gcInfo = 0;
    829         m_terminating = false;
    830         m_tracedAfterOrphaned = false;
    831     }
    832     bool orphaned() { return !m_threadState; }
    833     bool terminating() { return m_terminating; }
    834     void setTerminating() { m_terminating = true; }
    835     bool tracedAfterOrphaned() { return m_tracedAfterOrphaned; }
    836     void setTracedAfterOrphaned() { m_tracedAfterOrphaned = true; }
    837     size_t promptlyFreedSize() { return m_promptlyFreedSize; }
    838     void resetPromptlyFreedSize() { m_promptlyFreedSize = 0; }
    839     void addToPromptlyFreedSize(size_t size) { m_promptlyFreedSize += size; }
    840 
    841 private:
    842     PageMemory* m_storage;
    843     const GCInfo* m_gcInfo;
    844     ThreadState* m_threadState;
    845     // Pointer sized integer to ensure proper alignment of the
    846     // HeapPage header. We use some of the bits to determine
    847     // whether the page is part of a terminting thread or
    848     // if the page is traced after being terminated (orphaned).
    849     uintptr_t m_terminating : 1;
    850     uintptr_t m_tracedAfterOrphaned : 1;
    851     uintptr_t m_promptlyFreedSize : 17; // == blinkPageSizeLog2
    852 };
    853 
    854 }
    855 
    856 #endif // ThreadState_h
    857