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