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 AdvanceSweepers(static_cast<int>(new_space_.Size())); | 1107 AdvanceSweepers(static_cast<int>(new_space_.Size())); |
1102 | 1108 |
1103 // Flip the semispaces. After flipping, to space is empty, from space has | 1109 // Flip the semispaces. After flipping, to space is empty, from space has |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1175 ASSERT(new_space_front == new_space_.top()); | 1181 ASSERT(new_space_front == new_space_.top()); |
1176 | 1182 |
1177 // Set age mark. | 1183 // Set age mark. |
1178 new_space_.set_age_mark(new_space_.top()); | 1184 new_space_.set_age_mark(new_space_.top()); |
1179 | 1185 |
1180 new_space_.LowerInlineAllocationLimit( | 1186 new_space_.LowerInlineAllocationLimit( |
1181 new_space_.inline_allocation_limit_step()); | 1187 new_space_.inline_allocation_limit_step()); |
1182 | 1188 |
1183 // Update how much has survived scavenge. | 1189 // Update how much has survived scavenge. |
1184 IncrementYoungSurvivorsCounter(static_cast<int>( | 1190 IncrementYoungSurvivorsCounter(static_cast<int>( |
1185 (PromotedSpaceSize() - survived_watermark) + new_space_.Size())); | 1191 (PromotedSpaceSizeOfObjects() - survived_watermark) + new_space_.Size())); |
1186 | 1192 |
1187 LOG(isolate_, ResourceEvent("scavenge", "end")); | 1193 LOG(isolate_, ResourceEvent("scavenge", "end")); |
1188 | 1194 |
1189 gc_state_ = NOT_IN_GC; | 1195 gc_state_ = NOT_IN_GC; |
1190 | 1196 |
1191 scavenges_since_last_idle_round_++; | 1197 scavenges_since_last_idle_round_++; |
1192 } | 1198 } |
1193 | 1199 |
1194 | 1200 |
1195 String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap, | 1201 String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap, |
(...skipping 4210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5406 intptr_t Heap::PromotedSpaceSize() { | 5412 intptr_t Heap::PromotedSpaceSize() { |
5407 return old_pointer_space_->Size() | 5413 return old_pointer_space_->Size() |
5408 + old_data_space_->Size() | 5414 + old_data_space_->Size() |
5409 + code_space_->Size() | 5415 + code_space_->Size() |
5410 + map_space_->Size() | 5416 + map_space_->Size() |
5411 + cell_space_->Size() | 5417 + cell_space_->Size() |
5412 + lo_space_->Size(); | 5418 + lo_space_->Size(); |
5413 } | 5419 } |
5414 | 5420 |
5415 | 5421 |
| 5422 intptr_t Heap::PromotedSpaceSizeOfObjects() { |
| 5423 return old_pointer_space_->SizeOfObjects() |
| 5424 + old_data_space_->SizeOfObjects() |
| 5425 + code_space_->SizeOfObjects() |
| 5426 + map_space_->SizeOfObjects() |
| 5427 + cell_space_->SizeOfObjects() |
| 5428 + lo_space_->SizeOfObjects(); |
| 5429 } |
| 5430 |
| 5431 |
5416 int Heap::PromotedExternalMemorySize() { | 5432 int Heap::PromotedExternalMemorySize() { |
5417 if (amount_of_external_allocated_memory_ | 5433 if (amount_of_external_allocated_memory_ |
5418 <= amount_of_external_allocated_memory_at_last_global_gc_) return 0; | 5434 <= amount_of_external_allocated_memory_at_last_global_gc_) return 0; |
5419 return amount_of_external_allocated_memory_ | 5435 return amount_of_external_allocated_memory_ |
5420 - amount_of_external_allocated_memory_at_last_global_gc_; | 5436 - amount_of_external_allocated_memory_at_last_global_gc_; |
5421 } | 5437 } |
5422 | 5438 |
5423 #ifdef DEBUG | 5439 #ifdef DEBUG |
5424 | 5440 |
5425 // Tags 0, 1, and 3 are used. Use 2 for marking visited HeapObject. | 5441 // Tags 0, 1, and 3 are used. Use 2 for marking visited HeapObject. |
(...skipping 1228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6654 isolate_->heap()->store_buffer()->Compact(); | 6670 isolate_->heap()->store_buffer()->Compact(); |
6655 isolate_->heap()->store_buffer()->Filter(MemoryChunk::ABOUT_TO_BE_FREED); | 6671 isolate_->heap()->store_buffer()->Filter(MemoryChunk::ABOUT_TO_BE_FREED); |
6656 for (chunk = chunks_queued_for_free_; chunk != NULL; chunk = next) { | 6672 for (chunk = chunks_queued_for_free_; chunk != NULL; chunk = next) { |
6657 next = chunk->next_chunk(); | 6673 next = chunk->next_chunk(); |
6658 isolate_->memory_allocator()->Free(chunk); | 6674 isolate_->memory_allocator()->Free(chunk); |
6659 } | 6675 } |
6660 chunks_queued_for_free_ = NULL; | 6676 chunks_queued_for_free_ = NULL; |
6661 } | 6677 } |
6662 | 6678 |
6663 } } // namespace v8::internal | 6679 } } // namespace v8::internal |
OLD | NEW |