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 |