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/heap/heap.h" | 5 #include "src/heap/heap.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 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 crankshaft_codegen_bytes_generated_(0), | 127 crankshaft_codegen_bytes_generated_(0), |
128 new_space_allocation_counter_(0), | 128 new_space_allocation_counter_(0), |
129 old_generation_allocation_counter_(0), | 129 old_generation_allocation_counter_(0), |
130 old_generation_size_at_last_gc_(0), | 130 old_generation_size_at_last_gc_(0), |
131 gcs_since_last_deopt_(0), | 131 gcs_since_last_deopt_(0), |
132 allocation_sites_scratchpad_length_(0), | 132 allocation_sites_scratchpad_length_(0), |
133 ring_buffer_full_(false), | 133 ring_buffer_full_(false), |
134 ring_buffer_end_(0), | 134 ring_buffer_end_(0), |
135 promotion_queue_(this), | 135 promotion_queue_(this), |
136 configured_(false), | 136 configured_(false), |
| 137 current_gc_flags_(Heap::kNoGCFlags), |
137 external_string_table_(this), | 138 external_string_table_(this), |
138 chunks_queued_for_free_(NULL), | 139 chunks_queued_for_free_(NULL), |
139 gc_callbacks_depth_(0), | 140 gc_callbacks_depth_(0), |
140 deserialization_complete_(false), | 141 deserialization_complete_(false), |
141 concurrent_sweeping_enabled_(false), | 142 concurrent_sweeping_enabled_(false), |
142 strong_roots_list_(NULL) { | 143 strong_roots_list_(NULL) { |
143 // Allow build-time customization of the max semispace size. Building | 144 // Allow build-time customization of the max semispace size. Building |
144 // V8 with snapshots and a non-default max semispace size is much | 145 // V8 with snapshots and a non-default max semispace size is much |
145 // easier if you can define it as part of the build environment. | 146 // easier if you can define it as part of the build environment. |
146 #if defined(V8_MAX_SEMISPACE_SIZE) | 147 #if defined(V8_MAX_SEMISPACE_SIZE) |
(...skipping 644 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
791 } | 792 } |
792 } | 793 } |
793 } | 794 } |
794 | 795 |
795 | 796 |
796 void Heap::CollectAllGarbage(int flags, const char* gc_reason, | 797 void Heap::CollectAllGarbage(int flags, const char* gc_reason, |
797 const v8::GCCallbackFlags gc_callback_flags) { | 798 const v8::GCCallbackFlags gc_callback_flags) { |
798 // Since we are ignoring the return value, the exact choice of space does | 799 // Since we are ignoring the return value, the exact choice of space does |
799 // not matter, so long as we do not specify NEW_SPACE, which would not | 800 // not matter, so long as we do not specify NEW_SPACE, which would not |
800 // cause a full GC. | 801 // cause a full GC. |
801 mark_compact_collector_.SetFlags(flags); | 802 set_current_gc_flags(flags); |
802 CollectGarbage(OLD_SPACE, gc_reason, gc_callback_flags); | 803 CollectGarbage(OLD_SPACE, gc_reason, gc_callback_flags); |
803 mark_compact_collector_.SetFlags(kNoGCFlags); | 804 set_current_gc_flags(kNoGCFlags); |
804 } | 805 } |
805 | 806 |
806 | 807 |
807 void Heap::CollectAllAvailableGarbage(const char* gc_reason) { | 808 void Heap::CollectAllAvailableGarbage(const char* gc_reason) { |
808 // Since we are ignoring the return value, the exact choice of space does | 809 // Since we are ignoring the return value, the exact choice of space does |
809 // not matter, so long as we do not specify NEW_SPACE, which would not | 810 // not matter, so long as we do not specify NEW_SPACE, which would not |
810 // cause a full GC. | 811 // cause a full GC. |
811 // Major GC would invoke weak handle callbacks on weakly reachable | 812 // Major GC would invoke weak handle callbacks on weakly reachable |
812 // handles, but won't collect weakly reachable objects until next | 813 // handles, but won't collect weakly reachable objects until next |
813 // major GC. Therefore if we collect aggressively and weak handle callback | 814 // major GC. Therefore if we collect aggressively and weak handle callback |
814 // has been invoked, we rerun major GC to release objects which become | 815 // has been invoked, we rerun major GC to release objects which become |
815 // garbage. | 816 // garbage. |
816 // Note: as weak callbacks can execute arbitrary code, we cannot | 817 // Note: as weak callbacks can execute arbitrary code, we cannot |
817 // hope that eventually there will be no weak callbacks invocations. | 818 // hope that eventually there will be no weak callbacks invocations. |
818 // Therefore stop recollecting after several attempts. | 819 // Therefore stop recollecting after several attempts. |
819 if (isolate()->concurrent_recompilation_enabled()) { | 820 if (isolate()->concurrent_recompilation_enabled()) { |
820 // The optimizing compiler may be unnecessarily holding on to memory. | 821 // The optimizing compiler may be unnecessarily holding on to memory. |
821 DisallowHeapAllocation no_recursive_gc; | 822 DisallowHeapAllocation no_recursive_gc; |
822 isolate()->optimizing_compile_dispatcher()->Flush(); | 823 isolate()->optimizing_compile_dispatcher()->Flush(); |
823 } | 824 } |
824 isolate()->ClearSerializerData(); | 825 isolate()->ClearSerializerData(); |
825 mark_compact_collector()->SetFlags(kMakeHeapIterableMask | | 826 set_current_gc_flags(kMakeHeapIterableMask | kReduceMemoryFootprintMask); |
826 kReduceMemoryFootprintMask); | |
827 isolate_->compilation_cache()->Clear(); | 827 isolate_->compilation_cache()->Clear(); |
828 const int kMaxNumberOfAttempts = 7; | 828 const int kMaxNumberOfAttempts = 7; |
829 const int kMinNumberOfAttempts = 2; | 829 const int kMinNumberOfAttempts = 2; |
830 for (int attempt = 0; attempt < kMaxNumberOfAttempts; attempt++) { | 830 for (int attempt = 0; attempt < kMaxNumberOfAttempts; attempt++) { |
831 if (!CollectGarbage(MARK_COMPACTOR, gc_reason, NULL, | 831 if (!CollectGarbage(MARK_COMPACTOR, gc_reason, NULL, |
832 v8::kGCCallbackFlagForced) && | 832 v8::kGCCallbackFlagForced) && |
833 attempt + 1 >= kMinNumberOfAttempts) { | 833 attempt + 1 >= kMinNumberOfAttempts) { |
834 break; | 834 break; |
835 } | 835 } |
836 } | 836 } |
837 mark_compact_collector()->SetFlags(kNoGCFlags); | 837 set_current_gc_flags(kNoGCFlags); |
838 new_space_.Shrink(); | 838 new_space_.Shrink(); |
839 UncommitFromSpace(); | 839 UncommitFromSpace(); |
840 } | 840 } |
841 | 841 |
842 | 842 |
843 void Heap::EnsureFillerObjectAtTop() { | 843 void Heap::EnsureFillerObjectAtTop() { |
844 // There may be an allocation memento behind every object in new space. | 844 // There may be an allocation memento behind every object in new space. |
845 // If we evacuate a not full new space or if we are on the last page of | 845 // If we evacuate a not full new space or if we are on the last page of |
846 // the new space, then there may be uninitialized memory behind the top | 846 // the new space, then there may be uninitialized memory behind the top |
847 // pointer of the new space page. We store a filler object there to | 847 // pointer of the new space page. We store a filler object there to |
(...skipping 27 matching lines...) Expand all Loading... |
875 #endif | 875 #endif |
876 | 876 |
877 EnsureFillerObjectAtTop(); | 877 EnsureFillerObjectAtTop(); |
878 | 878 |
879 if (collector == SCAVENGER && !incremental_marking()->IsStopped()) { | 879 if (collector == SCAVENGER && !incremental_marking()->IsStopped()) { |
880 if (FLAG_trace_incremental_marking) { | 880 if (FLAG_trace_incremental_marking) { |
881 PrintF("[IncrementalMarking] Scavenge during marking.\n"); | 881 PrintF("[IncrementalMarking] Scavenge during marking.\n"); |
882 } | 882 } |
883 } | 883 } |
884 | 884 |
885 if (collector == MARK_COMPACTOR && | 885 if (collector == MARK_COMPACTOR && !ShouldFinalizeIncrementalMarking() && |
886 !mark_compact_collector()->finalize_incremental_marking() && | 886 !ShouldAbortIncrementalMarking() && !incremental_marking()->IsStopped() && |
887 !mark_compact_collector()->abort_incremental_marking() && | |
888 !incremental_marking()->IsStopped() && | |
889 !incremental_marking()->should_hurry() && FLAG_incremental_marking) { | 887 !incremental_marking()->should_hurry() && FLAG_incremental_marking) { |
890 // Make progress in incremental marking. | 888 // Make progress in incremental marking. |
891 const intptr_t kStepSizeWhenDelayedByScavenge = 1 * MB; | 889 const intptr_t kStepSizeWhenDelayedByScavenge = 1 * MB; |
892 incremental_marking()->Step(kStepSizeWhenDelayedByScavenge, | 890 incremental_marking()->Step(kStepSizeWhenDelayedByScavenge, |
893 IncrementalMarking::NO_GC_VIA_STACK_GUARD); | 891 IncrementalMarking::NO_GC_VIA_STACK_GUARD); |
894 if (!incremental_marking()->IsComplete() && | 892 if (!incremental_marking()->IsComplete() && |
895 !mark_compact_collector_.marking_deque_.IsEmpty() && !FLAG_gc_global) { | 893 !mark_compact_collector_.marking_deque_.IsEmpty() && !FLAG_gc_global) { |
896 if (FLAG_trace_incremental_marking) { | 894 if (FLAG_trace_incremental_marking) { |
897 PrintF("[IncrementalMarking] Delaying MarkSweep.\n"); | 895 PrintF("[IncrementalMarking] Delaying MarkSweep.\n"); |
898 } | 896 } |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
949 tracer()->Stop(collector); | 947 tracer()->Stop(collector); |
950 } | 948 } |
951 | 949 |
952 if (collector == MARK_COMPACTOR && | 950 if (collector == MARK_COMPACTOR && |
953 (gc_callback_flags & kGCCallbackFlagForced) != 0) { | 951 (gc_callback_flags & kGCCallbackFlagForced) != 0) { |
954 isolate()->CountUsage(v8::Isolate::kForcedGC); | 952 isolate()->CountUsage(v8::Isolate::kForcedGC); |
955 } | 953 } |
956 | 954 |
957 // Start incremental marking for the next cycle. The heap snapshot | 955 // Start incremental marking for the next cycle. The heap snapshot |
958 // generator needs incremental marking to stay off after it aborted. | 956 // generator needs incremental marking to stay off after it aborted. |
959 if (!mark_compact_collector()->abort_incremental_marking() && | 957 if (!ShouldAbortIncrementalMarking() && incremental_marking()->IsStopped() && |
960 incremental_marking()->IsStopped() && | |
961 incremental_marking()->ShouldActivateEvenWithoutIdleNotification()) { | 958 incremental_marking()->ShouldActivateEvenWithoutIdleNotification()) { |
962 incremental_marking()->Start(kNoGCFlags, kNoGCCallbackFlags, "GC epilogue"); | 959 incremental_marking()->Start(kNoGCFlags, kNoGCCallbackFlags, "GC epilogue"); |
963 } | 960 } |
964 | 961 |
965 return next_gc_likely_to_collect_more; | 962 return next_gc_likely_to_collect_more; |
966 } | 963 } |
967 | 964 |
968 | 965 |
969 int Heap::NotifyContextDisposed(bool dependant_context) { | 966 int Heap::NotifyContextDisposed(bool dependant_context) { |
970 if (!dependant_context) { | 967 if (!dependant_context) { |
(...skipping 4686 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5657 // memory-constrained devices. | 5654 // memory-constrained devices. |
5658 if (max_old_generation_size_ <= kMaxOldSpaceSizeMediumMemoryDevice || | 5655 if (max_old_generation_size_ <= kMaxOldSpaceSizeMediumMemoryDevice || |
5659 FLAG_optimize_for_size) { | 5656 FLAG_optimize_for_size) { |
5660 factor = Min(factor, kMaxHeapGrowingFactorMemoryConstrained); | 5657 factor = Min(factor, kMaxHeapGrowingFactorMemoryConstrained); |
5661 } | 5658 } |
5662 | 5659 |
5663 if (memory_reducer_.ShouldGrowHeapSlowly() || optimize_for_memory_usage_) { | 5660 if (memory_reducer_.ShouldGrowHeapSlowly() || optimize_for_memory_usage_) { |
5664 factor = Min(factor, kConservativeHeapGrowingFactor); | 5661 factor = Min(factor, kConservativeHeapGrowingFactor); |
5665 } | 5662 } |
5666 | 5663 |
5667 if (FLAG_stress_compaction || | 5664 if (FLAG_stress_compaction || ShouldReduceMemory()) { |
5668 mark_compact_collector()->reduce_memory_footprint_) { | |
5669 factor = kMinHeapGrowingFactor; | 5665 factor = kMinHeapGrowingFactor; |
5670 } | 5666 } |
5671 | 5667 |
5672 old_generation_allocation_limit_ = | 5668 old_generation_allocation_limit_ = |
5673 CalculateOldGenerationAllocationLimit(factor, old_gen_size); | 5669 CalculateOldGenerationAllocationLimit(factor, old_gen_size); |
5674 | 5670 |
5675 if (FLAG_trace_gc_verbose) { | 5671 if (FLAG_trace_gc_verbose) { |
5676 PrintIsolate(isolate_, "Grow: old size: %" V8_PTR_PREFIX | 5672 PrintIsolate(isolate_, "Grow: old size: %" V8_PTR_PREFIX |
5677 "d KB, new limit: %" V8_PTR_PREFIX "d KB (%.1f)\n", | 5673 "d KB, new limit: %" V8_PTR_PREFIX "d KB (%.1f)\n", |
5678 old_gen_size / KB, old_generation_allocation_limit_ / KB, | 5674 old_gen_size / KB, old_generation_allocation_limit_ / KB, |
(...skipping 1224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6903 *object_type = "CODE_TYPE"; \ | 6899 *object_type = "CODE_TYPE"; \ |
6904 *object_sub_type = "CODE_AGE/" #name; \ | 6900 *object_sub_type = "CODE_AGE/" #name; \ |
6905 return true; | 6901 return true; |
6906 CODE_AGE_LIST_COMPLETE(COMPARE_AND_RETURN_NAME) | 6902 CODE_AGE_LIST_COMPLETE(COMPARE_AND_RETURN_NAME) |
6907 #undef COMPARE_AND_RETURN_NAME | 6903 #undef COMPARE_AND_RETURN_NAME |
6908 } | 6904 } |
6909 return false; | 6905 return false; |
6910 } | 6906 } |
6911 } // namespace internal | 6907 } // namespace internal |
6912 } // namespace v8 | 6908 } // namespace v8 |
OLD | NEW |