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 |