| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 670 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 681 context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK); | 681 context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK); |
| 682 } | 682 } |
| 683 } | 683 } |
| 684 | 684 |
| 685 | 685 |
| 686 void Heap::UpdateSurvivalRateTrend(int start_new_space_size) { | 686 void Heap::UpdateSurvivalRateTrend(int start_new_space_size) { |
| 687 double survival_rate = | 687 double survival_rate = |
| 688 (static_cast<double>(young_survivors_after_last_gc_) * 100) / | 688 (static_cast<double>(young_survivors_after_last_gc_) * 100) / |
| 689 start_new_space_size; | 689 start_new_space_size; |
| 690 | 690 |
| 691 if (survival_rate > kYoungSurvivalRateThreshold) { | 691 if (survival_rate > kYoungSurvivalRateHighThreshold) { |
| 692 high_survival_rate_period_length_++; | 692 high_survival_rate_period_length_++; |
| 693 } else { | 693 } else { |
| 694 high_survival_rate_period_length_ = 0; | 694 high_survival_rate_period_length_ = 0; |
| 695 } | 695 } |
| 696 | 696 |
| 697 if (survival_rate < kYoungSurvivalRateLowThreshold) { |
| 698 low_survival_rate_period_length_++; |
| 699 } else { |
| 700 low_survival_rate_period_length_ = 0; |
| 701 } |
| 702 |
| 697 double survival_rate_diff = survival_rate_ - survival_rate; | 703 double survival_rate_diff = survival_rate_ - survival_rate; |
| 698 | 704 |
| 699 if (survival_rate_diff > kYoungSurvivalRateAllowedDeviation) { | 705 if (survival_rate_diff > kYoungSurvivalRateAllowedDeviation) { |
| 700 set_survival_rate_trend(DECREASING); | 706 set_survival_rate_trend(DECREASING); |
| 701 } else if (survival_rate_diff < -kYoungSurvivalRateAllowedDeviation) { | 707 } else if (survival_rate_diff < -kYoungSurvivalRateAllowedDeviation) { |
| 702 set_survival_rate_trend(INCREASING); | 708 set_survival_rate_trend(INCREASING); |
| 703 } else { | 709 } else { |
| 704 set_survival_rate_trend(STABLE); | 710 set_survival_rate_trend(STABLE); |
| 705 } | 711 } |
| 706 | 712 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 746 | 752 |
| 747 if (collector == MARK_COMPACTOR) { | 753 if (collector == MARK_COMPACTOR) { |
| 748 // Perform mark-sweep with optional compaction. | 754 // Perform mark-sweep with optional compaction. |
| 749 MarkCompact(tracer); | 755 MarkCompact(tracer); |
| 750 sweep_generation_++; | 756 sweep_generation_++; |
| 751 bool high_survival_rate_during_scavenges = IsHighSurvivalRate() && | 757 bool high_survival_rate_during_scavenges = IsHighSurvivalRate() && |
| 752 IsStableOrIncreasingSurvivalTrend(); | 758 IsStableOrIncreasingSurvivalTrend(); |
| 753 | 759 |
| 754 UpdateSurvivalRateTrend(start_new_space_size); | 760 UpdateSurvivalRateTrend(start_new_space_size); |
| 755 | 761 |
| 756 if (!new_space_high_promotion_mode_active_ && | |
| 757 new_space_.Capacity() == new_space_.MaximumCapacity() && | |
| 758 IsStableOrIncreasingSurvivalTrend() && | |
| 759 IsHighSurvivalRate()) { | |
| 760 // Stable high survival rates even though young generation is at | |
| 761 // maximum capacity indicates that most objects will be promoted. | |
| 762 // To decrease scavenger pauses and final mark-sweep pauses, we | |
| 763 // have to limit maximal capacity of the young generation. | |
| 764 new_space_high_promotion_mode_active_ = true; | |
| 765 if (FLAG_trace_gc) { | |
| 766 PrintF("Limited new space size due to high promotion rate: %d MB\n", | |
| 767 new_space_.InitialCapacity() / MB); | |
| 768 } | |
| 769 } else if (new_space_high_promotion_mode_active_ && | |
| 770 IsDecreasingSurvivalTrend() && | |
| 771 !IsHighSurvivalRate()) { | |
| 772 // Decreasing low survival rates might indicate that the above high | |
| 773 // promotion mode is over and we should allow the young generation | |
| 774 // to grow again. | |
| 775 new_space_high_promotion_mode_active_ = false; | |
| 776 if (FLAG_trace_gc) { | |
| 777 PrintF("Unlimited new space size due to low promotion rate: %d MB\n", | |
| 778 new_space_.MaximumCapacity() / MB); | |
| 779 } | |
| 780 } | |
| 781 | |
| 782 size_of_old_gen_at_last_old_space_gc_ = PromotedSpaceSize(); | 762 size_of_old_gen_at_last_old_space_gc_ = PromotedSpaceSize(); |
| 783 | 763 |
| 784 if (high_survival_rate_during_scavenges && | 764 if (high_survival_rate_during_scavenges && |
| 785 IsStableOrIncreasingSurvivalTrend()) { | 765 IsStableOrIncreasingSurvivalTrend()) { |
| 786 // Stable high survival rates of young objects both during partial and | 766 // Stable high survival rates of young objects both during partial and |
| 787 // full collection indicate that mutator is either building or modifying | 767 // full collection indicate that mutator is either building or modifying |
| 788 // a structure with a long lifetime. | 768 // a structure with a long lifetime. |
| 789 // In this case we aggressively raise old generation memory limits to | 769 // In this case we aggressively raise old generation memory limits to |
| 790 // postpone subsequent mark-sweep collection and thus trade memory | 770 // postpone subsequent mark-sweep collection and thus trade memory |
| 791 // space for the mutation speed. | 771 // space for the mutation speed. |
| 792 old_gen_limit_factor_ = 2; | 772 old_gen_limit_factor_ = 2; |
| 793 } else { | 773 } else { |
| 794 old_gen_limit_factor_ = 1; | 774 old_gen_limit_factor_ = 1; |
| 795 } | 775 } |
| 796 | 776 |
| 797 old_gen_promotion_limit_ = | 777 old_gen_promotion_limit_ = |
| 798 OldGenPromotionLimit(size_of_old_gen_at_last_old_space_gc_); | 778 OldGenPromotionLimit(size_of_old_gen_at_last_old_space_gc_); |
| 799 old_gen_allocation_limit_ = | 779 old_gen_allocation_limit_ = |
| 800 OldGenAllocationLimit(size_of_old_gen_at_last_old_space_gc_); | 780 OldGenAllocationLimit(size_of_old_gen_at_last_old_space_gc_); |
| 801 | 781 |
| 802 old_gen_exhausted_ = false; | 782 old_gen_exhausted_ = false; |
| 803 } else { | 783 } else { |
| 804 tracer_ = tracer; | 784 tracer_ = tracer; |
| 805 Scavenge(); | 785 Scavenge(); |
| 806 tracer_ = NULL; | 786 tracer_ = NULL; |
| 807 | 787 |
| 808 UpdateSurvivalRateTrend(start_new_space_size); | 788 UpdateSurvivalRateTrend(start_new_space_size); |
| 809 } | 789 } |
| 810 | 790 |
| 791 if (!new_space_high_promotion_mode_active_ && |
| 792 new_space_.Capacity() == new_space_.MaximumCapacity() && |
| 793 IsStableOrIncreasingSurvivalTrend() && |
| 794 IsHighSurvivalRate()) { |
| 795 // Stable high survival rates even though young generation is at |
| 796 // maximum capacity indicates that most objects will be promoted. |
| 797 // To decrease scavenger pauses and final mark-sweep pauses, we |
| 798 // have to limit maximal capacity of the young generation. |
| 799 new_space_high_promotion_mode_active_ = true; |
| 800 if (FLAG_trace_gc) { |
| 801 PrintF("Limited new space size due to high promotion rate: %d MB\n", |
| 802 new_space_.InitialCapacity() / MB); |
| 803 } |
| 804 } else if (new_space_high_promotion_mode_active_ && |
| 805 IsStableOrDecreasingSurvivalTrend() && |
| 806 IsLowSurvivalRate()) { |
| 807 // Decreasing low survival rates might indicate that the above high |
| 808 // promotion mode is over and we should allow the young generation |
| 809 // to grow again. |
| 810 new_space_high_promotion_mode_active_ = false; |
| 811 if (FLAG_trace_gc) { |
| 812 PrintF("Unlimited new space size due to low promotion rate: %d MB\n", |
| 813 new_space_.MaximumCapacity() / MB); |
| 814 } |
| 815 } |
| 816 |
| 811 if (new_space_high_promotion_mode_active_ && | 817 if (new_space_high_promotion_mode_active_ && |
| 812 new_space_.Capacity() > new_space_.InitialCapacity()) { | 818 new_space_.Capacity() > new_space_.InitialCapacity()) { |
| 813 new_space_.Shrink(); | 819 new_space_.Shrink(); |
| 814 } | 820 } |
| 815 | 821 |
| 816 isolate_->counters()->objs_since_last_young()->Set(0); | 822 isolate_->counters()->objs_since_last_young()->Set(0); |
| 817 | 823 |
| 818 gc_post_processing_depth_++; | 824 gc_post_processing_depth_++; |
| 819 { DisableAssertNoAllocation allow_allocation; | 825 { DisableAssertNoAllocation allow_allocation; |
| 820 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); | 826 GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1083 | 1089 |
| 1084 gc_state_ = SCAVENGE; | 1090 gc_state_ = SCAVENGE; |
| 1085 | 1091 |
| 1086 // Implements Cheney's copying algorithm | 1092 // Implements Cheney's copying algorithm |
| 1087 LOG(isolate_, ResourceEvent("scavenge", "begin")); | 1093 LOG(isolate_, ResourceEvent("scavenge", "begin")); |
| 1088 | 1094 |
| 1089 // Clear descriptor cache. | 1095 // Clear descriptor cache. |
| 1090 isolate_->descriptor_lookup_cache()->Clear(); | 1096 isolate_->descriptor_lookup_cache()->Clear(); |
| 1091 | 1097 |
| 1092 // Used for updating survived_since_last_expansion_ at function end. | 1098 // Used for updating survived_since_last_expansion_ at function end. |
| 1093 intptr_t survived_watermark = PromotedSpaceSize(); | 1099 intptr_t survived_watermark = PromotedSpaceSizeOfObjects(); |
| 1094 | 1100 |
| 1095 CheckNewSpaceExpansionCriteria(); | 1101 CheckNewSpaceExpansionCriteria(); |
| 1096 | 1102 |
| 1097 SelectScavengingVisitorsTable(); | 1103 SelectScavengingVisitorsTable(); |
| 1098 | 1104 |
| 1099 incremental_marking()->PrepareForScavenge(); | 1105 incremental_marking()->PrepareForScavenge(); |
| 1100 | 1106 |
| 1101 old_pointer_space()->AdvanceSweeper(new_space_.Size()); | 1107 old_pointer_space()->AdvanceSweeper(new_space_.Size()); |
| 1102 old_data_space()->AdvanceSweeper(new_space_.Size()); | 1108 old_data_space()->AdvanceSweeper(new_space_.Size()); |
| 1103 | 1109 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1176 ASSERT(new_space_front == new_space_.top()); | 1182 ASSERT(new_space_front == new_space_.top()); |
| 1177 | 1183 |
| 1178 // Set age mark. | 1184 // Set age mark. |
| 1179 new_space_.set_age_mark(new_space_.top()); | 1185 new_space_.set_age_mark(new_space_.top()); |
| 1180 | 1186 |
| 1181 new_space_.LowerInlineAllocationLimit( | 1187 new_space_.LowerInlineAllocationLimit( |
| 1182 new_space_.inline_allocation_limit_step()); | 1188 new_space_.inline_allocation_limit_step()); |
| 1183 | 1189 |
| 1184 // Update how much has survived scavenge. | 1190 // Update how much has survived scavenge. |
| 1185 IncrementYoungSurvivorsCounter(static_cast<int>( | 1191 IncrementYoungSurvivorsCounter(static_cast<int>( |
| 1186 (PromotedSpaceSize() - survived_watermark) + new_space_.Size())); | 1192 (PromotedSpaceSizeOfObjects() - survived_watermark) + new_space_.Size())); |
| 1187 | 1193 |
| 1188 LOG(isolate_, ResourceEvent("scavenge", "end")); | 1194 LOG(isolate_, ResourceEvent("scavenge", "end")); |
| 1189 | 1195 |
| 1190 gc_state_ = NOT_IN_GC; | 1196 gc_state_ = NOT_IN_GC; |
| 1191 } | 1197 } |
| 1192 | 1198 |
| 1193 | 1199 |
| 1194 String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap, | 1200 String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap, |
| 1195 Object** p) { | 1201 Object** p) { |
| 1196 MapWord first_word = HeapObject::cast(*p)->map_word(); | 1202 MapWord first_word = HeapObject::cast(*p)->map_word(); |
| (...skipping 4087 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5284 intptr_t Heap::PromotedSpaceSize() { | 5290 intptr_t Heap::PromotedSpaceSize() { |
| 5285 return old_pointer_space_->Size() | 5291 return old_pointer_space_->Size() |
| 5286 + old_data_space_->Size() | 5292 + old_data_space_->Size() |
| 5287 + code_space_->Size() | 5293 + code_space_->Size() |
| 5288 + map_space_->Size() | 5294 + map_space_->Size() |
| 5289 + cell_space_->Size() | 5295 + cell_space_->Size() |
| 5290 + lo_space_->Size(); | 5296 + lo_space_->Size(); |
| 5291 } | 5297 } |
| 5292 | 5298 |
| 5293 | 5299 |
| 5300 intptr_t Heap::PromotedSpaceSizeOfObjects() { |
| 5301 return old_pointer_space_->SizeOfObjects() |
| 5302 + old_data_space_->SizeOfObjects() |
| 5303 + code_space_->SizeOfObjects() |
| 5304 + map_space_->SizeOfObjects() |
| 5305 + cell_space_->SizeOfObjects() |
| 5306 + lo_space_->SizeOfObjects(); |
| 5307 } |
| 5308 |
| 5309 |
| 5294 int Heap::PromotedExternalMemorySize() { | 5310 int Heap::PromotedExternalMemorySize() { |
| 5295 if (amount_of_external_allocated_memory_ | 5311 if (amount_of_external_allocated_memory_ |
| 5296 <= amount_of_external_allocated_memory_at_last_global_gc_) return 0; | 5312 <= amount_of_external_allocated_memory_at_last_global_gc_) return 0; |
| 5297 return amount_of_external_allocated_memory_ | 5313 return amount_of_external_allocated_memory_ |
| 5298 - amount_of_external_allocated_memory_at_last_global_gc_; | 5314 - amount_of_external_allocated_memory_at_last_global_gc_; |
| 5299 } | 5315 } |
| 5300 | 5316 |
| 5301 #ifdef DEBUG | 5317 #ifdef DEBUG |
| 5302 | 5318 |
| 5303 // Tags 0, 1, and 3 are used. Use 2 for marking visited HeapObject. | 5319 // Tags 0, 1, and 3 are used. Use 2 for marking visited HeapObject. |
| (...skipping 1216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6520 isolate_->heap()->store_buffer()->Compact(); | 6536 isolate_->heap()->store_buffer()->Compact(); |
| 6521 isolate_->heap()->store_buffer()->Filter(MemoryChunk::ABOUT_TO_BE_FREED); | 6537 isolate_->heap()->store_buffer()->Filter(MemoryChunk::ABOUT_TO_BE_FREED); |
| 6522 for (chunk = chunks_queued_for_free_; chunk != NULL; chunk = next) { | 6538 for (chunk = chunks_queued_for_free_; chunk != NULL; chunk = next) { |
| 6523 next = chunk->next_chunk(); | 6539 next = chunk->next_chunk(); |
| 6524 isolate_->memory_allocator()->Free(chunk); | 6540 isolate_->memory_allocator()->Free(chunk); |
| 6525 } | 6541 } |
| 6526 chunks_queued_for_free_ = NULL; | 6542 chunks_queued_for_free_ = NULL; |
| 6527 } | 6543 } |
| 6528 | 6544 |
| 6529 } } // namespace v8::internal | 6545 } } // namespace v8::internal |
| OLD | NEW |