| 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 12 matching lines...) Expand all Loading... |
| 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 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(); |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |