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 Page* page = Page::FromAddress(node->address()); |
2130 | 2131 while ((node != nullptr) && page->IsEvacuationCandidate()) { |
2131 while (node != NULL && | |
2132 Page::FromAddress(node->address())->IsEvacuationCandidate()) { | |
2133 available_ -= node->Size(); | 2132 available_ -= node->Size(); |
| 2133 page->add_available_in_free_list(type_, -(node->Size())); |
2134 node = node->next(); | 2134 node = node->next(); |
2135 } | 2135 } |
2136 | 2136 |
2137 if (node != NULL) { | 2137 if (node != nullptr) { |
2138 set_top(node->next()); | 2138 set_top(node->next()); |
2139 *node_size = node->Size(); | 2139 *node_size = node->Size(); |
2140 available_ -= *node_size; | 2140 available_ -= *node_size; |
2141 } else { | 2141 } else { |
2142 set_top(NULL); | 2142 set_top(nullptr); |
2143 } | 2143 } |
2144 | 2144 |
2145 if (top() == NULL) { | 2145 if (top() == nullptr) { |
2146 set_end(NULL); | 2146 set_end(nullptr); |
2147 } | 2147 } |
2148 | 2148 |
2149 return node; | 2149 return node; |
2150 } | 2150 } |
2151 | 2151 |
2152 | 2152 |
2153 FreeSpace* FreeListCategory::PickNodeFromList(int size_in_bytes, | 2153 FreeSpace* FreeListCategory::PickNodeFromList(int size_in_bytes, |
2154 int* node_size) { | 2154 int* node_size) { |
2155 FreeSpace* node = PickNodeFromList(node_size); | 2155 FreeSpace* node = PickNodeFromList(node_size); |
2156 if (node != NULL && *node_size < size_in_bytes) { | 2156 if ((node != nullptr) && (*node_size < size_in_bytes)) { |
2157 Free(node, *node_size); | 2157 Free(node, *node_size); |
2158 *node_size = 0; | 2158 *node_size = 0; |
2159 return NULL; | 2159 return nullptr; |
2160 } | 2160 } |
2161 return node; | 2161 return node; |
2162 } | 2162 } |
2163 | 2163 |
2164 | 2164 |
2165 FreeSpace* FreeListCategory::SearchForNodeInList(int size_in_bytes, | 2165 FreeSpace* FreeListCategory::SearchForNodeInList(int size_in_bytes, |
2166 int* node_size) { | 2166 int* node_size) { |
2167 FreeSpace* return_node = nullptr; | 2167 FreeSpace* prev_non_evac_node = nullptr; |
2168 FreeSpace* top_node = top(); | 2168 for (FreeSpace* cur_node = top(); cur_node != nullptr; |
| 2169 cur_node = cur_node->next()) { |
| 2170 int size = cur_node->size(); |
| 2171 Page* page_for_node = Page::FromAddress(cur_node->address()); |
2169 | 2172 |
2170 for (FreeSpace** node_it = &top_node; *node_it != NULL; | 2173 if ((size >= size_in_bytes) || page_for_node->IsEvacuationCandidate()) { |
2171 node_it = (*node_it)->next_address()) { | 2174 // The node is either large enough or contained in an evacuation |
2172 FreeSpace* cur_node = *node_it; | 2175 // 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; | 2176 available_ -= size; |
2177 Page::FromAddress(cur_node->address()) | 2177 if (cur_node == top()) { |
2178 ->add_available_in_free_list(type_, -size); | 2178 set_top(cur_node->next()); |
2179 cur_node = cur_node->next(); | 2179 } |
| 2180 if (cur_node == end()) { |
| 2181 set_end(prev_non_evac_node); |
| 2182 } |
| 2183 if (prev_non_evac_node != nullptr) { |
| 2184 prev_non_evac_node->set_next(cur_node->next()); |
| 2185 } |
| 2186 // For evacuation candidates we continue. |
| 2187 if (page_for_node->IsEvacuationCandidate()) { |
| 2188 page_for_node->add_available_in_free_list(type_, -size); |
| 2189 continue; |
| 2190 } |
| 2191 // Otherwise we have a large enough node and can return. |
| 2192 *node_size = size; |
| 2193 return cur_node; |
2180 } | 2194 } |
2181 | 2195 |
2182 // Update iterator. | 2196 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 } | 2197 } |
2202 | 2198 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 } | 2199 } |
2212 | 2200 |
2213 | 2201 |
2214 void FreeListCategory::Free(FreeSpace* free_space, int size_in_bytes) { | 2202 void FreeListCategory::Free(FreeSpace* free_space, int size_in_bytes) { |
2215 free_space->set_next(top()); | 2203 free_space->set_next(top()); |
2216 set_top(free_space); | 2204 set_top(free_space); |
2217 if (end_ == NULL) { | 2205 if (end_ == NULL) { |
2218 end_ = free_space; | 2206 end_ = free_space; |
2219 } | 2207 } |
2220 available_ += size_in_bytes; | 2208 available_ += size_in_bytes; |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2322 if (node != nullptr) { | 2310 if (node != nullptr) { |
2323 Page::FromAddress(node->address()) | 2311 Page::FromAddress(node->address()) |
2324 ->add_available_in_free_list(category, -(*node_size)); | 2312 ->add_available_in_free_list(category, -(*node_size)); |
2325 DCHECK(IsVeryLong() || Available() == SumFreeLists()); | 2313 DCHECK(IsVeryLong() || Available() == SumFreeLists()); |
2326 } | 2314 } |
2327 return node; | 2315 return node; |
2328 } | 2316 } |
2329 | 2317 |
2330 | 2318 |
2331 FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { | 2319 FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { |
2332 FreeSpace* node = NULL; | 2320 FreeSpace* node = nullptr; |
2333 Page* page = NULL; | 2321 Page* page = nullptr; |
2334 | 2322 |
2335 if (size_in_bytes <= kSmallAllocationMax) { | 2323 if (size_in_bytes <= kSmallAllocationMax) { |
2336 node = FindNodeIn(kSmall, node_size); | 2324 node = FindNodeIn(kSmall, node_size); |
2337 if (node != NULL) { | 2325 if (node != nullptr) return node; |
2338 DCHECK(IsVeryLong() || Available() == SumFreeLists()); | |
2339 return node; | |
2340 } | |
2341 } | 2326 } |
2342 | 2327 |
2343 if (size_in_bytes <= kMediumAllocationMax) { | 2328 if (size_in_bytes <= kMediumAllocationMax) { |
2344 node = FindNodeIn(kMedium, node_size); | 2329 node = FindNodeIn(kMedium, node_size); |
2345 if (node != NULL) { | 2330 if (node != nullptr) return node; |
2346 DCHECK(IsVeryLong() || Available() == SumFreeLists()); | |
2347 return node; | |
2348 } | |
2349 } | 2331 } |
2350 | 2332 |
2351 if (size_in_bytes <= kLargeAllocationMax) { | 2333 if (size_in_bytes <= kLargeAllocationMax) { |
2352 node = FindNodeIn(kLarge, node_size); | 2334 node = FindNodeIn(kLarge, node_size); |
2353 if (node != NULL) { | 2335 if (node != nullptr) return node; |
2354 DCHECK(IsVeryLong() || Available() == SumFreeLists()); | |
2355 return node; | |
2356 } | |
2357 } | 2336 } |
2358 | 2337 |
2359 node = huge_list_.SearchForNodeInList(size_in_bytes, node_size); | 2338 node = huge_list_.SearchForNodeInList(size_in_bytes, node_size); |
2360 | 2339 if (node != nullptr) { |
2361 if (node != NULL) { | 2340 page = Page::FromAddress(node->address()); |
| 2341 page->add_available_in_large_free_list(-(*node_size)); |
2362 DCHECK(IsVeryLong() || Available() == SumFreeLists()); | 2342 DCHECK(IsVeryLong() || Available() == SumFreeLists()); |
2363 return node; | 2343 return node; |
2364 } | 2344 } |
2365 | 2345 |
2366 if (size_in_bytes <= kSmallListMax) { | 2346 if (size_in_bytes <= kSmallListMax) { |
2367 node = small_list_.PickNodeFromList(size_in_bytes, node_size); | 2347 node = small_list_.PickNodeFromList(size_in_bytes, node_size); |
2368 if (node != NULL) { | 2348 if (node != NULL) { |
2369 DCHECK(size_in_bytes <= *node_size); | 2349 DCHECK(size_in_bytes <= *node_size); |
2370 page = Page::FromAddress(node->address()); | 2350 page = Page::FromAddress(node->address()); |
2371 page->add_available_in_small_free_list(-(*node_size)); | 2351 page->add_available_in_small_free_list(-(*node_size)); |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2579 while (iterator.has_next()) { | 2559 while (iterator.has_next()) { |
2580 Page* page = iterator.next(); | 2560 Page* page = iterator.next(); |
2581 int size = static_cast<int>(page->non_available_small_blocks()); | 2561 int size = static_cast<int>(page->non_available_small_blocks()); |
2582 if (size == 0) continue; | 2562 if (size == 0) continue; |
2583 Address address = page->OffsetToAddress(Page::kPageSize - size); | 2563 Address address = page->OffsetToAddress(Page::kPageSize - size); |
2584 heap()->CreateFillerObjectAt(address, size); | 2564 heap()->CreateFillerObjectAt(address, size); |
2585 } | 2565 } |
2586 } | 2566 } |
2587 | 2567 |
2588 | 2568 |
2589 void PagedSpace::EvictEvacuationCandidatesFromFreeLists() { | 2569 void PagedSpace::EvictEvacuationCandidatesFromLinearAllocationArea() { |
2590 if (allocation_info_.top() >= allocation_info_.limit()) return; | 2570 if (allocation_info_.top() >= allocation_info_.limit()) return; |
2591 | 2571 |
2592 if (Page::FromAllocationTop(allocation_info_.top()) | 2572 if (Page::FromAllocationTop(allocation_info_.top()) |
2593 ->IsEvacuationCandidate()) { | 2573 ->IsEvacuationCandidate()) { |
2594 // Create filler object to keep page iterable if it was iterable. | 2574 // Create filler object to keep page iterable if it was iterable. |
2595 int remaining = | 2575 int remaining = |
2596 static_cast<int>(allocation_info_.limit() - allocation_info_.top()); | 2576 static_cast<int>(allocation_info_.limit() - allocation_info_.top()); |
2597 heap()->CreateFillerObjectAt(allocation_info_.top(), remaining); | 2577 heap()->CreateFillerObjectAt(allocation_info_.top(), remaining); |
2598 | 2578 |
2599 allocation_info_.set_top(NULL); | 2579 allocation_info_.set_top(nullptr); |
2600 allocation_info_.set_limit(NULL); | 2580 allocation_info_.set_limit(nullptr); |
2601 } | 2581 } |
2602 } | 2582 } |
2603 | 2583 |
2604 | 2584 |
2605 HeapObject* PagedSpace::WaitForSweeperThreadsAndRetryAllocation( | 2585 HeapObject* PagedSpace::WaitForSweeperThreadsAndRetryAllocation( |
2606 int size_in_bytes) { | 2586 int size_in_bytes) { |
2607 MarkCompactCollector* collector = heap()->mark_compact_collector(); | 2587 MarkCompactCollector* collector = heap()->mark_compact_collector(); |
2608 if (collector->sweeping_in_progress()) { | 2588 if (collector->sweeping_in_progress()) { |
2609 // Wait for the sweeper threads here and complete the sweeping phase. | 2589 // Wait for the sweeper threads here and complete the sweeping phase. |
2610 collector->EnsureSweepingCompleted(); | 2590 collector->EnsureSweepingCompleted(); |
(...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3156 object->ShortPrint(); | 3136 object->ShortPrint(); |
3157 PrintF("\n"); | 3137 PrintF("\n"); |
3158 } | 3138 } |
3159 printf(" --------------------------------------\n"); | 3139 printf(" --------------------------------------\n"); |
3160 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3140 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
3161 } | 3141 } |
3162 | 3142 |
3163 #endif // DEBUG | 3143 #endif // DEBUG |
3164 } // namespace internal | 3144 } // namespace internal |
3165 } // namespace v8 | 3145 } // namespace v8 |
OLD | NEW |