| 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 |