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 |