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 | |
277 // Is there enough space left in OLD to guarantee that a scavenge can | 270 // Is there enough space left in OLD to guarantee that a scavenge can |
278 // succeed? | 271 // succeed? |
279 // | 272 // |
280 // Note that MemoryAllocator->MaxAvailable() undercounts the memory available | 273 // Note that MemoryAllocator->MaxAvailable() undercounts the memory available |
281 // for object promotion. It counts only the bytes that the memory | 274 // for object promotion. It counts only the bytes that the memory |
282 // allocator has not yet allocated from the OS and assigned to any space, | 275 // allocator has not yet allocated from the OS and assigned to any space, |
283 // and does not count available bytes already in the old space or code | 276 // and does not count available bytes already in the old space or code |
284 // space. Undercounting is safe---we may get an unrequested full GC when | 277 // space. Undercounting is safe---we may get an unrequested full GC when |
285 // a scavenge would have succeeded. | 278 // a scavenge would have succeeded. |
286 if (memory_allocator()->MaxAvailable() <= new_space_->Size()) { | 279 if (memory_allocator()->MaxAvailable() <= new_space_->Size()) { |
(...skipping 674 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
961 if (collector == SCAVENGER && !incremental_marking()->IsStopped()) { | 954 if (collector == SCAVENGER && !incremental_marking()->IsStopped()) { |
962 if (FLAG_trace_incremental_marking) { | 955 if (FLAG_trace_incremental_marking) { |
963 isolate()->PrintWithTimestamp( | 956 isolate()->PrintWithTimestamp( |
964 "[IncrementalMarking] Scavenge during marking.\n"); | 957 "[IncrementalMarking] Scavenge during marking.\n"); |
965 } | 958 } |
966 } | 959 } |
967 | 960 |
968 if (collector == MARK_COMPACTOR && !ShouldFinalizeIncrementalMarking() && | 961 if (collector == MARK_COMPACTOR && !ShouldFinalizeIncrementalMarking() && |
969 !ShouldAbortIncrementalMarking() && !incremental_marking()->IsStopped() && | 962 !ShouldAbortIncrementalMarking() && !incremental_marking()->IsStopped() && |
970 !incremental_marking()->should_hurry() && FLAG_incremental_marking && | 963 !incremental_marking()->should_hurry() && FLAG_incremental_marking && |
971 OldGenerationAllocationLimitReached()) { | 964 OldGenerationSpaceAvailable() <= 0) { |
972 if (!incremental_marking()->IsComplete() && | 965 if (!incremental_marking()->IsComplete() && |
973 !mark_compact_collector()->marking_deque_.IsEmpty() && | 966 !mark_compact_collector()->marking_deque_.IsEmpty() && |
974 !FLAG_gc_global) { | 967 !FLAG_gc_global) { |
975 if (FLAG_trace_incremental_marking) { | 968 if (FLAG_trace_incremental_marking) { |
976 isolate()->PrintWithTimestamp( | 969 isolate()->PrintWithTimestamp( |
977 "[IncrementalMarking] Delaying MarkSweep.\n"); | 970 "[IncrementalMarking] Delaying MarkSweep.\n"); |
978 } | 971 } |
979 collector = SCAVENGER; | 972 collector = SCAVENGER; |
980 collector_reason = "incremental marking delaying mark-sweep"; | 973 collector_reason = "incremental marking delaying mark-sweep"; |
981 } | 974 } |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1073 GarbageCollectionReason gc_reason, | 1066 GarbageCollectionReason gc_reason, |
1074 GCCallbackFlags gc_callback_flags) { | 1067 GCCallbackFlags gc_callback_flags) { |
1075 DCHECK(incremental_marking()->IsStopped()); | 1068 DCHECK(incremental_marking()->IsStopped()); |
1076 set_current_gc_flags(gc_flags); | 1069 set_current_gc_flags(gc_flags); |
1077 current_gc_callback_flags_ = gc_callback_flags; | 1070 current_gc_callback_flags_ = gc_callback_flags; |
1078 incremental_marking()->Start(gc_reason); | 1071 incremental_marking()->Start(gc_reason); |
1079 } | 1072 } |
1080 | 1073 |
1081 void Heap::StartIncrementalMarkingIfAllocationLimitIsReached( | 1074 void Heap::StartIncrementalMarkingIfAllocationLimitIsReached( |
1082 int gc_flags, const GCCallbackFlags gc_callback_flags) { | 1075 int gc_flags, const GCCallbackFlags gc_callback_flags) { |
1083 if (incremental_marking()->IsStopped() && | 1076 if (incremental_marking()->IsStopped()) { |
1084 incremental_marking()->ShouldActivateEvenWithoutIdleNotification()) { | 1077 IncrementalMarkingLimit reached_limit = IncrementalMarkingLimitReached(); |
1085 StartIncrementalMarking(gc_flags, GarbageCollectionReason::kAllocationLimit, | 1078 if (reached_limit == IncrementalMarkingLimit::kSoftLimit) { |
1086 gc_callback_flags); | 1079 incremental_marking()->incremental_marking_job()->ScheduleTask(this); |
| 1080 } else if (reached_limit == IncrementalMarkingLimit::kHardLimit) { |
| 1081 StartIncrementalMarking(gc_flags, |
| 1082 GarbageCollectionReason::kAllocationLimit, |
| 1083 gc_callback_flags); |
| 1084 } |
1087 } | 1085 } |
1088 } | 1086 } |
1089 | 1087 |
1090 void Heap::StartIdleIncrementalMarking(GarbageCollectionReason gc_reason) { | 1088 void Heap::StartIdleIncrementalMarking(GarbageCollectionReason gc_reason) { |
1091 gc_idle_time_handler_->ResetNoProgressCounter(); | 1089 gc_idle_time_handler_->ResetNoProgressCounter(); |
1092 StartIncrementalMarking(kReduceMemoryFootprintMask, gc_reason, | 1090 StartIncrementalMarking(kReduceMemoryFootprintMask, gc_reason, |
1093 kNoGCCallbackFlags); | 1091 kNoGCCallbackFlags); |
1094 } | 1092 } |
1095 | 1093 |
1096 | 1094 |
(...skipping 4228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5325 CalculateOldGenerationAllocationLimit(factor, old_gen_size); | 5323 CalculateOldGenerationAllocationLimit(factor, old_gen_size); |
5326 | 5324 |
5327 if (FLAG_trace_gc_verbose) { | 5325 if (FLAG_trace_gc_verbose) { |
5328 isolate_->PrintWithTimestamp("Grow: old size: %" V8PRIdPTR | 5326 isolate_->PrintWithTimestamp("Grow: old size: %" V8PRIdPTR |
5329 " KB, new limit: %" V8PRIdPTR " KB (%.1f)\n", | 5327 " KB, new limit: %" V8PRIdPTR " KB (%.1f)\n", |
5330 old_gen_size / KB, | 5328 old_gen_size / KB, |
5331 old_generation_allocation_limit_ / KB, factor); | 5329 old_generation_allocation_limit_ / KB, factor); |
5332 } | 5330 } |
5333 } | 5331 } |
5334 | 5332 |
5335 | |
5336 void Heap::DampenOldGenerationAllocationLimit(intptr_t old_gen_size, | 5333 void Heap::DampenOldGenerationAllocationLimit(intptr_t old_gen_size, |
5337 double gc_speed, | 5334 double gc_speed, |
5338 double mutator_speed) { | 5335 double mutator_speed) { |
5339 double factor = HeapGrowingFactor(gc_speed, mutator_speed); | 5336 double factor = HeapGrowingFactor(gc_speed, mutator_speed); |
5340 intptr_t limit = CalculateOldGenerationAllocationLimit(factor, old_gen_size); | 5337 intptr_t limit = CalculateOldGenerationAllocationLimit(factor, old_gen_size); |
5341 if (limit < old_generation_allocation_limit_) { | 5338 if (limit < old_generation_allocation_limit_) { |
5342 if (FLAG_trace_gc_verbose) { | 5339 if (FLAG_trace_gc_verbose) { |
5343 isolate_->PrintWithTimestamp( | 5340 isolate_->PrintWithTimestamp( |
5344 "Dampen: old size: %" V8PRIdPTR " KB, old limit: %" V8PRIdPTR | 5341 "Dampen: old size: %" V8PRIdPTR " KB, old limit: %" V8PRIdPTR |
5345 " KB, " | 5342 " KB, " |
5346 "new limit: %" V8PRIdPTR " KB (%.1f)\n", | 5343 "new limit: %" V8PRIdPTR " KB (%.1f)\n", |
5347 old_gen_size / KB, old_generation_allocation_limit_ / KB, limit / KB, | 5344 old_gen_size / KB, old_generation_allocation_limit_ / KB, limit / KB, |
5348 factor); | 5345 factor); |
5349 } | 5346 } |
5350 old_generation_allocation_limit_ = limit; | 5347 old_generation_allocation_limit_ = limit; |
5351 } | 5348 } |
5352 } | 5349 } |
5353 | 5350 |
| 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 } |
5354 | 5398 |
5355 void Heap::EnableInlineAllocation() { | 5399 void Heap::EnableInlineAllocation() { |
5356 if (!inline_allocation_disabled_) return; | 5400 if (!inline_allocation_disabled_) return; |
5357 inline_allocation_disabled_ = false; | 5401 inline_allocation_disabled_ = false; |
5358 | 5402 |
5359 // Update inline allocation limit for new space. | 5403 // Update inline allocation limit for new space. |
5360 new_space()->UpdateInlineAllocationLimit(0); | 5404 new_space()->UpdateInlineAllocationLimit(0); |
5361 } | 5405 } |
5362 | 5406 |
5363 | 5407 |
(...skipping 1107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6471 } | 6515 } |
6472 | 6516 |
6473 | 6517 |
6474 // static | 6518 // static |
6475 int Heap::GetStaticVisitorIdForMap(Map* map) { | 6519 int Heap::GetStaticVisitorIdForMap(Map* map) { |
6476 return StaticVisitorBase::GetVisitorId(map); | 6520 return StaticVisitorBase::GetVisitorId(map); |
6477 } | 6521 } |
6478 | 6522 |
6479 } // namespace internal | 6523 } // namespace internal |
6480 } // namespace v8 | 6524 } // namespace v8 |
OLD | NEW |