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

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

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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 #endif 65 #endif
66 66
67 #include <v8.h> 67 #include <v8.h>
68 68
69 namespace blink { 69 namespace blink {
70 70
71 WTF::ThreadSpecific<ThreadState*>* ThreadState::s_threadSpecific = nullptr; 71 WTF::ThreadSpecific<ThreadState*>* ThreadState::s_threadSpecific = nullptr;
72 uintptr_t ThreadState::s_mainThreadStackStart = 0; 72 uintptr_t ThreadState::s_mainThreadStackStart = 0;
73 uintptr_t ThreadState::s_mainThreadUnderestimatedStackSize = 0; 73 uintptr_t ThreadState::s_mainThreadUnderestimatedStackSize = 0;
74 uint8_t ThreadState::s_mainThreadStateStorage[sizeof(ThreadState)]; 74 uint8_t ThreadState::s_mainThreadStateStorage[sizeof(ThreadState)];
75 SafePointBarrier* ThreadState::s_safePointBarrier = nullptr;
76
77 RecursiveMutex& ThreadState::threadAttachMutex()
78 {
79 DEFINE_THREAD_SAFE_STATIC_LOCAL(RecursiveMutex, mutex, (new RecursiveMutex)) ;
80 return mutex;
81 }
82 75
83 ThreadState::ThreadState() 76 ThreadState::ThreadState()
84 : m_thread(currentThread()) 77 : m_thread(currentThread())
85 , m_persistentRegion(adoptPtr(new PersistentRegion())) 78 , m_persistentRegion(adoptPtr(new PersistentRegion()))
86 #if OS(WIN) && COMPILER(MSVC) 79 #if OS(WIN) && COMPILER(MSVC)
87 , m_threadStackSize(0) 80 , m_threadStackSize(0)
88 #endif 81 #endif
89 , m_startOfStack(reinterpret_cast<intptr_t*>(StackFrameDepth::getStackStart( ))) 82 , m_startOfStack(reinterpret_cast<intptr_t*>(StackFrameDepth::getStackStart( )))
90 , m_endOfStack(reinterpret_cast<intptr_t*>(StackFrameDepth::getStackStart()) ) 83 , m_endOfStack(reinterpret_cast<intptr_t*>(StackFrameDepth::getStackStart()) )
91 , m_safePointScopeMarker(nullptr) 84 , m_safePointScopeMarker(nullptr)
(...skipping 23 matching lines...) Expand all
115 { 108 {
116 ASSERT(checkThread()); 109 ASSERT(checkThread());
117 ASSERT(!**s_threadSpecific); 110 ASSERT(!**s_threadSpecific);
118 **s_threadSpecific = this; 111 **s_threadSpecific = this;
119 112
120 if (isMainThread()) { 113 if (isMainThread()) {
121 s_mainThreadStackStart = reinterpret_cast<uintptr_t>(m_startOfStack) - s izeof(void*); 114 s_mainThreadStackStart = reinterpret_cast<uintptr_t>(m_startOfStack) - s izeof(void*);
122 size_t underestimatedStackSize = StackFrameDepth::getUnderestimatedStack Size(); 115 size_t underestimatedStackSize = StackFrameDepth::getUnderestimatedStack Size();
123 if (underestimatedStackSize > sizeof(void*)) 116 if (underestimatedStackSize > sizeof(void*))
124 s_mainThreadUnderestimatedStackSize = underestimatedStackSize - size of(void*); 117 s_mainThreadUnderestimatedStackSize = underestimatedStackSize - size of(void*);
118 m_heap = new ThreadHeap();
119 } else {
120 m_heap = &ThreadState::mainThreadState()->heap();
125 } 121 }
122 ASSERT(m_heap);
123 m_heap->attach(this);
126 124
127 for (int arenaIndex = 0; arenaIndex < BlinkGC::LargeObjectArenaIndex; arenaI ndex++) 125 for (int arenaIndex = 0; arenaIndex < BlinkGC::LargeObjectArenaIndex; arenaI ndex++)
128 m_arenas[arenaIndex] = new NormalPageArena(this, arenaIndex); 126 m_arenas[arenaIndex] = new NormalPageArena(this, arenaIndex);
129 m_arenas[BlinkGC::LargeObjectArenaIndex] = new LargeObjectArena(this, BlinkG C::LargeObjectArenaIndex); 127 m_arenas[BlinkGC::LargeObjectArenaIndex] = new LargeObjectArena(this, BlinkG C::LargeObjectArenaIndex);
130 128
131 m_likelyToBePromptlyFreed = adoptArrayPtr(new int[likelyToBePromptlyFreedArr aySize]); 129 m_likelyToBePromptlyFreed = adoptArrayPtr(new int[likelyToBePromptlyFreedArr aySize]);
132 clearArenaAges(); 130 clearArenaAges();
133 131
134 // There is little use of weak references and collections off the main threa d; 132 // There is little use of weak references and collections off the main threa d;
135 // use a much lower initial block reservation. 133 // use a much lower initial block reservation.
(...skipping 12 matching lines...) Expand all
148 **s_threadSpecific = nullptr; 146 **s_threadSpecific = nullptr;
149 if (isMainThread()) { 147 if (isMainThread()) {
150 s_mainThreadStackStart = 0; 148 s_mainThreadStackStart = 0;
151 s_mainThreadUnderestimatedStackSize = 0; 149 s_mainThreadUnderestimatedStackSize = 0;
152 } 150 }
153 } 151 }
154 152
155 void ThreadState::init() 153 void ThreadState::init()
156 { 154 {
157 s_threadSpecific = new WTF::ThreadSpecific<ThreadState*>(); 155 s_threadSpecific = new WTF::ThreadSpecific<ThreadState*>();
158 s_safePointBarrier = new SafePointBarrier;
159 }
160
161 void ThreadState::shutdown()
162 {
163 delete s_safePointBarrier;
164 s_safePointBarrier = nullptr;
165
166 // Thread-local storage shouldn't be disposed, so we don't call ~ThreadSpeci fic().
167 } 156 }
168 157
169 #if OS(WIN) && COMPILER(MSVC) 158 #if OS(WIN) && COMPILER(MSVC)
170 size_t ThreadState::threadStackSize() 159 size_t ThreadState::threadStackSize()
171 { 160 {
172 if (m_threadStackSize) 161 if (m_threadStackSize)
173 return m_threadStackSize; 162 return m_threadStackSize;
174 163
175 // Notice that we cannot use the TIB's StackLimit for the stack end, as it 164 // Notice that we cannot use the TIB's StackLimit for the stack end, as it
176 // tracks the end of the committed range. We're after the end of the reserve d 165 // tracks the end of the committed range. We're after the end of the reserve d
(...skipping 19 matching lines...) Expand all
196 // http://blogs.msdn.com/b/satyem/archive/2012/08/13/thread-s-stack-memory-m anagement.aspx 185 // http://blogs.msdn.com/b/satyem/archive/2012/08/13/thread-s-stack-memory-m anagement.aspx
197 // explains the details. 186 // explains the details.
198 RELEASE_ASSERT(m_threadStackSize > 4 * 0x1000); 187 RELEASE_ASSERT(m_threadStackSize > 4 * 0x1000);
199 m_threadStackSize -= 4 * 0x1000; 188 m_threadStackSize -= 4 * 0x1000;
200 return m_threadStackSize; 189 return m_threadStackSize;
201 } 190 }
202 #endif 191 #endif
203 192
204 void ThreadState::attachMainThread() 193 void ThreadState::attachMainThread()
205 { 194 {
206 MutexLocker locker(threadAttachMutex()); 195 RELEASE_ASSERT(!ProcessHeap::s_shutdownComplete);
207 ThreadState* state = new (s_mainThreadStateStorage) ThreadState(); 196 new(s_mainThreadStateStorage) ThreadState();
208 attachedThreads().add(state);
209 } 197 }
210 198
199 void ThreadState::attach()
200 {
201 RELEASE_ASSERT(!ProcessHeap::s_shutdownComplete);
202 new ThreadState();
203 }
204
205 void ThreadState::cleanupPages()
206 {
207 ASSERT(checkThread());
208 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i)
209 m_arenas[i]->cleanupPages();
210 }
211
212 void ThreadState::runThreadTerminationGC()
213 {
214 if (isMainThread()) {
215 cleanupPages();
216 return;
217 }
218 ASSERT(checkThread());
219
220 // Finish sweeping.
221 completeSweep();
222
223 // From here on ignore all conservatively discovered
224 // pointers into the heap owned by this thread.
225 m_isTerminating = true;
226
227 // Set the terminate flag on all heap pages of this thread. This is used to
228 // ensure we don't trace pages on other threads that are not part of the
229 // thread local GC.
230 prepareForThreadStateTermination();
231
232 ProcessHeap::crossThreadPersistentRegion().prepareForThreadStateTermination( this);
233
234 // Do thread local GC's as long as the count of thread local Persistents
235 // changes and is above zero.
236 int oldCount = -1;
237 int currentCount = getPersistentRegion()->numberOfPersistents();
238 ASSERT(currentCount >= 0);
239 while (currentCount != oldCount) {
240 ThreadHeap::collectGarbageForTerminatingThread(this);
241 oldCount = currentCount;
242 currentCount = getPersistentRegion()->numberOfPersistents();
243 }
244 // We should not have any persistents left when getting to this point,
245 // if we have it is probably a bug so adding a debug ASSERT to catch this.
246 ASSERT(!currentCount);
247 // All of pre-finalizers should be consumed.
248 ASSERT(m_orderedPreFinalizers.isEmpty());
249 RELEASE_ASSERT(gcState() == NoGCScheduled);
250
251 // Add pages to the orphaned page pool to ensure any global GCs from this po int
252 // on will not trace objects on this thread's arenas.
253 cleanupPages();
254 }
211 255
212 void ThreadState::cleanupMainThread() 256 void ThreadState::cleanupMainThread()
213 { 257 {
214 ASSERT(isMainThread()); 258 ASSERT(isMainThread());
215 259
216 #if defined(LEAK_SANITIZER) 260 #if defined(LEAK_SANITIZER)
217 // If LSan is about to perform leak detection, release all the registered 261 // If LSan is about to perform leak detection, release all the registered
218 // static Persistent<> root references to global caches that Blink keeps, 262 // static Persistent<> root references to global caches that Blink keeps,
219 // followed by GCs to clear out all they referred to. 263 // followed by GCs to clear out all they referred to.
220 // 264 //
221 // This is not needed for caches over non-Oilpan objects, as they're 265 // This is not needed for caches over non-Oilpan objects, as they're
222 // not scanned by LSan due to being held in non-global storage 266 // not scanned by LSan due to being held in non-global storage
223 // ("static" references inside functions/methods.) 267 // ("static" references inside functions/methods.)
224 releaseStaticPersistentNodes(); 268 releaseStaticPersistentNodes();
225 Heap::collectAllGarbage(); 269 ThreadHeap::collectAllGarbage();
226 #endif 270 #endif
227 271
228 // Finish sweeping before shutting down V8. Otherwise, some destructor 272 // Finish sweeping before shutting down V8. Otherwise, some destructor
229 // may access V8 and cause crashes. 273 // may access V8 and cause crashes.
230 completeSweep(); 274 completeSweep();
231 275
232 // It is unsafe to trigger GCs after this point because some 276 // It is unsafe to trigger GCs after this point because some
233 // destructor may access already-detached V8 and cause crashes. 277 // destructor may access already-detached V8 and cause crashes.
234 // Also it is useless. So we forbid GCs. 278 // Also it is useless. So we forbid GCs.
235 enterGCForbiddenScope(); 279 enterGCForbiddenScope();
236 } 280 }
237 281
238 void ThreadState::detachMainThread() 282 void ThreadState::detachMainThread()
239 { 283 {
240 // Enter a safe point before trying to acquire threadAttachMutex 284 // Enter a safe point before trying to acquire threadAttachMutex
241 // to avoid dead lock if another thread is preparing for GC, has acquired 285 // to avoid dead lock if another thread is preparing for GC, has acquired
242 // threadAttachMutex and waiting for other threads to pause or reach a 286 // threadAttachMutex and waiting for other threads to pause or reach a
243 // safepoint. 287 // safepoint.
244 ThreadState* state = mainThreadState(); 288 ThreadState* state = mainThreadState();
245 ASSERT(state == ThreadState::current());
246 ASSERT(state->checkThread());
247 ASSERT(!state->isSweepingInProgress());
248 289
249 // The main thread must be the last thread that gets detached. 290 // 1. Finish sweeping.
250 RELEASE_ASSERT(ThreadState::attachedThreads().size() == 1); 291 state->completeSweep();
251 292 state->detach();
252 // Add the main thread's heap pages to the orphaned pool.
253 state->cleanupPages();
254
255 // Detach the main thread. We don't need to grab a lock because
256 // the main thread should be the last thread that gets detached.
257 ASSERT(attachedThreads().contains(state));
258 attachedThreads().remove(state);
259 state->~ThreadState();
260 } 293 }
261 294
262 void ThreadState::attach() 295 void ThreadState::detachCurrentThread()
263 { 296 {
264 MutexLocker locker(threadAttachMutex()); 297 current()->detach();
265 ThreadState* state = new ThreadState();
266 attachedThreads().add(state);
267 }
268
269 void ThreadState::cleanupPages()
270 {
271 ASSERT(checkThread());
272 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i)
273 m_arenas[i]->cleanupPages();
274 }
275
276 void ThreadState::cleanup()
277 {
278 ASSERT(checkThread());
279 {
280 // Grab the threadAttachMutex to ensure only one thread can shutdown at
281 // a time and that no other thread can do a global GC. It also allows
282 // safe iteration of the attachedThreads set which happens as part of
283 // thread local GC asserts. We enter a safepoint while waiting for the
284 // lock to avoid a dead-lock where another thread has already requested
285 // GC.
286 SafePointAwareMutexLocker locker(threadAttachMutex(), BlinkGC::NoHeapPoi ntersOnStack);
287
288 // Finish sweeping.
289 completeSweep();
290
291 // From here on ignore all conservatively discovered
292 // pointers into the heap owned by this thread.
293 m_isTerminating = true;
294
295 // Set the terminate flag on all heap pages of this thread. This is used to
296 // ensure we don't trace pages on other threads that are not part of the
297 // thread local GC.
298 prepareForThreadStateTermination();
299
300 Heap::crossThreadPersistentRegion().prepareForThreadStateTermination(thi s);
301
302 // Do thread local GC's as long as the count of thread local Persistents
303 // changes and is above zero.
304 int oldCount = -1;
305 int currentCount = getPersistentRegion()->numberOfPersistents();
306 ASSERT(currentCount >= 0);
307 while (currentCount != oldCount) {
308 Heap::collectGarbageForTerminatingThread(this);
309 oldCount = currentCount;
310 currentCount = getPersistentRegion()->numberOfPersistents();
311 }
312 // We should not have any persistents left when getting to this point,
313 // if we have it is probably a bug so adding a debug ASSERT to catch thi s.
314 ASSERT(!currentCount);
315 // All of pre-finalizers should be consumed.
316 ASSERT(m_orderedPreFinalizers.isEmpty());
317 RELEASE_ASSERT(gcState() == NoGCScheduled);
318
319 // Add pages to the orphaned page pool to ensure any global GCs from thi s point
320 // on will not trace objects on this thread's arenas.
321 cleanupPages();
322
323 ASSERT(attachedThreads().contains(this));
324 attachedThreads().remove(this);
325 }
326 } 298 }
327 299
328 void ThreadState::detach() 300 void ThreadState::detach()
329 { 301 {
330 ThreadState* state = current(); 302 m_heap->detach(this);
331 state->cleanup(); 303 // Call destructor directly because we don't want to free s_mainThreadStateS torage.
332 RELEASE_ASSERT(state->gcState() == ThreadState::NoGCScheduled); 304 if (isMainThread()) {
333 delete state; 305 this->~ThreadState();
334 } 306 } else {
335 307 RELEASE_ASSERT(gcState() == ThreadState::NoGCScheduled);
336 void ThreadState::visitPersistentRoots(Visitor* visitor) 308 delete this;
337 { 309 }
338 TRACE_EVENT0("blink_gc", "ThreadState::visitPersistentRoots");
339 Heap::crossThreadPersistentRegion().tracePersistentNodes(visitor);
340
341 for (ThreadState* state : attachedThreads())
342 state->visitPersistents(visitor);
343 }
344
345 void ThreadState::visitStackRoots(Visitor* visitor)
346 {
347 TRACE_EVENT0("blink_gc", "ThreadState::visitStackRoots");
348 for (ThreadState* state : attachedThreads())
349 state->visitStack(visitor);
350 } 310 }
351 311
352 NO_SANITIZE_ADDRESS 312 NO_SANITIZE_ADDRESS
353 void ThreadState::visitAsanFakeStackForPointer(Visitor* visitor, Address ptr) 313 void ThreadState::visitAsanFakeStackForPointer(Visitor* visitor, Address ptr)
354 { 314 {
355 #if defined(ADDRESS_SANITIZER) 315 #if defined(ADDRESS_SANITIZER)
356 Address* start = reinterpret_cast<Address*>(m_startOfStack); 316 Address* start = reinterpret_cast<Address*>(m_startOfStack);
357 Address* end = reinterpret_cast<Address*>(m_endOfStack); 317 Address* end = reinterpret_cast<Address*>(m_endOfStack);
358 Address* fakeFrameStart = nullptr; 318 Address* fakeFrameStart = nullptr;
359 Address* fakeFrameEnd = nullptr; 319 Address* fakeFrameEnd = nullptr;
360 Address* maybeFakeFrame = reinterpret_cast<Address*>(ptr); 320 Address* maybeFakeFrame = reinterpret_cast<Address*>(ptr);
361 Address* realFrameForFakeFrame = 321 Address* realFrameForFakeFrame =
362 reinterpret_cast<Address*>( 322 reinterpret_cast<Address*>(
363 __asan_addr_is_in_fake_stack( 323 __asan_addr_is_in_fake_stack(
364 m_asanFakeStack, maybeFakeFrame, 324 m_asanFakeStack, maybeFakeFrame,
365 reinterpret_cast<void**>(&fakeFrameStart), 325 reinterpret_cast<void**>(&fakeFrameStart),
366 reinterpret_cast<void**>(&fakeFrameEnd))); 326 reinterpret_cast<void**>(&fakeFrameEnd)));
367 if (realFrameForFakeFrame) { 327 if (realFrameForFakeFrame) {
368 // This is a fake frame from the asan fake stack. 328 // This is a fake frame from the asan fake stack.
369 if (realFrameForFakeFrame > end && start > realFrameForFakeFrame) { 329 if (realFrameForFakeFrame > end && start > realFrameForFakeFrame) {
370 // The real stack address for the asan fake frame is 330 // The real stack address for the asan fake frame is
371 // within the stack range that we need to scan so we need 331 // within the stack range that we need to scan so we need
372 // to visit the values in the fake frame. 332 // to visit the values in the fake frame.
373 for (Address* p = fakeFrameStart; p < fakeFrameEnd; ++p) 333 for (Address* p = fakeFrameStart; p < fakeFrameEnd; ++p)
374 Heap::checkAndMarkPointer(visitor, *p); 334 m_heap->checkAndMarkPointer(visitor, *p);
375 } 335 }
376 } 336 }
377 #endif 337 #endif
378 } 338 }
379 339
380 NO_SANITIZE_ADDRESS 340 NO_SANITIZE_ADDRESS
381 void ThreadState::visitStack(Visitor* visitor) 341 void ThreadState::visitStack(Visitor* visitor)
382 { 342 {
383 if (m_stackState == BlinkGC::NoHeapPointersOnStack) 343 if (m_stackState == BlinkGC::NoHeapPointersOnStack)
384 return; 344 return;
(...skipping 15 matching lines...) Expand all
400 for (; current < start; ++current) { 360 for (; current < start; ++current) {
401 Address ptr = *current; 361 Address ptr = *current;
402 #if defined(MEMORY_SANITIZER) 362 #if defined(MEMORY_SANITIZER)
403 // |ptr| may be uninitialized by design. Mark it as initialized to keep 363 // |ptr| may be uninitialized by design. Mark it as initialized to keep
404 // MSan from complaining. 364 // MSan from complaining.
405 // Note: it may be tempting to get rid of |ptr| and simply use |current| 365 // Note: it may be tempting to get rid of |ptr| and simply use |current|
406 // here, but that would be incorrect. We intentionally use a local 366 // here, but that would be incorrect. We intentionally use a local
407 // variable because we don't want to unpoison the original stack. 367 // variable because we don't want to unpoison the original stack.
408 __msan_unpoison(&ptr, sizeof(ptr)); 368 __msan_unpoison(&ptr, sizeof(ptr));
409 #endif 369 #endif
410 Heap::checkAndMarkPointer(visitor, ptr); 370 m_heap->checkAndMarkPointer(visitor, ptr);
411 visitAsanFakeStackForPointer(visitor, ptr); 371 visitAsanFakeStackForPointer(visitor, ptr);
412 } 372 }
413 373
414 for (Address ptr : m_safePointStackCopy) { 374 for (Address ptr : m_safePointStackCopy) {
415 #if defined(MEMORY_SANITIZER) 375 #if defined(MEMORY_SANITIZER)
416 // See the comment above. 376 // See the comment above.
417 __msan_unpoison(&ptr, sizeof(ptr)); 377 __msan_unpoison(&ptr, sizeof(ptr));
418 #endif 378 #endif
419 Heap::checkAndMarkPointer(visitor, ptr); 379 m_heap->checkAndMarkPointer(visitor, ptr);
420 visitAsanFakeStackForPointer(visitor, ptr); 380 visitAsanFakeStackForPointer(visitor, ptr);
421 } 381 }
422 } 382 }
423 383
424 void ThreadState::visitPersistents(Visitor* visitor) 384 void ThreadState::visitPersistents(Visitor* visitor)
425 { 385 {
426 m_persistentRegion->tracePersistentNodes(visitor); 386 m_persistentRegion->tracePersistentNodes(visitor);
427 if (m_traceDOMWrappers) { 387 if (m_traceDOMWrappers) {
428 TRACE_EVENT0("blink_gc", "V8GCController::traceDOMWrappers"); 388 TRACE_EVENT0("blink_gc", "V8GCController::traceDOMWrappers");
429 m_traceDOMWrappers(m_isolate, visitor); 389 m_traceDOMWrappers(m_isolate, visitor);
(...skipping 14 matching lines...) Expand all
444 *slot = CallbackStack::Item(object, callback); 404 *slot = CallbackStack::Item(object, callback);
445 } 405 }
446 406
447 bool ThreadState::popAndInvokeThreadLocalWeakCallback(Visitor* visitor) 407 bool ThreadState::popAndInvokeThreadLocalWeakCallback(Visitor* visitor)
448 { 408 {
449 ASSERT(checkThread()); 409 ASSERT(checkThread());
450 // For weak processing we should never reach orphaned pages since orphaned 410 // For weak processing we should never reach orphaned pages since orphaned
451 // pages are not traced and thus objects on those pages are never be 411 // pages are not traced and thus objects on those pages are never be
452 // registered as objects on orphaned pages. We cannot assert this here since 412 // registered as objects on orphaned pages. We cannot assert this here since
453 // we might have an off-heap collection. We assert it in 413 // we might have an off-heap collection. We assert it in
454 // Heap::pushThreadLocalWeakCallback. 414 // ThreadHeap::pushThreadLocalWeakCallback.
455 if (CallbackStack::Item* item = m_threadLocalWeakCallbackStack->pop()) { 415 if (CallbackStack::Item* item = m_threadLocalWeakCallbackStack->pop()) {
456 // Note that the thread-local weak processing can be called for 416 // Note that the thread-local weak processing can be called for
457 // an already dead object (for which isHeapObjectAlive(object) can 417 // an already dead object (for which isHeapObjectAlive(object) can
458 // return false). This can happen in the following scenario: 418 // return false). This can happen in the following scenario:
459 // 419 //
460 // 1) Marking runs. A weak callback for an object X is registered 420 // 1) Marking runs. A weak callback for an object X is registered
461 // to the thread that created the object X (say, thread P). 421 // to the thread that created the object X (say, thread P).
462 // 2) Marking finishes. All other threads are resumed. 422 // 2) Marking finishes. All other threads are resumed.
463 // 3) The object X becomes unreachable. 423 // 3) The object X becomes unreachable.
464 // 4) A next GC hits before the thread P wakes up. 424 // 4) A next GC hits before the thread P wakes up.
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
510 470
511 if (isMainThread()) { 471 if (isMainThread()) {
512 double timeForThreadLocalWeakProcessing = WTF::currentTimeMS() - startTi me; 472 double timeForThreadLocalWeakProcessing = WTF::currentTimeMS() - startTi me;
513 DEFINE_STATIC_LOCAL(CustomCountHistogram, timeForWeakHistogram, ("BlinkG C.TimeForThreadLocalWeakProcessing", 1, 10 * 1000, 50)); 473 DEFINE_STATIC_LOCAL(CustomCountHistogram, timeForWeakHistogram, ("BlinkG C.TimeForThreadLocalWeakProcessing", 1, 10 * 1000, 50));
514 timeForWeakHistogram.count(timeForThreadLocalWeakProcessing); 474 timeForWeakHistogram.count(timeForThreadLocalWeakProcessing);
515 } 475 }
516 } 476 }
517 477
518 size_t ThreadState::totalMemorySize() 478 size_t ThreadState::totalMemorySize()
519 { 479 {
520 return Heap::allocatedObjectSize() + Heap::markedObjectSize() + WTF::Partiti ons::totalSizeOfCommittedPages(); 480 return m_heap->heapStats().allocatedObjectSize() + m_heap->heapStats().marke dObjectSize() + WTF::Partitions::totalSizeOfCommittedPages();
521 } 481 }
522 482
523 size_t ThreadState::estimatedLiveSize(size_t estimationBaseSize, size_t sizeAtLa stGC) 483 size_t ThreadState::estimatedLiveSize(size_t estimationBaseSize, size_t sizeAtLa stGC)
524 { 484 {
525 if (Heap::wrapperCountAtLastGC() == 0) { 485 if (m_heap->heapStats().wrapperCountAtLastGC() == 0) {
526 // We'll reach here only before hitting the first GC. 486 // We'll reach here only before hitting the first GC.
527 return 0; 487 return 0;
528 } 488 }
529 489
530 // (estimated size) = (estimation base size) - (heap size at the last GC) / (# of persistent handles at the last GC) * (# of persistent handles collected si nce the last GC); 490 // (estimated size) = (estimation base size) - (heap size at the last GC) / (# of persistent handles at the last GC) * (# of persistent handles collected si nce the last GC);
531 size_t sizeRetainedByCollectedPersistents = static_cast<size_t>(1.0 * sizeAt LastGC / Heap::wrapperCountAtLastGC() * Heap::collectedWrapperCount()); 491 size_t sizeRetainedByCollectedPersistents = static_cast<size_t>(1.0 * sizeAt LastGC / m_heap->heapStats().wrapperCountAtLastGC() * m_heap->heapStats().collec tedWrapperCount());
532 if (estimationBaseSize < sizeRetainedByCollectedPersistents) 492 if (estimationBaseSize < sizeRetainedByCollectedPersistents)
533 return 0; 493 return 0;
534 return estimationBaseSize - sizeRetainedByCollectedPersistents; 494 return estimationBaseSize - sizeRetainedByCollectedPersistents;
535 } 495 }
536 496
537 double ThreadState::heapGrowingRate() 497 double ThreadState::heapGrowingRate()
538 { 498 {
539 size_t currentSize = Heap::allocatedObjectSize() + Heap::markedObjectSize(); 499 size_t currentSize = m_heap->heapStats().allocatedObjectSize() + m_heap->hea pStats().markedObjectSize();
540 size_t estimatedSize = estimatedLiveSize(Heap::markedObjectSizeAtLastComplet eSweep(), Heap::markedObjectSizeAtLastCompleteSweep()); 500 size_t estimatedSize = estimatedLiveSize(m_heap->heapStats().markedObjectSiz eAtLastCompleteSweep(), m_heap->heapStats().markedObjectSizeAtLastCompleteSweep( ));
541 501
542 // If the estimatedSize is 0, we set a high growing rate to trigger a GC. 502 // If the estimatedSize is 0, we set a high growing rate to trigger a GC.
543 double growingRate = estimatedSize > 0 ? 1.0 * currentSize / estimatedSize : 100; 503 double growingRate = estimatedSize > 0 ? 1.0 * currentSize / estimatedSize : 100;
544 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::heapEsti matedSizeKB", std::min(estimatedSize / 1024, static_cast<size_t>(INT_MAX))); 504 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::heapEsti matedSizeKB", std::min(estimatedSize / 1024, static_cast<size_t>(INT_MAX)));
545 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::heapGrow ingRate", static_cast<int>(100 * growingRate)); 505 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::heapGrow ingRate", static_cast<int>(100 * growingRate));
546 return growingRate; 506 return growingRate;
547 } 507 }
548 508
549 double ThreadState::partitionAllocGrowingRate() 509 double ThreadState::partitionAllocGrowingRate()
550 { 510 {
551 size_t currentSize = WTF::Partitions::totalSizeOfCommittedPages(); 511 size_t currentSize = WTF::Partitions::totalSizeOfCommittedPages();
552 size_t estimatedSize = estimatedLiveSize(currentSize, Heap::partitionAllocSi zeAtLastGC()); 512 size_t estimatedSize = estimatedLiveSize(currentSize, m_heap->heapStats().pa rtitionAllocSizeAtLastGC());
553 513
554 // If the estimatedSize is 0, we set a high growing rate to trigger a GC. 514 // If the estimatedSize is 0, we set a high growing rate to trigger a GC.
555 double growingRate = estimatedSize > 0 ? 1.0 * currentSize / estimatedSize : 100; 515 double growingRate = estimatedSize > 0 ? 1.0 * currentSize / estimatedSize : 100;
556 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::partitio nAllocEstimatedSizeKB", std::min(estimatedSize / 1024, static_cast<size_t>(INT_M AX))); 516 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::partitio nAllocEstimatedSizeKB", std::min(estimatedSize / 1024, static_cast<size_t>(INT_M AX)));
557 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::partitio nAllocGrowingRate", static_cast<int>(100 * growingRate)); 517 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::partitio nAllocGrowingRate", static_cast<int>(100 * growingRate));
558 return growingRate; 518 return growingRate;
559 } 519 }
560 520
561 // TODO(haraken): We should improve the GC heuristics. The heuristics affect 521 // TODO(haraken): We should improve the GC heuristics. The heuristics affect
562 // performance significantly. 522 // performance significantly.
563 bool ThreadState::judgeGCThreshold(size_t totalMemorySizeThreshold, double heapG rowingRateThreshold) 523 bool ThreadState::judgeGCThreshold(size_t totalMemorySizeThreshold, double heapG rowingRateThreshold)
564 { 524 {
565 // If the allocated object size or the total memory size is small, don't tri gger a GC. 525 // If the allocated object size or the total memory size is small, don't tri gger a GC.
566 if (Heap::allocatedObjectSize() < 100 * 1024 || totalMemorySize() < totalMem orySizeThreshold) 526 if (m_heap->heapStats().allocatedObjectSize() < 100 * 1024 || totalMemorySiz e() < totalMemorySizeThreshold)
567 return false; 527 return false;
568 // If the growing rate of Oilpan's heap or PartitionAlloc is high enough, 528 // If the growing rate of Oilpan's heap or PartitionAlloc is high enough,
569 // trigger a GC. 529 // trigger a GC.
570 #if PRINT_HEAP_STATS 530 #if PRINT_HEAP_STATS
571 dataLogF("heapGrowingRate=%.1lf, partitionAllocGrowingRate=%.1lf\n", heapGro wingRate(), partitionAllocGrowingRate()); 531 dataLogF("heapGrowingRate=%.1lf, partitionAllocGrowingRate=%.1lf\n", heapGro wingRate(), partitionAllocGrowingRate());
572 #endif 532 #endif
573 return heapGrowingRate() >= heapGrowingRateThreshold || partitionAllocGrowin gRate() >= heapGrowingRateThreshold; 533 return heapGrowingRate() >= heapGrowingRateThreshold || partitionAllocGrowin gRate() >= heapGrowingRateThreshold;
574 } 534 }
575 535
576 bool ThreadState::shouldScheduleIdleGC() 536 bool ThreadState::shouldScheduleIdleGC()
(...skipping 27 matching lines...) Expand all
604 bool ThreadState::shouldForceMemoryPressureGC() 564 bool ThreadState::shouldForceMemoryPressureGC()
605 { 565 {
606 if (totalMemorySize() < 300 * 1024 * 1024) 566 if (totalMemorySize() < 300 * 1024 * 1024)
607 return false; 567 return false;
608 return judgeGCThreshold(0, 1.5); 568 return judgeGCThreshold(0, 1.5);
609 } 569 }
610 570
611 void ThreadState::scheduleV8FollowupGCIfNeeded(BlinkGC::V8GCType gcType) 571 void ThreadState::scheduleV8FollowupGCIfNeeded(BlinkGC::V8GCType gcType)
612 { 572 {
613 ASSERT(checkThread()); 573 ASSERT(checkThread());
614 Heap::reportMemoryUsageForTracing(); 574 ThreadHeap::reportMemoryUsageForTracing();
615 575
616 #if PRINT_HEAP_STATS 576 #if PRINT_HEAP_STATS
617 dataLogF("ThreadState::scheduleV8FollowupGCIfNeeded (gcType=%s)\n", gcType = = BlinkGC::V8MajorGC ? "MajorGC" : "MinorGC"); 577 dataLogF("ThreadState::scheduleV8FollowupGCIfNeeded (gcType=%s)\n", gcType = = BlinkGC::V8MajorGC ? "MajorGC" : "MinorGC");
618 #endif 578 #endif
619 579
620 if (isGCForbidden()) 580 if (isGCForbidden())
621 return; 581 return;
622 582
623 // This completeSweep() will do nothing in common cases since we've 583 // This completeSweep() will do nothing in common cases since we've
624 // called completeSweep() before V8 starts minor/major GCs. 584 // called completeSweep() before V8 starts minor/major GCs.
(...skipping 27 matching lines...) Expand all
652 // completeSweep() here, because gcPrologue for a major GC is called 612 // completeSweep() here, because gcPrologue for a major GC is called
653 // not at the point where the major GC started but at the point where 613 // not at the point where the major GC started but at the point where
654 // the major GC requests object grouping. 614 // the major GC requests object grouping.
655 if (gcType == BlinkGC::V8MajorGC) 615 if (gcType == BlinkGC::V8MajorGC)
656 completeSweep(); 616 completeSweep();
657 } 617 }
658 618
659 void ThreadState::schedulePageNavigationGCIfNeeded(float estimatedRemovalRatio) 619 void ThreadState::schedulePageNavigationGCIfNeeded(float estimatedRemovalRatio)
660 { 620 {
661 ASSERT(checkThread()); 621 ASSERT(checkThread());
662 Heap::reportMemoryUsageForTracing(); 622 ThreadHeap::reportMemoryUsageForTracing();
663 623
664 #if PRINT_HEAP_STATS 624 #if PRINT_HEAP_STATS
665 dataLogF("ThreadState::schedulePageNavigationGCIfNeeded (estimatedRemovalRat io=%.2lf)\n", estimatedRemovalRatio); 625 dataLogF("ThreadState::schedulePageNavigationGCIfNeeded (estimatedRemovalRat io=%.2lf)\n", estimatedRemovalRatio);
666 #endif 626 #endif
667 627
668 if (isGCForbidden()) 628 if (isGCForbidden())
669 return; 629 return;
670 630
671 // Finish on-going lazy sweeping. 631 // Finish on-going lazy sweeping.
672 // TODO(haraken): It might not make sense to force completeSweep() for all 632 // TODO(haraken): It might not make sense to force completeSweep() for all
673 // page navigations. 633 // page navigations.
674 completeSweep(); 634 completeSweep();
675 ASSERT(!isSweepingInProgress()); 635 ASSERT(!isSweepingInProgress());
676 ASSERT(!sweepForbidden()); 636 ASSERT(!sweepForbidden());
677 637
678 if (shouldForceMemoryPressureGC()) { 638 if (shouldForceMemoryPressureGC()) {
679 #if PRINT_HEAP_STATS 639 #if PRINT_HEAP_STATS
680 dataLogF("Scheduled MemoryPressureGC\n"); 640 dataLogF("Scheduled MemoryPressureGC\n");
681 #endif 641 #endif
682 Heap::collectGarbage(BlinkGC::HeapPointersOnStack, BlinkGC::GCWithoutSwe ep, BlinkGC::MemoryPressureGC); 642 ThreadHeap::collectGarbage(BlinkGC::HeapPointersOnStack, BlinkGC::GCWith outSweep, BlinkGC::MemoryPressureGC);
683 return; 643 return;
684 } 644 }
685 if (shouldSchedulePageNavigationGC(estimatedRemovalRatio)) { 645 if (shouldSchedulePageNavigationGC(estimatedRemovalRatio)) {
686 #if PRINT_HEAP_STATS 646 #if PRINT_HEAP_STATS
687 dataLogF("Scheduled PageNavigationGC\n"); 647 dataLogF("Scheduled PageNavigationGC\n");
688 #endif 648 #endif
689 schedulePageNavigationGC(); 649 schedulePageNavigationGC();
690 } 650 }
691 } 651 }
692 652
693 void ThreadState::schedulePageNavigationGC() 653 void ThreadState::schedulePageNavigationGC()
694 { 654 {
695 ASSERT(checkThread()); 655 ASSERT(checkThread());
696 ASSERT(!isSweepingInProgress()); 656 ASSERT(!isSweepingInProgress());
697 setGCState(PageNavigationGCScheduled); 657 setGCState(PageNavigationGCScheduled);
698 } 658 }
699 659
700 void ThreadState::scheduleGCIfNeeded() 660 void ThreadState::scheduleGCIfNeeded()
701 { 661 {
702 ASSERT(checkThread()); 662 ASSERT(checkThread());
703 Heap::reportMemoryUsageForTracing(); 663 ThreadHeap::reportMemoryUsageForTracing();
704 664
705 #if PRINT_HEAP_STATS 665 #if PRINT_HEAP_STATS
706 dataLogF("ThreadState::scheduleGCIfNeeded\n"); 666 dataLogF("ThreadState::scheduleGCIfNeeded\n");
707 #endif 667 #endif
708 668
709 // Allocation is allowed during sweeping, but those allocations should not 669 // Allocation is allowed during sweeping, but those allocations should not
710 // trigger nested GCs. 670 // trigger nested GCs.
711 if (isGCForbidden()) 671 if (isGCForbidden())
712 return; 672 return;
713 673
714 if (isSweepingInProgress()) 674 if (isSweepingInProgress())
715 return; 675 return;
716 ASSERT(!sweepForbidden()); 676 ASSERT(!sweepForbidden());
717 677
718 reportMemoryToV8(); 678 reportMemoryToV8();
719 679
720 if (shouldForceMemoryPressureGC()) { 680 if (shouldForceMemoryPressureGC()) {
721 completeSweep(); 681 completeSweep();
722 if (shouldForceMemoryPressureGC()) { 682 if (shouldForceMemoryPressureGC()) {
723 #if PRINT_HEAP_STATS 683 #if PRINT_HEAP_STATS
724 dataLogF("Scheduled MemoryPressureGC\n"); 684 dataLogF("Scheduled MemoryPressureGC\n");
725 #endif 685 #endif
726 Heap::collectGarbage(BlinkGC::HeapPointersOnStack, BlinkGC::GCWithou tSweep, BlinkGC::MemoryPressureGC); 686 ThreadHeap::collectGarbage(BlinkGC::HeapPointersOnStack, BlinkGC::GC WithoutSweep, BlinkGC::MemoryPressureGC);
727 return; 687 return;
728 } 688 }
729 } 689 }
730 690
731 if (shouldForceConservativeGC()) { 691 if (shouldForceConservativeGC()) {
732 completeSweep(); 692 completeSweep();
733 if (shouldForceConservativeGC()) { 693 if (shouldForceConservativeGC()) {
734 #if PRINT_HEAP_STATS 694 #if PRINT_HEAP_STATS
735 dataLogF("Scheduled ConservativeGC\n"); 695 dataLogF("Scheduled ConservativeGC\n");
736 #endif 696 #endif
737 Heap::collectGarbage(BlinkGC::HeapPointersOnStack, BlinkGC::GCWithou tSweep, BlinkGC::ConservativeGC); 697 ThreadHeap::collectGarbage(BlinkGC::HeapPointersOnStack, BlinkGC::GC WithoutSweep, BlinkGC::ConservativeGC);
738 return; 698 return;
739 } 699 }
740 } 700 }
741 if (shouldScheduleIdleGC()) { 701 if (shouldScheduleIdleGC()) {
742 #if PRINT_HEAP_STATS 702 #if PRINT_HEAP_STATS
743 dataLogF("Scheduled IdleGC\n"); 703 dataLogF("Scheduled IdleGC\n");
744 #endif 704 #endif
745 scheduleIdleGC(); 705 scheduleIdleGC();
746 return; 706 return;
747 } 707 }
748 } 708 }
749 709
710 ThreadState* ThreadState::fromObject(const void* object)
711 {
712 if (!object)
713 return nullptr;
714 BasePage* page = pageFromObject(object);
715 ASSERT(page);
716 ASSERT(page->arena());
717 return page->arena()->getThreadState();
718 }
719
750 void ThreadState::performIdleGC(double deadlineSeconds) 720 void ThreadState::performIdleGC(double deadlineSeconds)
751 { 721 {
752 ASSERT(checkThread()); 722 ASSERT(checkThread());
753 ASSERT(isMainThread()); 723 ASSERT(isMainThread());
754 ASSERT(Platform::current()->currentThread()->scheduler()); 724 ASSERT(Platform::current()->currentThread()->scheduler());
755 725
756 if (gcState() != IdleGCScheduled) 726 if (gcState() != IdleGCScheduled)
757 return; 727 return;
758 728
759 double idleDeltaInSeconds = deadlineSeconds - monotonicallyIncreasingTime(); 729 double idleDeltaInSeconds = deadlineSeconds - monotonicallyIncreasingTime();
760 TRACE_EVENT2("blink_gc", "ThreadState::performIdleGC", "idleDeltaInSeconds", idleDeltaInSeconds, "estimatedMarkingTime", Heap::estimatedMarkingTime()); 730 TRACE_EVENT2("blink_gc", "ThreadState::performIdleGC", "idleDeltaInSeconds", idleDeltaInSeconds, "estimatedMarkingTime", m_heap->heapStats().estimatedMarkin gTime());
761 if (idleDeltaInSeconds <= Heap::estimatedMarkingTime() && !Platform::current ()->currentThread()->scheduler()->canExceedIdleDeadlineIfRequired()) { 731 if (idleDeltaInSeconds <= m_heap->heapStats().estimatedMarkingTime() && !Pla tform::current()->currentThread()->scheduler()->canExceedIdleDeadlineIfRequired( )) {
762 // If marking is estimated to take longer than the deadline and we can't 732 // If marking is estimated to take longer than the deadline and we can't
763 // exceed the deadline, then reschedule for the next idle period. 733 // exceed the deadline, then reschedule for the next idle period.
764 scheduleIdleGC(); 734 scheduleIdleGC();
765 return; 735 return;
766 } 736 }
767 737
768 Heap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithoutSweep , BlinkGC::IdleGC); 738 ThreadHeap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithou tSweep, BlinkGC::IdleGC);
769 } 739 }
770 740
771 void ThreadState::performIdleLazySweep(double deadlineSeconds) 741 void ThreadState::performIdleLazySweep(double deadlineSeconds)
772 { 742 {
773 ASSERT(checkThread()); 743 ASSERT(checkThread());
774 ASSERT(isMainThread()); 744 ASSERT(isMainThread());
775 745
776 // If we are not in a sweeping phase, there is nothing to do here. 746 // If we are not in a sweeping phase, there is nothing to do here.
777 if (!isSweepingInProgress()) 747 if (!isSweepingInProgress())
778 return; 748 return;
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
934 // If a safe point is entered while initiating a GC, we clearly do 904 // If a safe point is entered while initiating a GC, we clearly do
935 // not want to do another as part that -- the safe point is only 905 // not want to do another as part that -- the safe point is only
936 // entered after checking if a scheduled GC ought to run first. 906 // entered after checking if a scheduled GC ought to run first.
937 // Prevent that from happening by marking GCs as forbidden while 907 // Prevent that from happening by marking GCs as forbidden while
938 // one is initiated and later running. 908 // one is initiated and later running.
939 if (isGCForbidden()) 909 if (isGCForbidden())
940 return; 910 return;
941 911
942 switch (gcState()) { 912 switch (gcState()) {
943 case FullGCScheduled: 913 case FullGCScheduled:
944 Heap::collectAllGarbage(); 914 ThreadHeap::collectAllGarbage();
945 break; 915 break;
946 case PreciseGCScheduled: 916 case PreciseGCScheduled:
947 Heap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithoutS weep, BlinkGC::PreciseGC); 917 ThreadHeap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWi thoutSweep, BlinkGC::PreciseGC);
948 break; 918 break;
949 case PageNavigationGCScheduled: 919 case PageNavigationGCScheduled:
950 Heap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSwee p, BlinkGC::PageNavigationGC); 920 ThreadHeap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWi thSweep, BlinkGC::PageNavigationGC);
951 break; 921 break;
952 case IdleGCScheduled: 922 case IdleGCScheduled:
953 // Idle time GC will be scheduled by Blink Scheduler. 923 // Idle time GC will be scheduled by Blink Scheduler.
954 break; 924 break;
955 default: 925 default:
956 break; 926 break;
957 } 927 }
958 } 928 }
959 929
960 void ThreadState::flushHeapDoesNotContainCacheIfNeeded() 930 void ThreadState::flushHeapDoesNotContainCacheIfNeeded()
961 { 931 {
962 if (m_shouldFlushHeapDoesNotContainCache) { 932 if (m_shouldFlushHeapDoesNotContainCache) {
963 Heap::flushHeapDoesNotContainCache(); 933 m_heap->flushHeapDoesNotContainCache();
964 m_shouldFlushHeapDoesNotContainCache = false; 934 m_shouldFlushHeapDoesNotContainCache = false;
965 } 935 }
966 } 936 }
967 937
968 void ThreadState::makeConsistentForGC() 938 void ThreadState::makeConsistentForGC()
969 { 939 {
970 ASSERT(isInGC()); 940 ASSERT(isInGC());
971 TRACE_EVENT0("blink_gc", "ThreadState::makeConsistentForGC"); 941 TRACE_EVENT0("blink_gc", "ThreadState::makeConsistentForGC");
972 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) 942 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i)
973 m_arenas[i]->makeConsistentForGC(); 943 m_arenas[i]->makeConsistentForGC();
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
1103 if (sweepForbidden()) 1073 if (sweepForbidden())
1104 return; 1074 return;
1105 1075
1106 SweepForbiddenScope scope(this); 1076 SweepForbiddenScope scope(this);
1107 { 1077 {
1108 ScriptForbiddenIfMainThreadScope scriptForbiddenScope; 1078 ScriptForbiddenIfMainThreadScope scriptForbiddenScope;
1109 1079
1110 TRACE_EVENT0("blink_gc,devtools.timeline", "ThreadState::completeSweep") ; 1080 TRACE_EVENT0("blink_gc,devtools.timeline", "ThreadState::completeSweep") ;
1111 double startTime = WTF::currentTimeMS(); 1081 double startTime = WTF::currentTimeMS();
1112 1082
1113 static_assert(BlinkGC::EagerSweepArenaIndex == 0, "Eagerly swept arenas must be processed first."); 1083 static_assert(BlinkGC::EagerSweepArenaIndex == 0, "Eagerly swept heaps m ust be processed first.");
1114 for (int i = 0; i < BlinkGC::NumberOfArenas; i++) 1084 for (int i = 0; i < BlinkGC::NumberOfArenas; i++)
1115 m_arenas[i]->completeSweep(); 1085 m_arenas[i]->completeSweep();
1116 1086
1117 double timeForCompleteSweep = WTF::currentTimeMS() - startTime; 1087 double timeForCompleteSweep = WTF::currentTimeMS() - startTime;
1118 accumulateSweepingTime(timeForCompleteSweep); 1088 accumulateSweepingTime(timeForCompleteSweep);
1119 1089
1120 if (isMainThread()) { 1090 if (isMainThread()) {
1121 DEFINE_STATIC_LOCAL(CustomCountHistogram, completeSweepHistogram, (" BlinkGC.CompleteSweep", 1, 10 * 1000, 50)); 1091 DEFINE_STATIC_LOCAL(CustomCountHistogram, completeSweepHistogram, (" BlinkGC.CompleteSweep", 1, 10 * 1000, 50));
1122 completeSweepHistogram.count(timeForCompleteSweep); 1092 completeSweepHistogram.count(timeForCompleteSweep);
1123 } 1093 }
1124 } 1094 }
1125 1095
1126 postSweep(); 1096 postSweep();
1127 } 1097 }
1128 1098
1129 void ThreadState::postSweep() 1099 void ThreadState::postSweep()
1130 { 1100 {
1131 ASSERT(checkThread()); 1101 ASSERT(checkThread());
1132 Heap::reportMemoryUsageForTracing(); 1102 ThreadHeap::reportMemoryUsageForTracing();
1133 1103
1134 if (isMainThread()) { 1104 if (isMainThread()) {
1135 double collectionRate = 0; 1105 double collectionRate = 0;
1136 if (Heap::objectSizeAtLastGC() > 0) 1106 if (m_heap->heapStats().objectSizeAtLastGC() > 0)
1137 collectionRate = 1 - 1.0 * Heap::markedObjectSize() / Heap::objectSi zeAtLastGC(); 1107 collectionRate = 1 - 1.0 * m_heap->heapStats().markedObjectSize() / m_heap->heapStats().objectSizeAtLastGC();
1138 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::coll ectionRate", static_cast<int>(100 * collectionRate)); 1108 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::coll ectionRate", static_cast<int>(100 * collectionRate));
1139 1109
1140 #if PRINT_HEAP_STATS 1110 #if PRINT_HEAP_STATS
1141 dataLogF("ThreadState::postSweep (collectionRate=%d%%)\n", static_cast<i nt>(100 * collectionRate)); 1111 dataLogF("ThreadState::postSweep (collectionRate=%d%%)\n", static_cast<i nt>(100 * collectionRate));
1142 #endif 1112 #endif
1143 1113
1144 // Heap::markedObjectSize() may be underestimated here if any other 1114 // ThreadHeap::markedObjectSize() may be underestimated here if any othe r
1145 // thread has not yet finished lazy sweeping. 1115 // thread has not yet finished lazy sweeping.
1146 Heap::setMarkedObjectSizeAtLastCompleteSweep(Heap::markedObjectSize()); 1116 m_heap->heapStats().setMarkedObjectSizeAtLastCompleteSweep(m_heap->heapS tats().markedObjectSize());
1147 1117
1148 DEFINE_STATIC_LOCAL(CustomCountHistogram, objectSizeBeforeGCHistogram, ( "BlinkGC.ObjectSizeBeforeGC", 1, 4 * 1024 * 1024, 50)); 1118 DEFINE_STATIC_LOCAL(CustomCountHistogram, objectSizeBeforeGCHistogram, ( "BlinkGC.ObjectSizeBeforeGC", 1, 4 * 1024 * 1024, 50));
1149 objectSizeBeforeGCHistogram.count(Heap::objectSizeAtLastGC() / 1024); 1119 objectSizeBeforeGCHistogram.count(m_heap->heapStats().objectSizeAtLastGC () / 1024);
1150 DEFINE_STATIC_LOCAL(CustomCountHistogram, objectSizeAfterGCHistogram, (" BlinkGC.ObjectSizeAfterGC", 1, 4 * 1024 * 1024, 50)); 1120 DEFINE_STATIC_LOCAL(CustomCountHistogram, objectSizeAfterGCHistogram, (" BlinkGC.ObjectSizeAfterGC", 1, 4 * 1024 * 1024, 50));
1151 objectSizeAfterGCHistogram.count(Heap::markedObjectSize() / 1024); 1121 objectSizeAfterGCHistogram.count(m_heap->heapStats().markedObjectSize() / 1024);
1152 DEFINE_STATIC_LOCAL(CustomCountHistogram, collectionRateHistogram, ("Bli nkGC.CollectionRate", 1, 100, 20)); 1122 DEFINE_STATIC_LOCAL(CustomCountHistogram, collectionRateHistogram, ("Bli nkGC.CollectionRate", 1, 100, 20));
1153 collectionRateHistogram.count(static_cast<int>(100 * collectionRate)); 1123 collectionRateHistogram.count(static_cast<int>(100 * collectionRate));
1154 DEFINE_STATIC_LOCAL(CustomCountHistogram, timeForSweepHistogram, ("Blink GC.TimeForSweepingAllObjects", 1, 10 * 1000, 50)); 1124 DEFINE_STATIC_LOCAL(CustomCountHistogram, timeForSweepHistogram, ("Blink GC.TimeForSweepingAllObjects", 1, 10 * 1000, 50));
1155 timeForSweepHistogram.count(m_accumulatedSweepingTime); 1125 timeForSweepHistogram.count(m_accumulatedSweepingTime);
1156 1126
1157 1127
1158 #define COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(GCReason) \ 1128 #define COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(GCReason) \
1159 case BlinkGC::GCReason: { \ 1129 case BlinkGC::GCReason: { \
1160 DEFINE_STATIC_LOCAL(CustomCountHistogram, histogram, \ 1130 DEFINE_STATIC_LOCAL(CustomCountHistogram, histogram, \
1161 ("BlinkGC.CollectionRate_" #GCReason, 1, 100, 20)); \ 1131 ("BlinkGC.CollectionRate_" #GCReason, 1, 100, 20)); \
1162 histogram.count(static_cast<int>(100 * collectionRate)); \ 1132 histogram.count(static_cast<int>(100 * collectionRate)); \
1163 break; \ 1133 break; \
1164 } 1134 }
1165 1135
1166 switch (Heap::lastGCReason()) { 1136 switch (m_heap->lastGCReason()) {
1167 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(IdleGC) 1137 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(IdleGC)
1168 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(PreciseGC) 1138 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(PreciseGC)
1169 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(ConservativeGC) 1139 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(ConservativeGC)
1170 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(ForcedGC) 1140 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(ForcedGC)
1171 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(MemoryPressureGC) 1141 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(MemoryPressureGC)
1172 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(PageNavigationGC) 1142 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(PageNavigationGC)
1173 default: 1143 default:
1174 break; 1144 break;
1175 } 1145 }
1176 } 1146 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1210 #endif 1180 #endif
1211 1181
1212 size_t ThreadState::objectPayloadSizeForTesting() 1182 size_t ThreadState::objectPayloadSizeForTesting()
1213 { 1183 {
1214 size_t objectPayloadSize = 0; 1184 size_t objectPayloadSize = 0;
1215 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) 1185 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i)
1216 objectPayloadSize += m_arenas[i]->objectPayloadSizeForTesting(); 1186 objectPayloadSize += m_arenas[i]->objectPayloadSizeForTesting();
1217 return objectPayloadSize; 1187 return objectPayloadSize;
1218 } 1188 }
1219 1189
1220 bool ThreadState::stopThreads()
1221 {
1222 return s_safePointBarrier->parkOthers();
1223 }
1224
1225 void ThreadState::resumeThreads()
1226 {
1227 s_safePointBarrier->resumeOthers();
1228 }
1229
1230 void ThreadState::safePoint(BlinkGC::StackState stackState) 1190 void ThreadState::safePoint(BlinkGC::StackState stackState)
1231 { 1191 {
1232 ASSERT(checkThread()); 1192 ASSERT(checkThread());
1233 Heap::reportMemoryUsageForTracing(); 1193 ThreadHeap::reportMemoryUsageForTracing();
1234 1194
1235 runScheduledGC(stackState); 1195 runScheduledGC(stackState);
1236 ASSERT(!m_atSafePoint); 1196 ASSERT(!m_atSafePoint);
1237 m_stackState = stackState; 1197 m_stackState = stackState;
1238 m_atSafePoint = true; 1198 m_atSafePoint = true;
1239 s_safePointBarrier->checkAndPark(this); 1199 m_heap->checkAndPark(this, nullptr);
1240 m_atSafePoint = false; 1200 m_atSafePoint = false;
1241 m_stackState = BlinkGC::HeapPointersOnStack; 1201 m_stackState = BlinkGC::HeapPointersOnStack;
1242 preSweep(); 1202 preSweep();
1243 } 1203 }
1244 1204
1245 #ifdef ADDRESS_SANITIZER 1205 #ifdef ADDRESS_SANITIZER
1246 // When we are running under AddressSanitizer with detect_stack_use_after_return =1 1206 // When we are running under AddressSanitizer with detect_stack_use_after_return =1
1247 // then stack marker obtained from SafePointScope will point into a fake stack. 1207 // then stack marker obtained from SafePointScope will point into a fake stack.
1248 // Detect this case by checking if it falls in between current stack frame 1208 // Detect this case by checking if it falls in between current stack frame
1249 // and stack start and use an arbitrary high enough value for it. 1209 // and stack start and use an arbitrary high enough value for it.
(...skipping 23 matching lines...) Expand all
1273 #ifdef ADDRESS_SANITIZER 1233 #ifdef ADDRESS_SANITIZER
1274 if (stackState == BlinkGC::HeapPointersOnStack) 1234 if (stackState == BlinkGC::HeapPointersOnStack)
1275 scopeMarker = adjustScopeMarkerForAdressSanitizer(scopeMarker); 1235 scopeMarker = adjustScopeMarkerForAdressSanitizer(scopeMarker);
1276 #endif 1236 #endif
1277 ASSERT(stackState == BlinkGC::NoHeapPointersOnStack || scopeMarker); 1237 ASSERT(stackState == BlinkGC::NoHeapPointersOnStack || scopeMarker);
1278 runScheduledGC(stackState); 1238 runScheduledGC(stackState);
1279 ASSERT(!m_atSafePoint); 1239 ASSERT(!m_atSafePoint);
1280 m_atSafePoint = true; 1240 m_atSafePoint = true;
1281 m_stackState = stackState; 1241 m_stackState = stackState;
1282 m_safePointScopeMarker = scopeMarker; 1242 m_safePointScopeMarker = scopeMarker;
1283 s_safePointBarrier->enterSafePoint(this); 1243 m_heap->enterSafePoint(this);
1284 } 1244 }
1285 1245
1286 void ThreadState::leaveSafePoint(SafePointAwareMutexLocker* locker) 1246 void ThreadState::leaveSafePoint(SafePointAwareMutexLocker* locker)
1287 { 1247 {
1288 ASSERT(checkThread()); 1248 ASSERT(checkThread());
1289 ASSERT(m_atSafePoint); 1249 ASSERT(m_atSafePoint);
1290 s_safePointBarrier->leaveSafePoint(this, locker); 1250 m_heap->leaveSafePoint(this, locker);
1291 m_atSafePoint = false; 1251 m_atSafePoint = false;
1292 m_stackState = BlinkGC::HeapPointersOnStack; 1252 m_stackState = BlinkGC::HeapPointersOnStack;
1293 clearSafePointScopeMarker(); 1253 clearSafePointScopeMarker();
1294 preSweep(); 1254 preSweep();
1295 } 1255 }
1296 1256
1297 void ThreadState::reportMemoryToV8() 1257 void ThreadState::reportMemoryToV8()
1298 { 1258 {
1299 if (!m_isolate) 1259 if (!m_isolate)
1300 return; 1260 return;
1301 1261
1302 size_t currentHeapSize = m_allocatedObjectSize + m_markedObjectSize; 1262 size_t currentHeapSize = m_allocatedObjectSize + m_markedObjectSize;
1303 int64_t diff = static_cast<int64_t>(currentHeapSize) - static_cast<int64_t>( m_reportedMemoryToV8); 1263 int64_t diff = static_cast<int64_t>(currentHeapSize) - static_cast<int64_t>( m_reportedMemoryToV8);
1304 m_isolate->AdjustAmountOfExternalAllocatedMemory(diff); 1264 m_isolate->AdjustAmountOfExternalAllocatedMemory(diff);
1305 m_reportedMemoryToV8 = currentHeapSize; 1265 m_reportedMemoryToV8 = currentHeapSize;
1306 } 1266 }
1307 1267
1308 void ThreadState::resetHeapCounters() 1268 void ThreadState::resetHeapCounters()
1309 { 1269 {
1310 m_allocatedObjectSize = 0; 1270 m_allocatedObjectSize = 0;
1311 m_markedObjectSize = 0; 1271 m_markedObjectSize = 0;
1312 } 1272 }
1313 1273
1314 void ThreadState::increaseAllocatedObjectSize(size_t delta) 1274 void ThreadState::increaseAllocatedObjectSize(size_t delta)
1315 { 1275 {
1316 m_allocatedObjectSize += delta; 1276 m_allocatedObjectSize += delta;
1317 Heap::increaseAllocatedObjectSize(delta); 1277 m_heap->heapStats().increaseAllocatedObjectSize(delta);
1318 } 1278 }
1319 1279
1320 void ThreadState::decreaseAllocatedObjectSize(size_t delta) 1280 void ThreadState::decreaseAllocatedObjectSize(size_t delta)
1321 { 1281 {
1322 m_allocatedObjectSize -= delta; 1282 m_allocatedObjectSize -= delta;
1323 Heap::decreaseAllocatedObjectSize(delta); 1283 m_heap->heapStats().decreaseAllocatedObjectSize(delta);
1324 } 1284 }
1325 1285
1326 void ThreadState::increaseMarkedObjectSize(size_t delta) 1286 void ThreadState::increaseMarkedObjectSize(size_t delta)
1327 { 1287 {
1328 m_markedObjectSize += delta; 1288 m_markedObjectSize += delta;
1329 Heap::increaseMarkedObjectSize(delta); 1289 m_heap->heapStats().increaseMarkedObjectSize(delta);
1330 } 1290 }
1331 1291
1332 void ThreadState::copyStackUntilSafePointScope() 1292 void ThreadState::copyStackUntilSafePointScope()
1333 { 1293 {
1334 if (!m_safePointScopeMarker || m_stackState == BlinkGC::NoHeapPointersOnStac k) 1294 if (!m_safePointScopeMarker || m_stackState == BlinkGC::NoHeapPointersOnStac k)
1335 return; 1295 return;
1336 1296
1337 Address* to = reinterpret_cast<Address*>(m_safePointScopeMarker); 1297 Address* to = reinterpret_cast<Address*>(m_safePointScopeMarker);
1338 Address* from = reinterpret_cast<Address*>(m_endOfStack); 1298 Address* from = reinterpret_cast<Address*>(m_endOfStack);
1339 RELEASE_ASSERT(from < to); 1299 RELEASE_ASSERT(from < to);
(...skipping 13 matching lines...) Expand all
1353 for (size_t i = 0; i < slotCount; ++i) { 1313 for (size_t i = 0; i < slotCount; ++i) {
1354 m_safePointStackCopy[i] = from[i]; 1314 m_safePointStackCopy[i] = from[i];
1355 } 1315 }
1356 } 1316 }
1357 1317
1358 void ThreadState::addInterruptor(PassOwnPtr<BlinkGCInterruptor> interruptor) 1318 void ThreadState::addInterruptor(PassOwnPtr<BlinkGCInterruptor> interruptor)
1359 { 1319 {
1360 ASSERT(checkThread()); 1320 ASSERT(checkThread());
1361 SafePointScope scope(BlinkGC::HeapPointersOnStack); 1321 SafePointScope scope(BlinkGC::HeapPointersOnStack);
1362 { 1322 {
1363 MutexLocker locker(threadAttachMutex()); 1323 MutexLocker locker(m_heap->threadAttachMutex());
1364 m_interruptors.append(interruptor); 1324 m_interruptors.append(interruptor);
1365 } 1325 }
1366 } 1326 }
1367 1327
1368 #if defined(LEAK_SANITIZER) 1328 #if defined(LEAK_SANITIZER)
1369 void ThreadState::registerStaticPersistentNode(PersistentNode* node) 1329 void ThreadState::registerStaticPersistentNode(PersistentNode* node)
1370 { 1330 {
1371 if (m_disabledStaticPersistentsRegistration) 1331 if (m_disabledStaticPersistentsRegistration)
1372 return; 1332 return;
1373 1333
(...skipping 14 matching lines...) Expand all
1388 m_disabledStaticPersistentsRegistration++; 1348 m_disabledStaticPersistentsRegistration++;
1389 } 1349 }
1390 1350
1391 void ThreadState::leaveStaticReferenceRegistrationDisabledScope() 1351 void ThreadState::leaveStaticReferenceRegistrationDisabledScope()
1392 { 1352 {
1393 ASSERT(m_disabledStaticPersistentsRegistration); 1353 ASSERT(m_disabledStaticPersistentsRegistration);
1394 m_disabledStaticPersistentsRegistration--; 1354 m_disabledStaticPersistentsRegistration--;
1395 } 1355 }
1396 #endif 1356 #endif
1397 1357
1398 ThreadState::AttachedThreadStateSet& ThreadState::attachedThreads()
1399 {
1400 DEFINE_STATIC_LOCAL(AttachedThreadStateSet, threads, ());
1401 return threads;
1402 }
1403
1404 void ThreadState::lockThreadAttachMutex() 1358 void ThreadState::lockThreadAttachMutex()
1405 { 1359 {
1406 threadAttachMutex().lock(); 1360 m_heap->threadAttachMutex().lock();
1407 } 1361 }
1408 1362
1409 void ThreadState::unlockThreadAttachMutex() 1363 void ThreadState::unlockThreadAttachMutex()
1410 { 1364 {
1411 threadAttachMutex().unlock(); 1365 m_heap->threadAttachMutex().unlock();
1412 } 1366 }
1413 1367
1414 void ThreadState::invokePreFinalizers() 1368 void ThreadState::invokePreFinalizers()
1415 { 1369 {
1416 ASSERT(checkThread()); 1370 ASSERT(checkThread());
1417 ASSERT(!sweepForbidden()); 1371 ASSERT(!sweepForbidden());
1418 TRACE_EVENT0("blink_gc", "ThreadState::invokePreFinalizers"); 1372 TRACE_EVENT0("blink_gc", "ThreadState::invokePreFinalizers");
1419 1373
1420 double startTime = WTF::currentTimeMS(); 1374 double startTime = WTF::currentTimeMS();
1421 if (!m_orderedPreFinalizers.isEmpty()) { 1375 if (!m_orderedPreFinalizers.isEmpty()) {
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
1557 threadDump->addScalar("dead_count", "objects", totalDeadCount); 1511 threadDump->addScalar("dead_count", "objects", totalDeadCount);
1558 threadDump->addScalar("live_size", "bytes", totalLiveSize); 1512 threadDump->addScalar("live_size", "bytes", totalLiveSize);
1559 threadDump->addScalar("dead_size", "bytes", totalDeadSize); 1513 threadDump->addScalar("dead_size", "bytes", totalDeadSize);
1560 1514
1561 WebMemoryAllocatorDump* heapsDump = BlinkGCMemoryDumpProvider::instance()->c reateMemoryAllocatorDumpForCurrentGC(heapsDumpName); 1515 WebMemoryAllocatorDump* heapsDump = BlinkGCMemoryDumpProvider::instance()->c reateMemoryAllocatorDumpForCurrentGC(heapsDumpName);
1562 WebMemoryAllocatorDump* classesDump = BlinkGCMemoryDumpProvider::instance()- >createMemoryAllocatorDumpForCurrentGC(classesDumpName); 1516 WebMemoryAllocatorDump* classesDump = BlinkGCMemoryDumpProvider::instance()- >createMemoryAllocatorDumpForCurrentGC(classesDumpName);
1563 BlinkGCMemoryDumpProvider::instance()->currentProcessMemoryDump()->addOwners hipEdge(classesDump->guid(), heapsDump->guid()); 1517 BlinkGCMemoryDumpProvider::instance()->currentProcessMemoryDump()->addOwners hipEdge(classesDump->guid(), heapsDump->guid());
1564 } 1518 }
1565 1519
1566 } // namespace blink 1520 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/platform/heap/ThreadState.h ('k') | third_party/WebKit/Source/platform/heap/Visitor.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698