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/slot-set.h" | 10 #include "src/heap/slot-set.h" |
(...skipping 1083 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1094 if (!base::VirtualMemory::HasLazyCommits()) return CommittedMemory(); | 1094 if (!base::VirtualMemory::HasLazyCommits()) return CommittedMemory(); |
1095 MemoryChunk::UpdateHighWaterMark(allocation_info_.top()); | 1095 MemoryChunk::UpdateHighWaterMark(allocation_info_.top()); |
1096 size_t size = 0; | 1096 size_t size = 0; |
1097 PageIterator it(this); | 1097 PageIterator it(this); |
1098 while (it.has_next()) { | 1098 while (it.has_next()) { |
1099 size += it.next()->CommittedPhysicalMemory(); | 1099 size += it.next()->CommittedPhysicalMemory(); |
1100 } | 1100 } |
1101 return size; | 1101 return size; |
1102 } | 1102 } |
1103 | 1103 |
1104 | 1104 bool PagedSpace::ContainsSlow(Address addr) { |
1105 bool PagedSpace::ContainsSafe(Address addr) { | |
1106 Page* p = Page::FromAddress(addr); | 1105 Page* p = Page::FromAddress(addr); |
1107 PageIterator iterator(this); | 1106 PageIterator iterator(this); |
1108 while (iterator.has_next()) { | 1107 while (iterator.has_next()) { |
1109 if (iterator.next() == p) return true; | 1108 if (iterator.next() == p) return true; |
1110 } | 1109 } |
1111 return false; | 1110 return false; |
1112 } | 1111 } |
1113 | 1112 |
1114 | 1113 |
1115 Object* PagedSpace::FindObject(Address addr) { | 1114 Object* PagedSpace::FindObject(Address addr) { |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1317 to_space_.SetUp(chunk_base_, initial_semispace_capacity, | 1316 to_space_.SetUp(chunk_base_, initial_semispace_capacity, |
1318 maximum_semispace_capacity); | 1317 maximum_semispace_capacity); |
1319 from_space_.SetUp(chunk_base_ + reserved_semispace_capacity, | 1318 from_space_.SetUp(chunk_base_ + reserved_semispace_capacity, |
1320 initial_semispace_capacity, maximum_semispace_capacity); | 1319 initial_semispace_capacity, maximum_semispace_capacity); |
1321 if (!to_space_.Commit()) { | 1320 if (!to_space_.Commit()) { |
1322 return false; | 1321 return false; |
1323 } | 1322 } |
1324 DCHECK(!from_space_.is_committed()); // No need to use memory yet. | 1323 DCHECK(!from_space_.is_committed()); // No need to use memory yet. |
1325 | 1324 |
1326 start_ = chunk_base_; | 1325 start_ = chunk_base_; |
1327 address_mask_ = ~(2 * reserved_semispace_capacity - 1); | |
1328 object_mask_ = address_mask_ | kHeapObjectTagMask; | |
1329 object_expected_ = reinterpret_cast<uintptr_t>(start_) | kHeapObjectTag; | |
1330 | 1326 |
1331 ResetAllocationInfo(); | 1327 ResetAllocationInfo(); |
1332 | 1328 |
1333 return true; | 1329 return true; |
1334 } | 1330 } |
1335 | 1331 |
1336 | 1332 |
1337 void NewSpace::TearDown() { | 1333 void NewSpace::TearDown() { |
1338 if (allocated_histogram_) { | 1334 if (allocated_histogram_) { |
1339 DeleteArray(allocated_histogram_); | 1335 DeleteArray(allocated_histogram_); |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1680 // SemiSpace implementation | 1676 // SemiSpace implementation |
1681 | 1677 |
1682 void SemiSpace::SetUp(Address start, int initial_capacity, | 1678 void SemiSpace::SetUp(Address start, int initial_capacity, |
1683 int maximum_capacity) { | 1679 int maximum_capacity) { |
1684 DCHECK_GE(maximum_capacity, Page::kPageSize); | 1680 DCHECK_GE(maximum_capacity, Page::kPageSize); |
1685 minimum_capacity_ = RoundDown(initial_capacity, Page::kPageSize); | 1681 minimum_capacity_ = RoundDown(initial_capacity, Page::kPageSize); |
1686 current_capacity_ = minimum_capacity_; | 1682 current_capacity_ = minimum_capacity_; |
1687 maximum_capacity_ = RoundDown(maximum_capacity, Page::kPageSize); | 1683 maximum_capacity_ = RoundDown(maximum_capacity, Page::kPageSize); |
1688 committed_ = false; | 1684 committed_ = false; |
1689 start_ = start; | 1685 start_ = start; |
1690 address_mask_ = ~(maximum_capacity_ - 1); | |
1691 object_mask_ = address_mask_ | kHeapObjectTagMask; | |
1692 object_expected_ = reinterpret_cast<uintptr_t>(start) | kHeapObjectTag; | |
1693 age_mark_ = start_ + NewSpacePage::kObjectStartOffset; | 1686 age_mark_ = start_ + NewSpacePage::kObjectStartOffset; |
1694 } | 1687 } |
1695 | 1688 |
1696 | 1689 |
1697 void SemiSpace::TearDown() { | 1690 void SemiSpace::TearDown() { |
1698 start_ = nullptr; | 1691 start_ = nullptr; |
1699 current_capacity_ = 0; | 1692 current_capacity_ = 0; |
1700 } | 1693 } |
1701 | 1694 |
1702 | 1695 |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1808 new_last_page->set_next_page(anchor()); | 1801 new_last_page->set_next_page(anchor()); |
1809 anchor()->set_prev_page(new_last_page); | 1802 anchor()->set_prev_page(new_last_page); |
1810 DCHECK((current_page_ >= first_page()) && (current_page_ <= new_last_page)); | 1803 DCHECK((current_page_ >= first_page()) && (current_page_ <= new_last_page)); |
1811 } | 1804 } |
1812 | 1805 |
1813 set_current_capacity(new_capacity); | 1806 set_current_capacity(new_capacity); |
1814 | 1807 |
1815 return true; | 1808 return true; |
1816 } | 1809 } |
1817 | 1810 |
1818 | 1811 void SemiSpace::FixPagesFlags(intptr_t flags, intptr_t mask) { |
1819 void SemiSpace::FlipPages(intptr_t flags, intptr_t mask) { | |
1820 anchor_.set_owner(this); | 1812 anchor_.set_owner(this); |
1821 // Fixup back-pointers to anchor. Address of anchor changes when we swap. | 1813 // Fixup back-pointers to anchor. Address of anchor changes when we swap. |
1822 anchor_.prev_page()->set_next_page(&anchor_); | 1814 anchor_.prev_page()->set_next_page(&anchor_); |
1823 anchor_.next_page()->set_prev_page(&anchor_); | 1815 anchor_.next_page()->set_prev_page(&anchor_); |
1824 | 1816 |
1825 bool becomes_to_space = (id_ == kFromSpace); | |
1826 id_ = becomes_to_space ? kToSpace : kFromSpace; | |
1827 NewSpacePageIterator it(this); | 1817 NewSpacePageIterator it(this); |
1828 while (it.has_next()) { | 1818 while (it.has_next()) { |
1829 NewSpacePage* page = it.next(); | 1819 NewSpacePage* page = it.next(); |
1830 page->set_owner(this); | 1820 page->set_owner(this); |
1831 page->SetFlags(flags, mask); | 1821 page->SetFlags(flags, mask); |
1832 if (becomes_to_space) { | 1822 if (id_ == kToSpace) { |
1833 page->ClearFlag(MemoryChunk::IN_FROM_SPACE); | 1823 page->ClearFlag(MemoryChunk::IN_FROM_SPACE); |
1834 page->SetFlag(MemoryChunk::IN_TO_SPACE); | 1824 page->SetFlag(MemoryChunk::IN_TO_SPACE); |
1835 page->ClearFlag(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK); | 1825 page->ClearFlag(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK); |
1836 page->ResetLiveBytes(); | 1826 page->ResetLiveBytes(); |
1837 } else { | 1827 } else { |
1838 page->SetFlag(MemoryChunk::IN_FROM_SPACE); | 1828 page->SetFlag(MemoryChunk::IN_FROM_SPACE); |
1839 page->ClearFlag(MemoryChunk::IN_TO_SPACE); | 1829 page->ClearFlag(MemoryChunk::IN_TO_SPACE); |
1840 } | 1830 } |
1841 DCHECK(page->IsFlagSet(MemoryChunk::IN_TO_SPACE) || | 1831 DCHECK(page->IsFlagSet(MemoryChunk::IN_TO_SPACE) || |
1842 page->IsFlagSet(MemoryChunk::IN_FROM_SPACE)); | 1832 page->IsFlagSet(MemoryChunk::IN_FROM_SPACE)); |
1843 } | 1833 } |
1844 } | 1834 } |
1845 | 1835 |
1846 | 1836 |
1847 void SemiSpace::Reset() { | 1837 void SemiSpace::Reset() { |
1848 DCHECK_NE(anchor_.next_page(), &anchor_); | 1838 DCHECK_NE(anchor_.next_page(), &anchor_); |
1849 current_page_ = anchor_.next_page(); | 1839 current_page_ = anchor_.next_page(); |
1850 } | 1840 } |
1851 | 1841 |
1852 | 1842 |
1853 void SemiSpace::Swap(SemiSpace* from, SemiSpace* to) { | 1843 void SemiSpace::Swap(SemiSpace* from, SemiSpace* to) { |
1854 // We won't be swapping semispaces without data in them. | 1844 // We won't be swapping semispaces without data in them. |
1855 DCHECK_NE(from->anchor_.next_page(), &from->anchor_); | 1845 DCHECK_NE(from->anchor_.next_page(), &from->anchor_); |
1856 DCHECK_NE(to->anchor_.next_page(), &to->anchor_); | 1846 DCHECK_NE(to->anchor_.next_page(), &to->anchor_); |
1857 | 1847 |
1858 // Swap bits. | 1848 intptr_t saved_to_space_flags = to->current_page()->GetFlags(); |
1859 SemiSpace tmp = *from; | |
1860 *from = *to; | |
1861 *to = tmp; | |
1862 | 1849 |
1863 // Fixup back-pointers to the page list anchor now that its address | 1850 // We swap all properties but id_. |
1864 // has changed. | 1851 std::swap(from->current_capacity_, to->current_capacity_); |
1865 // Swap to/from-space bits on pages. | 1852 std::swap(from->maximum_capacity_, to->maximum_capacity_); |
1866 // Copy GC flags from old active space (from-space) to new (to-space). | 1853 std::swap(from->minimum_capacity_, to->minimum_capacity_); |
1867 intptr_t flags = from->current_page()->GetFlags(); | 1854 std::swap(from->start_, to->start_); |
1868 to->FlipPages(flags, NewSpacePage::kCopyOnFlipFlagsMask); | 1855 std::swap(from->age_mark_, to->age_mark_); |
| 1856 std::swap(from->committed_, to->committed_); |
| 1857 std::swap(from->anchor_, to->anchor_); |
| 1858 std::swap(from->current_page_, to->current_page_); |
1869 | 1859 |
1870 from->FlipPages(0, 0); | 1860 to->FixPagesFlags(saved_to_space_flags, NewSpacePage::kCopyOnFlipFlagsMask); |
| 1861 from->FixPagesFlags(0, 0); |
1871 } | 1862 } |
1872 | 1863 |
1873 | 1864 |
1874 void SemiSpace::set_age_mark(Address mark) { | 1865 void SemiSpace::set_age_mark(Address mark) { |
1875 DCHECK_EQ(NewSpacePage::FromLimit(mark)->semi_space(), this); | 1866 DCHECK_EQ(NewSpacePage::FromLimit(mark)->semi_space(), this); |
1876 age_mark_ = mark; | 1867 age_mark_ = mark; |
1877 // Mark all pages up to the one containing mark. | 1868 // Mark all pages up to the one containing mark. |
1878 NewSpacePageIterator it(space_start(), mark); | 1869 NewSpacePageIterator it(space_start(), mark); |
1879 while (it.has_next()) { | 1870 while (it.has_next()) { |
1880 it.next()->SetFlag(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK); | 1871 it.next()->SetFlag(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK); |
(...skipping 1249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3130 MemoryChunk* chunk = MemoryChunk::FromAddress(address); | 3121 MemoryChunk* chunk = MemoryChunk::FromAddress(address); |
3131 | 3122 |
3132 bool owned = (chunk->owner() == this); | 3123 bool owned = (chunk->owner() == this); |
3133 | 3124 |
3134 SLOW_DCHECK(!owned || FindObject(address)->IsHeapObject()); | 3125 SLOW_DCHECK(!owned || FindObject(address)->IsHeapObject()); |
3135 | 3126 |
3136 return owned; | 3127 return owned; |
3137 } | 3128 } |
3138 | 3129 |
3139 | 3130 |
3140 bool LargeObjectSpace::Contains(Address address) { | |
3141 return FindPage(address) != NULL; | |
3142 } | |
3143 | |
3144 | |
3145 #ifdef VERIFY_HEAP | 3131 #ifdef VERIFY_HEAP |
3146 // We do not assume that the large object iterator works, because it depends | 3132 // We do not assume that the large object iterator works, because it depends |
3147 // on the invariants we are checking during verification. | 3133 // on the invariants we are checking during verification. |
3148 void LargeObjectSpace::Verify() { | 3134 void LargeObjectSpace::Verify() { |
3149 for (LargePage* chunk = first_page_; chunk != NULL; | 3135 for (LargePage* chunk = first_page_; chunk != NULL; |
3150 chunk = chunk->next_page()) { | 3136 chunk = chunk->next_page()) { |
3151 // Each chunk contains an object that starts at the large object page's | 3137 // Each chunk contains an object that starts at the large object page's |
3152 // object area start. | 3138 // object area start. |
3153 HeapObject* object = chunk->GetObject(); | 3139 HeapObject* object = chunk->GetObject(); |
3154 Page* page = Page::FromAddress(object->address()); | 3140 Page* page = Page::FromAddress(object->address()); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3248 object->ShortPrint(); | 3234 object->ShortPrint(); |
3249 PrintF("\n"); | 3235 PrintF("\n"); |
3250 } | 3236 } |
3251 printf(" --------------------------------------\n"); | 3237 printf(" --------------------------------------\n"); |
3252 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3238 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
3253 } | 3239 } |
3254 | 3240 |
3255 #endif // DEBUG | 3241 #endif // DEBUG |
3256 } // namespace internal | 3242 } // namespace internal |
3257 } // namespace v8 | 3243 } // namespace v8 |
OLD | NEW |