Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
| 8 #include "src/api.h" | 8 #include "src/api.h" |
| 9 #include "src/base/once.h" | 9 #include "src/base/once.h" |
| 10 #include "src/base/utils/random-number-generator.h" | 10 #include "src/base/utils/random-number-generator.h" |
| (...skipping 4209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4220 if (!IsHeapIterable()) { | 4220 if (!IsHeapIterable()) { |
| 4221 CollectAllGarbage(kMakeHeapIterableMask, "Heap::MakeHeapIterable"); | 4221 CollectAllGarbage(kMakeHeapIterableMask, "Heap::MakeHeapIterable"); |
| 4222 } | 4222 } |
| 4223 if (mark_compact_collector()->sweeping_in_progress()) { | 4223 if (mark_compact_collector()->sweeping_in_progress()) { |
| 4224 mark_compact_collector()->EnsureSweepingCompleted(); | 4224 mark_compact_collector()->EnsureSweepingCompleted(); |
| 4225 } | 4225 } |
| 4226 ASSERT(IsHeapIterable()); | 4226 ASSERT(IsHeapIterable()); |
| 4227 } | 4227 } |
| 4228 | 4228 |
| 4229 | 4229 |
| 4230 void Heap::AdvanceIdleIncrementalMarking(intptr_t step_size) { | 4230 int Heap::AdvanceIdleIncrementalMarking(intptr_t step_size) { |
| 4231 double start = base::OS::TimeCurrentMillis(); | |
| 4231 incremental_marking()->Step(step_size, | 4232 incremental_marking()->Step(step_size, |
| 4232 IncrementalMarking::NO_GC_VIA_STACK_GUARD); | 4233 IncrementalMarking::NO_GC_VIA_STACK_GUARD); |
| 4234 return static_cast<int>(base::OS::TimeCurrentMillis() - start); | |
| 4235 } | |
| 4233 | 4236 |
| 4237 | |
| 4238 void Heap::FinalizeIdleIncrementalMarking() { | |
| 4234 if (incremental_marking()->IsComplete()) { | 4239 if (incremental_marking()->IsComplete()) { |
| 4235 bool uncommit = false; | 4240 bool uncommit = false; |
| 4236 if (gc_count_at_last_idle_gc_ == gc_count_) { | 4241 if (gc_count_at_last_idle_gc_ == gc_count_) { |
| 4237 // No GC since the last full GC, the mutator is probably not active. | 4242 // No GC since the last full GC, the mutator is probably not active. |
| 4238 isolate_->compilation_cache()->Clear(); | 4243 isolate_->compilation_cache()->Clear(); |
| 4239 uncommit = true; | 4244 uncommit = true; |
| 4240 } | 4245 } |
| 4241 CollectAllGarbage(kReduceMemoryFootprintMask, | 4246 CollectAllGarbage(kReduceMemoryFootprintMask, |
| 4242 "idle notification: finalize incremental"); | 4247 "idle notification: finalize incremental"); |
| 4243 mark_sweeps_since_idle_round_started_++; | 4248 mark_sweeps_since_idle_round_started_++; |
| 4244 gc_count_at_last_idle_gc_ = gc_count_; | 4249 gc_count_at_last_idle_gc_ = gc_count_; |
| 4245 if (uncommit) { | 4250 if (uncommit) { |
| 4246 new_space_.Shrink(); | 4251 new_space_.Shrink(); |
| 4247 UncommitFromSpace(); | 4252 UncommitFromSpace(); |
| 4248 } | 4253 } |
| 4249 } | 4254 } |
| 4250 } | 4255 } |
| 4251 | 4256 |
| 4252 | 4257 |
| 4253 bool Heap::IdleNotification(int hint) { | 4258 bool Heap::IdleNotification(int idle_time_in_ms) { |
| 4254 // If incremental marking is off, we do not perform idle notification. | 4259 // If incremental marking is off, we do not perform idle notification. |
| 4255 if (!FLAG_incremental_marking) return true; | 4260 if (!FLAG_incremental_marking) return true; |
| 4256 | 4261 |
| 4257 // Hints greater than this value indicate that | 4262 // Hints greater than this value indicate that |
| 4258 // the embedder is requesting a lot of GC work. | 4263 // the embedder is requesting a lot of GC work. |
| 4259 const int kMaxHint = 1000; | 4264 const int kMaxHint = 1000; |
| 4265 // TODO(hpayer): remove min hint | |
| 4260 const int kMinHintForIncrementalMarking = 10; | 4266 const int kMinHintForIncrementalMarking = 10; |
| 4261 // Minimal hint that allows to do full GC. | 4267 // Minimal hint that allows to do full GC. |
| 4262 const int kMinHintForFullGC = 100; | 4268 const int kMinHintForFullGC = 100; |
| 4263 intptr_t size_factor = Min(Max(hint, 20), kMaxHint) / 4; | 4269 // TODO(hpayer, ernstm): use previous time measurements to calculate |
| 4270 // proper size_factor | |
| 4271 intptr_t size_factor = Min(Max(idle_time_in_ms, 20), kMaxHint) / 4; | |
| 4264 // The size factor is in range [5..250]. The numbers here are chosen from | 4272 // The size factor is in range [5..250]. The numbers here are chosen from |
| 4265 // experiments. If you changes them, make sure to test with | 4273 // experiments. If you changes them, make sure to test with |
| 4266 // chrome/performance_ui_tests --gtest_filter="GeneralMixMemoryTest.* | 4274 // chrome/performance_ui_tests --gtest_filter="GeneralMixMemoryTest.* |
| 4267 intptr_t step_size = | 4275 intptr_t step_size = |
| 4268 size_factor * IncrementalMarking::kAllocatedThreshold; | 4276 size_factor * IncrementalMarking::kAllocatedThreshold; |
| 4269 | 4277 |
| 4270 isolate()->counters()->gc_idle_time_allotted_in_ms()->AddSample(hint); | 4278 isolate()->counters()->gc_idle_time_allotted_in_ms()->AddSample( |
| 4279 idle_time_in_ms); | |
| 4271 HistogramTimerScope idle_notification_scope( | 4280 HistogramTimerScope idle_notification_scope( |
| 4272 isolate_->counters()->gc_idle_notification()); | 4281 isolate_->counters()->gc_idle_notification()); |
| 4273 | 4282 |
| 4274 if (contexts_disposed_ > 0) { | 4283 if (contexts_disposed_ > 0) { |
| 4275 contexts_disposed_ = 0; | 4284 contexts_disposed_ = 0; |
| 4276 int mark_sweep_time = Min(TimeMarkSweepWouldTakeInMs(), 1000); | 4285 int mark_sweep_time = Min(TimeMarkSweepWouldTakeInMs(), 1000); |
| 4277 if (hint >= mark_sweep_time && !FLAG_expose_gc && | 4286 if (idle_time_in_ms >= mark_sweep_time && !FLAG_expose_gc && |
| 4278 incremental_marking()->IsStopped()) { | 4287 incremental_marking()->IsStopped()) { |
| 4279 HistogramTimerScope scope(isolate_->counters()->gc_context()); | 4288 HistogramTimerScope scope(isolate_->counters()->gc_context()); |
| 4280 CollectAllGarbage(kReduceMemoryFootprintMask, | 4289 CollectAllGarbage(kReduceMemoryFootprintMask, |
| 4281 "idle notification: contexts disposed"); | 4290 "idle notification: contexts disposed"); |
| 4282 } else { | 4291 } else { |
| 4283 AdvanceIdleIncrementalMarking(step_size); | 4292 int remaining_time = AdvanceIdleIncrementalMarking(step_size); |
|
ernstm
2014/07/30 10:33:26
Isn't the value returned by AdvanceIdleIncremental
Hannes Payer (out of office)
2014/07/30 11:48:52
yes, that makes sense. actually, we should use the
| |
| 4293 if (idle_time_in_ms - remaining_time > kMinHintForIncrementalMarking) { | |
| 4294 FinalizeIdleIncrementalMarking(); | |
| 4295 } | |
| 4284 } | 4296 } |
| 4285 | 4297 |
| 4286 // After context disposal there is likely a lot of garbage remaining, reset | 4298 // After context disposal there is likely a lot of garbage remaining, reset |
| 4287 // the idle notification counters in order to trigger more incremental GCs | 4299 // the idle notification counters in order to trigger more incremental GCs |
| 4288 // on subsequent idle notifications. | 4300 // on subsequent idle notifications. |
| 4289 StartIdleRound(); | 4301 StartIdleRound(); |
| 4290 return false; | 4302 return false; |
| 4291 } | 4303 } |
| 4292 | 4304 |
| 4293 // By doing small chunks of GC work in each IdleNotification, | 4305 // By doing small chunks of GC work in each IdleNotification, |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 4308 | 4320 |
| 4309 int remaining_mark_sweeps = kMaxMarkSweepsInIdleRound - | 4321 int remaining_mark_sweeps = kMaxMarkSweepsInIdleRound - |
| 4310 mark_sweeps_since_idle_round_started_; | 4322 mark_sweeps_since_idle_round_started_; |
| 4311 | 4323 |
| 4312 if (incremental_marking()->IsStopped()) { | 4324 if (incremental_marking()->IsStopped()) { |
| 4313 // If there are no more than two GCs left in this idle round and we are | 4325 // If there are no more than two GCs left in this idle round and we are |
| 4314 // allowed to do a full GC, then make those GCs full in order to compact | 4326 // allowed to do a full GC, then make those GCs full in order to compact |
| 4315 // the code space. | 4327 // the code space. |
| 4316 // TODO(ulan): Once we enable code compaction for incremental marking, | 4328 // TODO(ulan): Once we enable code compaction for incremental marking, |
| 4317 // we can get rid of this special case and always start incremental marking. | 4329 // we can get rid of this special case and always start incremental marking. |
| 4318 if (remaining_mark_sweeps <= 2 && hint >= kMinHintForFullGC) { | 4330 if (remaining_mark_sweeps <= 2 && idle_time_in_ms >= kMinHintForFullGC) { |
| 4319 CollectAllGarbage(kReduceMemoryFootprintMask, | 4331 CollectAllGarbage(kReduceMemoryFootprintMask, |
| 4320 "idle notification: finalize idle round"); | 4332 "idle notification: finalize idle round"); |
| 4321 mark_sweeps_since_idle_round_started_++; | 4333 mark_sweeps_since_idle_round_started_++; |
| 4322 } else if (hint > kMinHintForIncrementalMarking) { | 4334 } else if (idle_time_in_ms > kMinHintForIncrementalMarking) { |
| 4323 incremental_marking()->Start(); | 4335 incremental_marking()->Start(); |
| 4324 } | 4336 } |
| 4325 } | 4337 } |
| 4326 if (!incremental_marking()->IsStopped() && | 4338 if (!incremental_marking()->IsStopped() && |
| 4327 hint > kMinHintForIncrementalMarking) { | 4339 idle_time_in_ms > kMinHintForIncrementalMarking) { |
| 4328 AdvanceIdleIncrementalMarking(step_size); | 4340 int remaining_time = AdvanceIdleIncrementalMarking(step_size); |
|
ernstm
2014/07/30 10:33:26
remaining_time -> time_elapsed?
Hannes Payer (out of office)
2014/07/30 11:48:52
yes.
| |
| 4341 if (idle_time_in_ms - remaining_time > kMinHintForIncrementalMarking) { | |
| 4342 FinalizeIdleIncrementalMarking(); | |
| 4343 } | |
| 4329 } | 4344 } |
| 4330 | 4345 |
| 4331 if (mark_sweeps_since_idle_round_started_ >= kMaxMarkSweepsInIdleRound) { | 4346 if (mark_sweeps_since_idle_round_started_ >= kMaxMarkSweepsInIdleRound) { |
| 4332 FinishIdleRound(); | 4347 FinishIdleRound(); |
| 4333 return true; | 4348 return true; |
| 4334 } | 4349 } |
| 4335 | 4350 |
| 4336 // If the IdleNotifcation is called with a large hint we will wait for | 4351 // If the IdleNotifcation is called with a large idle_time_in_ms we will wait |
| 4337 // the sweepter threads here. | 4352 // for the sweepter threads here. |
| 4338 if (hint >= kMinHintForFullGC && | 4353 if (idle_time_in_ms >= kMinHintForFullGC && |
| 4339 mark_compact_collector()->sweeping_in_progress()) { | 4354 mark_compact_collector()->sweeping_in_progress()) { |
| 4340 mark_compact_collector()->EnsureSweepingCompleted(); | 4355 mark_compact_collector()->EnsureSweepingCompleted(); |
| 4341 } | 4356 } |
| 4342 | 4357 |
| 4343 return false; | 4358 return false; |
| 4344 } | 4359 } |
| 4345 | 4360 |
| 4346 | 4361 |
| 4347 #ifdef DEBUG | 4362 #ifdef DEBUG |
| 4348 | 4363 |
| (...skipping 1817 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6166 static_cast<int>(object_sizes_last_time_[index])); | 6181 static_cast<int>(object_sizes_last_time_[index])); |
| 6167 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) | 6182 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) |
| 6168 #undef ADJUST_LAST_TIME_OBJECT_COUNT | 6183 #undef ADJUST_LAST_TIME_OBJECT_COUNT |
| 6169 | 6184 |
| 6170 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); | 6185 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); |
| 6171 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); | 6186 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); |
| 6172 ClearObjectStats(); | 6187 ClearObjectStats(); |
| 6173 } | 6188 } |
| 6174 | 6189 |
| 6175 } } // namespace v8::internal | 6190 } } // namespace v8::internal |
| OLD | NEW |