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 <list> | 8 #include <list> |
9 #include <memory> | 9 #include <memory> |
10 #include <unordered_set> | 10 #include <unordered_set> |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 // Performs a single try to pick a node of at least |minimum_size| from the | 183 // Performs a single try to pick a node of at least |minimum_size| from the |
184 // category. Stores the actual size in |node_size|. Returns nullptr if no | 184 // category. Stores the actual size in |node_size|. Returns nullptr if no |
185 // node is found. | 185 // node is found. |
186 FreeSpace* TryPickNodeFromList(size_t minimum_size, size_t* node_size); | 186 FreeSpace* TryPickNodeFromList(size_t minimum_size, size_t* node_size); |
187 | 187 |
188 // Picks a node of at least |minimum_size| from the category. Stores the | 188 // Picks a node of at least |minimum_size| from the category. Stores the |
189 // actual size in |node_size|. Returns nullptr if no node is found. | 189 // actual size in |node_size|. Returns nullptr if no node is found. |
190 FreeSpace* SearchForNodeInList(size_t minimum_size, size_t* node_size); | 190 FreeSpace* SearchForNodeInList(size_t minimum_size, size_t* node_size); |
191 | 191 |
192 inline FreeList* owner(); | 192 inline FreeList* owner(); |
| 193 inline Page* page() const; |
193 inline bool is_linked(); | 194 inline bool is_linked(); |
194 bool is_empty() { return top() == nullptr; } | 195 bool is_empty() { return top() == nullptr; } |
195 size_t available() const { return available_; } | 196 size_t available() const { return available_; } |
196 | 197 |
197 #ifdef DEBUG | 198 #ifdef DEBUG |
198 size_t SumFreeList(); | 199 size_t SumFreeList(); |
199 int FreeListLength(); | 200 int FreeListLength(); |
200 #endif | 201 #endif |
201 | 202 |
202 private: | 203 private: |
203 // For debug builds we accurately compute free lists lengths up until | 204 // For debug builds we accurately compute free lists lengths up until |
204 // {kVeryLongFreeList} by manually walking the list. | 205 // {kVeryLongFreeList} by manually walking the list. |
205 static const int kVeryLongFreeList = 500; | 206 static const int kVeryLongFreeList = 500; |
206 | 207 |
207 inline Page* page(); | |
208 | |
209 FreeSpace* top() { return top_; } | 208 FreeSpace* top() { return top_; } |
210 void set_top(FreeSpace* top) { top_ = top; } | 209 void set_top(FreeSpace* top) { top_ = top; } |
211 FreeListCategory* prev() { return prev_; } | 210 FreeListCategory* prev() { return prev_; } |
212 void set_prev(FreeListCategory* prev) { prev_ = prev; } | 211 void set_prev(FreeListCategory* prev) { prev_ = prev; } |
213 FreeListCategory* next() { return next_; } | 212 FreeListCategory* next() { return next_; } |
214 void set_next(FreeListCategory* next) { next_ = next; } | 213 void set_next(FreeListCategory* next) { next_ = next; } |
215 | 214 |
216 // |type_|: The type of this free list category. | 215 // |type_|: The type of this free list category. |
217 FreeListCategoryType type_; | 216 FreeListCategoryType type_; |
218 | 217 |
(...skipping 1495 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1714 } else if (maximum_freed <= kSmallListMax) { | 1713 } else if (maximum_freed <= kSmallListMax) { |
1715 return kSmallAllocationMax; | 1714 return kSmallAllocationMax; |
1716 } else if (maximum_freed <= kMediumListMax) { | 1715 } else if (maximum_freed <= kMediumListMax) { |
1717 return kMediumAllocationMax; | 1716 return kMediumAllocationMax; |
1718 } else if (maximum_freed <= kLargeListMax) { | 1717 } else if (maximum_freed <= kLargeListMax) { |
1719 return kLargeAllocationMax; | 1718 return kLargeAllocationMax; |
1720 } | 1719 } |
1721 return maximum_freed; | 1720 return maximum_freed; |
1722 } | 1721 } |
1723 | 1722 |
| 1723 static FreeListCategoryType SelectFreeListCategoryType(size_t size_in_bytes) { |
| 1724 if (size_in_bytes <= kTiniestListMax) { |
| 1725 return kTiniest; |
| 1726 } else if (size_in_bytes <= kTinyListMax) { |
| 1727 return kTiny; |
| 1728 } else if (size_in_bytes <= kSmallListMax) { |
| 1729 return kSmall; |
| 1730 } else if (size_in_bytes <= kMediumListMax) { |
| 1731 return kMedium; |
| 1732 } else if (size_in_bytes <= kLargeListMax) { |
| 1733 return kLarge; |
| 1734 } |
| 1735 return kHuge; |
| 1736 } |
| 1737 |
1724 explicit FreeList(PagedSpace* owner); | 1738 explicit FreeList(PagedSpace* owner); |
1725 | 1739 |
1726 // Adds a node on the free list. The block of size {size_in_bytes} starting | 1740 // Adds a node on the free list. The block of size {size_in_bytes} starting |
1727 // at {start} is placed on the free list. The return value is the number of | 1741 // at {start} is placed on the free list. The return value is the number of |
1728 // bytes that were not added to the free list, because they freed memory block | 1742 // bytes that were not added to the free list, because they freed memory block |
1729 // was too small. Bookkeeping information will be written to the block, i.e., | 1743 // was too small. Bookkeeping information will be written to the block, i.e., |
1730 // its contents will be destroyed. The start address should be word aligned, | 1744 // its contents will be destroyed. The start address should be word aligned, |
1731 // and the size should be a non-zero multiple of the word size. | 1745 // and the size should be a non-zero multiple of the word size. |
1732 size_t Free(Address start, size_t size_in_bytes, FreeMode mode); | 1746 size_t Free(Address start, size_t size_in_bytes, FreeMode mode); |
1733 | 1747 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1785 void ForAllFreeListCategories(Callback callback) { | 1799 void ForAllFreeListCategories(Callback callback) { |
1786 for (int i = kFirstCategory; i < kNumberOfCategories; i++) { | 1800 for (int i = kFirstCategory; i < kNumberOfCategories; i++) { |
1787 ForAllFreeListCategories(static_cast<FreeListCategoryType>(i), callback); | 1801 ForAllFreeListCategories(static_cast<FreeListCategoryType>(i), callback); |
1788 } | 1802 } |
1789 } | 1803 } |
1790 | 1804 |
1791 bool AddCategory(FreeListCategory* category); | 1805 bool AddCategory(FreeListCategory* category); |
1792 void RemoveCategory(FreeListCategory* category); | 1806 void RemoveCategory(FreeListCategory* category); |
1793 void PrintCategories(FreeListCategoryType type); | 1807 void PrintCategories(FreeListCategoryType type); |
1794 | 1808 |
| 1809 // Returns a page containing an entry for a given type, or nullptr otherwise. |
| 1810 inline Page* GetPageForCategoryType(FreeListCategoryType type); |
| 1811 |
1795 #ifdef DEBUG | 1812 #ifdef DEBUG |
1796 size_t SumFreeLists(); | 1813 size_t SumFreeLists(); |
1797 bool IsVeryLong(); | 1814 bool IsVeryLong(); |
1798 #endif | 1815 #endif |
1799 | 1816 |
1800 private: | 1817 private: |
1801 class FreeListCategoryIterator { | 1818 class FreeListCategoryIterator { |
1802 public: | 1819 public: |
1803 FreeListCategoryIterator(FreeList* free_list, FreeListCategoryType type) | 1820 FreeListCategoryIterator(FreeList* free_list, FreeListCategoryType type) |
1804 : current_(free_list->categories_[type]) {} | 1821 : current_(free_list->categories_[type]) {} |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1838 | 1855 |
1839 // Tries to retrieve a node from the first category in a given |type|. | 1856 // Tries to retrieve a node from the first category in a given |type|. |
1840 // Returns nullptr if the category is empty. | 1857 // Returns nullptr if the category is empty. |
1841 FreeSpace* TryFindNodeIn(FreeListCategoryType type, size_t* node_size, | 1858 FreeSpace* TryFindNodeIn(FreeListCategoryType type, size_t* node_size, |
1842 size_t minimum_size); | 1859 size_t minimum_size); |
1843 | 1860 |
1844 // Searches a given |type| for a node of at least |minimum_size|. | 1861 // Searches a given |type| for a node of at least |minimum_size|. |
1845 FreeSpace* SearchForNodeInList(FreeListCategoryType type, size_t* node_size, | 1862 FreeSpace* SearchForNodeInList(FreeListCategoryType type, size_t* node_size, |
1846 size_t minimum_size); | 1863 size_t minimum_size); |
1847 | 1864 |
1848 FreeListCategoryType SelectFreeListCategoryType(size_t size_in_bytes) { | |
1849 if (size_in_bytes <= kTiniestListMax) { | |
1850 return kTiniest; | |
1851 } else if (size_in_bytes <= kTinyListMax) { | |
1852 return kTiny; | |
1853 } else if (size_in_bytes <= kSmallListMax) { | |
1854 return kSmall; | |
1855 } else if (size_in_bytes <= kMediumListMax) { | |
1856 return kMedium; | |
1857 } else if (size_in_bytes <= kLargeListMax) { | |
1858 return kLarge; | |
1859 } | |
1860 return kHuge; | |
1861 } | |
1862 | |
1863 // The tiny categories are not used for fast allocation. | 1865 // The tiny categories are not used for fast allocation. |
1864 FreeListCategoryType SelectFastAllocationFreeListCategoryType( | 1866 FreeListCategoryType SelectFastAllocationFreeListCategoryType( |
1865 size_t size_in_bytes) { | 1867 size_t size_in_bytes) { |
1866 if (size_in_bytes <= kSmallAllocationMax) { | 1868 if (size_in_bytes <= kSmallAllocationMax) { |
1867 return kSmall; | 1869 return kSmall; |
1868 } else if (size_in_bytes <= kMediumAllocationMax) { | 1870 } else if (size_in_bytes <= kMediumAllocationMax) { |
1869 return kMedium; | 1871 return kMedium; |
1870 } else if (size_in_bytes <= kLargeAllocationMax) { | 1872 } else if (size_in_bytes <= kLargeAllocationMax) { |
1871 return kLarge; | 1873 return kLarge; |
1872 } | 1874 } |
1873 return kHuge; | 1875 return kHuge; |
1874 } | 1876 } |
1875 | 1877 |
1876 FreeListCategory* top(FreeListCategoryType type) { return categories_[type]; } | 1878 FreeListCategory* top(FreeListCategoryType type) const { |
| 1879 return categories_[type]; |
| 1880 } |
1877 | 1881 |
1878 PagedSpace* owner_; | 1882 PagedSpace* owner_; |
1879 base::AtomicNumber<size_t> wasted_bytes_; | 1883 base::AtomicNumber<size_t> wasted_bytes_; |
1880 FreeListCategory* categories_[kNumberOfCategories]; | 1884 FreeListCategory* categories_[kNumberOfCategories]; |
1881 | 1885 |
1882 friend class FreeListCategory; | 1886 friend class FreeListCategory; |
1883 | 1887 |
1884 DISALLOW_IMPLICIT_CONSTRUCTORS(FreeList); | 1888 DISALLOW_IMPLICIT_CONSTRUCTORS(FreeList); |
1885 }; | 1889 }; |
1886 | 1890 |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2141 | 2145 |
2142 iterator begin() { return iterator(anchor_.next_page()); } | 2146 iterator begin() { return iterator(anchor_.next_page()); } |
2143 iterator end() { return iterator(&anchor_); } | 2147 iterator end() { return iterator(&anchor_); } |
2144 | 2148 |
2145 // Shrink immortal immovable pages of the space to be exactly the size needed | 2149 // Shrink immortal immovable pages of the space to be exactly the size needed |
2146 // using the high water mark. | 2150 // using the high water mark. |
2147 void ShrinkImmortalImmovablePages(); | 2151 void ShrinkImmortalImmovablePages(); |
2148 | 2152 |
2149 std::unique_ptr<ObjectIterator> GetObjectIterator() override; | 2153 std::unique_ptr<ObjectIterator> GetObjectIterator() override; |
2150 | 2154 |
| 2155 // Remove a page if it has at least |size_in_bytes| bytes available that can |
| 2156 // be used for allocation. |
| 2157 Page* RemovePageSafe(int size_in_bytes); |
| 2158 void AddPage(Page* page); |
| 2159 |
2151 protected: | 2160 protected: |
2152 // PagedSpaces that should be included in snapshots have different, i.e., | 2161 // PagedSpaces that should be included in snapshots have different, i.e., |
2153 // smaller, initial pages. | 2162 // smaller, initial pages. |
2154 virtual bool snapshotable() { return true; } | 2163 virtual bool snapshotable() { return true; } |
2155 | 2164 |
2156 bool HasPages() { return anchor_.next_page() != &anchor_; } | 2165 bool HasPages() { return anchor_.next_page() != &anchor_; } |
2157 | 2166 |
2158 // Cleans up the space, frees all pages in this space except those belonging | 2167 // Cleans up the space, frees all pages in this space except those belonging |
2159 // to the initial chunk, uncommits addresses in the initial chunk. | 2168 // to the initial chunk, uncommits addresses in the initial chunk. |
2160 void TearDown(); | 2169 void TearDown(); |
(...skipping 792 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2953 PageIterator old_iterator_; | 2962 PageIterator old_iterator_; |
2954 PageIterator code_iterator_; | 2963 PageIterator code_iterator_; |
2955 PageIterator map_iterator_; | 2964 PageIterator map_iterator_; |
2956 LargePageIterator lo_iterator_; | 2965 LargePageIterator lo_iterator_; |
2957 }; | 2966 }; |
2958 | 2967 |
2959 } // namespace internal | 2968 } // namespace internal |
2960 } // namespace v8 | 2969 } // namespace v8 |
2961 | 2970 |
2962 #endif // V8_HEAP_SPACES_H_ | 2971 #endif // V8_HEAP_SPACES_H_ |
OLD | NEW |