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 1066 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1077 if (!base::VirtualMemory::HasLazyCommits()) return CommittedMemory(); | 1077 if (!base::VirtualMemory::HasLazyCommits()) return CommittedMemory(); |
1078 MemoryChunk::UpdateHighWaterMark(allocation_info_.top()); | 1078 MemoryChunk::UpdateHighWaterMark(allocation_info_.top()); |
1079 size_t size = 0; | 1079 size_t size = 0; |
1080 PageIterator it(this); | 1080 PageIterator it(this); |
1081 while (it.has_next()) { | 1081 while (it.has_next()) { |
1082 size += it.next()->CommittedPhysicalMemory(); | 1082 size += it.next()->CommittedPhysicalMemory(); |
1083 } | 1083 } |
1084 return size; | 1084 return size; |
1085 } | 1085 } |
1086 | 1086 |
1087 | 1087 bool PagedSpace::ContainsSlow(Address addr) { |
1088 bool PagedSpace::ContainsSafe(Address addr) { | |
1089 Page* p = Page::FromAddress(addr); | 1088 Page* p = Page::FromAddress(addr); |
1090 PageIterator iterator(this); | 1089 PageIterator iterator(this); |
1091 while (iterator.has_next()) { | 1090 while (iterator.has_next()) { |
1092 if (iterator.next() == p) return true; | 1091 if (iterator.next() == p) return true; |
1093 } | 1092 } |
1094 return false; | 1093 return false; |
1095 } | 1094 } |
1096 | 1095 |
1097 | 1096 |
1098 Object* PagedSpace::FindObject(Address addr) { | 1097 Object* PagedSpace::FindObject(Address addr) { |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1305 to_space_.SetUp(chunk_base_, initial_semispace_capacity, | 1304 to_space_.SetUp(chunk_base_, initial_semispace_capacity, |
1306 maximum_semispace_capacity); | 1305 maximum_semispace_capacity); |
1307 from_space_.SetUp(chunk_base_ + reserved_semispace_capacity, | 1306 from_space_.SetUp(chunk_base_ + reserved_semispace_capacity, |
1308 initial_semispace_capacity, maximum_semispace_capacity); | 1307 initial_semispace_capacity, maximum_semispace_capacity); |
1309 if (!to_space_.Commit()) { | 1308 if (!to_space_.Commit()) { |
1310 return false; | 1309 return false; |
1311 } | 1310 } |
1312 DCHECK(!from_space_.is_committed()); // No need to use memory yet. | 1311 DCHECK(!from_space_.is_committed()); // No need to use memory yet. |
1313 | 1312 |
1314 start_ = chunk_base_; | 1313 start_ = chunk_base_; |
1315 address_mask_ = ~(2 * reserved_semispace_capacity - 1); | |
1316 object_mask_ = address_mask_ | kHeapObjectTagMask; | |
1317 object_expected_ = reinterpret_cast<uintptr_t>(start_) | kHeapObjectTag; | |
1318 | 1314 |
1319 ResetAllocationInfo(); | 1315 ResetAllocationInfo(); |
1320 | 1316 |
1321 return true; | 1317 return true; |
1322 } | 1318 } |
1323 | 1319 |
1324 | 1320 |
1325 void NewSpace::TearDown() { | 1321 void NewSpace::TearDown() { |
1326 if (allocated_histogram_) { | 1322 if (allocated_histogram_) { |
1327 DeleteArray(allocated_histogram_); | 1323 DeleteArray(allocated_histogram_); |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1668 // SemiSpace implementation | 1664 // SemiSpace implementation |
1669 | 1665 |
1670 void SemiSpace::SetUp(Address start, int initial_capacity, | 1666 void SemiSpace::SetUp(Address start, int initial_capacity, |
1671 int maximum_capacity) { | 1667 int maximum_capacity) { |
1672 DCHECK_GE(maximum_capacity, Page::kPageSize); | 1668 DCHECK_GE(maximum_capacity, Page::kPageSize); |
1673 minimum_capacity_ = RoundDown(initial_capacity, Page::kPageSize); | 1669 minimum_capacity_ = RoundDown(initial_capacity, Page::kPageSize); |
1674 current_capacity_ = minimum_capacity_; | 1670 current_capacity_ = minimum_capacity_; |
1675 maximum_capacity_ = RoundDown(maximum_capacity, Page::kPageSize); | 1671 maximum_capacity_ = RoundDown(maximum_capacity, Page::kPageSize); |
1676 committed_ = false; | 1672 committed_ = false; |
1677 start_ = start; | 1673 start_ = start; |
1678 address_mask_ = ~(maximum_capacity_ - 1); | |
1679 object_mask_ = address_mask_ | kHeapObjectTagMask; | |
1680 object_expected_ = reinterpret_cast<uintptr_t>(start) | kHeapObjectTag; | |
1681 age_mark_ = start_ + NewSpacePage::kObjectStartOffset; | 1674 age_mark_ = start_ + NewSpacePage::kObjectStartOffset; |
1682 } | 1675 } |
1683 | 1676 |
1684 | 1677 |
1685 void SemiSpace::TearDown() { | 1678 void SemiSpace::TearDown() { |
1686 start_ = nullptr; | 1679 start_ = nullptr; |
1687 current_capacity_ = 0; | 1680 current_capacity_ = 0; |
1688 } | 1681 } |
1689 | 1682 |
1690 | 1683 |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1796 new_last_page->set_next_page(anchor()); | 1789 new_last_page->set_next_page(anchor()); |
1797 anchor()->set_prev_page(new_last_page); | 1790 anchor()->set_prev_page(new_last_page); |
1798 DCHECK((current_page_ >= first_page()) && (current_page_ <= new_last_page)); | 1791 DCHECK((current_page_ >= first_page()) && (current_page_ <= new_last_page)); |
1799 } | 1792 } |
1800 | 1793 |
1801 set_current_capacity(new_capacity); | 1794 set_current_capacity(new_capacity); |
1802 | 1795 |
1803 return true; | 1796 return true; |
1804 } | 1797 } |
1805 | 1798 |
1806 | 1799 void SemiSpace::FixPagesFlags(intptr_t flags, intptr_t mask) { |
1807 void SemiSpace::FlipPages(intptr_t flags, intptr_t mask) { | |
1808 anchor_.set_owner(this); | 1800 anchor_.set_owner(this); |
1809 // Fixup back-pointers to anchor. Address of anchor changes when we swap. | 1801 // Fixup back-pointers to anchor. Address of anchor changes when we swap. |
1810 anchor_.prev_page()->set_next_page(&anchor_); | 1802 anchor_.prev_page()->set_next_page(&anchor_); |
1811 anchor_.next_page()->set_prev_page(&anchor_); | 1803 anchor_.next_page()->set_prev_page(&anchor_); |
1812 | 1804 |
1813 bool becomes_to_space = (id_ == kFromSpace); | |
1814 id_ = becomes_to_space ? kToSpace : kFromSpace; | |
1815 NewSpacePageIterator it(this); | 1805 NewSpacePageIterator it(this); |
1816 while (it.has_next()) { | 1806 while (it.has_next()) { |
1817 NewSpacePage* page = it.next(); | 1807 NewSpacePage* page = it.next(); |
1818 page->set_owner(this); | 1808 page->set_owner(this); |
1819 page->SetFlags(flags, mask); | 1809 page->SetFlags(flags, mask); |
1820 if (becomes_to_space) { | 1810 if (id_ == kToSpace) { |
1821 page->ClearFlag(MemoryChunk::IN_FROM_SPACE); | 1811 page->ClearFlag(MemoryChunk::IN_FROM_SPACE); |
1822 page->SetFlag(MemoryChunk::IN_TO_SPACE); | 1812 page->SetFlag(MemoryChunk::IN_TO_SPACE); |
1823 page->ClearFlag(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK); | 1813 page->ClearFlag(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK); |
1824 page->ResetLiveBytes(); | 1814 page->ResetLiveBytes(); |
1825 } else { | 1815 } else { |
1826 page->SetFlag(MemoryChunk::IN_FROM_SPACE); | 1816 page->SetFlag(MemoryChunk::IN_FROM_SPACE); |
1827 page->ClearFlag(MemoryChunk::IN_TO_SPACE); | 1817 page->ClearFlag(MemoryChunk::IN_TO_SPACE); |
1828 } | 1818 } |
1829 DCHECK(page->IsFlagSet(MemoryChunk::SCAN_ON_SCAVENGE)); | 1819 DCHECK(page->IsFlagSet(MemoryChunk::SCAN_ON_SCAVENGE)); |
1830 DCHECK(page->IsFlagSet(MemoryChunk::IN_TO_SPACE) || | 1820 DCHECK(page->IsFlagSet(MemoryChunk::IN_TO_SPACE) || |
1831 page->IsFlagSet(MemoryChunk::IN_FROM_SPACE)); | 1821 page->IsFlagSet(MemoryChunk::IN_FROM_SPACE)); |
1832 } | 1822 } |
1833 } | 1823 } |
1834 | 1824 |
1835 | 1825 |
1836 void SemiSpace::Reset() { | 1826 void SemiSpace::Reset() { |
1837 DCHECK_NE(anchor_.next_page(), &anchor_); | 1827 DCHECK_NE(anchor_.next_page(), &anchor_); |
1838 current_page_ = anchor_.next_page(); | 1828 current_page_ = anchor_.next_page(); |
1839 } | 1829 } |
1840 | 1830 |
1841 | 1831 |
1842 void SemiSpace::Swap(SemiSpace* from, SemiSpace* to) { | 1832 void SemiSpace::Swap(SemiSpace* from, SemiSpace* to) { |
1843 // We won't be swapping semispaces without data in them. | 1833 // We won't be swapping semispaces without data in them. |
1844 DCHECK_NE(from->anchor_.next_page(), &from->anchor_); | 1834 DCHECK_NE(from->anchor_.next_page(), &from->anchor_); |
1845 DCHECK_NE(to->anchor_.next_page(), &to->anchor_); | 1835 DCHECK_NE(to->anchor_.next_page(), &to->anchor_); |
1846 | 1836 |
1847 // Swap bits. | 1837 intptr_t saved_to_space_flags = to->current_page()->GetFlags(); |
1848 SemiSpace tmp = *from; | |
1849 *from = *to; | |
1850 *to = tmp; | |
1851 | 1838 |
1852 // Fixup back-pointers to the page list anchor now that its address | 1839 // We swap all properties but id_. |
1853 // has changed. | 1840 std::swap(from->current_capacity_, to->current_capacity_); |
1854 // Swap to/from-space bits on pages. | 1841 std::swap(from->maximum_capacity_, to->maximum_capacity_); |
1855 // Copy GC flags from old active space (from-space) to new (to-space). | 1842 std::swap(from->minimum_capacity_, to->minimum_capacity_); |
1856 intptr_t flags = from->current_page()->GetFlags(); | 1843 std::swap(from->start_, to->start_); |
1857 to->FlipPages(flags, NewSpacePage::kCopyOnFlipFlagsMask); | 1844 std::swap(from->age_mark_, to->age_mark_); |
| 1845 std::swap(from->committed_, to->committed_); |
| 1846 std::swap(from->anchor_, to->anchor_); |
| 1847 std::swap(from->current_page_, to->current_page_); |
1858 | 1848 |
1859 from->FlipPages(0, 0); | 1849 to->FixPagesFlags(saved_to_space_flags, NewSpacePage::kCopyOnFlipFlagsMask); |
| 1850 from->FixPagesFlags(0, 0); |
1860 } | 1851 } |
1861 | 1852 |
1862 | 1853 |
1863 void SemiSpace::set_age_mark(Address mark) { | 1854 void SemiSpace::set_age_mark(Address mark) { |
1864 DCHECK_EQ(NewSpacePage::FromLimit(mark)->semi_space(), this); | 1855 DCHECK_EQ(NewSpacePage::FromLimit(mark)->semi_space(), this); |
1865 age_mark_ = mark; | 1856 age_mark_ = mark; |
1866 // Mark all pages up to the one containing mark. | 1857 // Mark all pages up to the one containing mark. |
1867 NewSpacePageIterator it(space_start(), mark); | 1858 NewSpacePageIterator it(space_start(), mark); |
1868 while (it.has_next()) { | 1859 while (it.has_next()) { |
1869 it.next()->SetFlag(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK); | 1860 it.next()->SetFlag(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK); |
(...skipping 1250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3120 MemoryChunk* chunk = MemoryChunk::FromAddress(address); | 3111 MemoryChunk* chunk = MemoryChunk::FromAddress(address); |
3121 | 3112 |
3122 bool owned = (chunk->owner() == this); | 3113 bool owned = (chunk->owner() == this); |
3123 | 3114 |
3124 SLOW_DCHECK(!owned || FindObject(address)->IsHeapObject()); | 3115 SLOW_DCHECK(!owned || FindObject(address)->IsHeapObject()); |
3125 | 3116 |
3126 return owned; | 3117 return owned; |
3127 } | 3118 } |
3128 | 3119 |
3129 | 3120 |
3130 bool LargeObjectSpace::Contains(Address address) { | |
3131 return FindPage(address) != NULL; | |
3132 } | |
3133 | |
3134 | |
3135 #ifdef VERIFY_HEAP | 3121 #ifdef VERIFY_HEAP |
3136 // We do not assume that the large object iterator works, because it depends | 3122 // We do not assume that the large object iterator works, because it depends |
3137 // on the invariants we are checking during verification. | 3123 // on the invariants we are checking during verification. |
3138 void LargeObjectSpace::Verify() { | 3124 void LargeObjectSpace::Verify() { |
3139 for (LargePage* chunk = first_page_; chunk != NULL; | 3125 for (LargePage* chunk = first_page_; chunk != NULL; |
3140 chunk = chunk->next_page()) { | 3126 chunk = chunk->next_page()) { |
3141 // Each chunk contains an object that starts at the large object page's | 3127 // Each chunk contains an object that starts at the large object page's |
3142 // object area start. | 3128 // object area start. |
3143 HeapObject* object = chunk->GetObject(); | 3129 HeapObject* object = chunk->GetObject(); |
3144 Page* page = Page::FromAddress(object->address()); | 3130 Page* page = Page::FromAddress(object->address()); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3238 object->ShortPrint(); | 3224 object->ShortPrint(); |
3239 PrintF("\n"); | 3225 PrintF("\n"); |
3240 } | 3226 } |
3241 printf(" --------------------------------------\n"); | 3227 printf(" --------------------------------------\n"); |
3242 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3228 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
3243 } | 3229 } |
3244 | 3230 |
3245 #endif // DEBUG | 3231 #endif // DEBUG |
3246 } // namespace internal | 3232 } // namespace internal |
3247 } // namespace v8 | 3233 } // namespace v8 |
OLD | NEW |