| 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 SlotSet; | 34 class SlotSet; |
| 35 class Space; | 35 class Space; |
| 36 | 36 |
| (...skipping 902 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 939 | 939 |
| 940 friend class MemoryAllocator; | 940 friend class MemoryAllocator; |
| 941 }; | 941 }; |
| 942 | 942 |
| 943 | 943 |
| 944 // ---------------------------------------------------------------------------- | 944 // ---------------------------------------------------------------------------- |
| 945 // Space is the abstract superclass for all allocation spaces. | 945 // Space is the abstract superclass for all allocation spaces. |
| 946 class Space : public Malloced { | 946 class Space : public Malloced { |
| 947 public: | 947 public: |
| 948 Space(Heap* heap, AllocationSpace id, Executability executable) | 948 Space(Heap* heap, AllocationSpace id, Executability executable) |
| 949 : heap_(heap), | 949 : allocation_observers_(new List<AllocationObserver*>()), |
| 950 allocation_observers_paused_(false), |
| 951 heap_(heap), |
| 950 id_(id), | 952 id_(id), |
| 951 executable_(executable), | 953 executable_(executable), |
| 952 committed_(0), | 954 committed_(0), |
| 953 max_committed_(0) {} | 955 max_committed_(0) {} |
| 954 | 956 |
| 955 virtual ~Space() {} | 957 virtual ~Space() {} |
| 956 | 958 |
| 957 Heap* heap() const { return heap_; } | 959 Heap* heap() const { return heap_; } |
| 958 | 960 |
| 959 // Does the space need executable memory? | 961 // Does the space need executable memory? |
| 960 Executability executable() { return executable_; } | 962 Executability executable() { return executable_; } |
| 961 | 963 |
| 962 // Identity used in error reporting. | 964 // Identity used in error reporting. |
| 963 AllocationSpace identity() { return id_; } | 965 AllocationSpace identity() { return id_; } |
| 964 | 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 USE(removed); |
| 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 |
| 965 // 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 |
| 966 // memory and page headers. | 988 // memory and page headers. |
| 967 virtual intptr_t CommittedMemory() { return committed_; } | 989 virtual intptr_t CommittedMemory() { return committed_; } |
| 968 | 990 |
| 969 virtual intptr_t MaximumCommittedMemory() { return max_committed_; } | 991 virtual intptr_t MaximumCommittedMemory() { return max_committed_; } |
| 970 | 992 |
| 971 // Returns allocated size. | 993 // Returns allocated size. |
| 972 virtual intptr_t Size() = 0; | 994 virtual intptr_t Size() = 0; |
| 973 | 995 |
| 974 // 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... |
| 1001 max_committed_ = committed_; | 1023 max_committed_ = committed_; |
| 1002 } | 1024 } |
| 1003 } | 1025 } |
| 1004 | 1026 |
| 1005 void AccountUncommitted(intptr_t bytes) { | 1027 void AccountUncommitted(intptr_t bytes) { |
| 1006 DCHECK_GE(bytes, 0); | 1028 DCHECK_GE(bytes, 0); |
| 1007 committed_ -= bytes; | 1029 committed_ -= bytes; |
| 1008 DCHECK_GE(committed_, 0); | 1030 DCHECK_GE(committed_, 0); |
| 1009 } | 1031 } |
| 1010 | 1032 |
| 1033 v8::base::SmartPointer<List<AllocationObserver*>> allocation_observers_; |
| 1034 bool allocation_observers_paused_; |
| 1035 |
| 1011 private: | 1036 private: |
| 1012 Heap* heap_; | 1037 Heap* heap_; |
| 1013 AllocationSpace id_; | 1038 AllocationSpace id_; |
| 1014 Executability executable_; | 1039 Executability executable_; |
| 1015 | 1040 |
| 1016 // Keeps track of committed memory in a space. | 1041 // Keeps track of committed memory in a space. |
| 1017 intptr_t committed_; | 1042 intptr_t committed_; |
| 1018 intptr_t max_committed_; | 1043 intptr_t max_committed_; |
| 1019 }; | 1044 }; |
| 1020 | 1045 |
| (...skipping 1501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2522 // forwards most functions to the appropriate semispace. | 2547 // forwards most functions to the appropriate semispace. |
| 2523 | 2548 |
| 2524 class NewSpace : public Space { | 2549 class NewSpace : public Space { |
| 2525 public: | 2550 public: |
| 2526 // Constructor. | 2551 // Constructor. |
| 2527 explicit NewSpace(Heap* heap) | 2552 explicit NewSpace(Heap* heap) |
| 2528 : Space(heap, NEW_SPACE, NOT_EXECUTABLE), | 2553 : Space(heap, NEW_SPACE, NOT_EXECUTABLE), |
| 2529 to_space_(heap, kToSpace), | 2554 to_space_(heap, kToSpace), |
| 2530 from_space_(heap, kFromSpace), | 2555 from_space_(heap, kFromSpace), |
| 2531 reservation_(), | 2556 reservation_(), |
| 2532 top_on_previous_step_(0), | 2557 top_on_previous_step_(0) {} |
| 2533 inline_allocation_observers_paused_(false) {} | |
| 2534 | 2558 |
| 2535 inline bool Contains(HeapObject* o); | 2559 inline bool Contains(HeapObject* o); |
| 2536 inline bool ContainsSlow(Address a); | 2560 inline bool ContainsSlow(Address a); |
| 2537 inline bool Contains(Object* o); | 2561 inline bool Contains(Object* o); |
| 2538 | 2562 |
| 2539 // Sets up the new space using the given chunk. | 2563 // Sets up the new space using the given chunk. |
| 2540 bool SetUp(int reserved_semispace_size_, int max_semi_space_size); | 2564 bool SetUp(int reserved_semispace_size_, int max_semi_space_size); |
| 2541 | 2565 |
| 2542 // Tears down the space. Heap memory was not allocated by the space, so it | 2566 // Tears down the space. Heap memory was not allocated by the space, so it |
| 2543 // is not deallocated here. | 2567 // is not deallocated here. |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2673 | 2697 |
| 2674 MUST_USE_RESULT INLINE(AllocationResult AllocateRaw( | 2698 MUST_USE_RESULT INLINE(AllocationResult AllocateRaw( |
| 2675 int size_in_bytes, AllocationAlignment alignment)); | 2699 int size_in_bytes, AllocationAlignment alignment)); |
| 2676 | 2700 |
| 2677 MUST_USE_RESULT inline AllocationResult AllocateRawSynchronized( | 2701 MUST_USE_RESULT inline AllocationResult AllocateRawSynchronized( |
| 2678 int size_in_bytes, AllocationAlignment alignment); | 2702 int size_in_bytes, AllocationAlignment alignment); |
| 2679 | 2703 |
| 2680 // Reset the allocation pointer to the beginning of the active semispace. | 2704 // Reset the allocation pointer to the beginning of the active semispace. |
| 2681 void ResetAllocationInfo(); | 2705 void ResetAllocationInfo(); |
| 2682 | 2706 |
| 2707 // When inline allocation stepping is active, either because of incremental |
| 2708 // marking, idle scavenge, or allocation statistics gathering, we 'interrupt' |
| 2709 // inline allocation every once in a while. This is done by setting |
| 2710 // allocation_info_.limit to be lower than the actual limit and and increasing |
| 2711 // it in steps to guarantee that the observers are notified periodically. |
| 2683 void UpdateInlineAllocationLimit(int size_in_bytes); | 2712 void UpdateInlineAllocationLimit(int size_in_bytes); |
| 2684 | 2713 |
| 2685 // Allows observation of inline allocation. The observer->Step() method gets | |
| 2686 // called after every step_size bytes have been allocated (approximately). | |
| 2687 // This works by adjusting the allocation limit to a lower value and adjusting | |
| 2688 // it after each step. | |
| 2689 void AddInlineAllocationObserver(InlineAllocationObserver* observer); | |
| 2690 | |
| 2691 // Removes a previously installed observer. | |
| 2692 void RemoveInlineAllocationObserver(InlineAllocationObserver* observer); | |
| 2693 | |
| 2694 void DisableInlineAllocationSteps() { | 2714 void DisableInlineAllocationSteps() { |
| 2695 top_on_previous_step_ = 0; | 2715 top_on_previous_step_ = 0; |
| 2696 UpdateInlineAllocationLimit(0); | 2716 UpdateInlineAllocationLimit(0); |
| 2697 } | 2717 } |
| 2698 | 2718 |
| 2719 // Allows observation of inline allocation. The observer->Step() method gets |
| 2720 // called after every step_size bytes have been allocated (approximately). |
| 2721 // This works by adjusting the allocation limit to a lower value and adjusting |
| 2722 // it after each step. |
| 2723 void AddAllocationObserver(AllocationObserver* observer) override; |
| 2724 |
| 2725 void RemoveAllocationObserver(AllocationObserver* observer) override; |
| 2726 |
| 2699 // Get the extent of the inactive semispace (for use as a marking stack, | 2727 // Get the extent of the inactive semispace (for use as a marking stack, |
| 2700 // or to zap it). Notice: space-addresses are not necessarily on the | 2728 // or to zap it). Notice: space-addresses are not necessarily on the |
| 2701 // same page, so FromSpaceStart() might be above FromSpaceEnd(). | 2729 // same page, so FromSpaceStart() might be above FromSpaceEnd(). |
| 2702 Address FromSpacePageLow() { return from_space_.page_low(); } | 2730 Address FromSpacePageLow() { return from_space_.page_low(); } |
| 2703 Address FromSpacePageHigh() { return from_space_.page_high(); } | 2731 Address FromSpacePageHigh() { return from_space_.page_high(); } |
| 2704 Address FromSpaceStart() { return from_space_.space_start(); } | 2732 Address FromSpaceStart() { return from_space_.space_start(); } |
| 2705 Address FromSpaceEnd() { return from_space_.space_end(); } | 2733 Address FromSpaceEnd() { return from_space_.space_end(); } |
| 2706 | 2734 |
| 2707 // Get the extent of the active semispace's pages' memory. | 2735 // Get the extent of the active semispace's pages' memory. |
| 2708 Address ToSpaceStart() { return to_space_.space_start(); } | 2736 Address ToSpaceStart() { return to_space_.space_start(); } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2751 | 2779 |
| 2752 bool UncommitFromSpace() { | 2780 bool UncommitFromSpace() { |
| 2753 if (!from_space_.is_committed()) return true; | 2781 if (!from_space_.is_committed()) return true; |
| 2754 return from_space_.Uncommit(); | 2782 return from_space_.Uncommit(); |
| 2755 } | 2783 } |
| 2756 | 2784 |
| 2757 bool IsFromSpaceCommitted() { return from_space_.is_committed(); } | 2785 bool IsFromSpaceCommitted() { return from_space_.is_committed(); } |
| 2758 | 2786 |
| 2759 SemiSpace* active_space() { return &to_space_; } | 2787 SemiSpace* active_space() { return &to_space_; } |
| 2760 | 2788 |
| 2789 void PauseAllocationObservers() override; |
| 2790 void ResumeAllocationObservers() override; |
| 2791 |
| 2761 private: | 2792 private: |
| 2762 // Update allocation info to match the current to-space page. | 2793 // Update allocation info to match the current to-space page. |
| 2763 void UpdateAllocationInfo(); | 2794 void UpdateAllocationInfo(); |
| 2764 | 2795 |
| 2765 base::Mutex mutex_; | 2796 base::Mutex mutex_; |
| 2766 | 2797 |
| 2767 Address chunk_base_; | 2798 Address chunk_base_; |
| 2768 uintptr_t chunk_size_; | 2799 uintptr_t chunk_size_; |
| 2769 | 2800 |
| 2770 // The semispaces. | 2801 // The semispaces. |
| 2771 SemiSpace to_space_; | 2802 SemiSpace to_space_; |
| 2772 SemiSpace from_space_; | 2803 SemiSpace from_space_; |
| 2773 base::VirtualMemory reservation_; | 2804 base::VirtualMemory reservation_; |
| 2774 int pages_used_; | 2805 int pages_used_; |
| 2775 | 2806 |
| 2776 // Start address and bit mask for containment testing. | 2807 // Start address and bit mask for containment testing. |
| 2777 Address start_; | 2808 Address start_; |
| 2778 | 2809 |
| 2779 // Allocation pointer and limit for normal allocation and allocation during | 2810 // Allocation pointer and limit for normal allocation and allocation during |
| 2780 // mark-compact collection. | 2811 // mark-compact collection. |
| 2781 AllocationInfo allocation_info_; | 2812 AllocationInfo allocation_info_; |
| 2782 | 2813 |
| 2783 // When inline allocation stepping is active, either because of incremental | |
| 2784 // marking or because of idle scavenge, we 'interrupt' inline allocation every | |
| 2785 // once in a while. This is done by setting allocation_info_.limit to be lower | |
| 2786 // than the actual limit and and increasing it in steps to guarantee that the | |
| 2787 // observers are notified periodically. | |
| 2788 List<InlineAllocationObserver*> inline_allocation_observers_; | |
| 2789 Address top_on_previous_step_; | 2814 Address top_on_previous_step_; |
| 2790 bool inline_allocation_observers_paused_; | |
| 2791 | 2815 |
| 2792 HistogramInfo* allocated_histogram_; | 2816 HistogramInfo* allocated_histogram_; |
| 2793 HistogramInfo* promoted_histogram_; | 2817 HistogramInfo* promoted_histogram_; |
| 2794 | 2818 |
| 2795 bool EnsureAllocation(int size_in_bytes, AllocationAlignment alignment); | 2819 bool EnsureAllocation(int size_in_bytes, AllocationAlignment alignment); |
| 2796 | 2820 |
| 2797 // If we are doing inline allocation in steps, this method performs the 'step' | 2821 // If we are doing inline allocation in steps, this method performs the 'step' |
| 2798 // operation. top is the memory address of the bump pointer at the last | 2822 // operation. top is the memory address of the bump pointer at the last |
| 2799 // inline allocation (i.e. it determines the numbers of bytes actually | 2823 // inline allocation (i.e. it determines the numbers of bytes actually |
| 2800 // allocated since the last step.) new_top is the address of the bump pointer | 2824 // allocated since the last step.) new_top is the address of the bump pointer |
| 2801 // where the next byte is going to be allocated from. top and new_top may be | 2825 // where the next byte is going to be allocated from. top and new_top may be |
| 2802 // different when we cross a page boundary or reset the space. | 2826 // different when we cross a page boundary or reset the space. |
| 2803 void InlineAllocationStep(Address top, Address new_top, Address soon_object, | 2827 void InlineAllocationStep(Address top, Address new_top, Address soon_object, |
| 2804 size_t size); | 2828 size_t size); |
| 2805 intptr_t GetNextInlineAllocationStepSize(); | 2829 intptr_t GetNextInlineAllocationStepSize(); |
| 2806 void StartNextInlineAllocationStep(); | 2830 void StartNextInlineAllocationStep(); |
| 2807 void PauseInlineAllocationObservers(); | |
| 2808 void ResumeInlineAllocationObservers(); | |
| 2809 | 2831 |
| 2810 friend class PauseInlineAllocationObserversScope; | |
| 2811 friend class SemiSpaceIterator; | 2832 friend class SemiSpaceIterator; |
| 2812 }; | 2833 }; |
| 2813 | 2834 |
| 2814 class PauseInlineAllocationObserversScope { | 2835 class PauseAllocationObserversScope { |
| 2815 public: | 2836 public: |
| 2816 explicit PauseInlineAllocationObserversScope(NewSpace* new_space) | 2837 explicit PauseAllocationObserversScope(Heap* heap); |
| 2817 : new_space_(new_space) { | 2838 ~PauseAllocationObserversScope(); |
| 2818 new_space_->PauseInlineAllocationObservers(); | |
| 2819 } | |
| 2820 ~PauseInlineAllocationObserversScope() { | |
| 2821 new_space_->ResumeInlineAllocationObservers(); | |
| 2822 } | |
| 2823 | 2839 |
| 2824 private: | 2840 private: |
| 2825 NewSpace* new_space_; | 2841 Heap* heap_; |
| 2826 DISALLOW_COPY_AND_ASSIGN(PauseInlineAllocationObserversScope); | 2842 DISALLOW_COPY_AND_ASSIGN(PauseAllocationObserversScope); |
| 2827 }; | 2843 }; |
| 2828 | 2844 |
| 2829 // ----------------------------------------------------------------------------- | 2845 // ----------------------------------------------------------------------------- |
| 2830 // Compaction space that is used temporarily during compaction. | 2846 // Compaction space that is used temporarily during compaction. |
| 2831 | 2847 |
| 2832 class CompactionSpace : public PagedSpace { | 2848 class CompactionSpace : public PagedSpace { |
| 2833 public: | 2849 public: |
| 2834 CompactionSpace(Heap* heap, AllocationSpace id, Executability executable) | 2850 CompactionSpace(Heap* heap, AllocationSpace id, Executability executable) |
| 2835 : PagedSpace(heap, id, executable) {} | 2851 : PagedSpace(heap, id, executable) {} |
| 2836 | 2852 |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3062 count = 0; | 3078 count = 0; |
| 3063 } | 3079 } |
| 3064 // Must be small, since an iteration is used for lookup. | 3080 // Must be small, since an iteration is used for lookup. |
| 3065 static const int kMaxComments = 64; | 3081 static const int kMaxComments = 64; |
| 3066 }; | 3082 }; |
| 3067 #endif | 3083 #endif |
| 3068 } // namespace internal | 3084 } // namespace internal |
| 3069 } // namespace v8 | 3085 } // namespace v8 |
| 3070 | 3086 |
| 3071 #endif // V8_HEAP_SPACES_H_ | 3087 #endif // V8_HEAP_SPACES_H_ |
| OLD | NEW |