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 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 | 145 |
146 private: | 146 private: |
147 ThreadState* m_state; | 147 ThreadState* m_state; |
148 }; | 148 }; |
149 | 149 |
150 class SweepForbiddenScope final { | 150 class SweepForbiddenScope final { |
151 STACK_ALLOCATED(); | 151 STACK_ALLOCATED(); |
152 | 152 |
153 public: | 153 public: |
154 explicit SweepForbiddenScope(ThreadState* state) : m_state(state) { | 154 explicit SweepForbiddenScope(ThreadState* state) : m_state(state) { |
155 ASSERT(!m_state->m_sweepForbidden); | 155 DCHECK(!m_state->m_sweepForbidden); |
156 m_state->m_sweepForbidden = true; | 156 m_state->m_sweepForbidden = true; |
157 } | 157 } |
158 ~SweepForbiddenScope() { | 158 ~SweepForbiddenScope() { |
159 ASSERT(m_state->m_sweepForbidden); | 159 DCHECK(m_state->m_sweepForbidden); |
160 m_state->m_sweepForbidden = false; | 160 m_state->m_sweepForbidden = false; |
161 } | 161 } |
162 | 162 |
163 private: | 163 private: |
164 ThreadState* m_state; | 164 ThreadState* m_state; |
165 }; | 165 }; |
166 | 166 |
167 void lockThreadAttachMutex(); | 167 void lockThreadAttachMutex(); |
168 void unlockThreadAttachMutex(); | 168 void unlockThreadAttachMutex(); |
169 | 169 |
(...skipping 20 matching lines...) Expand all Loading... |
190 return **s_threadSpecific; | 190 return **s_threadSpecific; |
191 #else | 191 #else |
192 uintptr_t dummy; | 192 uintptr_t dummy; |
193 uintptr_t addressDiff = | 193 uintptr_t addressDiff = |
194 s_mainThreadStackStart - reinterpret_cast<uintptr_t>(&dummy); | 194 s_mainThreadStackStart - reinterpret_cast<uintptr_t>(&dummy); |
195 // This is a fast way to judge if we are in the main thread. | 195 // This is a fast way to judge if we are in the main thread. |
196 // If |&dummy| is within |s_mainThreadUnderestimatedStackSize| byte from | 196 // If |&dummy| is within |s_mainThreadUnderestimatedStackSize| byte from |
197 // the stack start of the main thread, we judge that we are in | 197 // the stack start of the main thread, we judge that we are in |
198 // the main thread. | 198 // the main thread. |
199 if (LIKELY(addressDiff < s_mainThreadUnderestimatedStackSize)) { | 199 if (LIKELY(addressDiff < s_mainThreadUnderestimatedStackSize)) { |
200 ASSERT(**s_threadSpecific == mainThreadState()); | 200 DCHECK_EQ(**s_threadSpecific, mainThreadState()); |
201 return mainThreadState(); | 201 return mainThreadState(); |
202 } | 202 } |
203 // TLS lookup is slow. | 203 // TLS lookup is slow. |
204 return **s_threadSpecific; | 204 return **s_threadSpecific; |
205 #endif | 205 #endif |
206 } | 206 } |
207 | 207 |
208 static ThreadState* mainThreadState() { | 208 static ThreadState* mainThreadState() { |
209 return reinterpret_cast<ThreadState*>(s_mainThreadStateStorage); | 209 return reinterpret_cast<ThreadState*>(s_mainThreadStateStorage); |
210 } | 210 } |
211 | 211 |
212 static ThreadState* fromObject(const void*); | 212 static ThreadState* fromObject(const void*); |
213 | 213 |
214 bool isMainThread() const { return this == mainThreadState(); } | 214 bool isMainThread() const { return this == mainThreadState(); } |
215 #if ENABLE(ASSERT) | 215 #if DCHECK_IS_ON() |
216 bool checkThread() const { return m_thread == currentThread(); } | 216 bool checkThread() const { return m_thread == currentThread(); } |
217 #endif | 217 #endif |
218 | 218 |
219 ThreadHeap& heap() const { return *m_heap; } | 219 ThreadHeap& heap() const { return *m_heap; } |
220 | 220 |
221 // When ThreadState is detaching from non-main thread its | 221 // When ThreadState is detaching from non-main thread its |
222 // heap is expected to be empty (because it is going away). | 222 // heap is expected to be empty (because it is going away). |
223 // Perform registered cleanup tasks and garbage collection | 223 // Perform registered cleanup tasks and garbage collection |
224 // to sweep away any objects that are left on this heap. | 224 // to sweep away any objects that are left on this heap. |
225 // We assert that nothing must remain after this cleanup. | 225 // We assert that nothing must remain after this cleanup. |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
371 bool isAtSafePoint() const { return m_atSafePoint; } | 371 bool isAtSafePoint() const { return m_atSafePoint; } |
372 | 372 |
373 void addInterruptor(std::unique_ptr<BlinkGCInterruptor>); | 373 void addInterruptor(std::unique_ptr<BlinkGCInterruptor>); |
374 | 374 |
375 void recordStackEnd(intptr_t* endOfStack) { m_endOfStack = endOfStack; } | 375 void recordStackEnd(intptr_t* endOfStack) { m_endOfStack = endOfStack; } |
376 | 376 |
377 // Get one of the heap structures for this thread. | 377 // Get one of the heap structures for this thread. |
378 // The thread heap is split into multiple heap parts based on object types | 378 // The thread heap is split into multiple heap parts based on object types |
379 // and object sizes. | 379 // and object sizes. |
380 BaseArena* arena(int arenaIndex) const { | 380 BaseArena* arena(int arenaIndex) const { |
381 ASSERT(0 <= arenaIndex); | 381 DCHECK_LE(0, arenaIndex); |
382 ASSERT(arenaIndex < BlinkGC::NumberOfArenas); | 382 DCHECK_LT(arenaIndex, BlinkGC::NumberOfArenas); |
383 return m_arenas[arenaIndex]; | 383 return m_arenas[arenaIndex]; |
384 } | 384 } |
385 | 385 |
386 #if ENABLE(ASSERT) | 386 #if DCHECK_IS_ON() |
387 // Infrastructure to determine if an address is within one of the | 387 // Infrastructure to determine if an address is within one of the |
388 // address ranges for the Blink heap. If the address is in the Blink | 388 // address ranges for the Blink heap. If the address is in the Blink |
389 // heap the containing heap page is returned. | 389 // heap the containing heap page is returned. |
390 BasePage* findPageFromAddress(Address); | 390 BasePage* findPageFromAddress(Address); |
391 BasePage* findPageFromAddress(const void* pointer) { | 391 BasePage* findPageFromAddress(const void* pointer) { |
392 return findPageFromAddress( | 392 return findPageFromAddress( |
393 reinterpret_cast<Address>(const_cast<void*>(pointer))); | 393 reinterpret_cast<Address>(const_cast<void*>(pointer))); |
394 } | 394 } |
395 #endif | 395 #endif |
396 | 396 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
447 } | 447 } |
448 | 448 |
449 // By entering a gc-forbidden scope, conservative GCs will not | 449 // By entering a gc-forbidden scope, conservative GCs will not |
450 // be allowed while handling an out-of-line allocation request. | 450 // be allowed while handling an out-of-line allocation request. |
451 // Intended used when constructing subclasses of GC mixins, where | 451 // Intended used when constructing subclasses of GC mixins, where |
452 // the object being constructed cannot be safely traced & marked | 452 // the object being constructed cannot be safely traced & marked |
453 // fully should a GC be allowed while its subclasses are being | 453 // fully should a GC be allowed while its subclasses are being |
454 // constructed. | 454 // constructed. |
455 void enterGCForbiddenScopeIfNeeded( | 455 void enterGCForbiddenScopeIfNeeded( |
456 GarbageCollectedMixinConstructorMarker* gcMixinMarker) { | 456 GarbageCollectedMixinConstructorMarker* gcMixinMarker) { |
457 ASSERT(checkThread()); | 457 DCHECK(checkThread()); |
458 if (!m_gcMixinMarker) { | 458 if (!m_gcMixinMarker) { |
459 enterMixinConstructionScope(); | 459 enterMixinConstructionScope(); |
460 m_gcMixinMarker = gcMixinMarker; | 460 m_gcMixinMarker = gcMixinMarker; |
461 } | 461 } |
462 } | 462 } |
463 void leaveGCForbiddenScopeIfNeeded( | 463 void leaveGCForbiddenScopeIfNeeded( |
464 GarbageCollectedMixinConstructorMarker* gcMixinMarker) { | 464 GarbageCollectedMixinConstructorMarker* gcMixinMarker) { |
465 ASSERT(checkThread()); | 465 DCHECK(checkThread()); |
466 if (m_gcMixinMarker == gcMixinMarker) { | 466 if (m_gcMixinMarker == gcMixinMarker) { |
467 leaveMixinConstructionScope(); | 467 leaveMixinConstructionScope(); |
468 m_gcMixinMarker = nullptr; | 468 m_gcMixinMarker = nullptr; |
469 } | 469 } |
470 } | 470 } |
471 | 471 |
472 // vectorBackingArena() returns an arena that the vector allocation should | 472 // vectorBackingArena() returns an arena that the vector allocation should |
473 // use. We have four vector arenas and want to choose the best arena here. | 473 // use. We have four vector arenas and want to choose the best arena here. |
474 // | 474 // |
475 // The goal is to improve the succession rate where expand and | 475 // The goal is to improve the succession rate where expand and |
(...skipping 13 matching lines...) Expand all Loading... |
489 // To implement the heuristics, we add an arenaAge to each arena. The arenaAge | 489 // To implement the heuristics, we add an arenaAge to each arena. The arenaAge |
490 // is updated if: | 490 // is updated if: |
491 // | 491 // |
492 // - a vector on the arena is expanded; or | 492 // - a vector on the arena is expanded; or |
493 // - a vector that meets the condition (*) is allocated on the arena | 493 // - a vector that meets the condition (*) is allocated on the arena |
494 // | 494 // |
495 // (*) More than 33% of the same type of vectors have been promptly | 495 // (*) More than 33% of the same type of vectors have been promptly |
496 // freed since the last GC. | 496 // freed since the last GC. |
497 // | 497 // |
498 BaseArena* vectorBackingArena(size_t gcInfoIndex) { | 498 BaseArena* vectorBackingArena(size_t gcInfoIndex) { |
499 ASSERT(checkThread()); | 499 DCHECK(checkThread()); |
500 size_t entryIndex = gcInfoIndex & likelyToBePromptlyFreedArrayMask; | 500 size_t entryIndex = gcInfoIndex & likelyToBePromptlyFreedArrayMask; |
501 --m_likelyToBePromptlyFreed[entryIndex]; | 501 --m_likelyToBePromptlyFreed[entryIndex]; |
502 int arenaIndex = m_vectorBackingArenaIndex; | 502 int arenaIndex = m_vectorBackingArenaIndex; |
503 // If m_likelyToBePromptlyFreed[entryIndex] > 0, that means that | 503 // If m_likelyToBePromptlyFreed[entryIndex] > 0, that means that |
504 // more than 33% of vectors of the type have been promptly freed | 504 // more than 33% of vectors of the type have been promptly freed |
505 // since the last GC. | 505 // since the last GC. |
506 if (m_likelyToBePromptlyFreed[entryIndex] > 0) { | 506 if (m_likelyToBePromptlyFreed[entryIndex] > 0) { |
507 m_arenaAges[arenaIndex] = ++m_currentArenaAges; | 507 m_arenaAges[arenaIndex] = ++m_currentArenaAges; |
508 m_vectorBackingArenaIndex = arenaIndexOfVectorArenaLeastRecentlyExpanded( | 508 m_vectorBackingArenaIndex = arenaIndexOfVectorArenaLeastRecentlyExpanded( |
509 BlinkGC::Vector1ArenaIndex, BlinkGC::Vector4ArenaIndex); | 509 BlinkGC::Vector1ArenaIndex, BlinkGC::Vector4ArenaIndex); |
510 } | 510 } |
511 ASSERT(isVectorArenaIndex(arenaIndex)); | 511 DCHECK(isVectorArenaIndex(arenaIndex)); |
512 return m_arenas[arenaIndex]; | 512 return m_arenas[arenaIndex]; |
513 } | 513 } |
514 BaseArena* expandedVectorBackingArena(size_t gcInfoIndex); | 514 BaseArena* expandedVectorBackingArena(size_t gcInfoIndex); |
515 static bool isVectorArenaIndex(int arenaIndex) { | 515 static bool isVectorArenaIndex(int arenaIndex) { |
516 return BlinkGC::Vector1ArenaIndex <= arenaIndex && | 516 return BlinkGC::Vector1ArenaIndex <= arenaIndex && |
517 arenaIndex <= BlinkGC::Vector4ArenaIndex; | 517 arenaIndex <= BlinkGC::Vector4ArenaIndex; |
518 } | 518 } |
519 void allocationPointAdjusted(int arenaIndex); | 519 void allocationPointAdjusted(int arenaIndex); |
520 void promptlyFreed(size_t gcInfoIndex); | 520 void promptlyFreed(size_t gcInfoIndex); |
521 | 521 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
554 | 554 |
555 // Register the pre-finalizer for the |self| object. The class T must have | 555 // Register the pre-finalizer for the |self| object. The class T must have |
556 // USING_PRE_FINALIZER(). | 556 // USING_PRE_FINALIZER(). |
557 template <typename T> | 557 template <typename T> |
558 class PrefinalizerRegistration final { | 558 class PrefinalizerRegistration final { |
559 public: | 559 public: |
560 PrefinalizerRegistration(T* self) { | 560 PrefinalizerRegistration(T* self) { |
561 static_assert(sizeof(&T::invokePreFinalizer) > 0, | 561 static_assert(sizeof(&T::invokePreFinalizer) > 0, |
562 "USING_PRE_FINALIZER(T) must be defined."); | 562 "USING_PRE_FINALIZER(T) must be defined."); |
563 ThreadState* state = ThreadState::current(); | 563 ThreadState* state = ThreadState::current(); |
564 #if ENABLE(ASSERT) | 564 #if DCHECK_IS_ON() |
565 DCHECK(state->checkThread()); | 565 DCHECK(state->checkThread()); |
566 #endif | 566 #endif |
567 DCHECK(!state->sweepForbidden()); | 567 DCHECK(!state->sweepForbidden()); |
568 DCHECK(!state->m_orderedPreFinalizers.contains( | 568 DCHECK(!state->m_orderedPreFinalizers.contains( |
569 PreFinalizer(self, T::invokePreFinalizer))); | 569 PreFinalizer(self, T::invokePreFinalizer))); |
570 state->m_orderedPreFinalizers.add( | 570 state->m_orderedPreFinalizers.add( |
571 PreFinalizer(self, T::invokePreFinalizer)); | 571 PreFinalizer(self, T::invokePreFinalizer)); |
572 } | 572 } |
573 }; | 573 }; |
574 | 574 |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
759 template <ThreadAffinity affinity> | 759 template <ThreadAffinity affinity> |
760 class ThreadStateFor; | 760 class ThreadStateFor; |
761 | 761 |
762 template <> | 762 template <> |
763 class ThreadStateFor<MainThreadOnly> { | 763 class ThreadStateFor<MainThreadOnly> { |
764 STATIC_ONLY(ThreadStateFor); | 764 STATIC_ONLY(ThreadStateFor); |
765 | 765 |
766 public: | 766 public: |
767 static ThreadState* state() { | 767 static ThreadState* state() { |
768 // This specialization must only be used from the main thread. | 768 // This specialization must only be used from the main thread. |
769 ASSERT(ThreadState::current()->isMainThread()); | 769 DCHECK(ThreadState::current()->isMainThread()); |
770 return ThreadState::mainThreadState(); | 770 return ThreadState::mainThreadState(); |
771 } | 771 } |
772 }; | 772 }; |
773 | 773 |
774 template <> | 774 template <> |
775 class ThreadStateFor<AnyThread> { | 775 class ThreadStateFor<AnyThread> { |
776 STATIC_ONLY(ThreadStateFor); | 776 STATIC_ONLY(ThreadStateFor); |
777 | 777 |
778 public: | 778 public: |
779 static ThreadState* state() { return ThreadState::current(); } | 779 static ThreadState* state() { return ThreadState::current(); } |
780 }; | 780 }; |
781 | 781 |
782 } // namespace blink | 782 } // namespace blink |
783 | 783 |
784 #endif // ThreadState_h | 784 #endif // ThreadState_h |
OLD | NEW |