| 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 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 } | 219 } |
| 220 ASSERT(checkThread()); | 220 ASSERT(checkThread()); |
| 221 | 221 |
| 222 // Finish sweeping. | 222 // Finish sweeping. |
| 223 completeSweep(); | 223 completeSweep(); |
| 224 | 224 |
| 225 // From here on ignore all conservatively discovered | 225 // From here on ignore all conservatively discovered |
| 226 // pointers into the heap owned by this thread. | 226 // pointers into the heap owned by this thread. |
| 227 m_isTerminating = true; | 227 m_isTerminating = true; |
| 228 | 228 |
| 229 ThreadState::callThreadShutdownHooks(); | 229 releaseStaticPersistentNodes(); |
| 230 | 230 |
| 231 // Set the terminate flag on all heap pages of this thread. This is used to | 231 // Set the terminate flag on all heap pages of this thread. This is used to |
| 232 // ensure we don't trace pages on other threads that are not part of the | 232 // ensure we don't trace pages on other threads that are not part of the |
| 233 // thread local GC. | 233 // thread local GC. |
| 234 prepareForThreadStateTermination(); | 234 prepareForThreadStateTermination(); |
| 235 | 235 |
| 236 ProcessHeap::crossThreadPersistentRegion().prepareForThreadStateTermination(
this); | 236 ProcessHeap::crossThreadPersistentRegion().prepareForThreadStateTermination(
this); |
| 237 | 237 |
| 238 // Do thread local GC's as long as the count of thread local Persistents | 238 // Do thread local GC's as long as the count of thread local Persistents |
| 239 // changes and is above zero. | 239 // changes and is above zero. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 254 | 254 |
| 255 // Add pages to the orphaned page pool to ensure any global GCs from this po
int | 255 // Add pages to the orphaned page pool to ensure any global GCs from this po
int |
| 256 // on will not trace objects on this thread's arenas. | 256 // on will not trace objects on this thread's arenas. |
| 257 cleanupPages(); | 257 cleanupPages(); |
| 258 } | 258 } |
| 259 | 259 |
| 260 void ThreadState::cleanupMainThread() | 260 void ThreadState::cleanupMainThread() |
| 261 { | 261 { |
| 262 ASSERT(isMainThread()); | 262 ASSERT(isMainThread()); |
| 263 | 263 |
| 264 releaseStaticPersistentNodes(); |
| 265 |
| 264 #if defined(LEAK_SANITIZER) | 266 #if defined(LEAK_SANITIZER) |
| 265 // If LSan is about to perform leak detection, release all the registered | 267 // If LSan is about to perform leak detection, after having released all |
| 266 // static Persistent<> root references to global caches that Blink keeps, | 268 // the registered static Persistent<> root references to global caches |
| 267 // followed by GCs to clear out all they referred to. | 269 // that Blink keeps, follow up with a round of GCs to clear out all |
| 270 // what they referred to. |
| 268 // | 271 // |
| 269 // This is not needed for caches over non-Oilpan objects, as they're | 272 // This is not needed for caches over non-Oilpan objects, as they're |
| 270 // not scanned by LSan due to being held in non-global storage | 273 // not scanned by LSan due to being held in non-global storage |
| 271 // ("static" references inside functions/methods.) | 274 // ("static" references inside functions/methods.) |
| 272 releaseStaticPersistentNodes(); | |
| 273 ThreadHeap::collectAllGarbage(); | 275 ThreadHeap::collectAllGarbage(); |
| 274 #endif | 276 #endif |
| 275 | 277 |
| 276 // Finish sweeping before shutting down V8. Otherwise, some destructor | 278 // Finish sweeping before shutting down V8. Otherwise, some destructor |
| 277 // may access V8 and cause crashes. | 279 // may access V8 and cause crashes. |
| 278 completeSweep(); | 280 completeSweep(); |
| 279 | 281 |
| 280 // It is unsafe to trigger GCs after this point because some | 282 // It is unsafe to trigger GCs after this point because some |
| 281 // destructor may access already-detached V8 and cause crashes. | 283 // destructor may access already-detached V8 and cause crashes. |
| 282 // Also it is useless. So we forbid GCs. | 284 // Also it is useless. So we forbid GCs. |
| 283 enterGCForbiddenScope(); | 285 enterGCForbiddenScope(); |
| 284 } | 286 } |
| 285 | 287 |
| 286 void ThreadState::detachMainThread() | 288 void ThreadState::detachMainThread() |
| 287 { | 289 { |
| 288 // Enter a safe point before trying to acquire threadAttachMutex | 290 // Enter a safe point before trying to acquire threadAttachMutex |
| 289 // to avoid dead lock if another thread is preparing for GC, has acquired | 291 // to avoid dead lock if another thread is preparing for GC, has acquired |
| 290 // threadAttachMutex and waiting for other threads to pause or reach a | 292 // threadAttachMutex and waiting for other threads to pause or reach a |
| 291 // safepoint. | 293 // safepoint. |
| 292 ThreadState* state = mainThreadState(); | 294 ThreadState* state = mainThreadState(); |
| 293 ASSERT(!state->isSweepingInProgress()); | 295 ASSERT(!state->isSweepingInProgress()); |
| 294 | 296 |
| 295 state->heap().detach(state); | 297 state->heap().detach(state); |
| 296 state->~ThreadState(); | 298 state->~ThreadState(); |
| 297 } | 299 } |
| 298 | 300 |
| 299 void ThreadState::callThreadShutdownHooks() | |
| 300 { | |
| 301 // Invoke the cleanup hooks. This gives an opportunity to release any | |
| 302 // persistent handles that may exist, e.g. in thread-specific static | |
| 303 // locals. | |
| 304 for (const OwnPtr<SameThreadClosure>& hook : m_threadShutdownHooks) | |
| 305 (*hook)(); | |
| 306 } | |
| 307 | |
| 308 void ThreadState::detachCurrentThread() | 301 void ThreadState::detachCurrentThread() |
| 309 { | 302 { |
| 310 ThreadState* state = current(); | 303 ThreadState* state = current(); |
| 311 state->heap().detach(state); | 304 state->heap().detach(state); |
| 312 RELEASE_ASSERT(state->gcState() == ThreadState::NoGCScheduled); | 305 RELEASE_ASSERT(state->gcState() == ThreadState::NoGCScheduled); |
| 313 delete state; | 306 delete state; |
| 314 } | 307 } |
| 315 | 308 |
| 316 NO_SANITIZE_ADDRESS | 309 NO_SANITIZE_ADDRESS |
| 317 void ThreadState::visitAsanFakeStackForPointer(Visitor* visitor, Address ptr) | 310 void ThreadState::visitAsanFakeStackForPointer(Visitor* visitor, Address ptr) |
| (...skipping 997 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1315 void ThreadState::addInterruptor(PassOwnPtr<BlinkGCInterruptor> interruptor) | 1308 void ThreadState::addInterruptor(PassOwnPtr<BlinkGCInterruptor> interruptor) |
| 1316 { | 1309 { |
| 1317 ASSERT(checkThread()); | 1310 ASSERT(checkThread()); |
| 1318 SafePointScope scope(BlinkGC::HeapPointersOnStack); | 1311 SafePointScope scope(BlinkGC::HeapPointersOnStack); |
| 1319 { | 1312 { |
| 1320 MutexLocker locker(m_heap->threadAttachMutex()); | 1313 MutexLocker locker(m_heap->threadAttachMutex()); |
| 1321 m_interruptors.append(interruptor); | 1314 m_interruptors.append(interruptor); |
| 1322 } | 1315 } |
| 1323 } | 1316 } |
| 1324 | 1317 |
| 1325 void ThreadState::registerThreadShutdownHook(PassOwnPtr<SameThreadClosure> hook) | 1318 void ThreadState::registerStaticPersistentNode(PersistentNode* node, PersistentC
learCallback callback) |
| 1326 { | 1319 { |
| 1327 ASSERT(checkThread()); | |
| 1328 ASSERT(!isTerminating()); | |
| 1329 m_threadShutdownHooks.append(hook); | |
| 1330 } | |
| 1331 | |
| 1332 #if defined(LEAK_SANITIZER) | 1320 #if defined(LEAK_SANITIZER) |
| 1333 void ThreadState::registerStaticPersistentNode(PersistentNode* node) | |
| 1334 { | |
| 1335 if (m_disabledStaticPersistentsRegistration) | 1321 if (m_disabledStaticPersistentsRegistration) |
| 1336 return; | 1322 return; |
| 1323 #endif |
| 1337 | 1324 |
| 1338 ASSERT(!m_staticPersistents.contains(node)); | 1325 ASSERT(!m_staticPersistents.contains(node)); |
| 1339 m_staticPersistents.add(node); | 1326 m_staticPersistents.add(node, callback); |
| 1340 } | 1327 } |
| 1341 | 1328 |
| 1342 void ThreadState::releaseStaticPersistentNodes() | 1329 void ThreadState::releaseStaticPersistentNodes() |
| 1343 { | 1330 { |
| 1344 for (PersistentNode* node : m_staticPersistents) | 1331 HashMap<PersistentNode*, ThreadState::PersistentClearCallback> staticPersist
ents; |
| 1345 getPersistentRegion()->freePersistentNode(node); | 1332 staticPersistents.swap(m_staticPersistents); |
| 1346 | 1333 |
| 1347 m_staticPersistents.clear(); | 1334 PersistentRegion* persistentRegion = getPersistentRegion(); |
| 1335 for (const auto& it : staticPersistents) |
| 1336 persistentRegion->releasePersistentNode(it.key, it.value); |
| 1348 } | 1337 } |
| 1349 | 1338 |
| 1339 void ThreadState::freePersistentNode(PersistentNode* persistentNode) |
| 1340 { |
| 1341 PersistentRegion* persistentRegion = getPersistentRegion(); |
| 1342 persistentRegion->freePersistentNode(persistentNode); |
| 1343 // Do not allow static persistents to be freed before |
| 1344 // they're all released in releaseStaticPersistentNodes(). |
| 1345 // |
| 1346 // There's no fundamental reason why this couldn't be supported, |
| 1347 // but no known use for it. |
| 1348 ASSERT(!m_staticPersistents.contains(persistentNode)); |
| 1349 } |
| 1350 |
| 1351 #if defined(LEAK_SANITIZER) |
| 1350 void ThreadState::enterStaticReferenceRegistrationDisabledScope() | 1352 void ThreadState::enterStaticReferenceRegistrationDisabledScope() |
| 1351 { | 1353 { |
| 1352 m_disabledStaticPersistentsRegistration++; | 1354 m_disabledStaticPersistentsRegistration++; |
| 1353 } | 1355 } |
| 1354 | 1356 |
| 1355 void ThreadState::leaveStaticReferenceRegistrationDisabledScope() | 1357 void ThreadState::leaveStaticReferenceRegistrationDisabledScope() |
| 1356 { | 1358 { |
| 1357 ASSERT(m_disabledStaticPersistentsRegistration); | 1359 ASSERT(m_disabledStaticPersistentsRegistration); |
| 1358 m_disabledStaticPersistentsRegistration--; | 1360 m_disabledStaticPersistentsRegistration--; |
| 1359 } | 1361 } |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1515 threadDump->addScalar("dead_count", "objects", totalDeadCount); | 1517 threadDump->addScalar("dead_count", "objects", totalDeadCount); |
| 1516 threadDump->addScalar("live_size", "bytes", totalLiveSize); | 1518 threadDump->addScalar("live_size", "bytes", totalLiveSize); |
| 1517 threadDump->addScalar("dead_size", "bytes", totalDeadSize); | 1519 threadDump->addScalar("dead_size", "bytes", totalDeadSize); |
| 1518 | 1520 |
| 1519 WebMemoryAllocatorDump* heapsDump = BlinkGCMemoryDumpProvider::instance()->c
reateMemoryAllocatorDumpForCurrentGC(heapsDumpName); | 1521 WebMemoryAllocatorDump* heapsDump = BlinkGCMemoryDumpProvider::instance()->c
reateMemoryAllocatorDumpForCurrentGC(heapsDumpName); |
| 1520 WebMemoryAllocatorDump* classesDump = BlinkGCMemoryDumpProvider::instance()-
>createMemoryAllocatorDumpForCurrentGC(classesDumpName); | 1522 WebMemoryAllocatorDump* classesDump = BlinkGCMemoryDumpProvider::instance()-
>createMemoryAllocatorDumpForCurrentGC(classesDumpName); |
| 1521 BlinkGCMemoryDumpProvider::instance()->currentProcessMemoryDump()->addOwners
hipEdge(classesDump->guid(), heapsDump->guid()); | 1523 BlinkGCMemoryDumpProvider::instance()->currentProcessMemoryDump()->addOwners
hipEdge(classesDump->guid(), heapsDump->guid()); |
| 1522 } | 1524 } |
| 1523 | 1525 |
| 1524 } // namespace blink | 1526 } // namespace blink |
| OLD | NEW |