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 |