| 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 1113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1124 incremental_marking()->NotifyOfHighPromotionRate(); | 1124 incremental_marking()->NotifyOfHighPromotionRate(); |
| 1125 } | 1125 } |
| 1126 | 1126 |
| 1127 if (collector == MARK_COMPACTOR) { | 1127 if (collector == MARK_COMPACTOR) { |
| 1128 // Perform mark-sweep with optional compaction. | 1128 // Perform mark-sweep with optional compaction. |
| 1129 MarkCompact(); | 1129 MarkCompact(); |
| 1130 sweep_generation_++; | 1130 sweep_generation_++; |
| 1131 // Temporarily set the limit for case when PostGarbageCollectionProcessing | 1131 // Temporarily set the limit for case when PostGarbageCollectionProcessing |
| 1132 // allocates and triggers GC. The real limit is set at after | 1132 // allocates and triggers GC. The real limit is set at after |
| 1133 // PostGarbageCollectionProcessing. | 1133 // PostGarbageCollectionProcessing. |
| 1134 old_generation_allocation_limit_ = | 1134 SetOldGenerationAllocationLimit(PromotedSpaceSizeOfObjects(), 0); |
| 1135 OldGenerationAllocationLimit(PromotedSpaceSizeOfObjects(), 0); | |
| 1136 old_gen_exhausted_ = false; | 1135 old_gen_exhausted_ = false; |
| 1137 old_generation_size_configured_ = true; | 1136 old_generation_size_configured_ = true; |
| 1138 } else { | 1137 } else { |
| 1139 Scavenge(); | 1138 Scavenge(); |
| 1140 } | 1139 } |
| 1141 | 1140 |
| 1142 UpdateSurvivalStatistics(start_new_space_size); | 1141 UpdateSurvivalStatistics(start_new_space_size); |
| 1143 ConfigureInitialOldGenerationSize(); | 1142 ConfigureInitialOldGenerationSize(); |
| 1144 | 1143 |
| 1145 isolate_->counters()->objs_since_last_young()->Set(0); | 1144 isolate_->counters()->objs_since_last_young()->Set(0); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1159 | 1158 |
| 1160 isolate_->eternal_handles()->PostGarbageCollectionProcessing(this); | 1159 isolate_->eternal_handles()->PostGarbageCollectionProcessing(this); |
| 1161 | 1160 |
| 1162 // Update relocatables. | 1161 // Update relocatables. |
| 1163 Relocatable::PostGarbageCollectionProcessing(isolate_); | 1162 Relocatable::PostGarbageCollectionProcessing(isolate_); |
| 1164 | 1163 |
| 1165 if (collector == MARK_COMPACTOR) { | 1164 if (collector == MARK_COMPACTOR) { |
| 1166 // Register the amount of external allocated memory. | 1165 // Register the amount of external allocated memory. |
| 1167 amount_of_external_allocated_memory_at_last_global_gc_ = | 1166 amount_of_external_allocated_memory_at_last_global_gc_ = |
| 1168 amount_of_external_allocated_memory_; | 1167 amount_of_external_allocated_memory_; |
| 1169 old_generation_allocation_limit_ = OldGenerationAllocationLimit( | 1168 SetOldGenerationAllocationLimit(PromotedSpaceSizeOfObjects(), |
| 1170 PromotedSpaceSizeOfObjects(), freed_global_handles); | 1169 freed_global_handles); |
| 1171 // We finished a marking cycle. We can uncommit the marking deque until | 1170 // We finished a marking cycle. We can uncommit the marking deque until |
| 1172 // we start marking again. | 1171 // we start marking again. |
| 1173 mark_compact_collector_.UncommitMarkingDeque(); | 1172 mark_compact_collector_.UncommitMarkingDeque(); |
| 1174 } | 1173 } |
| 1175 | 1174 |
| 1176 { | 1175 { |
| 1177 GCCallbacksScope scope(this); | 1176 GCCallbacksScope scope(this); |
| 1178 if (scope.CheckReenter()) { | 1177 if (scope.CheckReenter()) { |
| 1179 AllowHeapAllocation allow_allocation; | 1178 AllowHeapAllocation allow_allocation; |
| 1180 GCTracer::Scope scope(tracer(), GCTracer::Scope::EXTERNAL); | 1179 GCTracer::Scope scope(tracer(), GCTracer::Scope::EXTERNAL); |
| (...skipping 3360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4541 final_incremental_mark_compact_speed_in_bytes_per_ms))) { | 4540 final_incremental_mark_compact_speed_in_bytes_per_ms))) { |
| 4542 CollectAllGarbage(kNoGCFlags, "idle notification: finalize incremental"); | 4541 CollectAllGarbage(kNoGCFlags, "idle notification: finalize incremental"); |
| 4543 return true; | 4542 return true; |
| 4544 } | 4543 } |
| 4545 return false; | 4544 return false; |
| 4546 } | 4545 } |
| 4547 | 4546 |
| 4548 | 4547 |
| 4549 bool Heap::WorthActivatingIncrementalMarking() { | 4548 bool Heap::WorthActivatingIncrementalMarking() { |
| 4550 return incremental_marking()->IsStopped() && | 4549 return incremental_marking()->IsStopped() && |
| 4551 incremental_marking()->WorthActivating() && NextGCIsLikelyToBeFull(); | 4550 incremental_marking()->ShouldActivate(); |
| 4552 } | 4551 } |
| 4553 | 4552 |
| 4554 | 4553 |
| 4555 static double MonotonicallyIncreasingTimeInMs() { | 4554 static double MonotonicallyIncreasingTimeInMs() { |
| 4556 return V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() * | 4555 return V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() * |
| 4557 static_cast<double>(base::Time::kMillisecondsPerSecond); | 4556 static_cast<double>(base::Time::kMillisecondsPerSecond); |
| 4558 } | 4557 } |
| 4559 | 4558 |
| 4560 | 4559 |
| 4561 bool Heap::IdleNotification(int idle_time_in_ms) { | 4560 bool Heap::IdleNotification(int idle_time_in_ms) { |
| 4562 return IdleNotification( | 4561 return IdleNotification( |
| 4563 V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() + | 4562 V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() + |
| 4564 (static_cast<double>(idle_time_in_ms) / | 4563 (static_cast<double>(idle_time_in_ms) / |
| 4565 static_cast<double>(base::Time::kMillisecondsPerSecond))); | 4564 static_cast<double>(base::Time::kMillisecondsPerSecond))); |
| 4566 } | 4565 } |
| 4567 | 4566 |
| 4568 | 4567 |
| 4569 bool Heap::IdleNotification(double deadline_in_seconds) { | 4568 bool Heap::IdleNotification(double deadline_in_seconds) { |
| 4570 CHECK(HasBeenSetUp()); // http://crbug.com/425035 | 4569 CHECK(HasBeenSetUp()); // http://crbug.com/425035 |
| 4571 double deadline_in_ms = | 4570 double deadline_in_ms = |
| 4572 deadline_in_seconds * | 4571 deadline_in_seconds * |
| 4573 static_cast<double>(base::Time::kMillisecondsPerSecond); | 4572 static_cast<double>(base::Time::kMillisecondsPerSecond); |
| 4574 HistogramTimerScope idle_notification_scope( | 4573 HistogramTimerScope idle_notification_scope( |
| 4575 isolate_->counters()->gc_idle_notification()); | 4574 isolate_->counters()->gc_idle_notification()); |
| 4575 double idle_time_in_ms = deadline_in_ms - MonotonicallyIncreasingTimeInMs(); |
| 4576 | 4576 |
| 4577 GCIdleTimeHandler::HeapState heap_state; | 4577 GCIdleTimeHandler::HeapState heap_state; |
| 4578 heap_state.contexts_disposed = contexts_disposed_; | 4578 heap_state.contexts_disposed = contexts_disposed_; |
| 4579 heap_state.contexts_disposal_rate = | 4579 heap_state.contexts_disposal_rate = |
| 4580 tracer()->ContextDisposalRateInMilliseconds(); | 4580 tracer()->ContextDisposalRateInMilliseconds(); |
| 4581 heap_state.size_of_objects = static_cast<size_t>(SizeOfObjects()); | 4581 heap_state.size_of_objects = static_cast<size_t>(SizeOfObjects()); |
| 4582 heap_state.incremental_marking_stopped = incremental_marking()->IsStopped(); | 4582 heap_state.incremental_marking_stopped = incremental_marking()->IsStopped(); |
| 4583 // TODO(ulan): Start incremental marking only for large heaps. | 4583 // TODO(ulan): Start incremental marking only for large heaps. |
| 4584 intptr_t limit = old_generation_allocation_limit_; |
| 4585 if (static_cast<size_t>(idle_time_in_ms) > |
| 4586 GCIdleTimeHandler::kMaxFrameRenderingIdleTime) { |
| 4587 limit = idle_old_generation_allocation_limit_; |
| 4588 } |
| 4589 |
| 4584 heap_state.can_start_incremental_marking = | 4590 heap_state.can_start_incremental_marking = |
| 4585 incremental_marking()->ShouldActivate() && FLAG_incremental_marking && | 4591 incremental_marking()->WorthActivating() && |
| 4592 NextGCIsLikelyToBeFull(limit) && FLAG_incremental_marking && |
| 4586 !mark_compact_collector()->sweeping_in_progress(); | 4593 !mark_compact_collector()->sweeping_in_progress(); |
| 4587 heap_state.sweeping_in_progress = | 4594 heap_state.sweeping_in_progress = |
| 4588 mark_compact_collector()->sweeping_in_progress(); | 4595 mark_compact_collector()->sweeping_in_progress(); |
| 4589 heap_state.sweeping_completed = | 4596 heap_state.sweeping_completed = |
| 4590 mark_compact_collector()->IsSweepingCompleted(); | 4597 mark_compact_collector()->IsSweepingCompleted(); |
| 4591 heap_state.mark_compact_speed_in_bytes_per_ms = | 4598 heap_state.mark_compact_speed_in_bytes_per_ms = |
| 4592 static_cast<size_t>(tracer()->MarkCompactSpeedInBytesPerMillisecond()); | 4599 static_cast<size_t>(tracer()->MarkCompactSpeedInBytesPerMillisecond()); |
| 4593 heap_state.incremental_marking_speed_in_bytes_per_ms = static_cast<size_t>( | 4600 heap_state.incremental_marking_speed_in_bytes_per_ms = static_cast<size_t>( |
| 4594 tracer()->IncrementalMarkingSpeedInBytesPerMillisecond()); | 4601 tracer()->IncrementalMarkingSpeedInBytesPerMillisecond()); |
| 4595 heap_state.final_incremental_mark_compact_speed_in_bytes_per_ms = | 4602 heap_state.final_incremental_mark_compact_speed_in_bytes_per_ms = |
| 4596 static_cast<size_t>( | 4603 static_cast<size_t>( |
| 4597 tracer()->FinalIncrementalMarkCompactSpeedInBytesPerMillisecond()); | 4604 tracer()->FinalIncrementalMarkCompactSpeedInBytesPerMillisecond()); |
| 4598 heap_state.scavenge_speed_in_bytes_per_ms = | 4605 heap_state.scavenge_speed_in_bytes_per_ms = |
| 4599 static_cast<size_t>(tracer()->ScavengeSpeedInBytesPerMillisecond()); | 4606 static_cast<size_t>(tracer()->ScavengeSpeedInBytesPerMillisecond()); |
| 4600 heap_state.used_new_space_size = new_space_.Size(); | 4607 heap_state.used_new_space_size = new_space_.Size(); |
| 4601 heap_state.new_space_capacity = new_space_.Capacity(); | 4608 heap_state.new_space_capacity = new_space_.Capacity(); |
| 4602 heap_state.new_space_allocation_throughput_in_bytes_per_ms = | 4609 heap_state.new_space_allocation_throughput_in_bytes_per_ms = |
| 4603 static_cast<size_t>( | 4610 static_cast<size_t>( |
| 4604 tracer()->NewSpaceAllocationThroughputInBytesPerMillisecond()); | 4611 tracer()->NewSpaceAllocationThroughputInBytesPerMillisecond()); |
| 4605 | 4612 |
| 4606 double idle_time_in_ms = deadline_in_ms - MonotonicallyIncreasingTimeInMs(); | |
| 4607 GCIdleTimeAction action = | 4613 GCIdleTimeAction action = |
| 4608 gc_idle_time_handler_.Compute(idle_time_in_ms, heap_state); | 4614 gc_idle_time_handler_.Compute(idle_time_in_ms, heap_state); |
| 4609 isolate()->counters()->gc_idle_time_allotted_in_ms()->AddSample( | 4615 isolate()->counters()->gc_idle_time_allotted_in_ms()->AddSample( |
| 4610 static_cast<int>(idle_time_in_ms)); | 4616 static_cast<int>(idle_time_in_ms)); |
| 4611 | 4617 |
| 4612 bool result = false; | 4618 bool result = false; |
| 4613 switch (action.type) { | 4619 switch (action.type) { |
| 4614 case DONE: | 4620 case DONE: |
| 4615 result = true; | 4621 result = true; |
| 4616 break; | 4622 break; |
| (...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5171 | 5177 |
| 5172 int64_t Heap::PromotedExternalMemorySize() { | 5178 int64_t Heap::PromotedExternalMemorySize() { |
| 5173 if (amount_of_external_allocated_memory_ <= | 5179 if (amount_of_external_allocated_memory_ <= |
| 5174 amount_of_external_allocated_memory_at_last_global_gc_) | 5180 amount_of_external_allocated_memory_at_last_global_gc_) |
| 5175 return 0; | 5181 return 0; |
| 5176 return amount_of_external_allocated_memory_ - | 5182 return amount_of_external_allocated_memory_ - |
| 5177 amount_of_external_allocated_memory_at_last_global_gc_; | 5183 amount_of_external_allocated_memory_at_last_global_gc_; |
| 5178 } | 5184 } |
| 5179 | 5185 |
| 5180 | 5186 |
| 5181 intptr_t Heap::OldGenerationAllocationLimit(intptr_t old_gen_size, | 5187 intptr_t Heap::CalculateOldGenerationAllocationLimit(double factor, |
| 5182 int freed_global_handles) { | 5188 intptr_t old_gen_size) { |
| 5189 CHECK(factor > 1.0); |
| 5190 CHECK(old_gen_size > 0); |
| 5191 intptr_t limit = static_cast<intptr_t>(old_gen_size * factor); |
| 5192 limit = Max(limit, kMinimumOldGenerationAllocationLimit); |
| 5193 limit += new_space_.Capacity(); |
| 5194 intptr_t halfway_to_the_max = (old_gen_size + max_old_generation_size_) / 2; |
| 5195 return Min(limit, halfway_to_the_max); |
| 5196 } |
| 5197 |
| 5198 |
| 5199 void Heap::SetOldGenerationAllocationLimit(intptr_t old_gen_size, |
| 5200 int freed_global_handles) { |
| 5183 const int kMaxHandles = 1000; | 5201 const int kMaxHandles = 1000; |
| 5184 const int kMinHandles = 100; | 5202 const int kMinHandles = 100; |
| 5185 double min_factor = 1.1; | 5203 const double min_factor = 1.1; |
| 5186 double max_factor = 4; | 5204 double max_factor = 4; |
| 5205 const double idle_max_factor = 1.5; |
| 5187 // We set the old generation growing factor to 2 to grow the heap slower on | 5206 // We set the old generation growing factor to 2 to grow the heap slower on |
| 5188 // memory-constrained devices. | 5207 // memory-constrained devices. |
| 5189 if (max_old_generation_size_ <= kMaxOldSpaceSizeMediumMemoryDevice) { | 5208 if (max_old_generation_size_ <= kMaxOldSpaceSizeMediumMemoryDevice) { |
| 5190 max_factor = 2; | 5209 max_factor = 2; |
| 5191 } | 5210 } |
| 5211 |
| 5192 // If there are many freed global handles, then the next full GC will | 5212 // 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 | 5213 // likely collect a lot of garbage. Choose the heap growing factor |
| 5194 // depending on freed global handles. | 5214 // depending on freed global handles. |
| 5195 // TODO(ulan, hpayer): Take into account mutator utilization. | 5215 // TODO(ulan, hpayer): Take into account mutator utilization. |
| 5216 // TODO(hpayer): The idle factor could make the handles heuristic obsolete. |
| 5217 // Look into that. |
| 5196 double factor; | 5218 double factor; |
| 5197 if (freed_global_handles <= kMinHandles) { | 5219 if (freed_global_handles <= kMinHandles) { |
| 5198 factor = max_factor; | 5220 factor = max_factor; |
| 5199 } else if (freed_global_handles >= kMaxHandles) { | 5221 } else if (freed_global_handles >= kMaxHandles) { |
| 5200 factor = min_factor; | 5222 factor = min_factor; |
| 5201 } else { | 5223 } else { |
| 5202 // Compute factor using linear interpolation between points | 5224 // Compute factor using linear interpolation between points |
| 5203 // (kMinHandles, max_factor) and (kMaxHandles, min_factor). | 5225 // (kMinHandles, max_factor) and (kMaxHandles, min_factor). |
| 5204 factor = max_factor - | 5226 factor = max_factor - |
| 5205 (freed_global_handles - kMinHandles) * (max_factor - min_factor) / | 5227 (freed_global_handles - kMinHandles) * (max_factor - min_factor) / |
| 5206 (kMaxHandles - kMinHandles); | 5228 (kMaxHandles - kMinHandles); |
| 5207 } | 5229 } |
| 5208 | 5230 |
| 5209 if (FLAG_stress_compaction || | 5231 if (FLAG_stress_compaction || |
| 5210 mark_compact_collector()->reduce_memory_footprint_) { | 5232 mark_compact_collector()->reduce_memory_footprint_) { |
| 5211 factor = min_factor; | 5233 factor = min_factor; |
| 5212 } | 5234 } |
| 5213 | 5235 |
| 5214 intptr_t limit = static_cast<intptr_t>(old_gen_size * factor); | 5236 old_generation_allocation_limit_ = |
| 5215 limit = Max(limit, kMinimumOldGenerationAllocationLimit); | 5237 CalculateOldGenerationAllocationLimit(factor, old_gen_size); |
| 5216 limit += new_space_.Capacity(); | 5238 idle_old_generation_allocation_limit_ = CalculateOldGenerationAllocationLimit( |
| 5217 intptr_t halfway_to_the_max = (old_gen_size + max_old_generation_size_) / 2; | 5239 Min(factor, idle_max_factor), old_gen_size); |
| 5218 return Min(limit, halfway_to_the_max); | |
| 5219 } | 5240 } |
| 5220 | 5241 |
| 5221 | 5242 |
| 5222 void Heap::EnableInlineAllocation() { | 5243 void Heap::EnableInlineAllocation() { |
| 5223 if (!inline_allocation_disabled_) return; | 5244 if (!inline_allocation_disabled_) return; |
| 5224 inline_allocation_disabled_ = false; | 5245 inline_allocation_disabled_ = false; |
| 5225 | 5246 |
| 5226 // Update inline allocation limit for new space. | 5247 // Update inline allocation limit for new space. |
| 5227 new_space()->UpdateInlineAllocationLimit(0); | 5248 new_space()->UpdateInlineAllocationLimit(0); |
| 5228 } | 5249 } |
| (...skipping 1125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6354 static_cast<int>(object_sizes_last_time_[index])); | 6375 static_cast<int>(object_sizes_last_time_[index])); |
| 6355 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) | 6376 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) |
| 6356 #undef ADJUST_LAST_TIME_OBJECT_COUNT | 6377 #undef ADJUST_LAST_TIME_OBJECT_COUNT |
| 6357 | 6378 |
| 6358 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); | 6379 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); |
| 6359 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); | 6380 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); |
| 6360 ClearObjectStats(); | 6381 ClearObjectStats(); |
| 6361 } | 6382 } |
| 6362 } | 6383 } |
| 6363 } // namespace v8::internal | 6384 } // namespace v8::internal |
| OLD | NEW |