| 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 588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 599 if (idleDeltaInSeconds <= Heap::estimatedMarkingTime() && !Scheduler::shared
()->canExceedIdleDeadlineIfRequired()) { | 599 if (idleDeltaInSeconds <= Heap::estimatedMarkingTime() && !Scheduler::shared
()->canExceedIdleDeadlineIfRequired()) { |
| 600 // If marking is estimated to take longer than the deadline and we can't | 600 // If marking is estimated to take longer than the deadline and we can't |
| 601 // exceed the deadline, then reschedule for the next idle period. | 601 // exceed the deadline, then reschedule for the next idle period. |
| 602 scheduleIdleGC(); | 602 scheduleIdleGC(); |
| 603 return; | 603 return; |
| 604 } | 604 } |
| 605 | 605 |
| 606 Heap::collectGarbage(NoHeapPointersOnStack, GCWithoutSweep, Heap::IdleGC); | 606 Heap::collectGarbage(NoHeapPointersOnStack, GCWithoutSweep, Heap::IdleGC); |
| 607 } | 607 } |
| 608 | 608 |
| 609 void ThreadState::performIdleCompleteSweep(double deadlineSeconds) | 609 void ThreadState::performIdleLazySweep(double deadlineSeconds) |
| 610 { | 610 { |
| 611 ASSERT(isMainThread()); | 611 ASSERT(isMainThread()); |
| 612 // The completeSweep() does nothing if the sweeping is already done. | 612 |
| 613 // TODO(haraken): Split the sweeping task into chunks so that each chunk fit
s | 613 // If we are not in a sweeping phase, there is nothing to do here. |
| 614 // in the deadlineSeconds. | 614 if (!isSweepingInProgress()) |
| 615 completeSweep(); | 615 return; |
| 616 |
| 617 // This check is here to prevent performIdleLazySweep() from being called |
| 618 // recursively. I'm not sure if it can happen but it would be safer to have |
| 619 // the check just in case. |
| 620 if (sweepForbidden()) |
| 621 return; |
| 622 |
| 623 bool sweepCompleted = true; |
| 624 ThreadState::SweepForbiddenScope scope(this); |
| 625 { |
| 626 if (isMainThread()) |
| 627 ScriptForbiddenScope::enter(); |
| 628 |
| 629 for (int i = 0; i < NumberOfHeaps; i++) { |
| 630 // lazySweepWithDeadline() won't check the deadline until it sweeps |
| 631 // 10 pages. So we give a small slack for safety. |
| 632 double slack = 0.001; |
| 633 double remainingBudget = deadlineSeconds - slack - Platform::current
()->monotonicallyIncreasingTime(); |
| 634 if (remainingBudget <= 0 || !m_heaps[i]->lazySweepWithDeadline(deadl
ineSeconds)) { |
| 635 // We couldn't finish the sweeping within the deadline. |
| 636 // We request another idle task for the remaining sweeping. |
| 637 scheduleIdleLazySweep(); |
| 638 sweepCompleted = false; |
| 639 break; |
| 640 } |
| 641 } |
| 642 |
| 643 if (isMainThread()) |
| 644 ScriptForbiddenScope::exit(); |
| 645 } |
| 646 |
| 647 if (sweepCompleted) |
| 648 postSweep(); |
| 616 } | 649 } |
| 617 | 650 |
| 618 void ThreadState::scheduleIdleGC() | 651 void ThreadState::scheduleIdleGC() |
| 619 { | 652 { |
| 620 // Idle GC is supported only in the main thread. | 653 // Idle GC is supported only in the main thread. |
| 621 if (!isMainThread()) | 654 if (!isMainThread()) |
| 622 return; | 655 return; |
| 623 | 656 |
| 624 if (isSweepingInProgress()) { | 657 if (isSweepingInProgress()) { |
| 625 setGCState(SweepingAndIdleGCScheduled); | 658 setGCState(SweepingAndIdleGCScheduled); |
| 626 return; | 659 return; |
| 627 } | 660 } |
| 628 | 661 |
| 629 Scheduler::shared()->postNonNestableIdleTask(FROM_HERE, WTF::bind<double>(&T
hreadState::performIdleGC, this)); | 662 Scheduler::shared()->postNonNestableIdleTask(FROM_HERE, WTF::bind<double>(&T
hreadState::performIdleGC, this)); |
| 630 setGCState(IdleGCScheduled); | 663 setGCState(IdleGCScheduled); |
| 631 } | 664 } |
| 632 | 665 |
| 633 void ThreadState::scheduleIdleCompleteSweep() | 666 void ThreadState::scheduleIdleLazySweep() |
| 634 { | 667 { |
| 635 // Idle complete sweep is supported only in the main thread. | 668 // Idle complete sweep is supported only in the main thread. |
| 636 if (!isMainThread()) | 669 if (!isMainThread()) |
| 637 return; | 670 return; |
| 638 | 671 |
| 639 // TODO(haraken): Temporarily disable complete sweeping in idle tasks | 672 // TODO(haraken): Remove this. Lazy sweeping is not yet enabled in non-oilpa
n builds. |
| 640 // because it turned out that it has a risk of violating the idle task | 673 #if ENABLE(OILPAN) |
| 641 // deadline and thus regressing queueing_durations. We'll enable this | 674 Scheduler::shared()->postIdleTask(FROM_HERE, WTF::bind<double>(&ThreadState:
:performIdleLazySweep, this)); |
| 642 // once we finish collecting performance numbers. | |
| 643 #if 0 | |
| 644 Scheduler::shared()->postIdleTask(FROM_HERE, WTF::bind<double>(&ThreadState:
:performIdleCompleteSweep, this)); | |
| 645 #endif | 675 #endif |
| 646 } | 676 } |
| 647 | 677 |
| 648 void ThreadState::schedulePreciseGC() | 678 void ThreadState::schedulePreciseGC() |
| 649 { | 679 { |
| 650 if (isSweepingInProgress()) { | 680 if (isSweepingInProgress()) { |
| 651 setGCState(SweepingAndPreciseGCScheduled); | 681 setGCState(SweepingAndPreciseGCScheduled); |
| 652 return; | 682 return; |
| 653 } | 683 } |
| 654 | 684 |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 777 return; | 807 return; |
| 778 | 808 |
| 779 // completeSweep() can be called recursively if finalizers can allocate | 809 // completeSweep() can be called recursively if finalizers can allocate |
| 780 // memory and the allocation triggers completeSweep(). This check prevents | 810 // memory and the allocation triggers completeSweep(). This check prevents |
| 781 // the sweeping from being executed recursively. | 811 // the sweeping from being executed recursively. |
| 782 if (sweepForbidden()) | 812 if (sweepForbidden()) |
| 783 return; | 813 return; |
| 784 | 814 |
| 785 ThreadState::SweepForbiddenScope scope(this); | 815 ThreadState::SweepForbiddenScope scope(this); |
| 786 { | 816 { |
| 817 if (isMainThread()) |
| 818 ScriptForbiddenScope::enter(); |
| 819 |
| 787 TRACE_EVENT0("blink_gc", "ThreadState::completeSweep"); | 820 TRACE_EVENT0("blink_gc", "ThreadState::completeSweep"); |
| 788 double timeStamp = WTF::currentTimeMS(); | 821 double timeStamp = WTF::currentTimeMS(); |
| 789 | 822 |
| 790 for (int i = 0; i < NumberOfHeaps; i++) | 823 for (int i = 0; i < NumberOfHeaps; i++) |
| 791 m_heaps[i]->completeSweep(); | 824 m_heaps[i]->completeSweep(); |
| 792 | 825 |
| 793 if (Platform::current()) { | 826 if (Platform::current()) { |
| 794 Platform::current()->histogramCustomCounts("BlinkGC.CompleteSweep",
WTF::currentTimeMS() - timeStamp, 0, 10 * 1000, 50); | 827 Platform::current()->histogramCustomCounts("BlinkGC.CompleteSweep",
WTF::currentTimeMS() - timeStamp, 0, 10 * 1000, 50); |
| 795 } | 828 } |
| 829 |
| 830 if (isMainThread()) |
| 831 ScriptForbiddenScope::exit(); |
| 796 } | 832 } |
| 797 | 833 |
| 834 postSweep(); |
| 835 } |
| 836 |
| 837 void ThreadState::postSweep() |
| 838 { |
| 798 if (isMainThread() && m_allocatedObjectSizeBeforeGC) { | 839 if (isMainThread() && m_allocatedObjectSizeBeforeGC) { |
| 799 // FIXME: Heap::markedObjectSize() may not be accurate because other | 840 // FIXME: Heap::markedObjectSize() may not be accurate because other |
| 800 // threads may not have finished sweeping. | 841 // threads may not have finished sweeping. |
| 801 m_collectionRate = 1.0 * Heap::markedObjectSize() / m_allocatedObjectSiz
eBeforeGC; | 842 m_collectionRate = 1.0 * Heap::markedObjectSize() / m_allocatedObjectSiz
eBeforeGC; |
| 802 ASSERT(m_collectionRate >= 0); | 843 ASSERT(m_collectionRate >= 0); |
| 803 | 844 |
| 804 // The main thread might be at a safe point, with other | 845 // The main thread might be at a safe point, with other |
| 805 // threads leaving theirs and accumulating marked object size | 846 // threads leaving theirs and accumulating marked object size |
| 806 // while continuing to sweep. That accumulated size might end up | 847 // while continuing to sweep. That accumulated size might end up |
| 807 // exceeding what the main thread sampled in preGC() (recorded | 848 // exceeding what the main thread sampled in preGC() (recorded |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1049 } | 1090 } |
| 1050 | 1091 |
| 1051 #if ENABLE(OILPAN) | 1092 #if ENABLE(OILPAN) |
| 1052 if (gcState() == EagerSweepScheduled) { | 1093 if (gcState() == EagerSweepScheduled) { |
| 1053 // Eager sweeping should happen only in testing. | 1094 // Eager sweeping should happen only in testing. |
| 1054 setGCState(Sweeping); | 1095 setGCState(Sweeping); |
| 1055 completeSweep(); | 1096 completeSweep(); |
| 1056 } else { | 1097 } else { |
| 1057 // The default behavior is lazy sweeping. | 1098 // The default behavior is lazy sweeping. |
| 1058 setGCState(Sweeping); | 1099 setGCState(Sweeping); |
| 1059 scheduleIdleCompleteSweep(); | 1100 scheduleIdleLazySweep(); |
| 1060 } | 1101 } |
| 1061 #else | 1102 #else |
| 1062 // FIXME: For now, we disable lazy sweeping in non-oilpan builds | 1103 // FIXME: For now, we disable lazy sweeping in non-oilpan builds |
| 1063 // to avoid unacceptable behavior regressions on trunk. | 1104 // to avoid unacceptable behavior regressions on trunk. |
| 1064 setGCState(Sweeping); | 1105 setGCState(Sweeping); |
| 1065 completeSweep(); | 1106 completeSweep(); |
| 1066 #endif | 1107 #endif |
| 1067 | 1108 |
| 1068 #if ENABLE(GC_PROFILING) | 1109 #if ENABLE(GC_PROFILING) |
| 1069 snapshotFreeListIfNecessary(); | 1110 snapshotFreeListIfNecessary(); |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1266 json->beginArray(it->key.ascii().data()); | 1307 json->beginArray(it->key.ascii().data()); |
| 1267 for (size_t age = 0; age <= maxHeapObjectAge; ++age) | 1308 for (size_t age = 0; age <= maxHeapObjectAge; ++age) |
| 1268 json->pushInteger(it->value.ages[age]); | 1309 json->pushInteger(it->value.ages[age]); |
| 1269 json->endArray(); | 1310 json->endArray(); |
| 1270 } | 1311 } |
| 1271 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(TRACE_DISABLED_BY_DEFAULT("blink_gc"), s
tatsName, this, json.release()); | 1312 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(TRACE_DISABLED_BY_DEFAULT("blink_gc"), s
tatsName, this, json.release()); |
| 1272 } | 1313 } |
| 1273 #endif | 1314 #endif |
| 1274 | 1315 |
| 1275 } // namespace blink | 1316 } // namespace blink |
| OLD | NEW |