| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 class BasePage; | 54 class BasePage; |
| 55 class CallbackStack; | 55 class CallbackStack; |
| 56 struct GCInfo; | 56 struct GCInfo; |
| 57 class GarbageCollectedMixinConstructorMarker; | 57 class GarbageCollectedMixinConstructorMarker; |
| 58 class HeapObjectHeader; | 58 class HeapObjectHeader; |
| 59 class PersistentNode; | 59 class PersistentNode; |
| 60 class PersistentRegion; | 60 class PersistentRegion; |
| 61 class BaseArena; | 61 class BaseArena; |
| 62 class SafePointAwareMutexLocker; | 62 class SafePointAwareMutexLocker; |
| 63 class SafePointBarrier; | 63 class SafePointBarrier; |
| 64 class ThreadHeap; |
| 64 class ThreadState; | 65 class ThreadState; |
| 65 class Visitor; | 66 class Visitor; |
| 66 | 67 |
| 67 // Declare that a class has a pre-finalizer. The pre-finalizer is called | 68 // Declare that a class has a pre-finalizer. The pre-finalizer is called |
| 68 // before any object gets swept, so it is safe to touch on-heap objects | 69 // before any object gets swept, so it is safe to touch on-heap objects |
| 69 // that may be collected in the same GC cycle. If you cannot avoid touching | 70 // that may be collected in the same GC cycle. If you cannot avoid touching |
| 70 // on-heap objects in a destructor (which is not allowed), you can consider | 71 // on-heap objects in a destructor (which is not allowed), you can consider |
| 71 // using the pre-finalizer. The only restriction is that the pre-finalizer | 72 // using the pre-finalizer. The only restriction is that the pre-finalizer |
| 72 // must not resurrect dead objects (e.g., store unmarked objects into | 73 // must not resurrect dead objects (e.g., store unmarked objects into |
| 73 // Members etc). The pre-finalizer is called on the thread that registered | 74 // Members etc). The pre-finalizer is called on the thread that registered |
| (...skipping 25 matching lines...) Expand all Loading... |
| 99 // { | 100 // { |
| 100 // m_bar->...; // It is safe to touch other on-heap objects. | 101 // m_bar->...; // It is safe to touch other on-heap objects. |
| 101 // } | 102 // } |
| 102 // Member<Bar> m_bar; | 103 // Member<Bar> m_bar; |
| 103 // }; | 104 // }; |
| 104 #define USING_PRE_FINALIZER(Class, preFinalizer) \ | 105 #define USING_PRE_FINALIZER(Class, preFinalizer) \ |
| 105 public: \ | 106 public: \ |
| 106 static bool invokePreFinalizer(void* object) \ | 107 static bool invokePreFinalizer(void* object) \ |
| 107 { \ | 108 { \ |
| 108 Class* self = reinterpret_cast<Class*>(object); \ | 109 Class* self = reinterpret_cast<Class*>(object); \ |
| 109 if (Heap::isHeapObjectAlive(self)) \ | 110 if (ThreadHeap::isHeapObjectAlive(self)) \ |
| 110 return false; \ | 111 return false; \ |
| 111 self->Class::preFinalizer(); \ | 112 self->Class::preFinalizer(); \ |
| 112 return true; \ | 113 return true; \ |
| 113 } \ | 114 } \ |
| 114 using UsingPreFinalizerMacroNeedsTrailingSemiColon = char | 115 using UsingPreFinalizerMacroNeedsTrailingSemiColon = char |
| 115 | 116 |
| 116 #if ENABLE(OILPAN) | 117 #if ENABLE(OILPAN) |
| 117 #define WILL_BE_USING_PRE_FINALIZER(Class, method) USING_PRE_FINALIZER(Class, me
thod) | 118 #define WILL_BE_USING_PRE_FINALIZER(Class, method) USING_PRE_FINALIZER(Class, me
thod) |
| 118 #else | 119 #else |
| 119 #define WILL_BE_USING_PRE_FINALIZER(Class, method) | 120 #define WILL_BE_USING_PRE_FINALIZER(Class, method) |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 167 } | 168 } |
| 168 ~SweepForbiddenScope() | 169 ~SweepForbiddenScope() |
| 169 { | 170 { |
| 170 ASSERT(m_state->m_sweepForbidden); | 171 ASSERT(m_state->m_sweepForbidden); |
| 171 m_state->m_sweepForbidden = false; | 172 m_state->m_sweepForbidden = false; |
| 172 } | 173 } |
| 173 private: | 174 private: |
| 174 ThreadState* m_state; | 175 ThreadState* m_state; |
| 175 }; | 176 }; |
| 176 | 177 |
| 177 // The set of ThreadStates for all threads attached to the Blink | 178 void lockThreadAttachMutex(); |
| 178 // garbage collector. | 179 void unlockThreadAttachMutex(); |
| 179 using AttachedThreadStateSet = HashSet<ThreadState*>; | |
| 180 static AttachedThreadStateSet& attachedThreads(); | |
| 181 static RecursiveMutex& threadAttachMutex(); | |
| 182 static void lockThreadAttachMutex(); | |
| 183 static void unlockThreadAttachMutex(); | |
| 184 | 180 |
| 185 // Initialize threading infrastructure. Should be called from the main | 181 // Initialize threading infrastructure. Should be called from the main |
| 186 // thread. | 182 // thread. |
| 187 static void init(); | 183 static void init(); |
| 188 static void shutdown(); | |
| 189 bool isTerminating() { return m_isTerminating; } | 184 bool isTerminating() { return m_isTerminating; } |
| 190 | 185 |
| 191 static void attachMainThread(); | 186 static void attachMainThread(); |
| 192 static void detachMainThread(); | 187 static void detachMainThread(); |
| 193 void cleanupMainThread(); | 188 void cleanupMainThread(); |
| 194 | 189 |
| 195 // Trace all persistent roots, called when marking the managed heap objects. | |
| 196 static void visitPersistentRoots(Visitor*); | |
| 197 | |
| 198 // Trace all objects found on the stack, used when doing conservative GCs. | |
| 199 static void visitStackRoots(Visitor*); | |
| 200 | |
| 201 // Associate ThreadState object with the current thread. After this | 190 // Associate ThreadState object with the current thread. After this |
| 202 // call thread can start using the garbage collected heap infrastructure. | 191 // call thread can start using the garbage collected heap infrastructure. |
| 203 // It also has to periodically check for safepoints. | 192 // It also has to periodically check for safepoints. |
| 204 static void attach(); | 193 static void attach(); |
| 205 | 194 |
| 206 // Disassociate attached ThreadState from the current thread. The thread | 195 // Disassociate attached ThreadState from the current thread. The thread |
| 207 // can no longer use the garbage collected heap after this call. | 196 // can no longer use the garbage collected heap after this call. |
| 208 static void detach(); | 197 static void detachCurrentThread(); |
| 198 void detach(); |
| 209 | 199 |
| 210 static ThreadState* current() | 200 static ThreadState* current() |
| 211 { | 201 { |
| 212 #if defined(__GLIBC__) || OS(ANDROID) || OS(FREEBSD) | 202 #if defined(__GLIBC__) || OS(ANDROID) || OS(FREEBSD) |
| 213 // TLS lookup is fast in these platforms. | 203 // TLS lookup is fast in these platforms. |
| 214 return **s_threadSpecific; | 204 return **s_threadSpecific; |
| 215 #else | 205 #else |
| 216 uintptr_t dummy; | 206 uintptr_t dummy; |
| 217 uintptr_t addressDiff = s_mainThreadStackStart - reinterpret_cast<uintpt
r_t>(&dummy); | 207 uintptr_t addressDiff = s_mainThreadStackStart - reinterpret_cast<uintpt
r_t>(&dummy); |
| 218 // This is a fast way to judge if we are in the main thread. | 208 // This is a fast way to judge if we are in the main thread. |
| 219 // If |&dummy| is within |s_mainThreadUnderestimatedStackSize| byte from | 209 // If |&dummy| is within |s_mainThreadUnderestimatedStackSize| byte from |
| 220 // the stack start of the main thread, we judge that we are in | 210 // the stack start of the main thread, we judge that we are in |
| 221 // the main thread. | 211 // the main thread. |
| 222 if (LIKELY(addressDiff < s_mainThreadUnderestimatedStackSize)) { | 212 if (LIKELY(addressDiff < s_mainThreadUnderestimatedStackSize)) { |
| 223 ASSERT(**s_threadSpecific == mainThreadState()); | 213 ASSERT(**s_threadSpecific == mainThreadState()); |
| 224 return mainThreadState(); | 214 return mainThreadState(); |
| 225 } | 215 } |
| 226 // TLS lookup is slow. | 216 // TLS lookup is slow. |
| 227 return **s_threadSpecific; | 217 return **s_threadSpecific; |
| 228 #endif | 218 #endif |
| 229 } | 219 } |
| 230 | 220 |
| 231 static ThreadState* mainThreadState() | 221 static ThreadState* mainThreadState() |
| 232 { | 222 { |
| 233 return reinterpret_cast<ThreadState*>(s_mainThreadStateStorage); | 223 return reinterpret_cast<ThreadState*>(s_mainThreadStateStorage); |
| 234 } | 224 } |
| 235 | 225 |
| 226 static ThreadState* fromObject(const void*); |
| 227 |
| 236 bool isMainThread() const { return this == mainThreadState(); } | 228 bool isMainThread() const { return this == mainThreadState(); } |
| 237 #if ENABLE(ASSERT) | 229 #if ENABLE(ASSERT) |
| 238 bool checkThread() const { return m_thread == currentThread(); } | 230 bool checkThread() const { return m_thread == currentThread(); } |
| 239 #endif | 231 #endif |
| 240 | 232 |
| 233 ThreadHeap& heap() { return *m_heap; } |
| 234 |
| 235 // When ThreadState is detaching from non-main thread its |
| 236 // heap is expected to be empty (because it is going away). |
| 237 // Perform registered cleanup tasks and garbage collection |
| 238 // to sweep away any objects that are left on this heap. |
| 239 // We assert that nothing must remain after this cleanup. |
| 240 // If assertion does not hold we crash as we are potentially |
| 241 // in the dangling pointer situation. |
| 242 void runThreadTerminationGC(); |
| 243 |
| 241 void performIdleGC(double deadlineSeconds); | 244 void performIdleGC(double deadlineSeconds); |
| 242 void performIdleLazySweep(double deadlineSeconds); | 245 void performIdleLazySweep(double deadlineSeconds); |
| 243 | 246 |
| 244 void scheduleIdleGC(); | 247 void scheduleIdleGC(); |
| 245 void scheduleIdleLazySweep(); | 248 void scheduleIdleLazySweep(); |
| 246 void schedulePreciseGC(); | 249 void schedulePreciseGC(); |
| 247 void scheduleV8FollowupGCIfNeeded(BlinkGC::V8GCType); | 250 void scheduleV8FollowupGCIfNeeded(BlinkGC::V8GCType); |
| 248 void schedulePageNavigationGCIfNeeded(float estimatedRemovalRatio); | 251 void schedulePageNavigationGCIfNeeded(float estimatedRemovalRatio); |
| 249 void schedulePageNavigationGC(); | 252 void schedulePageNavigationGC(); |
| 250 void scheduleGCIfNeeded(); | 253 void scheduleGCIfNeeded(); |
| 251 void willStartV8GC(BlinkGC::V8GCType); | 254 void willStartV8GC(BlinkGC::V8GCType); |
| 252 void setGCState(GCState); | 255 void setGCState(GCState); |
| 253 GCState gcState() const { return m_gcState; } | 256 GCState gcState() const { return m_gcState; } |
| 254 bool isInGC() const { return gcState() == GCRunning; } | 257 bool isInGC() const { return gcState() == GCRunning; } |
| 255 bool isSweepingInProgress() const | 258 bool isSweepingInProgress() const |
| 256 { | 259 { |
| 257 return gcState() == Sweeping || gcState() == SweepingAndPreciseGCSchedul
ed || gcState() == SweepingAndIdleGCScheduled; | 260 return gcState() == Sweeping || gcState() == SweepingAndPreciseGCSchedul
ed || gcState() == SweepingAndIdleGCScheduled; |
| 258 } | 261 } |
| 259 | 262 |
| 260 // A GC runs in the following sequence. | 263 // A GC runs in the following sequence. |
| 261 // | 264 // |
| 262 // 1) All threads park at safe points. | 265 // 1) All threads park at safe points. |
| 263 // 2) The GCing thread calls preGC() for all ThreadStates. | 266 // 2) The GCing thread calls preGC() for all ThreadStates. |
| 264 // 3) The GCing thread calls Heap::collectGarbage(). | 267 // 3) The GCing thread calls ThreadHeap::collectGarbage(). |
| 265 // This does marking but doesn't do sweeping. | 268 // This does marking but doesn't do sweeping. |
| 266 // 4) The GCing thread calls postGC() for all ThreadStates. | 269 // 4) The GCing thread calls postGC() for all ThreadStates. |
| 267 // 5) The GCing thread resume all threads. | 270 // 5) The GCing thread resume all threads. |
| 268 // 6) Each thread calls preSweep(). | 271 // 6) Each thread calls preSweep(). |
| 269 // 7) Each thread runs lazy sweeping (concurrently with sweepings | 272 // 7) Each thread runs lazy sweeping (concurrently with sweepings |
| 270 // in other threads) and eventually calls completeSweep(). | 273 // in other threads) and eventually calls completeSweep(). |
| 271 // 8) Each thread calls postSweep(). | 274 // 8) Each thread calls postSweep(). |
| 272 // | 275 // |
| 273 // Notes: | 276 // Notes: |
| 274 // - We stop the world between 1) and 5). | 277 // - We stop the world between 1) and 5). |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 322 // there is a GC in progress. | 325 // there is a GC in progress. |
| 323 // | 326 // |
| 324 // Each thread that has ThreadState attached must: | 327 // Each thread that has ThreadState attached must: |
| 325 // - periodically check if GC is requested from another thread by calling
a safePoint() method; | 328 // - periodically check if GC is requested from another thread by calling
a safePoint() method; |
| 326 // - use SafePointScope around long running loops that have no safePoint()
invocation inside, | 329 // - use SafePointScope around long running loops that have no safePoint()
invocation inside, |
| 327 // such loops must not touch any heap object; | 330 // such loops must not touch any heap object; |
| 328 // - register an BlinkGCInterruptor that can interrupt long running loops
that have no calls to safePoint and | 331 // - register an BlinkGCInterruptor that can interrupt long running loops
that have no calls to safePoint and |
| 329 // are not wrapped in a SafePointScope (e.g. BlinkGCInterruptor for Java
Script code) | 332 // are not wrapped in a SafePointScope (e.g. BlinkGCInterruptor for Java
Script code) |
| 330 // | 333 // |
| 331 | 334 |
| 332 // Request all other threads to stop. Must only be called if the current thr
ead is at safepoint. | |
| 333 static bool stopThreads(); | |
| 334 static void resumeThreads(); | |
| 335 | |
| 336 // Check if GC is requested by another thread and pause this thread if this
is the case. | 335 // Check if GC is requested by another thread and pause this thread if this
is the case. |
| 337 // Can only be called when current thread is in a consistent state. | 336 // Can only be called when current thread is in a consistent state. |
| 338 void safePoint(BlinkGC::StackState); | 337 void safePoint(BlinkGC::StackState); |
| 339 | 338 |
| 340 // Mark current thread as running inside safepoint. | 339 // Mark current thread as running inside safepoint. |
| 341 void enterSafePoint(BlinkGC::StackState, void*); | 340 void enterSafePoint(BlinkGC::StackState, void*); |
| 342 void leaveSafePoint(SafePointAwareMutexLocker* = nullptr); | 341 void leaveSafePoint(SafePointAwareMutexLocker* = nullptr); |
| 343 bool isAtSafePoint() const { return m_atSafePoint; } | 342 bool isAtSafePoint() const { return m_atSafePoint; } |
| 344 | 343 |
| 345 void addInterruptor(PassOwnPtr<BlinkGCInterruptor>); | 344 void addInterruptor(PassOwnPtr<BlinkGCInterruptor>); |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 577 | 576 |
| 578 void runScheduledGC(BlinkGC::StackState); | 577 void runScheduledGC(BlinkGC::StackState); |
| 579 | 578 |
| 580 void eagerSweep(); | 579 void eagerSweep(); |
| 581 | 580 |
| 582 #if defined(ADDRESS_SANITIZER) | 581 #if defined(ADDRESS_SANITIZER) |
| 583 void poisonEagerArena(); | 582 void poisonEagerArena(); |
| 584 void poisonAllHeaps(); | 583 void poisonAllHeaps(); |
| 585 #endif | 584 #endif |
| 586 | 585 |
| 587 // When ThreadState is detaching from non-main thread its | |
| 588 // heap is expected to be empty (because it is going away). | |
| 589 // Perform registered cleanup tasks and garbage collection | |
| 590 // to sweep away any objects that are left on this heap. | |
| 591 // We assert that nothing must remain after this cleanup. | |
| 592 // If assertion does not hold we crash as we are potentially | |
| 593 // in the dangling pointer situation. | |
| 594 void cleanup(); | |
| 595 void cleanupPages(); | 586 void cleanupPages(); |
| 596 | 587 |
| 597 void prepareForThreadStateTermination(); | 588 void prepareForThreadStateTermination(); |
| 598 | 589 |
| 599 void invokePreFinalizers(); | 590 void invokePreFinalizers(); |
| 600 | 591 |
| 601 void takeSnapshot(SnapshotType); | 592 void takeSnapshot(SnapshotType); |
| 602 void clearArenaAges(); | 593 void clearArenaAges(); |
| 603 int arenaIndexOfVectorArenaLeastRecentlyExpanded(int beginArenaIndex, int en
dArenaIndex); | 594 int arenaIndexOfVectorArenaLeastRecentlyExpanded(int beginArenaIndex, int en
dArenaIndex); |
| 604 | 595 |
| 605 void reportMemoryToV8(); | 596 void reportMemoryToV8(); |
| 606 | 597 |
| 607 // Should only be called under protection of threadAttachMutex(). | 598 // Should only be called under protection of threadAttachMutex(). |
| 608 const Vector<OwnPtr<BlinkGCInterruptor>>& interruptors() const { return m_in
terruptors; } | 599 const Vector<OwnPtr<BlinkGCInterruptor>>& interruptors() const { return m_in
terruptors; } |
| 609 | 600 |
| 610 friend class SafePointAwareMutexLocker; | 601 friend class SafePointAwareMutexLocker; |
| 611 friend class SafePointBarrier; | 602 friend class SafePointBarrier; |
| 612 friend class SafePointScope; | 603 friend class SafePointScope; |
| 613 | 604 |
| 614 static WTF::ThreadSpecific<ThreadState*>* s_threadSpecific; | 605 static WTF::ThreadSpecific<ThreadState*>* s_threadSpecific; |
| 615 static uintptr_t s_mainThreadStackStart; | 606 static uintptr_t s_mainThreadStackStart; |
| 616 static uintptr_t s_mainThreadUnderestimatedStackSize; | 607 static uintptr_t s_mainThreadUnderestimatedStackSize; |
| 617 static SafePointBarrier* s_safePointBarrier; | |
| 618 | 608 |
| 619 // We can't create a static member of type ThreadState here | 609 // We can't create a static member of type ThreadState here |
| 620 // because it will introduce global constructor and destructor. | 610 // because it will introduce global constructor and destructor. |
| 621 // We would like to manage lifetime of the ThreadState attached | 611 // We would like to manage lifetime of the ThreadState attached |
| 622 // to the main thread explicitly instead and still use normal | 612 // to the main thread explicitly instead and still use normal |
| 623 // constructor and destructor for the ThreadState class. | 613 // constructor and destructor for the ThreadState class. |
| 624 // For this we reserve static storage for the main ThreadState | 614 // For this we reserve static storage for the main ThreadState |
| 625 // and lazily construct ThreadState in it using placement new. | 615 // and lazily construct ThreadState in it using placement new. |
| 626 static uint8_t s_mainThreadStateStorage[]; | 616 static uint8_t s_mainThreadStateStorage[]; |
| 627 | 617 |
| 618 ThreadHeap* m_heap; |
| 628 ThreadIdentifier m_thread; | 619 ThreadIdentifier m_thread; |
| 629 OwnPtr<PersistentRegion> m_persistentRegion; | 620 OwnPtr<PersistentRegion> m_persistentRegion; |
| 630 BlinkGC::StackState m_stackState; | 621 BlinkGC::StackState m_stackState; |
| 631 #if OS(WIN) && COMPILER(MSVC) | 622 #if OS(WIN) && COMPILER(MSVC) |
| 632 size_t m_threadStackSize; | 623 size_t m_threadStackSize; |
| 633 #endif | 624 #endif |
| 634 intptr_t* m_startOfStack; | 625 intptr_t* m_startOfStack; |
| 635 intptr_t* m_endOfStack; | 626 intptr_t* m_endOfStack; |
| 636 | 627 |
| 637 void* m_safePointScopeMarker; | 628 void* m_safePointScopeMarker; |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 706 | 697 |
| 707 template<> class ThreadStateFor<AnyThread> { | 698 template<> class ThreadStateFor<AnyThread> { |
| 708 STATIC_ONLY(ThreadStateFor); | 699 STATIC_ONLY(ThreadStateFor); |
| 709 public: | 700 public: |
| 710 static ThreadState* state() { return ThreadState::current(); } | 701 static ThreadState* state() { return ThreadState::current(); } |
| 711 }; | 702 }; |
| 712 | 703 |
| 713 } // namespace blink | 704 } // namespace blink |
| 714 | 705 |
| 715 #endif // ThreadState_h | 706 #endif // ThreadState_h |
| OLD | NEW |