| 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 } |
| 75 | 82 |
| 76 ThreadState::ThreadState() | 83 ThreadState::ThreadState() |
| 77 : m_thread(currentThread()) | 84 : m_thread(currentThread()) |
| 78 , m_persistentRegion(adoptPtr(new PersistentRegion())) | 85 , m_persistentRegion(adoptPtr(new PersistentRegion())) |
| 79 #if OS(WIN) && COMPILER(MSVC) | 86 #if OS(WIN) && COMPILER(MSVC) |
| 80 , m_threadStackSize(0) | 87 , m_threadStackSize(0) |
| 81 #endif | 88 #endif |
| 82 , m_startOfStack(reinterpret_cast<intptr_t*>(StackFrameDepth::getStackStart(
))) | 89 , m_startOfStack(reinterpret_cast<intptr_t*>(StackFrameDepth::getStackStart(
))) |
| 83 , m_endOfStack(reinterpret_cast<intptr_t*>(StackFrameDepth::getStackStart())
) | 90 , m_endOfStack(reinterpret_cast<intptr_t*>(StackFrameDepth::getStackStart())
) |
| 84 , m_safePointScopeMarker(nullptr) | 91 , m_safePointScopeMarker(nullptr) |
| (...skipping 23 matching lines...) Expand all Loading... |
| 108 { | 115 { |
| 109 ASSERT(checkThread()); | 116 ASSERT(checkThread()); |
| 110 ASSERT(!**s_threadSpecific); | 117 ASSERT(!**s_threadSpecific); |
| 111 **s_threadSpecific = this; | 118 **s_threadSpecific = this; |
| 112 | 119 |
| 113 if (isMainThread()) { | 120 if (isMainThread()) { |
| 114 s_mainThreadStackStart = reinterpret_cast<uintptr_t>(m_startOfStack) - s
izeof(void*); | 121 s_mainThreadStackStart = reinterpret_cast<uintptr_t>(m_startOfStack) - s
izeof(void*); |
| 115 size_t underestimatedStackSize = StackFrameDepth::getUnderestimatedStack
Size(); | 122 size_t underestimatedStackSize = StackFrameDepth::getUnderestimatedStack
Size(); |
| 116 if (underestimatedStackSize > sizeof(void*)) | 123 if (underestimatedStackSize > sizeof(void*)) |
| 117 s_mainThreadUnderestimatedStackSize = underestimatedStackSize - size
of(void*); | 124 s_mainThreadUnderestimatedStackSize = underestimatedStackSize - size
of(void*); |
| 118 m_heap = new ThreadHeap(); | |
| 119 } else { | |
| 120 m_heap = &ThreadState::mainThreadState()->heap(); | |
| 121 } | 125 } |
| 122 ASSERT(m_heap); | |
| 123 m_heap->attach(this); | |
| 124 | 126 |
| 125 for (int arenaIndex = 0; arenaIndex < BlinkGC::LargeObjectArenaIndex; arenaI
ndex++) | 127 for (int arenaIndex = 0; arenaIndex < BlinkGC::LargeObjectArenaIndex; arenaI
ndex++) |
| 126 m_arenas[arenaIndex] = new NormalPageArena(this, arenaIndex); | 128 m_arenas[arenaIndex] = new NormalPageArena(this, arenaIndex); |
| 127 m_arenas[BlinkGC::LargeObjectArenaIndex] = new LargeObjectArena(this, BlinkG
C::LargeObjectArenaIndex); | 129 m_arenas[BlinkGC::LargeObjectArenaIndex] = new LargeObjectArena(this, BlinkG
C::LargeObjectArenaIndex); |
| 128 | 130 |
| 129 m_likelyToBePromptlyFreed = adoptArrayPtr(new int[likelyToBePromptlyFreedArr
aySize]); | 131 m_likelyToBePromptlyFreed = adoptArrayPtr(new int[likelyToBePromptlyFreedArr
aySize]); |
| 130 clearArenaAges(); | 132 clearArenaAges(); |
| 131 | 133 |
| 132 // There is little use of weak references and collections off the main threa
d; | 134 // There is little use of weak references and collections off the main threa
d; |
| 133 // use a much lower initial block reservation. | 135 // use a much lower initial block reservation. |
| 134 size_t initialBlockSize = isMainThread() ? CallbackStack::kDefaultBlockSize
: CallbackStack::kMinimalBlockSize; | 136 size_t initialBlockSize = isMainThread() ? CallbackStack::kDefaultBlockSize
: CallbackStack::kMinimalBlockSize; |
| 135 m_threadLocalWeakCallbackStack = new CallbackStack(initialBlockSize); | 137 m_threadLocalWeakCallbackStack = new CallbackStack(initialBlockSize); |
| 136 } | 138 } |
| 137 | 139 |
| 138 ThreadState::~ThreadState() | 140 ThreadState::~ThreadState() |
| 139 { | 141 { |
| 140 ASSERT(checkThread()); | 142 ASSERT(checkThread()); |
| 141 delete m_threadLocalWeakCallbackStack; | 143 delete m_threadLocalWeakCallbackStack; |
| 142 m_threadLocalWeakCallbackStack = nullptr; | 144 m_threadLocalWeakCallbackStack = nullptr; |
| 143 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) | 145 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) |
| 144 delete m_arenas[i]; | 146 delete m_arenas[i]; |
| 145 | 147 |
| 146 **s_threadSpecific = nullptr; | 148 **s_threadSpecific = nullptr; |
| 147 if (isMainThread()) { | 149 if (isMainThread()) { |
| 148 s_mainThreadStackStart = 0; | 150 s_mainThreadStackStart = 0; |
| 149 s_mainThreadUnderestimatedStackSize = 0; | 151 s_mainThreadUnderestimatedStackSize = 0; |
| 150 } | 152 } |
| 151 } | 153 } |
| 152 | 154 |
| 155 void ThreadState::init() |
| 156 { |
| 157 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 } |
| 168 |
| 153 #if OS(WIN) && COMPILER(MSVC) | 169 #if OS(WIN) && COMPILER(MSVC) |
| 154 size_t ThreadState::threadStackSize() | 170 size_t ThreadState::threadStackSize() |
| 155 { | 171 { |
| 156 if (m_threadStackSize) | 172 if (m_threadStackSize) |
| 157 return m_threadStackSize; | 173 return m_threadStackSize; |
| 158 | 174 |
| 159 // Notice that we cannot use the TIB's StackLimit for the stack end, as it | 175 // Notice that we cannot use the TIB's StackLimit for the stack end, as it |
| 160 // tracks the end of the committed range. We're after the end of the reserve
d | 176 // tracks the end of the committed range. We're after the end of the reserve
d |
| 161 // stack area (most of which will be uncommitted, most times.) | 177 // stack area (most of which will be uncommitted, most times.) |
| 162 MEMORY_BASIC_INFORMATION stackInfo; | 178 MEMORY_BASIC_INFORMATION stackInfo; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 180 // http://blogs.msdn.com/b/satyem/archive/2012/08/13/thread-s-stack-memory-m
anagement.aspx | 196 // http://blogs.msdn.com/b/satyem/archive/2012/08/13/thread-s-stack-memory-m
anagement.aspx |
| 181 // explains the details. | 197 // explains the details. |
| 182 RELEASE_ASSERT(m_threadStackSize > 4 * 0x1000); | 198 RELEASE_ASSERT(m_threadStackSize > 4 * 0x1000); |
| 183 m_threadStackSize -= 4 * 0x1000; | 199 m_threadStackSize -= 4 * 0x1000; |
| 184 return m_threadStackSize; | 200 return m_threadStackSize; |
| 185 } | 201 } |
| 186 #endif | 202 #endif |
| 187 | 203 |
| 188 void ThreadState::attachMainThread() | 204 void ThreadState::attachMainThread() |
| 189 { | 205 { |
| 190 RELEASE_ASSERT(!ProcessHeap::s_shutdownComplete); | 206 MutexLocker locker(threadAttachMutex()); |
| 191 s_threadSpecific = new WTF::ThreadSpecific<ThreadState*>(); | 207 ThreadState* state = new (s_mainThreadStateStorage) ThreadState(); |
| 192 new (s_mainThreadStateStorage) ThreadState(); | 208 attachedThreads().add(state); |
| 193 } | 209 } |
| 194 | 210 |
| 195 void ThreadState::attachCurrentThread() | |
| 196 { | |
| 197 RELEASE_ASSERT(!ProcessHeap::s_shutdownComplete); | |
| 198 new ThreadState(); | |
| 199 } | |
| 200 | |
| 201 void ThreadState::cleanupPages() | |
| 202 { | |
| 203 ASSERT(checkThread()); | |
| 204 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) | |
| 205 m_arenas[i]->cleanupPages(); | |
| 206 } | |
| 207 | |
| 208 void ThreadState::runTerminationGC() | |
| 209 { | |
| 210 if (isMainThread()) { | |
| 211 cleanupPages(); | |
| 212 return; | |
| 213 } | |
| 214 ASSERT(checkThread()); | |
| 215 | |
| 216 // Finish sweeping. | |
| 217 completeSweep(); | |
| 218 | |
| 219 // From here on ignore all conservatively discovered | |
| 220 // pointers into the heap owned by this thread. | |
| 221 m_isTerminating = true; | |
| 222 | |
| 223 releaseStaticPersistentNodes(); | |
| 224 | |
| 225 // Set the terminate flag on all heap pages of this thread. This is used to | |
| 226 // ensure we don't trace pages on other threads that are not part of the | |
| 227 // thread local GC. | |
| 228 prepareForThreadStateTermination(); | |
| 229 | |
| 230 ProcessHeap::crossThreadPersistentRegion().prepareForThreadStateTermination(
this); | |
| 231 | |
| 232 // Do thread local GC's as long as the count of thread local Persistents | |
| 233 // changes and is above zero. | |
| 234 int oldCount = -1; | |
| 235 int currentCount = getPersistentRegion()->numberOfPersistents(); | |
| 236 ASSERT(currentCount >= 0); | |
| 237 while (currentCount != oldCount) { | |
| 238 ThreadHeap::collectGarbageForTerminatingThread(this); | |
| 239 oldCount = currentCount; | |
| 240 currentCount = getPersistentRegion()->numberOfPersistents(); | |
| 241 } | |
| 242 // We should not have any persistents left when getting to this point, | |
| 243 // if we have it is probably a bug so adding a debug ASSERT to catch this. | |
| 244 ASSERT(!currentCount); | |
| 245 // All of pre-finalizers should be consumed. | |
| 246 ASSERT(m_orderedPreFinalizers.isEmpty()); | |
| 247 RELEASE_ASSERT(gcState() == NoGCScheduled); | |
| 248 | |
| 249 // Add pages to the orphaned page pool to ensure any global GCs from this po
int | |
| 250 // on will not trace objects on this thread's arenas. | |
| 251 cleanupPages(); | |
| 252 } | |
| 253 | 211 |
| 254 void ThreadState::cleanupMainThread() | 212 void ThreadState::cleanupMainThread() |
| 255 { | 213 { |
| 256 ASSERT(isMainThread()); | 214 ASSERT(isMainThread()); |
| 257 | 215 |
| 258 releaseStaticPersistentNodes(); | 216 releaseStaticPersistentNodes(); |
| 259 | 217 |
| 260 #if defined(LEAK_SANITIZER) | 218 #if defined(LEAK_SANITIZER) |
| 261 // If LSan is about to perform leak detection, after having released all | 219 // If LSan is about to perform leak detection, after having released all |
| 262 // the registered static Persistent<> root references to global caches | 220 // the registered static Persistent<> root references to global caches |
| (...skipping 16 matching lines...) Expand all Loading... |
| 279 enterGCForbiddenScope(); | 237 enterGCForbiddenScope(); |
| 280 } | 238 } |
| 281 | 239 |
| 282 void ThreadState::detachMainThread() | 240 void ThreadState::detachMainThread() |
| 283 { | 241 { |
| 284 // Enter a safe point before trying to acquire threadAttachMutex | 242 // Enter a safe point before trying to acquire threadAttachMutex |
| 285 // to avoid dead lock if another thread is preparing for GC, has acquired | 243 // to avoid dead lock if another thread is preparing for GC, has acquired |
| 286 // threadAttachMutex and waiting for other threads to pause or reach a | 244 // threadAttachMutex and waiting for other threads to pause or reach a |
| 287 // safepoint. | 245 // safepoint. |
| 288 ThreadState* state = mainThreadState(); | 246 ThreadState* state = mainThreadState(); |
| 247 ASSERT(state == ThreadState::current()); |
| 248 ASSERT(state->checkThread()); |
| 289 ASSERT(!state->isSweepingInProgress()); | 249 ASSERT(!state->isSweepingInProgress()); |
| 290 | 250 |
| 291 state->heap().detach(state); | 251 // The main thread must be the last thread that gets detached. |
| 252 RELEASE_ASSERT(ThreadState::attachedThreads().size() == 1); |
| 253 |
| 254 // Add the main thread's heap pages to the orphaned pool. |
| 255 state->cleanupPages(); |
| 256 |
| 257 // Detach the main thread. We don't need to grab a lock because |
| 258 // the main thread should be the last thread that gets detached. |
| 259 ASSERT(attachedThreads().contains(state)); |
| 260 attachedThreads().remove(state); |
| 292 state->~ThreadState(); | 261 state->~ThreadState(); |
| 293 } | 262 } |
| 294 | 263 |
| 295 void ThreadState::detachCurrentThread() | 264 void ThreadState::attach() |
| 265 { |
| 266 MutexLocker locker(threadAttachMutex()); |
| 267 ThreadState* state = new ThreadState(); |
| 268 attachedThreads().add(state); |
| 269 } |
| 270 |
| 271 void ThreadState::cleanupPages() |
| 272 { |
| 273 ASSERT(checkThread()); |
| 274 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) |
| 275 m_arenas[i]->cleanupPages(); |
| 276 } |
| 277 |
| 278 void ThreadState::cleanup() |
| 279 { |
| 280 ASSERT(checkThread()); |
| 281 { |
| 282 // Grab the threadAttachMutex to ensure only one thread can shutdown at |
| 283 // a time and that no other thread can do a global GC. It also allows |
| 284 // safe iteration of the attachedThreads set which happens as part of |
| 285 // thread local GC asserts. We enter a safepoint while waiting for the |
| 286 // lock to avoid a dead-lock where another thread has already requested |
| 287 // GC. |
| 288 SafePointAwareMutexLocker locker(threadAttachMutex(), BlinkGC::NoHeapPoi
ntersOnStack); |
| 289 |
| 290 // Finish sweeping. |
| 291 completeSweep(); |
| 292 |
| 293 // From here on ignore all conservatively discovered |
| 294 // pointers into the heap owned by this thread. |
| 295 m_isTerminating = true; |
| 296 |
| 297 releaseStaticPersistentNodes(); |
| 298 |
| 299 // Set the terminate flag on all heap pages of this thread. This is used
to |
| 300 // ensure we don't trace pages on other threads that are not part of the |
| 301 // thread local GC. |
| 302 prepareForThreadStateTermination(); |
| 303 |
| 304 ProcessHeap::crossThreadPersistentRegion().prepareForThreadStateTerminat
ion(this); |
| 305 |
| 306 // Do thread local GC's as long as the count of thread local Persistents |
| 307 // changes and is above zero. |
| 308 int oldCount = -1; |
| 309 int currentCount = getPersistentRegion()->numberOfPersistents(); |
| 310 ASSERT(currentCount >= 0); |
| 311 while (currentCount != oldCount) { |
| 312 ThreadHeap::collectGarbageForTerminatingThread(this); |
| 313 oldCount = currentCount; |
| 314 currentCount = getPersistentRegion()->numberOfPersistents(); |
| 315 } |
| 316 // We should not have any persistents left when getting to this point, |
| 317 // if we have it is probably a bug so adding a debug ASSERT to catch thi
s. |
| 318 ASSERT(!currentCount); |
| 319 // All of pre-finalizers should be consumed. |
| 320 ASSERT(m_orderedPreFinalizers.isEmpty()); |
| 321 RELEASE_ASSERT(gcState() == NoGCScheduled); |
| 322 |
| 323 // Add pages to the orphaned page pool to ensure any global GCs from thi
s point |
| 324 // on will not trace objects on this thread's arenas. |
| 325 cleanupPages(); |
| 326 |
| 327 ASSERT(attachedThreads().contains(this)); |
| 328 attachedThreads().remove(this); |
| 329 } |
| 330 } |
| 331 |
| 332 void ThreadState::detach() |
| 296 { | 333 { |
| 297 ThreadState* state = current(); | 334 ThreadState* state = current(); |
| 298 state->heap().detach(state); | 335 state->cleanup(); |
| 299 RELEASE_ASSERT(state->gcState() == ThreadState::NoGCScheduled); | 336 RELEASE_ASSERT(state->gcState() == ThreadState::NoGCScheduled); |
| 300 delete state; | 337 delete state; |
| 301 } | 338 } |
| 302 | 339 |
| 340 void ThreadState::visitPersistentRoots(Visitor* visitor) |
| 341 { |
| 342 TRACE_EVENT0("blink_gc", "ThreadState::visitPersistentRoots"); |
| 343 ProcessHeap::crossThreadPersistentRegion().tracePersistentNodes(visitor); |
| 344 |
| 345 for (ThreadState* state : attachedThreads()) |
| 346 state->visitPersistents(visitor); |
| 347 } |
| 348 |
| 349 void ThreadState::visitStackRoots(Visitor* visitor) |
| 350 { |
| 351 TRACE_EVENT0("blink_gc", "ThreadState::visitStackRoots"); |
| 352 for (ThreadState* state : attachedThreads()) |
| 353 state->visitStack(visitor); |
| 354 } |
| 355 |
| 303 NO_SANITIZE_ADDRESS | 356 NO_SANITIZE_ADDRESS |
| 304 void ThreadState::visitAsanFakeStackForPointer(Visitor* visitor, Address ptr) | 357 void ThreadState::visitAsanFakeStackForPointer(Visitor* visitor, Address ptr) |
| 305 { | 358 { |
| 306 #if defined(ADDRESS_SANITIZER) | 359 #if defined(ADDRESS_SANITIZER) |
| 307 Address* start = reinterpret_cast<Address*>(m_startOfStack); | 360 Address* start = reinterpret_cast<Address*>(m_startOfStack); |
| 308 Address* end = reinterpret_cast<Address*>(m_endOfStack); | 361 Address* end = reinterpret_cast<Address*>(m_endOfStack); |
| 309 Address* fakeFrameStart = nullptr; | 362 Address* fakeFrameStart = nullptr; |
| 310 Address* fakeFrameEnd = nullptr; | 363 Address* fakeFrameEnd = nullptr; |
| 311 Address* maybeFakeFrame = reinterpret_cast<Address*>(ptr); | 364 Address* maybeFakeFrame = reinterpret_cast<Address*>(ptr); |
| 312 Address* realFrameForFakeFrame = | 365 Address* realFrameForFakeFrame = |
| 313 reinterpret_cast<Address*>( | 366 reinterpret_cast<Address*>( |
| 314 __asan_addr_is_in_fake_stack( | 367 __asan_addr_is_in_fake_stack( |
| 315 m_asanFakeStack, maybeFakeFrame, | 368 m_asanFakeStack, maybeFakeFrame, |
| 316 reinterpret_cast<void**>(&fakeFrameStart), | 369 reinterpret_cast<void**>(&fakeFrameStart), |
| 317 reinterpret_cast<void**>(&fakeFrameEnd))); | 370 reinterpret_cast<void**>(&fakeFrameEnd))); |
| 318 if (realFrameForFakeFrame) { | 371 if (realFrameForFakeFrame) { |
| 319 // This is a fake frame from the asan fake stack. | 372 // This is a fake frame from the asan fake stack. |
| 320 if (realFrameForFakeFrame > end && start > realFrameForFakeFrame) { | 373 if (realFrameForFakeFrame > end && start > realFrameForFakeFrame) { |
| 321 // The real stack address for the asan fake frame is | 374 // The real stack address for the asan fake frame is |
| 322 // within the stack range that we need to scan so we need | 375 // within the stack range that we need to scan so we need |
| 323 // to visit the values in the fake frame. | 376 // to visit the values in the fake frame. |
| 324 for (Address* p = fakeFrameStart; p < fakeFrameEnd; ++p) | 377 for (Address* p = fakeFrameStart; p < fakeFrameEnd; ++p) |
| 325 m_heap->checkAndMarkPointer(visitor, *p); | 378 ThreadHeap::checkAndMarkPointer(visitor, *p); |
| 326 } | 379 } |
| 327 } | 380 } |
| 328 #endif | 381 #endif |
| 329 } | 382 } |
| 330 | 383 |
| 331 NO_SANITIZE_ADDRESS | 384 NO_SANITIZE_ADDRESS |
| 332 void ThreadState::visitStack(Visitor* visitor) | 385 void ThreadState::visitStack(Visitor* visitor) |
| 333 { | 386 { |
| 334 if (m_stackState == BlinkGC::NoHeapPointersOnStack) | 387 if (m_stackState == BlinkGC::NoHeapPointersOnStack) |
| 335 return; | 388 return; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 351 for (; current < start; ++current) { | 404 for (; current < start; ++current) { |
| 352 Address ptr = *current; | 405 Address ptr = *current; |
| 353 #if defined(MEMORY_SANITIZER) | 406 #if defined(MEMORY_SANITIZER) |
| 354 // |ptr| may be uninitialized by design. Mark it as initialized to keep | 407 // |ptr| may be uninitialized by design. Mark it as initialized to keep |
| 355 // MSan from complaining. | 408 // MSan from complaining. |
| 356 // Note: it may be tempting to get rid of |ptr| and simply use |current| | 409 // Note: it may be tempting to get rid of |ptr| and simply use |current| |
| 357 // here, but that would be incorrect. We intentionally use a local | 410 // here, but that would be incorrect. We intentionally use a local |
| 358 // variable because we don't want to unpoison the original stack. | 411 // variable because we don't want to unpoison the original stack. |
| 359 __msan_unpoison(&ptr, sizeof(ptr)); | 412 __msan_unpoison(&ptr, sizeof(ptr)); |
| 360 #endif | 413 #endif |
| 361 m_heap->checkAndMarkPointer(visitor, ptr); | 414 ThreadHeap::checkAndMarkPointer(visitor, ptr); |
| 362 visitAsanFakeStackForPointer(visitor, ptr); | 415 visitAsanFakeStackForPointer(visitor, ptr); |
| 363 } | 416 } |
| 364 | 417 |
| 365 for (Address ptr : m_safePointStackCopy) { | 418 for (Address ptr : m_safePointStackCopy) { |
| 366 #if defined(MEMORY_SANITIZER) | 419 #if defined(MEMORY_SANITIZER) |
| 367 // See the comment above. | 420 // See the comment above. |
| 368 __msan_unpoison(&ptr, sizeof(ptr)); | 421 __msan_unpoison(&ptr, sizeof(ptr)); |
| 369 #endif | 422 #endif |
| 370 m_heap->checkAndMarkPointer(visitor, ptr); | 423 ThreadHeap::checkAndMarkPointer(visitor, ptr); |
| 371 visitAsanFakeStackForPointer(visitor, ptr); | 424 visitAsanFakeStackForPointer(visitor, ptr); |
| 372 } | 425 } |
| 373 } | 426 } |
| 374 | 427 |
| 375 void ThreadState::visitPersistents(Visitor* visitor) | 428 void ThreadState::visitPersistents(Visitor* visitor) |
| 376 { | 429 { |
| 377 m_persistentRegion->tracePersistentNodes(visitor); | 430 m_persistentRegion->tracePersistentNodes(visitor); |
| 378 if (m_traceDOMWrappers) { | 431 if (m_traceDOMWrappers) { |
| 379 TRACE_EVENT0("blink_gc", "V8GCController::traceDOMWrappers"); | 432 TRACE_EVENT0("blink_gc", "V8GCController::traceDOMWrappers"); |
| 380 m_traceDOMWrappers(m_isolate, visitor); | 433 m_traceDOMWrappers(m_isolate, visitor); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 461 | 514 |
| 462 if (isMainThread()) { | 515 if (isMainThread()) { |
| 463 double timeForThreadLocalWeakProcessing = WTF::currentTimeMS() - startTi
me; | 516 double timeForThreadLocalWeakProcessing = WTF::currentTimeMS() - startTi
me; |
| 464 DEFINE_STATIC_LOCAL(CustomCountHistogram, timeForWeakHistogram, ("BlinkG
C.TimeForThreadLocalWeakProcessing", 1, 10 * 1000, 50)); | 517 DEFINE_STATIC_LOCAL(CustomCountHistogram, timeForWeakHistogram, ("BlinkG
C.TimeForThreadLocalWeakProcessing", 1, 10 * 1000, 50)); |
| 465 timeForWeakHistogram.count(timeForThreadLocalWeakProcessing); | 518 timeForWeakHistogram.count(timeForThreadLocalWeakProcessing); |
| 466 } | 519 } |
| 467 } | 520 } |
| 468 | 521 |
| 469 size_t ThreadState::totalMemorySize() | 522 size_t ThreadState::totalMemorySize() |
| 470 { | 523 { |
| 471 return m_heap->heapStats().allocatedObjectSize() + m_heap->heapStats().marke
dObjectSize() + WTF::Partitions::totalSizeOfCommittedPages(); | 524 return ThreadHeap::heapStats().allocatedObjectSize() + ThreadHeap::heapStats
().markedObjectSize() + WTF::Partitions::totalSizeOfCommittedPages(); |
| 472 } | 525 } |
| 473 | 526 |
| 474 size_t ThreadState::estimatedLiveSize(size_t estimationBaseSize, size_t sizeAtLa
stGC) | 527 size_t ThreadState::estimatedLiveSize(size_t estimationBaseSize, size_t sizeAtLa
stGC) |
| 475 { | 528 { |
| 476 if (m_heap->heapStats().wrapperCountAtLastGC() == 0) { | 529 if (ThreadHeap::heapStats().wrapperCountAtLastGC() == 0) { |
| 477 // We'll reach here only before hitting the first GC. | 530 // We'll reach here only before hitting the first GC. |
| 478 return 0; | 531 return 0; |
| 479 } | 532 } |
| 480 | 533 |
| 481 // (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); | 534 // (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); |
| 482 size_t sizeRetainedByCollectedPersistents = static_cast<size_t>(1.0 * sizeAt
LastGC / m_heap->heapStats().wrapperCountAtLastGC() * m_heap->heapStats().collec
tedWrapperCount()); | 535 size_t sizeRetainedByCollectedPersistents = static_cast<size_t>(1.0 * sizeAt
LastGC / ThreadHeap::heapStats().wrapperCountAtLastGC() * ThreadHeap::heapStats(
).collectedWrapperCount()); |
| 483 if (estimationBaseSize < sizeRetainedByCollectedPersistents) | 536 if (estimationBaseSize < sizeRetainedByCollectedPersistents) |
| 484 return 0; | 537 return 0; |
| 485 return estimationBaseSize - sizeRetainedByCollectedPersistents; | 538 return estimationBaseSize - sizeRetainedByCollectedPersistents; |
| 486 } | 539 } |
| 487 | 540 |
| 488 double ThreadState::heapGrowingRate() | 541 double ThreadState::heapGrowingRate() |
| 489 { | 542 { |
| 490 size_t currentSize = m_heap->heapStats().allocatedObjectSize() + m_heap->hea
pStats().markedObjectSize(); | 543 size_t currentSize = ThreadHeap::heapStats().allocatedObjectSize() + ThreadH
eap::heapStats().markedObjectSize(); |
| 491 size_t estimatedSize = estimatedLiveSize(m_heap->heapStats().markedObjectSiz
eAtLastCompleteSweep(), m_heap->heapStats().markedObjectSizeAtLastCompleteSweep(
)); | 544 size_t estimatedSize = estimatedLiveSize(ThreadHeap::heapStats().markedObjec
tSizeAtLastCompleteSweep(), ThreadHeap::heapStats().markedObjectSizeAtLastComple
teSweep()); |
| 492 | 545 |
| 493 // If the estimatedSize is 0, we set a high growing rate to trigger a GC. | 546 // If the estimatedSize is 0, we set a high growing rate to trigger a GC. |
| 494 double growingRate = estimatedSize > 0 ? 1.0 * currentSize / estimatedSize :
100; | 547 double growingRate = estimatedSize > 0 ? 1.0 * currentSize / estimatedSize :
100; |
| 495 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::heapEsti
matedSizeKB", std::min(estimatedSize / 1024, static_cast<size_t>(INT_MAX))); | 548 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::heapEsti
matedSizeKB", std::min(estimatedSize / 1024, static_cast<size_t>(INT_MAX))); |
| 496 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::heapGrow
ingRate", static_cast<int>(100 * growingRate)); | 549 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::heapGrow
ingRate", static_cast<int>(100 * growingRate)); |
| 497 return growingRate; | 550 return growingRate; |
| 498 } | 551 } |
| 499 | 552 |
| 500 double ThreadState::partitionAllocGrowingRate() | 553 double ThreadState::partitionAllocGrowingRate() |
| 501 { | 554 { |
| 502 size_t currentSize = WTF::Partitions::totalSizeOfCommittedPages(); | 555 size_t currentSize = WTF::Partitions::totalSizeOfCommittedPages(); |
| 503 size_t estimatedSize = estimatedLiveSize(currentSize, m_heap->heapStats().pa
rtitionAllocSizeAtLastGC()); | 556 size_t estimatedSize = estimatedLiveSize(currentSize, ThreadHeap::heapStats(
).partitionAllocSizeAtLastGC()); |
| 504 | 557 |
| 505 // If the estimatedSize is 0, we set a high growing rate to trigger a GC. | 558 // If the estimatedSize is 0, we set a high growing rate to trigger a GC. |
| 506 double growingRate = estimatedSize > 0 ? 1.0 * currentSize / estimatedSize :
100; | 559 double growingRate = estimatedSize > 0 ? 1.0 * currentSize / estimatedSize :
100; |
| 507 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::partitio
nAllocEstimatedSizeKB", std::min(estimatedSize / 1024, static_cast<size_t>(INT_M
AX))); | 560 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::partitio
nAllocEstimatedSizeKB", std::min(estimatedSize / 1024, static_cast<size_t>(INT_M
AX))); |
| 508 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::partitio
nAllocGrowingRate", static_cast<int>(100 * growingRate)); | 561 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::partitio
nAllocGrowingRate", static_cast<int>(100 * growingRate)); |
| 509 return growingRate; | 562 return growingRate; |
| 510 } | 563 } |
| 511 | 564 |
| 512 // TODO(haraken): We should improve the GC heuristics. The heuristics affect | 565 // TODO(haraken): We should improve the GC heuristics. The heuristics affect |
| 513 // performance significantly. | 566 // performance significantly. |
| 514 bool ThreadState::judgeGCThreshold(size_t totalMemorySizeThreshold, double heapG
rowingRateThreshold) | 567 bool ThreadState::judgeGCThreshold(size_t totalMemorySizeThreshold, double heapG
rowingRateThreshold) |
| 515 { | 568 { |
| 516 // If the allocated object size or the total memory size is small, don't tri
gger a GC. | 569 // If the allocated object size or the total memory size is small, don't tri
gger a GC. |
| 517 if (m_heap->heapStats().allocatedObjectSize() < 100 * 1024 || totalMemorySiz
e() < totalMemorySizeThreshold) | 570 if (ThreadHeap::heapStats().allocatedObjectSize() < 100 * 1024 || totalMemor
ySize() < totalMemorySizeThreshold) |
| 518 return false; | 571 return false; |
| 519 // If the growing rate of Oilpan's heap or PartitionAlloc is high enough, | 572 // If the growing rate of Oilpan's heap or PartitionAlloc is high enough, |
| 520 // trigger a GC. | 573 // trigger a GC. |
| 521 #if PRINT_HEAP_STATS | 574 #if PRINT_HEAP_STATS |
| 522 dataLogF("heapGrowingRate=%.1lf, partitionAllocGrowingRate=%.1lf\n", heapGro
wingRate(), partitionAllocGrowingRate()); | 575 dataLogF("heapGrowingRate=%.1lf, partitionAllocGrowingRate=%.1lf\n", heapGro
wingRate(), partitionAllocGrowingRate()); |
| 523 #endif | 576 #endif |
| 524 return heapGrowingRate() >= heapGrowingRateThreshold || partitionAllocGrowin
gRate() >= heapGrowingRateThreshold; | 577 return heapGrowingRate() >= heapGrowingRateThreshold || partitionAllocGrowin
gRate() >= heapGrowingRateThreshold; |
| 525 } | 578 } |
| 526 | 579 |
| 527 bool ThreadState::shouldScheduleIdleGC() | 580 bool ThreadState::shouldScheduleIdleGC() |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 691 } | 744 } |
| 692 if (shouldScheduleIdleGC()) { | 745 if (shouldScheduleIdleGC()) { |
| 693 #if PRINT_HEAP_STATS | 746 #if PRINT_HEAP_STATS |
| 694 dataLogF("Scheduled IdleGC\n"); | 747 dataLogF("Scheduled IdleGC\n"); |
| 695 #endif | 748 #endif |
| 696 scheduleIdleGC(); | 749 scheduleIdleGC(); |
| 697 return; | 750 return; |
| 698 } | 751 } |
| 699 } | 752 } |
| 700 | 753 |
| 701 ThreadState* ThreadState::fromObject(const void* object) | |
| 702 { | |
| 703 ASSERT(object); | |
| 704 BasePage* page = pageFromObject(object); | |
| 705 ASSERT(page); | |
| 706 ASSERT(page->arena()); | |
| 707 return page->arena()->getThreadState(); | |
| 708 } | |
| 709 | |
| 710 void ThreadState::performIdleGC(double deadlineSeconds) | 754 void ThreadState::performIdleGC(double deadlineSeconds) |
| 711 { | 755 { |
| 712 ASSERT(checkThread()); | 756 ASSERT(checkThread()); |
| 713 ASSERT(isMainThread()); | 757 ASSERT(isMainThread()); |
| 714 ASSERT(Platform::current()->currentThread()->scheduler()); | 758 ASSERT(Platform::current()->currentThread()->scheduler()); |
| 715 | 759 |
| 716 if (gcState() != IdleGCScheduled) | 760 if (gcState() != IdleGCScheduled) |
| 717 return; | 761 return; |
| 718 | 762 |
| 719 double idleDeltaInSeconds = deadlineSeconds - monotonicallyIncreasingTime(); | 763 double idleDeltaInSeconds = deadlineSeconds - monotonicallyIncreasingTime(); |
| 720 TRACE_EVENT2("blink_gc", "ThreadState::performIdleGC", "idleDeltaInSeconds",
idleDeltaInSeconds, "estimatedMarkingTime", m_heap->heapStats().estimatedMarkin
gTime()); | 764 TRACE_EVENT2("blink_gc", "ThreadState::performIdleGC", "idleDeltaInSeconds",
idleDeltaInSeconds, "estimatedMarkingTime", ThreadHeap::heapStats().estimatedMa
rkingTime()); |
| 721 if (idleDeltaInSeconds <= m_heap->heapStats().estimatedMarkingTime() && !Pla
tform::current()->currentThread()->scheduler()->canExceedIdleDeadlineIfRequired(
)) { | 765 if (idleDeltaInSeconds <= ThreadHeap::heapStats().estimatedMarkingTime() &&
!Platform::current()->currentThread()->scheduler()->canExceedIdleDeadlineIfRequi
red()) { |
| 722 // If marking is estimated to take longer than the deadline and we can't | 766 // If marking is estimated to take longer than the deadline and we can't |
| 723 // exceed the deadline, then reschedule for the next idle period. | 767 // exceed the deadline, then reschedule for the next idle period. |
| 724 scheduleIdleGC(); | 768 scheduleIdleGC(); |
| 725 return; | 769 return; |
| 726 } | 770 } |
| 727 | 771 |
| 728 ThreadHeap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithou
tSweep, BlinkGC::IdleGC); | 772 ThreadHeap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithou
tSweep, BlinkGC::IdleGC); |
| 729 } | 773 } |
| 730 | 774 |
| 731 void ThreadState::performIdleLazySweep(double deadlineSeconds) | 775 void ThreadState::performIdleLazySweep(double deadlineSeconds) |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 913 // Idle time GC will be scheduled by Blink Scheduler. | 957 // Idle time GC will be scheduled by Blink Scheduler. |
| 914 break; | 958 break; |
| 915 default: | 959 default: |
| 916 break; | 960 break; |
| 917 } | 961 } |
| 918 } | 962 } |
| 919 | 963 |
| 920 void ThreadState::flushHeapDoesNotContainCacheIfNeeded() | 964 void ThreadState::flushHeapDoesNotContainCacheIfNeeded() |
| 921 { | 965 { |
| 922 if (m_shouldFlushHeapDoesNotContainCache) { | 966 if (m_shouldFlushHeapDoesNotContainCache) { |
| 923 m_heap->flushHeapDoesNotContainCache(); | 967 ThreadHeap::flushHeapDoesNotContainCache(); |
| 924 m_shouldFlushHeapDoesNotContainCache = false; | 968 m_shouldFlushHeapDoesNotContainCache = false; |
| 925 } | 969 } |
| 926 } | 970 } |
| 927 | 971 |
| 928 void ThreadState::makeConsistentForGC() | 972 void ThreadState::makeConsistentForGC() |
| 929 { | 973 { |
| 930 ASSERT(isInGC()); | 974 ASSERT(isInGC()); |
| 931 TRACE_EVENT0("blink_gc", "ThreadState::makeConsistentForGC"); | 975 TRACE_EVENT0("blink_gc", "ThreadState::makeConsistentForGC"); |
| 932 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) | 976 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) |
| 933 m_arenas[i]->makeConsistentForGC(); | 977 m_arenas[i]->makeConsistentForGC(); |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1080 postSweep(); | 1124 postSweep(); |
| 1081 } | 1125 } |
| 1082 | 1126 |
| 1083 void ThreadState::postSweep() | 1127 void ThreadState::postSweep() |
| 1084 { | 1128 { |
| 1085 ASSERT(checkThread()); | 1129 ASSERT(checkThread()); |
| 1086 ThreadHeap::reportMemoryUsageForTracing(); | 1130 ThreadHeap::reportMemoryUsageForTracing(); |
| 1087 | 1131 |
| 1088 if (isMainThread()) { | 1132 if (isMainThread()) { |
| 1089 double collectionRate = 0; | 1133 double collectionRate = 0; |
| 1090 if (m_heap->heapStats().objectSizeAtLastGC() > 0) | 1134 if (ThreadHeap::heapStats().objectSizeAtLastGC() > 0) |
| 1091 collectionRate = 1 - 1.0 * m_heap->heapStats().markedObjectSize() /
m_heap->heapStats().objectSizeAtLastGC(); | 1135 collectionRate = 1 - 1.0 * ThreadHeap::heapStats().markedObjectSize(
) / ThreadHeap::heapStats().objectSizeAtLastGC(); |
| 1092 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::coll
ectionRate", static_cast<int>(100 * collectionRate)); | 1136 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::coll
ectionRate", static_cast<int>(100 * collectionRate)); |
| 1093 | 1137 |
| 1094 #if PRINT_HEAP_STATS | 1138 #if PRINT_HEAP_STATS |
| 1095 dataLogF("ThreadState::postSweep (collectionRate=%d%%)\n", static_cast<i
nt>(100 * collectionRate)); | 1139 dataLogF("ThreadState::postSweep (collectionRate=%d%%)\n", static_cast<i
nt>(100 * collectionRate)); |
| 1096 #endif | 1140 #endif |
| 1097 | 1141 |
| 1098 // ThreadHeap::markedObjectSize() may be underestimated here if any othe
r | 1142 // ThreadHeap::markedObjectSize() may be underestimated here if any othe
r |
| 1099 // thread has not yet finished lazy sweeping. | 1143 // thread has not yet finished lazy sweeping. |
| 1100 m_heap->heapStats().setMarkedObjectSizeAtLastCompleteSweep(m_heap->heapS
tats().markedObjectSize()); | 1144 ThreadHeap::heapStats().setMarkedObjectSizeAtLastCompleteSweep(ThreadHea
p::heapStats().markedObjectSize()); |
| 1101 | 1145 |
| 1102 DEFINE_STATIC_LOCAL(CustomCountHistogram, objectSizeBeforeGCHistogram, (
"BlinkGC.ObjectSizeBeforeGC", 1, 4 * 1024 * 1024, 50)); | 1146 DEFINE_STATIC_LOCAL(CustomCountHistogram, objectSizeBeforeGCHistogram, (
"BlinkGC.ObjectSizeBeforeGC", 1, 4 * 1024 * 1024, 50)); |
| 1103 objectSizeBeforeGCHistogram.count(m_heap->heapStats().objectSizeAtLastGC
() / 1024); | 1147 objectSizeBeforeGCHistogram.count(ThreadHeap::heapStats().objectSizeAtLa
stGC() / 1024); |
| 1104 DEFINE_STATIC_LOCAL(CustomCountHistogram, objectSizeAfterGCHistogram, ("
BlinkGC.ObjectSizeAfterGC", 1, 4 * 1024 * 1024, 50)); | 1148 DEFINE_STATIC_LOCAL(CustomCountHistogram, objectSizeAfterGCHistogram, ("
BlinkGC.ObjectSizeAfterGC", 1, 4 * 1024 * 1024, 50)); |
| 1105 objectSizeAfterGCHistogram.count(m_heap->heapStats().markedObjectSize()
/ 1024); | 1149 objectSizeAfterGCHistogram.count(ThreadHeap::heapStats().markedObjectSiz
e() / 1024); |
| 1106 DEFINE_STATIC_LOCAL(CustomCountHistogram, collectionRateHistogram, ("Bli
nkGC.CollectionRate", 1, 100, 20)); | 1150 DEFINE_STATIC_LOCAL(CustomCountHistogram, collectionRateHistogram, ("Bli
nkGC.CollectionRate", 1, 100, 20)); |
| 1107 collectionRateHistogram.count(static_cast<int>(100 * collectionRate)); | 1151 collectionRateHistogram.count(static_cast<int>(100 * collectionRate)); |
| 1108 DEFINE_STATIC_LOCAL(CustomCountHistogram, timeForSweepHistogram, ("Blink
GC.TimeForSweepingAllObjects", 1, 10 * 1000, 50)); | 1152 DEFINE_STATIC_LOCAL(CustomCountHistogram, timeForSweepHistogram, ("Blink
GC.TimeForSweepingAllObjects", 1, 10 * 1000, 50)); |
| 1109 timeForSweepHistogram.count(m_accumulatedSweepingTime); | 1153 timeForSweepHistogram.count(m_accumulatedSweepingTime); |
| 1110 | 1154 |
| 1111 | 1155 |
| 1112 #define COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(GCReason) \ | 1156 #define COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(GCReason) \ |
| 1113 case BlinkGC::GCReason: { \ | 1157 case BlinkGC::GCReason: { \ |
| 1114 DEFINE_STATIC_LOCAL(CustomCountHistogram, histogram, \ | 1158 DEFINE_STATIC_LOCAL(CustomCountHistogram, histogram, \ |
| 1115 ("BlinkGC.CollectionRate_" #GCReason, 1, 100, 20)); \ | 1159 ("BlinkGC.CollectionRate_" #GCReason, 1, 100, 20)); \ |
| 1116 histogram.count(static_cast<int>(100 * collectionRate)); \ | 1160 histogram.count(static_cast<int>(100 * collectionRate)); \ |
| 1117 break; \ | 1161 break; \ |
| 1118 } | 1162 } |
| 1119 | 1163 |
| 1120 switch (m_heap->lastGCReason()) { | 1164 switch (ThreadHeap::lastGCReason()) { |
| 1121 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(IdleGC) | 1165 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(IdleGC) |
| 1122 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(PreciseGC) | 1166 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(PreciseGC) |
| 1123 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(ConservativeGC) | 1167 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(ConservativeGC) |
| 1124 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(ForcedGC) | 1168 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(ForcedGC) |
| 1125 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(MemoryPressureGC) | 1169 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(MemoryPressureGC) |
| 1126 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(PageNavigationGC) | 1170 COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(PageNavigationGC) |
| 1127 default: | 1171 default: |
| 1128 break; | 1172 break; |
| 1129 } | 1173 } |
| 1130 } | 1174 } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1164 #endif | 1208 #endif |
| 1165 | 1209 |
| 1166 size_t ThreadState::objectPayloadSizeForTesting() | 1210 size_t ThreadState::objectPayloadSizeForTesting() |
| 1167 { | 1211 { |
| 1168 size_t objectPayloadSize = 0; | 1212 size_t objectPayloadSize = 0; |
| 1169 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) | 1213 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) |
| 1170 objectPayloadSize += m_arenas[i]->objectPayloadSizeForTesting(); | 1214 objectPayloadSize += m_arenas[i]->objectPayloadSizeForTesting(); |
| 1171 return objectPayloadSize; | 1215 return objectPayloadSize; |
| 1172 } | 1216 } |
| 1173 | 1217 |
| 1218 bool ThreadState::stopThreads() |
| 1219 { |
| 1220 return s_safePointBarrier->parkOthers(); |
| 1221 } |
| 1222 |
| 1223 void ThreadState::resumeThreads() |
| 1224 { |
| 1225 s_safePointBarrier->resumeOthers(); |
| 1226 } |
| 1227 |
| 1174 void ThreadState::safePoint(BlinkGC::StackState stackState) | 1228 void ThreadState::safePoint(BlinkGC::StackState stackState) |
| 1175 { | 1229 { |
| 1176 ASSERT(checkThread()); | 1230 ASSERT(checkThread()); |
| 1177 ThreadHeap::reportMemoryUsageForTracing(); | 1231 ThreadHeap::reportMemoryUsageForTracing(); |
| 1178 | 1232 |
| 1179 runScheduledGC(stackState); | 1233 runScheduledGC(stackState); |
| 1180 ASSERT(!m_atSafePoint); | 1234 ASSERT(!m_atSafePoint); |
| 1181 m_stackState = stackState; | 1235 m_stackState = stackState; |
| 1182 m_atSafePoint = true; | 1236 m_atSafePoint = true; |
| 1183 m_heap->checkAndPark(this, nullptr); | 1237 s_safePointBarrier->checkAndPark(this); |
| 1184 m_atSafePoint = false; | 1238 m_atSafePoint = false; |
| 1185 m_stackState = BlinkGC::HeapPointersOnStack; | 1239 m_stackState = BlinkGC::HeapPointersOnStack; |
| 1186 preSweep(); | 1240 preSweep(); |
| 1187 } | 1241 } |
| 1188 | 1242 |
| 1189 #ifdef ADDRESS_SANITIZER | 1243 #ifdef ADDRESS_SANITIZER |
| 1190 // When we are running under AddressSanitizer with detect_stack_use_after_return
=1 | 1244 // When we are running under AddressSanitizer with detect_stack_use_after_return
=1 |
| 1191 // then stack marker obtained from SafePointScope will point into a fake stack. | 1245 // then stack marker obtained from SafePointScope will point into a fake stack. |
| 1192 // Detect this case by checking if it falls in between current stack frame | 1246 // Detect this case by checking if it falls in between current stack frame |
| 1193 // and stack start and use an arbitrary high enough value for it. | 1247 // and stack start and use an arbitrary high enough value for it. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1217 #ifdef ADDRESS_SANITIZER | 1271 #ifdef ADDRESS_SANITIZER |
| 1218 if (stackState == BlinkGC::HeapPointersOnStack) | 1272 if (stackState == BlinkGC::HeapPointersOnStack) |
| 1219 scopeMarker = adjustScopeMarkerForAdressSanitizer(scopeMarker); | 1273 scopeMarker = adjustScopeMarkerForAdressSanitizer(scopeMarker); |
| 1220 #endif | 1274 #endif |
| 1221 ASSERT(stackState == BlinkGC::NoHeapPointersOnStack || scopeMarker); | 1275 ASSERT(stackState == BlinkGC::NoHeapPointersOnStack || scopeMarker); |
| 1222 runScheduledGC(stackState); | 1276 runScheduledGC(stackState); |
| 1223 ASSERT(!m_atSafePoint); | 1277 ASSERT(!m_atSafePoint); |
| 1224 m_atSafePoint = true; | 1278 m_atSafePoint = true; |
| 1225 m_stackState = stackState; | 1279 m_stackState = stackState; |
| 1226 m_safePointScopeMarker = scopeMarker; | 1280 m_safePointScopeMarker = scopeMarker; |
| 1227 m_heap->enterSafePoint(this); | 1281 s_safePointBarrier->enterSafePoint(this); |
| 1228 } | 1282 } |
| 1229 | 1283 |
| 1230 void ThreadState::leaveSafePoint(SafePointAwareMutexLocker* locker) | 1284 void ThreadState::leaveSafePoint(SafePointAwareMutexLocker* locker) |
| 1231 { | 1285 { |
| 1232 ASSERT(checkThread()); | 1286 ASSERT(checkThread()); |
| 1233 ASSERT(m_atSafePoint); | 1287 ASSERT(m_atSafePoint); |
| 1234 m_heap->leaveSafePoint(this, locker); | 1288 s_safePointBarrier->leaveSafePoint(this, locker); |
| 1235 m_atSafePoint = false; | 1289 m_atSafePoint = false; |
| 1236 m_stackState = BlinkGC::HeapPointersOnStack; | 1290 m_stackState = BlinkGC::HeapPointersOnStack; |
| 1237 clearSafePointScopeMarker(); | 1291 clearSafePointScopeMarker(); |
| 1238 preSweep(); | 1292 preSweep(); |
| 1239 } | 1293 } |
| 1240 | 1294 |
| 1241 void ThreadState::reportMemoryToV8() | 1295 void ThreadState::reportMemoryToV8() |
| 1242 { | 1296 { |
| 1243 if (!m_isolate) | 1297 if (!m_isolate) |
| 1244 return; | 1298 return; |
| 1245 | 1299 |
| 1246 size_t currentHeapSize = m_allocatedObjectSize + m_markedObjectSize; | 1300 size_t currentHeapSize = m_allocatedObjectSize + m_markedObjectSize; |
| 1247 int64_t diff = static_cast<int64_t>(currentHeapSize) - static_cast<int64_t>(
m_reportedMemoryToV8); | 1301 int64_t diff = static_cast<int64_t>(currentHeapSize) - static_cast<int64_t>(
m_reportedMemoryToV8); |
| 1248 m_isolate->AdjustAmountOfExternalAllocatedMemory(diff); | 1302 m_isolate->AdjustAmountOfExternalAllocatedMemory(diff); |
| 1249 m_reportedMemoryToV8 = currentHeapSize; | 1303 m_reportedMemoryToV8 = currentHeapSize; |
| 1250 } | 1304 } |
| 1251 | 1305 |
| 1252 void ThreadState::resetHeapCounters() | 1306 void ThreadState::resetHeapCounters() |
| 1253 { | 1307 { |
| 1254 m_allocatedObjectSize = 0; | 1308 m_allocatedObjectSize = 0; |
| 1255 m_markedObjectSize = 0; | 1309 m_markedObjectSize = 0; |
| 1256 } | 1310 } |
| 1257 | 1311 |
| 1258 void ThreadState::increaseAllocatedObjectSize(size_t delta) | 1312 void ThreadState::increaseAllocatedObjectSize(size_t delta) |
| 1259 { | 1313 { |
| 1260 m_allocatedObjectSize += delta; | 1314 m_allocatedObjectSize += delta; |
| 1261 m_heap->heapStats().increaseAllocatedObjectSize(delta); | 1315 ThreadHeap::heapStats().increaseAllocatedObjectSize(delta); |
| 1262 } | 1316 } |
| 1263 | 1317 |
| 1264 void ThreadState::decreaseAllocatedObjectSize(size_t delta) | 1318 void ThreadState::decreaseAllocatedObjectSize(size_t delta) |
| 1265 { | 1319 { |
| 1266 m_allocatedObjectSize -= delta; | 1320 m_allocatedObjectSize -= delta; |
| 1267 m_heap->heapStats().decreaseAllocatedObjectSize(delta); | 1321 ThreadHeap::heapStats().decreaseAllocatedObjectSize(delta); |
| 1268 } | 1322 } |
| 1269 | 1323 |
| 1270 void ThreadState::increaseMarkedObjectSize(size_t delta) | 1324 void ThreadState::increaseMarkedObjectSize(size_t delta) |
| 1271 { | 1325 { |
| 1272 m_markedObjectSize += delta; | 1326 m_markedObjectSize += delta; |
| 1273 m_heap->heapStats().increaseMarkedObjectSize(delta); | 1327 ThreadHeap::heapStats().increaseMarkedObjectSize(delta); |
| 1274 } | 1328 } |
| 1275 | 1329 |
| 1276 void ThreadState::copyStackUntilSafePointScope() | 1330 void ThreadState::copyStackUntilSafePointScope() |
| 1277 { | 1331 { |
| 1278 if (!m_safePointScopeMarker || m_stackState == BlinkGC::NoHeapPointersOnStac
k) | 1332 if (!m_safePointScopeMarker || m_stackState == BlinkGC::NoHeapPointersOnStac
k) |
| 1279 return; | 1333 return; |
| 1280 | 1334 |
| 1281 Address* to = reinterpret_cast<Address*>(m_safePointScopeMarker); | 1335 Address* to = reinterpret_cast<Address*>(m_safePointScopeMarker); |
| 1282 Address* from = reinterpret_cast<Address*>(m_endOfStack); | 1336 Address* from = reinterpret_cast<Address*>(m_endOfStack); |
| 1283 RELEASE_ASSERT(from < to); | 1337 RELEASE_ASSERT(from < to); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1297 for (size_t i = 0; i < slotCount; ++i) { | 1351 for (size_t i = 0; i < slotCount; ++i) { |
| 1298 m_safePointStackCopy[i] = from[i]; | 1352 m_safePointStackCopy[i] = from[i]; |
| 1299 } | 1353 } |
| 1300 } | 1354 } |
| 1301 | 1355 |
| 1302 void ThreadState::addInterruptor(PassOwnPtr<BlinkGCInterruptor> interruptor) | 1356 void ThreadState::addInterruptor(PassOwnPtr<BlinkGCInterruptor> interruptor) |
| 1303 { | 1357 { |
| 1304 ASSERT(checkThread()); | 1358 ASSERT(checkThread()); |
| 1305 SafePointScope scope(BlinkGC::HeapPointersOnStack); | 1359 SafePointScope scope(BlinkGC::HeapPointersOnStack); |
| 1306 { | 1360 { |
| 1307 MutexLocker locker(m_heap->threadAttachMutex()); | 1361 MutexLocker locker(threadAttachMutex()); |
| 1308 m_interruptors.append(interruptor); | 1362 m_interruptors.append(interruptor); |
| 1309 } | 1363 } |
| 1310 } | 1364 } |
| 1311 | 1365 |
| 1312 void ThreadState::registerStaticPersistentNode(PersistentNode* node, PersistentC
learCallback callback) | 1366 void ThreadState::registerStaticPersistentNode(PersistentNode* node, PersistentC
learCallback callback) |
| 1313 { | 1367 { |
| 1314 #if defined(LEAK_SANITIZER) | 1368 #if defined(LEAK_SANITIZER) |
| 1315 if (m_disabledStaticPersistentsRegistration) | 1369 if (m_disabledStaticPersistentsRegistration) |
| 1316 return; | 1370 return; |
| 1317 #endif | 1371 #endif |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1348 m_disabledStaticPersistentsRegistration++; | 1402 m_disabledStaticPersistentsRegistration++; |
| 1349 } | 1403 } |
| 1350 | 1404 |
| 1351 void ThreadState::leaveStaticReferenceRegistrationDisabledScope() | 1405 void ThreadState::leaveStaticReferenceRegistrationDisabledScope() |
| 1352 { | 1406 { |
| 1353 ASSERT(m_disabledStaticPersistentsRegistration); | 1407 ASSERT(m_disabledStaticPersistentsRegistration); |
| 1354 m_disabledStaticPersistentsRegistration--; | 1408 m_disabledStaticPersistentsRegistration--; |
| 1355 } | 1409 } |
| 1356 #endif | 1410 #endif |
| 1357 | 1411 |
| 1412 ThreadState::AttachedThreadStateSet& ThreadState::attachedThreads() |
| 1413 { |
| 1414 DEFINE_STATIC_LOCAL(AttachedThreadStateSet, threads, ()); |
| 1415 return threads; |
| 1416 } |
| 1417 |
| 1358 void ThreadState::lockThreadAttachMutex() | 1418 void ThreadState::lockThreadAttachMutex() |
| 1359 { | 1419 { |
| 1360 m_heap->threadAttachMutex().lock(); | 1420 threadAttachMutex().lock(); |
| 1361 } | 1421 } |
| 1362 | 1422 |
| 1363 void ThreadState::unlockThreadAttachMutex() | 1423 void ThreadState::unlockThreadAttachMutex() |
| 1364 { | 1424 { |
| 1365 m_heap->threadAttachMutex().unlock(); | 1425 threadAttachMutex().unlock(); |
| 1366 } | 1426 } |
| 1367 | 1427 |
| 1368 void ThreadState::invokePreFinalizers() | 1428 void ThreadState::invokePreFinalizers() |
| 1369 { | 1429 { |
| 1370 ASSERT(checkThread()); | 1430 ASSERT(checkThread()); |
| 1371 ASSERT(!sweepForbidden()); | 1431 ASSERT(!sweepForbidden()); |
| 1372 TRACE_EVENT0("blink_gc", "ThreadState::invokePreFinalizers"); | 1432 TRACE_EVENT0("blink_gc", "ThreadState::invokePreFinalizers"); |
| 1373 | 1433 |
| 1374 double startTime = WTF::currentTimeMS(); | 1434 double startTime = WTF::currentTimeMS(); |
| 1375 if (!m_orderedPreFinalizers.isEmpty()) { | 1435 if (!m_orderedPreFinalizers.isEmpty()) { |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1511 threadDump->addScalar("dead_count", "objects", totalDeadCount); | 1571 threadDump->addScalar("dead_count", "objects", totalDeadCount); |
| 1512 threadDump->addScalar("live_size", "bytes", totalLiveSize); | 1572 threadDump->addScalar("live_size", "bytes", totalLiveSize); |
| 1513 threadDump->addScalar("dead_size", "bytes", totalDeadSize); | 1573 threadDump->addScalar("dead_size", "bytes", totalDeadSize); |
| 1514 | 1574 |
| 1515 WebMemoryAllocatorDump* heapsDump = BlinkGCMemoryDumpProvider::instance()->c
reateMemoryAllocatorDumpForCurrentGC(heapsDumpName); | 1575 WebMemoryAllocatorDump* heapsDump = BlinkGCMemoryDumpProvider::instance()->c
reateMemoryAllocatorDumpForCurrentGC(heapsDumpName); |
| 1516 WebMemoryAllocatorDump* classesDump = BlinkGCMemoryDumpProvider::instance()-
>createMemoryAllocatorDumpForCurrentGC(classesDumpName); | 1576 WebMemoryAllocatorDump* classesDump = BlinkGCMemoryDumpProvider::instance()-
>createMemoryAllocatorDumpForCurrentGC(classesDumpName); |
| 1517 BlinkGCMemoryDumpProvider::instance()->currentProcessMemoryDump()->addOwners
hipEdge(classesDump->guid(), heapsDump->guid()); | 1577 BlinkGCMemoryDumpProvider::instance()->currentProcessMemoryDump()->addOwners
hipEdge(classesDump->guid(), heapsDump->guid()); |
| 1518 } | 1578 } |
| 1519 | 1579 |
| 1520 } // namespace blink | 1580 } // namespace blink |
| OLD | NEW |