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 #include "src/heap/spaces.h" | 5 #include "src/heap/spaces.h" |
6 | 6 |
7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
8 #include "src/base/platform/platform.h" | 8 #include "src/base/platform/platform.h" |
9 #include "src/full-codegen/full-codegen.h" | 9 #include "src/full-codegen/full-codegen.h" |
10 #include "src/heap/slots-buffer.h" | 10 #include "src/heap/slots-buffer.h" |
(...skipping 998 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1009 // end_of_unswept_pages_ | 1009 // end_of_unswept_pages_ |
1010 // unswept_free_bytes_ | 1010 // unswept_free_bytes_ |
1011 // anchor_ | 1011 // anchor_ |
1012 | 1012 |
1013 MoveOverFreeMemory(other); | 1013 MoveOverFreeMemory(other); |
1014 | 1014 |
1015 // Update and clear accounting statistics. | 1015 // Update and clear accounting statistics. |
1016 accounting_stats_.Merge(other->accounting_stats_); | 1016 accounting_stats_.Merge(other->accounting_stats_); |
1017 other->accounting_stats_.Reset(); | 1017 other->accounting_stats_.Reset(); |
1018 | 1018 |
| 1019 AccountCommitted(other->CommittedMemory()); |
| 1020 |
1019 // Move over pages. | 1021 // Move over pages. |
1020 PageIterator it(other); | 1022 PageIterator it(other); |
1021 Page* p = nullptr; | 1023 Page* p = nullptr; |
1022 while (it.has_next()) { | 1024 while (it.has_next()) { |
1023 p = it.next(); | 1025 p = it.next(); |
1024 p->Unlink(); | 1026 p->Unlink(); |
1025 p->set_owner(this); | 1027 p->set_owner(this); |
1026 p->InsertAfter(anchor_.prev_page()); | 1028 p->InsertAfter(anchor_.prev_page()); |
1027 } | 1029 } |
1028 } | 1030 } |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1087 if (snapshotable() && !HasPages()) { | 1089 if (snapshotable() && !HasPages()) { |
1088 size = Snapshot::SizeOfFirstPage(heap()->isolate(), identity()); | 1090 size = Snapshot::SizeOfFirstPage(heap()->isolate(), identity()); |
1089 } | 1091 } |
1090 | 1092 |
1091 if (!CanExpand(size)) return false; | 1093 if (!CanExpand(size)) return false; |
1092 | 1094 |
1093 Page* p = heap()->isolate()->memory_allocator()->AllocatePage(size, this, | 1095 Page* p = heap()->isolate()->memory_allocator()->AllocatePage(size, this, |
1094 executable()); | 1096 executable()); |
1095 if (p == NULL) return false; | 1097 if (p == NULL) return false; |
1096 | 1098 |
| 1099 AccountCommitted(static_cast<intptr_t>(p->size())); |
| 1100 |
1097 // Pages created during bootstrapping may contain immortal immovable objects. | 1101 // Pages created during bootstrapping may contain immortal immovable objects. |
1098 if (!heap()->deserialization_complete()) p->MarkNeverEvacuate(); | 1102 if (!heap()->deserialization_complete()) p->MarkNeverEvacuate(); |
1099 | 1103 |
1100 DCHECK(Capacity() <= heap()->MaxOldGenerationSize()); | 1104 DCHECK(Capacity() <= heap()->MaxOldGenerationSize()); |
1101 | 1105 |
1102 p->InsertAfter(anchor_.prev_page()); | 1106 p->InsertAfter(anchor_.prev_page()); |
1103 | 1107 |
1104 return true; | 1108 return true; |
1105 } | 1109 } |
1106 | 1110 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1153 allocation_info_.set_top(NULL); | 1157 allocation_info_.set_top(NULL); |
1154 allocation_info_.set_limit(NULL); | 1158 allocation_info_.set_limit(NULL); |
1155 } | 1159 } |
1156 | 1160 |
1157 // If page is still in a list, unlink it from that list. | 1161 // If page is still in a list, unlink it from that list. |
1158 if (page->next_chunk() != NULL) { | 1162 if (page->next_chunk() != NULL) { |
1159 DCHECK(page->prev_chunk() != NULL); | 1163 DCHECK(page->prev_chunk() != NULL); |
1160 page->Unlink(); | 1164 page->Unlink(); |
1161 } | 1165 } |
1162 | 1166 |
| 1167 AccountUncommitted(static_cast<intptr_t>(page->size())); |
1163 heap()->QueueMemoryChunkForFree(page); | 1168 heap()->QueueMemoryChunkForFree(page); |
1164 | 1169 |
1165 DCHECK(Capacity() > 0); | 1170 DCHECK(Capacity() > 0); |
1166 accounting_stats_.ShrinkSpace(AreaSize()); | 1171 accounting_stats_.ShrinkSpace(AreaSize()); |
1167 } | 1172 } |
1168 | 1173 |
1169 | 1174 |
1170 #ifdef DEBUG | 1175 #ifdef DEBUG |
1171 void PagedSpace::Print() {} | 1176 void PagedSpace::Print() {} |
1172 #endif | 1177 #endif |
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1579 // otherwise. In the mark-compact collector, the memory region of the from | 1584 // otherwise. In the mark-compact collector, the memory region of the from |
1580 // space is used as the marking stack. It requires contiguous memory | 1585 // space is used as the marking stack. It requires contiguous memory |
1581 // addresses. | 1586 // addresses. |
1582 DCHECK(maximum_capacity >= Page::kPageSize); | 1587 DCHECK(maximum_capacity >= Page::kPageSize); |
1583 DCHECK(initial_capacity <= target_capacity); | 1588 DCHECK(initial_capacity <= target_capacity); |
1584 DCHECK(target_capacity <= maximum_capacity); | 1589 DCHECK(target_capacity <= maximum_capacity); |
1585 initial_total_capacity_ = RoundDown(initial_capacity, Page::kPageSize); | 1590 initial_total_capacity_ = RoundDown(initial_capacity, Page::kPageSize); |
1586 total_capacity_ = initial_capacity; | 1591 total_capacity_ = initial_capacity; |
1587 target_capacity_ = RoundDown(target_capacity, Page::kPageSize); | 1592 target_capacity_ = RoundDown(target_capacity, Page::kPageSize); |
1588 maximum_total_capacity_ = RoundDown(maximum_capacity, Page::kPageSize); | 1593 maximum_total_capacity_ = RoundDown(maximum_capacity, Page::kPageSize); |
1589 maximum_committed_ = 0; | |
1590 committed_ = false; | 1594 committed_ = false; |
1591 start_ = start; | 1595 start_ = start; |
1592 address_mask_ = ~(maximum_capacity - 1); | 1596 address_mask_ = ~(maximum_capacity - 1); |
1593 object_mask_ = address_mask_ | kHeapObjectTagMask; | 1597 object_mask_ = address_mask_ | kHeapObjectTagMask; |
1594 object_expected_ = reinterpret_cast<uintptr_t>(start) | kHeapObjectTag; | 1598 object_expected_ = reinterpret_cast<uintptr_t>(start) | kHeapObjectTag; |
1595 age_mark_ = start_ + NewSpacePage::kObjectStartOffset; | 1599 age_mark_ = start_ + NewSpacePage::kObjectStartOffset; |
1596 } | 1600 } |
1597 | 1601 |
1598 | 1602 |
1599 void SemiSpace::TearDown() { | 1603 void SemiSpace::TearDown() { |
1600 start_ = NULL; | 1604 start_ = NULL; |
1601 total_capacity_ = 0; | 1605 total_capacity_ = 0; |
1602 } | 1606 } |
1603 | 1607 |
1604 | 1608 |
1605 bool SemiSpace::Commit() { | 1609 bool SemiSpace::Commit() { |
1606 DCHECK(!is_committed()); | 1610 DCHECK(!is_committed()); |
1607 int pages = total_capacity_ / Page::kPageSize; | 1611 int pages = total_capacity_ / Page::kPageSize; |
1608 if (!heap()->isolate()->memory_allocator()->CommitBlock( | 1612 if (!heap()->isolate()->memory_allocator()->CommitBlock( |
1609 start_, total_capacity_, executable())) { | 1613 start_, total_capacity_, executable())) { |
1610 return false; | 1614 return false; |
1611 } | 1615 } |
| 1616 AccountCommitted(total_capacity_); |
1612 | 1617 |
1613 NewSpacePage* current = anchor(); | 1618 NewSpacePage* current = anchor(); |
1614 for (int i = 0; i < pages; i++) { | 1619 for (int i = 0; i < pages; i++) { |
1615 NewSpacePage* new_page = | 1620 NewSpacePage* new_page = |
1616 NewSpacePage::Initialize(heap(), start_ + i * Page::kPageSize, this); | 1621 NewSpacePage::Initialize(heap(), start_ + i * Page::kPageSize, this); |
1617 new_page->InsertAfter(current); | 1622 new_page->InsertAfter(current); |
1618 current = new_page; | 1623 current = new_page; |
1619 } | 1624 } |
1620 | 1625 |
1621 SetCapacity(total_capacity_); | 1626 SetCapacity(total_capacity_); |
1622 committed_ = true; | 1627 committed_ = true; |
1623 Reset(); | 1628 Reset(); |
1624 return true; | 1629 return true; |
1625 } | 1630 } |
1626 | 1631 |
1627 | 1632 |
1628 bool SemiSpace::Uncommit() { | 1633 bool SemiSpace::Uncommit() { |
1629 DCHECK(is_committed()); | 1634 DCHECK(is_committed()); |
1630 Address start = start_ + maximum_total_capacity_ - total_capacity_; | 1635 Address start = start_ + maximum_total_capacity_ - total_capacity_; |
1631 if (!heap()->isolate()->memory_allocator()->UncommitBlock(start, | 1636 if (!heap()->isolate()->memory_allocator()->UncommitBlock(start, |
1632 total_capacity_)) { | 1637 total_capacity_)) { |
1633 return false; | 1638 return false; |
1634 } | 1639 } |
| 1640 AccountUncommitted(total_capacity_); |
| 1641 |
1635 anchor()->set_next_page(anchor()); | 1642 anchor()->set_next_page(anchor()); |
1636 anchor()->set_prev_page(anchor()); | 1643 anchor()->set_prev_page(anchor()); |
1637 | 1644 |
1638 committed_ = false; | 1645 committed_ = false; |
1639 return true; | 1646 return true; |
1640 } | 1647 } |
1641 | 1648 |
1642 | 1649 |
1643 size_t SemiSpace::CommittedPhysicalMemory() { | 1650 size_t SemiSpace::CommittedPhysicalMemory() { |
1644 if (!is_committed()) return 0; | 1651 if (!is_committed()) return 0; |
(...skipping 16 matching lines...) Expand all Loading... |
1661 int pages_before = total_capacity_ / Page::kPageSize; | 1668 int pages_before = total_capacity_ / Page::kPageSize; |
1662 int pages_after = new_capacity / Page::kPageSize; | 1669 int pages_after = new_capacity / Page::kPageSize; |
1663 | 1670 |
1664 size_t delta = new_capacity - total_capacity_; | 1671 size_t delta = new_capacity - total_capacity_; |
1665 | 1672 |
1666 DCHECK(IsAligned(delta, base::OS::AllocateAlignment())); | 1673 DCHECK(IsAligned(delta, base::OS::AllocateAlignment())); |
1667 if (!heap()->isolate()->memory_allocator()->CommitBlock( | 1674 if (!heap()->isolate()->memory_allocator()->CommitBlock( |
1668 start_ + total_capacity_, delta, executable())) { | 1675 start_ + total_capacity_, delta, executable())) { |
1669 return false; | 1676 return false; |
1670 } | 1677 } |
| 1678 AccountCommitted(static_cast<intptr_t>(delta)); |
1671 SetCapacity(new_capacity); | 1679 SetCapacity(new_capacity); |
1672 NewSpacePage* last_page = anchor()->prev_page(); | 1680 NewSpacePage* last_page = anchor()->prev_page(); |
1673 DCHECK(last_page != anchor()); | 1681 DCHECK(last_page != anchor()); |
1674 for (int i = pages_before; i < pages_after; i++) { | 1682 for (int i = pages_before; i < pages_after; i++) { |
1675 Address page_address = start_ + i * Page::kPageSize; | 1683 Address page_address = start_ + i * Page::kPageSize; |
1676 NewSpacePage* new_page = | 1684 NewSpacePage* new_page = |
1677 NewSpacePage::Initialize(heap(), page_address, this); | 1685 NewSpacePage::Initialize(heap(), page_address, this); |
1678 new_page->InsertAfter(last_page); | 1686 new_page->InsertAfter(last_page); |
1679 Bitmap::Clear(new_page); | 1687 Bitmap::Clear(new_page); |
1680 // Duplicate the flags that was set on the old page. | 1688 // Duplicate the flags that was set on the old page. |
(...skipping 10 matching lines...) Expand all Loading... |
1691 DCHECK(new_capacity >= initial_total_capacity_); | 1699 DCHECK(new_capacity >= initial_total_capacity_); |
1692 DCHECK(new_capacity < total_capacity_); | 1700 DCHECK(new_capacity < total_capacity_); |
1693 if (is_committed()) { | 1701 if (is_committed()) { |
1694 size_t delta = total_capacity_ - new_capacity; | 1702 size_t delta = total_capacity_ - new_capacity; |
1695 DCHECK(IsAligned(delta, base::OS::AllocateAlignment())); | 1703 DCHECK(IsAligned(delta, base::OS::AllocateAlignment())); |
1696 | 1704 |
1697 MemoryAllocator* allocator = heap()->isolate()->memory_allocator(); | 1705 MemoryAllocator* allocator = heap()->isolate()->memory_allocator(); |
1698 if (!allocator->UncommitBlock(start_ + new_capacity, delta)) { | 1706 if (!allocator->UncommitBlock(start_ + new_capacity, delta)) { |
1699 return false; | 1707 return false; |
1700 } | 1708 } |
| 1709 AccountUncommitted(static_cast<intptr_t>(delta)); |
1701 | 1710 |
1702 int pages_after = new_capacity / Page::kPageSize; | 1711 int pages_after = new_capacity / Page::kPageSize; |
1703 NewSpacePage* new_last_page = | 1712 NewSpacePage* new_last_page = |
1704 NewSpacePage::FromAddress(start_ + (pages_after - 1) * Page::kPageSize); | 1713 NewSpacePage::FromAddress(start_ + (pages_after - 1) * Page::kPageSize); |
1705 new_last_page->set_next_page(anchor()); | 1714 new_last_page->set_next_page(anchor()); |
1706 anchor()->set_prev_page(new_last_page); | 1715 anchor()->set_prev_page(new_last_page); |
1707 DCHECK((current_page_ >= first_page()) && (current_page_ <= new_last_page)); | 1716 DCHECK((current_page_ >= first_page()) && (current_page_ <= new_last_page)); |
1708 } | 1717 } |
1709 | 1718 |
1710 SetCapacity(new_capacity); | 1719 SetCapacity(new_capacity); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1776 // Copy GC flags from old active space (from-space) to new (to-space). | 1785 // Copy GC flags from old active space (from-space) to new (to-space). |
1777 intptr_t flags = from->current_page()->GetFlags(); | 1786 intptr_t flags = from->current_page()->GetFlags(); |
1778 to->FlipPages(flags, NewSpacePage::kCopyOnFlipFlagsMask); | 1787 to->FlipPages(flags, NewSpacePage::kCopyOnFlipFlagsMask); |
1779 | 1788 |
1780 from->FlipPages(0, 0); | 1789 from->FlipPages(0, 0); |
1781 } | 1790 } |
1782 | 1791 |
1783 | 1792 |
1784 void SemiSpace::SetCapacity(int new_capacity) { | 1793 void SemiSpace::SetCapacity(int new_capacity) { |
1785 total_capacity_ = new_capacity; | 1794 total_capacity_ = new_capacity; |
1786 if (total_capacity_ > maximum_committed_) { | |
1787 maximum_committed_ = total_capacity_; | |
1788 } | |
1789 } | 1795 } |
1790 | 1796 |
1791 | 1797 |
1792 void SemiSpace::set_age_mark(Address mark) { | 1798 void SemiSpace::set_age_mark(Address mark) { |
1793 DCHECK(NewSpacePage::FromLimit(mark)->semi_space() == this); | 1799 DCHECK(NewSpacePage::FromLimit(mark)->semi_space() == this); |
1794 age_mark_ = mark; | 1800 age_mark_ = mark; |
1795 // Mark all pages up to the one containing mark. | 1801 // Mark all pages up to the one containing mark. |
1796 NewSpacePageIterator it(space_start(), mark); | 1802 NewSpacePageIterator it(space_start(), mark); |
1797 while (it.has_next()) { | 1803 while (it.has_next()) { |
1798 it.next()->SetFlag(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK); | 1804 it.next()->SetFlag(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK); |
(...skipping 1057 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2856 objects_size_(0), | 2862 objects_size_(0), |
2857 chunk_map_(ComparePointers, 1024) {} | 2863 chunk_map_(ComparePointers, 1024) {} |
2858 | 2864 |
2859 | 2865 |
2860 LargeObjectSpace::~LargeObjectSpace() {} | 2866 LargeObjectSpace::~LargeObjectSpace() {} |
2861 | 2867 |
2862 | 2868 |
2863 bool LargeObjectSpace::SetUp() { | 2869 bool LargeObjectSpace::SetUp() { |
2864 first_page_ = NULL; | 2870 first_page_ = NULL; |
2865 size_ = 0; | 2871 size_ = 0; |
2866 maximum_committed_ = 0; | |
2867 page_count_ = 0; | 2872 page_count_ = 0; |
2868 objects_size_ = 0; | 2873 objects_size_ = 0; |
2869 chunk_map_.Clear(); | 2874 chunk_map_.Clear(); |
2870 return true; | 2875 return true; |
2871 } | 2876 } |
2872 | 2877 |
2873 | 2878 |
2874 void LargeObjectSpace::TearDown() { | 2879 void LargeObjectSpace::TearDown() { |
2875 while (first_page_ != NULL) { | 2880 while (first_page_ != NULL) { |
2876 LargePage* page = first_page_; | 2881 LargePage* page = first_page_; |
(...skipping 17 matching lines...) Expand all Loading... |
2894 !heap()->CanExpandOldGeneration(object_size)) { | 2899 !heap()->CanExpandOldGeneration(object_size)) { |
2895 return AllocationResult::Retry(identity()); | 2900 return AllocationResult::Retry(identity()); |
2896 } | 2901 } |
2897 | 2902 |
2898 LargePage* page = heap()->isolate()->memory_allocator()->AllocateLargePage( | 2903 LargePage* page = heap()->isolate()->memory_allocator()->AllocateLargePage( |
2899 object_size, this, executable); | 2904 object_size, this, executable); |
2900 if (page == NULL) return AllocationResult::Retry(identity()); | 2905 if (page == NULL) return AllocationResult::Retry(identity()); |
2901 DCHECK(page->area_size() >= object_size); | 2906 DCHECK(page->area_size() >= object_size); |
2902 | 2907 |
2903 size_ += static_cast<int>(page->size()); | 2908 size_ += static_cast<int>(page->size()); |
| 2909 AccountCommitted(static_cast<intptr_t>(page->size())); |
2904 objects_size_ += object_size; | 2910 objects_size_ += object_size; |
2905 page_count_++; | 2911 page_count_++; |
2906 page->set_next_page(first_page_); | 2912 page->set_next_page(first_page_); |
2907 first_page_ = page; | 2913 first_page_ = page; |
2908 | 2914 |
2909 if (size_ > maximum_committed_) { | |
2910 maximum_committed_ = size_; | |
2911 } | |
2912 | |
2913 // Register all MemoryChunk::kAlignment-aligned chunks covered by | 2915 // Register all MemoryChunk::kAlignment-aligned chunks covered by |
2914 // this large page in the chunk map. | 2916 // this large page in the chunk map. |
2915 uintptr_t base = reinterpret_cast<uintptr_t>(page) / MemoryChunk::kAlignment; | 2917 uintptr_t base = reinterpret_cast<uintptr_t>(page) / MemoryChunk::kAlignment; |
2916 uintptr_t limit = base + (page->size() - 1) / MemoryChunk::kAlignment; | 2918 uintptr_t limit = base + (page->size() - 1) / MemoryChunk::kAlignment; |
2917 for (uintptr_t key = base; key <= limit; key++) { | 2919 for (uintptr_t key = base; key <= limit; key++) { |
2918 HashMap::Entry* entry = chunk_map_.LookupOrInsert( | 2920 HashMap::Entry* entry = chunk_map_.LookupOrInsert( |
2919 reinterpret_cast<void*>(key), static_cast<uint32_t>(key)); | 2921 reinterpret_cast<void*>(key), static_cast<uint32_t>(key)); |
2920 DCHECK(entry != NULL); | 2922 DCHECK(entry != NULL); |
2921 entry->value = page; | 2923 entry->value = page; |
2922 } | 2924 } |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3006 if (previous == NULL) { | 3008 if (previous == NULL) { |
3007 first_page_ = current; | 3009 first_page_ = current; |
3008 } else { | 3010 } else { |
3009 previous->set_next_page(current); | 3011 previous->set_next_page(current); |
3010 } | 3012 } |
3011 | 3013 |
3012 // Free the chunk. | 3014 // Free the chunk. |
3013 heap()->mark_compact_collector()->ReportDeleteIfNeeded(object, | 3015 heap()->mark_compact_collector()->ReportDeleteIfNeeded(object, |
3014 heap()->isolate()); | 3016 heap()->isolate()); |
3015 size_ -= static_cast<int>(page->size()); | 3017 size_ -= static_cast<int>(page->size()); |
| 3018 AccountUncommitted(static_cast<intptr_t>(page->size())); |
3016 objects_size_ -= object->Size(); | 3019 objects_size_ -= object->Size(); |
3017 page_count_--; | 3020 page_count_--; |
3018 | 3021 |
3019 // Remove entries belonging to this page. | 3022 // Remove entries belonging to this page. |
3020 // Use variable alignment to help pass length check (<= 80 characters) | 3023 // Use variable alignment to help pass length check (<= 80 characters) |
3021 // of single line in tools/presubmit.py. | 3024 // of single line in tools/presubmit.py. |
3022 const intptr_t alignment = MemoryChunk::kAlignment; | 3025 const intptr_t alignment = MemoryChunk::kAlignment; |
3023 uintptr_t base = reinterpret_cast<uintptr_t>(page) / alignment; | 3026 uintptr_t base = reinterpret_cast<uintptr_t>(page) / alignment; |
3024 uintptr_t limit = base + (page->size() - 1) / alignment; | 3027 uintptr_t limit = base + (page->size() - 1) / alignment; |
3025 for (uintptr_t key = base; key <= limit; key++) { | 3028 for (uintptr_t key = base; key <= limit; key++) { |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3161 object->ShortPrint(); | 3164 object->ShortPrint(); |
3162 PrintF("\n"); | 3165 PrintF("\n"); |
3163 } | 3166 } |
3164 printf(" --------------------------------------\n"); | 3167 printf(" --------------------------------------\n"); |
3165 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3168 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
3166 } | 3169 } |
3167 | 3170 |
3168 #endif // DEBUG | 3171 #endif // DEBUG |
3169 } // namespace internal | 3172 } // namespace internal |
3170 } // namespace v8 | 3173 } // namespace v8 |
OLD | NEW |