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/once.h" | 9 #include "src/base/once.h" |
| 10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 54 reserved_semispace_size_(8 * (kPointerSize / 4) * MB), | 54 reserved_semispace_size_(8 * (kPointerSize / 4) * MB), |
| 55 max_semi_space_size_(8 * (kPointerSize / 4) * MB), | 55 max_semi_space_size_(8 * (kPointerSize / 4) * MB), |
| 56 initial_semispace_size_(Page::kPageSize), | 56 initial_semispace_size_(Page::kPageSize), |
| 57 max_old_generation_size_(700ul * (kPointerSize / 4) * MB), | 57 max_old_generation_size_(700ul * (kPointerSize / 4) * MB), |
| 58 max_executable_size_(256ul * (kPointerSize / 4) * MB), | 58 max_executable_size_(256ul * (kPointerSize / 4) * MB), |
| 59 // Variables set based on semispace_size_ and old_generation_size_ in | 59 // Variables set based on semispace_size_ and old_generation_size_ in |
| 60 // ConfigureHeap. | 60 // ConfigureHeap. |
| 61 // Will be 4 * reserved_semispace_size_ to ensure that young | 61 // Will be 4 * reserved_semispace_size_ to ensure that young |
| 62 // generation can be aligned to its size. | 62 // generation can be aligned to its size. |
| 63 maximum_committed_(0), | 63 maximum_committed_(0), |
| 64 old_space_growing_factor_(4), | |
| 65 survived_since_last_expansion_(0), | 64 survived_since_last_expansion_(0), |
| 66 sweep_generation_(0), | 65 sweep_generation_(0), |
| 67 always_allocate_scope_depth_(0), | 66 always_allocate_scope_depth_(0), |
| 68 contexts_disposed_(0), | 67 contexts_disposed_(0), |
| 69 global_ic_age_(0), | 68 global_ic_age_(0), |
| 70 flush_monomorphic_ics_(false), | 69 flush_monomorphic_ics_(false), |
| 71 scan_on_scavenge_pages_(0), | 70 scan_on_scavenge_pages_(0), |
| 72 new_space_(this), | 71 new_space_(this), |
| 73 old_pointer_space_(NULL), | 72 old_pointer_space_(NULL), |
| 74 old_data_space_(NULL), | 73 old_data_space_(NULL), |
| 75 code_space_(NULL), | 74 code_space_(NULL), |
| 76 map_space_(NULL), | 75 map_space_(NULL), |
| 77 cell_space_(NULL), | 76 cell_space_(NULL), |
| 78 property_cell_space_(NULL), | 77 property_cell_space_(NULL), |
| 79 lo_space_(NULL), | 78 lo_space_(NULL), |
| 80 gc_state_(NOT_IN_GC), | 79 gc_state_(NOT_IN_GC), |
| 81 gc_post_processing_depth_(0), | 80 gc_post_processing_depth_(0), |
| 82 allocations_count_(0), | 81 allocations_count_(0), |
| 83 raw_allocations_hash_(0), | 82 raw_allocations_hash_(0), |
| 84 dump_allocations_hash_countdown_(FLAG_dump_allocations_digest_at_alloc), | 83 dump_allocations_hash_countdown_(FLAG_dump_allocations_digest_at_alloc), |
| 85 ms_count_(0), | 84 ms_count_(0), |
| 86 gc_count_(0), | 85 gc_count_(0), |
| 87 remembered_unmapped_pages_index_(0), | 86 remembered_unmapped_pages_index_(0), |
| 88 unflattened_strings_length_(0), | 87 unflattened_strings_length_(0), |
| 89 #ifdef DEBUG | 88 #ifdef DEBUG |
| 90 allocation_timeout_(0), | 89 allocation_timeout_(0), |
| 91 #endif // DEBUG | 90 #endif // DEBUG |
| 92 old_generation_allocation_limit_(kMinimumOldGenerationAllocationLimit), | 91 old_generation_allocation_limit_(kMinimumOldGenerationAllocationLimit), |
| 93 size_of_old_gen_at_last_old_space_gc_(0), | |
| 94 old_gen_exhausted_(false), | 92 old_gen_exhausted_(false), |
| 95 inline_allocation_disabled_(false), | 93 inline_allocation_disabled_(false), |
| 96 store_buffer_rebuilder_(store_buffer()), | 94 store_buffer_rebuilder_(store_buffer()), |
| 97 hidden_string_(NULL), | 95 hidden_string_(NULL), |
| 98 gc_safe_size_of_old_object_(NULL), | 96 gc_safe_size_of_old_object_(NULL), |
| 99 total_regexp_code_generated_(0), | 97 total_regexp_code_generated_(0), |
| 100 tracer_(NULL), | 98 tracer_(NULL), |
| 101 high_survival_rate_period_length_(0), | 99 high_survival_rate_period_length_(0), |
| 102 promoted_objects_size_(0), | 100 promoted_objects_size_(0), |
| 103 promotion_rate_(0), | 101 promotion_rate_(0), |
| (...skipping 945 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1049 high_survival_rate_period_length_++; | 1047 high_survival_rate_period_length_++; |
| 1050 } else { | 1048 } else { |
| 1051 high_survival_rate_period_length_ = 0; | 1049 high_survival_rate_period_length_ = 0; |
| 1052 } | 1050 } |
| 1053 } | 1051 } |
| 1054 | 1052 |
| 1055 bool Heap::PerformGarbageCollection( | 1053 bool Heap::PerformGarbageCollection( |
| 1056 GarbageCollector collector, | 1054 GarbageCollector collector, |
| 1057 GCTracer* tracer, | 1055 GCTracer* tracer, |
| 1058 const v8::GCCallbackFlags gc_callback_flags) { | 1056 const v8::GCCallbackFlags gc_callback_flags) { |
| 1059 bool next_gc_likely_to_collect_more = false; | 1057 int freed_global_handles = 0; |
| 1060 | 1058 |
| 1061 if (collector != SCAVENGER) { | 1059 if (collector != SCAVENGER) { |
| 1062 PROFILE(isolate_, CodeMovingGCEvent()); | 1060 PROFILE(isolate_, CodeMovingGCEvent()); |
| 1063 } | 1061 } |
| 1064 | 1062 |
| 1065 #ifdef VERIFY_HEAP | 1063 #ifdef VERIFY_HEAP |
| 1066 if (FLAG_verify_heap) { | 1064 if (FLAG_verify_heap) { |
| 1067 VerifyStringTable(this); | 1065 VerifyStringTable(this); |
| 1068 } | 1066 } |
| 1069 #endif | 1067 #endif |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 1089 // We speed up the incremental marker if it is running so that it | 1087 // We speed up the incremental marker if it is running so that it |
| 1090 // does not fall behind the rate of promotion, which would cause a | 1088 // does not fall behind the rate of promotion, which would cause a |
| 1091 // constantly growing old space. | 1089 // constantly growing old space. |
| 1092 incremental_marking()->NotifyOfHighPromotionRate(); | 1090 incremental_marking()->NotifyOfHighPromotionRate(); |
| 1093 } | 1091 } |
| 1094 | 1092 |
| 1095 if (collector == MARK_COMPACTOR) { | 1093 if (collector == MARK_COMPACTOR) { |
| 1096 // Perform mark-sweep with optional compaction. | 1094 // Perform mark-sweep with optional compaction. |
| 1097 MarkCompact(tracer); | 1095 MarkCompact(tracer); |
| 1098 sweep_generation_++; | 1096 sweep_generation_++; |
| 1099 | 1097 // Temporarily set the limit for case when PostGarbageCollectionProcessing |
| 1100 size_of_old_gen_at_last_old_space_gc_ = PromotedSpaceSizeOfObjects(); | 1098 // allocates and triggers GC. The real limit is set at after |
| 1101 | 1099 // PostGarbageCollectionProcessing. |
| 1102 old_generation_allocation_limit_ = | 1100 old_generation_allocation_limit_ = |
| 1103 OldGenerationAllocationLimit(size_of_old_gen_at_last_old_space_gc_); | 1101 OldGenerationAllocationLimit(PromotedSpaceSizeOfObjects(), 0); |
| 1104 | |
| 1105 old_gen_exhausted_ = false; | 1102 old_gen_exhausted_ = false; |
| 1106 } else { | 1103 } else { |
| 1107 tracer_ = tracer; | 1104 tracer_ = tracer; |
| 1108 Scavenge(); | 1105 Scavenge(); |
| 1109 tracer_ = NULL; | 1106 tracer_ = NULL; |
| 1110 } | 1107 } |
| 1111 | 1108 |
| 1112 UpdateSurvivalStatistics(start_new_space_size); | 1109 UpdateSurvivalStatistics(start_new_space_size); |
| 1113 | 1110 |
| 1114 isolate_->counters()->objs_since_last_young()->Set(0); | 1111 isolate_->counters()->objs_since_last_young()->Set(0); |
| 1115 | 1112 |
| 1116 // Callbacks that fire after this point might trigger nested GCs and | 1113 // Callbacks that fire after this point might trigger nested GCs and |
| 1117 // restart incremental marking, the assertion can't be moved down. | 1114 // restart incremental marking, the assertion can't be moved down. |
| 1118 ASSERT(collector == SCAVENGER || incremental_marking()->IsStopped()); | 1115 ASSERT(collector == SCAVENGER || incremental_marking()->IsStopped()); |
| 1119 | 1116 |
| 1120 gc_post_processing_depth_++; | 1117 gc_post_processing_depth_++; |
| 1121 { AllowHeapAllocation allow_allocation; | 1118 { AllowHeapAllocation allow_allocation; |
| 1122 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); | 1119 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); |
| 1123 next_gc_likely_to_collect_more = | 1120 freed_global_handles = |
| 1124 isolate_->global_handles()->PostGarbageCollectionProcessing( | 1121 isolate_->global_handles()->PostGarbageCollectionProcessing( |
| 1125 collector, tracer); | 1122 collector, tracer); |
| 1126 } | 1123 } |
| 1127 gc_post_processing_depth_--; | 1124 gc_post_processing_depth_--; |
| 1128 | 1125 |
| 1129 isolate_->eternal_handles()->PostGarbageCollectionProcessing(this); | 1126 isolate_->eternal_handles()->PostGarbageCollectionProcessing(this); |
| 1130 | 1127 |
| 1131 // Update relocatables. | 1128 // Update relocatables. |
| 1132 Relocatable::PostGarbageCollectionProcessing(isolate_); | 1129 Relocatable::PostGarbageCollectionProcessing(isolate_); |
| 1133 | 1130 |
| 1134 if (collector == MARK_COMPACTOR) { | 1131 if (collector == MARK_COMPACTOR) { |
| 1135 // Register the amount of external allocated memory. | 1132 // Register the amount of external allocated memory. |
| 1136 amount_of_external_allocated_memory_at_last_global_gc_ = | 1133 amount_of_external_allocated_memory_at_last_global_gc_ = |
| 1137 amount_of_external_allocated_memory_; | 1134 amount_of_external_allocated_memory_; |
| 1135 old_generation_allocation_limit_ = | |
| 1136 OldGenerationAllocationLimit(PromotedSpaceSizeOfObjects(), | |
| 1137 freed_global_handles); | |
| 1138 } | 1138 } |
| 1139 | 1139 |
| 1140 { GCCallbacksScope scope(this); | 1140 { GCCallbacksScope scope(this); |
| 1141 if (scope.CheckReenter()) { | 1141 if (scope.CheckReenter()) { |
| 1142 AllowHeapAllocation allow_allocation; | 1142 AllowHeapAllocation allow_allocation; |
| 1143 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); | 1143 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); |
| 1144 VMState<EXTERNAL> state(isolate_); | 1144 VMState<EXTERNAL> state(isolate_); |
| 1145 HandleScope handle_scope(isolate_); | 1145 HandleScope handle_scope(isolate_); |
| 1146 CallGCEpilogueCallbacks(gc_type, gc_callback_flags); | 1146 CallGCEpilogueCallbacks(gc_type, gc_callback_flags); |
| 1147 } | 1147 } |
| 1148 } | 1148 } |
| 1149 | 1149 |
| 1150 #ifdef VERIFY_HEAP | 1150 #ifdef VERIFY_HEAP |
| 1151 if (FLAG_verify_heap) { | 1151 if (FLAG_verify_heap) { |
| 1152 VerifyStringTable(this); | 1152 VerifyStringTable(this); |
| 1153 } | 1153 } |
| 1154 #endif | 1154 #endif |
| 1155 | 1155 |
| 1156 return next_gc_likely_to_collect_more; | 1156 return freed_global_handles > 0; |
| 1157 } | 1157 } |
| 1158 | 1158 |
| 1159 | 1159 |
| 1160 void Heap::CallGCPrologueCallbacks(GCType gc_type, GCCallbackFlags flags) { | 1160 void Heap::CallGCPrologueCallbacks(GCType gc_type, GCCallbackFlags flags) { |
| 1161 for (int i = 0; i < gc_prologue_callbacks_.length(); ++i) { | 1161 for (int i = 0; i < gc_prologue_callbacks_.length(); ++i) { |
| 1162 if (gc_type & gc_prologue_callbacks_[i].gc_type) { | 1162 if (gc_type & gc_prologue_callbacks_[i].gc_type) { |
| 1163 if (!gc_prologue_callbacks_[i].pass_isolate_) { | 1163 if (!gc_prologue_callbacks_[i].pass_isolate_) { |
| 1164 v8::GCPrologueCallback callback = | 1164 v8::GCPrologueCallback callback = |
| 1165 reinterpret_cast<v8::GCPrologueCallback>( | 1165 reinterpret_cast<v8::GCPrologueCallback>( |
| 1166 gc_prologue_callbacks_[i].callback); | 1166 gc_prologue_callbacks_[i].callback); |
| (...skipping 3785 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4952 max_old_generation_size_); | 4952 max_old_generation_size_); |
| 4953 | 4953 |
| 4954 // We rely on being able to allocate new arrays in paged spaces. | 4954 // We rely on being able to allocate new arrays in paged spaces. |
| 4955 ASSERT(Page::kMaxRegularHeapObjectSize >= | 4955 ASSERT(Page::kMaxRegularHeapObjectSize >= |
| 4956 (JSArray::kSize + | 4956 (JSArray::kSize + |
| 4957 FixedArray::SizeFor(JSObject::kInitialMaxFastElementArray) + | 4957 FixedArray::SizeFor(JSObject::kInitialMaxFastElementArray) + |
| 4958 AllocationMemento::kSize)); | 4958 AllocationMemento::kSize)); |
| 4959 | 4959 |
| 4960 code_range_size_ = code_range_size * MB; | 4960 code_range_size_ = code_range_size * MB; |
| 4961 | 4961 |
| 4962 // We set the old generation growing factor to 2 to grow the heap slower on | |
| 4963 // memory-constrained devices. | |
| 4964 if (max_old_generation_size_ <= kMaxOldSpaceSizeMediumMemoryDevice) { | |
| 4965 old_space_growing_factor_ = 2; | |
| 4966 } | |
| 4967 | |
| 4968 configured_ = true; | 4962 configured_ = true; |
| 4969 return true; | 4963 return true; |
| 4970 } | 4964 } |
| 4971 | 4965 |
| 4972 | 4966 |
| 4973 bool Heap::ConfigureHeapDefault() { | 4967 bool Heap::ConfigureHeapDefault() { |
| 4974 return ConfigureHeap(0, 0, 0, 0); | 4968 return ConfigureHeap(0, 0, 0, 0); |
| 4975 } | 4969 } |
| 4976 | 4970 |
| 4977 | 4971 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5026 | 5020 |
| 5027 | 5021 |
| 5028 int64_t Heap::PromotedExternalMemorySize() { | 5022 int64_t Heap::PromotedExternalMemorySize() { |
| 5029 if (amount_of_external_allocated_memory_ | 5023 if (amount_of_external_allocated_memory_ |
| 5030 <= amount_of_external_allocated_memory_at_last_global_gc_) return 0; | 5024 <= amount_of_external_allocated_memory_at_last_global_gc_) return 0; |
| 5031 return amount_of_external_allocated_memory_ | 5025 return amount_of_external_allocated_memory_ |
| 5032 - amount_of_external_allocated_memory_at_last_global_gc_; | 5026 - amount_of_external_allocated_memory_at_last_global_gc_; |
| 5033 } | 5027 } |
| 5034 | 5028 |
| 5035 | 5029 |
| 5030 intptr_t Heap::OldGenerationAllocationLimit(intptr_t old_gen_size, | |
| 5031 int freed_global_handles) { | |
| 5032 const int kMaxHandles = 1000; | |
| 5033 const int kMinHandles = 100; | |
| 5034 double min_factor = 1.1; | |
| 5035 double max_factor = 4; | |
| 5036 // We set the old generation growing factor to 2 to grow the heap slower on | |
| 5037 // memory-constrained devices. | |
| 5038 if (max_old_generation_size_ <= kMaxOldSpaceSizeMediumMemoryDevice) { | |
| 5039 max_factor = 2; | |
| 5040 } | |
| 5041 // If there are many freed global handles, then the next full GC will | |
| 5042 // likely collect a lot of garbage. Choose the heap growing factor | |
| 5043 // depending on freed global handles. | |
| 5044 // TODO(ulan, hpayer): Take into account mutator utilization. | |
| 5045 double factor; | |
| 5046 if (freed_global_handles <= kMinHandles) { | |
| 5047 factor = max_factor; | |
| 5048 } else if (freed_global_handles >= kMaxHandles) { | |
| 5049 factor = min_factor; | |
| 5050 } else { | |
| 5051 factor = max_factor - | |
|
Hannes Payer (out of office)
2014/06/25 09:24:00
Could you please leave a comment here that explain
| |
| 5052 (freed_global_handles - kMinHandles) * (max_factor - min_factor) / | |
| 5053 (kMaxHandles - kMinHandles); | |
| 5054 } | |
| 5055 | |
| 5056 if (FLAG_stress_compaction || | |
| 5057 mark_compact_collector()->reduce_memory_footprint_) { | |
| 5058 factor = min_factor; | |
| 5059 } | |
| 5060 | |
| 5061 intptr_t limit = static_cast<intptr_t>(old_gen_size * factor); | |
| 5062 limit = Max(limit, kMinimumOldGenerationAllocationLimit); | |
| 5063 limit += new_space_.Capacity(); | |
| 5064 intptr_t halfway_to_the_max = (old_gen_size + max_old_generation_size_) / 2; | |
| 5065 return Min(limit, halfway_to_the_max); | |
| 5066 } | |
| 5067 | |
| 5068 | |
| 5036 void Heap::EnableInlineAllocation() { | 5069 void Heap::EnableInlineAllocation() { |
| 5037 if (!inline_allocation_disabled_) return; | 5070 if (!inline_allocation_disabled_) return; |
| 5038 inline_allocation_disabled_ = false; | 5071 inline_allocation_disabled_ = false; |
| 5039 | 5072 |
| 5040 // Update inline allocation limit for new space. | 5073 // Update inline allocation limit for new space. |
| 5041 new_space()->UpdateInlineAllocationLimit(0); | 5074 new_space()->UpdateInlineAllocationLimit(0); |
| 5042 } | 5075 } |
| 5043 | 5076 |
| 5044 | 5077 |
| 5045 void Heap::DisableInlineAllocation() { | 5078 void Heap::DisableInlineAllocation() { |
| (...skipping 1324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6370 static_cast<int>(object_sizes_last_time_[index])); | 6403 static_cast<int>(object_sizes_last_time_[index])); |
| 6371 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) | 6404 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) |
| 6372 #undef ADJUST_LAST_TIME_OBJECT_COUNT | 6405 #undef ADJUST_LAST_TIME_OBJECT_COUNT |
| 6373 | 6406 |
| 6374 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); | 6407 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); |
| 6375 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); | 6408 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); |
| 6376 ClearObjectStats(); | 6409 ClearObjectStats(); |
| 6377 } | 6410 } |
| 6378 | 6411 |
| 6379 } } // namespace v8::internal | 6412 } } // namespace v8::internal |
| OLD | NEW |