Chromium Code Reviews| 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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 11 matching lines...) Expand all Loading... | |
| 147 | 145 |
| 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*>(); |
|
haraken
2016/04/21 11:48:25
Can we move this to ThreadState::attachMainThread
keishi
2016/04/22 06:09:59
Done.
| |
| 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 Loading... | |
| 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(); |
|
haraken
2016/04/21 11:48:26
Nit: Add a space after 'new'.
keishi
2016/04/22 06:09:59
Done.
| |
| 208 attachedThreads().add(state); | |
| 209 } | 197 } |
| 210 | 198 |
| 199 void ThreadState::attach() | |
|
haraken
2016/04/21 11:48:25
attach => attachCurrentThread ? (for consistency w
keishi
2016/04/22 06:09:59
Done.
| |
| 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::cleanup() | |
|
haraken
2016/04/21 11:48:26
cleanup => runTerminationGC
keishi
2016/04/22 06:09:59
Done.
| |
| 213 { | |
| 214 if (isMainThread()) { | |
|
haraken
2016/04/21 11:48:25
This is okay at the moment, but you'll need to rep
| |
| 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 // Invoke the cleanup hooks. This gives an opportunity to release any | |
| 228 // persistent handles that may exist, e.g. in thread-specific static | |
| 229 // locals. | |
| 230 for (const OwnPtr<SameThreadClosure>& hook : m_threadShutdownHooks) | |
| 231 (*hook)(); | |
| 232 | |
| 233 // Set the terminate flag on all heap pages of this thread. This is used to | |
| 234 // ensure we don't trace pages on other threads that are not part of the | |
| 235 // thread local GC. | |
| 236 prepareForThreadStateTermination(); | |
| 237 | |
| 238 ProcessHeap::crossThreadPersistentRegion().prepareForThreadStateTermination( this); | |
| 239 | |
| 240 // Do thread local GC's as long as the count of thread local Persistents | |
| 241 // changes and is above zero. | |
| 242 int oldCount = -1; | |
| 243 int currentCount = getPersistentRegion()->numberOfPersistents(); | |
| 244 ASSERT(currentCount >= 0); | |
| 245 while (currentCount != oldCount) { | |
| 246 ThreadHeap::collectGarbageForTerminatingThread(this); | |
| 247 oldCount = currentCount; | |
| 248 currentCount = getPersistentRegion()->numberOfPersistents(); | |
| 249 } | |
| 250 // We should not have any persistents left when getting to this point, | |
| 251 // if we have it is probably a bug so adding a debug ASSERT to catch this. | |
| 252 ASSERT(!currentCount); | |
| 253 // All of pre-finalizers should be consumed. | |
| 254 ASSERT(m_orderedPreFinalizers.isEmpty()); | |
| 255 RELEASE_ASSERT(gcState() == NoGCScheduled); | |
| 256 | |
| 257 // Add pages to the orphaned page pool to ensure any global GCs from this po int | |
| 258 // on will not trace objects on this thread's arenas. | |
| 259 cleanupPages(); | |
| 260 } | |
| 211 | 261 |
| 212 void ThreadState::cleanupMainThread() | 262 void ThreadState::cleanupMainThread() |
| 213 { | 263 { |
| 214 ASSERT(isMainThread()); | 264 ASSERT(isMainThread()); |
| 215 | 265 |
| 216 #if defined(LEAK_SANITIZER) | 266 #if defined(LEAK_SANITIZER) |
| 217 // If LSan is about to perform leak detection, release all the registered | 267 // If LSan is about to perform leak detection, release all the registered |
| 218 // static Persistent<> root references to global caches that Blink keeps, | 268 // static Persistent<> root references to global caches that Blink keeps, |
| 219 // followed by GCs to clear out all they referred to. | 269 // followed by GCs to clear out all they referred to. |
| 220 // | 270 // |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 235 enterGCForbiddenScope(); | 285 enterGCForbiddenScope(); |
| 236 } | 286 } |
| 237 | 287 |
| 238 void ThreadState::detachMainThread() | 288 void ThreadState::detachMainThread() |
| 239 { | 289 { |
| 240 // Enter a safe point before trying to acquire threadAttachMutex | 290 // Enter a safe point before trying to acquire threadAttachMutex |
| 241 // to avoid dead lock if another thread is preparing for GC, has acquired | 291 // 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 | 292 // threadAttachMutex and waiting for other threads to pause or reach a |
| 243 // safepoint. | 293 // safepoint. |
| 244 ThreadState* state = mainThreadState(); | 294 ThreadState* state = mainThreadState(); |
| 245 ASSERT(state == ThreadState::current()); | |
| 246 ASSERT(state->checkThread()); | |
| 247 ASSERT(!state->isSweepingInProgress()); | 295 ASSERT(!state->isSweepingInProgress()); |
| 248 | 296 |
| 249 // The main thread must be the last thread that gets detached. | 297 state->heap().detach(state); |
| 250 RELEASE_ASSERT(ThreadState::attachedThreads().size() == 1); | |
|
haraken
2016/04/21 11:48:25
Can we keep this assert somewhere?
keishi
2016/04/22 06:09:59
I moved this assert to ThreadHeap::detach()
| |
| 251 | |
| 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(); | 298 state->~ThreadState(); |
| 260 } | 299 } |
| 261 | 300 |
| 262 void ThreadState::attach() | 301 void ThreadState::detachCurrentThread() |
| 263 { | |
| 264 MutexLocker locker(threadAttachMutex()); | |
| 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 // Invoke the cleanup hooks. This gives an opportunity to release any | |
| 296 // persistent handles that may exist, e.g. in thread-specific static | |
| 297 // locals. | |
| 298 for (const OwnPtr<SameThreadClosure>& hook : m_threadShutdownHooks) | |
| 299 (*hook)(); | |
| 300 | |
| 301 // Set the terminate flag on all heap pages of this thread. This is used to | |
| 302 // ensure we don't trace pages on other threads that are not part of the | |
| 303 // thread local GC. | |
| 304 prepareForThreadStateTermination(); | |
| 305 | |
| 306 ProcessHeap::crossThreadPersistentRegion().prepareForThreadStateTerminat ion(this); | |
| 307 | |
| 308 // Do thread local GC's as long as the count of thread local Persistents | |
| 309 // changes and is above zero. | |
| 310 int oldCount = -1; | |
| 311 int currentCount = getPersistentRegion()->numberOfPersistents(); | |
| 312 ASSERT(currentCount >= 0); | |
| 313 while (currentCount != oldCount) { | |
| 314 ThreadHeap::collectGarbageForTerminatingThread(this); | |
| 315 oldCount = currentCount; | |
| 316 currentCount = getPersistentRegion()->numberOfPersistents(); | |
| 317 } | |
| 318 // We should not have any persistents left when getting to this point, | |
| 319 // if we have it is probably a bug so adding a debug ASSERT to catch thi s. | |
| 320 ASSERT(!currentCount); | |
| 321 // All of pre-finalizers should be consumed. | |
| 322 ASSERT(m_orderedPreFinalizers.isEmpty()); | |
| 323 RELEASE_ASSERT(gcState() == NoGCScheduled); | |
| 324 | |
| 325 // Add pages to the orphaned page pool to ensure any global GCs from thi s point | |
| 326 // on will not trace objects on this thread's arenas. | |
| 327 cleanupPages(); | |
| 328 | |
| 329 ASSERT(attachedThreads().contains(this)); | |
| 330 attachedThreads().remove(this); | |
| 331 } | |
| 332 } | |
| 333 | |
| 334 void ThreadState::detach() | |
| 335 { | 302 { |
| 336 ThreadState* state = current(); | 303 ThreadState* state = current(); |
| 337 state->cleanup(); | 304 state->heap().detach(state); |
| 338 RELEASE_ASSERT(state->gcState() == ThreadState::NoGCScheduled); | |
|
haraken
2016/04/21 11:48:25
Can we keep this assert somewhere?
keishi
2016/04/22 06:09:59
Done. Added back to ThreadState::detachCurrentThre
| |
| 339 delete state; | 305 delete state; |
| 340 } | 306 } |
| 341 | 307 |
| 342 void ThreadState::visitPersistentRoots(Visitor* visitor) | |
| 343 { | |
| 344 TRACE_EVENT0("blink_gc", "ThreadState::visitPersistentRoots"); | |
| 345 ProcessHeap::crossThreadPersistentRegion().tracePersistentNodes(visitor); | |
| 346 | |
| 347 for (ThreadState* state : attachedThreads()) | |
| 348 state->visitPersistents(visitor); | |
| 349 } | |
| 350 | |
| 351 void ThreadState::visitStackRoots(Visitor* visitor) | |
| 352 { | |
| 353 TRACE_EVENT0("blink_gc", "ThreadState::visitStackRoots"); | |
| 354 for (ThreadState* state : attachedThreads()) | |
| 355 state->visitStack(visitor); | |
| 356 } | |
| 357 | |
| 358 NO_SANITIZE_ADDRESS | 308 NO_SANITIZE_ADDRESS |
| 359 void ThreadState::visitAsanFakeStackForPointer(Visitor* visitor, Address ptr) | 309 void ThreadState::visitAsanFakeStackForPointer(Visitor* visitor, Address ptr) |
| 360 { | 310 { |
| 361 #if defined(ADDRESS_SANITIZER) | 311 #if defined(ADDRESS_SANITIZER) |
| 362 Address* start = reinterpret_cast<Address*>(m_startOfStack); | 312 Address* start = reinterpret_cast<Address*>(m_startOfStack); |
| 363 Address* end = reinterpret_cast<Address*>(m_endOfStack); | 313 Address* end = reinterpret_cast<Address*>(m_endOfStack); |
| 364 Address* fakeFrameStart = nullptr; | 314 Address* fakeFrameStart = nullptr; |
| 365 Address* fakeFrameEnd = nullptr; | 315 Address* fakeFrameEnd = nullptr; |
| 366 Address* maybeFakeFrame = reinterpret_cast<Address*>(ptr); | 316 Address* maybeFakeFrame = reinterpret_cast<Address*>(ptr); |
| 367 Address* realFrameForFakeFrame = | 317 Address* realFrameForFakeFrame = |
| 368 reinterpret_cast<Address*>( | 318 reinterpret_cast<Address*>( |
| 369 __asan_addr_is_in_fake_stack( | 319 __asan_addr_is_in_fake_stack( |
| 370 m_asanFakeStack, maybeFakeFrame, | 320 m_asanFakeStack, maybeFakeFrame, |
| 371 reinterpret_cast<void**>(&fakeFrameStart), | 321 reinterpret_cast<void**>(&fakeFrameStart), |
| 372 reinterpret_cast<void**>(&fakeFrameEnd))); | 322 reinterpret_cast<void**>(&fakeFrameEnd))); |
| 373 if (realFrameForFakeFrame) { | 323 if (realFrameForFakeFrame) { |
| 374 // This is a fake frame from the asan fake stack. | 324 // This is a fake frame from the asan fake stack. |
| 375 if (realFrameForFakeFrame > end && start > realFrameForFakeFrame) { | 325 if (realFrameForFakeFrame > end && start > realFrameForFakeFrame) { |
| 376 // The real stack address for the asan fake frame is | 326 // The real stack address for the asan fake frame is |
| 377 // within the stack range that we need to scan so we need | 327 // within the stack range that we need to scan so we need |
| 378 // to visit the values in the fake frame. | 328 // to visit the values in the fake frame. |
| 379 for (Address* p = fakeFrameStart; p < fakeFrameEnd; ++p) | 329 for (Address* p = fakeFrameStart; p < fakeFrameEnd; ++p) |
| 380 ThreadHeap::checkAndMarkPointer(visitor, *p); | 330 m_heap->checkAndMarkPointer(visitor, *p); |
| 381 } | 331 } |
| 382 } | 332 } |
| 383 #endif | 333 #endif |
| 384 } | 334 } |
| 385 | 335 |
| 386 NO_SANITIZE_ADDRESS | 336 NO_SANITIZE_ADDRESS |
| 387 void ThreadState::visitStack(Visitor* visitor) | 337 void ThreadState::visitStack(Visitor* visitor) |
| 388 { | 338 { |
| 389 if (m_stackState == BlinkGC::NoHeapPointersOnStack) | 339 if (m_stackState == BlinkGC::NoHeapPointersOnStack) |
| 390 return; | 340 return; |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 406 for (; current < start; ++current) { | 356 for (; current < start; ++current) { |
| 407 Address ptr = *current; | 357 Address ptr = *current; |
| 408 #if defined(MEMORY_SANITIZER) | 358 #if defined(MEMORY_SANITIZER) |
| 409 // |ptr| may be uninitialized by design. Mark it as initialized to keep | 359 // |ptr| may be uninitialized by design. Mark it as initialized to keep |
| 410 // MSan from complaining. | 360 // MSan from complaining. |
| 411 // Note: it may be tempting to get rid of |ptr| and simply use |current| | 361 // Note: it may be tempting to get rid of |ptr| and simply use |current| |
| 412 // here, but that would be incorrect. We intentionally use a local | 362 // here, but that would be incorrect. We intentionally use a local |
| 413 // variable because we don't want to unpoison the original stack. | 363 // variable because we don't want to unpoison the original stack. |
| 414 __msan_unpoison(&ptr, sizeof(ptr)); | 364 __msan_unpoison(&ptr, sizeof(ptr)); |
| 415 #endif | 365 #endif |
| 416 ThreadHeap::checkAndMarkPointer(visitor, ptr); | 366 m_heap->checkAndMarkPointer(visitor, ptr); |
| 417 visitAsanFakeStackForPointer(visitor, ptr); | 367 visitAsanFakeStackForPointer(visitor, ptr); |
| 418 } | 368 } |
| 419 | 369 |
| 420 for (Address ptr : m_safePointStackCopy) { | 370 for (Address ptr : m_safePointStackCopy) { |
| 421 #if defined(MEMORY_SANITIZER) | 371 #if defined(MEMORY_SANITIZER) |
| 422 // See the comment above. | 372 // See the comment above. |
| 423 __msan_unpoison(&ptr, sizeof(ptr)); | 373 __msan_unpoison(&ptr, sizeof(ptr)); |
| 424 #endif | 374 #endif |
| 425 ThreadHeap::checkAndMarkPointer(visitor, ptr); | 375 m_heap->checkAndMarkPointer(visitor, ptr); |
| 426 visitAsanFakeStackForPointer(visitor, ptr); | 376 visitAsanFakeStackForPointer(visitor, ptr); |
| 427 } | 377 } |
| 428 } | 378 } |
| 429 | 379 |
| 430 void ThreadState::visitPersistents(Visitor* visitor) | 380 void ThreadState::visitPersistents(Visitor* visitor) |
| 431 { | 381 { |
| 432 m_persistentRegion->tracePersistentNodes(visitor); | 382 m_persistentRegion->tracePersistentNodes(visitor); |
| 433 if (m_traceDOMWrappers) { | 383 if (m_traceDOMWrappers) { |
| 434 TRACE_EVENT0("blink_gc", "V8GCController::traceDOMWrappers"); | 384 TRACE_EVENT0("blink_gc", "V8GCController::traceDOMWrappers"); |
| 435 m_traceDOMWrappers(m_isolate, visitor); | 385 m_traceDOMWrappers(m_isolate, visitor); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 516 | 466 |
| 517 if (isMainThread()) { | 467 if (isMainThread()) { |
| 518 double timeForThreadLocalWeakProcessing = WTF::currentTimeMS() - startTi me; | 468 double timeForThreadLocalWeakProcessing = WTF::currentTimeMS() - startTi me; |
| 519 DEFINE_STATIC_LOCAL(CustomCountHistogram, timeForWeakHistogram, ("BlinkG C.TimeForThreadLocalWeakProcessing", 1, 10 * 1000, 50)); | 469 DEFINE_STATIC_LOCAL(CustomCountHistogram, timeForWeakHistogram, ("BlinkG C.TimeForThreadLocalWeakProcessing", 1, 10 * 1000, 50)); |
| 520 timeForWeakHistogram.count(timeForThreadLocalWeakProcessing); | 470 timeForWeakHistogram.count(timeForThreadLocalWeakProcessing); |
| 521 } | 471 } |
| 522 } | 472 } |
| 523 | 473 |
| 524 size_t ThreadState::totalMemorySize() | 474 size_t ThreadState::totalMemorySize() |
| 525 { | 475 { |
| 526 return ThreadHeap::heapStats().allocatedObjectSize() + ThreadHeap::heapStats ().markedObjectSize() + WTF::Partitions::totalSizeOfCommittedPages(); | 476 return m_heap->heapStats().allocatedObjectSize() + m_heap->heapStats().marke dObjectSize() + WTF::Partitions::totalSizeOfCommittedPages(); |
| 527 } | 477 } |
| 528 | 478 |
| 529 size_t ThreadState::estimatedLiveSize(size_t estimationBaseSize, size_t sizeAtLa stGC) | 479 size_t ThreadState::estimatedLiveSize(size_t estimationBaseSize, size_t sizeAtLa stGC) |
| 530 { | 480 { |
| 531 if (ThreadHeap::heapStats().wrapperCountAtLastGC() == 0) { | 481 if (m_heap->heapStats().wrapperCountAtLastGC() == 0) { |
| 532 // We'll reach here only before hitting the first GC. | 482 // We'll reach here only before hitting the first GC. |
| 533 return 0; | 483 return 0; |
| 534 } | 484 } |
| 535 | 485 |
| 536 // (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); | 486 // (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); |
| 537 size_t sizeRetainedByCollectedPersistents = static_cast<size_t>(1.0 * sizeAt LastGC / ThreadHeap::heapStats().wrapperCountAtLastGC() * ThreadHeap::heapStats( ).collectedWrapperCount()); | 487 size_t sizeRetainedByCollectedPersistents = static_cast<size_t>(1.0 * sizeAt LastGC / m_heap->heapStats().wrapperCountAtLastGC() * m_heap->heapStats().collec tedWrapperCount()); |
| 538 if (estimationBaseSize < sizeRetainedByCollectedPersistents) | 488 if (estimationBaseSize < sizeRetainedByCollectedPersistents) |
| 539 return 0; | 489 return 0; |
| 540 return estimationBaseSize - sizeRetainedByCollectedPersistents; | 490 return estimationBaseSize - sizeRetainedByCollectedPersistents; |
| 541 } | 491 } |
| 542 | 492 |
| 543 double ThreadState::heapGrowingRate() | 493 double ThreadState::heapGrowingRate() |
| 544 { | 494 { |
| 545 size_t currentSize = ThreadHeap::heapStats().allocatedObjectSize() + ThreadH eap::heapStats().markedObjectSize(); | 495 size_t currentSize = m_heap->heapStats().allocatedObjectSize() + m_heap->hea pStats().markedObjectSize(); |
| 546 size_t estimatedSize = estimatedLiveSize(ThreadHeap::heapStats().markedObjec tSizeAtLastCompleteSweep(), ThreadHeap::heapStats().markedObjectSizeAtLastComple teSweep()); | 496 size_t estimatedSize = estimatedLiveSize(m_heap->heapStats().markedObjectSiz eAtLastCompleteSweep(), m_heap->heapStats().markedObjectSizeAtLastCompleteSweep( )); |
| 547 | 497 |
| 548 // If the estimatedSize is 0, we set a high growing rate to trigger a GC. | 498 // If the estimatedSize is 0, we set a high growing rate to trigger a GC. |
| 549 double growingRate = estimatedSize > 0 ? 1.0 * currentSize / estimatedSize : 100; | 499 double growingRate = estimatedSize > 0 ? 1.0 * currentSize / estimatedSize : 100; |
| 550 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::heapEsti matedSizeKB", std::min(estimatedSize / 1024, static_cast<size_t>(INT_MAX))); | 500 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::heapEsti matedSizeKB", std::min(estimatedSize / 1024, static_cast<size_t>(INT_MAX))); |
| 551 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::heapGrow ingRate", static_cast<int>(100 * growingRate)); | 501 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::heapGrow ingRate", static_cast<int>(100 * growingRate)); |
| 552 return growingRate; | 502 return growingRate; |
| 553 } | 503 } |
| 554 | 504 |
| 555 double ThreadState::partitionAllocGrowingRate() | 505 double ThreadState::partitionAllocGrowingRate() |
| 556 { | 506 { |
| 557 size_t currentSize = WTF::Partitions::totalSizeOfCommittedPages(); | 507 size_t currentSize = WTF::Partitions::totalSizeOfCommittedPages(); |
| 558 size_t estimatedSize = estimatedLiveSize(currentSize, ThreadHeap::heapStats( ).partitionAllocSizeAtLastGC()); | 508 size_t estimatedSize = estimatedLiveSize(currentSize, m_heap->heapStats().pa rtitionAllocSizeAtLastGC()); |
| 559 | 509 |
| 560 // If the estimatedSize is 0, we set a high growing rate to trigger a GC. | 510 // If the estimatedSize is 0, we set a high growing rate to trigger a GC. |
| 561 double growingRate = estimatedSize > 0 ? 1.0 * currentSize / estimatedSize : 100; | 511 double growingRate = estimatedSize > 0 ? 1.0 * currentSize / estimatedSize : 100; |
| 562 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::partitio nAllocEstimatedSizeKB", std::min(estimatedSize / 1024, static_cast<size_t>(INT_M AX))); | 512 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::partitio nAllocEstimatedSizeKB", std::min(estimatedSize / 1024, static_cast<size_t>(INT_M AX))); |
| 563 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::partitio nAllocGrowingRate", static_cast<int>(100 * growingRate)); | 513 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::partitio nAllocGrowingRate", static_cast<int>(100 * growingRate)); |
| 564 return growingRate; | 514 return growingRate; |
| 565 } | 515 } |
| 566 | 516 |
| 567 // TODO(haraken): We should improve the GC heuristics. The heuristics affect | 517 // TODO(haraken): We should improve the GC heuristics. The heuristics affect |
| 568 // performance significantly. | 518 // performance significantly. |
| 569 bool ThreadState::judgeGCThreshold(size_t totalMemorySizeThreshold, double heapG rowingRateThreshold) | 519 bool ThreadState::judgeGCThreshold(size_t totalMemorySizeThreshold, double heapG rowingRateThreshold) |
| 570 { | 520 { |
| 571 // If the allocated object size or the total memory size is small, don't tri gger a GC. | 521 // If the allocated object size or the total memory size is small, don't tri gger a GC. |
| 572 if (ThreadHeap::heapStats().allocatedObjectSize() < 100 * 1024 || totalMemor ySize() < totalMemorySizeThreshold) | 522 if (m_heap->heapStats().allocatedObjectSize() < 100 * 1024 || totalMemorySiz e() < totalMemorySizeThreshold) |
| 573 return false; | 523 return false; |
| 574 // If the growing rate of Oilpan's heap or PartitionAlloc is high enough, | 524 // If the growing rate of Oilpan's heap or PartitionAlloc is high enough, |
| 575 // trigger a GC. | 525 // trigger a GC. |
| 576 #if PRINT_HEAP_STATS | 526 #if PRINT_HEAP_STATS |
| 577 dataLogF("heapGrowingRate=%.1lf, partitionAllocGrowingRate=%.1lf\n", heapGro wingRate(), partitionAllocGrowingRate()); | 527 dataLogF("heapGrowingRate=%.1lf, partitionAllocGrowingRate=%.1lf\n", heapGro wingRate(), partitionAllocGrowingRate()); |
| 578 #endif | 528 #endif |
| 579 return heapGrowingRate() >= heapGrowingRateThreshold || partitionAllocGrowin gRate() >= heapGrowingRateThreshold; | 529 return heapGrowingRate() >= heapGrowingRateThreshold || partitionAllocGrowin gRate() >= heapGrowingRateThreshold; |
| 580 } | 530 } |
| 581 | 531 |
| 582 bool ThreadState::shouldScheduleIdleGC() | 532 bool ThreadState::shouldScheduleIdleGC() |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 746 } | 696 } |
| 747 if (shouldScheduleIdleGC()) { | 697 if (shouldScheduleIdleGC()) { |
| 748 #if PRINT_HEAP_STATS | 698 #if PRINT_HEAP_STATS |
| 749 dataLogF("Scheduled IdleGC\n"); | 699 dataLogF("Scheduled IdleGC\n"); |
| 750 #endif | 700 #endif |
| 751 scheduleIdleGC(); | 701 scheduleIdleGC(); |
| 752 return; | 702 return; |
| 753 } | 703 } |
| 754 } | 704 } |
| 755 | 705 |
| 706 ThreadState* ThreadState::fromObject(const void* object) | |
|
haraken
2016/04/21 11:48:25
Worth inlining this method?
keishi
2016/04/22 06:09:59
It's hard to avoid a circular include right now.
| |
| 707 { | |
| 708 if (!object) | |
|
haraken
2016/04/21 11:48:25
I'd remove this check. Instead add ASSERT(object).
keishi
2016/04/22 06:09:59
Done.
| |
| 709 return nullptr; | |
| 710 BasePage* page = pageFromObject(object); | |
| 711 ASSERT(page); | |
| 712 ASSERT(page->arena()); | |
| 713 return page->arena()->getThreadState(); | |
| 714 } | |
| 715 | |
| 756 void ThreadState::performIdleGC(double deadlineSeconds) | 716 void ThreadState::performIdleGC(double deadlineSeconds) |
| 757 { | 717 { |
| 758 ASSERT(checkThread()); | 718 ASSERT(checkThread()); |
| 759 ASSERT(isMainThread()); | 719 ASSERT(isMainThread()); |
| 760 ASSERT(Platform::current()->currentThread()->scheduler()); | 720 ASSERT(Platform::current()->currentThread()->scheduler()); |
| 761 | 721 |
| 762 if (gcState() != IdleGCScheduled) | 722 if (gcState() != IdleGCScheduled) |
| 763 return; | 723 return; |
| 764 | 724 |
| 765 double idleDeltaInSeconds = deadlineSeconds - monotonicallyIncreasingTime(); | 725 double idleDeltaInSeconds = deadlineSeconds - monotonicallyIncreasingTime(); |
| 766 TRACE_EVENT2("blink_gc", "ThreadState::performIdleGC", "idleDeltaInSeconds", idleDeltaInSeconds, "estimatedMarkingTime", ThreadHeap::heapStats().estimatedMa rkingTime()); | 726 TRACE_EVENT2("blink_gc", "ThreadState::performIdleGC", "idleDeltaInSeconds", idleDeltaInSeconds, "estimatedMarkingTime", m_heap->heapStats().estimatedMarkin gTime()); |
| 767 if (idleDeltaInSeconds <= ThreadHeap::heapStats().estimatedMarkingTime() && !Platform::current()->currentThread()->scheduler()->canExceedIdleDeadlineIfRequi red()) { | 727 if (idleDeltaInSeconds <= m_heap->heapStats().estimatedMarkingTime() && !Pla tform::current()->currentThread()->scheduler()->canExceedIdleDeadlineIfRequired( )) { |
| 768 // If marking is estimated to take longer than the deadline and we can't | 728 // If marking is estimated to take longer than the deadline and we can't |
| 769 // exceed the deadline, then reschedule for the next idle period. | 729 // exceed the deadline, then reschedule for the next idle period. |
| 770 scheduleIdleGC(); | 730 scheduleIdleGC(); |
| 771 return; | 731 return; |
| 772 } | 732 } |
| 773 | 733 |
| 774 ThreadHeap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithou tSweep, BlinkGC::IdleGC); | 734 ThreadHeap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithou tSweep, BlinkGC::IdleGC); |
| 775 } | 735 } |
| 776 | 736 |
| 777 void ThreadState::performIdleLazySweep(double deadlineSeconds) | 737 void ThreadState::performIdleLazySweep(double deadlineSeconds) |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 959 // Idle time GC will be scheduled by Blink Scheduler. | 919 // Idle time GC will be scheduled by Blink Scheduler. |
| 960 break; | 920 break; |
| 961 default: | 921 default: |
| 962 break; | 922 break; |
| 963 } | 923 } |
| 964 } | 924 } |
| 965 | 925 |
| 966 void ThreadState::flushHeapDoesNotContainCacheIfNeeded() | 926 void ThreadState::flushHeapDoesNotContainCacheIfNeeded() |
| 967 { | 927 { |
| 968 if (m_shouldFlushHeapDoesNotContainCache) { | 928 if (m_shouldFlushHeapDoesNotContainCache) { |
| 969 ThreadHeap::flushHeapDoesNotContainCache(); | 929 m_heap->flushHeapDoesNotContainCache(); |
| 970 m_shouldFlushHeapDoesNotContainCache = false; | 930 m_shouldFlushHeapDoesNotContainCache = false; |
| 971 } | 931 } |
| 972 } | 932 } |
| 973 | 933 |
| 974 void ThreadState::makeConsistentForGC() | 934 void ThreadState::makeConsistentForGC() |
| 975 { | 935 { |
| 976 ASSERT(isInGC()); | 936 ASSERT(isInGC()); |
| 977 TRACE_EVENT0("blink_gc", "ThreadState::makeConsistentForGC"); | 937 TRACE_EVENT0("blink_gc", "ThreadState::makeConsistentForGC"); |
| 978 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) | 938 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) |
| 979 m_arenas[i]->makeConsistentForGC(); | 939 m_arenas[i]->makeConsistentForGC(); |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1126 postSweep(); | 1086 postSweep(); |
| 1127 } | 1087 } |
| 1128 | 1088 |
| 1129 void ThreadState::postSweep() | 1089 void ThreadState::postSweep() |
| 1130 { | 1090 { |
| 1131 ASSERT(checkThread()); | 1091 ASSERT(checkThread()); |
| 1132 ThreadHeap::reportMemoryUsageForTracing(); | 1092 ThreadHeap::reportMemoryUsageForTracing(); |
| 1133 | 1093 |
| 1134 if (isMainThread()) { | 1094 if (isMainThread()) { |
| 1135 double collectionRate = 0; | 1095 double collectionRate = 0; |
| 1136 if (ThreadHeap::heapStats().objectSizeAtLastGC() > 0) | 1096 if (m_heap->heapStats().objectSizeAtLastGC() > 0) |
| 1137 collectionRate = 1 - 1.0 * ThreadHeap::heapStats().markedObjectSize( ) / ThreadHeap::heapStats().objectSizeAtLastGC(); | 1097 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)); | 1098 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::coll ectionRate", static_cast<int>(100 * collectionRate)); |
| 1139 | 1099 |
| 1140 #if PRINT_HEAP_STATS | 1100 #if PRINT_HEAP_STATS |
| 1141 dataLogF("ThreadState::postSweep (collectionRate=%d%%)\n", static_cast<i nt>(100 * collectionRate)); | 1101 dataLogF("ThreadState::postSweep (collectionRate=%d%%)\n", static_cast<i nt>(100 * collectionRate)); |
| 1142 #endif | 1102 #endif |
| 1143 | 1103 |
| 1144 // ThreadHeap::markedObjectSize() may be underestimated here if any othe r | 1104 // ThreadHeap::markedObjectSize() may be underestimated here if any othe r |
| 1145 // thread has not yet finished lazy sweeping. | 1105 // thread has not yet finished lazy sweeping. |
| 1146 ThreadHeap::heapStats().setMarkedObjectSizeAtLastCompleteSweep(ThreadHea p::heapStats().markedObjectSize()); | 1106 m_heap->heapStats().setMarkedObjectSizeAtLastCompleteSweep(m_heap->heapS tats().markedObjectSize()); |
| 1147 | 1107 |
| 1148 DEFINE_STATIC_LOCAL(CustomCountHistogram, objectSizeBeforeGCHistogram, ( "BlinkGC.ObjectSizeBeforeGC", 1, 4 * 1024 * 1024, 50)); | 1108 DEFINE_STATIC_LOCAL(CustomCountHistogram, objectSizeBeforeGCHistogram, ( "BlinkGC.ObjectSizeBeforeGC", 1, 4 * 1024 * 1024, 50)); |
| 1149 objectSizeBeforeGCHistogram.count(ThreadHeap::heapStats().objectSizeAtLa stGC() / 1024); | 1109 objectSizeBeforeGCHistogram.count(m_heap->heapStats().objectSizeAtLastGC () / 1024); |
| 1150 DEFINE_STATIC_LOCAL(CustomCountHistogram, objectSizeAfterGCHistogram, (" BlinkGC.ObjectSizeAfterGC", 1, 4 * 1024 * 1024, 50)); | 1110 DEFINE_STATIC_LOCAL(CustomCountHistogram, objectSizeAfterGCHistogram, (" BlinkGC.ObjectSizeAfterGC", 1, 4 * 1024 * 1024, 50)); |
| 1151 objectSizeAfterGCHistogram.count(ThreadHeap::heapStats().markedObjectSiz e() / 1024); | 1111 objectSizeAfterGCHistogram.count(m_heap->heapStats().markedObjectSize() / 1024); |
| 1152 DEFINE_STATIC_LOCAL(CustomCountHistogram, collectionRateHistogram, ("Bli nkGC.CollectionRate", 1, 100, 20)); | 1112 DEFINE_STATIC_LOCAL(CustomCountHistogram, collectionRateHistogram, ("Bli nkGC.CollectionRate", 1, 100, 20)); |
| 1153 collectionRateHistogram.count(static_cast<int>(100 * collectionRate)); | 1113 collectionRateHistogram.count(static_cast<int>(100 * collectionRate)); |
| 1154 DEFINE_STATIC_LOCAL(CustomCountHistogram, timeForSweepHistogram, ("Blink GC.TimeForSweepingAllObjects", 1, 10 * 1000, 50)); | 1114 DEFINE_STATIC_LOCAL(CustomCountHistogram, timeForSweepHistogram, ("Blink GC.TimeForSweepingAllObjects", 1, 10 * 1000, 50)); |
| 1155 timeForSweepHistogram.count(m_accumulatedSweepingTime); | 1115 timeForSweepHistogram.count(m_accumulatedSweepingTime); |
| 1156 | 1116 |
| 1157 | 1117 |
| 1158 #define COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(GCReason) \ | 1118 #define COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(GCReason) \ |
| 1159 case BlinkGC::GCReason: { \ | 1119 case BlinkGC::GCReason: { \ |
| 1160 DEFINE_STATIC_LOCAL(CustomCountHistogram, histogram, \ | 1120 DEFINE_STATIC_LOCAL(CustomCountHistogram, histogram, \ |
| 1161 ("BlinkGC.CollectionRate_" #GCReason, 1, 100, 20)); \ | 1121 ("BlinkGC.CollectionRate_" #GCReason, 1, 100, 20)); \ |
| 1162 histogram.count(static_cast<int>(100 * collectionRate)); \ | 1122 histogram.count(static_cast<int>(100 * collectionRate)); \ |
| 1163 break; \ | 1123 break; \ |
| 1164 } | 1124 } |
| 1165 | 1125 |
| 1166 switch (ThreadHeap::lastGCReason()) { | 1126 switch (m_heap->lastGCReason()) { |
| 1167 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(IdleGC) | 1127 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(IdleGC) |
| 1168 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(PreciseGC) | 1128 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(PreciseGC) |
| 1169 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(ConservativeGC) | 1129 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(ConservativeGC) |
| 1170 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(ForcedGC) | 1130 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(ForcedGC) |
| 1171 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(MemoryPressureGC) | 1131 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(MemoryPressureGC) |
| 1172 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(PageNavigationGC) | 1132 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(PageNavigationGC) |
| 1173 default: | 1133 default: |
| 1174 break; | 1134 break; |
| 1175 } | 1135 } |
| 1176 } | 1136 } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1210 #endif | 1170 #endif |
| 1211 | 1171 |
| 1212 size_t ThreadState::objectPayloadSizeForTesting() | 1172 size_t ThreadState::objectPayloadSizeForTesting() |
| 1213 { | 1173 { |
| 1214 size_t objectPayloadSize = 0; | 1174 size_t objectPayloadSize = 0; |
| 1215 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) | 1175 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) |
| 1216 objectPayloadSize += m_arenas[i]->objectPayloadSizeForTesting(); | 1176 objectPayloadSize += m_arenas[i]->objectPayloadSizeForTesting(); |
| 1217 return objectPayloadSize; | 1177 return objectPayloadSize; |
| 1218 } | 1178 } |
| 1219 | 1179 |
| 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) | 1180 void ThreadState::safePoint(BlinkGC::StackState stackState) |
| 1231 { | 1181 { |
| 1232 ASSERT(checkThread()); | 1182 ASSERT(checkThread()); |
| 1233 ThreadHeap::reportMemoryUsageForTracing(); | 1183 ThreadHeap::reportMemoryUsageForTracing(); |
| 1234 | 1184 |
| 1235 runScheduledGC(stackState); | 1185 runScheduledGC(stackState); |
| 1236 ASSERT(!m_atSafePoint); | 1186 ASSERT(!m_atSafePoint); |
| 1237 m_stackState = stackState; | 1187 m_stackState = stackState; |
| 1238 m_atSafePoint = true; | 1188 m_atSafePoint = true; |
| 1239 s_safePointBarrier->checkAndPark(this); | 1189 m_heap->checkAndPark(this, nullptr); |
| 1240 m_atSafePoint = false; | 1190 m_atSafePoint = false; |
| 1241 m_stackState = BlinkGC::HeapPointersOnStack; | 1191 m_stackState = BlinkGC::HeapPointersOnStack; |
| 1242 preSweep(); | 1192 preSweep(); |
| 1243 } | 1193 } |
| 1244 | 1194 |
| 1245 #ifdef ADDRESS_SANITIZER | 1195 #ifdef ADDRESS_SANITIZER |
| 1246 // When we are running under AddressSanitizer with detect_stack_use_after_return =1 | 1196 // 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. | 1197 // 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 | 1198 // 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. | 1199 // and stack start and use an arbitrary high enough value for it. |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 1273 #ifdef ADDRESS_SANITIZER | 1223 #ifdef ADDRESS_SANITIZER |
| 1274 if (stackState == BlinkGC::HeapPointersOnStack) | 1224 if (stackState == BlinkGC::HeapPointersOnStack) |
| 1275 scopeMarker = adjustScopeMarkerForAdressSanitizer(scopeMarker); | 1225 scopeMarker = adjustScopeMarkerForAdressSanitizer(scopeMarker); |
| 1276 #endif | 1226 #endif |
| 1277 ASSERT(stackState == BlinkGC::NoHeapPointersOnStack || scopeMarker); | 1227 ASSERT(stackState == BlinkGC::NoHeapPointersOnStack || scopeMarker); |
| 1278 runScheduledGC(stackState); | 1228 runScheduledGC(stackState); |
| 1279 ASSERT(!m_atSafePoint); | 1229 ASSERT(!m_atSafePoint); |
| 1280 m_atSafePoint = true; | 1230 m_atSafePoint = true; |
| 1281 m_stackState = stackState; | 1231 m_stackState = stackState; |
| 1282 m_safePointScopeMarker = scopeMarker; | 1232 m_safePointScopeMarker = scopeMarker; |
| 1283 s_safePointBarrier->enterSafePoint(this); | 1233 m_heap->enterSafePoint(this); |
| 1284 } | 1234 } |
| 1285 | 1235 |
| 1286 void ThreadState::leaveSafePoint(SafePointAwareMutexLocker* locker) | 1236 void ThreadState::leaveSafePoint(SafePointAwareMutexLocker* locker) |
| 1287 { | 1237 { |
| 1288 ASSERT(checkThread()); | 1238 ASSERT(checkThread()); |
| 1289 ASSERT(m_atSafePoint); | 1239 ASSERT(m_atSafePoint); |
| 1290 s_safePointBarrier->leaveSafePoint(this, locker); | 1240 m_heap->leaveSafePoint(this, locker); |
| 1291 m_atSafePoint = false; | 1241 m_atSafePoint = false; |
| 1292 m_stackState = BlinkGC::HeapPointersOnStack; | 1242 m_stackState = BlinkGC::HeapPointersOnStack; |
| 1293 clearSafePointScopeMarker(); | 1243 clearSafePointScopeMarker(); |
| 1294 preSweep(); | 1244 preSweep(); |
| 1295 } | 1245 } |
| 1296 | 1246 |
| 1297 void ThreadState::reportMemoryToV8() | 1247 void ThreadState::reportMemoryToV8() |
| 1298 { | 1248 { |
| 1299 if (!m_isolate) | 1249 if (!m_isolate) |
| 1300 return; | 1250 return; |
| 1301 | 1251 |
| 1302 size_t currentHeapSize = m_allocatedObjectSize + m_markedObjectSize; | 1252 size_t currentHeapSize = m_allocatedObjectSize + m_markedObjectSize; |
| 1303 int64_t diff = static_cast<int64_t>(currentHeapSize) - static_cast<int64_t>( m_reportedMemoryToV8); | 1253 int64_t diff = static_cast<int64_t>(currentHeapSize) - static_cast<int64_t>( m_reportedMemoryToV8); |
| 1304 m_isolate->AdjustAmountOfExternalAllocatedMemory(diff); | 1254 m_isolate->AdjustAmountOfExternalAllocatedMemory(diff); |
| 1305 m_reportedMemoryToV8 = currentHeapSize; | 1255 m_reportedMemoryToV8 = currentHeapSize; |
| 1306 } | 1256 } |
| 1307 | 1257 |
| 1308 void ThreadState::resetHeapCounters() | 1258 void ThreadState::resetHeapCounters() |
| 1309 { | 1259 { |
| 1310 m_allocatedObjectSize = 0; | 1260 m_allocatedObjectSize = 0; |
| 1311 m_markedObjectSize = 0; | 1261 m_markedObjectSize = 0; |
| 1312 } | 1262 } |
| 1313 | 1263 |
| 1314 void ThreadState::increaseAllocatedObjectSize(size_t delta) | 1264 void ThreadState::increaseAllocatedObjectSize(size_t delta) |
| 1315 { | 1265 { |
| 1316 m_allocatedObjectSize += delta; | 1266 m_allocatedObjectSize += delta; |
| 1317 ThreadHeap::heapStats().increaseAllocatedObjectSize(delta); | 1267 m_heap->heapStats().increaseAllocatedObjectSize(delta); |
| 1318 } | 1268 } |
| 1319 | 1269 |
| 1320 void ThreadState::decreaseAllocatedObjectSize(size_t delta) | 1270 void ThreadState::decreaseAllocatedObjectSize(size_t delta) |
| 1321 { | 1271 { |
| 1322 m_allocatedObjectSize -= delta; | 1272 m_allocatedObjectSize -= delta; |
| 1323 ThreadHeap::heapStats().decreaseAllocatedObjectSize(delta); | 1273 m_heap->heapStats().decreaseAllocatedObjectSize(delta); |
| 1324 } | 1274 } |
| 1325 | 1275 |
| 1326 void ThreadState::increaseMarkedObjectSize(size_t delta) | 1276 void ThreadState::increaseMarkedObjectSize(size_t delta) |
| 1327 { | 1277 { |
| 1328 m_markedObjectSize += delta; | 1278 m_markedObjectSize += delta; |
| 1329 ThreadHeap::heapStats().increaseMarkedObjectSize(delta); | 1279 m_heap->heapStats().increaseMarkedObjectSize(delta); |
| 1330 } | 1280 } |
| 1331 | 1281 |
| 1332 void ThreadState::copyStackUntilSafePointScope() | 1282 void ThreadState::copyStackUntilSafePointScope() |
| 1333 { | 1283 { |
| 1334 if (!m_safePointScopeMarker || m_stackState == BlinkGC::NoHeapPointersOnStac k) | 1284 if (!m_safePointScopeMarker || m_stackState == BlinkGC::NoHeapPointersOnStac k) |
| 1335 return; | 1285 return; |
| 1336 | 1286 |
| 1337 Address* to = reinterpret_cast<Address*>(m_safePointScopeMarker); | 1287 Address* to = reinterpret_cast<Address*>(m_safePointScopeMarker); |
| 1338 Address* from = reinterpret_cast<Address*>(m_endOfStack); | 1288 Address* from = reinterpret_cast<Address*>(m_endOfStack); |
| 1339 RELEASE_ASSERT(from < to); | 1289 RELEASE_ASSERT(from < to); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 1353 for (size_t i = 0; i < slotCount; ++i) { | 1303 for (size_t i = 0; i < slotCount; ++i) { |
| 1354 m_safePointStackCopy[i] = from[i]; | 1304 m_safePointStackCopy[i] = from[i]; |
| 1355 } | 1305 } |
| 1356 } | 1306 } |
| 1357 | 1307 |
| 1358 void ThreadState::addInterruptor(PassOwnPtr<BlinkGCInterruptor> interruptor) | 1308 void ThreadState::addInterruptor(PassOwnPtr<BlinkGCInterruptor> interruptor) |
| 1359 { | 1309 { |
| 1360 ASSERT(checkThread()); | 1310 ASSERT(checkThread()); |
| 1361 SafePointScope scope(BlinkGC::HeapPointersOnStack); | 1311 SafePointScope scope(BlinkGC::HeapPointersOnStack); |
| 1362 { | 1312 { |
| 1363 MutexLocker locker(threadAttachMutex()); | 1313 MutexLocker locker(m_heap->threadAttachMutex()); |
| 1364 m_interruptors.append(interruptor); | 1314 m_interruptors.append(interruptor); |
| 1365 } | 1315 } |
| 1366 } | 1316 } |
| 1367 | 1317 |
| 1368 void ThreadState::registerThreadShutdownHook(PassOwnPtr<SameThreadClosure> hook) | 1318 void ThreadState::registerThreadShutdownHook(PassOwnPtr<SameThreadClosure> hook) |
| 1369 { | 1319 { |
| 1370 ASSERT(checkThread()); | 1320 ASSERT(checkThread()); |
| 1371 ASSERT(!isTerminating()); | 1321 ASSERT(!isTerminating()); |
| 1372 m_threadShutdownHooks.append(hook); | 1322 m_threadShutdownHooks.append(hook); |
| 1373 } | 1323 } |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 1395 m_disabledStaticPersistentsRegistration++; | 1345 m_disabledStaticPersistentsRegistration++; |
| 1396 } | 1346 } |
| 1397 | 1347 |
| 1398 void ThreadState::leaveStaticReferenceRegistrationDisabledScope() | 1348 void ThreadState::leaveStaticReferenceRegistrationDisabledScope() |
| 1399 { | 1349 { |
| 1400 ASSERT(m_disabledStaticPersistentsRegistration); | 1350 ASSERT(m_disabledStaticPersistentsRegistration); |
| 1401 m_disabledStaticPersistentsRegistration--; | 1351 m_disabledStaticPersistentsRegistration--; |
| 1402 } | 1352 } |
| 1403 #endif | 1353 #endif |
| 1404 | 1354 |
| 1405 ThreadState::AttachedThreadStateSet& ThreadState::attachedThreads() | |
| 1406 { | |
| 1407 DEFINE_STATIC_LOCAL(AttachedThreadStateSet, threads, ()); | |
| 1408 return threads; | |
| 1409 } | |
| 1410 | |
| 1411 void ThreadState::lockThreadAttachMutex() | 1355 void ThreadState::lockThreadAttachMutex() |
| 1412 { | 1356 { |
| 1413 threadAttachMutex().lock(); | 1357 m_heap->threadAttachMutex().lock(); |
| 1414 } | 1358 } |
| 1415 | 1359 |
| 1416 void ThreadState::unlockThreadAttachMutex() | 1360 void ThreadState::unlockThreadAttachMutex() |
| 1417 { | 1361 { |
| 1418 threadAttachMutex().unlock(); | 1362 m_heap->threadAttachMutex().unlock(); |
| 1419 } | 1363 } |
| 1420 | 1364 |
| 1421 void ThreadState::invokePreFinalizers() | 1365 void ThreadState::invokePreFinalizers() |
| 1422 { | 1366 { |
| 1423 ASSERT(checkThread()); | 1367 ASSERT(checkThread()); |
| 1424 ASSERT(!sweepForbidden()); | 1368 ASSERT(!sweepForbidden()); |
| 1425 TRACE_EVENT0("blink_gc", "ThreadState::invokePreFinalizers"); | 1369 TRACE_EVENT0("blink_gc", "ThreadState::invokePreFinalizers"); |
| 1426 | 1370 |
| 1427 double startTime = WTF::currentTimeMS(); | 1371 double startTime = WTF::currentTimeMS(); |
| 1428 if (!m_orderedPreFinalizers.isEmpty()) { | 1372 if (!m_orderedPreFinalizers.isEmpty()) { |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1564 threadDump->addScalar("dead_count", "objects", totalDeadCount); | 1508 threadDump->addScalar("dead_count", "objects", totalDeadCount); |
| 1565 threadDump->addScalar("live_size", "bytes", totalLiveSize); | 1509 threadDump->addScalar("live_size", "bytes", totalLiveSize); |
| 1566 threadDump->addScalar("dead_size", "bytes", totalDeadSize); | 1510 threadDump->addScalar("dead_size", "bytes", totalDeadSize); |
| 1567 | 1511 |
| 1568 WebMemoryAllocatorDump* heapsDump = BlinkGCMemoryDumpProvider::instance()->c reateMemoryAllocatorDumpForCurrentGC(heapsDumpName); | 1512 WebMemoryAllocatorDump* heapsDump = BlinkGCMemoryDumpProvider::instance()->c reateMemoryAllocatorDumpForCurrentGC(heapsDumpName); |
| 1569 WebMemoryAllocatorDump* classesDump = BlinkGCMemoryDumpProvider::instance()- >createMemoryAllocatorDumpForCurrentGC(classesDumpName); | 1513 WebMemoryAllocatorDump* classesDump = BlinkGCMemoryDumpProvider::instance()- >createMemoryAllocatorDumpForCurrentGC(classesDumpName); |
| 1570 BlinkGCMemoryDumpProvider::instance()->currentProcessMemoryDump()->addOwners hipEdge(classesDump->guid(), heapsDump->guid()); | 1514 BlinkGCMemoryDumpProvider::instance()->currentProcessMemoryDump()->addOwners hipEdge(classesDump->guid(), heapsDump->guid()); |
| 1571 } | 1515 } |
| 1572 | 1516 |
| 1573 } // namespace blink | 1517 } // namespace blink |
| OLD | NEW |