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