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