| 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 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 460 return false; | 460 return false; |
| 461 } | 461 } |
| 462 | 462 |
| 463 void ThreadState::threadLocalWeakProcessing() | 463 void ThreadState::threadLocalWeakProcessing() |
| 464 { | 464 { |
| 465 ASSERT(checkThread()); | 465 ASSERT(checkThread()); |
| 466 ASSERT(!sweepForbidden()); | 466 ASSERT(!sweepForbidden()); |
| 467 TRACE_EVENT0("blink_gc", "ThreadState::threadLocalWeakProcessing"); | 467 TRACE_EVENT0("blink_gc", "ThreadState::threadLocalWeakProcessing"); |
| 468 double startTime = WTF::currentTimeMS(); | 468 double startTime = WTF::currentTimeMS(); |
| 469 | 469 |
| 470 SweepForbiddenScope forbiddenScope(this); | 470 SweepForbiddenScope sweepForbiddenScope(this); |
| 471 if (isMainThread()) | 471 ScriptForbiddenIfMainThreadScope scriptForbiddenScope; |
| 472 ScriptForbiddenScope::enter(); | |
| 473 | 472 |
| 474 // Disallow allocation during weak processing. | 473 // Disallow allocation during weak processing. |
| 475 // It would be technically safe to allow allocations, but it is unsafe | 474 // It would be technically safe to allow allocations, but it is unsafe |
| 476 // to mutate an object graph in a way in which a dead object gets | 475 // to mutate an object graph in a way in which a dead object gets |
| 477 // resurrected or mutate a HashTable (because HashTable's weak processing | 476 // resurrected or mutate a HashTable (because HashTable's weak processing |
| 478 // assumes that the HashTable hasn't been mutated since the latest marking). | 477 // assumes that the HashTable hasn't been mutated since the latest marking). |
| 479 // Due to the complexity, we just forbid allocations. | 478 // Due to the complexity, we just forbid allocations. |
| 480 NoAllocationScope noAllocationScope(this); | 479 NoAllocationScope noAllocationScope(this); |
| 481 | 480 |
| 482 MarkingVisitor<Visitor::WeakProcessing> weakProcessingVisitor; | 481 MarkingVisitor<Visitor::WeakProcessing> weakProcessingVisitor; |
| 483 | 482 |
| 484 // Perform thread-specific weak processing. | 483 // Perform thread-specific weak processing. |
| 485 while (popAndInvokeThreadLocalWeakCallback(&weakProcessingVisitor)) { } | 484 while (popAndInvokeThreadLocalWeakCallback(&weakProcessingVisitor)) { } |
| 486 | 485 |
| 487 if (isMainThread()) { | 486 if (isMainThread()) { |
| 488 ScriptForbiddenScope::exit(); | |
| 489 double timeForThreadLocalWeakProcessing = WTF::currentTimeMS() - startTi
me; | 487 double timeForThreadLocalWeakProcessing = WTF::currentTimeMS() - startTi
me; |
| 490 Platform::current()->histogramCustomCounts("BlinkGC.timeForThreadLocalWe
akProcessing", timeForThreadLocalWeakProcessing, 1, 10 * 1000, 50); | 488 Platform::current()->histogramCustomCounts("BlinkGC.timeForThreadLocalWe
akProcessing", timeForThreadLocalWeakProcessing, 1, 10 * 1000, 50); |
| 491 } | 489 } |
| 492 } | 490 } |
| 493 | 491 |
| 494 CrossThreadPersistentRegion& ThreadState::crossThreadPersistentRegion() | 492 CrossThreadPersistentRegion& ThreadState::crossThreadPersistentRegion() |
| 495 { | 493 { |
| 496 AtomicallyInitializedStaticReference(CrossThreadPersistentRegion, persistent
Region, new CrossThreadPersistentRegion()); | 494 AtomicallyInitializedStaticReference(CrossThreadPersistentRegion, persistent
Region, new CrossThreadPersistentRegion()); |
| 497 return persistentRegion; | 495 return persistentRegion; |
| 498 } | 496 } |
| (...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 777 // the check just in case. | 775 // the check just in case. |
| 778 if (sweepForbidden()) | 776 if (sweepForbidden()) |
| 779 return; | 777 return; |
| 780 | 778 |
| 781 TRACE_EVENT1("blink_gc", "ThreadState::performIdleLazySweep", "idleDeltaInSe
conds", deadlineSeconds - Platform::current()->monotonicallyIncreasingTimeSecond
s()); | 779 TRACE_EVENT1("blink_gc", "ThreadState::performIdleLazySweep", "idleDeltaInSe
conds", deadlineSeconds - Platform::current()->monotonicallyIncreasingTimeSecond
s()); |
| 782 | 780 |
| 783 bool sweepCompleted = true; | 781 bool sweepCompleted = true; |
| 784 SweepForbiddenScope scope(this); | 782 SweepForbiddenScope scope(this); |
| 785 { | 783 { |
| 786 double startTime = WTF::currentTimeMS(); | 784 double startTime = WTF::currentTimeMS(); |
| 787 if (isMainThread()) | 785 ScriptForbiddenIfMainThreadScope scriptForbiddenScope; |
| 788 ScriptForbiddenScope::enter(); | |
| 789 | 786 |
| 790 for (int i = 0; i < BlinkGC::NumberOfHeaps; i++) { | 787 for (int i = 0; i < BlinkGC::NumberOfHeaps; i++) { |
| 791 // lazySweepWithDeadline() won't check the deadline until it sweeps | 788 // lazySweepWithDeadline() won't check the deadline until it sweeps |
| 792 // 10 pages. So we give a small slack for safety. | 789 // 10 pages. So we give a small slack for safety. |
| 793 double slack = 0.001; | 790 double slack = 0.001; |
| 794 double remainingBudget = deadlineSeconds - slack - Platform::current
()->monotonicallyIncreasingTimeSeconds(); | 791 double remainingBudget = deadlineSeconds - slack - Platform::current
()->monotonicallyIncreasingTimeSeconds(); |
| 795 if (remainingBudget <= 0 || !m_heaps[i]->lazySweepWithDeadline(deadl
ineSeconds)) { | 792 if (remainingBudget <= 0 || !m_heaps[i]->lazySweepWithDeadline(deadl
ineSeconds)) { |
| 796 // We couldn't finish the sweeping within the deadline. | 793 // We couldn't finish the sweeping within the deadline. |
| 797 // We request another idle task for the remaining sweeping. | 794 // We request another idle task for the remaining sweeping. |
| 798 scheduleIdleLazySweep(); | 795 scheduleIdleLazySweep(); |
| 799 sweepCompleted = false; | 796 sweepCompleted = false; |
| 800 break; | 797 break; |
| 801 } | 798 } |
| 802 } | 799 } |
| 803 | 800 |
| 804 if (isMainThread()) | |
| 805 ScriptForbiddenScope::exit(); | |
| 806 accumulateSweepingTime(WTF::currentTimeMS() - startTime); | 801 accumulateSweepingTime(WTF::currentTimeMS() - startTime); |
| 807 } | 802 } |
| 808 | 803 |
| 809 if (sweepCompleted) | 804 if (sweepCompleted) |
| 810 postSweep(); | 805 postSweep(); |
| 811 } | 806 } |
| 812 | 807 |
| 813 void ThreadState::scheduleIdleGC() | 808 void ThreadState::scheduleIdleGC() |
| 814 { | 809 { |
| 815 // TODO(haraken): Idle GC should be supported in worker threads as well. | 810 // TODO(haraken): Idle GC should be supported in worker threads as well. |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1068 // Some objects need to be finalized promptly and cannot be handled | 1063 // Some objects need to be finalized promptly and cannot be handled |
| 1069 // by lazy sweeping. Keep those in a designated heap and sweep it | 1064 // by lazy sweeping. Keep those in a designated heap and sweep it |
| 1070 // eagerly. | 1065 // eagerly. |
| 1071 ASSERT(isSweepingInProgress()); | 1066 ASSERT(isSweepingInProgress()); |
| 1072 | 1067 |
| 1073 // Mirroring the completeSweep() condition; see its comment. | 1068 // Mirroring the completeSweep() condition; see its comment. |
| 1074 if (sweepForbidden()) | 1069 if (sweepForbidden()) |
| 1075 return; | 1070 return; |
| 1076 | 1071 |
| 1077 SweepForbiddenScope scope(this); | 1072 SweepForbiddenScope scope(this); |
| 1078 { | 1073 ScriptForbiddenIfMainThreadScope scriptForbiddenScope; |
| 1079 double startTime = WTF::currentTimeMS(); | |
| 1080 if (isMainThread()) | |
| 1081 ScriptForbiddenScope::enter(); | |
| 1082 | 1074 |
| 1083 m_heaps[BlinkGC::EagerSweepHeapIndex]->completeSweep(); | 1075 double startTime = WTF::currentTimeMS(); |
| 1084 | 1076 m_heaps[BlinkGC::EagerSweepHeapIndex]->completeSweep(); |
| 1085 if (isMainThread()) | 1077 accumulateSweepingTime(WTF::currentTimeMS() - startTime); |
| 1086 ScriptForbiddenScope::exit(); | |
| 1087 accumulateSweepingTime(WTF::currentTimeMS() - startTime); | |
| 1088 } | |
| 1089 } | 1078 } |
| 1090 | 1079 |
| 1091 void ThreadState::completeSweep() | 1080 void ThreadState::completeSweep() |
| 1092 { | 1081 { |
| 1093 ASSERT(checkThread()); | 1082 ASSERT(checkThread()); |
| 1094 // If we are not in a sweeping phase, there is nothing to do here. | 1083 // If we are not in a sweeping phase, there is nothing to do here. |
| 1095 if (!isSweepingInProgress()) | 1084 if (!isSweepingInProgress()) |
| 1096 return; | 1085 return; |
| 1097 | 1086 |
| 1098 // completeSweep() can be called recursively if finalizers can allocate | 1087 // completeSweep() can be called recursively if finalizers can allocate |
| 1099 // memory and the allocation triggers completeSweep(). This check prevents | 1088 // memory and the allocation triggers completeSweep(). This check prevents |
| 1100 // the sweeping from being executed recursively. | 1089 // the sweeping from being executed recursively. |
| 1101 if (sweepForbidden()) | 1090 if (sweepForbidden()) |
| 1102 return; | 1091 return; |
| 1103 | 1092 |
| 1104 SweepForbiddenScope scope(this); | 1093 SweepForbiddenScope scope(this); |
| 1105 { | 1094 { |
| 1106 if (isMainThread()) | 1095 ScriptForbiddenIfMainThreadScope scriptForbiddenScope; |
| 1107 ScriptForbiddenScope::enter(); | |
| 1108 | 1096 |
| 1109 TRACE_EVENT0("blink_gc", "ThreadState::completeSweep"); | 1097 TRACE_EVENT0("blink_gc", "ThreadState::completeSweep"); |
| 1110 double startTime = WTF::currentTimeMS(); | 1098 double startTime = WTF::currentTimeMS(); |
| 1111 | 1099 |
| 1112 static_assert(BlinkGC::EagerSweepHeapIndex == 0, "Eagerly swept heaps mu
st be processed first."); | 1100 static_assert(BlinkGC::EagerSweepHeapIndex == 0, "Eagerly swept heaps mu
st be processed first."); |
| 1113 for (int i = 0; i < BlinkGC::NumberOfHeaps; i++) | 1101 for (int i = 0; i < BlinkGC::NumberOfHeaps; i++) |
| 1114 m_heaps[i]->completeSweep(); | 1102 m_heaps[i]->completeSweep(); |
| 1115 | 1103 |
| 1116 double timeForCompleteSweep = WTF::currentTimeMS() - startTime; | 1104 double timeForCompleteSweep = WTF::currentTimeMS() - startTime; |
| 1117 accumulateSweepingTime(timeForCompleteSweep); | 1105 accumulateSweepingTime(timeForCompleteSweep); |
| 1118 | 1106 |
| 1119 if (isMainThread()) { | 1107 if (isMainThread()) |
| 1120 ScriptForbiddenScope::exit(); | |
| 1121 Platform::current()->histogramCustomCounts("BlinkGC.CompleteSweep",
timeForCompleteSweep, 1, 10 * 1000, 50); | 1108 Platform::current()->histogramCustomCounts("BlinkGC.CompleteSweep",
timeForCompleteSweep, 1, 10 * 1000, 50); |
| 1122 } | |
| 1123 } | 1109 } |
| 1124 | 1110 |
| 1125 postSweep(); | 1111 postSweep(); |
| 1126 } | 1112 } |
| 1127 | 1113 |
| 1128 void ThreadState::postSweep() | 1114 void ThreadState::postSweep() |
| 1129 { | 1115 { |
| 1130 ASSERT(checkThread()); | 1116 ASSERT(checkThread()); |
| 1131 Heap::reportMemoryUsageForTracing(); | 1117 Heap::reportMemoryUsageForTracing(); |
| 1132 | 1118 |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1333 threadAttachMutex().unlock(); | 1319 threadAttachMutex().unlock(); |
| 1334 } | 1320 } |
| 1335 | 1321 |
| 1336 void ThreadState::invokePreFinalizers() | 1322 void ThreadState::invokePreFinalizers() |
| 1337 { | 1323 { |
| 1338 ASSERT(checkThread()); | 1324 ASSERT(checkThread()); |
| 1339 ASSERT(!sweepForbidden()); | 1325 ASSERT(!sweepForbidden()); |
| 1340 TRACE_EVENT0("blink_gc", "ThreadState::invokePreFinalizers"); | 1326 TRACE_EVENT0("blink_gc", "ThreadState::invokePreFinalizers"); |
| 1341 double startTime = WTF::currentTimeMS(); | 1327 double startTime = WTF::currentTimeMS(); |
| 1342 | 1328 |
| 1343 if (isMainThread()) | 1329 |
| 1344 ScriptForbiddenScope::enter(); | 1330 ScriptForbiddenIfMainThreadScope scriptForbidden; |
| 1345 | 1331 |
| 1346 SweepForbiddenScope forbiddenScope(this); | 1332 SweepForbiddenScope forbiddenScope(this); |
| 1347 Vector<PreFinalizer> deadPreFinalizers; | 1333 Vector<PreFinalizer> deadPreFinalizers; |
| 1348 // Call the pre-finalizers in the reverse order in which they | 1334 // Call the pre-finalizers in the reverse order in which they |
| 1349 // are registered. | 1335 // are registered. |
| 1350 for (auto it = m_orderedPreFinalizers.rbegin(); it != m_orderedPreFinalizers
.rend(); ++it) { | 1336 for (auto it = m_orderedPreFinalizers.rbegin(); it != m_orderedPreFinalizers
.rend(); ++it) { |
| 1351 if (!(it->second)(it->first)) | 1337 if (!(it->second)(it->first)) |
| 1352 continue; | 1338 continue; |
| 1353 deadPreFinalizers.append(*it); | 1339 deadPreFinalizers.append(*it); |
| 1354 } | 1340 } |
| 1355 // FIXME: removeAll is inefficient. It can shrink repeatedly. | 1341 // FIXME: removeAll is inefficient. It can shrink repeatedly. |
| 1356 m_orderedPreFinalizers.removeAll(deadPreFinalizers); | 1342 m_orderedPreFinalizers.removeAll(deadPreFinalizers); |
| 1357 | 1343 |
| 1358 if (isMainThread()) { | 1344 if (isMainThread()) { |
| 1359 ScriptForbiddenScope::exit(); | |
| 1360 double timeForInvokingPreFinalizers = WTF::currentTimeMS() - startTime; | 1345 double timeForInvokingPreFinalizers = WTF::currentTimeMS() - startTime; |
| 1361 Platform::current()->histogramCustomCounts("BlinkGC.TimeForInvokingPreFi
nalizers", timeForInvokingPreFinalizers, 1, 10 * 1000, 50); | 1346 Platform::current()->histogramCustomCounts("BlinkGC.TimeForInvokingPreFi
nalizers", timeForInvokingPreFinalizers, 1, 10 * 1000, 50); |
| 1362 } | 1347 } |
| 1363 } | 1348 } |
| 1364 | 1349 |
| 1365 void ThreadState::clearHeapAges() | 1350 void ThreadState::clearHeapAges() |
| 1366 { | 1351 { |
| 1367 memset(m_heapAges, 0, sizeof(size_t) * BlinkGC::NumberOfHeaps); | 1352 memset(m_heapAges, 0, sizeof(size_t) * BlinkGC::NumberOfHeaps); |
| 1368 memset(m_likelyToBePromptlyFreed.get(), 0, sizeof(int) * likelyToBePromptlyF
reedArraySize); | 1353 memset(m_likelyToBePromptlyFreed.get(), 0, sizeof(int) * likelyToBePromptlyF
reedArraySize); |
| 1369 m_currentHeapAges = 0; | 1354 m_currentHeapAges = 0; |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1483 threadDump->addScalar("dead_count", "objects", totalDeadCount); | 1468 threadDump->addScalar("dead_count", "objects", totalDeadCount); |
| 1484 threadDump->addScalar("live_size", "bytes", totalLiveSize); | 1469 threadDump->addScalar("live_size", "bytes", totalLiveSize); |
| 1485 threadDump->addScalar("dead_size", "bytes", totalDeadSize); | 1470 threadDump->addScalar("dead_size", "bytes", totalDeadSize); |
| 1486 | 1471 |
| 1487 WebMemoryAllocatorDump* heapsDump = BlinkGCMemoryDumpProvider::instance()->c
reateMemoryAllocatorDumpForCurrentGC(heapsDumpName); | 1472 WebMemoryAllocatorDump* heapsDump = BlinkGCMemoryDumpProvider::instance()->c
reateMemoryAllocatorDumpForCurrentGC(heapsDumpName); |
| 1488 WebMemoryAllocatorDump* classesDump = BlinkGCMemoryDumpProvider::instance()-
>createMemoryAllocatorDumpForCurrentGC(classesDumpName); | 1473 WebMemoryAllocatorDump* classesDump = BlinkGCMemoryDumpProvider::instance()-
>createMemoryAllocatorDumpForCurrentGC(classesDumpName); |
| 1489 BlinkGCMemoryDumpProvider::instance()->currentProcessMemoryDump()->addOwners
hipEdge(classesDump->guid(), heapsDump->guid()); | 1474 BlinkGCMemoryDumpProvider::instance()->currentProcessMemoryDump()->addOwners
hipEdge(classesDump->guid(), heapsDump->guid()); |
| 1490 } | 1475 } |
| 1491 | 1476 |
| 1492 } // namespace blink | 1477 } // namespace blink |
| OLD | NEW |