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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 namespace internal { | 43 namespace internal { |
44 | 44 |
45 | 45 |
46 struct Heap::StrongRootsList { | 46 struct Heap::StrongRootsList { |
47 Object** start; | 47 Object** start; |
48 Object** end; | 48 Object** end; |
49 StrongRootsList* next; | 49 StrongRootsList* next; |
50 }; | 50 }; |
51 | 51 |
52 | 52 |
53 DEFINE_OPERATORS_FOR_FLAGS(Heap::GCFlags) | |
54 | |
55 | |
56 Heap::Heap() | 53 Heap::Heap() |
57 : amount_of_external_allocated_memory_(0), | 54 : amount_of_external_allocated_memory_(0), |
58 amount_of_external_allocated_memory_at_last_global_gc_(0), | 55 amount_of_external_allocated_memory_at_last_global_gc_(0), |
59 isolate_(NULL), | 56 isolate_(NULL), |
60 code_range_size_(0), | 57 code_range_size_(0), |
61 // semispace_size_ should be a power of 2 and old_generation_size_ should | 58 // semispace_size_ should be a power of 2 and old_generation_size_ should |
62 // be a multiple of Page::kPageSize. | 59 // be a multiple of Page::kPageSize. |
63 reserved_semispace_size_(8 * (kPointerSize / 4) * MB), | 60 reserved_semispace_size_(8 * (kPointerSize / 4) * MB), |
64 max_semi_space_size_(8 * (kPointerSize / 4) * MB), | 61 max_semi_space_size_(8 * (kPointerSize / 4) * MB), |
65 initial_semispace_size_(Page::kPageSize), | 62 initial_semispace_size_(Page::kPageSize), |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 crankshaft_codegen_bytes_generated_(0), | 126 crankshaft_codegen_bytes_generated_(0), |
130 new_space_allocation_counter_(0), | 127 new_space_allocation_counter_(0), |
131 old_generation_allocation_counter_(0), | 128 old_generation_allocation_counter_(0), |
132 old_generation_size_at_last_gc_(0), | 129 old_generation_size_at_last_gc_(0), |
133 gcs_since_last_deopt_(0), | 130 gcs_since_last_deopt_(0), |
134 allocation_sites_scratchpad_length_(0), | 131 allocation_sites_scratchpad_length_(0), |
135 ring_buffer_full_(false), | 132 ring_buffer_full_(false), |
136 ring_buffer_end_(0), | 133 ring_buffer_end_(0), |
137 promotion_queue_(this), | 134 promotion_queue_(this), |
138 configured_(false), | 135 configured_(false), |
139 current_gc_flags_(kNoGCFlags), | 136 current_gc_flags_(Heap::kNoGCFlags), |
140 current_gc_callback_flags_(GCCallbackFlags::kNoGCCallbackFlags), | 137 current_gc_callback_flags_(GCCallbackFlags::kNoGCCallbackFlags), |
141 external_string_table_(this), | 138 external_string_table_(this), |
142 chunks_queued_for_free_(NULL), | 139 chunks_queued_for_free_(NULL), |
143 concurrent_unmapping_tasks_active_(0), | 140 concurrent_unmapping_tasks_active_(0), |
144 pending_unmapping_tasks_semaphore_(0), | 141 pending_unmapping_tasks_semaphore_(0), |
145 gc_callbacks_depth_(0), | 142 gc_callbacks_depth_(0), |
146 deserialization_complete_(false), | 143 deserialization_complete_(false), |
147 concurrent_sweeping_enabled_(false), | 144 concurrent_sweeping_enabled_(false), |
148 strong_roots_list_(NULL) { | 145 strong_roots_list_(NULL) { |
149 // Allow build-time customization of the max semispace size. Building | 146 // Allow build-time customization of the max semispace size. Building |
(...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
746 } | 743 } |
747 // We must not compact the weak fixed list here, as we may be in the middle | 744 // We must not compact the weak fixed list here, as we may be in the middle |
748 // of writing to it, when the GC triggered. Instead, we reset the root value. | 745 // of writing to it, when the GC triggered. Instead, we reset the root value. |
749 set_weak_stack_trace_list(Smi::FromInt(0)); | 746 set_weak_stack_trace_list(Smi::FromInt(0)); |
750 } | 747 } |
751 | 748 |
752 | 749 |
753 void Heap::HandleGCRequest() { | 750 void Heap::HandleGCRequest() { |
754 if (incremental_marking()->request_type() == | 751 if (incremental_marking()->request_type() == |
755 IncrementalMarking::COMPLETE_MARKING) { | 752 IncrementalMarking::COMPLETE_MARKING) { |
756 CollectAllGarbage("GC interrupt", current_gc_flags_, | 753 CollectAllGarbage(current_gc_flags_, "GC interrupt", |
757 current_gc_callback_flags_); | 754 current_gc_callback_flags_); |
758 return; | 755 return; |
759 } | 756 } |
760 DCHECK(FLAG_overapproximate_weak_closure); | 757 DCHECK(FLAG_overapproximate_weak_closure); |
761 if (!incremental_marking()->weak_closure_was_overapproximated()) { | 758 if (!incremental_marking()->weak_closure_was_overapproximated()) { |
762 OverApproximateWeakClosure("GC interrupt"); | 759 OverApproximateWeakClosure("GC interrupt"); |
763 } | 760 } |
764 } | 761 } |
765 | 762 |
766 | 763 |
(...skipping 23 matching lines...) Expand all Loading... |
790 AllowHeapAllocation allow_allocation; | 787 AllowHeapAllocation allow_allocation; |
791 GCTracer::Scope scope(tracer(), GCTracer::Scope::EXTERNAL); | 788 GCTracer::Scope scope(tracer(), GCTracer::Scope::EXTERNAL); |
792 VMState<EXTERNAL> state(isolate_); | 789 VMState<EXTERNAL> state(isolate_); |
793 HandleScope handle_scope(isolate_); | 790 HandleScope handle_scope(isolate_); |
794 CallGCEpilogueCallbacks(kGCTypeIncrementalMarking, kNoGCCallbackFlags); | 791 CallGCEpilogueCallbacks(kGCTypeIncrementalMarking, kNoGCCallbackFlags); |
795 } | 792 } |
796 } | 793 } |
797 } | 794 } |
798 | 795 |
799 | 796 |
800 void Heap::CollectAllGarbage(const char* gc_reason, const GCFlags flags, | 797 void Heap::CollectAllGarbage(int flags, const char* gc_reason, |
801 const v8::GCCallbackFlags gc_callback_flags) { | 798 const v8::GCCallbackFlags gc_callback_flags) { |
802 // 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 |
803 // 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 |
804 // cause a full GC. | 801 // cause a full GC. |
805 CollectGarbage(OLD_SPACE, gc_reason, flags, gc_callback_flags); | 802 set_current_gc_flags(flags); |
| 803 CollectGarbage(OLD_SPACE, gc_reason, gc_callback_flags); |
| 804 set_current_gc_flags(kNoGCFlags); |
806 } | 805 } |
807 | 806 |
808 | 807 |
809 void Heap::CollectAllAvailableGarbage(const char* gc_reason) { | 808 void Heap::CollectAllAvailableGarbage(const char* gc_reason) { |
810 // 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 |
811 // 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 |
812 // cause a full GC. | 811 // cause a full GC. |
813 // Major GC would invoke weak handle callbacks on weakly reachable | 812 // Major GC would invoke weak handle callbacks on weakly reachable |
814 // handles, but won't collect weakly reachable objects until next | 813 // handles, but won't collect weakly reachable objects until next |
815 // major GC. Therefore if we collect aggressively and weak handle callback | 814 // major GC. Therefore if we collect aggressively and weak handle callback |
816 // 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 |
817 // garbage. | 816 // garbage. |
818 // Note: as weak callbacks can execute arbitrary code, we cannot | 817 // Note: as weak callbacks can execute arbitrary code, we cannot |
819 // hope that eventually there will be no weak callbacks invocations. | 818 // hope that eventually there will be no weak callbacks invocations. |
820 // Therefore stop recollecting after several attempts. | 819 // Therefore stop recollecting after several attempts. |
821 if (isolate()->concurrent_recompilation_enabled()) { | 820 if (isolate()->concurrent_recompilation_enabled()) { |
822 // The optimizing compiler may be unnecessarily holding on to memory. | 821 // The optimizing compiler may be unnecessarily holding on to memory. |
823 DisallowHeapAllocation no_recursive_gc; | 822 DisallowHeapAllocation no_recursive_gc; |
824 isolate()->optimizing_compile_dispatcher()->Flush(); | 823 isolate()->optimizing_compile_dispatcher()->Flush(); |
825 } | 824 } |
826 isolate()->ClearSerializerData(); | 825 isolate()->ClearSerializerData(); |
827 isolate()->compilation_cache()->Clear(); | 826 set_current_gc_flags(kMakeHeapIterableMask | kReduceMemoryFootprintMask); |
| 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(OLD_SPACE, gc_reason, | 831 if (!CollectGarbage(MARK_COMPACTOR, gc_reason, NULL, |
832 Heap::kAbortIncrementalMarkingMask | | 832 v8::kGCCallbackFlagForced) && |
833 Heap::kReduceMemoryFootprintMask, | 833 attempt + 1 >= kMinNumberOfAttempts) { |
834 kGCCallbackFlagForced) && | |
835 ((attempt + 1) >= kMinNumberOfAttempts)) { | |
836 break; | 834 break; |
837 } | 835 } |
838 } | 836 } |
| 837 set_current_gc_flags(kNoGCFlags); |
839 new_space_.Shrink(); | 838 new_space_.Shrink(); |
840 UncommitFromSpace(); | 839 UncommitFromSpace(); |
841 } | 840 } |
842 | 841 |
843 | 842 |
844 void Heap::EnsureFillerObjectAtTop() { | 843 void Heap::EnsureFillerObjectAtTop() { |
845 // 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. |
846 // 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 |
847 // 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 |
848 // 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 |
849 // identify the unused space. | 848 // identify the unused space. |
850 Address from_top = new_space_.top(); | 849 Address from_top = new_space_.top(); |
851 // Check that from_top is inside its page (i.e., not at the end). | 850 // Check that from_top is inside its page (i.e., not at the end). |
852 Address space_end = new_space_.ToSpaceEnd(); | 851 Address space_end = new_space_.ToSpaceEnd(); |
853 if (from_top < space_end) { | 852 if (from_top < space_end) { |
854 Page* page = Page::FromAddress(from_top); | 853 Page* page = Page::FromAddress(from_top); |
855 if (page->Contains(from_top)) { | 854 if (page->Contains(from_top)) { |
856 int remaining_in_page = static_cast<int>(page->area_end() - from_top); | 855 int remaining_in_page = static_cast<int>(page->area_end() - from_top); |
857 CreateFillerObjectAt(from_top, remaining_in_page); | 856 CreateFillerObjectAt(from_top, remaining_in_page); |
858 } | 857 } |
859 } | 858 } |
860 } | 859 } |
861 | 860 |
862 | 861 |
863 bool Heap::CollectGarbage(GarbageCollector collector, const char* gc_reason, | 862 bool Heap::CollectGarbage(GarbageCollector collector, const char* gc_reason, |
864 const char* collector_reason) { | 863 const char* collector_reason, |
| 864 const v8::GCCallbackFlags gc_callback_flags) { |
865 // The VM is in the GC state until exiting this function. | 865 // The VM is in the GC state until exiting this function. |
866 VMState<GC> state(isolate_); | 866 VMState<GC> state(isolate_); |
867 | 867 |
868 #ifdef DEBUG | 868 #ifdef DEBUG |
869 // Reset the allocation timeout to the GC interval, but make sure to | 869 // Reset the allocation timeout to the GC interval, but make sure to |
870 // allow at least a few allocations after a collection. The reason | 870 // allow at least a few allocations after a collection. The reason |
871 // for this is that we have a lot of allocation sequences and we | 871 // for this is that we have a lot of allocation sequences and we |
872 // assume that a garbage collection will allow the subsequent | 872 // assume that a garbage collection will allow the subsequent |
873 // allocation attempts to go through. | 873 // allocation attempts to go through. |
874 allocation_timeout_ = Max(6, FLAG_gc_interval); | 874 allocation_timeout_ = Max(6, FLAG_gc_interval); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
909 { | 909 { |
910 tracer()->Start(collector, gc_reason, collector_reason); | 910 tracer()->Start(collector, gc_reason, collector_reason); |
911 DCHECK(AllowHeapAllocation::IsAllowed()); | 911 DCHECK(AllowHeapAllocation::IsAllowed()); |
912 DisallowHeapAllocation no_allocation_during_gc; | 912 DisallowHeapAllocation no_allocation_during_gc; |
913 GarbageCollectionPrologue(); | 913 GarbageCollectionPrologue(); |
914 | 914 |
915 { | 915 { |
916 HistogramTimerScope histogram_timer_scope( | 916 HistogramTimerScope histogram_timer_scope( |
917 (collector == SCAVENGER) ? isolate_->counters()->gc_scavenger() | 917 (collector == SCAVENGER) ? isolate_->counters()->gc_scavenger() |
918 : isolate_->counters()->gc_compactor()); | 918 : isolate_->counters()->gc_compactor()); |
919 next_gc_likely_to_collect_more = PerformGarbageCollection(collector); | 919 next_gc_likely_to_collect_more = |
| 920 PerformGarbageCollection(collector, gc_callback_flags); |
920 } | 921 } |
921 | 922 |
922 GarbageCollectionEpilogue(); | 923 GarbageCollectionEpilogue(); |
923 if (collector == MARK_COMPACTOR && FLAG_track_detached_contexts) { | 924 if (collector == MARK_COMPACTOR && FLAG_track_detached_contexts) { |
924 isolate()->CheckDetachedContextsAfterGC(); | 925 isolate()->CheckDetachedContextsAfterGC(); |
925 } | 926 } |
926 | 927 |
927 if (collector == MARK_COMPACTOR) { | 928 if (collector == MARK_COMPACTOR) { |
928 intptr_t committed_memory_after = CommittedOldGenerationMemory(); | 929 intptr_t committed_memory_after = CommittedOldGenerationMemory(); |
929 intptr_t used_memory_after = PromotedSpaceSizeOfObjects(); | 930 intptr_t used_memory_after = PromotedSpaceSizeOfObjects(); |
(...skipping 10 matching lines...) Expand all Loading... |
940 (detached_contexts()->length() > 0); | 941 (detached_contexts()->length() > 0); |
941 if (deserialization_complete_) { | 942 if (deserialization_complete_) { |
942 memory_reducer_->NotifyMarkCompact(event); | 943 memory_reducer_->NotifyMarkCompact(event); |
943 } | 944 } |
944 } | 945 } |
945 | 946 |
946 tracer()->Stop(collector); | 947 tracer()->Stop(collector); |
947 } | 948 } |
948 | 949 |
949 if (collector == MARK_COMPACTOR && | 950 if (collector == MARK_COMPACTOR && |
950 (current_gc_callback_flags_ & kGCCallbackFlagForced) != 0) { | 951 (gc_callback_flags & kGCCallbackFlagForced) != 0) { |
951 isolate()->CountUsage(v8::Isolate::kForcedGC); | 952 isolate()->CountUsage(v8::Isolate::kForcedGC); |
952 } | 953 } |
953 | 954 |
954 // Start incremental marking for the next cycle. The heap snapshot | 955 // Start incremental marking for the next cycle. The heap snapshot |
955 // generator needs incremental marking to stay off after it aborted. | 956 // generator needs incremental marking to stay off after it aborted. |
956 if (!ShouldAbortIncrementalMarking() && incremental_marking()->IsStopped() && | 957 if (!ShouldAbortIncrementalMarking() && incremental_marking()->IsStopped() && |
957 incremental_marking()->ShouldActivateEvenWithoutIdleNotification()) { | 958 incremental_marking()->ShouldActivateEvenWithoutIdleNotification()) { |
958 StartIncrementalMarking(kNoGCFlags, kNoGCCallbackFlags, "GC epilogue"); | 959 StartIncrementalMarking(kNoGCFlags, kNoGCCallbackFlags, "GC epilogue"); |
959 } | 960 } |
960 | 961 |
(...skipping 14 matching lines...) Expand all Loading... |
975 set_retained_maps(ArrayList::cast(empty_fixed_array())); | 976 set_retained_maps(ArrayList::cast(empty_fixed_array())); |
976 tracer()->AddContextDisposalTime(base::OS::TimeCurrentMillis()); | 977 tracer()->AddContextDisposalTime(base::OS::TimeCurrentMillis()); |
977 MemoryReducer::Event event; | 978 MemoryReducer::Event event; |
978 event.type = MemoryReducer::kContextDisposed; | 979 event.type = MemoryReducer::kContextDisposed; |
979 event.time_ms = MonotonicallyIncreasingTimeInMs(); | 980 event.time_ms = MonotonicallyIncreasingTimeInMs(); |
980 memory_reducer_->NotifyContextDisposed(event); | 981 memory_reducer_->NotifyContextDisposed(event); |
981 return ++contexts_disposed_; | 982 return ++contexts_disposed_; |
982 } | 983 } |
983 | 984 |
984 | 985 |
985 void Heap::StartIncrementalMarking(const GCFlags gc_flags, | 986 void Heap::StartIncrementalMarking(int gc_flags, |
986 const GCCallbackFlags gc_callback_flags, | 987 const GCCallbackFlags gc_callback_flags, |
987 const char* reason) { | 988 const char* reason) { |
988 DCHECK(incremental_marking()->IsStopped()); | 989 DCHECK(incremental_marking()->IsStopped()); |
989 set_current_gc_flags(gc_flags); | 990 set_current_gc_flags(gc_flags); |
990 current_gc_callback_flags_ = gc_callback_flags; | 991 current_gc_callback_flags_ = gc_callback_flags; |
991 incremental_marking()->Start(reason); | 992 incremental_marking()->Start(reason); |
992 } | 993 } |
993 | 994 |
994 | 995 |
995 void Heap::StartIdleIncrementalMarking() { | 996 void Heap::StartIdleIncrementalMarking() { |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1077 chunk.start = free_space_address; | 1078 chunk.start = free_space_address; |
1078 chunk.end = free_space_address + size; | 1079 chunk.end = free_space_address + size; |
1079 } else { | 1080 } else { |
1080 perform_gc = true; | 1081 perform_gc = true; |
1081 break; | 1082 break; |
1082 } | 1083 } |
1083 } | 1084 } |
1084 } | 1085 } |
1085 if (perform_gc) { | 1086 if (perform_gc) { |
1086 if (space == NEW_SPACE) { | 1087 if (space == NEW_SPACE) { |
1087 CollectGarbageNewSpace("failed to reserve space in the new space"); | 1088 CollectGarbage(NEW_SPACE, "failed to reserve space in the new space"); |
1088 } else { | 1089 } else { |
1089 if (counter > 1) { | 1090 if (counter > 1) { |
1090 CollectAllGarbage( | 1091 CollectAllGarbage( |
| 1092 kReduceMemoryFootprintMask | kAbortIncrementalMarkingMask, |
1091 "failed to reserve space in paged or large " | 1093 "failed to reserve space in paged or large " |
1092 "object space, trying to reduce memory footprint", | 1094 "object space, trying to reduce memory footprint"); |
1093 kReduceMemoryFootprintMask | kAbortIncrementalMarkingMask); | |
1094 } else { | 1095 } else { |
1095 CollectAllGarbage( | 1096 CollectAllGarbage( |
1096 "failed to reserve space in paged or large object space", | 1097 kAbortIncrementalMarkingMask, |
1097 kAbortIncrementalMarkingMask); | 1098 "failed to reserve space in paged or large object space"); |
1098 } | 1099 } |
1099 } | 1100 } |
1100 gc_performed = true; | 1101 gc_performed = true; |
1101 break; // Abort for-loop over spaces and retry. | 1102 break; // Abort for-loop over spaces and retry. |
1102 } | 1103 } |
1103 } | 1104 } |
1104 } | 1105 } |
1105 | 1106 |
1106 return !gc_performed; | 1107 return !gc_performed; |
1107 } | 1108 } |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1156 | 1157 |
1157 double survival_rate = promotion_ratio_ + semi_space_copied_rate_; | 1158 double survival_rate = promotion_ratio_ + semi_space_copied_rate_; |
1158 tracer()->AddSurvivalRatio(survival_rate); | 1159 tracer()->AddSurvivalRatio(survival_rate); |
1159 if (survival_rate > kYoungSurvivalRateHighThreshold) { | 1160 if (survival_rate > kYoungSurvivalRateHighThreshold) { |
1160 high_survival_rate_period_length_++; | 1161 high_survival_rate_period_length_++; |
1161 } else { | 1162 } else { |
1162 high_survival_rate_period_length_ = 0; | 1163 high_survival_rate_period_length_ = 0; |
1163 } | 1164 } |
1164 } | 1165 } |
1165 | 1166 |
1166 | 1167 bool Heap::PerformGarbageCollection( |
1167 bool Heap::PerformGarbageCollection(GarbageCollector collector) { | 1168 GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags) { |
1168 int freed_global_handles = 0; | 1169 int freed_global_handles = 0; |
1169 | 1170 |
1170 if (collector != SCAVENGER) { | 1171 if (collector != SCAVENGER) { |
1171 PROFILE(isolate_, CodeMovingGCEvent()); | 1172 PROFILE(isolate_, CodeMovingGCEvent()); |
1172 } | 1173 } |
1173 | 1174 |
1174 #ifdef VERIFY_HEAP | 1175 #ifdef VERIFY_HEAP |
1175 if (FLAG_verify_heap) { | 1176 if (FLAG_verify_heap) { |
1176 VerifyStringTable(this); | 1177 VerifyStringTable(this); |
1177 } | 1178 } |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1234 mark_compact_collector_.EnsureMarkingDequeIsCommitted( | 1235 mark_compact_collector_.EnsureMarkingDequeIsCommitted( |
1235 MarkCompactCollector::kMinMarkingDequeSize); | 1236 MarkCompactCollector::kMinMarkingDequeSize); |
1236 } | 1237 } |
1237 | 1238 |
1238 gc_post_processing_depth_++; | 1239 gc_post_processing_depth_++; |
1239 { | 1240 { |
1240 AllowHeapAllocation allow_allocation; | 1241 AllowHeapAllocation allow_allocation; |
1241 GCTracer::Scope scope(tracer(), GCTracer::Scope::EXTERNAL); | 1242 GCTracer::Scope scope(tracer(), GCTracer::Scope::EXTERNAL); |
1242 freed_global_handles = | 1243 freed_global_handles = |
1243 isolate_->global_handles()->PostGarbageCollectionProcessing( | 1244 isolate_->global_handles()->PostGarbageCollectionProcessing( |
1244 collector, current_gc_callback_flags_); | 1245 collector, gc_callback_flags); |
1245 } | 1246 } |
1246 gc_post_processing_depth_--; | 1247 gc_post_processing_depth_--; |
1247 | 1248 |
1248 isolate_->eternal_handles()->PostGarbageCollectionProcessing(this); | 1249 isolate_->eternal_handles()->PostGarbageCollectionProcessing(this); |
1249 | 1250 |
1250 // Update relocatables. | 1251 // Update relocatables. |
1251 Relocatable::PostGarbageCollectionProcessing(isolate_); | 1252 Relocatable::PostGarbageCollectionProcessing(isolate_); |
1252 | 1253 |
1253 double gc_speed = tracer()->CombinedMarkCompactSpeedInBytesPerMillisecond(); | 1254 double gc_speed = tracer()->CombinedMarkCompactSpeedInBytesPerMillisecond(); |
1254 double mutator_speed = static_cast<double>( | 1255 double mutator_speed = static_cast<double>( |
(...skipping 10 matching lines...) Expand all Loading... |
1265 DampenOldGenerationAllocationLimit(old_gen_size, gc_speed, mutator_speed); | 1266 DampenOldGenerationAllocationLimit(old_gen_size, gc_speed, mutator_speed); |
1266 } | 1267 } |
1267 | 1268 |
1268 { | 1269 { |
1269 GCCallbacksScope scope(this); | 1270 GCCallbacksScope scope(this); |
1270 if (scope.CheckReenter()) { | 1271 if (scope.CheckReenter()) { |
1271 AllowHeapAllocation allow_allocation; | 1272 AllowHeapAllocation allow_allocation; |
1272 GCTracer::Scope scope(tracer(), GCTracer::Scope::EXTERNAL); | 1273 GCTracer::Scope scope(tracer(), GCTracer::Scope::EXTERNAL); |
1273 VMState<EXTERNAL> state(isolate_); | 1274 VMState<EXTERNAL> state(isolate_); |
1274 HandleScope handle_scope(isolate_); | 1275 HandleScope handle_scope(isolate_); |
1275 CallGCEpilogueCallbacks(gc_type, current_gc_callback_flags_); | 1276 CallGCEpilogueCallbacks(gc_type, gc_callback_flags); |
1276 } | 1277 } |
1277 } | 1278 } |
1278 | 1279 |
1279 #ifdef VERIFY_HEAP | 1280 #ifdef VERIFY_HEAP |
1280 if (FLAG_verify_heap) { | 1281 if (FLAG_verify_heap) { |
1281 VerifyStringTable(this); | 1282 VerifyStringTable(this); |
1282 } | 1283 } |
1283 #endif | 1284 #endif |
1284 | 1285 |
1285 return freed_global_handles > 0; | 1286 return freed_global_handles > 0; |
(...skipping 3243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4529 bool Heap::IsHeapIterable() { | 4530 bool Heap::IsHeapIterable() { |
4530 // TODO(hpayer): This function is not correct. Allocation folding in old | 4531 // TODO(hpayer): This function is not correct. Allocation folding in old |
4531 // space breaks the iterability. | 4532 // space breaks the iterability. |
4532 return new_space_top_after_last_gc_ == new_space()->top(); | 4533 return new_space_top_after_last_gc_ == new_space()->top(); |
4533 } | 4534 } |
4534 | 4535 |
4535 | 4536 |
4536 void Heap::MakeHeapIterable() { | 4537 void Heap::MakeHeapIterable() { |
4537 DCHECK(AllowHeapAllocation::IsAllowed()); | 4538 DCHECK(AllowHeapAllocation::IsAllowed()); |
4538 if (!IsHeapIterable()) { | 4539 if (!IsHeapIterable()) { |
4539 CollectAllGarbage("Heap::MakeHeapIterable", kMakeHeapIterableMask); | 4540 CollectAllGarbage(kMakeHeapIterableMask, "Heap::MakeHeapIterable"); |
4540 } | 4541 } |
4541 if (mark_compact_collector()->sweeping_in_progress()) { | 4542 if (mark_compact_collector()->sweeping_in_progress()) { |
4542 mark_compact_collector()->EnsureSweepingCompleted(); | 4543 mark_compact_collector()->EnsureSweepingCompleted(); |
4543 } | 4544 } |
4544 DCHECK(IsHeapIterable()); | 4545 DCHECK(IsHeapIterable()); |
4545 } | 4546 } |
4546 | 4547 |
4547 | 4548 |
4548 static double ComputeMutatorUtilization(double mutator_speed, double gc_speed) { | 4549 static double ComputeMutatorUtilization(double mutator_speed, double gc_speed) { |
4549 const double kMinMutatorUtilization = 0.0; | 4550 const double kMinMutatorUtilization = 0.0; |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4654 gc_idle_time_handler_.ShouldDoOverApproximateWeakClosure( | 4655 gc_idle_time_handler_.ShouldDoOverApproximateWeakClosure( |
4655 static_cast<size_t>(idle_time_in_ms))))) { | 4656 static_cast<size_t>(idle_time_in_ms))))) { |
4656 OverApproximateWeakClosure( | 4657 OverApproximateWeakClosure( |
4657 "Idle notification: overapproximate weak closure"); | 4658 "Idle notification: overapproximate weak closure"); |
4658 return true; | 4659 return true; |
4659 } else if (incremental_marking()->IsComplete() || | 4660 } else if (incremental_marking()->IsComplete() || |
4660 (mark_compact_collector_.marking_deque()->IsEmpty() && | 4661 (mark_compact_collector_.marking_deque()->IsEmpty() && |
4661 gc_idle_time_handler_.ShouldDoFinalIncrementalMarkCompact( | 4662 gc_idle_time_handler_.ShouldDoFinalIncrementalMarkCompact( |
4662 static_cast<size_t>(idle_time_in_ms), size_of_objects, | 4663 static_cast<size_t>(idle_time_in_ms), size_of_objects, |
4663 final_incremental_mark_compact_speed_in_bytes_per_ms))) { | 4664 final_incremental_mark_compact_speed_in_bytes_per_ms))) { |
4664 CollectAllGarbage("idle notification: finalize incremental", | 4665 CollectAllGarbage(current_gc_flags_, |
4665 current_gc_flags_); | 4666 "idle notification: finalize incremental"); |
4666 return true; | 4667 return true; |
4667 } | 4668 } |
4668 return false; | 4669 return false; |
4669 } | 4670 } |
4670 | 4671 |
4671 | 4672 |
4672 GCIdleTimeHandler::HeapState Heap::ComputeHeapState() { | 4673 GCIdleTimeHandler::HeapState Heap::ComputeHeapState() { |
4673 GCIdleTimeHandler::HeapState heap_state; | 4674 GCIdleTimeHandler::HeapState heap_state; |
4674 heap_state.contexts_disposed = contexts_disposed_; | 4675 heap_state.contexts_disposed = contexts_disposed_; |
4675 heap_state.contexts_disposal_rate = | 4676 heap_state.contexts_disposal_rate = |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4738 if (remaining_idle_time_in_ms > 0.0) { | 4739 if (remaining_idle_time_in_ms > 0.0) { |
4739 action.additional_work = TryFinalizeIdleIncrementalMarking( | 4740 action.additional_work = TryFinalizeIdleIncrementalMarking( |
4740 remaining_idle_time_in_ms, heap_state.size_of_objects, | 4741 remaining_idle_time_in_ms, heap_state.size_of_objects, |
4741 heap_state.final_incremental_mark_compact_speed_in_bytes_per_ms); | 4742 heap_state.final_incremental_mark_compact_speed_in_bytes_per_ms); |
4742 } | 4743 } |
4743 break; | 4744 break; |
4744 } | 4745 } |
4745 case DO_FULL_GC: { | 4746 case DO_FULL_GC: { |
4746 DCHECK(contexts_disposed_ > 0); | 4747 DCHECK(contexts_disposed_ > 0); |
4747 HistogramTimerScope scope(isolate_->counters()->gc_context()); | 4748 HistogramTimerScope scope(isolate_->counters()->gc_context()); |
4748 CollectAllGarbage("idle notification: contexts disposed", kNoGCFlags); | 4749 CollectAllGarbage(kNoGCFlags, "idle notification: contexts disposed"); |
4749 break; | 4750 break; |
4750 } | 4751 } |
4751 case DO_SCAVENGE: | 4752 case DO_SCAVENGE: |
4752 CollectGarbageNewSpace("idle notification: scavenge"); | 4753 CollectGarbage(NEW_SPACE, "idle notification: scavenge"); |
4753 break; | 4754 break; |
4754 case DO_FINALIZE_SWEEPING: | 4755 case DO_FINALIZE_SWEEPING: |
4755 mark_compact_collector()->EnsureSweepingCompleted(); | 4756 mark_compact_collector()->EnsureSweepingCompleted(); |
4756 break; | 4757 break; |
4757 case DO_NOTHING: | 4758 case DO_NOTHING: |
4758 break; | 4759 break; |
4759 } | 4760 } |
4760 | 4761 |
4761 return result; | 4762 return result; |
4762 } | 4763 } |
(...skipping 2010 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6773 *object_type = "CODE_TYPE"; \ | 6774 *object_type = "CODE_TYPE"; \ |
6774 *object_sub_type = "CODE_AGE/" #name; \ | 6775 *object_sub_type = "CODE_AGE/" #name; \ |
6775 return true; | 6776 return true; |
6776 CODE_AGE_LIST_COMPLETE(COMPARE_AND_RETURN_NAME) | 6777 CODE_AGE_LIST_COMPLETE(COMPARE_AND_RETURN_NAME) |
6777 #undef COMPARE_AND_RETURN_NAME | 6778 #undef COMPARE_AND_RETURN_NAME |
6778 } | 6779 } |
6779 return false; | 6780 return false; |
6780 } | 6781 } |
6781 } // namespace internal | 6782 } // namespace internal |
6782 } // namespace v8 | 6783 } // namespace v8 |
OLD | NEW |