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 4236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4247 gc_count_at_last_idle_gc_ = gc_count_; | 4247 gc_count_at_last_idle_gc_ = gc_count_; |
| 4248 if (uncommit) { | 4248 if (uncommit) { |
| 4249 new_space_.Shrink(); | 4249 new_space_.Shrink(); |
| 4250 UncommitFromSpace(); | 4250 UncommitFromSpace(); |
| 4251 } | 4251 } |
| 4252 } | 4252 } |
| 4253 } | 4253 } |
| 4254 | 4254 |
| 4255 | 4255 |
| 4256 bool Heap::IdleNotification(int hint) { | 4256 bool Heap::IdleNotification(int hint) { |
| 4257 // If incremental marking is off, we do not perform idle notification. | |
| 4258 if (!FLAG_incremental_marking) return true; | |
|
jochen (gone - plz use gerrit)
2014/07/28 13:11:13
why not return false (meaning "no need to call aga
Hannes Payer (out of office)
2014/07/28 13:56:49
Return true means that "we are done".
| |
| 4259 | |
| 4257 // Hints greater than this value indicate that | 4260 // Hints greater than this value indicate that |
| 4258 // the embedder is requesting a lot of GC work. | 4261 // the embedder is requesting a lot of GC work. |
| 4259 const int kMaxHint = 1000; | 4262 const int kMaxHint = 1000; |
| 4260 const int kMinHintForIncrementalMarking = 10; | 4263 const int kMinHintForIncrementalMarking = 10; |
| 4261 // Minimal hint that allows to do full GC. | 4264 // Minimal hint that allows to do full GC. |
| 4262 const int kMinHintForFullGC = 100; | 4265 const int kMinHintForFullGC = 100; |
| 4263 intptr_t size_factor = Min(Max(hint, 20), kMaxHint) / 4; | 4266 intptr_t size_factor = Min(Max(hint, 20), kMaxHint) / 4; |
| 4264 // The size factor is in range [5..250]. The numbers here are chosen from | 4267 // 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 | 4268 // experiments. If you changes them, make sure to test with |
| 4266 // chrome/performance_ui_tests --gtest_filter="GeneralMixMemoryTest.* | 4269 // chrome/performance_ui_tests --gtest_filter="GeneralMixMemoryTest.* |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 4283 AdvanceIdleIncrementalMarking(step_size); | 4286 AdvanceIdleIncrementalMarking(step_size); |
| 4284 } | 4287 } |
| 4285 | 4288 |
| 4286 // After context disposal there is likely a lot of garbage remaining, reset | 4289 // After context disposal there is likely a lot of garbage remaining, reset |
| 4287 // the idle notification counters in order to trigger more incremental GCs | 4290 // the idle notification counters in order to trigger more incremental GCs |
| 4288 // on subsequent idle notifications. | 4291 // on subsequent idle notifications. |
| 4289 StartIdleRound(); | 4292 StartIdleRound(); |
| 4290 return false; | 4293 return false; |
| 4291 } | 4294 } |
| 4292 | 4295 |
| 4293 if (!FLAG_incremental_marking || isolate_->serializer_enabled()) { | |
| 4294 return IdleGlobalGC(); | |
| 4295 } | |
| 4296 | |
| 4297 // By doing small chunks of GC work in each IdleNotification, | 4296 // By doing small chunks of GC work in each IdleNotification, |
| 4298 // perform a round of incremental GCs and after that wait until | 4297 // perform a round of incremental GCs and after that wait until |
| 4299 // the mutator creates enough garbage to justify a new round. | 4298 // the mutator creates enough garbage to justify a new round. |
| 4300 // An incremental GC progresses as follows: | 4299 // An incremental GC progresses as follows: |
| 4301 // 1. many incremental marking steps, | 4300 // 1. many incremental marking steps, |
| 4302 // 2. one old space mark-sweep-compact, | 4301 // 2. one old space mark-sweep-compact, |
| 4303 // Use mark-sweep-compact events to count incremental GCs in a round. | 4302 // Use mark-sweep-compact events to count incremental GCs in a round. |
| 4304 | 4303 |
| 4305 if (mark_sweeps_since_idle_round_started_ >= kMaxMarkSweepsInIdleRound) { | 4304 if (mark_sweeps_since_idle_round_started_ >= kMaxMarkSweepsInIdleRound) { |
| 4306 if (EnoughGarbageSinceLastIdleRound()) { | 4305 if (EnoughGarbageSinceLastIdleRound()) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4341 // the sweepter threads here. | 4340 // the sweepter threads here. |
| 4342 if (hint >= kMinHintForFullGC && | 4341 if (hint >= kMinHintForFullGC && |
| 4343 mark_compact_collector()->sweeping_in_progress()) { | 4342 mark_compact_collector()->sweeping_in_progress()) { |
| 4344 mark_compact_collector()->EnsureSweepingCompleted(); | 4343 mark_compact_collector()->EnsureSweepingCompleted(); |
| 4345 } | 4344 } |
| 4346 | 4345 |
| 4347 return false; | 4346 return false; |
| 4348 } | 4347 } |
| 4349 | 4348 |
| 4350 | 4349 |
| 4351 bool Heap::IdleGlobalGC() { | |
| 4352 static const int kIdlesBeforeScavenge = 4; | |
| 4353 static const int kIdlesBeforeMarkSweep = 7; | |
| 4354 static const int kIdlesBeforeMarkCompact = 8; | |
| 4355 static const int kMaxIdleCount = kIdlesBeforeMarkCompact + 1; | |
| 4356 static const unsigned int kGCsBetweenCleanup = 4; | |
| 4357 | |
| 4358 if (!last_idle_notification_gc_count_init_) { | |
| 4359 last_idle_notification_gc_count_ = gc_count_; | |
| 4360 last_idle_notification_gc_count_init_ = true; | |
| 4361 } | |
| 4362 | |
| 4363 bool uncommit = true; | |
| 4364 bool finished = false; | |
| 4365 | |
| 4366 // Reset the number of idle notifications received when a number of | |
| 4367 // GCs have taken place. This allows another round of cleanup based | |
| 4368 // on idle notifications if enough work has been carried out to | |
| 4369 // provoke a number of garbage collections. | |
| 4370 if (gc_count_ - last_idle_notification_gc_count_ < kGCsBetweenCleanup) { | |
| 4371 number_idle_notifications_ = | |
| 4372 Min(number_idle_notifications_ + 1, kMaxIdleCount); | |
| 4373 } else { | |
| 4374 number_idle_notifications_ = 0; | |
| 4375 last_idle_notification_gc_count_ = gc_count_; | |
| 4376 } | |
| 4377 | |
| 4378 if (number_idle_notifications_ == kIdlesBeforeScavenge) { | |
| 4379 CollectGarbage(NEW_SPACE, "idle notification"); | |
| 4380 new_space_.Shrink(); | |
| 4381 last_idle_notification_gc_count_ = gc_count_; | |
| 4382 } else if (number_idle_notifications_ == kIdlesBeforeMarkSweep) { | |
| 4383 // Before doing the mark-sweep collections we clear the | |
| 4384 // compilation cache to avoid hanging on to source code and | |
| 4385 // generated code for cached functions. | |
| 4386 isolate_->compilation_cache()->Clear(); | |
| 4387 | |
| 4388 CollectAllGarbage(kReduceMemoryFootprintMask, "idle notification"); | |
| 4389 new_space_.Shrink(); | |
| 4390 last_idle_notification_gc_count_ = gc_count_; | |
| 4391 | |
| 4392 } else if (number_idle_notifications_ == kIdlesBeforeMarkCompact) { | |
| 4393 CollectAllGarbage(kReduceMemoryFootprintMask, "idle notification"); | |
| 4394 new_space_.Shrink(); | |
| 4395 last_idle_notification_gc_count_ = gc_count_; | |
| 4396 number_idle_notifications_ = 0; | |
| 4397 finished = true; | |
| 4398 } else if (number_idle_notifications_ > kIdlesBeforeMarkCompact) { | |
| 4399 // If we have received more than kIdlesBeforeMarkCompact idle | |
| 4400 // notifications we do not perform any cleanup because we don't | |
| 4401 // expect to gain much by doing so. | |
| 4402 finished = true; | |
| 4403 } | |
| 4404 | |
| 4405 if (uncommit) UncommitFromSpace(); | |
| 4406 | |
| 4407 return finished; | |
| 4408 } | |
| 4409 | |
| 4410 | |
| 4411 #ifdef DEBUG | 4350 #ifdef DEBUG |
| 4412 | 4351 |
| 4413 void Heap::Print() { | 4352 void Heap::Print() { |
| 4414 if (!HasBeenSetUp()) return; | 4353 if (!HasBeenSetUp()) return; |
| 4415 isolate()->PrintStack(stdout); | 4354 isolate()->PrintStack(stdout); |
| 4416 AllSpaces spaces(this); | 4355 AllSpaces spaces(this); |
| 4417 for (Space* space = spaces.next(); space != NULL; space = spaces.next()) { | 4356 for (Space* space = spaces.next(); space != NULL; space = spaces.next()) { |
| 4418 space->Print(); | 4357 space->Print(); |
| 4419 } | 4358 } |
| 4420 } | 4359 } |
| (...skipping 1809 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6230 static_cast<int>(object_sizes_last_time_[index])); | 6169 static_cast<int>(object_sizes_last_time_[index])); |
| 6231 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) | 6170 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) |
| 6232 #undef ADJUST_LAST_TIME_OBJECT_COUNT | 6171 #undef ADJUST_LAST_TIME_OBJECT_COUNT |
| 6233 | 6172 |
| 6234 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); | 6173 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); |
| 6235 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); | 6174 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); |
| 6236 ClearObjectStats(); | 6175 ClearObjectStats(); |
| 6237 } | 6176 } |
| 6238 | 6177 |
| 6239 } } // namespace v8::internal | 6178 } } // namespace v8::internal |
| OLD | NEW |