Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(87)

Side by Side Diff: third_party/WebKit/Source/platform/heap/ThreadState.h

Issue 1477023003: Refactor the Heap into ThreadHeap to prepare for per thread heaps Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 class BasePage; 54 class BasePage;
55 class CallbackStack; 55 class CallbackStack;
56 struct GCInfo; 56 struct GCInfo;
57 class GarbageCollectedMixinConstructorMarker; 57 class GarbageCollectedMixinConstructorMarker;
58 class HeapObjectHeader; 58 class HeapObjectHeader;
59 class PersistentNode; 59 class PersistentNode;
60 class PersistentRegion; 60 class PersistentRegion;
61 class BaseArena; 61 class BaseArena;
62 class SafePointAwareMutexLocker; 62 class SafePointAwareMutexLocker;
63 class SafePointBarrier; 63 class SafePointBarrier;
64 class ThreadHeap;
64 class ThreadState; 65 class ThreadState;
65 class Visitor; 66 class Visitor;
66 67
67 // Declare that a class has a pre-finalizer. The pre-finalizer is called 68 // Declare that a class has a pre-finalizer. The pre-finalizer is called
68 // before any object gets swept, so it is safe to touch on-heap objects 69 // before any object gets swept, so it is safe to touch on-heap objects
69 // that may be collected in the same GC cycle. If you cannot avoid touching 70 // that may be collected in the same GC cycle. If you cannot avoid touching
70 // on-heap objects in a destructor (which is not allowed), you can consider 71 // on-heap objects in a destructor (which is not allowed), you can consider
71 // using the pre-finalizer. The only restriction is that the pre-finalizer 72 // using the pre-finalizer. The only restriction is that the pre-finalizer
72 // must not resurrect dead objects (e.g., store unmarked objects into 73 // must not resurrect dead objects (e.g., store unmarked objects into
73 // Members etc). The pre-finalizer is called on the thread that registered 74 // Members etc). The pre-finalizer is called on the thread that registered
(...skipping 25 matching lines...) Expand all
99 // { 100 // {
100 // m_bar->...; // It is safe to touch other on-heap objects. 101 // m_bar->...; // It is safe to touch other on-heap objects.
101 // } 102 // }
102 // Member<Bar> m_bar; 103 // Member<Bar> m_bar;
103 // }; 104 // };
104 #define USING_PRE_FINALIZER(Class, preFinalizer) \ 105 #define USING_PRE_FINALIZER(Class, preFinalizer) \
105 public: \ 106 public: \
106 static bool invokePreFinalizer(void* object) \ 107 static bool invokePreFinalizer(void* object) \
107 { \ 108 { \
108 Class* self = reinterpret_cast<Class*>(object); \ 109 Class* self = reinterpret_cast<Class*>(object); \
109 if (Heap::isHeapObjectAlive(self)) \ 110 if (ThreadHeap::isHeapObjectAlive(self)) \
110 return false; \ 111 return false; \
111 self->Class::preFinalizer(); \ 112 self->Class::preFinalizer(); \
112 return true; \ 113 return true; \
113 } \ 114 } \
114 using UsingPreFinalizerMacroNeedsTrailingSemiColon = char 115 using UsingPreFinalizerMacroNeedsTrailingSemiColon = char
115 116
116 #if ENABLE(OILPAN) 117 #if ENABLE(OILPAN)
117 #define WILL_BE_USING_PRE_FINALIZER(Class, method) USING_PRE_FINALIZER(Class, me thod) 118 #define WILL_BE_USING_PRE_FINALIZER(Class, method) USING_PRE_FINALIZER(Class, me thod)
118 #else 119 #else
119 #define WILL_BE_USING_PRE_FINALIZER(Class, method) 120 #define WILL_BE_USING_PRE_FINALIZER(Class, method)
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 } 168 }
168 ~SweepForbiddenScope() 169 ~SweepForbiddenScope()
169 { 170 {
170 ASSERT(m_state->m_sweepForbidden); 171 ASSERT(m_state->m_sweepForbidden);
171 m_state->m_sweepForbidden = false; 172 m_state->m_sweepForbidden = false;
172 } 173 }
173 private: 174 private:
174 ThreadState* m_state; 175 ThreadState* m_state;
175 }; 176 };
176 177
177 // The set of ThreadStates for all threads attached to the Blink 178 void lockThreadAttachMutex();
178 // garbage collector. 179 void unlockThreadAttachMutex();
179 using AttachedThreadStateSet = HashSet<ThreadState*>;
180 static AttachedThreadStateSet& attachedThreads();
181 static RecursiveMutex& threadAttachMutex();
182 static void lockThreadAttachMutex();
183 static void unlockThreadAttachMutex();
184 180
185 // Initialize threading infrastructure. Should be called from the main 181 // Initialize threading infrastructure. Should be called from the main
186 // thread. 182 // thread.
187 static void init(); 183 static void init();
188 static void shutdown();
189 bool isTerminating() { return m_isTerminating; } 184 bool isTerminating() { return m_isTerminating; }
190 185
191 static void attachMainThread(); 186 static void attachMainThread();
192 static void detachMainThread(); 187 static void detachMainThread();
193 void cleanupMainThread(); 188 void cleanupMainThread();
194 189
195 // Trace all persistent roots, called when marking the managed heap objects.
196 static void visitPersistentRoots(Visitor*);
197
198 // Trace all objects found on the stack, used when doing conservative GCs.
199 static void visitStackRoots(Visitor*);
200
201 // Associate ThreadState object with the current thread. After this 190 // Associate ThreadState object with the current thread. After this
202 // call thread can start using the garbage collected heap infrastructure. 191 // call thread can start using the garbage collected heap infrastructure.
203 // It also has to periodically check for safepoints. 192 // It also has to periodically check for safepoints.
204 static void attach(); 193 static void attach();
205 194
206 // Disassociate attached ThreadState from the current thread. The thread 195 // Disassociate attached ThreadState from the current thread. The thread
207 // can no longer use the garbage collected heap after this call. 196 // can no longer use the garbage collected heap after this call.
208 static void detach(); 197 static void detachCurrentThread();
198 void detach();
209 199
210 static ThreadState* current() 200 static ThreadState* current()
211 { 201 {
212 #if defined(__GLIBC__) || OS(ANDROID) || OS(FREEBSD) 202 #if defined(__GLIBC__) || OS(ANDROID) || OS(FREEBSD)
213 // TLS lookup is fast in these platforms. 203 // TLS lookup is fast in these platforms.
214 return **s_threadSpecific; 204 return **s_threadSpecific;
215 #else 205 #else
216 uintptr_t dummy; 206 uintptr_t dummy;
217 uintptr_t addressDiff = s_mainThreadStackStart - reinterpret_cast<uintpt r_t>(&dummy); 207 uintptr_t addressDiff = s_mainThreadStackStart - reinterpret_cast<uintpt r_t>(&dummy);
218 // This is a fast way to judge if we are in the main thread. 208 // This is a fast way to judge if we are in the main thread.
219 // If |&dummy| is within |s_mainThreadUnderestimatedStackSize| byte from 209 // If |&dummy| is within |s_mainThreadUnderestimatedStackSize| byte from
220 // the stack start of the main thread, we judge that we are in 210 // the stack start of the main thread, we judge that we are in
221 // the main thread. 211 // the main thread.
222 if (LIKELY(addressDiff < s_mainThreadUnderestimatedStackSize)) { 212 if (LIKELY(addressDiff < s_mainThreadUnderestimatedStackSize)) {
223 ASSERT(**s_threadSpecific == mainThreadState()); 213 ASSERT(**s_threadSpecific == mainThreadState());
224 return mainThreadState(); 214 return mainThreadState();
225 } 215 }
226 // TLS lookup is slow. 216 // TLS lookup is slow.
227 return **s_threadSpecific; 217 return **s_threadSpecific;
228 #endif 218 #endif
229 } 219 }
230 220
231 static ThreadState* mainThreadState() 221 static ThreadState* mainThreadState()
232 { 222 {
233 return reinterpret_cast<ThreadState*>(s_mainThreadStateStorage); 223 return reinterpret_cast<ThreadState*>(s_mainThreadStateStorage);
234 } 224 }
235 225
226 static ThreadState* fromObject(const void*);
227
236 bool isMainThread() const { return this == mainThreadState(); } 228 bool isMainThread() const { return this == mainThreadState(); }
237 #if ENABLE(ASSERT) 229 #if ENABLE(ASSERT)
238 bool checkThread() const { return m_thread == currentThread(); } 230 bool checkThread() const { return m_thread == currentThread(); }
239 #endif 231 #endif
240 232
233 ThreadHeap& heap() { return *m_heap; }
234
235 // When ThreadState is detaching from non-main thread its
236 // heap is expected to be empty (because it is going away).
237 // Perform registered cleanup tasks and garbage collection
238 // to sweep away any objects that are left on this heap.
239 // We assert that nothing must remain after this cleanup.
240 // If assertion does not hold we crash as we are potentially
241 // in the dangling pointer situation.
242 void runThreadTerminationGC();
243
241 void performIdleGC(double deadlineSeconds); 244 void performIdleGC(double deadlineSeconds);
242 void performIdleLazySweep(double deadlineSeconds); 245 void performIdleLazySweep(double deadlineSeconds);
243 246
244 void scheduleIdleGC(); 247 void scheduleIdleGC();
245 void scheduleIdleLazySweep(); 248 void scheduleIdleLazySweep();
246 void schedulePreciseGC(); 249 void schedulePreciseGC();
247 void scheduleV8FollowupGCIfNeeded(BlinkGC::V8GCType); 250 void scheduleV8FollowupGCIfNeeded(BlinkGC::V8GCType);
248 void schedulePageNavigationGCIfNeeded(float estimatedRemovalRatio); 251 void schedulePageNavigationGCIfNeeded(float estimatedRemovalRatio);
249 void schedulePageNavigationGC(); 252 void schedulePageNavigationGC();
250 void scheduleGCIfNeeded(); 253 void scheduleGCIfNeeded();
251 void willStartV8GC(BlinkGC::V8GCType); 254 void willStartV8GC(BlinkGC::V8GCType);
252 void setGCState(GCState); 255 void setGCState(GCState);
253 GCState gcState() const { return m_gcState; } 256 GCState gcState() const { return m_gcState; }
254 bool isInGC() const { return gcState() == GCRunning; } 257 bool isInGC() const { return gcState() == GCRunning; }
255 bool isSweepingInProgress() const 258 bool isSweepingInProgress() const
256 { 259 {
257 return gcState() == Sweeping || gcState() == SweepingAndPreciseGCSchedul ed || gcState() == SweepingAndIdleGCScheduled; 260 return gcState() == Sweeping || gcState() == SweepingAndPreciseGCSchedul ed || gcState() == SweepingAndIdleGCScheduled;
258 } 261 }
259 262
260 // A GC runs in the following sequence. 263 // A GC runs in the following sequence.
261 // 264 //
262 // 1) All threads park at safe points. 265 // 1) All threads park at safe points.
263 // 2) The GCing thread calls preGC() for all ThreadStates. 266 // 2) The GCing thread calls preGC() for all ThreadStates.
264 // 3) The GCing thread calls Heap::collectGarbage(). 267 // 3) The GCing thread calls ThreadHeap::collectGarbage().
265 // This does marking but doesn't do sweeping. 268 // This does marking but doesn't do sweeping.
266 // 4) The GCing thread calls postGC() for all ThreadStates. 269 // 4) The GCing thread calls postGC() for all ThreadStates.
267 // 5) The GCing thread resume all threads. 270 // 5) The GCing thread resume all threads.
268 // 6) Each thread calls preSweep(). 271 // 6) Each thread calls preSweep().
269 // 7) Each thread runs lazy sweeping (concurrently with sweepings 272 // 7) Each thread runs lazy sweeping (concurrently with sweepings
270 // in other threads) and eventually calls completeSweep(). 273 // in other threads) and eventually calls completeSweep().
271 // 8) Each thread calls postSweep(). 274 // 8) Each thread calls postSweep().
272 // 275 //
273 // Notes: 276 // Notes:
274 // - We stop the world between 1) and 5). 277 // - We stop the world between 1) and 5).
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 // there is a GC in progress. 325 // there is a GC in progress.
323 // 326 //
324 // Each thread that has ThreadState attached must: 327 // Each thread that has ThreadState attached must:
325 // - periodically check if GC is requested from another thread by calling a safePoint() method; 328 // - periodically check if GC is requested from another thread by calling a safePoint() method;
326 // - use SafePointScope around long running loops that have no safePoint() invocation inside, 329 // - use SafePointScope around long running loops that have no safePoint() invocation inside,
327 // such loops must not touch any heap object; 330 // such loops must not touch any heap object;
328 // - register an BlinkGCInterruptor that can interrupt long running loops that have no calls to safePoint and 331 // - register an BlinkGCInterruptor that can interrupt long running loops that have no calls to safePoint and
329 // are not wrapped in a SafePointScope (e.g. BlinkGCInterruptor for Java Script code) 332 // are not wrapped in a SafePointScope (e.g. BlinkGCInterruptor for Java Script code)
330 // 333 //
331 334
332 // Request all other threads to stop. Must only be called if the current thr ead is at safepoint.
333 static bool stopThreads();
334 static void resumeThreads();
335
336 // Check if GC is requested by another thread and pause this thread if this is the case. 335 // Check if GC is requested by another thread and pause this thread if this is the case.
337 // Can only be called when current thread is in a consistent state. 336 // Can only be called when current thread is in a consistent state.
338 void safePoint(BlinkGC::StackState); 337 void safePoint(BlinkGC::StackState);
339 338
340 // Mark current thread as running inside safepoint. 339 // Mark current thread as running inside safepoint.
341 void enterSafePoint(BlinkGC::StackState, void*); 340 void enterSafePoint(BlinkGC::StackState, void*);
342 void leaveSafePoint(SafePointAwareMutexLocker* = nullptr); 341 void leaveSafePoint(SafePointAwareMutexLocker* = nullptr);
343 bool isAtSafePoint() const { return m_atSafePoint; } 342 bool isAtSafePoint() const { return m_atSafePoint; }
344 343
345 void addInterruptor(PassOwnPtr<BlinkGCInterruptor>); 344 void addInterruptor(PassOwnPtr<BlinkGCInterruptor>);
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
577 576
578 void runScheduledGC(BlinkGC::StackState); 577 void runScheduledGC(BlinkGC::StackState);
579 578
580 void eagerSweep(); 579 void eagerSweep();
581 580
582 #if defined(ADDRESS_SANITIZER) 581 #if defined(ADDRESS_SANITIZER)
583 void poisonEagerArena(); 582 void poisonEagerArena();
584 void poisonAllHeaps(); 583 void poisonAllHeaps();
585 #endif 584 #endif
586 585
587 // When ThreadState is detaching from non-main thread its
588 // heap is expected to be empty (because it is going away).
589 // Perform registered cleanup tasks and garbage collection
590 // to sweep away any objects that are left on this heap.
591 // We assert that nothing must remain after this cleanup.
592 // If assertion does not hold we crash as we are potentially
593 // in the dangling pointer situation.
594 void cleanup();
595 void cleanupPages(); 586 void cleanupPages();
596 587
597 void prepareForThreadStateTermination(); 588 void prepareForThreadStateTermination();
598 589
599 void invokePreFinalizers(); 590 void invokePreFinalizers();
600 591
601 void takeSnapshot(SnapshotType); 592 void takeSnapshot(SnapshotType);
602 void clearArenaAges(); 593 void clearArenaAges();
603 int arenaIndexOfVectorArenaLeastRecentlyExpanded(int beginArenaIndex, int en dArenaIndex); 594 int arenaIndexOfVectorArenaLeastRecentlyExpanded(int beginArenaIndex, int en dArenaIndex);
604 595
605 void reportMemoryToV8(); 596 void reportMemoryToV8();
606 597
607 // Should only be called under protection of threadAttachMutex(). 598 // Should only be called under protection of threadAttachMutex().
608 const Vector<OwnPtr<BlinkGCInterruptor>>& interruptors() const { return m_in terruptors; } 599 const Vector<OwnPtr<BlinkGCInterruptor>>& interruptors() const { return m_in terruptors; }
609 600
610 friend class SafePointAwareMutexLocker; 601 friend class SafePointAwareMutexLocker;
611 friend class SafePointBarrier; 602 friend class SafePointBarrier;
612 friend class SafePointScope; 603 friend class SafePointScope;
613 604
614 static WTF::ThreadSpecific<ThreadState*>* s_threadSpecific; 605 static WTF::ThreadSpecific<ThreadState*>* s_threadSpecific;
615 static uintptr_t s_mainThreadStackStart; 606 static uintptr_t s_mainThreadStackStart;
616 static uintptr_t s_mainThreadUnderestimatedStackSize; 607 static uintptr_t s_mainThreadUnderestimatedStackSize;
617 static SafePointBarrier* s_safePointBarrier;
618 608
619 // We can't create a static member of type ThreadState here 609 // We can't create a static member of type ThreadState here
620 // because it will introduce global constructor and destructor. 610 // because it will introduce global constructor and destructor.
621 // We would like to manage lifetime of the ThreadState attached 611 // We would like to manage lifetime of the ThreadState attached
622 // to the main thread explicitly instead and still use normal 612 // to the main thread explicitly instead and still use normal
623 // constructor and destructor for the ThreadState class. 613 // constructor and destructor for the ThreadState class.
624 // For this we reserve static storage for the main ThreadState 614 // For this we reserve static storage for the main ThreadState
625 // and lazily construct ThreadState in it using placement new. 615 // and lazily construct ThreadState in it using placement new.
626 static uint8_t s_mainThreadStateStorage[]; 616 static uint8_t s_mainThreadStateStorage[];
627 617
618 ThreadHeap* m_heap;
628 ThreadIdentifier m_thread; 619 ThreadIdentifier m_thread;
629 OwnPtr<PersistentRegion> m_persistentRegion; 620 OwnPtr<PersistentRegion> m_persistentRegion;
630 BlinkGC::StackState m_stackState; 621 BlinkGC::StackState m_stackState;
631 #if OS(WIN) && COMPILER(MSVC) 622 #if OS(WIN) && COMPILER(MSVC)
632 size_t m_threadStackSize; 623 size_t m_threadStackSize;
633 #endif 624 #endif
634 intptr_t* m_startOfStack; 625 intptr_t* m_startOfStack;
635 intptr_t* m_endOfStack; 626 intptr_t* m_endOfStack;
636 627
637 void* m_safePointScopeMarker; 628 void* m_safePointScopeMarker;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 697
707 template<> class ThreadStateFor<AnyThread> { 698 template<> class ThreadStateFor<AnyThread> {
708 STATIC_ONLY(ThreadStateFor); 699 STATIC_ONLY(ThreadStateFor);
709 public: 700 public:
710 static ThreadState* state() { return ThreadState::current(); } 701 static ThreadState* state() { return ThreadState::current(); }
711 }; 702 };
712 703
713 } // namespace blink 704 } // namespace blink
714 705
715 #endif // ThreadState_h 706 #endif // ThreadState_h
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/platform/heap/SafePoint.cpp ('k') | third_party/WebKit/Source/platform/heap/ThreadState.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698