| 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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 55 class BasePage; | 55 class BasePage; |
| 56 class CallbackStack; | 56 class CallbackStack; |
| 57 struct GCInfo; | 57 struct GCInfo; |
| 58 class GarbageCollectedMixinConstructorMarker; | 58 class GarbageCollectedMixinConstructorMarker; |
| 59 class HeapObjectHeader; | 59 class HeapObjectHeader; |
| 60 class PersistentNode; | 60 class PersistentNode; |
| 61 class PersistentRegion; | 61 class PersistentRegion; |
| 62 class BaseArena; | 62 class BaseArena; |
| 63 class SafePointAwareMutexLocker; | 63 class SafePointAwareMutexLocker; |
| 64 class SafePointBarrier; | 64 class SafePointBarrier; |
| 65 class ThreadHeap; |
| 65 class ThreadState; | 66 class ThreadState; |
| 66 class Visitor; | 67 class Visitor; |
| 67 | 68 |
| 68 // Declare that a class has a pre-finalizer. The pre-finalizer is called | 69 // Declare that a class has a pre-finalizer. The pre-finalizer is called |
| 69 // before any object gets swept, so it is safe to touch on-heap objects | 70 // before any object gets swept, so it is safe to touch on-heap objects |
| 70 // that may be collected in the same GC cycle. If you cannot avoid touching | 71 // that may be collected in the same GC cycle. If you cannot avoid touching |
| 71 // on-heap objects in a destructor (which is not allowed), you can consider | 72 // on-heap objects in a destructor (which is not allowed), you can consider |
| 72 // using the pre-finalizer. The only restriction is that the pre-finalizer | 73 // using the pre-finalizer. The only restriction is that the pre-finalizer |
| 73 // must not resurrect dead objects (e.g., store unmarked objects into | 74 // must not resurrect dead objects (e.g., store unmarked objects into |
| 74 // Members etc). The pre-finalizer is called on the thread that registered | 75 // Members etc). The pre-finalizer is called on the thread that registered |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 162 } | 163 } |
| 163 ~SweepForbiddenScope() | 164 ~SweepForbiddenScope() |
| 164 { | 165 { |
| 165 ASSERT(m_state->m_sweepForbidden); | 166 ASSERT(m_state->m_sweepForbidden); |
| 166 m_state->m_sweepForbidden = false; | 167 m_state->m_sweepForbidden = false; |
| 167 } | 168 } |
| 168 private: | 169 private: |
| 169 ThreadState* m_state; | 170 ThreadState* m_state; |
| 170 }; | 171 }; |
| 171 | 172 |
| 172 // The set of ThreadStates for all threads attached to the Blink | 173 void lockThreadAttachMutex(); |
| 173 // garbage collector. | 174 void unlockThreadAttachMutex(); |
| 174 using AttachedThreadStateSet = HashSet<ThreadState*>; | |
| 175 static AttachedThreadStateSet& attachedThreads(); | |
| 176 static RecursiveMutex& threadAttachMutex(); | |
| 177 static void lockThreadAttachMutex(); | |
| 178 static void unlockThreadAttachMutex(); | |
| 179 | 175 |
| 180 // Initialize threading infrastructure. Should be called from the main | |
| 181 // thread. | |
| 182 static void init(); | |
| 183 static void shutdown(); | |
| 184 bool isTerminating() { return m_isTerminating; } | 176 bool isTerminating() { return m_isTerminating; } |
| 185 | 177 |
| 186 static void attachMainThread(); | 178 static void attachMainThread(); |
| 187 static void detachMainThread(); | 179 static void detachMainThread(); |
| 188 void cleanupMainThread(); | 180 void cleanupMainThread(); |
| 189 | 181 |
| 190 // Trace all persistent roots, called when marking the managed heap objects. | |
| 191 static void visitPersistentRoots(Visitor*); | |
| 192 | |
| 193 // Trace all objects found on the stack, used when doing conservative GCs. | |
| 194 static void visitStackRoots(Visitor*); | |
| 195 | |
| 196 // Associate ThreadState object with the current thread. After this | 182 // Associate ThreadState object with the current thread. After this |
| 197 // call thread can start using the garbage collected heap infrastructure. | 183 // call thread can start using the garbage collected heap infrastructure. |
| 198 // It also has to periodically check for safepoints. | 184 // It also has to periodically check for safepoints. |
| 199 static void attach(); | 185 static void attachCurrentThread(); |
| 200 | 186 |
| 201 // Disassociate attached ThreadState from the current thread. The thread | 187 // Disassociate attached ThreadState from the current thread. The thread |
| 202 // can no longer use the garbage collected heap after this call. | 188 // can no longer use the garbage collected heap after this call. |
| 203 static void detach(); | 189 static void detachCurrentThread(); |
| 204 | 190 |
| 205 static ThreadState* current() | 191 static ThreadState* current() |
| 206 { | 192 { |
| 207 #if defined(__GLIBC__) || OS(ANDROID) || OS(FREEBSD) | 193 #if defined(__GLIBC__) || OS(ANDROID) || OS(FREEBSD) |
| 208 // TLS lookup is fast in these platforms. | 194 // TLS lookup is fast in these platforms. |
| 209 return **s_threadSpecific; | 195 return **s_threadSpecific; |
| 210 #else | 196 #else |
| 211 uintptr_t dummy; | 197 uintptr_t dummy; |
| 212 uintptr_t addressDiff = s_mainThreadStackStart - reinterpret_cast<uintpt
r_t>(&dummy); | 198 uintptr_t addressDiff = s_mainThreadStackStart - reinterpret_cast<uintpt
r_t>(&dummy); |
| 213 // This is a fast way to judge if we are in the main thread. | 199 // This is a fast way to judge if we are in the main thread. |
| 214 // If |&dummy| is within |s_mainThreadUnderestimatedStackSize| byte from | 200 // If |&dummy| is within |s_mainThreadUnderestimatedStackSize| byte from |
| 215 // the stack start of the main thread, we judge that we are in | 201 // the stack start of the main thread, we judge that we are in |
| 216 // the main thread. | 202 // the main thread. |
| 217 if (LIKELY(addressDiff < s_mainThreadUnderestimatedStackSize)) { | 203 if (LIKELY(addressDiff < s_mainThreadUnderestimatedStackSize)) { |
| 218 ASSERT(**s_threadSpecific == mainThreadState()); | 204 ASSERT(**s_threadSpecific == mainThreadState()); |
| 219 return mainThreadState(); | 205 return mainThreadState(); |
| 220 } | 206 } |
| 221 // TLS lookup is slow. | 207 // TLS lookup is slow. |
| 222 return **s_threadSpecific; | 208 return **s_threadSpecific; |
| 223 #endif | 209 #endif |
| 224 } | 210 } |
| 225 | 211 |
| 226 static ThreadState* mainThreadState() | 212 static ThreadState* mainThreadState() |
| 227 { | 213 { |
| 228 return reinterpret_cast<ThreadState*>(s_mainThreadStateStorage); | 214 return reinterpret_cast<ThreadState*>(s_mainThreadStateStorage); |
| 229 } | 215 } |
| 230 | 216 |
| 217 static ThreadState* fromObject(const void*); |
| 218 |
| 231 bool isMainThread() const { return this == mainThreadState(); } | 219 bool isMainThread() const { return this == mainThreadState(); } |
| 232 #if ENABLE(ASSERT) | 220 #if ENABLE(ASSERT) |
| 233 bool checkThread() const { return m_thread == currentThread(); } | 221 bool checkThread() const { return m_thread == currentThread(); } |
| 234 #endif | 222 #endif |
| 235 | 223 |
| 224 ThreadHeap& heap() { return *m_heap; } |
| 225 |
| 226 // When ThreadState is detaching from non-main thread its |
| 227 // heap is expected to be empty (because it is going away). |
| 228 // Perform registered cleanup tasks and garbage collection |
| 229 // to sweep away any objects that are left on this heap. |
| 230 // We assert that nothing must remain after this cleanup. |
| 231 // If assertion does not hold we crash as we are potentially |
| 232 // in the dangling pointer situation. |
| 233 void runTerminationGC(); |
| 234 |
| 236 void performIdleGC(double deadlineSeconds); | 235 void performIdleGC(double deadlineSeconds); |
| 237 void performIdleLazySweep(double deadlineSeconds); | 236 void performIdleLazySweep(double deadlineSeconds); |
| 238 | 237 |
| 239 void scheduleIdleGC(); | 238 void scheduleIdleGC(); |
| 240 void scheduleIdleLazySweep(); | 239 void scheduleIdleLazySweep(); |
| 241 void schedulePreciseGC(); | 240 void schedulePreciseGC(); |
| 242 void scheduleV8FollowupGCIfNeeded(BlinkGC::V8GCType); | 241 void scheduleV8FollowupGCIfNeeded(BlinkGC::V8GCType); |
| 243 void schedulePageNavigationGCIfNeeded(float estimatedRemovalRatio); | 242 void schedulePageNavigationGCIfNeeded(float estimatedRemovalRatio); |
| 244 void schedulePageNavigationGC(); | 243 void schedulePageNavigationGC(); |
| 245 void scheduleGCIfNeeded(); | 244 void scheduleGCIfNeeded(); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 317 // there is a GC in progress. | 316 // there is a GC in progress. |
| 318 // | 317 // |
| 319 // Each thread that has ThreadState attached must: | 318 // Each thread that has ThreadState attached must: |
| 320 // - periodically check if GC is requested from another thread by calling
a safePoint() method; | 319 // - periodically check if GC is requested from another thread by calling
a safePoint() method; |
| 321 // - use SafePointScope around long running loops that have no safePoint()
invocation inside, | 320 // - use SafePointScope around long running loops that have no safePoint()
invocation inside, |
| 322 // such loops must not touch any heap object; | 321 // such loops must not touch any heap object; |
| 323 // - register an BlinkGCInterruptor that can interrupt long running loops
that have no calls to safePoint and | 322 // - register an BlinkGCInterruptor that can interrupt long running loops
that have no calls to safePoint and |
| 324 // are not wrapped in a SafePointScope (e.g. BlinkGCInterruptor for Java
Script code) | 323 // are not wrapped in a SafePointScope (e.g. BlinkGCInterruptor for Java
Script code) |
| 325 // | 324 // |
| 326 | 325 |
| 327 // Request all other threads to stop. Must only be called if the current thr
ead is at safepoint. | |
| 328 static bool stopThreads(); | |
| 329 static void resumeThreads(); | |
| 330 | |
| 331 // Check if GC is requested by another thread and pause this thread if this
is the case. | 326 // Check if GC is requested by another thread and pause this thread if this
is the case. |
| 332 // Can only be called when current thread is in a consistent state. | 327 // Can only be called when current thread is in a consistent state. |
| 333 void safePoint(BlinkGC::StackState); | 328 void safePoint(BlinkGC::StackState); |
| 334 | 329 |
| 335 // Mark current thread as running inside safepoint. | 330 // Mark current thread as running inside safepoint. |
| 336 void enterSafePoint(BlinkGC::StackState, void*); | 331 void enterSafePoint(BlinkGC::StackState, void*); |
| 337 void leaveSafePoint(SafePointAwareMutexLocker* = nullptr); | 332 void leaveSafePoint(SafePointAwareMutexLocker* = nullptr); |
| 338 bool isAtSafePoint() const { return m_atSafePoint; } | 333 bool isAtSafePoint() const { return m_atSafePoint; } |
| 339 | 334 |
| 340 void addInterruptor(PassOwnPtr<BlinkGCInterruptor>); | 335 void addInterruptor(PassOwnPtr<BlinkGCInterruptor>); |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 516 #if defined(LEAK_SANITIZER) | 511 #if defined(LEAK_SANITIZER) |
| 517 void enterStaticReferenceRegistrationDisabledScope(); | 512 void enterStaticReferenceRegistrationDisabledScope(); |
| 518 void leaveStaticReferenceRegistrationDisabledScope(); | 513 void leaveStaticReferenceRegistrationDisabledScope(); |
| 519 #endif | 514 #endif |
| 520 | 515 |
| 521 void resetHeapCounters(); | 516 void resetHeapCounters(); |
| 522 void increaseAllocatedObjectSize(size_t); | 517 void increaseAllocatedObjectSize(size_t); |
| 523 void decreaseAllocatedObjectSize(size_t); | 518 void decreaseAllocatedObjectSize(size_t); |
| 524 void increaseMarkedObjectSize(size_t); | 519 void increaseMarkedObjectSize(size_t); |
| 525 | 520 |
| 521 void callThreadShutdownHooks(); |
| 522 |
| 526 private: | 523 private: |
| 527 enum SnapshotType { | 524 enum SnapshotType { |
| 528 HeapSnapshot, | 525 HeapSnapshot, |
| 529 FreelistSnapshot | 526 FreelistSnapshot |
| 530 }; | 527 }; |
| 531 | 528 |
| 532 ThreadState(); | 529 ThreadState(); |
| 533 ~ThreadState(); | 530 ~ThreadState(); |
| 534 | 531 |
| 535 NO_SANITIZE_ADDRESS void copyStackUntilSafePointScope(); | 532 NO_SANITIZE_ADDRESS void copyStackUntilSafePointScope(); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 576 | 573 |
| 577 void runScheduledGC(BlinkGC::StackState); | 574 void runScheduledGC(BlinkGC::StackState); |
| 578 | 575 |
| 579 void eagerSweep(); | 576 void eagerSweep(); |
| 580 | 577 |
| 581 #if defined(ADDRESS_SANITIZER) | 578 #if defined(ADDRESS_SANITIZER) |
| 582 void poisonEagerArena(); | 579 void poisonEagerArena(); |
| 583 void poisonAllHeaps(); | 580 void poisonAllHeaps(); |
| 584 #endif | 581 #endif |
| 585 | 582 |
| 586 // When ThreadState is detaching from non-main thread its | |
| 587 // heap is expected to be empty (because it is going away). | |
| 588 // Perform registered cleanup tasks and garbage collection | |
| 589 // to sweep away any objects that are left on this heap. | |
| 590 // We assert that nothing must remain after this cleanup. | |
| 591 // If assertion does not hold we crash as we are potentially | |
| 592 // in the dangling pointer situation. | |
| 593 void cleanup(); | |
| 594 void cleanupPages(); | 583 void cleanupPages(); |
| 595 | 584 |
| 596 void prepareForThreadStateTermination(); | 585 void prepareForThreadStateTermination(); |
| 597 | 586 |
| 598 void invokePreFinalizers(); | 587 void invokePreFinalizers(); |
| 599 | 588 |
| 600 void takeSnapshot(SnapshotType); | 589 void takeSnapshot(SnapshotType); |
| 601 void clearArenaAges(); | 590 void clearArenaAges(); |
| 602 int arenaIndexOfVectorArenaLeastRecentlyExpanded(int beginArenaIndex, int en
dArenaIndex); | 591 int arenaIndexOfVectorArenaLeastRecentlyExpanded(int beginArenaIndex, int en
dArenaIndex); |
| 603 | 592 |
| 604 void reportMemoryToV8(); | 593 void reportMemoryToV8(); |
| 605 | 594 |
| 606 // Should only be called under protection of threadAttachMutex(). | 595 // Should only be called under protection of threadAttachMutex(). |
| 607 const Vector<OwnPtr<BlinkGCInterruptor>>& interruptors() const { return m_in
terruptors; } | 596 const Vector<OwnPtr<BlinkGCInterruptor>>& interruptors() const { return m_in
terruptors; } |
| 608 | 597 |
| 609 friend class SafePointAwareMutexLocker; | 598 friend class SafePointAwareMutexLocker; |
| 610 friend class SafePointBarrier; | 599 friend class SafePointBarrier; |
| 611 friend class SafePointScope; | 600 friend class SafePointScope; |
| 612 | 601 |
| 613 static WTF::ThreadSpecific<ThreadState*>* s_threadSpecific; | 602 static WTF::ThreadSpecific<ThreadState*>* s_threadSpecific; |
| 614 static uintptr_t s_mainThreadStackStart; | 603 static uintptr_t s_mainThreadStackStart; |
| 615 static uintptr_t s_mainThreadUnderestimatedStackSize; | 604 static uintptr_t s_mainThreadUnderestimatedStackSize; |
| 616 static SafePointBarrier* s_safePointBarrier; | |
| 617 | 605 |
| 618 // We can't create a static member of type ThreadState here | 606 // We can't create a static member of type ThreadState here |
| 619 // because it will introduce global constructor and destructor. | 607 // because it will introduce global constructor and destructor. |
| 620 // We would like to manage lifetime of the ThreadState attached | 608 // We would like to manage lifetime of the ThreadState attached |
| 621 // to the main thread explicitly instead and still use normal | 609 // to the main thread explicitly instead and still use normal |
| 622 // constructor and destructor for the ThreadState class. | 610 // constructor and destructor for the ThreadState class. |
| 623 // For this we reserve static storage for the main ThreadState | 611 // For this we reserve static storage for the main ThreadState |
| 624 // and lazily construct ThreadState in it using placement new. | 612 // and lazily construct ThreadState in it using placement new. |
| 625 static uint8_t s_mainThreadStateStorage[]; | 613 static uint8_t s_mainThreadStateStorage[]; |
| 626 | 614 |
| 615 ThreadHeap* m_heap; |
| 627 ThreadIdentifier m_thread; | 616 ThreadIdentifier m_thread; |
| 628 OwnPtr<PersistentRegion> m_persistentRegion; | 617 OwnPtr<PersistentRegion> m_persistentRegion; |
| 629 BlinkGC::StackState m_stackState; | 618 BlinkGC::StackState m_stackState; |
| 630 #if OS(WIN) && COMPILER(MSVC) | 619 #if OS(WIN) && COMPILER(MSVC) |
| 631 size_t m_threadStackSize; | 620 size_t m_threadStackSize; |
| 632 #endif | 621 #endif |
| 633 intptr_t* m_startOfStack; | 622 intptr_t* m_startOfStack; |
| 634 intptr_t* m_endOfStack; | 623 intptr_t* m_endOfStack; |
| 635 | 624 |
| 636 void* m_safePointScopeMarker; | 625 void* m_safePointScopeMarker; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 707 | 696 |
| 708 template<> class ThreadStateFor<AnyThread> { | 697 template<> class ThreadStateFor<AnyThread> { |
| 709 STATIC_ONLY(ThreadStateFor); | 698 STATIC_ONLY(ThreadStateFor); |
| 710 public: | 699 public: |
| 711 static ThreadState* state() { return ThreadState::current(); } | 700 static ThreadState* state() { return ThreadState::current(); } |
| 712 }; | 701 }; |
| 713 | 702 |
| 714 } // namespace blink | 703 } // namespace blink |
| 715 | 704 |
| 716 #endif // ThreadState_h | 705 #endif // ThreadState_h |
| OLD | NEW |