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