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 ThreadState::SweepForbiddenScope scope(this); |
| 624 { |
| 625 for (int i = 0; i < NumberOfHeaps; i++) { |
| 626 double remainingBudget = deadlineSeconds - Platform::current()->mono
tonicallyIncreasingTime(); |
| 627 if (remainingBudget <= 0 || !m_heaps[i]->lazySweepWithDeadline(deadl
ineSeconds)) { |
| 628 // We couldn't finish the sweeping within the deadline. |
| 629 // We request another idle task for the remaining sweeping. |
| 630 scheduleIdleLazySweep(); |
| 631 return; |
| 632 } |
| 633 } |
| 634 } |
| 635 |
| 636 // Now we have finished the sweeping. |
| 637 postSweep(); |
616 } | 638 } |
617 | 639 |
618 void ThreadState::scheduleIdleGC() | 640 void ThreadState::scheduleIdleGC() |
619 { | 641 { |
620 // Idle GC is supported only in the main thread. | 642 // Idle GC is supported only in the main thread. |
621 if (!isMainThread()) | 643 if (!isMainThread()) |
622 return; | 644 return; |
623 | 645 |
624 if (isSweepingInProgress()) { | 646 if (isSweepingInProgress()) { |
625 setGCState(SweepingAndIdleGCScheduled); | 647 setGCState(SweepingAndIdleGCScheduled); |
626 return; | 648 return; |
627 } | 649 } |
628 | 650 |
629 Scheduler::shared()->postNonNestableIdleTask(FROM_HERE, WTF::bind<double>(&T
hreadState::performIdleGC, this)); | 651 Scheduler::shared()->postNonNestableIdleTask(FROM_HERE, WTF::bind<double>(&T
hreadState::performIdleGC, this)); |
630 setGCState(IdleGCScheduled); | 652 setGCState(IdleGCScheduled); |
631 } | 653 } |
632 | 654 |
633 void ThreadState::scheduleIdleCompleteSweep() | 655 void ThreadState::scheduleIdleLazySweep() |
634 { | 656 { |
635 // Idle complete sweep is supported only in the main thread. | 657 // Idle complete sweep is supported only in the main thread. |
636 if (!isMainThread()) | 658 if (!isMainThread()) |
637 return; | 659 return; |
638 | 660 |
639 // TODO(haraken): Temporarily disable complete sweeping in idle tasks | 661 // 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 | 662 #if ENABLE(OILPAN) |
641 // deadline and thus regressing queueing_durations. We'll enable this | 663 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 | 664 #endif |
646 } | 665 } |
647 | 666 |
648 void ThreadState::schedulePreciseGC() | 667 void ThreadState::schedulePreciseGC() |
649 { | 668 { |
650 if (isSweepingInProgress()) { | 669 if (isSweepingInProgress()) { |
651 setGCState(SweepingAndPreciseGCScheduled); | 670 setGCState(SweepingAndPreciseGCScheduled); |
652 return; | 671 return; |
653 } | 672 } |
654 | 673 |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
788 double timeStamp = WTF::currentTimeMS(); | 807 double timeStamp = WTF::currentTimeMS(); |
789 | 808 |
790 for (int i = 0; i < NumberOfHeaps; i++) | 809 for (int i = 0; i < NumberOfHeaps; i++) |
791 m_heaps[i]->completeSweep(); | 810 m_heaps[i]->completeSweep(); |
792 | 811 |
793 if (Platform::current()) { | 812 if (Platform::current()) { |
794 Platform::current()->histogramCustomCounts("BlinkGC.CompleteSweep",
WTF::currentTimeMS() - timeStamp, 0, 10 * 1000, 50); | 813 Platform::current()->histogramCustomCounts("BlinkGC.CompleteSweep",
WTF::currentTimeMS() - timeStamp, 0, 10 * 1000, 50); |
795 } | 814 } |
796 } | 815 } |
797 | 816 |
| 817 postSweep(); |
| 818 } |
| 819 |
| 820 void ThreadState::postSweep() |
| 821 { |
798 if (isMainThread() && m_allocatedObjectSizeBeforeGC) { | 822 if (isMainThread() && m_allocatedObjectSizeBeforeGC) { |
799 // FIXME: Heap::markedObjectSize() may not be accurate because other | 823 // FIXME: Heap::markedObjectSize() may not be accurate because other |
800 // threads may not have finished sweeping. | 824 // threads may not have finished sweeping. |
801 m_collectionRate = 1.0 * Heap::markedObjectSize() / m_allocatedObjectSiz
eBeforeGC; | 825 m_collectionRate = 1.0 * Heap::markedObjectSize() / m_allocatedObjectSiz
eBeforeGC; |
802 ASSERT(m_collectionRate >= 0); | 826 ASSERT(m_collectionRate >= 0); |
803 | 827 |
804 // The main thread might be at a safe point, with other | 828 // The main thread might be at a safe point, with other |
805 // threads leaving theirs and accumulating marked object size | 829 // threads leaving theirs and accumulating marked object size |
806 // while continuing to sweep. That accumulated size might end up | 830 // while continuing to sweep. That accumulated size might end up |
807 // exceeding what the main thread sampled in preGC() (recorded | 831 // exceeding what the main thread sampled in preGC() (recorded |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1049 } | 1073 } |
1050 | 1074 |
1051 #if ENABLE(OILPAN) | 1075 #if ENABLE(OILPAN) |
1052 if (gcState() == EagerSweepScheduled) { | 1076 if (gcState() == EagerSweepScheduled) { |
1053 // Eager sweeping should happen only in testing. | 1077 // Eager sweeping should happen only in testing. |
1054 setGCState(Sweeping); | 1078 setGCState(Sweeping); |
1055 completeSweep(); | 1079 completeSweep(); |
1056 } else { | 1080 } else { |
1057 // The default behavior is lazy sweeping. | 1081 // The default behavior is lazy sweeping. |
1058 setGCState(Sweeping); | 1082 setGCState(Sweeping); |
1059 scheduleIdleCompleteSweep(); | 1083 scheduleIdleLazySweep(); |
1060 } | 1084 } |
1061 #else | 1085 #else |
1062 // FIXME: For now, we disable lazy sweeping in non-oilpan builds | 1086 // FIXME: For now, we disable lazy sweeping in non-oilpan builds |
1063 // to avoid unacceptable behavior regressions on trunk. | 1087 // to avoid unacceptable behavior regressions on trunk. |
1064 setGCState(Sweeping); | 1088 setGCState(Sweeping); |
1065 completeSweep(); | 1089 completeSweep(); |
1066 #endif | 1090 #endif |
1067 | 1091 |
1068 #if ENABLE(GC_PROFILING) | 1092 #if ENABLE(GC_PROFILING) |
1069 snapshotFreeListIfNecessary(); | 1093 snapshotFreeListIfNecessary(); |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1266 json->beginArray(it->key.ascii().data()); | 1290 json->beginArray(it->key.ascii().data()); |
1267 for (size_t age = 0; age <= maxHeapObjectAge; ++age) | 1291 for (size_t age = 0; age <= maxHeapObjectAge; ++age) |
1268 json->pushInteger(it->value.ages[age]); | 1292 json->pushInteger(it->value.ages[age]); |
1269 json->endArray(); | 1293 json->endArray(); |
1270 } | 1294 } |
1271 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(TRACE_DISABLED_BY_DEFAULT("blink_gc"), s
tatsName, this, json.release()); | 1295 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(TRACE_DISABLED_BY_DEFAULT("blink_gc"), s
tatsName, this, json.release()); |
1272 } | 1296 } |
1273 #endif | 1297 #endif |
1274 | 1298 |
1275 } // namespace blink | 1299 } // namespace blink |
OLD | NEW |