| 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 | 
|---|