Chromium Code Reviews| 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 |