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