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