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/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/base/once.h" | 10 #include "src/base/once.h" |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
94 raw_allocations_hash_(0), | 94 raw_allocations_hash_(0), |
95 dump_allocations_hash_countdown_(FLAG_dump_allocations_digest_at_alloc), | 95 dump_allocations_hash_countdown_(FLAG_dump_allocations_digest_at_alloc), |
96 ms_count_(0), | 96 ms_count_(0), |
97 gc_count_(0), | 97 gc_count_(0), |
98 remembered_unmapped_pages_index_(0), | 98 remembered_unmapped_pages_index_(0), |
99 unflattened_strings_length_(0), | 99 unflattened_strings_length_(0), |
100 #ifdef DEBUG | 100 #ifdef DEBUG |
101 allocation_timeout_(0), | 101 allocation_timeout_(0), |
102 #endif // DEBUG | 102 #endif // DEBUG |
103 old_generation_allocation_limit_(initial_old_generation_size_), | 103 old_generation_allocation_limit_(initial_old_generation_size_), |
104 min_old_generation_growing_factor_(1.1), | |
105 max_old_generation_growing_factor_(4.0), | |
106 idle_old_generation_growing_factor_(1.5), | |
107 current_old_generation_growing_factor_( | |
108 max_old_generation_growing_factor_), | |
104 old_gen_exhausted_(false), | 109 old_gen_exhausted_(false), |
105 inline_allocation_disabled_(false), | 110 inline_allocation_disabled_(false), |
106 store_buffer_rebuilder_(store_buffer()), | 111 store_buffer_rebuilder_(store_buffer()), |
107 hidden_string_(NULL), | 112 hidden_string_(NULL), |
108 gc_safe_size_of_old_object_(NULL), | 113 gc_safe_size_of_old_object_(NULL), |
109 total_regexp_code_generated_(0), | 114 total_regexp_code_generated_(0), |
110 tracer_(this), | 115 tracer_(this), |
111 high_survival_rate_period_length_(0), | 116 high_survival_rate_period_length_(0), |
112 promoted_objects_size_(0), | 117 promoted_objects_size_(0), |
113 promotion_ratio_(0), | 118 promotion_ratio_(0), |
(...skipping 4427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4541 final_incremental_mark_compact_speed_in_bytes_per_ms))) { | 4546 final_incremental_mark_compact_speed_in_bytes_per_ms))) { |
4542 CollectAllGarbage(kNoGCFlags, "idle notification: finalize incremental"); | 4547 CollectAllGarbage(kNoGCFlags, "idle notification: finalize incremental"); |
4543 return true; | 4548 return true; |
4544 } | 4549 } |
4545 return false; | 4550 return false; |
4546 } | 4551 } |
4547 | 4552 |
4548 | 4553 |
4549 bool Heap::WorthActivatingIncrementalMarking() { | 4554 bool Heap::WorthActivatingIncrementalMarking() { |
4550 return incremental_marking()->IsStopped() && | 4555 return incremental_marking()->IsStopped() && |
4551 incremental_marking()->WorthActivating() && NextGCIsLikelyToBeFull(); | 4556 incremental_marking()->ShouldActivate(); |
4552 } | 4557 } |
4553 | 4558 |
4554 | 4559 |
4555 static double MonotonicallyIncreasingTimeInMs() { | 4560 static double MonotonicallyIncreasingTimeInMs() { |
4556 return V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() * | 4561 return V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() * |
4557 static_cast<double>(base::Time::kMillisecondsPerSecond); | 4562 static_cast<double>(base::Time::kMillisecondsPerSecond); |
4558 } | 4563 } |
4559 | 4564 |
4560 | 4565 |
4561 bool Heap::IdleNotification(int idle_time_in_ms) { | 4566 bool Heap::IdleNotification(int idle_time_in_ms) { |
4562 return IdleNotification( | 4567 return IdleNotification( |
4563 V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() + | 4568 V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() + |
4564 (static_cast<double>(idle_time_in_ms) / | 4569 (static_cast<double>(idle_time_in_ms) / |
4565 static_cast<double>(base::Time::kMillisecondsPerSecond))); | 4570 static_cast<double>(base::Time::kMillisecondsPerSecond))); |
4566 } | 4571 } |
4567 | 4572 |
4568 | 4573 |
4569 bool Heap::IdleNotification(double deadline_in_seconds) { | 4574 bool Heap::IdleNotification(double deadline_in_seconds) { |
4570 CHECK(HasBeenSetUp()); // http://crbug.com/425035 | 4575 CHECK(HasBeenSetUp()); // http://crbug.com/425035 |
4571 double deadline_in_ms = | 4576 double deadline_in_ms = |
4572 deadline_in_seconds * | 4577 deadline_in_seconds * |
4573 static_cast<double>(base::Time::kMillisecondsPerSecond); | 4578 static_cast<double>(base::Time::kMillisecondsPerSecond); |
4574 HistogramTimerScope idle_notification_scope( | 4579 HistogramTimerScope idle_notification_scope( |
4575 isolate_->counters()->gc_idle_notification()); | 4580 isolate_->counters()->gc_idle_notification()); |
4581 double idle_time_in_ms = deadline_in_ms - MonotonicallyIncreasingTimeInMs(); | |
4576 | 4582 |
4577 GCIdleTimeHandler::HeapState heap_state; | 4583 GCIdleTimeHandler::HeapState heap_state; |
4578 heap_state.contexts_disposed = contexts_disposed_; | 4584 heap_state.contexts_disposed = contexts_disposed_; |
4579 heap_state.contexts_disposal_rate = | 4585 heap_state.contexts_disposal_rate = |
4580 tracer()->ContextDisposalRateInMilliseconds(); | 4586 tracer()->ContextDisposalRateInMilliseconds(); |
4581 heap_state.size_of_objects = static_cast<size_t>(SizeOfObjects()); | 4587 heap_state.size_of_objects = static_cast<size_t>(SizeOfObjects()); |
4582 heap_state.incremental_marking_stopped = incremental_marking()->IsStopped(); | 4588 heap_state.incremental_marking_stopped = incremental_marking()->IsStopped(); |
4583 // TODO(ulan): Start incremental marking only for large heaps. | 4589 // TODO(ulan): Start incremental marking only for large heaps. |
4590 intptr_t limit = old_generation_allocation_limit_; | |
4591 if (static_cast<size_t>(idle_time_in_ms) > | |
4592 GCIdleTimeHandler::kMaxFrameRenderingIdleTime) { | |
4593 limit = | |
ulan
2015/04/16 14:17:21
Instead of storing current_old_generation_growing_
Hannes Payer (out of office)
2015/04/16 14:46:45
Done.
| |
4594 static_cast<intptr_t>((limit / current_old_generation_growing_factor_) * | |
4595 idle_old_generation_growing_factor_); | |
4596 } | |
4597 | |
4584 heap_state.can_start_incremental_marking = | 4598 heap_state.can_start_incremental_marking = |
4585 incremental_marking()->ShouldActivate() && FLAG_incremental_marking && | 4599 incremental_marking()->WorthActivating() && |
4600 NextGCIsLikelyToBeFull(limit) && FLAG_incremental_marking && | |
4586 !mark_compact_collector()->sweeping_in_progress(); | 4601 !mark_compact_collector()->sweeping_in_progress(); |
4587 heap_state.sweeping_in_progress = | 4602 heap_state.sweeping_in_progress = |
4588 mark_compact_collector()->sweeping_in_progress(); | 4603 mark_compact_collector()->sweeping_in_progress(); |
4589 heap_state.sweeping_completed = | 4604 heap_state.sweeping_completed = |
4590 mark_compact_collector()->IsSweepingCompleted(); | 4605 mark_compact_collector()->IsSweepingCompleted(); |
4591 heap_state.mark_compact_speed_in_bytes_per_ms = | 4606 heap_state.mark_compact_speed_in_bytes_per_ms = |
4592 static_cast<size_t>(tracer()->MarkCompactSpeedInBytesPerMillisecond()); | 4607 static_cast<size_t>(tracer()->MarkCompactSpeedInBytesPerMillisecond()); |
4593 heap_state.incremental_marking_speed_in_bytes_per_ms = static_cast<size_t>( | 4608 heap_state.incremental_marking_speed_in_bytes_per_ms = static_cast<size_t>( |
4594 tracer()->IncrementalMarkingSpeedInBytesPerMillisecond()); | 4609 tracer()->IncrementalMarkingSpeedInBytesPerMillisecond()); |
4595 heap_state.final_incremental_mark_compact_speed_in_bytes_per_ms = | 4610 heap_state.final_incremental_mark_compact_speed_in_bytes_per_ms = |
4596 static_cast<size_t>( | 4611 static_cast<size_t>( |
4597 tracer()->FinalIncrementalMarkCompactSpeedInBytesPerMillisecond()); | 4612 tracer()->FinalIncrementalMarkCompactSpeedInBytesPerMillisecond()); |
4598 heap_state.scavenge_speed_in_bytes_per_ms = | 4613 heap_state.scavenge_speed_in_bytes_per_ms = |
4599 static_cast<size_t>(tracer()->ScavengeSpeedInBytesPerMillisecond()); | 4614 static_cast<size_t>(tracer()->ScavengeSpeedInBytesPerMillisecond()); |
4600 heap_state.used_new_space_size = new_space_.Size(); | 4615 heap_state.used_new_space_size = new_space_.Size(); |
4601 heap_state.new_space_capacity = new_space_.Capacity(); | 4616 heap_state.new_space_capacity = new_space_.Capacity(); |
4602 heap_state.new_space_allocation_throughput_in_bytes_per_ms = | 4617 heap_state.new_space_allocation_throughput_in_bytes_per_ms = |
4603 static_cast<size_t>( | 4618 static_cast<size_t>( |
4604 tracer()->NewSpaceAllocationThroughputInBytesPerMillisecond()); | 4619 tracer()->NewSpaceAllocationThroughputInBytesPerMillisecond()); |
4605 | 4620 |
4606 double idle_time_in_ms = deadline_in_ms - MonotonicallyIncreasingTimeInMs(); | |
4607 GCIdleTimeAction action = | 4621 GCIdleTimeAction action = |
4608 gc_idle_time_handler_.Compute(idle_time_in_ms, heap_state); | 4622 gc_idle_time_handler_.Compute(idle_time_in_ms, heap_state); |
4609 isolate()->counters()->gc_idle_time_allotted_in_ms()->AddSample( | 4623 isolate()->counters()->gc_idle_time_allotted_in_ms()->AddSample( |
4610 static_cast<int>(idle_time_in_ms)); | 4624 static_cast<int>(idle_time_in_ms)); |
4611 | 4625 |
4612 bool result = false; | 4626 bool result = false; |
4613 switch (action.type) { | 4627 switch (action.type) { |
4614 case DONE: | 4628 case DONE: |
4615 result = true; | 4629 result = true; |
4616 break; | 4630 break; |
(...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5100 if (FLAG_semi_space_growth_factor < 2) { | 5114 if (FLAG_semi_space_growth_factor < 2) { |
5101 FLAG_semi_space_growth_factor = 2; | 5115 FLAG_semi_space_growth_factor = 2; |
5102 } | 5116 } |
5103 | 5117 |
5104 // The old generation is paged and needs at least one page for each space. | 5118 // The old generation is paged and needs at least one page for each space. |
5105 int paged_space_count = LAST_PAGED_SPACE - FIRST_PAGED_SPACE + 1; | 5119 int paged_space_count = LAST_PAGED_SPACE - FIRST_PAGED_SPACE + 1; |
5106 max_old_generation_size_ = | 5120 max_old_generation_size_ = |
5107 Max(static_cast<intptr_t>(paged_space_count * Page::kPageSize), | 5121 Max(static_cast<intptr_t>(paged_space_count * Page::kPageSize), |
5108 max_old_generation_size_); | 5122 max_old_generation_size_); |
5109 | 5123 |
5124 | |
5125 // We set the old generation growing factor to 2 to grow the heap slower on | |
5126 // memory-constrained devices. | |
5127 if (max_old_generation_size_ <= kMaxOldSpaceSizeMediumMemoryDevice) { | |
5128 max_old_generation_growing_factor_ = 2; | |
5129 } | |
5130 | |
5110 if (FLAG_initial_old_space_size > 0) { | 5131 if (FLAG_initial_old_space_size > 0) { |
5111 initial_old_generation_size_ = FLAG_initial_old_space_size * MB; | 5132 initial_old_generation_size_ = FLAG_initial_old_space_size * MB; |
5112 } else { | 5133 } else { |
5113 initial_old_generation_size_ = | 5134 initial_old_generation_size_ = |
5114 max_old_generation_size_ / kInitalOldGenerationLimitFactor; | 5135 max_old_generation_size_ / kInitalOldGenerationLimitFactor; |
5115 } | 5136 } |
5116 old_generation_allocation_limit_ = initial_old_generation_size_; | 5137 old_generation_allocation_limit_ = initial_old_generation_size_; |
5117 | 5138 |
5118 // We rely on being able to allocate new arrays in paged spaces. | 5139 // We rely on being able to allocate new arrays in paged spaces. |
5119 DCHECK(Page::kMaxRegularHeapObjectSize >= | 5140 DCHECK(Page::kMaxRegularHeapObjectSize >= |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5175 return 0; | 5196 return 0; |
5176 return amount_of_external_allocated_memory_ - | 5197 return amount_of_external_allocated_memory_ - |
5177 amount_of_external_allocated_memory_at_last_global_gc_; | 5198 amount_of_external_allocated_memory_at_last_global_gc_; |
5178 } | 5199 } |
5179 | 5200 |
5180 | 5201 |
5181 intptr_t Heap::OldGenerationAllocationLimit(intptr_t old_gen_size, | 5202 intptr_t Heap::OldGenerationAllocationLimit(intptr_t old_gen_size, |
5182 int freed_global_handles) { | 5203 int freed_global_handles) { |
5183 const int kMaxHandles = 1000; | 5204 const int kMaxHandles = 1000; |
5184 const int kMinHandles = 100; | 5205 const int kMinHandles = 100; |
5185 double min_factor = 1.1; | 5206 |
5186 double max_factor = 1.5; | |
5187 // We set the old generation growing factor to 2 to grow the heap slower on | |
5188 // memory-constrained devices. | |
5189 if (max_old_generation_size_ <= kMaxOldSpaceSizeMediumMemoryDevice) { | |
5190 max_factor = 1.5; | |
5191 } | |
5192 // If there are many freed global handles, then the next full GC will | 5207 // If there are many freed global handles, then the next full GC will |
5193 // likely collect a lot of garbage. Choose the heap growing factor | 5208 // likely collect a lot of garbage. Choose the heap growing factor |
5194 // depending on freed global handles. | 5209 // depending on freed global handles. |
5195 // TODO(ulan, hpayer): Take into account mutator utilization. | 5210 // TODO(ulan, hpayer): Take into account mutator utilization. |
5211 // TODO(hpayer): The idle factor could make the handles heuristic obsolete. | |
5212 // Look into that. | |
5196 double factor; | 5213 double factor; |
5197 if (freed_global_handles <= kMinHandles) { | 5214 if (freed_global_handles <= kMinHandles) { |
5198 factor = max_factor; | 5215 factor = max_old_generation_growing_factor_; |
5199 } else if (freed_global_handles >= kMaxHandles) { | 5216 } else if (freed_global_handles >= kMaxHandles) { |
5200 factor = min_factor; | 5217 factor = min_old_generation_growing_factor_; |
5201 } else { | 5218 } else { |
5202 // Compute factor using linear interpolation between points | 5219 // Compute factor using linear interpolation between points |
5203 // (kMinHandles, max_factor) and (kMaxHandles, min_factor). | 5220 // (kMinHandles, max_factor) and (kMaxHandles, min_factor). |
5204 factor = max_factor - | 5221 factor = max_old_generation_growing_factor_ - |
5205 (freed_global_handles - kMinHandles) * (max_factor - min_factor) / | 5222 (freed_global_handles - kMinHandles) * |
5223 (max_old_generation_growing_factor_ - | |
5224 min_old_generation_growing_factor_) / | |
5206 (kMaxHandles - kMinHandles); | 5225 (kMaxHandles - kMinHandles); |
5207 } | 5226 } |
5208 | 5227 |
5209 if (FLAG_stress_compaction || | 5228 if (FLAG_stress_compaction || |
5210 mark_compact_collector()->reduce_memory_footprint_) { | 5229 mark_compact_collector()->reduce_memory_footprint_) { |
5211 factor = min_factor; | 5230 factor = min_old_generation_growing_factor_; |
5212 } | 5231 } |
5213 | 5232 |
5233 // When the limit is taken from halfway_to_the_max, the current factor | |
5234 // does not correspond to the original old generation size. However, it | |
5235 // may be close. | |
Erik Corry Chromium.org
2015/04/16 14:16:44
But it may not be close.
I'm not very happy with
Hannes Payer (out of office)
2015/04/16 14:46:45
Done.
| |
5236 current_old_generation_growing_factor_ = factor; | |
ulan
2015/04/16 14:17:22
Since it is used for just for the idle limit compu
Hannes Payer (out of office)
2015/04/16 14:46:45
Done.
| |
5237 | |
5214 intptr_t limit = static_cast<intptr_t>(old_gen_size * factor); | 5238 intptr_t limit = static_cast<intptr_t>(old_gen_size * factor); |
5215 limit = Max(limit, kMinimumOldGenerationAllocationLimit); | 5239 limit = Max(limit, kMinimumOldGenerationAllocationLimit); |
5216 limit += new_space_.Capacity(); | 5240 limit += new_space_.Capacity(); |
5217 intptr_t halfway_to_the_max = (old_gen_size + max_old_generation_size_) / 2; | 5241 intptr_t halfway_to_the_max = (old_gen_size + max_old_generation_size_) / 2; |
5218 return Min(limit, halfway_to_the_max); | 5242 return Min(limit, halfway_to_the_max); |
5219 } | 5243 } |
5220 | 5244 |
5221 | 5245 |
5222 void Heap::EnableInlineAllocation() { | 5246 void Heap::EnableInlineAllocation() { |
5223 if (!inline_allocation_disabled_) return; | 5247 if (!inline_allocation_disabled_) return; |
(...skipping 1085 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6309 static_cast<int>(object_sizes_last_time_[index])); | 6333 static_cast<int>(object_sizes_last_time_[index])); |
6310 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) | 6334 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) |
6311 #undef ADJUST_LAST_TIME_OBJECT_COUNT | 6335 #undef ADJUST_LAST_TIME_OBJECT_COUNT |
6312 | 6336 |
6313 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); | 6337 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); |
6314 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); | 6338 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); |
6315 ClearObjectStats(); | 6339 ClearObjectStats(); |
6316 } | 6340 } |
6317 } | 6341 } |
6318 } // namespace v8::internal | 6342 } // namespace v8::internal |
OLD | NEW |