| 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 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 | 48 |
| 49 namespace v8 { | 49 namespace v8 { |
| 50 class Isolate; | 50 class Isolate; |
| 51 }; | 51 }; |
| 52 | 52 |
| 53 namespace blink { | 53 namespace blink { |
| 54 | 54 |
| 55 class BasePage; | 55 class BasePage; |
| 56 class CallbackStack; | 56 class CallbackStack; |
| 57 class CrossThreadPersistentRegion; | 57 class CrossThreadPersistentRegion; |
| 58 class FreePagePool; |
| 58 struct GCInfo; | 59 struct GCInfo; |
| 59 class GarbageCollectedMixinConstructorMarker; | 60 class GarbageCollectedMixinConstructorMarker; |
| 61 class HeapDoesNotContainCache; |
| 60 class HeapObjectHeader; | 62 class HeapObjectHeader; |
| 63 class OrphanedPagePool; |
| 61 class PersistentRegion; | 64 class PersistentRegion; |
| 65 class XThreadPersistentRegion; |
| 62 class BaseHeap; | 66 class BaseHeap; |
| 63 class SafePointAwareMutexLocker; | 67 class SafePointAwareMutexLocker; |
| 64 class SafePointBarrier; | 68 class SafePointBarrier; |
| 65 class ThreadState; | 69 class ThreadState; |
| 66 class Visitor; | 70 class Visitor; |
| 71 class PageMemoryRegion; |
| 67 | 72 |
| 68 // Declare that a class has a pre-finalizer. The pre-finalizer is called | 73 // 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 | 74 // 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 | 75 // 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 | 76 // 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 | 77 // using the pre-finalizer. The only restriction is that the pre-finalizer |
| 73 // must not resurrect dead objects (e.g., store unmarked objects into | 78 // must not resurrect dead objects (e.g., store unmarked objects into |
| 74 // Members etc). The pre-finalizer is called on the thread that registered | 79 // Members etc). The pre-finalizer is called on the thread that registered |
| 75 // the pre-finalizer. | 80 // the pre-finalizer. |
| 76 // | 81 // |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 #define WILL_BE_USING_PRE_FINALIZER(Class, method) USING_PRE_FINALIZER(Class, me
thod) | 123 #define WILL_BE_USING_PRE_FINALIZER(Class, method) USING_PRE_FINALIZER(Class, me
thod) |
| 119 #else | 124 #else |
| 120 #define WILL_BE_USING_PRE_FINALIZER(Class, method) | 125 #define WILL_BE_USING_PRE_FINALIZER(Class, method) |
| 121 #endif | 126 #endif |
| 122 | 127 |
| 123 class PLATFORM_EXPORT ThreadState { | 128 class PLATFORM_EXPORT ThreadState { |
| 124 WTF_MAKE_NONCOPYABLE(ThreadState); | 129 WTF_MAKE_NONCOPYABLE(ThreadState); |
| 125 public: | 130 public: |
| 126 typedef std::pair<void*, PreFinalizerCallback> PreFinalizer; | 131 typedef std::pair<void*, PreFinalizerCallback> PreFinalizer; |
| 127 | 132 |
| 133 // A RegionTree is a simple binary search tree of PageMemoryRegions sorted |
| 134 // by base addresses. |
| 135 class RegionTree { |
| 136 public: |
| 137 explicit RegionTree(PageMemoryRegion* region) : m_region(region), m_left
(nullptr), m_right(nullptr) { } |
| 138 ~RegionTree() |
| 139 { |
| 140 delete m_left; |
| 141 delete m_right; |
| 142 } |
| 143 PageMemoryRegion* lookup(Address); |
| 144 static void add(RegionTree*, RegionTree**); |
| 145 static void remove(PageMemoryRegion*, RegionTree**); |
| 146 private: |
| 147 PageMemoryRegion* m_region; |
| 148 RegionTree* m_left; |
| 149 RegionTree* m_right; |
| 150 }; |
| 151 |
| 128 // See setGCState() for possible state transitions. | 152 // See setGCState() for possible state transitions. |
| 129 enum GCState { | 153 enum GCState { |
| 130 NoGCScheduled, | 154 NoGCScheduled, |
| 131 IdleGCScheduled, | 155 IdleGCScheduled, |
| 132 PreciseGCScheduled, | 156 PreciseGCScheduled, |
| 133 FullGCScheduled, | 157 FullGCScheduled, |
| 134 PageNavigationGCScheduled, | 158 PageNavigationGCScheduled, |
| 135 GCRunning, | 159 GCRunning, |
| 136 EagerSweepScheduled, | 160 EagerSweepScheduled, |
| 137 LazySweepScheduled, | 161 LazySweepScheduled, |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 218 // the stack start of the main thread, we judge that we are in | 242 // the stack start of the main thread, we judge that we are in |
| 219 // the main thread. | 243 // the main thread. |
| 220 if (LIKELY(addressDiff < s_mainThreadUnderestimatedStackSize)) { | 244 if (LIKELY(addressDiff < s_mainThreadUnderestimatedStackSize)) { |
| 221 ASSERT(**s_threadSpecific == mainThreadState()); | 245 ASSERT(**s_threadSpecific == mainThreadState()); |
| 222 return mainThreadState(); | 246 return mainThreadState(); |
| 223 } | 247 } |
| 224 // TLS lookup is slow. | 248 // TLS lookup is slow. |
| 225 return **s_threadSpecific; | 249 return **s_threadSpecific; |
| 226 #endif | 250 #endif |
| 227 } | 251 } |
| 252 static ThreadState* terminating() |
| 253 { |
| 254 // TLS lookup is fast in these platforms. |
| 255 return **s_threadSpecificTerminating; |
| 256 } |
| 228 | 257 |
| 229 static ThreadState* mainThreadState() | 258 static ThreadState* mainThreadState() |
| 230 { | 259 { |
| 231 return reinterpret_cast<ThreadState*>(s_mainThreadStateStorage); | 260 return reinterpret_cast<ThreadState*>(s_mainThreadStateStorage); |
| 232 } | 261 } |
| 233 | 262 |
| 263 CallbackStack* markingStack() const { return m_markingStack.get(); } |
| 264 CallbackStack* postMarkingCallbackStack() const { return m_postMarkingCallba
ckStack.get(); } |
| 265 CallbackStack* globalWeakCallbackStack() const { return m_globalWeakCallback
Stack.get(); } |
| 266 CallbackStack* ephemeronStack() const { return m_ephemeronStack.get(); } |
| 267 FreePagePool* freePagePool() const { return m_freePagePool.get(); } |
| 268 void setMarkedObjectSizeAtLastCompleteSweep(size_t size) { releaseStore(&m_m
arkedObjectSizeAtLastCompleteSweep, size); } |
| 269 size_t markedObjectSizeAtLastCompleteSweep() { return acquireLoad(&m_markedO
bjectSizeAtLastCompleteSweep); } |
| 270 void increaseAllocatedObjectSize(size_t delta) { atomicAdd(&m_allocatedObjec
tSize, static_cast<long>(delta)); } |
| 271 void decreaseAllocatedObjectSize(size_t delta) { atomicSubtract(&m_allocated
ObjectSize, static_cast<long>(delta)); } |
| 272 size_t allocatedObjectSize() { return acquireLoad(&m_allocatedObjectSize); } |
| 273 void increaseMarkedObjectSize(size_t delta) { atomicAdd(&m_markedObjectSize,
static_cast<long>(delta)); } |
| 274 size_t markedObjectSize() { return acquireLoad(&m_markedObjectSize); } |
| 275 void increaseAllocatedSpace(size_t delta) { atomicAdd(&m_allocatedSpace, sta
tic_cast<long>(delta)); } |
| 276 void decreaseAllocatedSpace(size_t delta) { atomicSubtract(&m_allocatedSpace
, static_cast<long>(delta)); } |
| 277 size_t allocatedSpace() { return acquireLoad(&m_allocatedSpace); } |
| 278 size_t objectSizeAtLastGC() { return acquireLoad(&m_objectSizeAtLastGC); } |
| 279 void increaseWrapperCount(size_t delta) { atomicAdd(&m_wrapperCount, static_
cast<long>(delta)); } |
| 280 void decreaseWrapperCount(size_t delta) { atomicSubtract(&m_wrapperCount, st
atic_cast<long>(delta)); } |
| 281 size_t wrapperCount() { return acquireLoad(&m_wrapperCount); } |
| 282 size_t wrapperCountAtLastGC() { return acquireLoad(&m_wrapperCountAtLastGC);
} |
| 283 void increaseCollectedWrapperCount(size_t delta) { atomicAdd(&m_collectedWra
pperCount, static_cast<long>(delta)); } |
| 284 size_t collectedWrapperCount() { return acquireLoad(&m_collectedWrapperCount
); } |
| 285 size_t partitionAllocSizeAtLastGC() { return acquireLoad(&m_partitionAllocSi
zeAtLastGC); } |
| 286 |
| 287 void setEstimatedMarkingTimePerByte(double estimatedMarkingTimePerByte) { m_
estimatedMarkingTimePerByte = estimatedMarkingTimePerByte; } |
| 288 double estimatedMarkingTimePerByte() const { return m_estimatedMarkingTimePe
rByte; } |
| 289 void setShutdownCalled(bool shutdownCalled) { m_shutdownCalled = shutdownCal
led; } |
| 290 bool shutdownCalled() const { return m_shutdownCalled; } |
| 291 HeapDoesNotContainCache* heapDoesNotContainCache() const { return m_heapDoes
NotContainCache.get(); } |
| 292 RegionTree* regionTree() const { return m_regionTree; } |
| 293 void setRegionTree(RegionTree* tree) { m_regionTree = tree; } |
| 294 |
| 295 double estimatedMarkingTime(); |
| 296 void reportMemoryUsageHistogram(); |
| 297 void reportMemoryUsageForTracing(); |
| 298 |
| 299 #if ENABLE(ASSERT) |
| 300 void incrementGcGeneration() { |
| 301 if (++m_gcGeneration == 0) |
| 302 m_gcGeneration = 1; |
| 303 } |
| 304 uint16_t gcGeneration() { return m_gcGeneration; } |
| 305 #endif |
| 306 |
| 307 void flushHeapDoesNotContainCache(); |
| 308 OrphanedPagePool* orphanedPagePool() { return m_orphanedPagePool.get(); } |
| 309 |
| 310 // Reset counters that track live and allocated-since-last-GC sizes. |
| 311 void resetHeapCounters(); |
| 312 |
| 234 bool isMainThread() const { return this == mainThreadState(); } | 313 bool isMainThread() const { return this == mainThreadState(); } |
| 235 #if ENABLE(ASSERT) | 314 #if ENABLE(ASSERT) |
| 236 bool checkThread() const { return m_thread == currentThread(); } | 315 bool checkThread() const { return m_thread == currentThread(); } |
| 237 #endif | 316 #endif |
| 238 | 317 |
| 239 void performIdleGC(double deadlineSeconds); | 318 void performIdleGC(double deadlineSeconds); |
| 240 void performIdleLazySweep(double deadlineSeconds); | 319 void performIdleLazySweep(double deadlineSeconds); |
| 241 | 320 |
| 242 void scheduleIdleGC(); | 321 void scheduleIdleGC(); |
| 243 void scheduleIdleLazySweep(); | 322 void scheduleIdleLazySweep(); |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 361 #if ENABLE(ASSERT) | 440 #if ENABLE(ASSERT) |
| 362 // Infrastructure to determine if an address is within one of the | 441 // Infrastructure to determine if an address is within one of the |
| 363 // address ranges for the Blink heap. If the address is in the Blink | 442 // address ranges for the Blink heap. If the address is in the Blink |
| 364 // heap the containing heap page is returned. | 443 // heap the containing heap page is returned. |
| 365 BasePage* findPageFromAddress(Address); | 444 BasePage* findPageFromAddress(Address); |
| 366 BasePage* findPageFromAddress(const void* pointer) { return findPageFromAddr
ess(reinterpret_cast<Address>(const_cast<void*>(pointer))); } | 445 BasePage* findPageFromAddress(const void* pointer) { return findPageFromAddr
ess(reinterpret_cast<Address>(const_cast<void*>(pointer))); } |
| 367 #endif | 446 #endif |
| 368 | 447 |
| 369 // A region of PersistentNodes allocated on the given thread. | 448 // A region of PersistentNodes allocated on the given thread. |
| 370 PersistentRegion* persistentRegion() const { return m_persistentRegion.get()
; } | 449 PersistentRegion* persistentRegion() const { return m_persistentRegion.get()
; } |
| 450 XThreadPersistentRegion* xThreadPersistentRegion() const { return m_xThreadP
ersistentRegion.get(); } |
| 371 // A region of PersistentNodes not owned by any particular thread. | 451 // A region of PersistentNodes not owned by any particular thread. |
| 372 static CrossThreadPersistentRegion& crossThreadPersistentRegion(); | 452 static CrossThreadPersistentRegion& crossThreadPersistentRegion(); |
| 373 | 453 |
| 374 // Visit local thread stack and trace all pointers conservatively. | 454 // Visit local thread stack and trace all pointers conservatively. |
| 375 void visitStack(Visitor*); | 455 void visitStack(Visitor*); |
| 376 | 456 |
| 377 // Visit the asan fake stack frame corresponding to a slot on the | 457 // Visit the asan fake stack frame corresponding to a slot on the |
| 378 // real machine stack if there is one. | 458 // real machine stack if there is one. |
| 379 void visitAsanFakeStackForPointer(Visitor*, Address); | 459 void visitAsanFakeStackForPointer(Visitor*, Address); |
| 380 | 460 |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 503 } | 583 } |
| 504 void allocationPointAdjusted(int heapIndex); | 584 void allocationPointAdjusted(int heapIndex); |
| 505 void promptlyFreed(size_t gcInfoIndex); | 585 void promptlyFreed(size_t gcInfoIndex); |
| 506 | 586 |
| 507 void accumulateSweepingTime(double time) { m_accumulatedSweepingTime += time
; } | 587 void accumulateSweepingTime(double time) { m_accumulatedSweepingTime += time
; } |
| 508 | 588 |
| 509 #if OS(WIN) && COMPILER(MSVC) | 589 #if OS(WIN) && COMPILER(MSVC) |
| 510 size_t threadStackSize(); | 590 size_t threadStackSize(); |
| 511 #endif | 591 #endif |
| 512 | 592 |
| 593 void setIsolated(bool isolated) { m_isolated = isolated; } |
| 594 bool isolated() { return m_isolated; } |
| 595 |
| 513 private: | 596 private: |
| 514 enum SnapshotType { | 597 enum SnapshotType { |
| 515 HeapSnapshot, | 598 HeapSnapshot, |
| 516 FreelistSnapshot | 599 FreelistSnapshot |
| 517 }; | 600 }; |
| 518 | 601 |
| 519 ThreadState(); | 602 ThreadState(); |
| 520 ~ThreadState(); | 603 ~ThreadState(); |
| 521 | 604 |
| 522 NO_SANITIZE_ADDRESS void copyStackUntilSafePointScope(); | 605 NO_SANITIZE_ADDRESS void copyStackUntilSafePointScope(); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 589 int heapIndexOfVectorHeapLeastRecentlyExpanded(int beginHeapIndex, int endHe
apIndex); | 672 int heapIndexOfVectorHeapLeastRecentlyExpanded(int beginHeapIndex, int endHe
apIndex); |
| 590 | 673 |
| 591 // Should only be called under protection of threadAttachMutex(). | 674 // Should only be called under protection of threadAttachMutex(). |
| 592 const Vector<OwnPtr<BlinkGCInterruptor>>& interruptors() const { return m_in
terruptors; } | 675 const Vector<OwnPtr<BlinkGCInterruptor>>& interruptors() const { return m_in
terruptors; } |
| 593 | 676 |
| 594 friend class SafePointAwareMutexLocker; | 677 friend class SafePointAwareMutexLocker; |
| 595 friend class SafePointBarrier; | 678 friend class SafePointBarrier; |
| 596 friend class SafePointScope; | 679 friend class SafePointScope; |
| 597 | 680 |
| 598 static WTF::ThreadSpecific<ThreadState*>* s_threadSpecific; | 681 static WTF::ThreadSpecific<ThreadState*>* s_threadSpecific; |
| 682 static WTF::ThreadSpecific<ThreadState*>* s_threadSpecificTerminating; |
| 599 static uintptr_t s_mainThreadStackStart; | 683 static uintptr_t s_mainThreadStackStart; |
| 600 static uintptr_t s_mainThreadUnderestimatedStackSize; | 684 static uintptr_t s_mainThreadUnderestimatedStackSize; |
| 601 static SafePointBarrier* s_safePointBarrier; | 685 static SafePointBarrier* s_safePointBarrier; |
| 602 | 686 |
| 603 // We can't create a static member of type ThreadState here | 687 // We can't create a static member of type ThreadState here |
| 604 // because it will introduce global constructor and destructor. | 688 // because it will introduce global constructor and destructor. |
| 605 // We would like to manage lifetime of the ThreadState attached | 689 // We would like to manage lifetime of the ThreadState attached |
| 606 // to the main thread explicitly instead and still use normal | 690 // to the main thread explicitly instead and still use normal |
| 607 // constructor and destructor for the ThreadState class. | 691 // constructor and destructor for the ThreadState class. |
| 608 // For this we reserve static storage for the main ThreadState | 692 // For this we reserve static storage for the main ThreadState |
| 609 // and lazily construct ThreadState in it using placement new. | 693 // and lazily construct ThreadState in it using placement new. |
| 610 static uint8_t s_mainThreadStateStorage[]; | 694 static uint8_t s_mainThreadStateStorage[]; |
| 611 | 695 |
| 612 ThreadIdentifier m_thread; | 696 ThreadIdentifier m_thread; |
| 697 bool m_isolated; |
| 613 OwnPtr<PersistentRegion> m_persistentRegion; | 698 OwnPtr<PersistentRegion> m_persistentRegion; |
| 699 OwnPtr<XThreadPersistentRegion> m_xThreadPersistentRegion; |
| 614 BlinkGC::StackState m_stackState; | 700 BlinkGC::StackState m_stackState; |
| 615 #if OS(WIN) && COMPILER(MSVC) | 701 #if OS(WIN) && COMPILER(MSVC) |
| 616 size_t m_threadStackSize; | 702 size_t m_threadStackSize; |
| 617 #endif | 703 #endif |
| 618 intptr_t* m_startOfStack; | 704 intptr_t* m_startOfStack; |
| 619 intptr_t* m_endOfStack; | 705 intptr_t* m_endOfStack; |
| 620 | 706 |
| 621 void* m_safePointScopeMarker; | 707 void* m_safePointScopeMarker; |
| 622 Vector<Address> m_safePointStackCopy; | 708 Vector<Address> m_safePointStackCopy; |
| 623 bool m_atSafePoint; | 709 bool m_atSafePoint; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 652 void* m_asanFakeStack; | 738 void* m_asanFakeStack; |
| 653 #endif | 739 #endif |
| 654 | 740 |
| 655 // Ideally we want to allocate an array of size |gcInfoTableMax| but it will | 741 // Ideally we want to allocate an array of size |gcInfoTableMax| but it will |
| 656 // waste memory. Thus we limit the array size to 2^8 and share one entry | 742 // waste memory. Thus we limit the array size to 2^8 and share one entry |
| 657 // with multiple types of vectors. This won't be an issue in practice, | 743 // with multiple types of vectors. This won't be an issue in practice, |
| 658 // since there will be less than 2^8 types of objects in common cases. | 744 // since there will be less than 2^8 types of objects in common cases. |
| 659 static const int likelyToBePromptlyFreedArraySize = (1 << 8); | 745 static const int likelyToBePromptlyFreedArraySize = (1 << 8); |
| 660 static const int likelyToBePromptlyFreedArrayMask = likelyToBePromptlyFreedA
rraySize - 1; | 746 static const int likelyToBePromptlyFreedArrayMask = likelyToBePromptlyFreedA
rraySize - 1; |
| 661 OwnPtr<int[]> m_likelyToBePromptlyFreed; | 747 OwnPtr<int[]> m_likelyToBePromptlyFreed; |
| 748 |
| 749 OwnPtr<CallbackStack> m_markingStack; |
| 750 OwnPtr<CallbackStack> m_postMarkingCallbackStack; |
| 751 OwnPtr<CallbackStack> m_globalWeakCallbackStack; |
| 752 OwnPtr<CallbackStack> m_ephemeronStack; |
| 753 OwnPtr<FreePagePool> m_freePagePool; |
| 754 size_t m_allocatedSpace; |
| 755 size_t m_allocatedObjectSize; |
| 756 size_t m_objectSizeAtLastGC; |
| 757 size_t m_markedObjectSize; |
| 758 size_t m_markedObjectSizeAtLastCompleteSweep; |
| 759 size_t m_wrapperCount; |
| 760 size_t m_wrapperCountAtLastGC; |
| 761 size_t m_collectedWrapperCount; |
| 762 size_t m_partitionAllocSizeAtLastGC; |
| 763 double m_estimatedMarkingTimePerByte; |
| 764 #if ENABLE(ASSERT) |
| 765 uint16_t m_gcGeneration; |
| 766 #endif |
| 767 OwnPtr<HeapDoesNotContainCache> m_heapDoesNotContainCache; |
| 768 bool m_shutdownCalled; |
| 769 OwnPtr<OrphanedPagePool> m_orphanedPagePool; |
| 770 RegionTree* m_regionTree; |
| 662 }; | 771 }; |
| 663 | 772 |
| 664 template<ThreadAffinity affinity> class ThreadStateFor; | 773 template<ThreadAffinity affinity> class ThreadStateFor; |
| 665 | 774 |
| 666 template<> class ThreadStateFor<MainThreadOnly> { | 775 template<> class ThreadStateFor<MainThreadOnly> { |
| 667 public: | 776 public: |
| 668 static ThreadState* state() | 777 static ThreadState* state() |
| 669 { | 778 { |
| 670 // This specialization must only be used from the main thread. | 779 // This specialization must only be used from the main thread. |
| 671 ASSERT(ThreadState::current()->isMainThread()); | 780 ASSERT(ThreadState::current()->isMainThread()); |
| 672 return ThreadState::mainThreadState(); | 781 return ThreadState::mainThreadState(); |
| 673 } | 782 } |
| 674 }; | 783 }; |
| 675 | 784 |
| 676 template<> class ThreadStateFor<AnyThread> { | 785 template<> class ThreadStateFor<AnyThread> { |
| 677 public: | 786 public: |
| 678 static ThreadState* state() { return ThreadState::current(); } | 787 static ThreadState* state() { return ThreadState::current(); } |
| 679 }; | 788 }; |
| 680 | 789 |
| 681 } // namespace blink | 790 } // namespace blink |
| 682 | 791 |
| 683 #endif // ThreadState_h | 792 #endif // ThreadState_h |
| OLD | NEW |