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 1436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1447 // functions increase or decrease one of the non-capacity stats in conjunction | 1447 // functions increase or decrease one of the non-capacity stats in conjunction |
1448 // with capacity, or else they always balance increases and decreases to the | 1448 // with capacity, or else they always balance increases and decreases to the |
1449 // non-capacity stats. | 1449 // non-capacity stats. |
1450 class AllocationStats BASE_EMBEDDED { | 1450 class AllocationStats BASE_EMBEDDED { |
1451 public: | 1451 public: |
1452 AllocationStats() { Clear(); } | 1452 AllocationStats() { Clear(); } |
1453 | 1453 |
1454 // Zero out all the allocation statistics (i.e., no capacity). | 1454 // Zero out all the allocation statistics (i.e., no capacity). |
1455 void Clear() { | 1455 void Clear() { |
1456 capacity_ = 0; | 1456 capacity_ = 0; |
1457 max_capacity_ = 0; | |
1458 size_ = 0; | 1457 size_ = 0; |
| 1458 committed_ = 0; |
| 1459 max_committed_ = 0; |
1459 } | 1460 } |
1460 | 1461 |
1461 void ClearSize() { size_ = capacity_; } | 1462 void ClearSize() { size_ = capacity_; } |
1462 | 1463 |
1463 // Reset the allocation statistics (i.e., available = capacity with no wasted | 1464 // Reset the allocation statistics (i.e., available = capacity with no wasted |
1464 // or allocated bytes). | 1465 // or allocated bytes). |
1465 void Reset() { | 1466 void Reset() { |
1466 size_ = 0; | 1467 size_ = 0; |
1467 } | 1468 } |
1468 | 1469 |
1469 // Accessors for the allocation statistics. | 1470 // Accessors for the allocation statistics. |
1470 intptr_t Capacity() { return capacity_; } | 1471 intptr_t Capacity() { return capacity_; } |
1471 intptr_t MaxCapacity() { return max_capacity_; } | |
1472 intptr_t Size() { return size_; } | 1472 intptr_t Size() { return size_; } |
| 1473 intptr_t Committed() { return committed_; } |
| 1474 intptr_t MaxCommitted() { return max_committed_; } |
1473 | 1475 |
1474 // Grow the space by adding available bytes. They are initially marked as | 1476 // Grow the space by adding available bytes. They are initially marked as |
1475 // being in use (part of the size), but will normally be immediately freed, | 1477 // being in use (part of the size), but will normally be immediately freed, |
1476 // putting them on the free list and removing them from size_. | 1478 // putting them on the free list and removing them from size_. |
1477 void ExpandSpace(int size_in_bytes) { | 1479 void ExpandSpace(int size_in_bytes) { |
1478 capacity_ += size_in_bytes; | 1480 capacity_ += size_in_bytes; |
1479 size_ += size_in_bytes; | 1481 size_ += size_in_bytes; |
1480 if (capacity_ > max_capacity_) { | |
1481 max_capacity_ = capacity_; | |
1482 } | |
1483 DCHECK(size_ >= 0); | 1482 DCHECK(size_ >= 0); |
1484 } | 1483 } |
1485 | 1484 |
1486 // Shrink the space by removing available bytes. Since shrinking is done | 1485 // Shrink the space by removing available bytes. Since shrinking is done |
1487 // during sweeping, bytes have been marked as being in use (part of the size) | 1486 // during sweeping, bytes have been marked as being in use (part of the size) |
1488 // and are hereby freed. | 1487 // and are hereby freed. |
1489 void ShrinkSpace(int size_in_bytes) { | 1488 void ShrinkSpace(int size_in_bytes) { |
1490 capacity_ -= size_in_bytes; | 1489 capacity_ -= size_in_bytes; |
1491 size_ -= size_in_bytes; | 1490 size_ -= size_in_bytes; |
1492 DCHECK(size_ >= 0); | 1491 DCHECK(size_ >= 0); |
1493 } | 1492 } |
1494 | 1493 |
1495 // Allocate from available bytes (available -> size). | 1494 // Allocate from available bytes (available -> size). |
1496 void AllocateBytes(intptr_t size_in_bytes) { | 1495 void AllocateBytes(intptr_t size_in_bytes) { |
1497 size_ += size_in_bytes; | 1496 size_ += size_in_bytes; |
1498 DCHECK(size_ >= 0); | 1497 DCHECK(size_ >= 0); |
1499 } | 1498 } |
1500 | 1499 |
1501 // Free allocated bytes, making them available (size -> available). | 1500 // Free allocated bytes, making them available (size -> available). |
1502 void DeallocateBytes(intptr_t size_in_bytes) { | 1501 void DeallocateBytes(intptr_t size_in_bytes) { |
1503 size_ -= size_in_bytes; | 1502 size_ -= size_in_bytes; |
1504 DCHECK(size_ >= 0); | 1503 DCHECK_GE(size_, 0); |
1505 } | 1504 } |
1506 | 1505 |
1507 // Merge {other} into {this}. | 1506 // Merge {other} into {this}. |
1508 void Merge(const AllocationStats& other) { | 1507 void Merge(const AllocationStats& other) { |
1509 capacity_ += other.capacity_; | 1508 capacity_ += other.capacity_; |
1510 size_ += other.size_; | 1509 size_ += other.size_; |
1511 if (other.max_capacity_ > max_capacity_) { | 1510 committed_ += other.committed_; |
1512 max_capacity_ = other.max_capacity_; | 1511 if (committed_ > max_committed_) { |
| 1512 max_committed_ = committed_; |
1513 } | 1513 } |
1514 } | 1514 } |
1515 | 1515 |
1516 void DecreaseCapacity(intptr_t size_in_bytes) { | 1516 void DecreaseCapacity(intptr_t size_in_bytes) { |
1517 capacity_ -= size_in_bytes; | 1517 capacity_ -= size_in_bytes; |
1518 DCHECK_GE(capacity_, 0); | 1518 DCHECK_GE(capacity_, 0); |
| 1519 DCHECK_GE(capacity_, size_); |
1519 } | 1520 } |
1520 | 1521 |
1521 void IncreaseCapacity(intptr_t size_in_bytes) { capacity_ += size_in_bytes; } | 1522 void IncreaseCapacity(intptr_t size_in_bytes) { capacity_ += size_in_bytes; } |
1522 | 1523 |
| 1524 void CommitMemory(intptr_t size_in_bytes) { |
| 1525 DCHECK_GE(size_in_bytes, 0); |
| 1526 committed_ += size_in_bytes; |
| 1527 if (committed_ > max_committed_) { |
| 1528 max_committed_ = committed_; |
| 1529 } |
| 1530 } |
| 1531 |
| 1532 void UncommitMemory(intptr_t size_in_bytes) { |
| 1533 DCHECK_GE(size_in_bytes, 0); |
| 1534 DCHECK_GE(committed_, size_in_bytes); |
| 1535 committed_ -= size_in_bytes; |
| 1536 } |
| 1537 |
1523 private: | 1538 private: |
1524 // |capacity_|: The number of object-area bytes (i.e., not including page | 1539 // |capacity_|: The number of object-area bytes (i.e., not including page |
1525 // bookkeeping structures) currently in the space. | 1540 // bookkeeping structures) currently in the space. |
1526 intptr_t capacity_; | 1541 intptr_t capacity_; |
1527 | 1542 |
1528 // |max_capacity_|: The maximum capacity ever observed. | |
1529 intptr_t max_capacity_; | |
1530 | |
1531 // |size_|: The number of allocated bytes. | 1543 // |size_|: The number of allocated bytes. |
1532 intptr_t size_; | 1544 intptr_t size_; |
| 1545 |
| 1546 // |committed_|: The number of bytes committed in the corresponding space, |
| 1547 // including page headers. Note that committed memory does not need to |
| 1548 // be larger than capacity/size, as memory can be moved to other spaces. |
| 1549 intptr_t committed_; |
| 1550 |
| 1551 // |max_committed_|: The maximum number of bytes committed ever observed. |
| 1552 intptr_t max_committed_; |
1533 }; | 1553 }; |
1534 | 1554 |
1535 | 1555 |
1536 // ----------------------------------------------------------------------------- | 1556 // ----------------------------------------------------------------------------- |
1537 // Free lists for old object spaces | 1557 // Free lists for old object spaces |
1538 | 1558 |
1539 // The free list category holds a pointer to the top element and a pointer to | 1559 // The free list category holds a pointer to the top element and a pointer to |
1540 // the end element of the linked list of free memory blocks. | 1560 // the end element of the linked list of free memory blocks. |
1541 class FreeListCategory { | 1561 class FreeListCategory { |
1542 public: | 1562 public: |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1623 // spaces are called medium. | 1643 // spaces are called medium. |
1624 // 1048-16383 words: There is a list of spaces this large. It is used for top | 1644 // 1048-16383 words: There is a list of spaces this large. It is used for top |
1625 // and limit when the object we need to allocate is 256-2047 words in size. | 1645 // and limit when the object we need to allocate is 256-2047 words in size. |
1626 // These spaces are call large. | 1646 // These spaces are call large. |
1627 // At least 16384 words. This list is for objects of 2048 words or larger. | 1647 // At least 16384 words. This list is for objects of 2048 words or larger. |
1628 // Empty pages are added to this list. These spaces are called huge. | 1648 // Empty pages are added to this list. These spaces are called huge. |
1629 class FreeList { | 1649 class FreeList { |
1630 public: | 1650 public: |
1631 explicit FreeList(PagedSpace* owner); | 1651 explicit FreeList(PagedSpace* owner); |
1632 | 1652 |
| 1653 // The method concatenates {other} into {this} and returns the added bytes, |
| 1654 // including waste. |
| 1655 // |
| 1656 // Can be used concurrently. |
1633 intptr_t Concatenate(FreeList* other); | 1657 intptr_t Concatenate(FreeList* other); |
1634 | 1658 |
1635 // Clear the free list. | 1659 // Clear the free list. |
1636 void Reset(); | 1660 void Reset(); |
1637 | 1661 |
1638 void ResetStats() { wasted_bytes_ = 0; } | 1662 void ResetStats() { wasted_bytes_ = 0; } |
1639 | 1663 |
1640 // Return the number of bytes available on the free list. | 1664 // Return the number of bytes available on the free list. |
1641 intptr_t available() { | 1665 intptr_t available() { |
1642 return small_list_.available() + medium_list_.available() + | 1666 return small_list_.available() + medium_list_.available() + |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1801 // During boot the free_space_map is created, and afterwards we may need | 1825 // During boot the free_space_map is created, and afterwards we may need |
1802 // to write it into the free list nodes that were already created. | 1826 // to write it into the free list nodes that were already created. |
1803 void RepairFreeListsAfterDeserialization(); | 1827 void RepairFreeListsAfterDeserialization(); |
1804 | 1828 |
1805 // Prepares for a mark-compact GC. | 1829 // Prepares for a mark-compact GC. |
1806 void PrepareForMarkCompact(); | 1830 void PrepareForMarkCompact(); |
1807 | 1831 |
1808 // Current capacity without growing (Size() + Available()). | 1832 // Current capacity without growing (Size() + Available()). |
1809 intptr_t Capacity() { return accounting_stats_.Capacity(); } | 1833 intptr_t Capacity() { return accounting_stats_.Capacity(); } |
1810 | 1834 |
1811 // Total amount of memory committed for this space. For paged | 1835 // Total amount of memory committed for this space. |
1812 // spaces this equals the capacity. | 1836 intptr_t CommittedMemory() override { return accounting_stats_.Committed(); } |
1813 intptr_t CommittedMemory() override { return Capacity(); } | |
1814 | 1837 |
1815 // The maximum amount of memory ever committed for this space. | 1838 // The maximum amount of memory ever committed for this space. |
1816 intptr_t MaximumCommittedMemory() { return accounting_stats_.MaxCapacity(); } | 1839 intptr_t MaximumCommittedMemory() { return accounting_stats_.MaxCommitted(); } |
1817 | 1840 |
1818 // Approximate amount of physical memory committed for this space. | 1841 // Approximate amount of physical memory committed for this space. |
1819 size_t CommittedPhysicalMemory() override; | 1842 size_t CommittedPhysicalMemory() override; |
1820 | 1843 |
1821 void ResetFreeListStatistics(); | 1844 void ResetFreeListStatistics(); |
1822 | 1845 |
1823 // Sets the capacity, the available space and the wasted space to zero. | 1846 // Sets the capacity, the available space and the wasted space to zero. |
1824 // The stats are rebuilt during sweeping by adding each page to the | 1847 // The stats are rebuilt during sweeping by adding each page to the |
1825 // capacity and the size when it is encountered. As free spaces are | 1848 // capacity and the size when it is encountered. As free spaces are |
1826 // discovered during the sweeping they are subtracted from the size and added | 1849 // discovered during the sweeping they are subtracted from the size and added |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1948 static void ResetCodeStatistics(Isolate* isolate); | 1971 static void ResetCodeStatistics(Isolate* isolate); |
1949 #endif | 1972 #endif |
1950 | 1973 |
1951 // Evacuation candidates are swept by evacuator. Needs to return a valid | 1974 // Evacuation candidates are swept by evacuator. Needs to return a valid |
1952 // result before _and_ after evacuation has finished. | 1975 // result before _and_ after evacuation has finished. |
1953 static bool ShouldBeSweptBySweeperThreads(Page* p) { | 1976 static bool ShouldBeSweptBySweeperThreads(Page* p) { |
1954 return !p->IsEvacuationCandidate() && | 1977 return !p->IsEvacuationCandidate() && |
1955 !p->IsFlagSet(Page::RESCAN_ON_EVACUATION) && !p->WasSwept(); | 1978 !p->IsFlagSet(Page::RESCAN_ON_EVACUATION) && !p->WasSwept(); |
1956 } | 1979 } |
1957 | 1980 |
1958 void IncrementUnsweptFreeBytes(intptr_t by) { unswept_free_bytes_ += by; } | |
1959 | |
1960 void IncreaseUnsweptFreeBytes(Page* p) { | |
1961 DCHECK(ShouldBeSweptBySweeperThreads(p)); | |
1962 unswept_free_bytes_ += (p->area_size() - p->LiveBytes()); | |
1963 } | |
1964 | |
1965 void DecrementUnsweptFreeBytes(intptr_t by) { unswept_free_bytes_ -= by; } | |
1966 | |
1967 void DecreaseUnsweptFreeBytes(Page* p) { | |
1968 DCHECK(ShouldBeSweptBySweeperThreads(p)); | |
1969 unswept_free_bytes_ -= (p->area_size() - p->LiveBytes()); | |
1970 } | |
1971 | |
1972 void ResetUnsweptFreeBytes() { unswept_free_bytes_ = 0; } | |
1973 | |
1974 // This function tries to steal size_in_bytes memory from the sweeper threads | 1981 // This function tries to steal size_in_bytes memory from the sweeper threads |
1975 // free-lists. If it does not succeed stealing enough memory, it will wait | 1982 // free-lists. If it does not succeed stealing enough memory, it will wait |
1976 // for the sweeper threads to finish sweeping. | 1983 // for the sweeper threads to finish sweeping. |
1977 // It returns true when sweeping is completed and false otherwise. | 1984 // It returns true when sweeping is completed and false otherwise. |
1978 bool EnsureSweeperProgress(intptr_t size_in_bytes); | 1985 bool EnsureSweeperProgress(intptr_t size_in_bytes); |
1979 | 1986 |
1980 void set_end_of_unswept_pages(Page* page) { end_of_unswept_pages_ = page; } | 1987 void set_end_of_unswept_pages(Page* page) { end_of_unswept_pages_ = page; } |
1981 | 1988 |
1982 Page* end_of_unswept_pages() { return end_of_unswept_pages_; } | 1989 Page* end_of_unswept_pages() { return end_of_unswept_pages_; } |
1983 | 1990 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2046 | 2053 |
2047 // The dummy page that anchors the double linked list of pages. | 2054 // The dummy page that anchors the double linked list of pages. |
2048 Page anchor_; | 2055 Page anchor_; |
2049 | 2056 |
2050 // The space's free list. | 2057 // The space's free list. |
2051 FreeList free_list_; | 2058 FreeList free_list_; |
2052 | 2059 |
2053 // Normal allocation information. | 2060 // Normal allocation information. |
2054 AllocationInfo allocation_info_; | 2061 AllocationInfo allocation_info_; |
2055 | 2062 |
2056 // The number of free bytes which could be reclaimed by advancing the | |
2057 // concurrent sweeper threads. | |
2058 intptr_t unswept_free_bytes_; | |
2059 | |
2060 // The sweeper threads iterate over the list of pointer and data space pages | 2063 // The sweeper threads iterate over the list of pointer and data space pages |
2061 // and sweep these pages concurrently. They will stop sweeping after the | 2064 // and sweep these pages concurrently. They will stop sweeping after the |
2062 // end_of_unswept_pages_ page. | 2065 // end_of_unswept_pages_ page. |
2063 Page* end_of_unswept_pages_; | 2066 Page* end_of_unswept_pages_; |
2064 | 2067 |
2065 // Mutex guarding any concurrent access to the space. | 2068 // Mutex guarding any concurrent access to the space. |
2066 base::Mutex space_mutex_; | 2069 base::Mutex space_mutex_; |
2067 | 2070 |
2068 friend class MarkCompactCollector; | 2071 friend class MarkCompactCollector; |
2069 friend class PageIterator; | 2072 friend class PageIterator; |
(...skipping 917 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2987 count = 0; | 2990 count = 0; |
2988 } | 2991 } |
2989 // Must be small, since an iteration is used for lookup. | 2992 // Must be small, since an iteration is used for lookup. |
2990 static const int kMaxComments = 64; | 2993 static const int kMaxComments = 64; |
2991 }; | 2994 }; |
2992 #endif | 2995 #endif |
2993 } // namespace internal | 2996 } // namespace internal |
2994 } // namespace v8 | 2997 } // namespace v8 |
2995 | 2998 |
2996 #endif // V8_HEAP_SPACES_H_ | 2999 #endif // V8_HEAP_SPACES_H_ |
OLD | NEW |