Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 #ifndef V8_HEAP_SPACES_H_ | 5 #ifndef V8_HEAP_SPACES_H_ |
| 6 #define V8_HEAP_SPACES_H_ | 6 #define V8_HEAP_SPACES_H_ |
| 7 | 7 |
| 8 #include "src/allocation.h" | 8 #include "src/allocation.h" |
| 9 #include "src/atomic-utils.h" | 9 #include "src/atomic-utils.h" |
| 10 #include "src/base/atomicops.h" | 10 #include "src/base/atomicops.h" |
| 11 #include "src/base/bits.h" | 11 #include "src/base/bits.h" |
| 12 #include "src/base/platform/mutex.h" | 12 #include "src/base/platform/mutex.h" |
| 13 #include "src/flags.h" | 13 #include "src/flags.h" |
| 14 #include "src/hashmap.h" | 14 #include "src/hashmap.h" |
| 15 #include "src/list.h" | 15 #include "src/list.h" |
| 16 #include "src/objects.h" | 16 #include "src/objects.h" |
| 17 #include "src/utils.h" | 17 #include "src/utils.h" |
| 18 | 18 |
| 19 namespace v8 { | 19 namespace v8 { |
| 20 namespace internal { | 20 namespace internal { |
| 21 | 21 |
| 22 class AllocationInfo; | 22 class AllocationInfo; |
| 23 class AllocationObserver; | |
| 23 class CompactionSpace; | 24 class CompactionSpace; |
| 24 class CompactionSpaceCollection; | 25 class CompactionSpaceCollection; |
| 25 class FreeList; | 26 class FreeList; |
| 26 class InlineAllocationObserver; | |
| 27 class Isolate; | 27 class Isolate; |
| 28 class MemoryAllocator; | 28 class MemoryAllocator; |
| 29 class MemoryChunk; | 29 class MemoryChunk; |
| 30 class PagedSpace; | 30 class PagedSpace; |
| 31 class SemiSpace; | 31 class SemiSpace; |
| 32 class SkipList; | 32 class SkipList; |
| 33 class SlotsBuffer; | 33 class SlotsBuffer; |
| 34 class Space; | 34 class Space; |
| 35 | 35 |
| 36 // ----------------------------------------------------------------------------- | 36 // ----------------------------------------------------------------------------- |
| (...skipping 903 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 940 | 940 |
| 941 friend class MemoryAllocator; | 941 friend class MemoryAllocator; |
| 942 }; | 942 }; |
| 943 | 943 |
| 944 | 944 |
| 945 // ---------------------------------------------------------------------------- | 945 // ---------------------------------------------------------------------------- |
| 946 // Space is the abstract superclass for all allocation spaces. | 946 // Space is the abstract superclass for all allocation spaces. |
| 947 class Space : public Malloced { | 947 class Space : public Malloced { |
| 948 public: | 948 public: |
| 949 Space(Heap* heap, AllocationSpace id, Executability executable) | 949 Space(Heap* heap, AllocationSpace id, Executability executable) |
| 950 : heap_(heap), | 950 : allocation_observers_paused_(false), |
| 951 heap_(heap), | |
| 951 id_(id), | 952 id_(id), |
| 952 executable_(executable), | 953 executable_(executable), |
| 953 committed_(0), | 954 committed_(0), |
| 954 max_committed_(0) {} | 955 max_committed_(0) { |
| 956 allocation_observers_ = new List<AllocationObserver*>(); | |
|
ofrobots
2016/02/11 05:51:46
Never freed? Use SmartPointer to manage this.
mattloring
2016/02/11 14:54:14
Done.
| |
| 957 } | |
| 955 | 958 |
| 956 virtual ~Space() {} | 959 virtual ~Space() {} |
| 957 | 960 |
| 958 Heap* heap() const { return heap_; } | 961 Heap* heap() const { return heap_; } |
| 959 | 962 |
| 960 // Does the space need executable memory? | 963 // Does the space need executable memory? |
| 961 Executability executable() { return executable_; } | 964 Executability executable() { return executable_; } |
| 962 | 965 |
| 963 // Identity used in error reporting. | 966 // Identity used in error reporting. |
| 964 AllocationSpace identity() { return id_; } | 967 AllocationSpace identity() { return id_; } |
| 965 | 968 |
| 969 virtual void AddAllocationObserver(AllocationObserver* observer) { | |
| 970 allocation_observers_->Add(observer); | |
| 971 } | |
| 972 | |
| 973 virtual void RemoveAllocationObserver(AllocationObserver* observer) { | |
| 974 bool removed = allocation_observers_->RemoveElement(observer); | |
| 975 USE(removed); | |
| 976 DCHECK(removed); | |
| 977 } | |
| 978 | |
| 979 virtual void PauseAllocationObservers() { | |
| 980 allocation_observers_paused_ = true; | |
| 981 } | |
| 982 | |
| 983 virtual void ResumeAllocationObservers() { | |
| 984 allocation_observers_paused_ = false; | |
| 985 } | |
| 986 | |
| 987 void AllocationStep(Address soon_object, int size); | |
| 988 | |
| 966 // Return the total amount committed memory for this space, i.e., allocatable | 989 // Return the total amount committed memory for this space, i.e., allocatable |
| 967 // memory and page headers. | 990 // memory and page headers. |
| 968 virtual intptr_t CommittedMemory() { return committed_; } | 991 virtual intptr_t CommittedMemory() { return committed_; } |
| 969 | 992 |
| 970 virtual intptr_t MaximumCommittedMemory() { return max_committed_; } | 993 virtual intptr_t MaximumCommittedMemory() { return max_committed_; } |
| 971 | 994 |
| 972 // Returns allocated size. | 995 // Returns allocated size. |
| 973 virtual intptr_t Size() = 0; | 996 virtual intptr_t Size() = 0; |
| 974 | 997 |
| 975 // Returns size of objects. Can differ from the allocated size | 998 // Returns size of objects. Can differ from the allocated size |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 1002 max_committed_ = committed_; | 1025 max_committed_ = committed_; |
| 1003 } | 1026 } |
| 1004 } | 1027 } |
| 1005 | 1028 |
| 1006 void AccountUncommitted(intptr_t bytes) { | 1029 void AccountUncommitted(intptr_t bytes) { |
| 1007 DCHECK_GE(bytes, 0); | 1030 DCHECK_GE(bytes, 0); |
| 1008 committed_ -= bytes; | 1031 committed_ -= bytes; |
| 1009 DCHECK_GE(committed_, 0); | 1032 DCHECK_GE(committed_, 0); |
| 1010 } | 1033 } |
| 1011 | 1034 |
| 1035 // When inline allocation stepping is active, either because of incremental | |
| 1036 // marking, idle scavenge, or allocation statistics gathering, we 'interrupt' | |
| 1037 // inline allocation every once in a while. This is done by setting | |
| 1038 // allocation_info_.limit to be lower than the actual limit and and increasing | |
| 1039 // it in steps to guarantee that the observers are notified periodically. | |
| 1040 List<AllocationObserver*>* allocation_observers_; | |
|
ofrobots
2016/02/11 05:51:46
The comment about inline allocation stepping seems
mattloring
2016/02/11 14:54:14
I'm guessing you meant that it doesn't. I've moved
| |
| 1041 bool allocation_observers_paused_; | |
| 1042 | |
| 1012 private: | 1043 private: |
| 1013 Heap* heap_; | 1044 Heap* heap_; |
| 1014 AllocationSpace id_; | 1045 AllocationSpace id_; |
| 1015 Executability executable_; | 1046 Executability executable_; |
| 1016 | 1047 |
| 1017 // Keeps track of committed memory in a space. | 1048 // Keeps track of committed memory in a space. |
| 1018 intptr_t committed_; | 1049 intptr_t committed_; |
| 1019 intptr_t max_committed_; | 1050 intptr_t max_committed_; |
| 1020 }; | 1051 }; |
| 1021 | 1052 |
| (...skipping 1528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2550 // forwards most functions to the appropriate semispace. | 2581 // forwards most functions to the appropriate semispace. |
| 2551 | 2582 |
| 2552 class NewSpace : public Space { | 2583 class NewSpace : public Space { |
| 2553 public: | 2584 public: |
| 2554 // Constructor. | 2585 // Constructor. |
| 2555 explicit NewSpace(Heap* heap) | 2586 explicit NewSpace(Heap* heap) |
| 2556 : Space(heap, NEW_SPACE, NOT_EXECUTABLE), | 2587 : Space(heap, NEW_SPACE, NOT_EXECUTABLE), |
| 2557 to_space_(heap, kToSpace), | 2588 to_space_(heap, kToSpace), |
| 2558 from_space_(heap, kFromSpace), | 2589 from_space_(heap, kFromSpace), |
| 2559 reservation_(), | 2590 reservation_(), |
| 2560 top_on_previous_step_(0), | 2591 top_on_previous_step_(0) {} |
| 2561 inline_allocation_observers_paused_(false) {} | |
| 2562 | 2592 |
| 2563 // Sets up the new space using the given chunk. | 2593 // Sets up the new space using the given chunk. |
| 2564 bool SetUp(int reserved_semispace_size_, int max_semi_space_size); | 2594 bool SetUp(int reserved_semispace_size_, int max_semi_space_size); |
| 2565 | 2595 |
| 2566 // Tears down the space. Heap memory was not allocated by the space, so it | 2596 // Tears down the space. Heap memory was not allocated by the space, so it |
| 2567 // is not deallocated here. | 2597 // is not deallocated here. |
| 2568 void TearDown(); | 2598 void TearDown(); |
| 2569 | 2599 |
| 2570 // True if the space has been set up but not torn down. | 2600 // True if the space has been set up but not torn down. |
| 2571 bool HasBeenSetUp() { | 2601 bool HasBeenSetUp() { |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2723 int size_in_bytes, AllocationAlignment alignment)); | 2753 int size_in_bytes, AllocationAlignment alignment)); |
| 2724 | 2754 |
| 2725 MUST_USE_RESULT inline AllocationResult AllocateRawSynchronized( | 2755 MUST_USE_RESULT inline AllocationResult AllocateRawSynchronized( |
| 2726 int size_in_bytes, AllocationAlignment alignment); | 2756 int size_in_bytes, AllocationAlignment alignment); |
| 2727 | 2757 |
| 2728 // Reset the allocation pointer to the beginning of the active semispace. | 2758 // Reset the allocation pointer to the beginning of the active semispace. |
| 2729 void ResetAllocationInfo(); | 2759 void ResetAllocationInfo(); |
| 2730 | 2760 |
| 2731 void UpdateInlineAllocationLimit(int size_in_bytes); | 2761 void UpdateInlineAllocationLimit(int size_in_bytes); |
| 2732 | 2762 |
| 2733 // Allows observation of inline allocation. The observer->Step() method gets | |
| 2734 // called after every step_size bytes have been allocated (approximately). | |
| 2735 // This works by adjusting the allocation limit to a lower value and adjusting | |
| 2736 // it after each step. | |
| 2737 void AddInlineAllocationObserver(InlineAllocationObserver* observer); | |
| 2738 | |
| 2739 // Removes a previously installed observer. | |
| 2740 void RemoveInlineAllocationObserver(InlineAllocationObserver* observer); | |
| 2741 | |
| 2742 void DisableInlineAllocationSteps() { | 2763 void DisableInlineAllocationSteps() { |
| 2743 top_on_previous_step_ = 0; | 2764 top_on_previous_step_ = 0; |
| 2744 UpdateInlineAllocationLimit(0); | 2765 UpdateInlineAllocationLimit(0); |
| 2745 } | 2766 } |
| 2746 | 2767 |
| 2768 // Allows observation of inline allocation. The observer->Step() method gets | |
| 2769 // called after every step_size bytes have been allocated (approximately). | |
| 2770 // This works by adjusting the allocation limit to a lower value and adjusting | |
| 2771 // it after each step. | |
| 2772 void AddAllocationObserver(AllocationObserver* observer) override; | |
| 2773 | |
| 2774 void RemoveAllocationObserver(AllocationObserver* observer) override; | |
| 2775 | |
| 2747 // Get the extent of the inactive semispace (for use as a marking stack, | 2776 // Get the extent of the inactive semispace (for use as a marking stack, |
| 2748 // or to zap it). Notice: space-addresses are not necessarily on the | 2777 // or to zap it). Notice: space-addresses are not necessarily on the |
| 2749 // same page, so FromSpaceStart() might be above FromSpaceEnd(). | 2778 // same page, so FromSpaceStart() might be above FromSpaceEnd(). |
| 2750 Address FromSpacePageLow() { return from_space_.page_low(); } | 2779 Address FromSpacePageLow() { return from_space_.page_low(); } |
| 2751 Address FromSpacePageHigh() { return from_space_.page_high(); } | 2780 Address FromSpacePageHigh() { return from_space_.page_high(); } |
| 2752 Address FromSpaceStart() { return from_space_.space_start(); } | 2781 Address FromSpaceStart() { return from_space_.space_start(); } |
| 2753 Address FromSpaceEnd() { return from_space_.space_end(); } | 2782 Address FromSpaceEnd() { return from_space_.space_end(); } |
| 2754 | 2783 |
| 2755 // Get the extent of the active semispace's pages' memory. | 2784 // Get the extent of the active semispace's pages' memory. |
| 2756 Address ToSpaceStart() { return to_space_.space_start(); } | 2785 Address ToSpaceStart() { return to_space_.space_start(); } |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2807 | 2836 |
| 2808 bool UncommitFromSpace() { | 2837 bool UncommitFromSpace() { |
| 2809 if (!from_space_.is_committed()) return true; | 2838 if (!from_space_.is_committed()) return true; |
| 2810 return from_space_.Uncommit(); | 2839 return from_space_.Uncommit(); |
| 2811 } | 2840 } |
| 2812 | 2841 |
| 2813 bool IsFromSpaceCommitted() { return from_space_.is_committed(); } | 2842 bool IsFromSpaceCommitted() { return from_space_.is_committed(); } |
| 2814 | 2843 |
| 2815 SemiSpace* active_space() { return &to_space_; } | 2844 SemiSpace* active_space() { return &to_space_; } |
| 2816 | 2845 |
| 2846 void PauseAllocationObservers() override; | |
| 2847 void ResumeAllocationObservers() override; | |
| 2848 | |
| 2817 private: | 2849 private: |
| 2818 // Update allocation info to match the current to-space page. | 2850 // Update allocation info to match the current to-space page. |
| 2819 void UpdateAllocationInfo(); | 2851 void UpdateAllocationInfo(); |
| 2820 | 2852 |
| 2821 base::Mutex mutex_; | 2853 base::Mutex mutex_; |
| 2822 | 2854 |
| 2823 Address chunk_base_; | 2855 Address chunk_base_; |
| 2824 uintptr_t chunk_size_; | 2856 uintptr_t chunk_size_; |
| 2825 | 2857 |
| 2826 // The semispaces. | 2858 // The semispaces. |
| 2827 SemiSpace to_space_; | 2859 SemiSpace to_space_; |
| 2828 SemiSpace from_space_; | 2860 SemiSpace from_space_; |
| 2829 base::VirtualMemory reservation_; | 2861 base::VirtualMemory reservation_; |
| 2830 int pages_used_; | 2862 int pages_used_; |
| 2831 | 2863 |
| 2832 // Start address and bit mask for containment testing. | 2864 // Start address and bit mask for containment testing. |
| 2833 Address start_; | 2865 Address start_; |
| 2834 uintptr_t address_mask_; | 2866 uintptr_t address_mask_; |
| 2835 uintptr_t object_mask_; | 2867 uintptr_t object_mask_; |
| 2836 uintptr_t object_expected_; | 2868 uintptr_t object_expected_; |
| 2837 | 2869 |
| 2838 // Allocation pointer and limit for normal allocation and allocation during | 2870 // Allocation pointer and limit for normal allocation and allocation during |
| 2839 // mark-compact collection. | 2871 // mark-compact collection. |
| 2840 AllocationInfo allocation_info_; | 2872 AllocationInfo allocation_info_; |
| 2841 | 2873 |
| 2842 // When inline allocation stepping is active, either because of incremental | |
| 2843 // marking or because of idle scavenge, we 'interrupt' inline allocation every | |
| 2844 // once in a while. This is done by setting allocation_info_.limit to be lower | |
| 2845 // than the actual limit and and increasing it in steps to guarantee that the | |
| 2846 // observers are notified periodically. | |
| 2847 List<InlineAllocationObserver*> inline_allocation_observers_; | |
| 2848 Address top_on_previous_step_; | 2874 Address top_on_previous_step_; |
| 2849 bool inline_allocation_observers_paused_; | |
| 2850 | 2875 |
| 2851 HistogramInfo* allocated_histogram_; | 2876 HistogramInfo* allocated_histogram_; |
| 2852 HistogramInfo* promoted_histogram_; | 2877 HistogramInfo* promoted_histogram_; |
| 2853 | 2878 |
| 2854 bool EnsureAllocation(int size_in_bytes, AllocationAlignment alignment); | 2879 bool EnsureAllocation(int size_in_bytes, AllocationAlignment alignment); |
| 2855 | 2880 |
| 2856 // If we are doing inline allocation in steps, this method performs the 'step' | 2881 // If we are doing inline allocation in steps, this method performs the 'step' |
| 2857 // operation. top is the memory address of the bump pointer at the last | 2882 // operation. top is the memory address of the bump pointer at the last |
| 2858 // inline allocation (i.e. it determines the numbers of bytes actually | 2883 // inline allocation (i.e. it determines the numbers of bytes actually |
| 2859 // allocated since the last step.) new_top is the address of the bump pointer | 2884 // allocated since the last step.) new_top is the address of the bump pointer |
| 2860 // where the next byte is going to be allocated from. top and new_top may be | 2885 // where the next byte is going to be allocated from. top and new_top may be |
| 2861 // different when we cross a page boundary or reset the space. | 2886 // different when we cross a page boundary or reset the space. |
| 2862 void InlineAllocationStep(Address top, Address new_top, Address soon_object, | 2887 void InlineAllocationStep(Address top, Address new_top, Address soon_object, |
| 2863 size_t size); | 2888 size_t size); |
| 2864 intptr_t GetNextInlineAllocationStepSize(); | 2889 intptr_t GetNextInlineAllocationStepSize(); |
| 2865 void StartNextInlineAllocationStep(); | 2890 void StartNextInlineAllocationStep(); |
| 2866 void PauseInlineAllocationObservers(); | |
| 2867 void ResumeInlineAllocationObservers(); | |
| 2868 | 2891 |
| 2869 friend class PauseInlineAllocationObserversScope; | |
| 2870 friend class SemiSpaceIterator; | 2892 friend class SemiSpaceIterator; |
| 2871 }; | 2893 }; |
| 2872 | 2894 |
| 2873 class PauseInlineAllocationObserversScope { | 2895 class PauseAllocationObserversScope { |
| 2874 public: | 2896 public: |
| 2875 explicit PauseInlineAllocationObserversScope(NewSpace* new_space) | 2897 explicit PauseAllocationObserversScope(Heap* heap); |
| 2876 : new_space_(new_space) { | 2898 ~PauseAllocationObserversScope(); |
| 2877 new_space_->PauseInlineAllocationObservers(); | |
| 2878 } | |
| 2879 ~PauseInlineAllocationObserversScope() { | |
| 2880 new_space_->ResumeInlineAllocationObservers(); | |
| 2881 } | |
| 2882 | 2899 |
| 2883 private: | 2900 private: |
| 2884 NewSpace* new_space_; | 2901 Heap* heap_; |
| 2885 DISALLOW_COPY_AND_ASSIGN(PauseInlineAllocationObserversScope); | 2902 DISALLOW_COPY_AND_ASSIGN(PauseAllocationObserversScope); |
| 2886 }; | 2903 }; |
| 2887 | 2904 |
| 2888 // ----------------------------------------------------------------------------- | 2905 // ----------------------------------------------------------------------------- |
| 2889 // Compaction space that is used temporarily during compaction. | 2906 // Compaction space that is used temporarily during compaction. |
| 2890 | 2907 |
| 2891 class CompactionSpace : public PagedSpace { | 2908 class CompactionSpace : public PagedSpace { |
| 2892 public: | 2909 public: |
| 2893 CompactionSpace(Heap* heap, AllocationSpace id, Executability executable) | 2910 CompactionSpace(Heap* heap, AllocationSpace id, Executability executable) |
| 2894 : PagedSpace(heap, id, executable) {} | 2911 : PagedSpace(heap, id, executable) {} |
| 2895 | 2912 |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3128 count = 0; | 3145 count = 0; |
| 3129 } | 3146 } |
| 3130 // Must be small, since an iteration is used for lookup. | 3147 // Must be small, since an iteration is used for lookup. |
| 3131 static const int kMaxComments = 64; | 3148 static const int kMaxComments = 64; |
| 3132 }; | 3149 }; |
| 3133 #endif | 3150 #endif |
| 3134 } // namespace internal | 3151 } // namespace internal |
| 3135 } // namespace v8 | 3152 } // namespace v8 |
| 3136 | 3153 |
| 3137 #endif // V8_HEAP_SPACES_H_ | 3154 #endif // V8_HEAP_SPACES_H_ |
| OLD | NEW |