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 AllocationObserver; | |
| 22 class CompactionSpaceCollection; | 23 class CompactionSpaceCollection; |
| 23 class InlineAllocationObserver; | |
| 24 class Isolate; | 24 class Isolate; |
| 25 | 25 |
| 26 // ----------------------------------------------------------------------------- | 26 // ----------------------------------------------------------------------------- |
| 27 // Heap structures: | 27 // Heap structures: |
| 28 // | 28 // |
| 29 // A JS heap consists of a young generation, an old generation, and a large | 29 // A JS heap consists of a young generation, an old generation, and a large |
| 30 // object space. The young generation is divided into two semispaces. A | 30 // object space. The young generation is divided into two semispaces. A |
| 31 // scavenger implements Cheney's copying algorithm. The old generation is | 31 // scavenger implements Cheney's copying algorithm. The old generation is |
| 32 // separated into a map space and an old object space. The map space contains | 32 // separated into a map space and an old object space. The map space contains |
| 33 // all (and only) map objects, the rest of old objects go into the old space. | 33 // all (and only) map objects, the rest of old objects go into the old space. |
| (...skipping 916 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 950 | 950 |
| 951 friend class MemoryAllocator; | 951 friend class MemoryAllocator; |
| 952 }; | 952 }; |
| 953 | 953 |
| 954 | 954 |
| 955 // ---------------------------------------------------------------------------- | 955 // ---------------------------------------------------------------------------- |
| 956 // Space is the abstract superclass for all allocation spaces. | 956 // Space is the abstract superclass for all allocation spaces. |
| 957 class Space : public Malloced { | 957 class Space : public Malloced { |
| 958 public: | 958 public: |
| 959 Space(Heap* heap, AllocationSpace id, Executability executable) | 959 Space(Heap* heap, AllocationSpace id, Executability executable) |
| 960 : heap_(heap), | 960 : allocation_observers_paused_(false), |
|
ofrobots
2016/01/26 00:38:25
As per suggestion above, it might make sense for H
mattloring
2016/01/30 00:38:03
This is currently enforced by the PauseAllocationO
| |
| 961 heap_(heap), | |
| 961 id_(id), | 962 id_(id), |
| 962 executable_(executable), | 963 executable_(executable), |
| 963 committed_(0), | 964 committed_(0), |
| 964 max_committed_(0) {} | 965 max_committed_(0) {} |
| 965 | 966 |
| 966 virtual ~Space() {} | 967 virtual ~Space() {} |
| 967 | 968 |
| 968 Heap* heap() const { return heap_; } | 969 Heap* heap() const { return heap_; } |
| 969 | 970 |
| 970 // Does the space need executable memory? | 971 // Does the space need executable memory? |
| 971 Executability executable() { return executable_; } | 972 Executability executable() { return executable_; } |
| 972 | 973 |
| 973 // Identity used in error reporting. | 974 // Identity used in error reporting. |
| 974 AllocationSpace identity() { return id_; } | 975 AllocationSpace identity() { return id_; } |
| 975 | 976 |
| 977 virtual void AddAllocationObserver(AllocationObserver* observer) { | |
| 978 allocation_observers_->Add(observer); | |
| 979 } | |
| 980 | |
| 981 virtual void RemoveAllocationObserver(AllocationObserver* observer) { | |
| 982 bool removed = allocation_observers_->RemoveElement(observer); | |
| 983 static_cast<void>(removed); | |
| 984 DCHECK(removed); | |
| 985 } | |
| 986 | |
| 987 virtual void PauseAllocationObservers() { | |
| 988 allocation_observers_paused_ = true; | |
| 989 } | |
| 990 | |
| 991 virtual void ResumeAllocationObservers() { | |
| 992 allocation_observers_paused_ = false; | |
| 993 } | |
| 994 | |
| 995 void AllocationStep(Address soon_object, int size); | |
| 996 | |
| 976 // Return the total amount committed memory for this space, i.e., allocatable | 997 // Return the total amount committed memory for this space, i.e., allocatable |
| 977 // memory and page headers. | 998 // memory and page headers. |
| 978 virtual intptr_t CommittedMemory() { return committed_; } | 999 virtual intptr_t CommittedMemory() { return committed_; } |
| 979 | 1000 |
| 980 virtual intptr_t MaximumCommittedMemory() { return max_committed_; } | 1001 virtual intptr_t MaximumCommittedMemory() { return max_committed_; } |
| 981 | 1002 |
| 982 // Returns allocated size. | 1003 // Returns allocated size. |
| 983 virtual intptr_t Size() = 0; | 1004 virtual intptr_t Size() = 0; |
| 984 | 1005 |
| 985 // Returns size of objects. Can differ from the allocated size | 1006 // Returns size of objects. Can differ from the allocated size |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 1012 max_committed_ = committed_; | 1033 max_committed_ = committed_; |
| 1013 } | 1034 } |
| 1014 } | 1035 } |
| 1015 | 1036 |
| 1016 void AccountUncommitted(intptr_t bytes) { | 1037 void AccountUncommitted(intptr_t bytes) { |
| 1017 DCHECK_GE(bytes, 0); | 1038 DCHECK_GE(bytes, 0); |
| 1018 committed_ -= bytes; | 1039 committed_ -= bytes; |
| 1019 DCHECK_GE(committed_, 0); | 1040 DCHECK_GE(committed_, 0); |
| 1020 } | 1041 } |
| 1021 | 1042 |
| 1043 List<AllocationObserver*>* allocation_observers_ = | |
| 1044 new List<AllocationObserver*>(); | |
| 1045 bool allocation_observers_paused_; | |
| 1046 | |
| 1022 private: | 1047 private: |
| 1023 Heap* heap_; | 1048 Heap* heap_; |
| 1024 AllocationSpace id_; | 1049 AllocationSpace id_; |
| 1025 Executability executable_; | 1050 Executability executable_; |
| 1026 | 1051 |
| 1027 // Keeps track of committed memory in a space. | 1052 // Keeps track of committed memory in a space. |
| 1028 intptr_t committed_; | 1053 intptr_t committed_; |
| 1029 intptr_t max_committed_; | 1054 intptr_t max_committed_; |
| 1030 }; | 1055 }; |
| 1031 | 1056 |
| (...skipping 1535 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2567 // forwards most functions to the appropriate semispace. | 2592 // forwards most functions to the appropriate semispace. |
| 2568 | 2593 |
| 2569 class NewSpace : public Space { | 2594 class NewSpace : public Space { |
| 2570 public: | 2595 public: |
| 2571 // Constructor. | 2596 // Constructor. |
| 2572 explicit NewSpace(Heap* heap) | 2597 explicit NewSpace(Heap* heap) |
| 2573 : Space(heap, NEW_SPACE, NOT_EXECUTABLE), | 2598 : Space(heap, NEW_SPACE, NOT_EXECUTABLE), |
| 2574 to_space_(heap, kToSpace), | 2599 to_space_(heap, kToSpace), |
| 2575 from_space_(heap, kFromSpace), | 2600 from_space_(heap, kFromSpace), |
| 2576 reservation_(), | 2601 reservation_(), |
| 2577 top_on_previous_step_(0), | 2602 top_on_previous_step_(0) {} |
| 2578 inline_allocation_observers_paused_(false) {} | |
| 2579 | 2603 |
| 2580 // Sets up the new space using the given chunk. | 2604 // Sets up the new space using the given chunk. |
| 2581 bool SetUp(int reserved_semispace_size_, int max_semi_space_size); | 2605 bool SetUp(int reserved_semispace_size_, int max_semi_space_size); |
| 2582 | 2606 |
| 2583 // Tears down the space. Heap memory was not allocated by the space, so it | 2607 // Tears down the space. Heap memory was not allocated by the space, so it |
| 2584 // is not deallocated here. | 2608 // is not deallocated here. |
| 2585 void TearDown(); | 2609 void TearDown(); |
| 2586 | 2610 |
| 2587 // True if the space has been set up but not torn down. | 2611 // True if the space has been set up but not torn down. |
| 2588 bool HasBeenSetUp() { | 2612 bool HasBeenSetUp() { |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2745 int size_in_bytes, AllocationAlignment alignment)); | 2769 int size_in_bytes, AllocationAlignment alignment)); |
| 2746 | 2770 |
| 2747 MUST_USE_RESULT inline AllocationResult AllocateRawSynchronized( | 2771 MUST_USE_RESULT inline AllocationResult AllocateRawSynchronized( |
| 2748 int size_in_bytes, AllocationAlignment alignment); | 2772 int size_in_bytes, AllocationAlignment alignment); |
| 2749 | 2773 |
| 2750 // Reset the allocation pointer to the beginning of the active semispace. | 2774 // Reset the allocation pointer to the beginning of the active semispace. |
| 2751 void ResetAllocationInfo(); | 2775 void ResetAllocationInfo(); |
| 2752 | 2776 |
| 2753 void UpdateInlineAllocationLimit(int size_in_bytes); | 2777 void UpdateInlineAllocationLimit(int size_in_bytes); |
| 2754 | 2778 |
| 2755 // Allows observation of inline allocation. The observer->Step() method gets | |
| 2756 // called after every step_size bytes have been allocated (approximately). | |
| 2757 // This works by adjusting the allocation limit to a lower value and adjusting | |
| 2758 // it after each step. | |
| 2759 void AddInlineAllocationObserver(InlineAllocationObserver* observer); | |
| 2760 | |
| 2761 // Removes a previously installed observer. | |
| 2762 void RemoveInlineAllocationObserver(InlineAllocationObserver* observer); | |
| 2763 | |
| 2764 void DisableInlineAllocationSteps() { | 2779 void DisableInlineAllocationSteps() { |
| 2765 top_on_previous_step_ = 0; | 2780 top_on_previous_step_ = 0; |
| 2766 UpdateInlineAllocationLimit(0); | 2781 UpdateInlineAllocationLimit(0); |
| 2767 } | 2782 } |
| 2768 | 2783 |
| 2784 void AddAllocationObserver(AllocationObserver* observer) override; | |
| 2785 | |
| 2786 void RemoveAllocationObserver(AllocationObserver* observer) override; | |
| 2787 | |
| 2769 // Get the extent of the inactive semispace (for use as a marking stack, | 2788 // Get the extent of the inactive semispace (for use as a marking stack, |
| 2770 // or to zap it). Notice: space-addresses are not necessarily on the | 2789 // or to zap it). Notice: space-addresses are not necessarily on the |
| 2771 // same page, so FromSpaceStart() might be above FromSpaceEnd(). | 2790 // same page, so FromSpaceStart() might be above FromSpaceEnd(). |
| 2772 Address FromSpacePageLow() { return from_space_.page_low(); } | 2791 Address FromSpacePageLow() { return from_space_.page_low(); } |
| 2773 Address FromSpacePageHigh() { return from_space_.page_high(); } | 2792 Address FromSpacePageHigh() { return from_space_.page_high(); } |
| 2774 Address FromSpaceStart() { return from_space_.space_start(); } | 2793 Address FromSpaceStart() { return from_space_.space_start(); } |
| 2775 Address FromSpaceEnd() { return from_space_.space_end(); } | 2794 Address FromSpaceEnd() { return from_space_.space_end(); } |
| 2776 | 2795 |
| 2777 // Get the extent of the active semispace's pages' memory. | 2796 // Get the extent of the active semispace's pages' memory. |
| 2778 Address ToSpaceStart() { return to_space_.space_start(); } | 2797 Address ToSpaceStart() { return to_space_.space_start(); } |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2854 // Start address and bit mask for containment testing. | 2873 // Start address and bit mask for containment testing. |
| 2855 Address start_; | 2874 Address start_; |
| 2856 uintptr_t address_mask_; | 2875 uintptr_t address_mask_; |
| 2857 uintptr_t object_mask_; | 2876 uintptr_t object_mask_; |
| 2858 uintptr_t object_expected_; | 2877 uintptr_t object_expected_; |
| 2859 | 2878 |
| 2860 // Allocation pointer and limit for normal allocation and allocation during | 2879 // Allocation pointer and limit for normal allocation and allocation during |
| 2861 // mark-compact collection. | 2880 // mark-compact collection. |
| 2862 AllocationInfo allocation_info_; | 2881 AllocationInfo allocation_info_; |
| 2863 | 2882 |
| 2864 // When inline allocation stepping is active, either because of incremental | |
| 2865 // marking or because of idle scavenge, we 'interrupt' inline allocation every | |
| 2866 // once in a while. This is done by setting allocation_info_.limit to be lower | |
| 2867 // than the actual limit and and increasing it in steps to guarantee that the | |
| 2868 // observers are notified periodically. | |
| 2869 List<InlineAllocationObserver*> inline_allocation_observers_; | |
| 2870 Address top_on_previous_step_; | 2883 Address top_on_previous_step_; |
| 2871 bool inline_allocation_observers_paused_; | |
| 2872 | 2884 |
| 2873 HistogramInfo* allocated_histogram_; | 2885 HistogramInfo* allocated_histogram_; |
| 2874 HistogramInfo* promoted_histogram_; | 2886 HistogramInfo* promoted_histogram_; |
| 2875 | 2887 |
| 2876 bool EnsureAllocation(int size_in_bytes, AllocationAlignment alignment); | 2888 bool EnsureAllocation(int size_in_bytes, AllocationAlignment alignment); |
| 2877 | 2889 |
| 2878 // If we are doing inline allocation in steps, this method performs the 'step' | 2890 // If we are doing inline allocation in steps, this method performs the 'step' |
| 2879 // operation. top is the memory address of the bump pointer at the last | 2891 // operation. top is the memory address of the bump pointer at the last |
| 2880 // inline allocation (i.e. it determines the numbers of bytes actually | 2892 // inline allocation (i.e. it determines the numbers of bytes actually |
| 2881 // allocated since the last step.) new_top is the address of the bump pointer | 2893 // allocated since the last step.) new_top is the address of the bump pointer |
| 2882 // where the next byte is going to be allocated from. top and new_top may be | 2894 // where the next byte is going to be allocated from. top and new_top may be |
| 2883 // different when we cross a page boundary or reset the space. | 2895 // different when we cross a page boundary or reset the space. |
| 2884 void InlineAllocationStep(Address top, Address new_top, Address soon_object, | 2896 void InlineAllocationStep(Address top, Address new_top, Address soon_object, |
| 2885 size_t size); | 2897 size_t size); |
| 2886 intptr_t GetNextInlineAllocationStepSize(); | 2898 intptr_t GetNextInlineAllocationStepSize(); |
| 2887 void StartNextInlineAllocationStep(); | 2899 void StartNextInlineAllocationStep(); |
| 2888 void PauseInlineAllocationObservers(); | 2900 void PauseAllocationObservers() override; |
| 2889 void ResumeInlineAllocationObservers(); | 2901 void ResumeAllocationObservers() override; |
| 2890 | 2902 |
| 2891 friend class PauseInlineAllocationObserversScope; | 2903 friend class PauseInlineAllocationObserversScope; |
| 2892 friend class SemiSpaceIterator; | 2904 friend class SemiSpaceIterator; |
| 2893 }; | 2905 }; |
| 2894 | 2906 |
| 2895 class PauseInlineAllocationObserversScope { | 2907 class PauseAllocationObserversScope { |
| 2896 public: | 2908 public: |
| 2897 explicit PauseInlineAllocationObserversScope(NewSpace* new_space) | 2909 explicit PauseAllocationObserversScope(Space* space) : space_(space) { |
| 2898 : new_space_(new_space) { | 2910 space_->PauseAllocationObservers(); |
| 2899 new_space_->PauseInlineAllocationObservers(); | |
| 2900 } | 2911 } |
| 2901 ~PauseInlineAllocationObserversScope() { | 2912 ~PauseAllocationObserversScope() { space_->ResumeAllocationObservers(); } |
| 2902 new_space_->ResumeInlineAllocationObservers(); | |
| 2903 } | |
| 2904 | 2913 |
| 2905 private: | 2914 private: |
| 2906 NewSpace* new_space_; | 2915 Space* space_; |
| 2907 DISALLOW_COPY_AND_ASSIGN(PauseInlineAllocationObserversScope); | 2916 DISALLOW_COPY_AND_ASSIGN(PauseAllocationObserversScope); |
| 2908 }; | 2917 }; |
| 2909 | 2918 |
| 2910 // ----------------------------------------------------------------------------- | 2919 // ----------------------------------------------------------------------------- |
| 2911 // Compaction space that is used temporarily during compaction. | 2920 // Compaction space that is used temporarily during compaction. |
| 2912 | 2921 |
| 2913 class CompactionSpace : public PagedSpace { | 2922 class CompactionSpace : public PagedSpace { |
| 2914 public: | 2923 public: |
| 2915 CompactionSpace(Heap* heap, AllocationSpace id, Executability executable) | 2924 CompactionSpace(Heap* heap, AllocationSpace id, Executability executable) |
| 2916 : PagedSpace(heap, id, executable) {} | 2925 : PagedSpace(heap, id, executable) {} |
| 2917 | 2926 |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3164 count = 0; | 3173 count = 0; |
| 3165 } | 3174 } |
| 3166 // Must be small, since an iteration is used for lookup. | 3175 // Must be small, since an iteration is used for lookup. |
| 3167 static const int kMaxComments = 64; | 3176 static const int kMaxComments = 64; |
| 3168 }; | 3177 }; |
| 3169 #endif | 3178 #endif |
| 3170 } // namespace internal | 3179 } // namespace internal |
| 3171 } // namespace v8 | 3180 } // namespace v8 |
| 3172 | 3181 |
| 3173 #endif // V8_HEAP_SPACES_H_ | 3182 #endif // V8_HEAP_SPACES_H_ |
| OLD | NEW |