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) {} |
955 | 956 |
956 virtual ~Space() {} | 957 virtual ~Space() {} |
957 | 958 |
958 Heap* heap() const { return heap_; } | 959 Heap* heap() const { return heap_; } |
959 | 960 |
960 // Does the space need executable memory? | 961 // Does the space need executable memory? |
961 Executability executable() { return executable_; } | 962 Executability executable() { return executable_; } |
962 | 963 |
963 // Identity used in error reporting. | 964 // Identity used in error reporting. |
964 AllocationSpace identity() { return id_; } | 965 AllocationSpace identity() { return id_; } |
965 | 966 |
967 virtual void AddAllocationObserver(AllocationObserver* observer) { | |
968 allocation_observers_->Add(observer); | |
969 } | |
970 | |
971 virtual void RemoveAllocationObserver(AllocationObserver* observer) { | |
972 bool removed = allocation_observers_->RemoveElement(observer); | |
973 static_cast<void>(removed); | |
Hannes Payer (out of office)
2016/02/08 10:13:48
USE(removed);
mattloring
2016/02/09 20:20:05
Done.
| |
974 DCHECK(removed); | |
975 } | |
976 | |
977 virtual void PauseAllocationObservers() { | |
978 allocation_observers_paused_ = true; | |
979 } | |
980 | |
981 virtual void ResumeAllocationObservers() { | |
982 allocation_observers_paused_ = false; | |
983 } | |
984 | |
985 void AllocationStep(Address soon_object, int size); | |
986 | |
966 // Return the total amount committed memory for this space, i.e., allocatable | 987 // Return the total amount committed memory for this space, i.e., allocatable |
967 // memory and page headers. | 988 // memory and page headers. |
968 virtual intptr_t CommittedMemory() { return committed_; } | 989 virtual intptr_t CommittedMemory() { return committed_; } |
969 | 990 |
970 virtual intptr_t MaximumCommittedMemory() { return max_committed_; } | 991 virtual intptr_t MaximumCommittedMemory() { return max_committed_; } |
971 | 992 |
972 // Returns allocated size. | 993 // Returns allocated size. |
973 virtual intptr_t Size() = 0; | 994 virtual intptr_t Size() = 0; |
974 | 995 |
975 // Returns size of objects. Can differ from the allocated size | 996 // Returns size of objects. Can differ from the allocated size |
(...skipping 26 matching lines...) Expand all Loading... | |
1002 max_committed_ = committed_; | 1023 max_committed_ = committed_; |
1003 } | 1024 } |
1004 } | 1025 } |
1005 | 1026 |
1006 void AccountUncommitted(intptr_t bytes) { | 1027 void AccountUncommitted(intptr_t bytes) { |
1007 DCHECK_GE(bytes, 0); | 1028 DCHECK_GE(bytes, 0); |
1008 committed_ -= bytes; | 1029 committed_ -= bytes; |
1009 DCHECK_GE(committed_, 0); | 1030 DCHECK_GE(committed_, 0); |
1010 } | 1031 } |
1011 | 1032 |
1033 // When inline allocation stepping is active, either because of incremental | |
1034 // marking or because of idle scavenge, we 'interrupt' inline allocation every | |
Hannes Payer (out of office)
2016/02/08 10:13:48
This list is not complete: allocation statistics g
mattloring
2016/02/09 20:20:05
Done.
| |
1035 // once in a while. This is done by setting allocation_info_.limit to be lower | |
1036 // than the actual limit and and increasing it in steps to guarantee that the | |
1037 // observers are notified periodically. | |
1038 List<AllocationObserver*>* allocation_observers_ = | |
Hannes Payer (out of office)
2016/02/08 10:13:48
allocate the allocation_observers in the construct
mattloring
2016/02/09 20:20:05
What is the best strategy for deallocating a list
ofrobots
2016/02/10 08:15:38
Does allocation_observers_ need to be dynamically
mattloring
2016/02/10 13:19:23
If I do not dynamically allocate it, it causes the
Hannes Payer (out of office)
2016/02/11 11:50:08
I am not sure if I understand your question.
When
mattloring
2016/02/11 14:54:14
Sorry for the confusion. This should be handled no
| |
1039 new List<AllocationObserver*>(); | |
1040 bool allocation_observers_paused_; | |
1041 | |
1012 private: | 1042 private: |
1013 Heap* heap_; | 1043 Heap* heap_; |
1014 AllocationSpace id_; | 1044 AllocationSpace id_; |
1015 Executability executable_; | 1045 Executability executable_; |
1016 | 1046 |
1017 // Keeps track of committed memory in a space. | 1047 // Keeps track of committed memory in a space. |
1018 intptr_t committed_; | 1048 intptr_t committed_; |
1019 intptr_t max_committed_; | 1049 intptr_t max_committed_; |
1020 }; | 1050 }; |
1021 | 1051 |
(...skipping 1528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2550 // forwards most functions to the appropriate semispace. | 2580 // forwards most functions to the appropriate semispace. |
2551 | 2581 |
2552 class NewSpace : public Space { | 2582 class NewSpace : public Space { |
2553 public: | 2583 public: |
2554 // Constructor. | 2584 // Constructor. |
2555 explicit NewSpace(Heap* heap) | 2585 explicit NewSpace(Heap* heap) |
2556 : Space(heap, NEW_SPACE, NOT_EXECUTABLE), | 2586 : Space(heap, NEW_SPACE, NOT_EXECUTABLE), |
2557 to_space_(heap, kToSpace), | 2587 to_space_(heap, kToSpace), |
2558 from_space_(heap, kFromSpace), | 2588 from_space_(heap, kFromSpace), |
2559 reservation_(), | 2589 reservation_(), |
2560 top_on_previous_step_(0), | 2590 top_on_previous_step_(0) {} |
2561 inline_allocation_observers_paused_(false) {} | |
2562 | 2591 |
2563 // Sets up the new space using the given chunk. | 2592 // Sets up the new space using the given chunk. |
2564 bool SetUp(int reserved_semispace_size_, int max_semi_space_size); | 2593 bool SetUp(int reserved_semispace_size_, int max_semi_space_size); |
2565 | 2594 |
2566 // Tears down the space. Heap memory was not allocated by the space, so it | 2595 // Tears down the space. Heap memory was not allocated by the space, so it |
2567 // is not deallocated here. | 2596 // is not deallocated here. |
2568 void TearDown(); | 2597 void TearDown(); |
2569 | 2598 |
2570 // True if the space has been set up but not torn down. | 2599 // True if the space has been set up but not torn down. |
2571 bool HasBeenSetUp() { | 2600 bool HasBeenSetUp() { |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2723 int size_in_bytes, AllocationAlignment alignment)); | 2752 int size_in_bytes, AllocationAlignment alignment)); |
2724 | 2753 |
2725 MUST_USE_RESULT inline AllocationResult AllocateRawSynchronized( | 2754 MUST_USE_RESULT inline AllocationResult AllocateRawSynchronized( |
2726 int size_in_bytes, AllocationAlignment alignment); | 2755 int size_in_bytes, AllocationAlignment alignment); |
2727 | 2756 |
2728 // Reset the allocation pointer to the beginning of the active semispace. | 2757 // Reset the allocation pointer to the beginning of the active semispace. |
2729 void ResetAllocationInfo(); | 2758 void ResetAllocationInfo(); |
2730 | 2759 |
2731 void UpdateInlineAllocationLimit(int size_in_bytes); | 2760 void UpdateInlineAllocationLimit(int size_in_bytes); |
2732 | 2761 |
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() { | 2762 void DisableInlineAllocationSteps() { |
2743 top_on_previous_step_ = 0; | 2763 top_on_previous_step_ = 0; |
2744 UpdateInlineAllocationLimit(0); | 2764 UpdateInlineAllocationLimit(0); |
2745 } | 2765 } |
2746 | 2766 |
2767 // Allows observation of inline allocation. The observer->Step() method gets | |
2768 // called after every step_size bytes have been allocated (approximately). | |
2769 // This works by adjusting the allocation limit to a lower value and adjusting | |
2770 // it after each step. | |
2771 void AddAllocationObserver(AllocationObserver* observer) override; | |
2772 | |
2773 void RemoveAllocationObserver(AllocationObserver* observer) override; | |
2774 | |
2747 // Get the extent of the inactive semispace (for use as a marking stack, | 2775 // 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 | 2776 // or to zap it). Notice: space-addresses are not necessarily on the |
2749 // same page, so FromSpaceStart() might be above FromSpaceEnd(). | 2777 // same page, so FromSpaceStart() might be above FromSpaceEnd(). |
2750 Address FromSpacePageLow() { return from_space_.page_low(); } | 2778 Address FromSpacePageLow() { return from_space_.page_low(); } |
2751 Address FromSpacePageHigh() { return from_space_.page_high(); } | 2779 Address FromSpacePageHigh() { return from_space_.page_high(); } |
2752 Address FromSpaceStart() { return from_space_.space_start(); } | 2780 Address FromSpaceStart() { return from_space_.space_start(); } |
2753 Address FromSpaceEnd() { return from_space_.space_end(); } | 2781 Address FromSpaceEnd() { return from_space_.space_end(); } |
2754 | 2782 |
2755 // Get the extent of the active semispace's pages' memory. | 2783 // Get the extent of the active semispace's pages' memory. |
2756 Address ToSpaceStart() { return to_space_.space_start(); } | 2784 Address ToSpaceStart() { return to_space_.space_start(); } |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2807 | 2835 |
2808 bool UncommitFromSpace() { | 2836 bool UncommitFromSpace() { |
2809 if (!from_space_.is_committed()) return true; | 2837 if (!from_space_.is_committed()) return true; |
2810 return from_space_.Uncommit(); | 2838 return from_space_.Uncommit(); |
2811 } | 2839 } |
2812 | 2840 |
2813 bool IsFromSpaceCommitted() { return from_space_.is_committed(); } | 2841 bool IsFromSpaceCommitted() { return from_space_.is_committed(); } |
2814 | 2842 |
2815 SemiSpace* active_space() { return &to_space_; } | 2843 SemiSpace* active_space() { return &to_space_; } |
2816 | 2844 |
2845 void PauseAllocationObservers() override; | |
2846 void ResumeAllocationObservers() override; | |
2847 | |
2817 private: | 2848 private: |
2818 // Update allocation info to match the current to-space page. | 2849 // Update allocation info to match the current to-space page. |
2819 void UpdateAllocationInfo(); | 2850 void UpdateAllocationInfo(); |
2820 | 2851 |
2821 base::Mutex mutex_; | 2852 base::Mutex mutex_; |
2822 | 2853 |
2823 Address chunk_base_; | 2854 Address chunk_base_; |
2824 uintptr_t chunk_size_; | 2855 uintptr_t chunk_size_; |
2825 | 2856 |
2826 // The semispaces. | 2857 // The semispaces. |
2827 SemiSpace to_space_; | 2858 SemiSpace to_space_; |
2828 SemiSpace from_space_; | 2859 SemiSpace from_space_; |
2829 base::VirtualMemory reservation_; | 2860 base::VirtualMemory reservation_; |
2830 int pages_used_; | 2861 int pages_used_; |
2831 | 2862 |
2832 // Start address and bit mask for containment testing. | 2863 // Start address and bit mask for containment testing. |
2833 Address start_; | 2864 Address start_; |
2834 uintptr_t address_mask_; | 2865 uintptr_t address_mask_; |
2835 uintptr_t object_mask_; | 2866 uintptr_t object_mask_; |
2836 uintptr_t object_expected_; | 2867 uintptr_t object_expected_; |
2837 | 2868 |
2838 // Allocation pointer and limit for normal allocation and allocation during | 2869 // Allocation pointer and limit for normal allocation and allocation during |
2839 // mark-compact collection. | 2870 // mark-compact collection. |
2840 AllocationInfo allocation_info_; | 2871 AllocationInfo allocation_info_; |
2841 | 2872 |
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_; | 2873 Address top_on_previous_step_; |
2849 bool inline_allocation_observers_paused_; | |
2850 | 2874 |
2851 HistogramInfo* allocated_histogram_; | 2875 HistogramInfo* allocated_histogram_; |
2852 HistogramInfo* promoted_histogram_; | 2876 HistogramInfo* promoted_histogram_; |
2853 | 2877 |
2854 bool EnsureAllocation(int size_in_bytes, AllocationAlignment alignment); | 2878 bool EnsureAllocation(int size_in_bytes, AllocationAlignment alignment); |
2855 | 2879 |
2856 // If we are doing inline allocation in steps, this method performs the 'step' | 2880 // 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 | 2881 // 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 | 2882 // 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 | 2883 // 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 | 2884 // 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. | 2885 // different when we cross a page boundary or reset the space. |
2862 void InlineAllocationStep(Address top, Address new_top, Address soon_object, | 2886 void InlineAllocationStep(Address top, Address new_top, Address soon_object, |
2863 size_t size); | 2887 size_t size); |
2864 intptr_t GetNextInlineAllocationStepSize(); | 2888 intptr_t GetNextInlineAllocationStepSize(); |
2865 void StartNextInlineAllocationStep(); | 2889 void StartNextInlineAllocationStep(); |
2866 void PauseInlineAllocationObservers(); | |
2867 void ResumeInlineAllocationObservers(); | |
2868 | 2890 |
2869 friend class PauseInlineAllocationObserversScope; | |
2870 friend class SemiSpaceIterator; | 2891 friend class SemiSpaceIterator; |
2871 }; | 2892 }; |
2872 | 2893 |
2873 class PauseInlineAllocationObserversScope { | 2894 class PauseAllocationObserversScope { |
2874 public: | 2895 public: |
2875 explicit PauseInlineAllocationObserversScope(NewSpace* new_space) | 2896 explicit PauseAllocationObserversScope(Heap* heap); |
2876 : new_space_(new_space) { | 2897 ~PauseAllocationObserversScope(); |
2877 new_space_->PauseInlineAllocationObservers(); | |
2878 } | |
2879 ~PauseInlineAllocationObserversScope() { | |
2880 new_space_->ResumeInlineAllocationObservers(); | |
2881 } | |
2882 | 2898 |
2883 private: | 2899 private: |
2884 NewSpace* new_space_; | 2900 Heap* heap_; |
2885 DISALLOW_COPY_AND_ASSIGN(PauseInlineAllocationObserversScope); | 2901 DISALLOW_COPY_AND_ASSIGN(PauseAllocationObserversScope); |
2886 }; | 2902 }; |
2887 | 2903 |
2888 // ----------------------------------------------------------------------------- | 2904 // ----------------------------------------------------------------------------- |
2889 // Compaction space that is used temporarily during compaction. | 2905 // Compaction space that is used temporarily during compaction. |
2890 | 2906 |
2891 class CompactionSpace : public PagedSpace { | 2907 class CompactionSpace : public PagedSpace { |
2892 public: | 2908 public: |
2893 CompactionSpace(Heap* heap, AllocationSpace id, Executability executable) | 2909 CompactionSpace(Heap* heap, AllocationSpace id, Executability executable) |
2894 : PagedSpace(heap, id, executable) {} | 2910 : PagedSpace(heap, id, executable) {} |
2895 | 2911 |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3128 count = 0; | 3144 count = 0; |
3129 } | 3145 } |
3130 // Must be small, since an iteration is used for lookup. | 3146 // Must be small, since an iteration is used for lookup. |
3131 static const int kMaxComments = 64; | 3147 static const int kMaxComments = 64; |
3132 }; | 3148 }; |
3133 #endif | 3149 #endif |
3134 } // namespace internal | 3150 } // namespace internal |
3135 } // namespace v8 | 3151 } // namespace v8 |
3136 | 3152 |
3137 #endif // V8_HEAP_SPACES_H_ | 3153 #endif // V8_HEAP_SPACES_H_ |
OLD | NEW |