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/heap/heap.h" | 5 #include "src/heap/heap.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/ast/context-slot-cache.h" | 9 #include "src/ast/context-slot-cache.h" |
10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 isolate_->counters()->gc_compactor_caused_by_request()->Increment(); | 260 isolate_->counters()->gc_compactor_caused_by_request()->Increment(); |
261 *reason = "GC in old space requested"; | 261 *reason = "GC in old space requested"; |
262 return MARK_COMPACTOR; | 262 return MARK_COMPACTOR; |
263 } | 263 } |
264 | 264 |
265 if (FLAG_gc_global || (FLAG_stress_compaction && (gc_count_ & 1) != 0)) { | 265 if (FLAG_gc_global || (FLAG_stress_compaction && (gc_count_ & 1) != 0)) { |
266 *reason = "GC in old space forced by flags"; | 266 *reason = "GC in old space forced by flags"; |
267 return MARK_COMPACTOR; | 267 return MARK_COMPACTOR; |
268 } | 268 } |
269 | 269 |
| 270 // Is enough data promoted to justify a global GC? |
| 271 if (OldGenerationAllocationLimitReached()) { |
| 272 isolate_->counters()->gc_compactor_caused_by_promoted_data()->Increment(); |
| 273 *reason = "promotion limit reached"; |
| 274 return MARK_COMPACTOR; |
| 275 } |
| 276 |
270 // Is there enough space left in OLD to guarantee that a scavenge can | 277 // Is there enough space left in OLD to guarantee that a scavenge can |
271 // succeed? | 278 // succeed? |
272 // | 279 // |
273 // Note that MemoryAllocator->MaxAvailable() undercounts the memory available | 280 // Note that MemoryAllocator->MaxAvailable() undercounts the memory available |
274 // for object promotion. It counts only the bytes that the memory | 281 // for object promotion. It counts only the bytes that the memory |
275 // allocator has not yet allocated from the OS and assigned to any space, | 282 // allocator has not yet allocated from the OS and assigned to any space, |
276 // and does not count available bytes already in the old space or code | 283 // and does not count available bytes already in the old space or code |
277 // space. Undercounting is safe---we may get an unrequested full GC when | 284 // space. Undercounting is safe---we may get an unrequested full GC when |
278 // a scavenge would have succeeded. | 285 // a scavenge would have succeeded. |
279 if (memory_allocator()->MaxAvailable() <= new_space_->Size()) { | 286 if (memory_allocator()->MaxAvailable() <= new_space_->Size()) { |
(...skipping 674 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
954 if (collector == SCAVENGER && !incremental_marking()->IsStopped()) { | 961 if (collector == SCAVENGER && !incremental_marking()->IsStopped()) { |
955 if (FLAG_trace_incremental_marking) { | 962 if (FLAG_trace_incremental_marking) { |
956 isolate()->PrintWithTimestamp( | 963 isolate()->PrintWithTimestamp( |
957 "[IncrementalMarking] Scavenge during marking.\n"); | 964 "[IncrementalMarking] Scavenge during marking.\n"); |
958 } | 965 } |
959 } | 966 } |
960 | 967 |
961 if (collector == MARK_COMPACTOR && !ShouldFinalizeIncrementalMarking() && | 968 if (collector == MARK_COMPACTOR && !ShouldFinalizeIncrementalMarking() && |
962 !ShouldAbortIncrementalMarking() && !incremental_marking()->IsStopped() && | 969 !ShouldAbortIncrementalMarking() && !incremental_marking()->IsStopped() && |
963 !incremental_marking()->should_hurry() && FLAG_incremental_marking && | 970 !incremental_marking()->should_hurry() && FLAG_incremental_marking && |
964 OldGenerationSpaceAvailable() <= 0) { | 971 OldGenerationAllocationLimitReached()) { |
965 if (!incremental_marking()->IsComplete() && | 972 if (!incremental_marking()->IsComplete() && |
966 !mark_compact_collector()->marking_deque_.IsEmpty() && | 973 !mark_compact_collector()->marking_deque_.IsEmpty() && |
967 !FLAG_gc_global) { | 974 !FLAG_gc_global) { |
968 if (FLAG_trace_incremental_marking) { | 975 if (FLAG_trace_incremental_marking) { |
969 isolate()->PrintWithTimestamp( | 976 isolate()->PrintWithTimestamp( |
970 "[IncrementalMarking] Delaying MarkSweep.\n"); | 977 "[IncrementalMarking] Delaying MarkSweep.\n"); |
971 } | 978 } |
972 collector = SCAVENGER; | 979 collector = SCAVENGER; |
973 collector_reason = "incremental marking delaying mark-sweep"; | 980 collector_reason = "incremental marking delaying mark-sweep"; |
974 } | 981 } |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1066 GarbageCollectionReason gc_reason, | 1073 GarbageCollectionReason gc_reason, |
1067 GCCallbackFlags gc_callback_flags) { | 1074 GCCallbackFlags gc_callback_flags) { |
1068 DCHECK(incremental_marking()->IsStopped()); | 1075 DCHECK(incremental_marking()->IsStopped()); |
1069 set_current_gc_flags(gc_flags); | 1076 set_current_gc_flags(gc_flags); |
1070 current_gc_callback_flags_ = gc_callback_flags; | 1077 current_gc_callback_flags_ = gc_callback_flags; |
1071 incremental_marking()->Start(gc_reason); | 1078 incremental_marking()->Start(gc_reason); |
1072 } | 1079 } |
1073 | 1080 |
1074 void Heap::StartIncrementalMarkingIfAllocationLimitIsReached( | 1081 void Heap::StartIncrementalMarkingIfAllocationLimitIsReached( |
1075 int gc_flags, const GCCallbackFlags gc_callback_flags) { | 1082 int gc_flags, const GCCallbackFlags gc_callback_flags) { |
1076 if (incremental_marking()->IsStopped()) { | 1083 if (incremental_marking()->IsStopped() && |
1077 IncrementalMarkingLimit reached_limit = IncrementalMarkingLimitReached(); | 1084 incremental_marking()->ShouldActivateEvenWithoutIdleNotification()) { |
1078 if (reached_limit == IncrementalMarkingLimit::kSoftLimit) { | 1085 StartIncrementalMarking(gc_flags, GarbageCollectionReason::kAllocationLimit, |
1079 incremental_marking()->incremental_marking_job()->ScheduleTask(this); | 1086 gc_callback_flags); |
1080 } else if (reached_limit == IncrementalMarkingLimit::kHardLimit) { | |
1081 StartIncrementalMarking(gc_flags, | |
1082 GarbageCollectionReason::kAllocationLimit, | |
1083 gc_callback_flags); | |
1084 } | |
1085 } | 1087 } |
1086 } | 1088 } |
1087 | 1089 |
1088 void Heap::StartIdleIncrementalMarking(GarbageCollectionReason gc_reason) { | 1090 void Heap::StartIdleIncrementalMarking(GarbageCollectionReason gc_reason) { |
1089 gc_idle_time_handler_->ResetNoProgressCounter(); | 1091 gc_idle_time_handler_->ResetNoProgressCounter(); |
1090 StartIncrementalMarking(kReduceMemoryFootprintMask, gc_reason, | 1092 StartIncrementalMarking(kReduceMemoryFootprintMask, gc_reason, |
1091 kNoGCCallbackFlags); | 1093 kNoGCCallbackFlags); |
1092 } | 1094 } |
1093 | 1095 |
1094 | 1096 |
(...skipping 4228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5323 CalculateOldGenerationAllocationLimit(factor, old_gen_size); | 5325 CalculateOldGenerationAllocationLimit(factor, old_gen_size); |
5324 | 5326 |
5325 if (FLAG_trace_gc_verbose) { | 5327 if (FLAG_trace_gc_verbose) { |
5326 isolate_->PrintWithTimestamp("Grow: old size: %" V8PRIdPTR | 5328 isolate_->PrintWithTimestamp("Grow: old size: %" V8PRIdPTR |
5327 " KB, new limit: %" V8PRIdPTR " KB (%.1f)\n", | 5329 " KB, new limit: %" V8PRIdPTR " KB (%.1f)\n", |
5328 old_gen_size / KB, | 5330 old_gen_size / KB, |
5329 old_generation_allocation_limit_ / KB, factor); | 5331 old_generation_allocation_limit_ / KB, factor); |
5330 } | 5332 } |
5331 } | 5333 } |
5332 | 5334 |
| 5335 |
5333 void Heap::DampenOldGenerationAllocationLimit(intptr_t old_gen_size, | 5336 void Heap::DampenOldGenerationAllocationLimit(intptr_t old_gen_size, |
5334 double gc_speed, | 5337 double gc_speed, |
5335 double mutator_speed) { | 5338 double mutator_speed) { |
5336 double factor = HeapGrowingFactor(gc_speed, mutator_speed); | 5339 double factor = HeapGrowingFactor(gc_speed, mutator_speed); |
5337 intptr_t limit = CalculateOldGenerationAllocationLimit(factor, old_gen_size); | 5340 intptr_t limit = CalculateOldGenerationAllocationLimit(factor, old_gen_size); |
5338 if (limit < old_generation_allocation_limit_) { | 5341 if (limit < old_generation_allocation_limit_) { |
5339 if (FLAG_trace_gc_verbose) { | 5342 if (FLAG_trace_gc_verbose) { |
5340 isolate_->PrintWithTimestamp( | 5343 isolate_->PrintWithTimestamp( |
5341 "Dampen: old size: %" V8PRIdPTR " KB, old limit: %" V8PRIdPTR | 5344 "Dampen: old size: %" V8PRIdPTR " KB, old limit: %" V8PRIdPTR |
5342 " KB, " | 5345 " KB, " |
5343 "new limit: %" V8PRIdPTR " KB (%.1f)\n", | 5346 "new limit: %" V8PRIdPTR " KB (%.1f)\n", |
5344 old_gen_size / KB, old_generation_allocation_limit_ / KB, limit / KB, | 5347 old_gen_size / KB, old_generation_allocation_limit_ / KB, limit / KB, |
5345 factor); | 5348 factor); |
5346 } | 5349 } |
5347 old_generation_allocation_limit_ = limit; | 5350 old_generation_allocation_limit_ = limit; |
5348 } | 5351 } |
5349 } | 5352 } |
5350 | 5353 |
5351 // This predicate is called when an old generation space cannot allocated from | |
5352 // the free list and is about to add a new page. Returning false will cause a | |
5353 // major GC. It happens when the old generation allocation limit is reached and | |
5354 // - either we need to optimize for memory usage, | |
5355 // - or the incremental marking is not in progress and we cannot start it. | |
5356 bool Heap::ShouldExpandOldGenerationOnAllocationFailure() { | |
5357 if (always_allocate() || OldGenerationSpaceAvailable() > 0) return true; | |
5358 // We reached the old generation allocation limit. | |
5359 | |
5360 if (ShouldOptimizeForMemoryUsage()) return false; | |
5361 | |
5362 if (incremental_marking()->IsStopped() && | |
5363 IncrementalMarkingLimitReached() == IncrementalMarkingLimit::kNoLimit) { | |
5364 // We cannot start incremental marking. | |
5365 return false; | |
5366 } | |
5367 return true; | |
5368 } | |
5369 | |
5370 // This function returns either kNoLimit, kSoftLimit, or kHardLimit. | |
5371 // The kNoLimit means that either incremental marking is disabled or it is too | |
5372 // early to start incremental marking. | |
5373 // The kSoftLimit means that incremental marking should be started soon. | |
5374 // The kHardLimit means that incremental marking should be started immediately. | |
5375 Heap::IncrementalMarkingLimit Heap::IncrementalMarkingLimitReached() { | |
5376 if (!incremental_marking()->CanBeActivated() || | |
5377 PromotedSpaceSizeOfObjects() < IncrementalMarking::kActivationThreshold) { | |
5378 // Incremental marking is disabled or it is too early to start. | |
5379 return IncrementalMarkingLimit::kNoLimit; | |
5380 } | |
5381 if ((FLAG_stress_compaction && (gc_count_ & 1) != 0) || | |
5382 HighMemoryPressure()) { | |
5383 // If there is high memory pressure or stress testing is enabled, then | |
5384 // start marking immediately. | |
5385 return IncrementalMarkingLimit::kHardLimit; | |
5386 } | |
5387 intptr_t old_generation_space_available = OldGenerationSpaceAvailable(); | |
5388 if (old_generation_space_available > new_space_->Capacity()) { | |
5389 return IncrementalMarkingLimit::kNoLimit; | |
5390 } | |
5391 // We are close to the allocation limit. | |
5392 // Choose between the hard and the soft limits. | |
5393 if (old_generation_space_available <= 0 || ShouldOptimizeForMemoryUsage()) { | |
5394 return IncrementalMarkingLimit::kHardLimit; | |
5395 } | |
5396 return IncrementalMarkingLimit::kSoftLimit; | |
5397 } | |
5398 | 5354 |
5399 void Heap::EnableInlineAllocation() { | 5355 void Heap::EnableInlineAllocation() { |
5400 if (!inline_allocation_disabled_) return; | 5356 if (!inline_allocation_disabled_) return; |
5401 inline_allocation_disabled_ = false; | 5357 inline_allocation_disabled_ = false; |
5402 | 5358 |
5403 // Update inline allocation limit for new space. | 5359 // Update inline allocation limit for new space. |
5404 new_space()->UpdateInlineAllocationLimit(0); | 5360 new_space()->UpdateInlineAllocationLimit(0); |
5405 } | 5361 } |
5406 | 5362 |
5407 | 5363 |
(...skipping 1107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6515 } | 6471 } |
6516 | 6472 |
6517 | 6473 |
6518 // static | 6474 // static |
6519 int Heap::GetStaticVisitorIdForMap(Map* map) { | 6475 int Heap::GetStaticVisitorIdForMap(Map* map) { |
6520 return StaticVisitorBase::GetVisitorId(map); | 6476 return StaticVisitorBase::GetVisitorId(map); |
6521 } | 6477 } |
6522 | 6478 |
6523 } // namespace internal | 6479 } // namespace internal |
6524 } // namespace v8 | 6480 } // namespace v8 |
OLD | NEW |