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 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 kNumberOfCategories = kLastCategory + 1, | 128 kNumberOfCategories = kLastCategory + 1, |
129 kInvalidCategory | 129 kInvalidCategory |
130 }; | 130 }; |
131 | 131 |
132 enum FreeMode { kLinkCategory, kDoNotLinkCategory }; | 132 enum FreeMode { kLinkCategory, kDoNotLinkCategory }; |
133 | 133 |
134 // A free list category maintains a linked list of free memory blocks. | 134 // A free list category maintains a linked list of free memory blocks. |
135 class FreeListCategory { | 135 class FreeListCategory { |
136 public: | 136 public: |
137 static const int kSize = kIntSize + // FreeListCategoryType type_ | 137 static const int kSize = kIntSize + // FreeListCategoryType type_ |
138 kIntSize + // int available_ | 138 kIntSize + // padding for type_ |
| 139 kSizetSize + // size_t available_ |
139 kPointerSize + // FreeSpace* top_ | 140 kPointerSize + // FreeSpace* top_ |
140 kPointerSize + // FreeListCategory* prev_ | 141 kPointerSize + // FreeListCategory* prev_ |
141 kPointerSize; // FreeListCategory* next_ | 142 kPointerSize; // FreeListCategory* next_ |
142 | 143 |
143 FreeListCategory() | 144 FreeListCategory() |
144 : type_(kInvalidCategory), | 145 : type_(kInvalidCategory), |
145 available_(0), | 146 available_(0), |
146 top_(nullptr), | 147 top_(nullptr), |
147 prev_(nullptr), | 148 prev_(nullptr), |
148 next_(nullptr) {} | 149 next_(nullptr) {} |
(...skipping 11 matching lines...) Expand all Loading... |
160 void Reset(); | 161 void Reset(); |
161 | 162 |
162 void ResetStats() { Reset(); } | 163 void ResetStats() { Reset(); } |
163 | 164 |
164 void RepairFreeList(Heap* heap); | 165 void RepairFreeList(Heap* heap); |
165 | 166 |
166 // Relinks the category into the currently owning free list. Requires that the | 167 // Relinks the category into the currently owning free list. Requires that the |
167 // category is currently unlinked. | 168 // category is currently unlinked. |
168 void Relink(); | 169 void Relink(); |
169 | 170 |
170 bool Free(FreeSpace* node, int size_in_bytes, FreeMode mode); | 171 bool Free(FreeSpace* node, size_t size_in_bytes, FreeMode mode); |
171 | 172 |
172 // Picks a node from the list and stores its size in |node_size|. Returns | 173 // Picks a node from the list and stores its size in |node_size|. Returns |
173 // nullptr if the category is empty. | 174 // nullptr if the category is empty. |
174 FreeSpace* PickNodeFromList(int* node_size); | 175 FreeSpace* PickNodeFromList(size_t* node_size); |
175 | 176 |
176 // Performs a single try to pick a node of at least |minimum_size| from the | 177 // Performs a single try to pick a node of at least |minimum_size| from the |
177 // category. Stores the actual size in |node_size|. Returns nullptr if no | 178 // category. Stores the actual size in |node_size|. Returns nullptr if no |
178 // node is found. | 179 // node is found. |
179 FreeSpace* TryPickNodeFromList(int minimum_size, int* node_size); | 180 FreeSpace* TryPickNodeFromList(size_t minimum_size, size_t* node_size); |
180 | 181 |
181 // Picks a node of at least |minimum_size| from the category. Stores the | 182 // Picks a node of at least |minimum_size| from the category. Stores the |
182 // actual size in |node_size|. Returns nullptr if no node is found. | 183 // actual size in |node_size|. Returns nullptr if no node is found. |
183 FreeSpace* SearchForNodeInList(int minimum_size, int* node_size); | 184 FreeSpace* SearchForNodeInList(size_t minimum_size, size_t* node_size); |
184 | 185 |
185 inline FreeList* owner(); | 186 inline FreeList* owner(); |
186 inline bool is_linked(); | 187 inline bool is_linked(); |
187 bool is_empty() { return top() == nullptr; } | 188 bool is_empty() { return top() == nullptr; } |
188 int available() const { return available_; } | 189 size_t available() const { return available_; } |
189 | 190 |
190 #ifdef DEBUG | 191 #ifdef DEBUG |
191 intptr_t SumFreeList(); | 192 size_t SumFreeList(); |
192 int FreeListLength(); | 193 int FreeListLength(); |
193 #endif | 194 #endif |
194 | 195 |
195 private: | 196 private: |
196 // For debug builds we accurately compute free lists lengths up until | 197 // For debug builds we accurately compute free lists lengths up until |
197 // {kVeryLongFreeList} by manually walking the list. | 198 // {kVeryLongFreeList} by manually walking the list. |
198 static const int kVeryLongFreeList = 500; | 199 static const int kVeryLongFreeList = 500; |
199 | 200 |
200 inline Page* page(); | 201 inline Page* page(); |
201 | 202 |
202 FreeSpace* top() { return top_; } | 203 FreeSpace* top() { return top_; } |
203 void set_top(FreeSpace* top) { top_ = top; } | 204 void set_top(FreeSpace* top) { top_ = top; } |
204 FreeListCategory* prev() { return prev_; } | 205 FreeListCategory* prev() { return prev_; } |
205 void set_prev(FreeListCategory* prev) { prev_ = prev; } | 206 void set_prev(FreeListCategory* prev) { prev_ = prev; } |
206 FreeListCategory* next() { return next_; } | 207 FreeListCategory* next() { return next_; } |
207 void set_next(FreeListCategory* next) { next_ = next; } | 208 void set_next(FreeListCategory* next) { next_ = next; } |
208 | 209 |
209 // |type_|: The type of this free list category. | 210 // |type_|: The type of this free list category. |
210 FreeListCategoryType type_; | 211 FreeListCategoryType type_; |
211 | 212 |
212 // |available_|: Total available bytes in all blocks of this free list | 213 // |available_|: Total available bytes in all blocks of this free list |
213 // category. | 214 // category. |
214 int available_; | 215 size_t available_; |
215 | 216 |
216 // |top_|: Points to the top FreeSpace* in the free list category. | 217 // |top_|: Points to the top FreeSpace* in the free list category. |
217 FreeSpace* top_; | 218 FreeSpace* top_; |
218 | 219 |
219 FreeListCategory* prev_; | 220 FreeListCategory* prev_; |
220 FreeListCategory* next_; | 221 FreeListCategory* next_; |
221 | 222 |
222 friend class FreeList; | 223 friend class FreeList; |
223 friend class PagedSpace; | 224 friend class PagedSpace; |
224 }; | 225 }; |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 static const intptr_t kAlignment = | 314 static const intptr_t kAlignment = |
314 (static_cast<uintptr_t>(1) << kPageSizeBits); | 315 (static_cast<uintptr_t>(1) << kPageSizeBits); |
315 | 316 |
316 static const intptr_t kAlignmentMask = kAlignment - 1; | 317 static const intptr_t kAlignmentMask = kAlignment - 1; |
317 | 318 |
318 static const intptr_t kSizeOffset = 0; | 319 static const intptr_t kSizeOffset = 0; |
319 | 320 |
320 static const intptr_t kFlagsOffset = kSizeOffset + kPointerSize; | 321 static const intptr_t kFlagsOffset = kSizeOffset + kPointerSize; |
321 | 322 |
322 static const size_t kMinHeaderSize = | 323 static const size_t kMinHeaderSize = |
323 kSizeOffset + kPointerSize // size_t size | 324 kSizeOffset + kSizetSize // size_t size |
324 + kIntptrSize // Flags flags_ | 325 + kIntptrSize // Flags flags_ |
325 + kPointerSize // Address area_start_ | 326 + kPointerSize // Address area_start_ |
326 + kPointerSize // Address area_end_ | 327 + kPointerSize // Address area_end_ |
327 + 2 * kPointerSize // base::VirtualMemory reservation_ | 328 + 2 * kPointerSize // base::VirtualMemory reservation_ |
328 + kPointerSize // Address owner_ | 329 + kPointerSize // Address owner_ |
329 + kPointerSize // Heap* heap_ | 330 + kPointerSize // Heap* heap_ |
330 + kIntSize // int progress_bar_ | 331 + kIntSize // int progress_bar_ |
331 + kIntSize // int live_bytes_count_ | 332 + kIntSize // int live_bytes_count_ |
332 + kPointerSize // SlotSet* old_to_new_slots_ | 333 + kPointerSize // SlotSet* old_to_new_slots_ |
333 + kPointerSize // SlotSet* old_to_old_slots_ | 334 + kPointerSize // SlotSet* old_to_old_slots_ |
334 + kPointerSize // TypedSlotSet* typed_old_to_new_slots_ | 335 + kPointerSize // TypedSlotSet* typed_old_to_new_slots_ |
335 + kPointerSize // TypedSlotSet* typed_old_to_old_slots_ | 336 + kPointerSize // TypedSlotSet* typed_old_to_old_slots_ |
336 + kPointerSize // SkipList* skip_list_ | 337 + kPointerSize // SkipList* skip_list_ |
337 + kPointerSize // AtomicValue high_water_mark_ | 338 + kPointerSize // AtomicValue high_water_mark_ |
338 + kPointerSize // base::Mutex* mutex_ | 339 + kPointerSize // base::Mutex* mutex_ |
339 + kPointerSize // base::AtomicWord concurrent_sweeping_ | 340 + kPointerSize // base::AtomicWord concurrent_sweeping_ |
340 + 2 * kPointerSize // AtomicNumber free-list statistics | 341 + 2 * kSizetSize // AtomicNumber free-list statistics |
341 + kPointerSize // AtomicValue next_chunk_ | 342 + kPointerSize // AtomicValue next_chunk_ |
342 + kPointerSize // AtomicValue prev_chunk_ | 343 + kPointerSize // AtomicValue prev_chunk_ |
343 // FreeListCategory categories_[kNumberOfCategories] | 344 // FreeListCategory categories_[kNumberOfCategories] |
344 + FreeListCategory::kSize * kNumberOfCategories + | 345 + FreeListCategory::kSize * kNumberOfCategories + |
345 kPointerSize // LocalArrayBufferTracker* local_tracker_ | 346 kPointerSize // LocalArrayBufferTracker* local_tracker_ |
346 // std::unordered_set<Address>* black_area_end_marker_map_ | 347 // std::unordered_set<Address>* black_area_end_marker_map_ |
347 + kPointerSize; | 348 + kPointerSize; |
348 | 349 |
349 // We add some more space to the computed header size to amount for missing | 350 // We add some more space to the computed header size to amount for missing |
350 // alignment requirements in our computation. | 351 // alignment requirements in our computation. |
351 // Try to get kHeaderSize properly aligned on 32-bit and 64-bit machines. | 352 // Try to get kHeaderSize properly aligned on 32-bit and 64-bit machines. |
352 static const size_t kHeaderSize = kMinHeaderSize; | 353 static const size_t kHeaderSize = kMinHeaderSize; |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
452 void ReleaseOldToOldSlots(); | 453 void ReleaseOldToOldSlots(); |
453 void AllocateTypedOldToNewSlots(); | 454 void AllocateTypedOldToNewSlots(); |
454 void ReleaseTypedOldToNewSlots(); | 455 void ReleaseTypedOldToNewSlots(); |
455 void AllocateTypedOldToOldSlots(); | 456 void AllocateTypedOldToOldSlots(); |
456 void ReleaseTypedOldToOldSlots(); | 457 void ReleaseTypedOldToOldSlots(); |
457 void AllocateLocalTracker(); | 458 void AllocateLocalTracker(); |
458 void ReleaseLocalTracker(); | 459 void ReleaseLocalTracker(); |
459 | 460 |
460 Address area_start() { return area_start_; } | 461 Address area_start() { return area_start_; } |
461 Address area_end() { return area_end_; } | 462 Address area_end() { return area_end_; } |
462 int area_size() { return static_cast<int>(area_end() - area_start()); } | 463 size_t area_size() { return static_cast<size_t>(area_end() - area_start()); } |
463 | 464 |
464 bool CommitArea(size_t requested); | 465 bool CommitArea(size_t requested); |
465 | 466 |
466 // Approximate amount of physical memory committed for this chunk. | 467 // Approximate amount of physical memory committed for this chunk. |
467 size_t CommittedPhysicalMemory(); | 468 size_t CommittedPhysicalMemory(); |
468 | 469 |
469 Address HighWaterMark() { return address() + high_water_mark_.Value(); } | 470 Address HighWaterMark() { return address() + high_water_mark_.Value(); } |
470 | 471 |
471 int progress_bar() { | 472 int progress_bar() { |
472 DCHECK(IsFlagSet(HAS_PROGRESS_BAR)); | 473 DCHECK(IsFlagSet(HAS_PROGRESS_BAR)); |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
742 void set_prev_page(Page* page) { set_prev_chunk(page); } | 743 void set_prev_page(Page* page) { set_prev_chunk(page); } |
743 | 744 |
744 template <typename Callback> | 745 template <typename Callback> |
745 inline void ForAllFreeListCategories(Callback callback) { | 746 inline void ForAllFreeListCategories(Callback callback) { |
746 for (int i = kFirstCategory; i < kNumberOfCategories; i++) { | 747 for (int i = kFirstCategory; i < kNumberOfCategories; i++) { |
747 callback(&categories_[i]); | 748 callback(&categories_[i]); |
748 } | 749 } |
749 } | 750 } |
750 | 751 |
751 // Returns the offset of a given address to this page. | 752 // Returns the offset of a given address to this page. |
752 inline int Offset(Address a) { | 753 inline size_t Offset(Address a) { return static_cast<size_t>(a - address()); } |
753 int offset = static_cast<int>(a - address()); | |
754 return offset; | |
755 } | |
756 | 754 |
757 // Returns the address for a given offset to the this page. | 755 // Returns the address for a given offset to the this page. |
758 Address OffsetToAddress(int offset) { | 756 Address OffsetToAddress(size_t offset) { |
759 DCHECK_PAGE_OFFSET(offset); | 757 DCHECK_PAGE_OFFSET(offset); |
760 return address() + offset; | 758 return address() + offset; |
761 } | 759 } |
762 | 760 |
763 // WaitUntilSweepingCompleted only works when concurrent sweeping is in | 761 // WaitUntilSweepingCompleted only works when concurrent sweeping is in |
764 // progress. In particular, when we know that right before this call a | 762 // progress. In particular, when we know that right before this call a |
765 // sweeper thread was sweeping this page. | 763 // sweeper thread was sweeping this page. |
766 void WaitUntilSweepingCompleted() { | 764 void WaitUntilSweepingCompleted() { |
767 mutex_->Lock(); | 765 mutex_->Lock(); |
768 mutex_->Unlock(); | 766 mutex_->Unlock(); |
769 DCHECK(SweepingDone()); | 767 DCHECK(SweepingDone()); |
770 } | 768 } |
771 | 769 |
772 bool SweepingDone() { | 770 bool SweepingDone() { |
773 return concurrent_sweeping_state().Value() == kSweepingDone; | 771 return concurrent_sweeping_state().Value() == kSweepingDone; |
774 } | 772 } |
775 | 773 |
776 void ResetFreeListStatistics(); | 774 void ResetFreeListStatistics(); |
777 | 775 |
778 int LiveBytesFromFreeList() { | 776 size_t AvailableInFreeList(); |
779 return static_cast<int>(area_size() - wasted_memory() - | 777 |
780 available_in_free_list()); | 778 size_t LiveBytesFromFreeList() { |
| 779 DCHECK_GE(area_size(), wasted_memory() + available_in_free_list()); |
| 780 return area_size() - wasted_memory() - available_in_free_list(); |
781 } | 781 } |
782 | 782 |
783 FreeListCategory* free_list_category(FreeListCategoryType type) { | 783 FreeListCategory* free_list_category(FreeListCategoryType type) { |
784 return &categories_[type]; | 784 return &categories_[type]; |
785 } | 785 } |
786 | 786 |
787 bool is_anchor() { return IsFlagSet(Page::ANCHOR); } | 787 bool is_anchor() { return IsFlagSet(Page::ANCHOR); } |
788 | 788 |
789 intptr_t wasted_memory() { return wasted_memory_.Value(); } | 789 size_t wasted_memory() { return wasted_memory_.Value(); } |
790 void add_wasted_memory(intptr_t waste) { wasted_memory_.Increment(waste); } | 790 void add_wasted_memory(size_t waste) { wasted_memory_.Increment(waste); } |
791 intptr_t available_in_free_list() { return available_in_free_list_.Value(); } | 791 size_t available_in_free_list() { return available_in_free_list_.Value(); } |
792 void add_available_in_free_list(intptr_t available) { | 792 void add_available_in_free_list(size_t available) { |
| 793 DCHECK_LE(available, area_size()); |
793 available_in_free_list_.Increment(available); | 794 available_in_free_list_.Increment(available); |
794 } | 795 } |
| 796 void remove_available_in_free_list(size_t available) { |
| 797 DCHECK_LE(available, area_size()); |
| 798 DCHECK_GE(available_in_free_list(), available); |
| 799 available_in_free_list_.Decrement(available); |
| 800 } |
795 | 801 |
796 size_t ShrinkToHighWaterMark(); | 802 size_t ShrinkToHighWaterMark(); |
797 | 803 |
798 #ifdef DEBUG | 804 #ifdef DEBUG |
799 void Print(); | 805 void Print(); |
800 #endif // DEBUG | 806 #endif // DEBUG |
801 | 807 |
802 private: | 808 private: |
803 enum InitializationMode { kFreeMemory, kDoNotFreeMemory }; | 809 enum InitializationMode { kFreeMemory, kDoNotFreeMemory }; |
804 | 810 |
(...skipping 881 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1686 } | 1692 } |
1687 | 1693 |
1688 explicit FreeList(PagedSpace* owner); | 1694 explicit FreeList(PagedSpace* owner); |
1689 | 1695 |
1690 // Adds a node on the free list. The block of size {size_in_bytes} starting | 1696 // Adds a node on the free list. The block of size {size_in_bytes} starting |
1691 // at {start} is placed on the free list. The return value is the number of | 1697 // at {start} is placed on the free list. The return value is the number of |
1692 // bytes that were not added to the free list, because they freed memory block | 1698 // bytes that were not added to the free list, because they freed memory block |
1693 // was too small. Bookkeeping information will be written to the block, i.e., | 1699 // was too small. Bookkeeping information will be written to the block, i.e., |
1694 // its contents will be destroyed. The start address should be word aligned, | 1700 // its contents will be destroyed. The start address should be word aligned, |
1695 // and the size should be a non-zero multiple of the word size. | 1701 // and the size should be a non-zero multiple of the word size. |
1696 int Free(Address start, int size_in_bytes, FreeMode mode); | 1702 size_t Free(Address start, size_t size_in_bytes, FreeMode mode); |
1697 | 1703 |
1698 // Allocate a block of size {size_in_bytes} from the free list. The block is | 1704 // Allocate a block of size {size_in_bytes} from the free list. The block is |
1699 // unitialized. A failure is returned if no block is available. The size | 1705 // unitialized. A failure is returned if no block is available. The size |
1700 // should be a non-zero multiple of the word size. | 1706 // should be a non-zero multiple of the word size. |
1701 MUST_USE_RESULT HeapObject* Allocate(int size_in_bytes); | 1707 MUST_USE_RESULT HeapObject* Allocate(size_t size_in_bytes); |
1702 | 1708 |
1703 // Clear the free list. | 1709 // Clear the free list. |
1704 void Reset(); | 1710 void Reset(); |
1705 | 1711 |
1706 void ResetStats() { | 1712 void ResetStats() { |
1707 wasted_bytes_.SetValue(0); | 1713 wasted_bytes_.SetValue(0); |
1708 ForAllFreeListCategories( | 1714 ForAllFreeListCategories( |
1709 [](FreeListCategory* category) { category->ResetStats(); }); | 1715 [](FreeListCategory* category) { category->ResetStats(); }); |
1710 } | 1716 } |
1711 | 1717 |
(...skipping 10 matching lines...) Expand all Loading... |
1722 bool empty = true; | 1728 bool empty = true; |
1723 ForAllFreeListCategories([&empty](FreeListCategory* category) { | 1729 ForAllFreeListCategories([&empty](FreeListCategory* category) { |
1724 if (!category->is_empty()) empty = false; | 1730 if (!category->is_empty()) empty = false; |
1725 }); | 1731 }); |
1726 return empty; | 1732 return empty; |
1727 } | 1733 } |
1728 | 1734 |
1729 // Used after booting the VM. | 1735 // Used after booting the VM. |
1730 void RepairLists(Heap* heap); | 1736 void RepairLists(Heap* heap); |
1731 | 1737 |
1732 intptr_t EvictFreeListItems(Page* page); | 1738 size_t EvictFreeListItems(Page* page); |
1733 bool ContainsPageFreeListItems(Page* page); | 1739 bool ContainsPageFreeListItems(Page* page); |
1734 | 1740 |
1735 PagedSpace* owner() { return owner_; } | 1741 PagedSpace* owner() { return owner_; } |
1736 intptr_t wasted_bytes() { return wasted_bytes_.Value(); } | 1742 size_t wasted_bytes() { return wasted_bytes_.Value(); } |
1737 | 1743 |
1738 template <typename Callback> | 1744 template <typename Callback> |
1739 void ForAllFreeListCategories(FreeListCategoryType type, Callback callback) { | 1745 void ForAllFreeListCategories(FreeListCategoryType type, Callback callback) { |
1740 FreeListCategory* current = categories_[type]; | 1746 FreeListCategory* current = categories_[type]; |
1741 while (current != nullptr) { | 1747 while (current != nullptr) { |
1742 FreeListCategory* next = current->next(); | 1748 FreeListCategory* next = current->next(); |
1743 callback(current); | 1749 callback(current); |
1744 current = next; | 1750 current = next; |
1745 } | 1751 } |
1746 } | 1752 } |
1747 | 1753 |
1748 template <typename Callback> | 1754 template <typename Callback> |
1749 void ForAllFreeListCategories(Callback callback) { | 1755 void ForAllFreeListCategories(Callback callback) { |
1750 for (int i = kFirstCategory; i < kNumberOfCategories; i++) { | 1756 for (int i = kFirstCategory; i < kNumberOfCategories; i++) { |
1751 ForAllFreeListCategories(static_cast<FreeListCategoryType>(i), callback); | 1757 ForAllFreeListCategories(static_cast<FreeListCategoryType>(i), callback); |
1752 } | 1758 } |
1753 } | 1759 } |
1754 | 1760 |
1755 bool AddCategory(FreeListCategory* category); | 1761 bool AddCategory(FreeListCategory* category); |
1756 void RemoveCategory(FreeListCategory* category); | 1762 void RemoveCategory(FreeListCategory* category); |
1757 void PrintCategories(FreeListCategoryType type); | 1763 void PrintCategories(FreeListCategoryType type); |
1758 | 1764 |
1759 #ifdef DEBUG | 1765 #ifdef DEBUG |
1760 intptr_t SumFreeLists(); | 1766 size_t SumFreeLists(); |
1761 bool IsVeryLong(); | 1767 bool IsVeryLong(); |
1762 #endif | 1768 #endif |
1763 | 1769 |
1764 private: | 1770 private: |
1765 class FreeListCategoryIterator { | 1771 class FreeListCategoryIterator { |
1766 public: | 1772 public: |
1767 FreeListCategoryIterator(FreeList* free_list, FreeListCategoryType type) | 1773 FreeListCategoryIterator(FreeList* free_list, FreeListCategoryType type) |
1768 : current_(free_list->categories_[type]) {} | 1774 : current_(free_list->categories_[type]) {} |
1769 | 1775 |
1770 bool HasNext() { return current_ != nullptr; } | 1776 bool HasNext() { return current_ != nullptr; } |
1771 | 1777 |
1772 FreeListCategory* Next() { | 1778 FreeListCategory* Next() { |
1773 DCHECK(HasNext()); | 1779 DCHECK(HasNext()); |
1774 FreeListCategory* tmp = current_; | 1780 FreeListCategory* tmp = current_; |
1775 current_ = current_->next(); | 1781 current_ = current_->next(); |
1776 return tmp; | 1782 return tmp; |
1777 } | 1783 } |
1778 | 1784 |
1779 private: | 1785 private: |
1780 FreeListCategory* current_; | 1786 FreeListCategory* current_; |
1781 }; | 1787 }; |
1782 | 1788 |
1783 // The size range of blocks, in bytes. | 1789 // The size range of blocks, in bytes. |
1784 static const int kMinBlockSize = 3 * kPointerSize; | 1790 static const size_t kMinBlockSize = 3 * kPointerSize; |
1785 static const int kMaxBlockSize = Page::kAllocatableMemory; | 1791 static const size_t kMaxBlockSize = Page::kAllocatableMemory; |
1786 | 1792 |
1787 static const int kTiniestListMax = 0xa * kPointerSize; | 1793 static const size_t kTiniestListMax = 0xa * kPointerSize; |
1788 static const int kTinyListMax = 0x1f * kPointerSize; | 1794 static const size_t kTinyListMax = 0x1f * kPointerSize; |
1789 static const int kSmallListMax = 0xff * kPointerSize; | 1795 static const size_t kSmallListMax = 0xff * kPointerSize; |
1790 static const int kMediumListMax = 0x7ff * kPointerSize; | 1796 static const size_t kMediumListMax = 0x7ff * kPointerSize; |
1791 static const int kLargeListMax = 0x3fff * kPointerSize; | 1797 static const size_t kLargeListMax = 0x3fff * kPointerSize; |
1792 static const int kTinyAllocationMax = kTiniestListMax; | 1798 static const size_t kTinyAllocationMax = kTiniestListMax; |
1793 static const int kSmallAllocationMax = kTinyListMax; | 1799 static const size_t kSmallAllocationMax = kTinyListMax; |
1794 static const int kMediumAllocationMax = kSmallListMax; | 1800 static const size_t kMediumAllocationMax = kSmallListMax; |
1795 static const int kLargeAllocationMax = kMediumListMax; | 1801 static const size_t kLargeAllocationMax = kMediumListMax; |
1796 | 1802 |
1797 FreeSpace* FindNodeFor(int size_in_bytes, int* node_size); | 1803 FreeSpace* FindNodeFor(size_t size_in_bytes, size_t* node_size); |
1798 | 1804 |
1799 // Walks all available categories for a given |type| and tries to retrieve | 1805 // Walks all available categories for a given |type| and tries to retrieve |
1800 // a node. Returns nullptr if the category is empty. | 1806 // a node. Returns nullptr if the category is empty. |
1801 FreeSpace* FindNodeIn(FreeListCategoryType type, int* node_size); | 1807 FreeSpace* FindNodeIn(FreeListCategoryType type, size_t* node_size); |
1802 | 1808 |
1803 // Tries to retrieve a node from the first category in a given |type|. | 1809 // Tries to retrieve a node from the first category in a given |type|. |
1804 // Returns nullptr if the category is empty. | 1810 // Returns nullptr if the category is empty. |
1805 FreeSpace* TryFindNodeIn(FreeListCategoryType type, int* node_size, | 1811 FreeSpace* TryFindNodeIn(FreeListCategoryType type, size_t* node_size, |
1806 int minimum_size); | 1812 size_t minimum_size); |
1807 | 1813 |
1808 // Searches a given |type| for a node of at least |minimum_size|. | 1814 // Searches a given |type| for a node of at least |minimum_size|. |
1809 FreeSpace* SearchForNodeInList(FreeListCategoryType type, int* node_size, | 1815 FreeSpace* SearchForNodeInList(FreeListCategoryType type, size_t* node_size, |
1810 int minimum_size); | 1816 size_t minimum_size); |
1811 | 1817 |
1812 FreeListCategoryType SelectFreeListCategoryType(size_t size_in_bytes) { | 1818 FreeListCategoryType SelectFreeListCategoryType(size_t size_in_bytes) { |
1813 if (size_in_bytes <= kTiniestListMax) { | 1819 if (size_in_bytes <= kTiniestListMax) { |
1814 return kTiniest; | 1820 return kTiniest; |
1815 } else if (size_in_bytes <= kTinyListMax) { | 1821 } else if (size_in_bytes <= kTinyListMax) { |
1816 return kTiny; | 1822 return kTiny; |
1817 } else if (size_in_bytes <= kSmallListMax) { | 1823 } else if (size_in_bytes <= kSmallListMax) { |
1818 return kSmall; | 1824 return kSmall; |
1819 } else if (size_in_bytes <= kMediumListMax) { | 1825 } else if (size_in_bytes <= kMediumListMax) { |
1820 return kMedium; | 1826 return kMedium; |
(...skipping 12 matching lines...) Expand all Loading... |
1833 return kMedium; | 1839 return kMedium; |
1834 } else if (size_in_bytes <= kLargeAllocationMax) { | 1840 } else if (size_in_bytes <= kLargeAllocationMax) { |
1835 return kLarge; | 1841 return kLarge; |
1836 } | 1842 } |
1837 return kHuge; | 1843 return kHuge; |
1838 } | 1844 } |
1839 | 1845 |
1840 FreeListCategory* top(FreeListCategoryType type) { return categories_[type]; } | 1846 FreeListCategory* top(FreeListCategoryType type) { return categories_[type]; } |
1841 | 1847 |
1842 PagedSpace* owner_; | 1848 PagedSpace* owner_; |
1843 base::AtomicNumber<intptr_t> wasted_bytes_; | 1849 base::AtomicNumber<size_t> wasted_bytes_; |
1844 FreeListCategory* categories_[kNumberOfCategories]; | 1850 FreeListCategory* categories_[kNumberOfCategories]; |
1845 | 1851 |
1846 friend class FreeListCategory; | 1852 friend class FreeListCategory; |
1847 | 1853 |
1848 DISALLOW_IMPLICIT_CONSTRUCTORS(FreeList); | 1854 DISALLOW_IMPLICIT_CONSTRUCTORS(FreeList); |
1849 }; | 1855 }; |
1850 | 1856 |
1851 // LocalAllocationBuffer represents a linear allocation area that is created | 1857 // LocalAllocationBuffer represents a linear allocation area that is created |
1852 // from a given {AllocationResult} and can be used to allocate memory without | 1858 // from a given {AllocationResult} and can be used to allocate memory without |
1853 // synchronization. | 1859 // synchronization. |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2020 | 2026 |
2021 // Allocate the requested number of bytes in the space and consider allocation | 2027 // Allocate the requested number of bytes in the space and consider allocation |
2022 // alignment if needed. | 2028 // alignment if needed. |
2023 MUST_USE_RESULT inline AllocationResult AllocateRaw( | 2029 MUST_USE_RESULT inline AllocationResult AllocateRaw( |
2024 int size_in_bytes, AllocationAlignment alignment); | 2030 int size_in_bytes, AllocationAlignment alignment); |
2025 | 2031 |
2026 // Give a block of memory to the space's free list. It might be added to | 2032 // Give a block of memory to the space's free list. It might be added to |
2027 // the free list or accounted as waste. | 2033 // the free list or accounted as waste. |
2028 // If add_to_freelist is false then just accounting stats are updated and | 2034 // If add_to_freelist is false then just accounting stats are updated and |
2029 // no attempt to add area to free list is made. | 2035 // no attempt to add area to free list is made. |
2030 int Free(Address start, int size_in_bytes) { | 2036 size_t Free(Address start, size_t size_in_bytes) { |
2031 int wasted = free_list_.Free(start, size_in_bytes, kLinkCategory); | 2037 size_t wasted = free_list_.Free(start, size_in_bytes, kLinkCategory); |
2032 accounting_stats_.DeallocateBytes(size_in_bytes); | 2038 accounting_stats_.DeallocateBytes(size_in_bytes); |
| 2039 DCHECK_GE(size_in_bytes, wasted); |
2033 return size_in_bytes - wasted; | 2040 return size_in_bytes - wasted; |
2034 } | 2041 } |
2035 | 2042 |
2036 int UnaccountedFree(Address start, int size_in_bytes) { | 2043 size_t UnaccountedFree(Address start, size_t size_in_bytes) { |
2037 int wasted = free_list_.Free(start, size_in_bytes, kDoNotLinkCategory); | 2044 size_t wasted = free_list_.Free(start, size_in_bytes, kDoNotLinkCategory); |
| 2045 DCHECK_GE(size_in_bytes, wasted); |
2038 return size_in_bytes - wasted; | 2046 return size_in_bytes - wasted; |
2039 } | 2047 } |
2040 | 2048 |
2041 void ResetFreeList() { free_list_.Reset(); } | 2049 void ResetFreeList() { free_list_.Reset(); } |
2042 | 2050 |
2043 // Set space allocation info. | 2051 // Set space allocation info. |
2044 void SetTopAndLimit(Address top, Address limit) { | 2052 void SetTopAndLimit(Address top, Address limit) { |
2045 DCHECK(top == limit || | 2053 DCHECK(top == limit || |
2046 Page::FromAddress(top) == Page::FromAddress(limit - 1)); | 2054 Page::FromAddress(top) == Page::FromAddress(limit - 1)); |
2047 MemoryChunk::UpdateHighWaterMark(allocation_info_.top()); | 2055 MemoryChunk::UpdateHighWaterMark(allocation_info_.top()); |
(...skipping 877 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2925 PageIterator old_iterator_; | 2933 PageIterator old_iterator_; |
2926 PageIterator code_iterator_; | 2934 PageIterator code_iterator_; |
2927 PageIterator map_iterator_; | 2935 PageIterator map_iterator_; |
2928 LargePageIterator lo_iterator_; | 2936 LargePageIterator lo_iterator_; |
2929 }; | 2937 }; |
2930 | 2938 |
2931 } // namespace internal | 2939 } // namespace internal |
2932 } // namespace v8 | 2940 } // namespace v8 |
2933 | 2941 |
2934 #endif // V8_HEAP_SPACES_H_ | 2942 #endif // V8_HEAP_SPACES_H_ |
OLD | NEW |