Chromium Code Reviews| 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 1466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1477 } | 1477 } |
| 1478 CHECK(allocation_pointer_found_in_space); | 1478 CHECK(allocation_pointer_found_in_space); |
| 1479 } | 1479 } |
| 1480 #endif // VERIFY_HEAP | 1480 #endif // VERIFY_HEAP |
| 1481 | 1481 |
| 1482 // ----------------------------------------------------------------------------- | 1482 // ----------------------------------------------------------------------------- |
| 1483 // NewSpace implementation | 1483 // NewSpace implementation |
| 1484 | 1484 |
| 1485 bool NewSpace::SetUp(int initial_semispace_capacity, | 1485 bool NewSpace::SetUp(int initial_semispace_capacity, |
| 1486 int maximum_semispace_capacity) { | 1486 int maximum_semispace_capacity) { |
| 1487 DCHECK(initial_semispace_capacity <= maximum_semispace_capacity); | 1487 DCHECK_LE(initial_semispace_capacity, maximum_semispace_capacity); |
| 1488 DCHECK(base::bits::IsPowerOfTwo32(maximum_semispace_capacity)); | 1488 DCHECK(base::bits::IsPowerOfTwo32(maximum_semispace_capacity)); |
| 1489 DCHECK_GE(initial_semispace_capacity, 2 * Page::kPageSize); | |
| 1489 | 1490 |
| 1490 to_space_.SetUp(initial_semispace_capacity, maximum_semispace_capacity); | 1491 to_space_.SetUp(initial_semispace_capacity, maximum_semispace_capacity); |
| 1491 from_space_.SetUp(initial_semispace_capacity, maximum_semispace_capacity); | 1492 from_space_.SetUp(initial_semispace_capacity, maximum_semispace_capacity); |
| 1492 if (!to_space_.Commit()) { | 1493 if (!to_space_.Commit()) { |
| 1493 return false; | 1494 return false; |
| 1494 } | 1495 } |
| 1495 DCHECK(!from_space_.is_committed()); // No need to use memory yet. | 1496 DCHECK(!from_space_.is_committed()); // No need to use memory yet. |
| 1496 ResetAllocationInfo(); | 1497 ResetAllocationInfo(); |
| 1497 | 1498 |
| 1498 // Allocate and set up the histogram arrays if necessary. | 1499 // Allocate and set up the histogram arrays if necessary. |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1579 bool SemiSpace::EnsureCurrentCapacity() { | 1580 bool SemiSpace::EnsureCurrentCapacity() { |
| 1580 if (is_committed()) { | 1581 if (is_committed()) { |
| 1581 const int expected_pages = current_capacity_ / Page::kPageSize; | 1582 const int expected_pages = current_capacity_ / Page::kPageSize; |
| 1582 int actual_pages = 0; | 1583 int actual_pages = 0; |
| 1583 Page* current_page = anchor()->next_page(); | 1584 Page* current_page = anchor()->next_page(); |
| 1584 while (current_page != anchor()) { | 1585 while (current_page != anchor()) { |
| 1585 actual_pages++; | 1586 actual_pages++; |
| 1586 current_page = current_page->next_page(); | 1587 current_page = current_page->next_page(); |
| 1587 if (actual_pages > expected_pages) { | 1588 if (actual_pages > expected_pages) { |
| 1588 Page* to_remove = current_page->prev_page(); | 1589 Page* to_remove = current_page->prev_page(); |
| 1589 // Make sure we don't overtake the actual top pointer. | 1590 if (to_remove == current_page_) { |
| 1590 CHECK_NE(to_remove, current_page_); | 1591 // Corner case: All pages have been moved within new space. We are |
| 1592 // removing the page that contains the top pointer and need to set | |
| 1593 // it to the end of the intermediate generation. | |
| 1594 NewSpace* new_space = heap()->new_space(); | |
| 1595 CHECK_EQ(new_space->top(), current_page_->area_start()); | |
| 1596 current_page_ = to_remove->prev_page(); | |
| 1597 CHECK(current_page_->InIntermediateGeneration()); | |
| 1598 new_space->SetAllocationInfo(page_high(), page_high()); | |
|
Hannes Payer (out of office)
2016/09/27 08:28:31
can we set top and limit to null?
Michael Lippautz
2016/09/27 11:13:47
As discussed offline, there are quite some callers
| |
| 1599 } | |
| 1591 to_remove->Unlink(); | 1600 to_remove->Unlink(); |
| 1592 heap()->memory_allocator()->Free<MemoryAllocator::kPooledAndQueue>( | 1601 heap()->memory_allocator()->Free<MemoryAllocator::kPooledAndQueue>( |
| 1593 to_remove); | 1602 to_remove); |
| 1594 } | 1603 } |
| 1595 } | 1604 } |
| 1596 while (actual_pages < expected_pages) { | 1605 while (actual_pages < expected_pages) { |
| 1597 actual_pages++; | 1606 actual_pages++; |
| 1598 current_page = | 1607 current_page = |
| 1599 heap()->memory_allocator()->AllocatePage<MemoryAllocator::kPooled>( | 1608 heap()->memory_allocator()->AllocatePage<MemoryAllocator::kPooled>( |
| 1600 Page::kAllocatableMemory, this, executable()); | 1609 Page::kAllocatableMemory, this, executable()); |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1906 Page::kAllocatableMemory, this, executable()); | 1915 Page::kAllocatableMemory, this, executable()); |
| 1907 if (new_page == nullptr) { | 1916 if (new_page == nullptr) { |
| 1908 RewindPages(current, pages_added); | 1917 RewindPages(current, pages_added); |
| 1909 return false; | 1918 return false; |
| 1910 } | 1919 } |
| 1911 new_page->InsertAfter(current); | 1920 new_page->InsertAfter(current); |
| 1912 current = new_page; | 1921 current = new_page; |
| 1913 } | 1922 } |
| 1914 Reset(); | 1923 Reset(); |
| 1915 AccountCommitted(current_capacity_); | 1924 AccountCommitted(current_capacity_); |
| 1916 if (age_mark_ == nullptr) { | |
| 1917 age_mark_ = first_page()->area_start(); | |
| 1918 } | |
| 1919 committed_ = true; | 1925 committed_ = true; |
| 1920 return true; | 1926 return true; |
| 1921 } | 1927 } |
| 1922 | 1928 |
| 1923 | 1929 |
| 1924 bool SemiSpace::Uncommit() { | 1930 bool SemiSpace::Uncommit() { |
| 1925 DCHECK(is_committed()); | 1931 DCHECK(is_committed()); |
| 1926 for (auto it = begin(); it != end();) { | 1932 for (auto it = begin(); it != end();) { |
| 1927 Page* p = *(it++); | 1933 Page* p = *(it++); |
| 1928 heap()->memory_allocator()->Free<MemoryAllocator::kPooledAndQueue>(p); | 1934 heap()->memory_allocator()->Free<MemoryAllocator::kPooledAndQueue>(p); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2020 anchor_.set_owner(this); | 2026 anchor_.set_owner(this); |
| 2021 anchor_.prev_page()->set_next_page(&anchor_); | 2027 anchor_.prev_page()->set_next_page(&anchor_); |
| 2022 anchor_.next_page()->set_prev_page(&anchor_); | 2028 anchor_.next_page()->set_prev_page(&anchor_); |
| 2023 | 2029 |
| 2024 for (Page* page : *this) { | 2030 for (Page* page : *this) { |
| 2025 page->set_owner(this); | 2031 page->set_owner(this); |
| 2026 page->SetFlags(flags, mask); | 2032 page->SetFlags(flags, mask); |
| 2027 if (id_ == kToSpace) { | 2033 if (id_ == kToSpace) { |
| 2028 page->ClearFlag(MemoryChunk::IN_FROM_SPACE); | 2034 page->ClearFlag(MemoryChunk::IN_FROM_SPACE); |
| 2029 page->SetFlag(MemoryChunk::IN_TO_SPACE); | 2035 page->SetFlag(MemoryChunk::IN_TO_SPACE); |
| 2030 page->ClearFlag(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK); | 2036 page->ClearFlag(MemoryChunk::IN_INTERMEDIATE_GENERATION); |
| 2031 page->ResetLiveBytes(); | 2037 page->ResetLiveBytes(); |
| 2032 } else { | 2038 } else { |
| 2033 page->SetFlag(MemoryChunk::IN_FROM_SPACE); | 2039 page->SetFlag(MemoryChunk::IN_FROM_SPACE); |
| 2034 page->ClearFlag(MemoryChunk::IN_TO_SPACE); | 2040 page->ClearFlag(MemoryChunk::IN_TO_SPACE); |
| 2035 } | 2041 } |
| 2036 DCHECK(page->IsFlagSet(MemoryChunk::IN_TO_SPACE) || | 2042 DCHECK(page->IsFlagSet(MemoryChunk::IN_TO_SPACE) || |
| 2037 page->IsFlagSet(MemoryChunk::IN_FROM_SPACE)); | 2043 page->IsFlagSet(MemoryChunk::IN_FROM_SPACE)); |
| 2038 } | 2044 } |
| 2039 } | 2045 } |
| 2040 | 2046 |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 2063 // We won't be swapping semispaces without data in them. | 2069 // We won't be swapping semispaces without data in them. |
| 2064 DCHECK_NE(from->anchor_.next_page(), &from->anchor_); | 2070 DCHECK_NE(from->anchor_.next_page(), &from->anchor_); |
| 2065 DCHECK_NE(to->anchor_.next_page(), &to->anchor_); | 2071 DCHECK_NE(to->anchor_.next_page(), &to->anchor_); |
| 2066 | 2072 |
| 2067 intptr_t saved_to_space_flags = to->current_page()->GetFlags(); | 2073 intptr_t saved_to_space_flags = to->current_page()->GetFlags(); |
| 2068 | 2074 |
| 2069 // We swap all properties but id_. | 2075 // We swap all properties but id_. |
| 2070 std::swap(from->current_capacity_, to->current_capacity_); | 2076 std::swap(from->current_capacity_, to->current_capacity_); |
| 2071 std::swap(from->maximum_capacity_, to->maximum_capacity_); | 2077 std::swap(from->maximum_capacity_, to->maximum_capacity_); |
| 2072 std::swap(from->minimum_capacity_, to->minimum_capacity_); | 2078 std::swap(from->minimum_capacity_, to->minimum_capacity_); |
| 2073 std::swap(from->age_mark_, to->age_mark_); | |
| 2074 std::swap(from->committed_, to->committed_); | 2079 std::swap(from->committed_, to->committed_); |
| 2075 std::swap(from->anchor_, to->anchor_); | 2080 std::swap(from->anchor_, to->anchor_); |
| 2076 std::swap(from->current_page_, to->current_page_); | 2081 std::swap(from->current_page_, to->current_page_); |
| 2077 | 2082 |
| 2078 to->FixPagesFlags(saved_to_space_flags, Page::kCopyOnFlipFlagsMask); | 2083 to->FixPagesFlags(saved_to_space_flags, Page::kCopyOnFlipFlagsMask); |
| 2079 from->FixPagesFlags(0, 0); | 2084 from->FixPagesFlags(0, 0); |
| 2080 } | 2085 } |
| 2081 | 2086 |
| 2087 void NewSpace::SealIntermediateGeneration() { | |
| 2088 fragmentation_in_intermediate_generation_ = 0; | |
| 2089 const Address mark = top(); | |
| 2082 | 2090 |
| 2083 void SemiSpace::set_age_mark(Address mark) { | 2091 for (Page* p : NewSpacePageRange(to_space_.space_start(), mark)) { |
| 2084 DCHECK_EQ(Page::FromAllocationAreaAddress(mark)->owner(), this); | 2092 p->SetFlag(MemoryChunk::IN_INTERMEDIATE_GENERATION); |
| 2085 age_mark_ = mark; | 2093 } |
| 2086 // Mark all pages up to the one containing mark. | 2094 |
| 2087 for (Page* p : NewSpacePageRange(space_start(), mark)) { | 2095 Page* p = Page::FromAllocationAreaAddress(mark); |
| 2088 p->SetFlag(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK); | 2096 if (mark < p->area_end()) { |
| 2097 heap()->CreateFillerObjectAt(mark, static_cast<int>(p->area_end() - mark), | |
| 2098 ClearRecordedSlots::kNo); | |
| 2099 fragmentation_in_intermediate_generation_ = | |
| 2100 static_cast<size_t>(p->area_end() - mark); | |
| 2101 DCHECK_EQ(to_space_.current_page(), p); | |
| 2102 if (to_space_.AdvancePage()) { | |
| 2103 UpdateAllocationInfo(); | |
| 2104 } else { | |
| 2105 allocation_info_.Reset(to_space_.page_high(), to_space_.page_high()); | |
|
Hannes Payer (out of office)
2016/09/27 08:28:31
same as above, wouldn't it be cleaner to set top a
Michael Lippautz
2016/09/27 11:13:47
See above.
| |
| 2106 } | |
| 2107 } | |
| 2108 if (FLAG_trace_gc_verbose) { | |
| 2109 PrintIsolate(heap()->isolate(), | |
| 2110 "Sealing intermediate generation: bytes_lost=%zu\n", | |
| 2111 fragmentation_in_intermediate_generation_); | |
| 2089 } | 2112 } |
| 2090 } | 2113 } |
| 2091 | 2114 |
| 2092 | |
| 2093 #ifdef DEBUG | 2115 #ifdef DEBUG |
| 2094 void SemiSpace::Print() {} | 2116 void SemiSpace::Print() {} |
| 2095 #endif | 2117 #endif |
| 2096 | 2118 |
| 2097 #ifdef VERIFY_HEAP | 2119 #ifdef VERIFY_HEAP |
| 2098 void SemiSpace::Verify() { | 2120 void SemiSpace::Verify() { |
| 2099 bool is_from_space = (id_ == kFromSpace); | 2121 bool is_from_space = (id_ == kFromSpace); |
| 2100 Page* page = anchor_.next_page(); | 2122 Page* page = anchor_.next_page(); |
| 2101 CHECK(anchor_.owner() == this); | 2123 CHECK(anchor_.owner() == this); |
| 2102 while (page != &anchor_) { | 2124 while (page != &anchor_) { |
| (...skipping 1132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3235 object->ShortPrint(); | 3257 object->ShortPrint(); |
| 3236 PrintF("\n"); | 3258 PrintF("\n"); |
| 3237 } | 3259 } |
| 3238 printf(" --------------------------------------\n"); | 3260 printf(" --------------------------------------\n"); |
| 3239 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3261 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
| 3240 } | 3262 } |
| 3241 | 3263 |
| 3242 #endif // DEBUG | 3264 #endif // DEBUG |
| 3243 } // namespace internal | 3265 } // namespace internal |
| 3244 } // namespace v8 | 3266 } // namespace v8 |
| OLD | NEW |