| 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" |
| 11 #include "src/bootstrapper.h" | 11 #include "src/bootstrapper.h" |
| 12 #include "src/codegen.h" | 12 #include "src/codegen.h" |
| 13 #include "src/compilation-cache.h" | 13 #include "src/compilation-cache.h" |
| 14 #include "src/conversions.h" | 14 #include "src/conversions.h" |
| 15 #include "src/cpu-profiler.h" | 15 #include "src/cpu-profiler.h" |
| 16 #include "src/debug.h" | 16 #include "src/debug.h" |
| 17 #include "src/deoptimizer.h" | 17 #include "src/deoptimizer.h" |
| 18 #include "src/global-handles.h" | 18 #include "src/global-handles.h" |
| 19 #include "src/heap/gc-idle-time-handler.h" |
| 19 #include "src/heap/incremental-marking.h" | 20 #include "src/heap/incremental-marking.h" |
| 20 #include "src/heap/mark-compact.h" | 21 #include "src/heap/mark-compact.h" |
| 21 #include "src/heap/objects-visiting-inl.h" | 22 #include "src/heap/objects-visiting-inl.h" |
| 22 #include "src/heap/objects-visiting.h" | 23 #include "src/heap/objects-visiting.h" |
| 23 #include "src/heap/store-buffer.h" | 24 #include "src/heap/store-buffer.h" |
| 24 #include "src/heap-profiler.h" | 25 #include "src/heap-profiler.h" |
| 25 #include "src/isolate-inl.h" | 26 #include "src/isolate-inl.h" |
| 26 #include "src/natives.h" | 27 #include "src/natives.h" |
| 27 #include "src/runtime-profiler.h" | 28 #include "src/runtime-profiler.h" |
| 28 #include "src/scopeinfo.h" | 29 #include "src/scopeinfo.h" |
| (...skipping 4227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4256 if (!IsHeapIterable()) { | 4257 if (!IsHeapIterable()) { |
| 4257 CollectAllGarbage(kMakeHeapIterableMask, "Heap::MakeHeapIterable"); | 4258 CollectAllGarbage(kMakeHeapIterableMask, "Heap::MakeHeapIterable"); |
| 4258 } | 4259 } |
| 4259 if (mark_compact_collector()->sweeping_in_progress()) { | 4260 if (mark_compact_collector()->sweeping_in_progress()) { |
| 4260 mark_compact_collector()->EnsureSweepingCompleted(); | 4261 mark_compact_collector()->EnsureSweepingCompleted(); |
| 4261 } | 4262 } |
| 4262 DCHECK(IsHeapIterable()); | 4263 DCHECK(IsHeapIterable()); |
| 4263 } | 4264 } |
| 4264 | 4265 |
| 4265 | 4266 |
| 4266 void Heap::AdvanceIdleIncrementalMarking(intptr_t step_size) { | 4267 void Heap::AdvanceIdleIncrementalMarking(int idle_time_in_ms) { |
| 4268 intptr_t step_size = GCIdleTimeHandler::EstimateMarkingStepSize( |
| 4269 idle_time_in_ms, tracer_.IncrementalMarkingSpeedInBytesPerMillisecond()); |
| 4270 |
| 4267 incremental_marking()->Step(step_size, | 4271 incremental_marking()->Step(step_size, |
| 4268 IncrementalMarking::NO_GC_VIA_STACK_GUARD, true); | 4272 IncrementalMarking::NO_GC_VIA_STACK_GUARD, true); |
| 4269 | 4273 |
| 4270 if (incremental_marking()->IsComplete()) { | 4274 if (incremental_marking()->IsComplete()) { |
| 4271 bool uncommit = false; | 4275 bool uncommit = false; |
| 4272 if (gc_count_at_last_idle_gc_ == gc_count_) { | 4276 if (gc_count_at_last_idle_gc_ == gc_count_) { |
| 4273 // No GC since the last full GC, the mutator is probably not active. | 4277 // No GC since the last full GC, the mutator is probably not active. |
| 4274 isolate_->compilation_cache()->Clear(); | 4278 isolate_->compilation_cache()->Clear(); |
| 4275 uncommit = true; | 4279 uncommit = true; |
| 4276 } | 4280 } |
| 4277 CollectAllGarbage(kReduceMemoryFootprintMask, | 4281 CollectAllGarbage(kReduceMemoryFootprintMask, |
| 4278 "idle notification: finalize incremental"); | 4282 "idle notification: finalize incremental"); |
| 4279 mark_sweeps_since_idle_round_started_++; | 4283 mark_sweeps_since_idle_round_started_++; |
| 4280 gc_count_at_last_idle_gc_ = gc_count_; | 4284 gc_count_at_last_idle_gc_ = gc_count_; |
| 4281 if (uncommit) { | 4285 if (uncommit) { |
| 4282 new_space_.Shrink(); | 4286 new_space_.Shrink(); |
| 4283 UncommitFromSpace(); | 4287 UncommitFromSpace(); |
| 4284 } | 4288 } |
| 4285 } | 4289 } |
| 4286 } | 4290 } |
| 4287 | 4291 |
| 4288 | 4292 |
| 4289 bool Heap::IdleNotification(int hint) { | 4293 bool Heap::IdleNotification(int idle_time_in_ms) { |
| 4290 // If incremental marking is off, we do not perform idle notification. | 4294 // If incremental marking is off, we do not perform idle notification. |
| 4291 if (!FLAG_incremental_marking) return true; | 4295 if (!FLAG_incremental_marking) return true; |
| 4292 | 4296 |
| 4293 // Hints greater than this value indicate that | |
| 4294 // the embedder is requesting a lot of GC work. | |
| 4295 const int kMaxHint = 1000; | |
| 4296 const int kMinHintForIncrementalMarking = 10; | |
| 4297 // Minimal hint that allows to do full GC. | 4297 // Minimal hint that allows to do full GC. |
| 4298 const int kMinHintForFullGC = 100; | 4298 const int kMinHintForFullGC = 100; |
| 4299 intptr_t size_factor = Min(Max(hint, 20), kMaxHint) / 4; | 4299 isolate()->counters()->gc_idle_time_allotted_in_ms()->AddSample( |
| 4300 // The size factor is in range [5..250]. The numbers here are chosen from | 4300 idle_time_in_ms); |
| 4301 // experiments. If you changes them, make sure to test with | |
| 4302 // chrome/performance_ui_tests --gtest_filter="GeneralMixMemoryTest.* | |
| 4303 intptr_t step_size = size_factor * IncrementalMarking::kAllocatedThreshold; | |
| 4304 | |
| 4305 isolate()->counters()->gc_idle_time_allotted_in_ms()->AddSample(hint); | |
| 4306 HistogramTimerScope idle_notification_scope( | 4301 HistogramTimerScope idle_notification_scope( |
| 4307 isolate_->counters()->gc_idle_notification()); | 4302 isolate_->counters()->gc_idle_notification()); |
| 4308 | 4303 |
| 4309 if (contexts_disposed_ > 0) { | 4304 if (contexts_disposed_ > 0) { |
| 4310 contexts_disposed_ = 0; | 4305 contexts_disposed_ = 0; |
| 4311 int mark_sweep_time = Min(TimeMarkSweepWouldTakeInMs(), 1000); | 4306 int mark_sweep_time = Min(TimeMarkSweepWouldTakeInMs(), 1000); |
| 4312 if (hint >= mark_sweep_time && !FLAG_expose_gc && | 4307 if (idle_time_in_ms >= mark_sweep_time && !FLAG_expose_gc && |
| 4313 incremental_marking()->IsStopped()) { | 4308 incremental_marking()->IsStopped()) { |
| 4314 HistogramTimerScope scope(isolate_->counters()->gc_context()); | 4309 HistogramTimerScope scope(isolate_->counters()->gc_context()); |
| 4315 CollectAllGarbage(kReduceMemoryFootprintMask, | 4310 CollectAllGarbage(kReduceMemoryFootprintMask, |
| 4316 "idle notification: contexts disposed"); | 4311 "idle notification: contexts disposed"); |
| 4317 } else { | 4312 } else { |
| 4318 AdvanceIdleIncrementalMarking(step_size); | 4313 AdvanceIdleIncrementalMarking(idle_time_in_ms); |
| 4319 } | 4314 } |
| 4320 | 4315 |
| 4321 // After context disposal there is likely a lot of garbage remaining, reset | 4316 // After context disposal there is likely a lot of garbage remaining, reset |
| 4322 // the idle notification counters in order to trigger more incremental GCs | 4317 // the idle notification counters in order to trigger more incremental GCs |
| 4323 // on subsequent idle notifications. | 4318 // on subsequent idle notifications. |
| 4324 StartIdleRound(); | 4319 StartIdleRound(); |
| 4325 return false; | 4320 return false; |
| 4326 } | 4321 } |
| 4327 | 4322 |
| 4328 // By doing small chunks of GC work in each IdleNotification, | 4323 // By doing small chunks of GC work in each IdleNotification, |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4343 | 4338 |
| 4344 int remaining_mark_sweeps = | 4339 int remaining_mark_sweeps = |
| 4345 kMaxMarkSweepsInIdleRound - mark_sweeps_since_idle_round_started_; | 4340 kMaxMarkSweepsInIdleRound - mark_sweeps_since_idle_round_started_; |
| 4346 | 4341 |
| 4347 if (incremental_marking()->IsStopped()) { | 4342 if (incremental_marking()->IsStopped()) { |
| 4348 // If there are no more than two GCs left in this idle round and we are | 4343 // If there are no more than two GCs left in this idle round and we are |
| 4349 // allowed to do a full GC, then make those GCs full in order to compact | 4344 // allowed to do a full GC, then make those GCs full in order to compact |
| 4350 // the code space. | 4345 // the code space. |
| 4351 // TODO(ulan): Once we enable code compaction for incremental marking, | 4346 // TODO(ulan): Once we enable code compaction for incremental marking, |
| 4352 // we can get rid of this special case and always start incremental marking. | 4347 // we can get rid of this special case and always start incremental marking. |
| 4353 if (remaining_mark_sweeps <= 2 && hint >= kMinHintForFullGC) { | 4348 if (remaining_mark_sweeps <= 2 && idle_time_in_ms >= kMinHintForFullGC) { |
| 4354 CollectAllGarbage(kReduceMemoryFootprintMask, | 4349 CollectAllGarbage(kReduceMemoryFootprintMask, |
| 4355 "idle notification: finalize idle round"); | 4350 "idle notification: finalize idle round"); |
| 4356 mark_sweeps_since_idle_round_started_++; | 4351 mark_sweeps_since_idle_round_started_++; |
| 4357 } else if (hint > kMinHintForIncrementalMarking) { | 4352 } else { |
| 4358 incremental_marking()->Start(); | 4353 incremental_marking()->Start(); |
| 4359 } | 4354 } |
| 4360 } | 4355 } |
| 4361 if (!incremental_marking()->IsStopped() && | 4356 if (!incremental_marking()->IsStopped()) { |
| 4362 hint > kMinHintForIncrementalMarking) { | 4357 AdvanceIdleIncrementalMarking(idle_time_in_ms); |
| 4363 AdvanceIdleIncrementalMarking(step_size); | |
| 4364 } | 4358 } |
| 4365 | 4359 |
| 4366 if (mark_sweeps_since_idle_round_started_ >= kMaxMarkSweepsInIdleRound) { | 4360 if (mark_sweeps_since_idle_round_started_ >= kMaxMarkSweepsInIdleRound) { |
| 4367 FinishIdleRound(); | 4361 FinishIdleRound(); |
| 4368 return true; | 4362 return true; |
| 4369 } | 4363 } |
| 4370 | 4364 |
| 4371 // If the IdleNotifcation is called with a large hint we will wait for | 4365 // If the IdleNotifcation is called with a large hint we will wait for |
| 4372 // the sweepter threads here. | 4366 // the sweepter threads here. |
| 4373 if (hint >= kMinHintForFullGC && | 4367 if (idle_time_in_ms >= kMinHintForFullGC && |
| 4374 mark_compact_collector()->sweeping_in_progress()) { | 4368 mark_compact_collector()->sweeping_in_progress()) { |
| 4375 mark_compact_collector()->EnsureSweepingCompleted(); | 4369 mark_compact_collector()->EnsureSweepingCompleted(); |
| 4376 } | 4370 } |
| 4377 | 4371 |
| 4378 return false; | 4372 return false; |
| 4379 } | 4373 } |
| 4380 | 4374 |
| 4381 | 4375 |
| 4382 #ifdef DEBUG | 4376 #ifdef DEBUG |
| 4383 | 4377 |
| (...skipping 1763 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6147 static_cast<int>(object_sizes_last_time_[index])); | 6141 static_cast<int>(object_sizes_last_time_[index])); |
| 6148 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) | 6142 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) |
| 6149 #undef ADJUST_LAST_TIME_OBJECT_COUNT | 6143 #undef ADJUST_LAST_TIME_OBJECT_COUNT |
| 6150 | 6144 |
| 6151 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); | 6145 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); |
| 6152 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); | 6146 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); |
| 6153 ClearObjectStats(); | 6147 ClearObjectStats(); |
| 6154 } | 6148 } |
| 6155 } | 6149 } |
| 6156 } // namespace v8::internal | 6150 } // namespace v8::internal |
| OLD | NEW |