| 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 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 108 allocation_timeout_(0), | 108 allocation_timeout_(0), |
| 109 #endif // DEBUG | 109 #endif // DEBUG |
| 110 old_generation_allocation_limit_(initial_old_generation_size_), | 110 old_generation_allocation_limit_(initial_old_generation_size_), |
| 111 old_gen_exhausted_(false), | 111 old_gen_exhausted_(false), |
| 112 inline_allocation_disabled_(false), | 112 inline_allocation_disabled_(false), |
| 113 store_buffer_rebuilder_(store_buffer()), | 113 store_buffer_rebuilder_(store_buffer()), |
| 114 hidden_string_(NULL), | 114 hidden_string_(NULL), |
| 115 gc_safe_size_of_old_object_(NULL), | 115 gc_safe_size_of_old_object_(NULL), |
| 116 total_regexp_code_generated_(0), | 116 total_regexp_code_generated_(0), |
| 117 tracer_(this), | 117 tracer_(this), |
| 118 new_space_high_promotion_mode_active_(false), | |
| 119 gathering_lifetime_feedback_(0), | |
| 120 high_survival_rate_period_length_(0), | 118 high_survival_rate_period_length_(0), |
| 121 promoted_objects_size_(0), | 119 promoted_objects_size_(0), |
| 122 low_survival_rate_period_length_(0), | |
| 123 survival_rate_(0), | |
| 124 promotion_ratio_(0), | 120 promotion_ratio_(0), |
| 125 semi_space_copied_object_size_(0), | 121 semi_space_copied_object_size_(0), |
| 126 previous_semi_space_copied_object_size_(0), | 122 previous_semi_space_copied_object_size_(0), |
| 127 semi_space_copied_rate_(0), | 123 semi_space_copied_rate_(0), |
| 128 nodes_died_in_new_space_(0), | 124 nodes_died_in_new_space_(0), |
| 129 nodes_copied_in_new_space_(0), | 125 nodes_copied_in_new_space_(0), |
| 130 nodes_promoted_(0), | 126 nodes_promoted_(0), |
| 131 maximum_size_scavenges_(0), | 127 maximum_size_scavenges_(0), |
| 132 previous_survival_rate_trend_(Heap::STABLE), | |
| 133 survival_rate_trend_(Heap::STABLE), | |
| 134 max_gc_pause_(0.0), | 128 max_gc_pause_(0.0), |
| 135 total_gc_time_ms_(0.0), | 129 total_gc_time_ms_(0.0), |
| 136 max_alive_after_gc_(0), | 130 max_alive_after_gc_(0), |
| 137 min_in_mutator_(kMaxInt), | 131 min_in_mutator_(kMaxInt), |
| 138 marking_time_(0.0), | 132 marking_time_(0.0), |
| 139 sweeping_time_(0.0), | 133 sweeping_time_(0.0), |
| 140 last_idle_notification_time_(0.0), | 134 last_idle_notification_time_(0.0), |
| 141 last_gc_time_(0.0), | 135 last_gc_time_(0.0), |
| 142 mark_compact_collector_(this), | 136 mark_compact_collector_(this), |
| 143 store_buffer_(this), | 137 store_buffer_(this), |
| (...skipping 1049 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1193 (static_cast<double>(semi_space_copied_object_size_) / | 1187 (static_cast<double>(semi_space_copied_object_size_) / |
| 1194 static_cast<double>(start_new_space_size) * 100); | 1188 static_cast<double>(start_new_space_size) * 100); |
| 1195 | 1189 |
| 1196 double survival_rate = promotion_ratio_ + semi_space_copied_rate_; | 1190 double survival_rate = promotion_ratio_ + semi_space_copied_rate_; |
| 1197 tracer()->AddSurvivalRatio(survival_rate); | 1191 tracer()->AddSurvivalRatio(survival_rate); |
| 1198 if (survival_rate > kYoungSurvivalRateHighThreshold) { | 1192 if (survival_rate > kYoungSurvivalRateHighThreshold) { |
| 1199 high_survival_rate_period_length_++; | 1193 high_survival_rate_period_length_++; |
| 1200 } else { | 1194 } else { |
| 1201 high_survival_rate_period_length_ = 0; | 1195 high_survival_rate_period_length_ = 0; |
| 1202 } | 1196 } |
| 1203 | |
| 1204 if (survival_rate < kYoungSurvivalRateLowThreshold) { | |
| 1205 low_survival_rate_period_length_++; | |
| 1206 } else { | |
| 1207 low_survival_rate_period_length_ = 0; | |
| 1208 } | |
| 1209 | |
| 1210 double survival_rate_diff = survival_rate_ - survival_rate; | |
| 1211 | |
| 1212 if (survival_rate_diff > kYoungSurvivalRateAllowedDeviation) { | |
| 1213 set_survival_rate_trend(DECREASING); | |
| 1214 } else if (survival_rate_diff < -kYoungSurvivalRateAllowedDeviation) { | |
| 1215 set_survival_rate_trend(INCREASING); | |
| 1216 } else { | |
| 1217 set_survival_rate_trend(STABLE); | |
| 1218 } | |
| 1219 | |
| 1220 survival_rate_ = survival_rate; | |
| 1221 } | 1197 } |
| 1222 | 1198 |
| 1223 bool Heap::PerformGarbageCollection( | 1199 bool Heap::PerformGarbageCollection( |
| 1224 GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags) { | 1200 GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags) { |
| 1225 int freed_global_handles = 0; | 1201 int freed_global_handles = 0; |
| 1226 | 1202 |
| 1227 if (collector != SCAVENGER) { | 1203 if (collector != SCAVENGER) { |
| 1228 PROFILE(isolate_, CodeMovingGCEvent()); | 1204 PROFILE(isolate_, CodeMovingGCEvent()); |
| 1229 } | 1205 } |
| 1230 | 1206 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1268 old_generation_size_configured_ = true; | 1244 old_generation_size_configured_ = true; |
| 1269 // This should be updated before PostGarbageCollectionProcessing, which can | 1245 // This should be updated before PostGarbageCollectionProcessing, which can |
| 1270 // cause another GC. Take into account the objects promoted during GC. | 1246 // cause another GC. Take into account the objects promoted during GC. |
| 1271 old_generation_allocation_counter_ += | 1247 old_generation_allocation_counter_ += |
| 1272 static_cast<size_t>(promoted_objects_size_); | 1248 static_cast<size_t>(promoted_objects_size_); |
| 1273 old_generation_size_at_last_gc_ = PromotedSpaceSizeOfObjects(); | 1249 old_generation_size_at_last_gc_ = PromotedSpaceSizeOfObjects(); |
| 1274 } else { | 1250 } else { |
| 1275 Scavenge(); | 1251 Scavenge(); |
| 1276 } | 1252 } |
| 1277 | 1253 |
| 1278 bool deopted = ProcessPretenuringFeedback(); | 1254 ProcessPretenuringFeedback(); |
| 1279 UpdateSurvivalStatistics(start_new_space_size); | 1255 UpdateSurvivalStatistics(start_new_space_size); |
| 1280 | |
| 1281 // When pretenuring is collecting new feedback, we do not shrink the new space | |
| 1282 // right away. | |
| 1283 if (deopted) { | |
| 1284 RecordDeoptForPretenuring(); | |
| 1285 } else { | |
| 1286 ConfigureNewGenerationSize(); | |
| 1287 } | |
| 1288 ConfigureInitialOldGenerationSize(); | 1256 ConfigureInitialOldGenerationSize(); |
| 1289 | 1257 |
| 1290 isolate_->counters()->objs_since_last_young()->Set(0); | 1258 isolate_->counters()->objs_since_last_young()->Set(0); |
| 1291 | 1259 |
| 1292 if (collector != SCAVENGER) { | 1260 if (collector != SCAVENGER) { |
| 1293 // Callbacks that fire after this point might trigger nested GCs and | 1261 // Callbacks that fire after this point might trigger nested GCs and |
| 1294 // restart incremental marking, the assertion can't be moved down. | 1262 // restart incremental marking, the assertion can't be moved down. |
| 1295 DCHECK(incremental_marking()->IsStopped()); | 1263 DCHECK(incremental_marking()->IsStopped()); |
| 1296 | 1264 |
| 1297 // We finished a marking cycle. We can uncommit the marking deque until | 1265 // We finished a marking cycle. We can uncommit the marking deque until |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1502 void Heap::CheckNewSpaceExpansionCriteria() { | 1470 void Heap::CheckNewSpaceExpansionCriteria() { |
| 1503 if (FLAG_experimental_new_space_growth_heuristic) { | 1471 if (FLAG_experimental_new_space_growth_heuristic) { |
| 1504 if (new_space_.TotalCapacity() < new_space_.MaximumCapacity() && | 1472 if (new_space_.TotalCapacity() < new_space_.MaximumCapacity() && |
| 1505 survived_last_scavenge_ * 100 / new_space_.TotalCapacity() >= 10) { | 1473 survived_last_scavenge_ * 100 / new_space_.TotalCapacity() >= 10) { |
| 1506 // Grow the size of new space if there is room to grow, and more than 10% | 1474 // Grow the size of new space if there is room to grow, and more than 10% |
| 1507 // have survived the last scavenge. | 1475 // have survived the last scavenge. |
| 1508 new_space_.Grow(); | 1476 new_space_.Grow(); |
| 1509 survived_since_last_expansion_ = 0; | 1477 survived_since_last_expansion_ = 0; |
| 1510 } | 1478 } |
| 1511 } else if (new_space_.TotalCapacity() < new_space_.MaximumCapacity() && | 1479 } else if (new_space_.TotalCapacity() < new_space_.MaximumCapacity() && |
| 1512 survived_since_last_expansion_ > new_space_.TotalCapacity() && | 1480 survived_since_last_expansion_ > new_space_.TotalCapacity()) { |
| 1513 !new_space_high_promotion_mode_active_) { | |
| 1514 // Grow the size of new space if there is room to grow, and enough data | 1481 // Grow the size of new space if there is room to grow, and enough data |
| 1515 // has survived scavenge since the last expansion. | 1482 // has survived scavenge since the last expansion. |
| 1516 new_space_.Grow(); | 1483 new_space_.Grow(); |
| 1517 survived_since_last_expansion_ = 0; | 1484 survived_since_last_expansion_ = 0; |
| 1518 } | 1485 } |
| 1519 } | 1486 } |
| 1520 | 1487 |
| 1521 | 1488 |
| 1522 static bool IsUnscavengedHeapObject(Heap* heap, Object** p) { | 1489 static bool IsUnscavengedHeapObject(Heap* heap, Object** p) { |
| 1523 return heap->InNewSpace(*p) && | 1490 return heap->InNewSpace(*p) && |
| (...skipping 1133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2657 if (!old_generation_size_configured_ && tracer()->SurvivalEventsRecorded()) { | 2624 if (!old_generation_size_configured_ && tracer()->SurvivalEventsRecorded()) { |
| 2658 old_generation_allocation_limit_ = | 2625 old_generation_allocation_limit_ = |
| 2659 Max(kMinimumOldGenerationAllocationLimit, | 2626 Max(kMinimumOldGenerationAllocationLimit, |
| 2660 static_cast<intptr_t>( | 2627 static_cast<intptr_t>( |
| 2661 static_cast<double>(old_generation_allocation_limit_) * | 2628 static_cast<double>(old_generation_allocation_limit_) * |
| 2662 (tracer()->AverageSurvivalRatio() / 100))); | 2629 (tracer()->AverageSurvivalRatio() / 100))); |
| 2663 } | 2630 } |
| 2664 } | 2631 } |
| 2665 | 2632 |
| 2666 | 2633 |
| 2667 void Heap::ConfigureNewGenerationSize() { | |
| 2668 bool still_gathering_lifetime_data = gathering_lifetime_feedback_ != 0; | |
| 2669 if (gathering_lifetime_feedback_ != 0) gathering_lifetime_feedback_--; | |
| 2670 if (!new_space_high_promotion_mode_active_ && | |
| 2671 new_space_.TotalCapacity() == new_space_.MaximumCapacity() && | |
| 2672 IsStableOrIncreasingSurvivalTrend() && IsHighSurvivalRate()) { | |
| 2673 // Stable high survival rates even though young generation is at | |
| 2674 // maximum capacity indicates that most objects will be promoted. | |
| 2675 // To decrease scavenger pauses and final mark-sweep pauses, we | |
| 2676 // have to limit maximal capacity of the young generation. | |
| 2677 if (still_gathering_lifetime_data) { | |
| 2678 if (FLAG_trace_gc) { | |
| 2679 PrintPID( | |
| 2680 "Postpone entering high promotion mode as optimized pretenuring " | |
| 2681 "code is still being generated\n"); | |
| 2682 } | |
| 2683 } else { | |
| 2684 new_space_high_promotion_mode_active_ = true; | |
| 2685 if (FLAG_trace_gc) { | |
| 2686 PrintPID("Limited new space size due to high promotion rate: %d MB\n", | |
| 2687 new_space_.InitialTotalCapacity() / MB); | |
| 2688 } | |
| 2689 } | |
| 2690 } else if (new_space_high_promotion_mode_active_ && | |
| 2691 IsStableOrDecreasingSurvivalTrend() && IsLowSurvivalRate()) { | |
| 2692 // Decreasing low survival rates might indicate that the above high | |
| 2693 // promotion mode is over and we should allow the young generation | |
| 2694 // to grow again. | |
| 2695 new_space_high_promotion_mode_active_ = false; | |
| 2696 if (FLAG_trace_gc) { | |
| 2697 PrintPID("Unlimited new space size due to low promotion rate: %d MB\n", | |
| 2698 new_space_.MaximumCapacity() / MB); | |
| 2699 } | |
| 2700 } | |
| 2701 | |
| 2702 if (new_space_high_promotion_mode_active_ && | |
| 2703 new_space_.TotalCapacity() > new_space_.InitialTotalCapacity()) { | |
| 2704 new_space_.Shrink(); | |
| 2705 } | |
| 2706 } | |
| 2707 | |
| 2708 | |
| 2709 AllocationResult Heap::AllocatePartialMap(InstanceType instance_type, | 2634 AllocationResult Heap::AllocatePartialMap(InstanceType instance_type, |
| 2710 int instance_size) { | 2635 int instance_size) { |
| 2711 Object* result = nullptr; | 2636 Object* result = nullptr; |
| 2712 AllocationResult allocation = AllocateRaw(Map::kSize, MAP_SPACE, MAP_SPACE); | 2637 AllocationResult allocation = AllocateRaw(Map::kSize, MAP_SPACE, MAP_SPACE); |
| 2713 if (!allocation.To(&result)) return allocation; | 2638 if (!allocation.To(&result)) return allocation; |
| 2714 | 2639 |
| 2715 // Map::cast cannot be used due to uninitialized map field. | 2640 // Map::cast cannot be used due to uninitialized map field. |
| 2716 reinterpret_cast<Map*>(result)->set_map(raw_unchecked_meta_map()); | 2641 reinterpret_cast<Map*>(result)->set_map(raw_unchecked_meta_map()); |
| 2717 reinterpret_cast<Map*>(result)->set_instance_type(instance_type); | 2642 reinterpret_cast<Map*>(result)->set_instance_type(instance_type); |
| 2718 reinterpret_cast<Map*>(result)->set_instance_size(instance_size); | 2643 reinterpret_cast<Map*>(result)->set_instance_size(instance_size); |
| (...skipping 4168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6887 *object_type = "CODE_TYPE"; \ | 6812 *object_type = "CODE_TYPE"; \ |
| 6888 *object_sub_type = "CODE_AGE/" #name; \ | 6813 *object_sub_type = "CODE_AGE/" #name; \ |
| 6889 return true; | 6814 return true; |
| 6890 CODE_AGE_LIST_COMPLETE(COMPARE_AND_RETURN_NAME) | 6815 CODE_AGE_LIST_COMPLETE(COMPARE_AND_RETURN_NAME) |
| 6891 #undef COMPARE_AND_RETURN_NAME | 6816 #undef COMPARE_AND_RETURN_NAME |
| 6892 } | 6817 } |
| 6893 return false; | 6818 return false; |
| 6894 } | 6819 } |
| 6895 } // namespace internal | 6820 } // namespace internal |
| 6896 } // namespace v8 | 6821 } // namespace v8 |
| OLD | NEW |