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 "src/allocation.h" | 8 #include "src/allocation.h" |
9 #include "src/atomic-utils.h" | 9 #include "src/atomic-utils.h" |
10 #include "src/base/atomicops.h" | 10 #include "src/base/atomicops.h" |
(...skipping 1566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1577 intptr_t capacity_; | 1577 intptr_t capacity_; |
1578 | 1578 |
1579 // |max_capacity_|: The maximum capacity ever observed. | 1579 // |max_capacity_|: The maximum capacity ever observed. |
1580 intptr_t max_capacity_; | 1580 intptr_t max_capacity_; |
1581 | 1581 |
1582 // |size_|: The number of allocated bytes. | 1582 // |size_|: The number of allocated bytes. |
1583 intptr_t size_; | 1583 intptr_t size_; |
1584 }; | 1584 }; |
1585 | 1585 |
1586 | 1586 |
1587 // ----------------------------------------------------------------------------- | 1587 // A free list category maintains a linked list of free memory blocks. |
1588 // Free lists for old object spaces | |
1589 | |
1590 // The free list category holds a pointer to the top element and a pointer to | |
1591 // the end element of the linked list of free memory blocks. | |
1592 class FreeListCategory { | 1588 class FreeListCategory { |
1593 public: | 1589 public: |
1594 explicit FreeListCategory(FreeList* owner, FreeListCategoryType type) | 1590 explicit FreeListCategory(FreeList* owner, FreeListCategoryType type) |
1595 : type_(type), | 1591 : type_(type), |
1596 top_(nullptr), | 1592 top_(nullptr), |
1597 end_(nullptr), | 1593 end_(nullptr), |
1598 available_(0), | 1594 available_(0), |
1599 owner_(owner) {} | 1595 owner_(owner) {} |
1600 | 1596 |
1597 // Concatenates {category} into {this}. | |
1598 // | |
1599 // Note: Concurrency safe. | |
Hannes Payer (out of office)
2015/10/15 12:23:42
thread-safe.
Michael Lippautz
2015/10/15 12:31:34
Done.
| |
1601 intptr_t Concatenate(FreeListCategory* category); | 1600 intptr_t Concatenate(FreeListCategory* category); |
1602 | 1601 |
1603 void Reset(); | 1602 void Reset(); |
1604 | 1603 |
1605 void Free(FreeSpace* node, int size_in_bytes); | 1604 void Free(FreeSpace* node, int size_in_bytes); |
1606 | 1605 |
1607 // Pick a node from the list. | 1606 // Pick a node from the list. |
1608 FreeSpace* PickNodeFromList(int* node_size); | 1607 FreeSpace* PickNodeFromList(int* node_size); |
1609 | 1608 |
1610 // Pick a node from the list and compare it against {size_in_bytes}. If the | 1609 // Pick a node from the list and compare it against {size_in_bytes}. If the |
1611 // node's size is greater or equal return the node and null otherwise. | 1610 // node's size is greater or equal return the node and null otherwise. |
1612 FreeSpace* PickNodeFromList(int size_in_bytes, int* node_size); | 1611 FreeSpace* PickNodeFromList(int size_in_bytes, int* node_size); |
1613 | 1612 |
1614 // Search for a node of size {size_in_bytes}. | 1613 // Search for a node of size {size_in_bytes}. |
1615 FreeSpace* SearchForNodeInList(int size_in_bytes, int* node_size); | 1614 FreeSpace* SearchForNodeInList(int size_in_bytes, int* node_size); |
1616 | 1615 |
1617 intptr_t EvictFreeListItemsInList(Page* p); | 1616 intptr_t EvictFreeListItemsInList(Page* p); |
1618 bool ContainsPageFreeListItemsInList(Page* p); | 1617 bool ContainsPageFreeListItemsInList(Page* p); |
1619 | 1618 |
1620 void RepairFreeList(Heap* heap); | 1619 void RepairFreeList(Heap* heap); |
1621 | 1620 |
1622 bool IsEmpty() { return top() == nullptr; } | 1621 bool IsEmpty() { return top() == nullptr; } |
1623 | 1622 |
1624 FreeList* owner() { return owner_; } | 1623 FreeList* owner() { return owner_; } |
1625 int available() const { return available_; } | 1624 int available() const { return available_; } |
1626 | 1625 |
1627 #ifdef DEBUG | 1626 #ifdef DEBUG |
1628 intptr_t SumFreeList(); | 1627 intptr_t SumFreeList(); |
1629 int FreeListLength(); | 1628 int FreeListLength(); |
1629 bool IsVeryLong(); | |
1630 #endif | 1630 #endif |
1631 | 1631 |
1632 private: | 1632 private: |
1633 static const int kVeryLongFreeList = 500; | |
Hannes Payer (out of office)
2015/10/15 12:23:42
Let's add a comment that describes that constant.
Michael Lippautz
2015/10/15 12:31:34
Done.
| |
1634 | |
1633 FreeSpace* top() { return top_.Value(); } | 1635 FreeSpace* top() { return top_.Value(); } |
1634 void set_top(FreeSpace* top) { top_.SetValue(top); } | 1636 void set_top(FreeSpace* top) { top_.SetValue(top); } |
1635 | 1637 |
1636 FreeSpace* end() const { return end_; } | 1638 FreeSpace* end() const { return end_; } |
1637 void set_end(FreeSpace* end) { end_ = end; } | 1639 void set_end(FreeSpace* end) { end_ = end; } |
1638 | 1640 |
1639 // |type_|: The type of this free list category. | 1641 // |type_|: The type of this free list category. |
1640 FreeListCategoryType type_; | 1642 FreeListCategoryType type_; |
1641 | 1643 |
1642 // |top_|: Points to the top FreeSpace* in the free list category. | 1644 // |top_|: Points to the top FreeSpace* in the free list category. |
1643 AtomicValue<FreeSpace*> top_; | 1645 AtomicValue<FreeSpace*> top_; |
1644 | 1646 |
1645 // |end_|: Points to the end FreeSpace* in the free list category. | 1647 // |end_|: Points to the end FreeSpace* in the free list category. |
1646 FreeSpace* end_; | 1648 FreeSpace* end_; |
1647 | 1649 |
1648 // |available_|: Total available bytes in all blocks of this free list | 1650 // |available_|: Total available bytes in all blocks of this free list |
1649 // category. | 1651 // category. |
1650 int available_; | 1652 int available_; |
1651 | 1653 |
1652 // |owner_|: The owning free list of this category. | 1654 // |owner_|: The owning free list of this category. |
1653 FreeList* owner_; | 1655 FreeList* owner_; |
1654 }; | 1656 }; |
1655 | 1657 |
1656 | 1658 // A free list maintaining free blocks of memory. The free list is organized in |
1657 // The free list for the old space. The free list is organized in such a way | 1659 // a way to encourage objects allocated around the same time to be near each |
1658 // as to encourage objects allocated around the same time to be near each | 1660 // other. The normal way to allocate is intended to be by bumping a 'top' |
1659 // other. The normal way to allocate is intended to be by bumping a 'top' | |
1660 // pointer until it hits a 'limit' pointer. When the limit is hit we need to | 1661 // pointer until it hits a 'limit' pointer. When the limit is hit we need to |
1661 // find a new space to allocate from. This is done with the free list, which | 1662 // find a new space to allocate from. This is done with the free list, which is |
1662 // is divided up into rough categories to cut down on waste. Having finer | 1663 // divided up into rough categories to cut down on waste. Having finer |
1663 // categories would scatter allocation more. | 1664 // categories would scatter allocation more. |
1664 | 1665 |
1665 // The old space free list is organized in categories. | 1666 // The free list is organized in categories as follows: |
1666 // 1-31 words: Such small free areas are discarded for efficiency reasons. | 1667 // 1-31 words: Such small free areas are discarded for efficiency reasons. They |
Hannes Payer (out of office)
2015/10/15 12:23:42
We could call this category "too small". WDYT?
Michael Lippautz
2015/10/15 12:31:34
Done.
| |
1667 // They can be reclaimed by the compactor. However the distance between top | 1668 // can be reclaimed by the compactor. However the distance between top and |
1668 // and limit may be this small. | 1669 // limit may be this small. |
1669 // 32-255 words: There is a list of spaces this large. It is used for top and | 1670 // 32-255 words (small): Used for allocating free space between 1-31 words in |
1670 // limit when the object we need to allocate is 1-31 words in size. These | 1671 // size. |
1671 // spaces are called small. | 1672 // 256-2047 words (medium): Used for allocating free space between 32-255 words |
1672 // 256-2047 words: There is a list of spaces this large. It is used for top and | 1673 // in size. |
1673 // limit when the object we need to allocate is 32-255 words in size. These | 1674 // 1048-16383 words (large): Used for allocating free space between 256-2047 |
1674 // spaces are called medium. | 1675 // words in size. |
1675 // 1048-16383 words: There is a list of spaces this large. It is used for top | 1676 // At least 16384 words (huge): This list is for objects of 2048 words or |
1676 // and limit when the object we need to allocate is 256-2047 words in size. | 1677 // larger. Empty pages are also added to this list. |
1677 // These spaces are call large. | |
1678 // At least 16384 words. This list is for objects of 2048 words or larger. | |
1679 // Empty pages are added to this list. These spaces are called huge. | |
1680 class FreeList { | 1678 class FreeList { |
1681 public: | 1679 public: |
1682 explicit FreeList(PagedSpace* owner); | |
1683 | |
1684 // The method concatenates {other} into {this} and returns the added bytes, | |
1685 // including waste. | |
1686 // | |
1687 // Can be used concurrently. | |
1688 intptr_t Concatenate(FreeList* other); | |
1689 | |
1690 // Clear the free list. | |
1691 void Reset(); | |
1692 | |
1693 void ResetStats() { wasted_bytes_ = 0; } | |
1694 | |
1695 // Return the number of bytes available on the free list. | |
1696 intptr_t available() { | |
1697 return small_list_.available() + medium_list_.available() + | |
1698 large_list_.available() + huge_list_.available(); | |
1699 } | |
1700 | |
1701 // Place a node on the free list. The block of size 'size_in_bytes' | |
1702 // starting at 'start' is placed on the free list. The return value is the | |
1703 // number of bytes that have been lost due to internal fragmentation by | |
1704 // freeing the block. Bookkeeping information will be written to the block, | |
1705 // i.e., its contents will be destroyed. The start address should be word | |
1706 // aligned, and the size should be a non-zero multiple of the word size. | |
1707 int Free(Address start, int size_in_bytes); | |
1708 | |
1709 // This method returns how much memory can be allocated after freeing | 1680 // This method returns how much memory can be allocated after freeing |
1710 // maximum_freed memory. | 1681 // maximum_freed memory. |
1711 static inline int GuaranteedAllocatable(int maximum_freed) { | 1682 static inline int GuaranteedAllocatable(int maximum_freed) { |
1712 if (maximum_freed <= kSmallListMin) { | 1683 if (maximum_freed <= kSmallListMin) { |
1713 return 0; | 1684 return 0; |
1714 } else if (maximum_freed <= kSmallListMax) { | 1685 } else if (maximum_freed <= kSmallListMax) { |
1715 return kSmallAllocationMax; | 1686 return kSmallAllocationMax; |
1716 } else if (maximum_freed <= kMediumListMax) { | 1687 } else if (maximum_freed <= kMediumListMax) { |
1717 return kMediumAllocationMax; | 1688 return kMediumAllocationMax; |
1718 } else if (maximum_freed <= kLargeListMax) { | 1689 } else if (maximum_freed <= kLargeListMax) { |
1719 return kLargeAllocationMax; | 1690 return kLargeAllocationMax; |
1720 } | 1691 } |
1721 return maximum_freed; | 1692 return maximum_freed; |
1722 } | 1693 } |
1723 | 1694 |
1724 // Allocate a block of size 'size_in_bytes' from the free list. The block | 1695 explicit FreeList(PagedSpace* owner); |
1725 // is unitialized. A failure is returned if no block is available. | 1696 |
1726 // The size should be a non-zero multiple of the word size. | 1697 // The method concatenates {other} into {this} and returns the added bytes, |
1698 // including waste. | |
1699 // | |
1700 // Note: Concurrency safe. | |
Hannes Payer (out of office)
2015/10/15 12:23:42
thread-safe.
Michael Lippautz
2015/10/15 12:31:34
Done.
| |
1701 intptr_t Concatenate(FreeList* other); | |
1702 | |
1703 // Place a node on the free list. The block of size {size_in_bytes} starting | |
Hannes Payer (out of office)
2015/10/15 12:23:42
Adds
Michael Lippautz
2015/10/15 12:31:34
Done.
| |
1704 // at {start} is placed on the free list. The return value is the number of | |
1705 // bytes that have been lost due to internal fragmentation by freeing the | |
Hannes Payer (out of office)
2015/10/15 12:23:42
...bytes that were not added to the free list, bec
Michael Lippautz
2015/10/15 12:31:34
Done.
| |
1706 // block. Bookkeeping information will be written to the block, i.e., its | |
1707 // contents will be destroyed. The start address should be word aligned, and | |
1708 // the size should be a non-zero multiple of the word size. | |
1709 int Free(Address start, int size_in_bytes); | |
1710 | |
1711 // Allocate a block of size {size_in_bytes} from the free list. The block is | |
1712 // unitialized. A failure is returned if no block is available. The size | |
1713 // should be a non-zero multiple of the word size. | |
1727 MUST_USE_RESULT HeapObject* Allocate(int size_in_bytes); | 1714 MUST_USE_RESULT HeapObject* Allocate(int size_in_bytes); |
1728 | 1715 |
1716 // Clear the free list. | |
1717 void Reset(); | |
1718 | |
1719 void ResetStats() { wasted_bytes_ = 0; } | |
1720 | |
1721 // Return the number of bytes available on the free list. | |
1722 intptr_t Available() { | |
1723 return small_list_.available() + medium_list_.available() + | |
1724 large_list_.available() + huge_list_.available(); | |
1725 } | |
1726 | |
1729 bool IsEmpty() { | 1727 bool IsEmpty() { |
1730 return small_list_.IsEmpty() && medium_list_.IsEmpty() && | 1728 return small_list_.IsEmpty() && medium_list_.IsEmpty() && |
1731 large_list_.IsEmpty() && huge_list_.IsEmpty(); | 1729 large_list_.IsEmpty() && huge_list_.IsEmpty(); |
1732 } | 1730 } |
1733 | 1731 |
1734 #ifdef DEBUG | |
1735 void Zap(); | |
1736 intptr_t SumFreeLists(); | |
1737 bool IsVeryLong(); | |
1738 #endif | |
1739 | |
1740 // Used after booting the VM. | 1732 // Used after booting the VM. |
1741 void RepairLists(Heap* heap); | 1733 void RepairLists(Heap* heap); |
1742 | 1734 |
1743 intptr_t EvictFreeListItems(Page* p); | 1735 intptr_t EvictFreeListItems(Page* p); |
1744 bool ContainsPageFreeListItems(Page* p); | 1736 bool ContainsPageFreeListItems(Page* p); |
1745 | 1737 |
1746 PagedSpace* owner() { return owner_; } | 1738 PagedSpace* owner() { return owner_; } |
1747 intptr_t wasted_bytes() { return wasted_bytes_; } | 1739 intptr_t wasted_bytes() { return wasted_bytes_; } |
1748 base::Mutex* mutex() { return &mutex_; } | 1740 base::Mutex* mutex() { return &mutex_; } |
1749 | 1741 |
1742 #ifdef DEBUG | |
1743 void Zap(); | |
1744 intptr_t SumFreeLists(); | |
1745 bool IsVeryLong(); | |
1746 #endif | |
1747 | |
1750 private: | 1748 private: |
1751 // The size range of blocks, in bytes. | 1749 // The size range of blocks, in bytes. |
1752 static const int kMinBlockSize = 3 * kPointerSize; | 1750 static const int kMinBlockSize = 3 * kPointerSize; |
1753 static const int kMaxBlockSize = Page::kAllocatableMemory; | 1751 static const int kMaxBlockSize = Page::kAllocatableMemory; |
1754 | 1752 |
1755 static const int kSmallListMin = 0x1f * kPointerSize; | 1753 static const int kSmallListMin = 0x1f * kPointerSize; |
1756 static const int kSmallListMax = 0xff * kPointerSize; | 1754 static const int kSmallListMax = 0xff * kPointerSize; |
1757 static const int kMediumListMax = 0x7ff * kPointerSize; | 1755 static const int kMediumListMax = 0x7ff * kPointerSize; |
1758 static const int kLargeListMax = 0x3fff * kPointerSize; | 1756 static const int kLargeListMax = 0x3fff * kPointerSize; |
1759 static const int kSmallAllocationMax = kSmallListMin; | 1757 static const int kSmallAllocationMax = kSmallListMin; |
(...skipping 13 matching lines...) Expand all Loading... | |
1773 return &large_list_; | 1771 return &large_list_; |
1774 case kHuge: | 1772 case kHuge: |
1775 return &huge_list_; | 1773 return &huge_list_; |
1776 default: | 1774 default: |
1777 UNREACHABLE(); | 1775 UNREACHABLE(); |
1778 } | 1776 } |
1779 UNREACHABLE(); | 1777 UNREACHABLE(); |
1780 return nullptr; | 1778 return nullptr; |
1781 } | 1779 } |
1782 | 1780 |
1783 | |
1784 PagedSpace* owner_; | 1781 PagedSpace* owner_; |
1785 Heap* heap_; | |
1786 base::Mutex mutex_; | 1782 base::Mutex mutex_; |
1787 intptr_t wasted_bytes_; | 1783 intptr_t wasted_bytes_; |
1788 FreeListCategory small_list_; | 1784 FreeListCategory small_list_; |
1789 FreeListCategory medium_list_; | 1785 FreeListCategory medium_list_; |
1790 FreeListCategory large_list_; | 1786 FreeListCategory large_list_; |
1791 FreeListCategory huge_list_; | 1787 FreeListCategory huge_list_; |
1792 | 1788 |
1793 DISALLOW_IMPLICIT_CONSTRUCTORS(FreeList); | 1789 DISALLOW_IMPLICIT_CONSTRUCTORS(FreeList); |
1794 }; | 1790 }; |
1795 | 1791 |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1895 | 1891 |
1896 // Increases the number of available bytes of that space. | 1892 // Increases the number of available bytes of that space. |
1897 void AddToAccountingStats(intptr_t bytes) { | 1893 void AddToAccountingStats(intptr_t bytes) { |
1898 accounting_stats_.DeallocateBytes(bytes); | 1894 accounting_stats_.DeallocateBytes(bytes); |
1899 } | 1895 } |
1900 | 1896 |
1901 // Available bytes without growing. These are the bytes on the free list. | 1897 // Available bytes without growing. These are the bytes on the free list. |
1902 // The bytes in the linear allocation area are not included in this total | 1898 // The bytes in the linear allocation area are not included in this total |
1903 // because updating the stats would slow down allocation. New pages are | 1899 // because updating the stats would slow down allocation. New pages are |
1904 // immediately added to the free list so they show up here. | 1900 // immediately added to the free list so they show up here. |
1905 intptr_t Available() override { return free_list_.available(); } | 1901 intptr_t Available() override { return free_list_.Available(); } |
1906 | 1902 |
1907 // Allocated bytes in this space. Garbage bytes that were not found due to | 1903 // Allocated bytes in this space. Garbage bytes that were not found due to |
1908 // concurrent sweeping are counted as being allocated! The bytes in the | 1904 // concurrent sweeping are counted as being allocated! The bytes in the |
1909 // current linear allocation area (between top and limit) are also counted | 1905 // current linear allocation area (between top and limit) are also counted |
1910 // here. | 1906 // here. |
1911 intptr_t Size() override { return accounting_stats_.Size(); } | 1907 intptr_t Size() override { return accounting_stats_.Size(); } |
1912 | 1908 |
1913 // As size, but the bytes in lazily swept pages are estimated and the bytes | 1909 // As size, but the bytes in lazily swept pages are estimated and the bytes |
1914 // in the current linear allocation area are not included. | 1910 // in the current linear allocation area are not included. |
1915 intptr_t SizeOfObjects() override; | 1911 intptr_t SizeOfObjects() override; |
(...skipping 1093 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3009 count = 0; | 3005 count = 0; |
3010 } | 3006 } |
3011 // Must be small, since an iteration is used for lookup. | 3007 // Must be small, since an iteration is used for lookup. |
3012 static const int kMaxComments = 64; | 3008 static const int kMaxComments = 64; |
3013 }; | 3009 }; |
3014 #endif | 3010 #endif |
3015 } // namespace internal | 3011 } // namespace internal |
3016 } // namespace v8 | 3012 } // namespace v8 |
3017 | 3013 |
3018 #endif // V8_HEAP_SPACES_H_ | 3014 #endif // V8_HEAP_SPACES_H_ |
OLD | NEW |