Chromium Code Reviews| 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 |