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 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 old_generation_allocation_limit_(initial_old_generation_size_), | 109 old_generation_allocation_limit_(initial_old_generation_size_), |
110 idle_old_generation_allocation_limit_( | 110 idle_old_generation_allocation_limit_( |
111 kMinimumOldGenerationAllocationLimit), | 111 kMinimumOldGenerationAllocationLimit), |
112 old_gen_exhausted_(false), | 112 old_gen_exhausted_(false), |
113 inline_allocation_disabled_(false), | 113 inline_allocation_disabled_(false), |
114 store_buffer_rebuilder_(store_buffer()), | 114 store_buffer_rebuilder_(store_buffer()), |
115 hidden_string_(NULL), | 115 hidden_string_(NULL), |
116 gc_safe_size_of_old_object_(NULL), | 116 gc_safe_size_of_old_object_(NULL), |
117 total_regexp_code_generated_(0), | 117 total_regexp_code_generated_(0), |
118 tracer_(this), | 118 tracer_(this), |
| 119 new_space_high_promotion_mode_active_(false), |
119 high_survival_rate_period_length_(0), | 120 high_survival_rate_period_length_(0), |
120 promoted_objects_size_(0), | 121 promoted_objects_size_(0), |
| 122 low_survival_rate_period_length_(0), |
| 123 survival_rate_(0), |
121 promotion_ratio_(0), | 124 promotion_ratio_(0), |
122 semi_space_copied_object_size_(0), | 125 semi_space_copied_object_size_(0), |
123 previous_semi_space_copied_object_size_(0), | 126 previous_semi_space_copied_object_size_(0), |
124 semi_space_copied_rate_(0), | 127 semi_space_copied_rate_(0), |
125 nodes_died_in_new_space_(0), | 128 nodes_died_in_new_space_(0), |
126 nodes_copied_in_new_space_(0), | 129 nodes_copied_in_new_space_(0), |
127 nodes_promoted_(0), | 130 nodes_promoted_(0), |
128 maximum_size_scavenges_(0), | 131 maximum_size_scavenges_(0), |
| 132 previous_survival_rate_trend_(Heap::STABLE), |
| 133 survival_rate_trend_(Heap::STABLE), |
129 max_gc_pause_(0.0), | 134 max_gc_pause_(0.0), |
130 total_gc_time_ms_(0.0), | 135 total_gc_time_ms_(0.0), |
131 max_alive_after_gc_(0), | 136 max_alive_after_gc_(0), |
132 min_in_mutator_(kMaxInt), | 137 min_in_mutator_(kMaxInt), |
133 marking_time_(0.0), | 138 marking_time_(0.0), |
134 sweeping_time_(0.0), | 139 sweeping_time_(0.0), |
135 last_idle_notification_time_(0.0), | 140 last_idle_notification_time_(0.0), |
136 last_gc_time_(0.0), | 141 last_gc_time_(0.0), |
137 mark_compact_collector_(this), | 142 mark_compact_collector_(this), |
138 store_buffer_(this), | 143 store_buffer_(this), |
(...skipping 1026 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1165 (static_cast<double>(semi_space_copied_object_size_) / | 1170 (static_cast<double>(semi_space_copied_object_size_) / |
1166 static_cast<double>(start_new_space_size) * 100); | 1171 static_cast<double>(start_new_space_size) * 100); |
1167 | 1172 |
1168 double survival_rate = promotion_ratio_ + semi_space_copied_rate_; | 1173 double survival_rate = promotion_ratio_ + semi_space_copied_rate_; |
1169 tracer()->AddSurvivalRatio(survival_rate); | 1174 tracer()->AddSurvivalRatio(survival_rate); |
1170 if (survival_rate > kYoungSurvivalRateHighThreshold) { | 1175 if (survival_rate > kYoungSurvivalRateHighThreshold) { |
1171 high_survival_rate_period_length_++; | 1176 high_survival_rate_period_length_++; |
1172 } else { | 1177 } else { |
1173 high_survival_rate_period_length_ = 0; | 1178 high_survival_rate_period_length_ = 0; |
1174 } | 1179 } |
| 1180 |
| 1181 if (survival_rate < kYoungSurvivalRateLowThreshold) { |
| 1182 low_survival_rate_period_length_++; |
| 1183 } else { |
| 1184 low_survival_rate_period_length_ = 0; |
| 1185 } |
| 1186 |
| 1187 double survival_rate_diff = survival_rate_ - survival_rate; |
| 1188 |
| 1189 if (survival_rate_diff > kYoungSurvivalRateAllowedDeviation) { |
| 1190 set_survival_rate_trend(DECREASING); |
| 1191 } else if (survival_rate_diff < -kYoungSurvivalRateAllowedDeviation) { |
| 1192 set_survival_rate_trend(INCREASING); |
| 1193 } else { |
| 1194 set_survival_rate_trend(STABLE); |
| 1195 } |
| 1196 |
| 1197 survival_rate_ = survival_rate; |
1175 } | 1198 } |
1176 | 1199 |
1177 bool Heap::PerformGarbageCollection( | 1200 bool Heap::PerformGarbageCollection( |
1178 GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags) { | 1201 GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags) { |
1179 int freed_global_handles = 0; | 1202 int freed_global_handles = 0; |
1180 | 1203 |
1181 if (collector != SCAVENGER) { | 1204 if (collector != SCAVENGER) { |
1182 PROFILE(isolate_, CodeMovingGCEvent()); | 1205 PROFILE(isolate_, CodeMovingGCEvent()); |
1183 } | 1206 } |
1184 | 1207 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1221 old_generation_size_configured_ = true; | 1244 old_generation_size_configured_ = true; |
1222 } else { | 1245 } else { |
1223 Scavenge(); | 1246 Scavenge(); |
1224 } | 1247 } |
1225 | 1248 |
1226 // This should be updated before PostGarbageCollectionProcessing, which can | 1249 // This should be updated before PostGarbageCollectionProcessing, which can |
1227 // cause another GC. | 1250 // cause another GC. |
1228 old_generation_size_at_last_gc_ = PromotedSpaceSizeOfObjects(); | 1251 old_generation_size_at_last_gc_ = PromotedSpaceSizeOfObjects(); |
1229 | 1252 |
1230 UpdateSurvivalStatistics(start_new_space_size); | 1253 UpdateSurvivalStatistics(start_new_space_size); |
| 1254 ConfigureNewGenerationSize(); |
1231 ConfigureInitialOldGenerationSize(); | 1255 ConfigureInitialOldGenerationSize(); |
1232 | 1256 |
1233 isolate_->counters()->objs_since_last_young()->Set(0); | 1257 isolate_->counters()->objs_since_last_young()->Set(0); |
1234 | 1258 |
1235 if (collector != SCAVENGER) { | 1259 if (collector != SCAVENGER) { |
1236 // Callbacks that fire after this point might trigger nested GCs and | 1260 // Callbacks that fire after this point might trigger nested GCs and |
1237 // restart incremental marking, the assertion can't be moved down. | 1261 // restart incremental marking, the assertion can't be moved down. |
1238 DCHECK(incremental_marking()->IsStopped()); | 1262 DCHECK(incremental_marking()->IsStopped()); |
1239 | 1263 |
1240 // We finished a marking cycle. We can uncommit the marking deque until | 1264 // We finished a marking cycle. We can uncommit the marking deque until |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1438 void Heap::CheckNewSpaceExpansionCriteria() { | 1462 void Heap::CheckNewSpaceExpansionCriteria() { |
1439 if (FLAG_experimental_new_space_growth_heuristic) { | 1463 if (FLAG_experimental_new_space_growth_heuristic) { |
1440 if (new_space_.TotalCapacity() < new_space_.MaximumCapacity() && | 1464 if (new_space_.TotalCapacity() < new_space_.MaximumCapacity() && |
1441 survived_last_scavenge_ * 100 / new_space_.TotalCapacity() >= 10) { | 1465 survived_last_scavenge_ * 100 / new_space_.TotalCapacity() >= 10) { |
1442 // Grow the size of new space if there is room to grow, and more than 10% | 1466 // Grow the size of new space if there is room to grow, and more than 10% |
1443 // have survived the last scavenge. | 1467 // have survived the last scavenge. |
1444 new_space_.Grow(); | 1468 new_space_.Grow(); |
1445 survived_since_last_expansion_ = 0; | 1469 survived_since_last_expansion_ = 0; |
1446 } | 1470 } |
1447 } else if (new_space_.TotalCapacity() < new_space_.MaximumCapacity() && | 1471 } else if (new_space_.TotalCapacity() < new_space_.MaximumCapacity() && |
1448 survived_since_last_expansion_ > new_space_.TotalCapacity()) { | 1472 survived_since_last_expansion_ > new_space_.TotalCapacity() && |
| 1473 !new_space_high_promotion_mode_active_) { |
1449 // Grow the size of new space if there is room to grow, and enough data | 1474 // Grow the size of new space if there is room to grow, and enough data |
1450 // has survived scavenge since the last expansion. | 1475 // has survived scavenge since the last expansion. |
1451 new_space_.Grow(); | 1476 new_space_.Grow(); |
1452 survived_since_last_expansion_ = 0; | 1477 survived_since_last_expansion_ = 0; |
1453 } | 1478 } |
1454 } | 1479 } |
1455 | 1480 |
1456 | 1481 |
1457 static bool IsUnscavengedHeapObject(Heap* heap, Object** p) { | 1482 static bool IsUnscavengedHeapObject(Heap* heap, Object** p) { |
1458 return heap->InNewSpace(*p) && | 1483 return heap->InNewSpace(*p) && |
(...skipping 1013 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2472 if (!old_generation_size_configured_ && tracer()->SurvivalEventsRecorded()) { | 2497 if (!old_generation_size_configured_ && tracer()->SurvivalEventsRecorded()) { |
2473 old_generation_allocation_limit_ = | 2498 old_generation_allocation_limit_ = |
2474 Max(kMinimumOldGenerationAllocationLimit, | 2499 Max(kMinimumOldGenerationAllocationLimit, |
2475 static_cast<intptr_t>( | 2500 static_cast<intptr_t>( |
2476 static_cast<double>(old_generation_allocation_limit_) * | 2501 static_cast<double>(old_generation_allocation_limit_) * |
2477 (tracer()->AverageSurvivalRatio() / 100))); | 2502 (tracer()->AverageSurvivalRatio() / 100))); |
2478 } | 2503 } |
2479 } | 2504 } |
2480 | 2505 |
2481 | 2506 |
| 2507 void Heap::ConfigureNewGenerationSize() { |
| 2508 if (!new_space_high_promotion_mode_active_ && |
| 2509 new_space_.TotalCapacity() == new_space_.MaximumCapacity() && |
| 2510 IsStableOrIncreasingSurvivalTrend() && IsHighSurvivalRate()) { |
| 2511 // Stable high survival rates even though young generation is at |
| 2512 // maximum capacity indicates that most objects will be promoted. |
| 2513 // To decrease scavenger pauses and final mark-sweep pauses, we |
| 2514 // have to limit maximal capacity of the young generation. |
| 2515 new_space_high_promotion_mode_active_ = true; |
| 2516 if (FLAG_trace_gc) { |
| 2517 PrintPID("Limited new space size due to high promotion rate: %d MB\n", |
| 2518 new_space_.InitialTotalCapacity() / MB); |
| 2519 } |
| 2520 } else if (new_space_high_promotion_mode_active_ && |
| 2521 IsStableOrDecreasingSurvivalTrend() && IsLowSurvivalRate()) { |
| 2522 // Decreasing low survival rates might indicate that the above high |
| 2523 // promotion mode is over and we should allow the young generation |
| 2524 // to grow again. |
| 2525 new_space_high_promotion_mode_active_ = false; |
| 2526 if (FLAG_trace_gc) { |
| 2527 PrintPID("Unlimited new space size due to low promotion rate: %d MB\n", |
| 2528 new_space_.MaximumCapacity() / MB); |
| 2529 } |
| 2530 } |
| 2531 |
| 2532 if (new_space_high_promotion_mode_active_ && |
| 2533 new_space_.TotalCapacity() > new_space_.InitialTotalCapacity()) { |
| 2534 new_space_.Shrink(); |
| 2535 } |
| 2536 } |
| 2537 |
| 2538 |
2482 AllocationResult Heap::AllocatePartialMap(InstanceType instance_type, | 2539 AllocationResult Heap::AllocatePartialMap(InstanceType instance_type, |
2483 int instance_size) { | 2540 int instance_size) { |
2484 Object* result = nullptr; | 2541 Object* result = nullptr; |
2485 AllocationResult allocation = AllocateRaw(Map::kSize, MAP_SPACE, MAP_SPACE); | 2542 AllocationResult allocation = AllocateRaw(Map::kSize, MAP_SPACE, MAP_SPACE); |
2486 if (!allocation.To(&result)) return allocation; | 2543 if (!allocation.To(&result)) return allocation; |
2487 | 2544 |
2488 // Map::cast cannot be used due to uninitialized map field. | 2545 // Map::cast cannot be used due to uninitialized map field. |
2489 reinterpret_cast<Map*>(result)->set_map(raw_unchecked_meta_map()); | 2546 reinterpret_cast<Map*>(result)->set_map(raw_unchecked_meta_map()); |
2490 reinterpret_cast<Map*>(result)->set_instance_type(instance_type); | 2547 reinterpret_cast<Map*>(result)->set_instance_type(instance_type); |
2491 reinterpret_cast<Map*>(result)->set_instance_size(instance_size); | 2548 reinterpret_cast<Map*>(result)->set_instance_size(instance_size); |
(...skipping 4061 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6553 *object_type = "CODE_TYPE"; \ | 6610 *object_type = "CODE_TYPE"; \ |
6554 *object_sub_type = "CODE_AGE/" #name; \ | 6611 *object_sub_type = "CODE_AGE/" #name; \ |
6555 return true; | 6612 return true; |
6556 CODE_AGE_LIST_COMPLETE(COMPARE_AND_RETURN_NAME) | 6613 CODE_AGE_LIST_COMPLETE(COMPARE_AND_RETURN_NAME) |
6557 #undef COMPARE_AND_RETURN_NAME | 6614 #undef COMPARE_AND_RETURN_NAME |
6558 } | 6615 } |
6559 return false; | 6616 return false; |
6560 } | 6617 } |
6561 } // namespace internal | 6618 } // namespace internal |
6562 } // namespace v8 | 6619 } // namespace v8 |
OLD | NEW |