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