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