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 <utility> | 7 #include <utility> |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/base/platform/platform.h" | 10 #include "src/base/platform/platform.h" |
(...skipping 1471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1482 } | 1482 } |
1483 CHECK(allocation_pointer_found_in_space); | 1483 CHECK(allocation_pointer_found_in_space); |
1484 } | 1484 } |
1485 #endif // VERIFY_HEAP | 1485 #endif // VERIFY_HEAP |
1486 | 1486 |
1487 // ----------------------------------------------------------------------------- | 1487 // ----------------------------------------------------------------------------- |
1488 // NewSpace implementation | 1488 // NewSpace implementation |
1489 | 1489 |
1490 bool NewSpace::SetUp(int initial_semispace_capacity, | 1490 bool NewSpace::SetUp(int initial_semispace_capacity, |
1491 int maximum_semispace_capacity) { | 1491 int maximum_semispace_capacity) { |
1492 DCHECK_LE(initial_semispace_capacity, maximum_semispace_capacity); | 1492 DCHECK(initial_semispace_capacity <= maximum_semispace_capacity); |
1493 DCHECK(base::bits::IsPowerOfTwo32(maximum_semispace_capacity)); | 1493 DCHECK(base::bits::IsPowerOfTwo32(maximum_semispace_capacity)); |
1494 DCHECK_GE(initial_semispace_capacity, 2 * Page::kPageSize); | |
1495 | 1494 |
1496 to_space_.SetUp(initial_semispace_capacity, maximum_semispace_capacity); | 1495 to_space_.SetUp(initial_semispace_capacity, maximum_semispace_capacity); |
1497 from_space_.SetUp(initial_semispace_capacity, maximum_semispace_capacity); | 1496 from_space_.SetUp(initial_semispace_capacity, maximum_semispace_capacity); |
1498 if (!to_space_.Commit()) { | 1497 if (!to_space_.Commit()) { |
1499 return false; | 1498 return false; |
1500 } | 1499 } |
1501 DCHECK(!from_space_.is_committed()); // No need to use memory yet. | 1500 DCHECK(!from_space_.is_committed()); // No need to use memory yet. |
1502 ResetAllocationInfo(); | 1501 ResetAllocationInfo(); |
1503 | 1502 |
1504 // Allocate and set up the histogram arrays if necessary. | 1503 // Allocate and set up the histogram arrays if necessary. |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1585 bool SemiSpace::EnsureCurrentCapacity() { | 1584 bool SemiSpace::EnsureCurrentCapacity() { |
1586 if (is_committed()) { | 1585 if (is_committed()) { |
1587 const int expected_pages = current_capacity_ / Page::kPageSize; | 1586 const int expected_pages = current_capacity_ / Page::kPageSize; |
1588 int actual_pages = 0; | 1587 int actual_pages = 0; |
1589 Page* current_page = anchor()->next_page(); | 1588 Page* current_page = anchor()->next_page(); |
1590 while (current_page != anchor()) { | 1589 while (current_page != anchor()) { |
1591 actual_pages++; | 1590 actual_pages++; |
1592 current_page = current_page->next_page(); | 1591 current_page = current_page->next_page(); |
1593 if (actual_pages > expected_pages) { | 1592 if (actual_pages > expected_pages) { |
1594 Page* to_remove = current_page->prev_page(); | 1593 Page* to_remove = current_page->prev_page(); |
1595 if (to_remove == current_page_) { | 1594 // Make sure we don't overtake the actual top pointer. |
1596 // Corner case: All pages have been moved within new space. We are | 1595 CHECK_NE(to_remove, current_page_); |
1597 // removing the page that contains the top pointer and need to set | |
1598 // it to the end of the intermediate generation. | |
1599 NewSpace* new_space = heap()->new_space(); | |
1600 CHECK_EQ(new_space->top(), current_page_->area_start()); | |
1601 current_page_ = to_remove->prev_page(); | |
1602 CHECK(current_page_->InIntermediateGeneration()); | |
1603 new_space->SetAllocationInfo(page_high(), page_high()); | |
1604 } | |
1605 to_remove->Unlink(); | 1596 to_remove->Unlink(); |
1606 heap()->memory_allocator()->Free<MemoryAllocator::kPooledAndQueue>( | 1597 heap()->memory_allocator()->Free<MemoryAllocator::kPooledAndQueue>( |
1607 to_remove); | 1598 to_remove); |
1608 } | 1599 } |
1609 } | 1600 } |
1610 while (actual_pages < expected_pages) { | 1601 while (actual_pages < expected_pages) { |
1611 actual_pages++; | 1602 actual_pages++; |
1612 current_page = | 1603 current_page = |
1613 heap()->memory_allocator()->AllocatePage<MemoryAllocator::kPooled>( | 1604 heap()->memory_allocator()->AllocatePage<MemoryAllocator::kPooled>( |
1614 Page::kAllocatableMemory, this, executable()); | 1605 Page::kAllocatableMemory, this, executable()); |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1924 Page::kAllocatableMemory, this, executable()); | 1915 Page::kAllocatableMemory, this, executable()); |
1925 if (new_page == nullptr) { | 1916 if (new_page == nullptr) { |
1926 RewindPages(current, pages_added); | 1917 RewindPages(current, pages_added); |
1927 return false; | 1918 return false; |
1928 } | 1919 } |
1929 new_page->InsertAfter(current); | 1920 new_page->InsertAfter(current); |
1930 current = new_page; | 1921 current = new_page; |
1931 } | 1922 } |
1932 Reset(); | 1923 Reset(); |
1933 AccountCommitted(current_capacity_); | 1924 AccountCommitted(current_capacity_); |
| 1925 if (age_mark_ == nullptr) { |
| 1926 age_mark_ = first_page()->area_start(); |
| 1927 } |
1934 committed_ = true; | 1928 committed_ = true; |
1935 return true; | 1929 return true; |
1936 } | 1930 } |
1937 | 1931 |
1938 | 1932 |
1939 bool SemiSpace::Uncommit() { | 1933 bool SemiSpace::Uncommit() { |
1940 DCHECK(is_committed()); | 1934 DCHECK(is_committed()); |
1941 for (auto it = begin(); it != end();) { | 1935 for (auto it = begin(); it != end();) { |
1942 Page* p = *(it++); | 1936 Page* p = *(it++); |
1943 heap()->memory_allocator()->Free<MemoryAllocator::kPooledAndQueue>(p); | 1937 heap()->memory_allocator()->Free<MemoryAllocator::kPooledAndQueue>(p); |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2035 anchor_.set_owner(this); | 2029 anchor_.set_owner(this); |
2036 anchor_.prev_page()->set_next_page(&anchor_); | 2030 anchor_.prev_page()->set_next_page(&anchor_); |
2037 anchor_.next_page()->set_prev_page(&anchor_); | 2031 anchor_.next_page()->set_prev_page(&anchor_); |
2038 | 2032 |
2039 for (Page* page : *this) { | 2033 for (Page* page : *this) { |
2040 page->set_owner(this); | 2034 page->set_owner(this); |
2041 page->SetFlags(flags, mask); | 2035 page->SetFlags(flags, mask); |
2042 if (id_ == kToSpace) { | 2036 if (id_ == kToSpace) { |
2043 page->ClearFlag(MemoryChunk::IN_FROM_SPACE); | 2037 page->ClearFlag(MemoryChunk::IN_FROM_SPACE); |
2044 page->SetFlag(MemoryChunk::IN_TO_SPACE); | 2038 page->SetFlag(MemoryChunk::IN_TO_SPACE); |
2045 page->ClearFlag(MemoryChunk::IN_INTERMEDIATE_GENERATION); | 2039 page->ClearFlag(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK); |
2046 page->ResetLiveBytes(); | 2040 page->ResetLiveBytes(); |
2047 } else { | 2041 } else { |
2048 page->SetFlag(MemoryChunk::IN_FROM_SPACE); | 2042 page->SetFlag(MemoryChunk::IN_FROM_SPACE); |
2049 page->ClearFlag(MemoryChunk::IN_TO_SPACE); | 2043 page->ClearFlag(MemoryChunk::IN_TO_SPACE); |
2050 } | 2044 } |
2051 DCHECK(page->IsFlagSet(MemoryChunk::IN_TO_SPACE) || | 2045 DCHECK(page->IsFlagSet(MemoryChunk::IN_TO_SPACE) || |
2052 page->IsFlagSet(MemoryChunk::IN_FROM_SPACE)); | 2046 page->IsFlagSet(MemoryChunk::IN_FROM_SPACE)); |
2053 } | 2047 } |
2054 } | 2048 } |
2055 | 2049 |
(...skipping 22 matching lines...) Expand all Loading... |
2078 // We won't be swapping semispaces without data in them. | 2072 // We won't be swapping semispaces without data in them. |
2079 DCHECK_NE(from->anchor_.next_page(), &from->anchor_); | 2073 DCHECK_NE(from->anchor_.next_page(), &from->anchor_); |
2080 DCHECK_NE(to->anchor_.next_page(), &to->anchor_); | 2074 DCHECK_NE(to->anchor_.next_page(), &to->anchor_); |
2081 | 2075 |
2082 intptr_t saved_to_space_flags = to->current_page()->GetFlags(); | 2076 intptr_t saved_to_space_flags = to->current_page()->GetFlags(); |
2083 | 2077 |
2084 // We swap all properties but id_. | 2078 // We swap all properties but id_. |
2085 std::swap(from->current_capacity_, to->current_capacity_); | 2079 std::swap(from->current_capacity_, to->current_capacity_); |
2086 std::swap(from->maximum_capacity_, to->maximum_capacity_); | 2080 std::swap(from->maximum_capacity_, to->maximum_capacity_); |
2087 std::swap(from->minimum_capacity_, to->minimum_capacity_); | 2081 std::swap(from->minimum_capacity_, to->minimum_capacity_); |
| 2082 std::swap(from->age_mark_, to->age_mark_); |
2088 std::swap(from->committed_, to->committed_); | 2083 std::swap(from->committed_, to->committed_); |
2089 std::swap(from->anchor_, to->anchor_); | 2084 std::swap(from->anchor_, to->anchor_); |
2090 std::swap(from->current_page_, to->current_page_); | 2085 std::swap(from->current_page_, to->current_page_); |
2091 | 2086 |
2092 to->FixPagesFlags(saved_to_space_flags, Page::kCopyOnFlipFlagsMask); | 2087 to->FixPagesFlags(saved_to_space_flags, Page::kCopyOnFlipFlagsMask); |
2093 from->FixPagesFlags(0, 0); | 2088 from->FixPagesFlags(0, 0); |
2094 } | 2089 } |
2095 | 2090 |
2096 void NewSpace::SealIntermediateGeneration() { | 2091 void SemiSpace::set_age_mark(Address mark) { |
2097 fragmentation_in_intermediate_generation_ = 0; | 2092 DCHECK_EQ(Page::FromAllocationAreaAddress(mark)->owner(), this); |
2098 const Address mark = top(); | 2093 age_mark_ = mark; |
2099 | 2094 // Mark all pages up to the one containing mark. |
2100 if (mark == to_space_.space_start()) { | 2095 for (Page* p : NewSpacePageRange(space_start(), mark)) { |
2101 // Do not mark any pages as being part of the intermediate generation if no | 2096 p->SetFlag(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK); |
2102 // objects got moved. | |
2103 return; | |
2104 } | |
2105 | |
2106 for (Page* p : NewSpacePageRange(to_space_.space_start(), mark)) { | |
2107 p->SetFlag(MemoryChunk::IN_INTERMEDIATE_GENERATION); | |
2108 } | |
2109 | |
2110 Page* p = Page::FromAllocationAreaAddress(mark); | |
2111 if (mark < p->area_end()) { | |
2112 heap()->CreateFillerObjectAt(mark, static_cast<int>(p->area_end() - mark), | |
2113 ClearRecordedSlots::kNo); | |
2114 fragmentation_in_intermediate_generation_ = | |
2115 static_cast<size_t>(p->area_end() - mark); | |
2116 DCHECK_EQ(to_space_.current_page(), p); | |
2117 if (to_space_.AdvancePage()) { | |
2118 UpdateAllocationInfo(); | |
2119 } else { | |
2120 allocation_info_.Reset(to_space_.page_high(), to_space_.page_high()); | |
2121 } | |
2122 } | |
2123 if (FLAG_trace_gc_verbose) { | |
2124 PrintIsolate(heap()->isolate(), | |
2125 "Sealing intermediate generation: bytes_lost=%zu\n", | |
2126 fragmentation_in_intermediate_generation_); | |
2127 } | 2097 } |
2128 } | 2098 } |
2129 | 2099 |
2130 std::unique_ptr<ObjectIterator> SemiSpace::GetObjectIterator() { | 2100 std::unique_ptr<ObjectIterator> SemiSpace::GetObjectIterator() { |
2131 // Use the NewSpace::NewObjectIterator to iterate the ToSpace. | 2101 // Use the NewSpace::NewObjectIterator to iterate the ToSpace. |
2132 UNREACHABLE(); | 2102 UNREACHABLE(); |
2133 return std::unique_ptr<ObjectIterator>(); | 2103 return std::unique_ptr<ObjectIterator>(); |
2134 } | 2104 } |
2135 | 2105 |
2136 #ifdef DEBUG | 2106 #ifdef DEBUG |
(...skipping 1132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3269 object->ShortPrint(); | 3239 object->ShortPrint(); |
3270 PrintF("\n"); | 3240 PrintF("\n"); |
3271 } | 3241 } |
3272 printf(" --------------------------------------\n"); | 3242 printf(" --------------------------------------\n"); |
3273 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3243 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
3274 } | 3244 } |
3275 | 3245 |
3276 #endif // DEBUG | 3246 #endif // DEBUG |
3277 } // namespace internal | 3247 } // namespace internal |
3278 } // namespace v8 | 3248 } // namespace v8 |
OLD | NEW |