| 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 |