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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 47 #include "src/mips/regexp-macro-assembler-mips.h" // NOLINT | 47 #include "src/mips/regexp-macro-assembler-mips.h" // NOLINT |
| 48 #endif | 48 #endif |
| 49 #if V8_TARGET_ARCH_MIPS64 && !V8_INTERPRETED_REGEXP | 49 #if V8_TARGET_ARCH_MIPS64 && !V8_INTERPRETED_REGEXP |
| 50 #include "src/regexp-macro-assembler.h" | 50 #include "src/regexp-macro-assembler.h" |
| 51 #include "src/mips64/regexp-macro-assembler-mips64.h" | 51 #include "src/mips64/regexp-macro-assembler-mips64.h" |
| 52 #endif | 52 #endif |
| 53 | 53 |
| 54 namespace v8 { | 54 namespace v8 { |
| 55 namespace internal { | 55 namespace internal { |
| 56 | 56 |
| 57 static const intptr_t kDefaultMaxOldGenSize = 700ul * (kPointerSize / 4) * MB; | |
|
Hannes Payer (out of office)
2015/03/25 14:30:06
Please define the constant next to the other heap
Erik Corry Chromium.org
2015/03/25 15:16:06
Done.
| |
| 57 | 58 |
| 58 Heap::Heap() | 59 Heap::Heap() |
| 59 : amount_of_external_allocated_memory_(0), | 60 : amount_of_external_allocated_memory_(0), |
| 60 amount_of_external_allocated_memory_at_last_global_gc_(0), | 61 amount_of_external_allocated_memory_at_last_global_gc_(0), |
| 61 isolate_(NULL), | 62 isolate_(NULL), |
| 62 code_range_size_(0), | 63 code_range_size_(0), |
| 63 // semispace_size_ should be a power of 2 and old_generation_size_ should | 64 // semispace_size_ should be a power of 2 and old_generation_size_ should |
| 64 // be a multiple of Page::kPageSize. | 65 // be a multiple of Page::kPageSize. |
| 65 reserved_semispace_size_(8 * (kPointerSize / 4) * MB), | 66 reserved_semispace_size_(8 * (kPointerSize / 4) * MB), |
| 66 max_semi_space_size_(8 * (kPointerSize / 4) * MB), | 67 max_semi_space_size_(8 * (kPointerSize / 4) * MB), |
| 67 initial_semispace_size_(Page::kPageSize), | 68 initial_semispace_size_(Page::kPageSize), |
| 68 target_semispace_size_(Page::kPageSize), | 69 target_semispace_size_(Page::kPageSize), |
| 69 max_old_generation_size_(700ul * (kPointerSize / 4) * MB), | 70 max_old_generation_size_(kDefaultMaxOldGenSize), |
| 70 initial_old_generation_size_(max_old_generation_size_ / | 71 initial_old_generation_size_(max_old_generation_size_ / |
| 71 kInitalOldGenerationLimitFactor), | 72 kInitalOldGenerationLimitFactor), |
| 72 old_generation_size_configured_(false), | 73 old_generation_size_configured_(false), |
| 73 max_executable_size_(256ul * (kPointerSize / 4) * MB), | 74 max_executable_size_(256ul * (kPointerSize / 4) * MB), |
| 74 // Variables set based on semispace_size_ and old_generation_size_ in | 75 // Variables set based on semispace_size_ and old_generation_size_ in |
| 75 // ConfigureHeap. | 76 // ConfigureHeap. |
| 76 // Will be 4 * reserved_semispace_size_ to ensure that young | 77 // Will be 4 * reserved_semispace_size_ to ensure that young |
| 77 // generation can be aligned to its size. | 78 // generation can be aligned to its size. |
| 78 maximum_committed_(0), | 79 maximum_committed_(0), |
| 79 survived_since_last_expansion_(0), | 80 survived_since_last_expansion_(0), |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 96 raw_allocations_hash_(0), | 97 raw_allocations_hash_(0), |
| 97 dump_allocations_hash_countdown_(FLAG_dump_allocations_digest_at_alloc), | 98 dump_allocations_hash_countdown_(FLAG_dump_allocations_digest_at_alloc), |
| 98 ms_count_(0), | 99 ms_count_(0), |
| 99 gc_count_(0), | 100 gc_count_(0), |
| 100 remembered_unmapped_pages_index_(0), | 101 remembered_unmapped_pages_index_(0), |
| 101 unflattened_strings_length_(0), | 102 unflattened_strings_length_(0), |
| 102 #ifdef DEBUG | 103 #ifdef DEBUG |
| 103 allocation_timeout_(0), | 104 allocation_timeout_(0), |
| 104 #endif // DEBUG | 105 #endif // DEBUG |
| 105 old_generation_allocation_limit_(initial_old_generation_size_), | 106 old_generation_allocation_limit_(initial_old_generation_size_), |
| 107 old_generation_committed_memory_limit_(kDefaultMaxOldGenSize >> 1), | |
|
Hannes Payer (out of office)
2015/03/25 14:30:06
why not set it to initial_old_generation_size_?
Erik Corry Chromium.org
2015/03/25 15:16:06
This is "halfway from here to the limit", which is
| |
| 106 old_gen_exhausted_(false), | 108 old_gen_exhausted_(false), |
| 107 inline_allocation_disabled_(false), | 109 inline_allocation_disabled_(false), |
| 108 store_buffer_rebuilder_(store_buffer()), | 110 store_buffer_rebuilder_(store_buffer()), |
| 109 hidden_string_(NULL), | 111 hidden_string_(NULL), |
| 110 gc_safe_size_of_old_object_(NULL), | 112 gc_safe_size_of_old_object_(NULL), |
| 111 total_regexp_code_generated_(0), | 113 total_regexp_code_generated_(0), |
| 112 tracer_(this), | 114 tracer_(this), |
| 113 high_survival_rate_period_length_(0), | 115 high_survival_rate_period_length_(0), |
| 114 promoted_objects_size_(0), | 116 promoted_objects_size_(0), |
| 115 promotion_ratio_(0), | 117 promotion_ratio_(0), |
| (...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 853 | 855 |
| 854 EnsureFillerObjectAtTop(); | 856 EnsureFillerObjectAtTop(); |
| 855 | 857 |
| 856 if (collector == SCAVENGER && !incremental_marking()->IsStopped()) { | 858 if (collector == SCAVENGER && !incremental_marking()->IsStopped()) { |
| 857 if (FLAG_trace_incremental_marking) { | 859 if (FLAG_trace_incremental_marking) { |
| 858 PrintF("[IncrementalMarking] Scavenge during marking.\n"); | 860 PrintF("[IncrementalMarking] Scavenge during marking.\n"); |
| 859 } | 861 } |
| 860 } | 862 } |
| 861 | 863 |
| 862 if (collector == MARK_COMPACTOR && | 864 if (collector == MARK_COMPACTOR && |
| 863 !mark_compact_collector()->abort_incremental_marking() && | 865 !mark_compact_collector()->incremental_marking_abort_requested() && |
| 864 !incremental_marking()->IsStopped() && | 866 !incremental_marking()->IsStopped() && |
| 865 !incremental_marking()->should_hurry() && | 867 !incremental_marking()->should_hurry() && |
| 866 FLAG_incremental_marking_steps) { | 868 FLAG_incremental_marking_steps) { |
| 867 // Make progress in incremental marking. | 869 // Make progress in incremental marking. |
| 868 const intptr_t kStepSizeWhenDelayedByScavenge = 1 * MB; | 870 const intptr_t kStepSizeWhenDelayedByScavenge = 1 * MB; |
| 869 incremental_marking()->Step(kStepSizeWhenDelayedByScavenge, | 871 incremental_marking()->Step(kStepSizeWhenDelayedByScavenge, |
| 870 IncrementalMarking::NO_GC_VIA_STACK_GUARD); | 872 IncrementalMarking::NO_GC_VIA_STACK_GUARD); |
| 871 if (!incremental_marking()->IsComplete() && | 873 if (!incremental_marking()->IsComplete() && |
| 872 !mark_compact_collector_.marking_deque_.IsEmpty() && !FLAG_gc_global) { | 874 !mark_compact_collector_.marking_deque_.IsEmpty() && !FLAG_gc_global) { |
| 873 if (FLAG_trace_incremental_marking) { | 875 if (FLAG_trace_incremental_marking) { |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 896 | 898 |
| 897 GarbageCollectionEpilogue(); | 899 GarbageCollectionEpilogue(); |
| 898 if (collector == MARK_COMPACTOR && FLAG_track_detached_contexts) { | 900 if (collector == MARK_COMPACTOR && FLAG_track_detached_contexts) { |
| 899 isolate()->CheckDetachedContextsAfterGC(); | 901 isolate()->CheckDetachedContextsAfterGC(); |
| 900 } | 902 } |
| 901 tracer()->Stop(collector); | 903 tracer()->Stop(collector); |
| 902 } | 904 } |
| 903 | 905 |
| 904 // Start incremental marking for the next cycle. The heap snapshot | 906 // Start incremental marking for the next cycle. The heap snapshot |
| 905 // generator needs incremental marking to stay off after it aborted. | 907 // generator needs incremental marking to stay off after it aborted. |
| 906 if (!mark_compact_collector()->abort_incremental_marking() && | 908 if (!mark_compact_collector()->incremental_marking_abort_requested() && |
| 907 WorthActivatingIncrementalMarking()) { | 909 incremental_marking()->IsStopped() && |
| 910 incremental_marking()->ShouldActivate()) { | |
| 908 incremental_marking()->Start(); | 911 incremental_marking()->Start(); |
| 909 } | 912 } |
| 910 | 913 |
| 911 return next_gc_likely_to_collect_more; | 914 return next_gc_likely_to_collect_more; |
| 912 } | 915 } |
| 913 | 916 |
| 914 | 917 |
| 915 int Heap::NotifyContextDisposed(bool dependant_context) { | 918 int Heap::NotifyContextDisposed(bool dependant_context) { |
| 916 if (!dependant_context) { | 919 if (!dependant_context) { |
| 917 tracer()->ResetSurvivalEvents(); | 920 tracer()->ResetSurvivalEvents(); |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1154 incremental_marking()->NotifyOfHighPromotionRate(); | 1157 incremental_marking()->NotifyOfHighPromotionRate(); |
| 1155 } | 1158 } |
| 1156 | 1159 |
| 1157 if (collector == MARK_COMPACTOR) { | 1160 if (collector == MARK_COMPACTOR) { |
| 1158 // Perform mark-sweep with optional compaction. | 1161 // Perform mark-sweep with optional compaction. |
| 1159 MarkCompact(); | 1162 MarkCompact(); |
| 1160 sweep_generation_++; | 1163 sweep_generation_++; |
| 1161 // Temporarily set the limit for case when PostGarbageCollectionProcessing | 1164 // Temporarily set the limit for case when PostGarbageCollectionProcessing |
| 1162 // allocates and triggers GC. The real limit is set at after | 1165 // allocates and triggers GC. The real limit is set at after |
| 1163 // PostGarbageCollectionProcessing. | 1166 // PostGarbageCollectionProcessing. |
| 1164 old_generation_allocation_limit_ = | 1167 SetOldGenerationAllocationLimit(PromotedSpaceSizeOfObjects(), 0); |
| 1165 OldGenerationAllocationLimit(PromotedSpaceSizeOfObjects(), 0); | |
| 1166 old_gen_exhausted_ = false; | 1168 old_gen_exhausted_ = false; |
| 1167 old_generation_size_configured_ = true; | 1169 old_generation_size_configured_ = true; |
| 1168 } else { | 1170 } else { |
| 1169 Scavenge(); | 1171 Scavenge(); |
| 1170 } | 1172 } |
| 1171 | 1173 |
| 1172 UpdateSurvivalStatistics(start_new_space_size); | 1174 UpdateSurvivalStatistics(start_new_space_size); |
| 1173 ConfigureInitialOldGenerationSize(); | 1175 ConfigureInitialOldGenerationSize(); |
| 1174 | 1176 |
| 1175 isolate_->counters()->objs_since_last_young()->Set(0); | 1177 isolate_->counters()->objs_since_last_young()->Set(0); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 1189 | 1191 |
| 1190 isolate_->eternal_handles()->PostGarbageCollectionProcessing(this); | 1192 isolate_->eternal_handles()->PostGarbageCollectionProcessing(this); |
| 1191 | 1193 |
| 1192 // Update relocatables. | 1194 // Update relocatables. |
| 1193 Relocatable::PostGarbageCollectionProcessing(isolate_); | 1195 Relocatable::PostGarbageCollectionProcessing(isolate_); |
| 1194 | 1196 |
| 1195 if (collector == MARK_COMPACTOR) { | 1197 if (collector == MARK_COMPACTOR) { |
| 1196 // Register the amount of external allocated memory. | 1198 // Register the amount of external allocated memory. |
| 1197 amount_of_external_allocated_memory_at_last_global_gc_ = | 1199 amount_of_external_allocated_memory_at_last_global_gc_ = |
| 1198 amount_of_external_allocated_memory_; | 1200 amount_of_external_allocated_memory_; |
| 1199 old_generation_allocation_limit_ = OldGenerationAllocationLimit( | 1201 SetOldGenerationAllocationLimit(PromotedSpaceSizeOfObjects(), |
| 1200 PromotedSpaceSizeOfObjects(), freed_global_handles); | 1202 freed_global_handles); |
| 1201 // We finished a marking cycle. We can uncommit the marking deque until | 1203 // We finished a marking cycle. We can uncommit the marking deque until |
| 1202 // we start marking again. | 1204 // we start marking again. |
| 1203 mark_compact_collector_.UncommitMarkingDeque(); | 1205 mark_compact_collector_.UncommitMarkingDeque(); |
| 1204 } | 1206 } |
| 1205 | 1207 |
| 1206 { | 1208 { |
| 1207 GCCallbacksScope scope(this); | 1209 GCCallbacksScope scope(this); |
| 1208 if (scope.CheckReenter()) { | 1210 if (scope.CheckReenter()) { |
| 1209 AllowHeapAllocation allow_allocation; | 1211 AllowHeapAllocation allow_allocation; |
| 1210 GCTracer::Scope scope(tracer(), GCTracer::Scope::EXTERNAL); | 1212 GCTracer::Scope scope(tracer(), GCTracer::Scope::EXTERNAL); |
| (...skipping 3356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4567 gc_idle_time_handler_.ShouldDoFinalIncrementalMarkCompact( | 4569 gc_idle_time_handler_.ShouldDoFinalIncrementalMarkCompact( |
| 4568 static_cast<size_t>(idle_time_in_ms), size_of_objects, | 4570 static_cast<size_t>(idle_time_in_ms), size_of_objects, |
| 4569 final_incremental_mark_compact_speed_in_bytes_per_ms))) { | 4571 final_incremental_mark_compact_speed_in_bytes_per_ms))) { |
| 4570 CollectAllGarbage(kNoGCFlags, "idle notification: finalize incremental"); | 4572 CollectAllGarbage(kNoGCFlags, "idle notification: finalize incremental"); |
| 4571 return true; | 4573 return true; |
| 4572 } | 4574 } |
| 4573 return false; | 4575 return false; |
| 4574 } | 4576 } |
| 4575 | 4577 |
| 4576 | 4578 |
| 4577 bool Heap::WorthActivatingIncrementalMarking() { | |
| 4578 return incremental_marking()->IsStopped() && | |
| 4579 incremental_marking()->WorthActivating() && NextGCIsLikelyToBeFull(); | |
| 4580 } | |
| 4581 | |
| 4582 | |
| 4583 static double MonotonicallyIncreasingTimeInMs() { | 4579 static double MonotonicallyIncreasingTimeInMs() { |
| 4584 return V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() * | 4580 return V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() * |
| 4585 static_cast<double>(base::Time::kMillisecondsPerSecond); | 4581 static_cast<double>(base::Time::kMillisecondsPerSecond); |
| 4586 } | 4582 } |
| 4587 | 4583 |
| 4588 | 4584 |
| 4589 bool Heap::IdleNotification(int idle_time_in_ms) { | 4585 bool Heap::IdleNotification(int idle_time_in_ms) { |
| 4590 return IdleNotification( | 4586 return IdleNotification( |
| 4591 V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() + | 4587 V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() + |
| 4592 (static_cast<double>(idle_time_in_ms) / | 4588 (static_cast<double>(idle_time_in_ms) / |
| (...skipping 631 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5224 | 5220 |
| 5225 int64_t Heap::PromotedExternalMemorySize() { | 5221 int64_t Heap::PromotedExternalMemorySize() { |
| 5226 if (amount_of_external_allocated_memory_ <= | 5222 if (amount_of_external_allocated_memory_ <= |
| 5227 amount_of_external_allocated_memory_at_last_global_gc_) | 5223 amount_of_external_allocated_memory_at_last_global_gc_) |
| 5228 return 0; | 5224 return 0; |
| 5229 return amount_of_external_allocated_memory_ - | 5225 return amount_of_external_allocated_memory_ - |
| 5230 amount_of_external_allocated_memory_at_last_global_gc_; | 5226 amount_of_external_allocated_memory_at_last_global_gc_; |
| 5231 } | 5227 } |
| 5232 | 5228 |
| 5233 | 5229 |
| 5234 intptr_t Heap::OldGenerationAllocationLimit(intptr_t old_gen_size, | 5230 void Heap::SetOldGenerationAllocationLimit(intptr_t old_gen_size, |
| 5235 int freed_global_handles) { | 5231 int freed_global_handles) { |
| 5236 const int kMaxHandles = 1000; | 5232 const int kMaxHandles = 1000; |
| 5237 const int kMinHandles = 100; | 5233 const int kMinHandles = 100; |
| 5238 double min_factor = 1.1; | 5234 double min_factor = 1.1; |
| 5239 double max_factor = 4; | 5235 double max_factor = 4; |
| 5240 // We set the old generation growing factor to 2 to grow the heap slower on | 5236 // We set the old generation growing factor to 2 to grow the heap slower on |
| 5241 // memory-constrained devices. | 5237 // memory-constrained devices. |
| 5242 if (max_old_generation_size_ <= kMaxOldSpaceSizeMediumMemoryDevice) { | 5238 if (max_old_generation_size_ <= kMaxOldSpaceSizeMediumMemoryDevice) { |
| 5243 max_factor = 2; | 5239 max_factor = 2; |
| 5244 } | 5240 } |
| 5245 // If there are many freed global handles, then the next full GC will | 5241 // If there are many freed global handles, then the next full GC will |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 5259 (kMaxHandles - kMinHandles); | 5255 (kMaxHandles - kMinHandles); |
| 5260 } | 5256 } |
| 5261 | 5257 |
| 5262 if (FLAG_stress_compaction || | 5258 if (FLAG_stress_compaction || |
| 5263 mark_compact_collector()->reduce_memory_footprint_) { | 5259 mark_compact_collector()->reduce_memory_footprint_) { |
| 5264 factor = min_factor; | 5260 factor = min_factor; |
| 5265 } | 5261 } |
| 5266 | 5262 |
| 5267 intptr_t limit = static_cast<intptr_t>(old_gen_size * factor); | 5263 intptr_t limit = static_cast<intptr_t>(old_gen_size * factor); |
| 5268 limit = Max(limit, kMinimumOldGenerationAllocationLimit); | 5264 limit = Max(limit, kMinimumOldGenerationAllocationLimit); |
| 5269 limit += new_space_.Capacity(); | 5265 |
| 5270 intptr_t halfway_to_the_max = (old_gen_size + max_old_generation_size_) / 2; | 5266 old_generation_allocation_limit_ = limit + new_space_.Capacity(); |
| 5271 return Min(limit, halfway_to_the_max); | 5267 old_generation_committed_memory_limit_ = |
| 5268 CommittedOldGenerationMemory() / 2 + max_old_generation_size_ / 2; | |
| 5269 | |
| 5270 if (FLAG_trace_gc) { | |
|
Hannes Payer (out of office)
2015/03/25 14:30:05
We may want to print that behind a different flag
Erik Corry Chromium.org
2015/03/25 15:16:06
I'd like to keep this one, but I put the other one
| |
| 5271 PrintF("Next GC at %.1f (%.1f) -> %.1f (%.1f)\n", old_gen_size * 1.0 / MB, | |
| 5272 CommittedOldGenerationMemory() * 1.0 / MB, limit * 1.0 / MB, | |
| 5273 old_generation_committed_memory_limit_ * 1.0 / MB); | |
| 5274 } | |
| 5272 } | 5275 } |
| 5273 | 5276 |
| 5274 | 5277 |
| 5275 void Heap::EnableInlineAllocation() { | 5278 void Heap::EnableInlineAllocation() { |
| 5276 if (!inline_allocation_disabled_) return; | 5279 if (!inline_allocation_disabled_) return; |
| 5277 inline_allocation_disabled_ = false; | 5280 inline_allocation_disabled_ = false; |
| 5278 | 5281 |
| 5279 // Update inline allocation limit for new space. | 5282 // Update inline allocation limit for new space. |
| 5280 new_space()->UpdateInlineAllocationLimit(0); | 5283 new_space()->UpdateInlineAllocationLimit(0); |
| 5281 } | 5284 } |
| (...skipping 1108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6390 static_cast<int>(object_sizes_last_time_[index])); | 6393 static_cast<int>(object_sizes_last_time_[index])); |
| 6391 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) | 6394 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) |
| 6392 #undef ADJUST_LAST_TIME_OBJECT_COUNT | 6395 #undef ADJUST_LAST_TIME_OBJECT_COUNT |
| 6393 | 6396 |
| 6394 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); | 6397 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); |
| 6395 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); | 6398 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); |
| 6396 ClearObjectStats(); | 6399 ClearObjectStats(); |
| 6397 } | 6400 } |
| 6398 } | 6401 } |
| 6399 } // namespace v8::internal | 6402 } // namespace v8::internal |
| OLD | NEW |