OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 4974 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4985 if (uncommit) { | 4985 if (uncommit) { |
4986 new_space_.Shrink(); | 4986 new_space_.Shrink(); |
4987 UncommitFromSpace(); | 4987 UncommitFromSpace(); |
4988 } | 4988 } |
4989 } | 4989 } |
4990 } | 4990 } |
4991 | 4991 |
4992 | 4992 |
4993 bool Heap::IdleNotification(int hint) { | 4993 bool Heap::IdleNotification(int hint) { |
4994 const int kMaxHint = 1000; | 4994 const int kMaxHint = 1000; |
4995 intptr_t size_factor = Min(Max(hint, 30), kMaxHint) / 10; | 4995 intptr_t size_factor = Min(Max(hint, 20), kMaxHint) / 4; |
4996 // The size factor is in range [3..100]. | 4996 // The size factor is in range [5..250]. The numbers here are chosen from |
| 4997 // experiments. If you changes them, make sure to test with |
| 4998 // chrome/performance_ui_tests --gtest_filter="GeneralMixMemoryTest.* |
4997 intptr_t step_size = size_factor * IncrementalMarking::kAllocatedThreshold; | 4999 intptr_t step_size = size_factor * IncrementalMarking::kAllocatedThreshold; |
4998 | 5000 |
4999 if (contexts_disposed_ > 0) { | 5001 if (contexts_disposed_ > 0) { |
5000 if (hint >= kMaxHint) { | 5002 if (hint >= kMaxHint) { |
5001 // The embedder is requesting a lot of GC work after context disposal, | 5003 // The embedder is requesting a lot of GC work after context disposal, |
5002 // we age inline caches so that they don't keep objects from | 5004 // we age inline caches so that they don't keep objects from |
5003 // the old context alive. | 5005 // the old context alive. |
5004 AgeInlineCaches(); | 5006 AgeInlineCaches(); |
5005 } | 5007 } |
5006 int mark_sweep_time = Min(TimeMarkSweepWouldTakeInMs(), 1000); | 5008 int mark_sweep_time = Min(TimeMarkSweepWouldTakeInMs(), 1000); |
5007 if (hint >= mark_sweep_time && !FLAG_expose_gc && | 5009 if (hint >= mark_sweep_time && !FLAG_expose_gc && |
5008 incremental_marking()->IsStopped()) { | 5010 incremental_marking()->IsStopped()) { |
5009 HistogramTimerScope scope(isolate_->counters()->gc_context()); | 5011 HistogramTimerScope scope(isolate_->counters()->gc_context()); |
5010 CollectAllGarbage(kReduceMemoryFootprintMask, | 5012 CollectAllGarbage(kReduceMemoryFootprintMask, |
5011 "idle notification: contexts disposed"); | 5013 "idle notification: contexts disposed"); |
5012 } else { | 5014 } else { |
5013 AdvanceIdleIncrementalMarking(step_size); | 5015 AdvanceIdleIncrementalMarking(step_size); |
5014 contexts_disposed_ = 0; | 5016 contexts_disposed_ = 0; |
5015 } | 5017 } |
5016 // Make sure that we have no pending context disposals. | 5018 // Make sure that we have no pending context disposals. |
5017 // Take into account that we might have decided to delay full collection | 5019 // Take into account that we might have decided to delay full collection |
5018 // because incremental marking is in progress. | 5020 // because incremental marking is in progress. |
5019 ASSERT((contexts_disposed_ == 0) || !incremental_marking()->IsStopped()); | 5021 ASSERT((contexts_disposed_ == 0) || !incremental_marking()->IsStopped()); |
| 5022 // After context disposal there is likely a lot of garbage remaining, reset |
| 5023 // the idle notification counters in order to trigger more incremental GCs |
| 5024 // on subsequent idle notifications. |
| 5025 StartIdleRound(); |
5020 return false; | 5026 return false; |
5021 } | 5027 } |
5022 | 5028 |
5023 if (hint >= kMaxHint || !FLAG_incremental_marking || | 5029 if (!FLAG_incremental_marking || FLAG_expose_gc || Serializer::enabled()) { |
5024 FLAG_expose_gc || Serializer::enabled()) { | |
5025 return IdleGlobalGC(); | 5030 return IdleGlobalGC(); |
5026 } | 5031 } |
5027 | 5032 |
5028 // By doing small chunks of GC work in each IdleNotification, | 5033 // By doing small chunks of GC work in each IdleNotification, |
5029 // perform a round of incremental GCs and after that wait until | 5034 // perform a round of incremental GCs and after that wait until |
5030 // the mutator creates enough garbage to justify a new round. | 5035 // the mutator creates enough garbage to justify a new round. |
5031 // An incremental GC progresses as follows: | 5036 // An incremental GC progresses as follows: |
5032 // 1. many incremental marking steps, | 5037 // 1. many incremental marking steps, |
5033 // 2. one old space mark-sweep-compact, | 5038 // 2. one old space mark-sweep-compact, |
5034 // 3. many lazy sweep steps. | 5039 // 3. many lazy sweep steps. |
(...skipping 18 matching lines...) Expand all Loading... |
5053 int new_mark_sweeps = ms_count_ - ms_count_at_last_idle_notification_; | 5058 int new_mark_sweeps = ms_count_ - ms_count_at_last_idle_notification_; |
5054 mark_sweeps_since_idle_round_started_ += new_mark_sweeps; | 5059 mark_sweeps_since_idle_round_started_ += new_mark_sweeps; |
5055 ms_count_at_last_idle_notification_ = ms_count_; | 5060 ms_count_at_last_idle_notification_ = ms_count_; |
5056 | 5061 |
5057 if (mark_sweeps_since_idle_round_started_ >= kMaxMarkSweepsInIdleRound) { | 5062 if (mark_sweeps_since_idle_round_started_ >= kMaxMarkSweepsInIdleRound) { |
5058 FinishIdleRound(); | 5063 FinishIdleRound(); |
5059 return true; | 5064 return true; |
5060 } | 5065 } |
5061 | 5066 |
5062 if (incremental_marking()->IsStopped()) { | 5067 if (incremental_marking()->IsStopped()) { |
5063 if (!WorthStartingGCWhenIdle()) { | |
5064 FinishIdleRound(); | |
5065 return true; | |
5066 } | |
5067 incremental_marking()->Start(); | 5068 incremental_marking()->Start(); |
5068 } | 5069 } |
5069 | 5070 |
5070 AdvanceIdleIncrementalMarking(step_size); | 5071 AdvanceIdleIncrementalMarking(step_size); |
5071 return false; | 5072 return false; |
5072 } | 5073 } |
5073 | 5074 |
5074 | 5075 |
5075 bool Heap::IdleGlobalGC() { | 5076 bool Heap::IdleGlobalGC() { |
5076 static const int kIdlesBeforeScavenge = 4; | 5077 static const int kIdlesBeforeScavenge = 4; |
(...skipping 2062 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7139 } else { | 7140 } else { |
7140 p ^= 0x1d1ed & (Page::kPageSize - 1); // I died. | 7141 p ^= 0x1d1ed & (Page::kPageSize - 1); // I died. |
7141 } | 7142 } |
7142 remembered_unmapped_pages_[remembered_unmapped_pages_index_] = | 7143 remembered_unmapped_pages_[remembered_unmapped_pages_index_] = |
7143 reinterpret_cast<Address>(p); | 7144 reinterpret_cast<Address>(p); |
7144 remembered_unmapped_pages_index_++; | 7145 remembered_unmapped_pages_index_++; |
7145 remembered_unmapped_pages_index_ %= kRememberedUnmappedPages; | 7146 remembered_unmapped_pages_index_ %= kRememberedUnmappedPages; |
7146 } | 7147 } |
7147 | 7148 |
7148 } } // namespace v8::internal | 7149 } } // namespace v8::internal |
OLD | NEW |