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 "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 2107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2118 while (node != NULL) { | 2118 while (node != NULL) { |
| 2119 if (Page::FromAddress(node->address()) == p) return true; | 2119 if (Page::FromAddress(node->address()) == p) return true; |
| 2120 node = node->next(); | 2120 node = node->next(); |
| 2121 } | 2121 } |
| 2122 return false; | 2122 return false; |
| 2123 } | 2123 } |
| 2124 | 2124 |
| 2125 | 2125 |
| 2126 FreeSpace* FreeListCategory::PickNodeFromList(int* node_size) { | 2126 FreeSpace* FreeListCategory::PickNodeFromList(int* node_size) { |
| 2127 FreeSpace* node = top(); | 2127 FreeSpace* node = top(); |
| 2128 if (node == nullptr) return nullptr; | |
| 2128 | 2129 |
| 2129 if (node == NULL) return NULL; | 2130 while ((node != nullptr) && |
| 2130 | |
| 2131 while (node != NULL && | |
| 2132 Page::FromAddress(node->address())->IsEvacuationCandidate()) { | 2131 Page::FromAddress(node->address())->IsEvacuationCandidate()) { |
|
Hannes Payer (out of office)
2015/10/15 12:45:10
Let's re-write this piece of code.
Create a local
Michael Lippautz
2015/10/15 12:53:21
Done.
| |
| 2133 available_ -= node->Size(); | 2132 available_ -= node->Size(); |
| 2133 Page::FromAddress(node->address()) | |
|
Michael Lippautz
2015/10/15 12:23:32
This was a bug, as we did not remove the size when
Hannes Payer (out of office)
2015/10/15 12:45:10
Acknowledged.
| |
| 2134 ->add_available_in_free_list(type_, -(node->Size())); | |
| 2134 node = node->next(); | 2135 node = node->next(); |
| 2135 } | 2136 } |
| 2136 | 2137 |
| 2137 if (node != NULL) { | 2138 if (node != nullptr) { |
| 2138 set_top(node->next()); | 2139 set_top(node->next()); |
| 2139 *node_size = node->Size(); | 2140 *node_size = node->Size(); |
| 2140 available_ -= *node_size; | 2141 available_ -= *node_size; |
| 2141 } else { | 2142 } else { |
| 2142 set_top(NULL); | 2143 set_top(nullptr); |
| 2143 } | 2144 } |
| 2144 | 2145 |
| 2145 if (top() == NULL) { | 2146 if (top() == nullptr) { |
| 2146 set_end(NULL); | 2147 set_end(nullptr); |
| 2147 } | 2148 } |
| 2148 | 2149 |
| 2149 return node; | 2150 return node; |
| 2150 } | 2151 } |
| 2151 | 2152 |
| 2152 | 2153 |
| 2153 FreeSpace* FreeListCategory::PickNodeFromList(int size_in_bytes, | 2154 FreeSpace* FreeListCategory::PickNodeFromList(int size_in_bytes, |
| 2154 int* node_size) { | 2155 int* node_size) { |
| 2155 FreeSpace* node = PickNodeFromList(node_size); | 2156 FreeSpace* node = PickNodeFromList(node_size); |
| 2156 if (node != NULL && *node_size < size_in_bytes) { | 2157 if ((node != nullptr) && (*node_size < size_in_bytes)) { |
| 2157 Free(node, *node_size); | 2158 Free(node, *node_size); |
| 2158 *node_size = 0; | 2159 *node_size = 0; |
| 2159 return NULL; | 2160 return nullptr; |
| 2160 } | 2161 } |
| 2161 return node; | 2162 return node; |
| 2162 } | 2163 } |
| 2163 | 2164 |
| 2164 | 2165 |
| 2165 FreeSpace* FreeListCategory::SearchForNodeInList(int size_in_bytes, | 2166 FreeSpace* FreeListCategory::SearchForNodeInList(int size_in_bytes, |
| 2166 int* node_size) { | 2167 int* node_size) { |
| 2167 FreeSpace* return_node = nullptr; | 2168 FreeSpace* prev_non_evac_node = nullptr; |
| 2168 FreeSpace* top_node = top(); | 2169 for (FreeSpace* cur_node = top(); cur_node != nullptr; |
| 2170 cur_node = cur_node->next()) { | |
| 2171 int size = cur_node->size(); | |
| 2172 Page* page_for_node = Page::FromAddress(cur_node->address()); | |
| 2169 | 2173 |
| 2170 for (FreeSpace** node_it = &top_node; *node_it != NULL; | 2174 if ((size >= size_in_bytes) || page_for_node->IsEvacuationCandidate()) { |
| 2171 node_it = (*node_it)->next_address()) { | 2175 // The node is either large enough or contained in an evacuation |
| 2172 FreeSpace* cur_node = *node_it; | 2176 // candidate. In both cases we need to unlink it from the list. |
| 2173 while (cur_node != NULL && | |
| 2174 Page::FromAddress(cur_node->address())->IsEvacuationCandidate()) { | |
| 2175 int size = cur_node->Size(); | |
| 2176 available_ -= size; | 2177 available_ -= size; |
| 2177 Page::FromAddress(cur_node->address()) | 2178 if (cur_node == top()) { |
| 2178 ->add_available_in_free_list(type_, -size); | 2179 set_top(cur_node->next()); |
| 2179 cur_node = cur_node->next(); | 2180 } |
| 2181 if (cur_node == end()) { | |
|
Michael Lippautz
2015/10/15 12:23:32
Bug: end() was not handled properly. The bug flush
Hannes Payer (out of office)
2015/10/15 12:45:10
Acknowledged.
| |
| 2182 set_end(prev_non_evac_node); | |
| 2183 } | |
| 2184 if (prev_non_evac_node != nullptr) { | |
| 2185 prev_non_evac_node->set_next(cur_node->next()); | |
| 2186 } | |
| 2187 // For evacuation candidates we continue. | |
| 2188 if (page_for_node->IsEvacuationCandidate()) { | |
| 2189 page_for_node->add_available_in_free_list(type_, -size); | |
|
Hannes Payer (out of office)
2015/10/15 12:45:10
I like it that this counter is updated here, since
Michael Lippautz
2015/10/15 12:53:21
Acknowledged.
| |
| 2190 continue; | |
| 2191 } | |
| 2192 // Otherwise we have a large enough node and can return. | |
| 2193 *node_size = size; | |
| 2194 return cur_node; | |
| 2180 } | 2195 } |
| 2181 | 2196 |
| 2182 // Update iterator. | 2197 prev_non_evac_node = cur_node; |
| 2183 *node_it = cur_node; | |
| 2184 | |
| 2185 if (cur_node == nullptr) { | |
| 2186 set_end(nullptr); | |
| 2187 break; | |
| 2188 } | |
| 2189 | |
| 2190 int size = cur_node->Size(); | |
| 2191 if (size >= size_in_bytes) { | |
| 2192 // Large enough node found. Unlink it from the list. | |
| 2193 return_node = cur_node; | |
| 2194 *node_it = cur_node->next(); | |
| 2195 *node_size = size; | |
| 2196 available_ -= size; | |
| 2197 Page::FromAddress(return_node->address()) | |
| 2198 ->add_available_in_free_list(type_, -size); | |
| 2199 break; | |
| 2200 } | |
| 2201 } | 2198 } |
| 2202 | 2199 return nullptr; |
| 2203 // Top could've changed if we took the first node. Update top and end | |
| 2204 // accordingly. | |
| 2205 set_top(top_node); | |
| 2206 if (top() == nullptr) { | |
| 2207 set_end(nullptr); | |
| 2208 } | |
| 2209 | |
| 2210 return return_node; | |
| 2211 } | 2200 } |
| 2212 | 2201 |
| 2213 | 2202 |
| 2214 void FreeListCategory::Free(FreeSpace* free_space, int size_in_bytes) { | 2203 void FreeListCategory::Free(FreeSpace* free_space, int size_in_bytes) { |
| 2215 free_space->set_next(top()); | 2204 free_space->set_next(top()); |
| 2216 set_top(free_space); | 2205 set_top(free_space); |
| 2217 if (end_ == NULL) { | 2206 if (end_ == NULL) { |
| 2218 end_ = free_space; | 2207 end_ = free_space; |
| 2219 } | 2208 } |
| 2220 available_ += size_in_bytes; | 2209 available_ += size_in_bytes; |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2323 if (node != nullptr) { | 2312 if (node != nullptr) { |
| 2324 Page::FromAddress(node->address()) | 2313 Page::FromAddress(node->address()) |
| 2325 ->add_available_in_free_list(category, -(*node_size)); | 2314 ->add_available_in_free_list(category, -(*node_size)); |
| 2326 DCHECK(IsVeryLong() || available() == SumFreeLists()); | 2315 DCHECK(IsVeryLong() || available() == SumFreeLists()); |
| 2327 } | 2316 } |
| 2328 return node; | 2317 return node; |
| 2329 } | 2318 } |
| 2330 | 2319 |
| 2331 | 2320 |
| 2332 FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { | 2321 FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { |
| 2333 FreeSpace* node = NULL; | 2322 FreeSpace* node = nullptr; |
| 2334 Page* page = NULL; | 2323 Page* page = nullptr; |
| 2335 | 2324 |
| 2336 if (size_in_bytes <= kSmallAllocationMax) { | 2325 if (size_in_bytes <= kSmallAllocationMax) { |
| 2337 node = FindNodeIn(kSmall, node_size); | 2326 node = FindNodeIn(kSmall, node_size); |
| 2338 if (node != NULL) { | 2327 if (node != nullptr) return node; |
| 2339 DCHECK(IsVeryLong() || available() == SumFreeLists()); | |
| 2340 return node; | |
| 2341 } | |
| 2342 } | 2328 } |
| 2343 | 2329 |
| 2344 if (size_in_bytes <= kMediumAllocationMax) { | 2330 if (size_in_bytes <= kMediumAllocationMax) { |
| 2345 node = FindNodeIn(kMedium, node_size); | 2331 node = FindNodeIn(kMedium, node_size); |
| 2346 if (node != NULL) { | 2332 if (node != nullptr) return node; |
| 2347 DCHECK(IsVeryLong() || available() == SumFreeLists()); | |
| 2348 return node; | |
| 2349 } | |
| 2350 } | 2333 } |
| 2351 | 2334 |
| 2352 if (size_in_bytes <= kLargeAllocationMax) { | 2335 if (size_in_bytes <= kLargeAllocationMax) { |
| 2353 node = FindNodeIn(kLarge, node_size); | 2336 node = FindNodeIn(kLarge, node_size); |
| 2354 if (node != NULL) { | 2337 if (node != nullptr) return node; |
| 2355 DCHECK(IsVeryLong() || available() == SumFreeLists()); | |
| 2356 return node; | |
| 2357 } | |
| 2358 } | 2338 } |
| 2359 | 2339 |
| 2360 node = huge_list_.SearchForNodeInList(size_in_bytes, node_size); | 2340 node = huge_list_.SearchForNodeInList(size_in_bytes, node_size); |
| 2361 | 2341 if (node != nullptr) { |
| 2362 if (node != NULL) { | 2342 page = Page::FromAddress(node->address()); |
| 2343 page->add_available_in_large_free_list(-(*node_size)); | |
| 2363 DCHECK(IsVeryLong() || available() == SumFreeLists()); | 2344 DCHECK(IsVeryLong() || available() == SumFreeLists()); |
| 2364 return node; | 2345 return node; |
| 2365 } | 2346 } |
| 2366 | 2347 |
| 2367 if (size_in_bytes <= kSmallListMax) { | 2348 if (size_in_bytes <= kSmallListMax) { |
| 2368 node = small_list_.PickNodeFromList(size_in_bytes, node_size); | 2349 node = small_list_.PickNodeFromList(size_in_bytes, node_size); |
| 2369 if (node != NULL) { | 2350 if (node != NULL) { |
| 2370 DCHECK(size_in_bytes <= *node_size); | 2351 DCHECK(size_in_bytes <= *node_size); |
| 2371 page = Page::FromAddress(node->address()); | 2352 page = Page::FromAddress(node->address()); |
| 2372 page->add_available_in_small_free_list(-(*node_size)); | 2353 page->add_available_in_small_free_list(-(*node_size)); |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2581 while (iterator.has_next()) { | 2562 while (iterator.has_next()) { |
| 2582 Page* page = iterator.next(); | 2563 Page* page = iterator.next(); |
| 2583 int size = static_cast<int>(page->non_available_small_blocks()); | 2564 int size = static_cast<int>(page->non_available_small_blocks()); |
| 2584 if (size == 0) continue; | 2565 if (size == 0) continue; |
| 2585 Address address = page->OffsetToAddress(Page::kPageSize - size); | 2566 Address address = page->OffsetToAddress(Page::kPageSize - size); |
| 2586 heap()->CreateFillerObjectAt(address, size); | 2567 heap()->CreateFillerObjectAt(address, size); |
| 2587 } | 2568 } |
| 2588 } | 2569 } |
| 2589 | 2570 |
| 2590 | 2571 |
| 2591 void PagedSpace::EvictEvacuationCandidatesFromFreeLists() { | 2572 void PagedSpace::EvictEvacuationCandidatesFromLinearAllocationArea() { |
| 2592 if (allocation_info_.top() >= allocation_info_.limit()) return; | 2573 if (allocation_info_.top() >= allocation_info_.limit()) return; |
| 2593 | 2574 |
| 2594 if (Page::FromAllocationTop(allocation_info_.top()) | 2575 if (Page::FromAllocationTop(allocation_info_.top()) |
| 2595 ->IsEvacuationCandidate()) { | 2576 ->IsEvacuationCandidate()) { |
| 2596 // Create filler object to keep page iterable if it was iterable. | 2577 // Create filler object to keep page iterable if it was iterable. |
| 2597 int remaining = | 2578 int remaining = |
| 2598 static_cast<int>(allocation_info_.limit() - allocation_info_.top()); | 2579 static_cast<int>(allocation_info_.limit() - allocation_info_.top()); |
| 2599 heap()->CreateFillerObjectAt(allocation_info_.top(), remaining); | 2580 heap()->CreateFillerObjectAt(allocation_info_.top(), remaining); |
| 2600 | 2581 |
| 2601 allocation_info_.set_top(NULL); | 2582 allocation_info_.set_top(nullptr); |
| 2602 allocation_info_.set_limit(NULL); | 2583 allocation_info_.set_limit(nullptr); |
| 2603 } | 2584 } |
| 2604 } | 2585 } |
| 2605 | 2586 |
| 2606 | 2587 |
| 2607 HeapObject* PagedSpace::WaitForSweeperThreadsAndRetryAllocation( | 2588 HeapObject* PagedSpace::WaitForSweeperThreadsAndRetryAllocation( |
| 2608 int size_in_bytes) { | 2589 int size_in_bytes) { |
| 2609 MarkCompactCollector* collector = heap()->mark_compact_collector(); | 2590 MarkCompactCollector* collector = heap()->mark_compact_collector(); |
| 2610 if (collector->sweeping_in_progress()) { | 2591 if (collector->sweeping_in_progress()) { |
| 2611 // Wait for the sweeper threads here and complete the sweeping phase. | 2592 // Wait for the sweeper threads here and complete the sweeping phase. |
| 2612 collector->EnsureSweepingCompleted(); | 2593 collector->EnsureSweepingCompleted(); |
| (...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3158 object->ShortPrint(); | 3139 object->ShortPrint(); |
| 3159 PrintF("\n"); | 3140 PrintF("\n"); |
| 3160 } | 3141 } |
| 3161 printf(" --------------------------------------\n"); | 3142 printf(" --------------------------------------\n"); |
| 3162 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3143 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
| 3163 } | 3144 } |
| 3164 | 3145 |
| 3165 #endif // DEBUG | 3146 #endif // DEBUG |
| 3166 } // namespace internal | 3147 } // namespace internal |
| 3167 } // namespace v8 | 3148 } // namespace v8 |
| OLD | NEW |