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 996 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1007 // area_size_ | 1007 // area_size_ |
1008 // allocation_info_ | 1008 // allocation_info_ |
1009 // end_of_unswept_pages_ | 1009 // end_of_unswept_pages_ |
1010 // unswept_free_bytes_ | 1010 // unswept_free_bytes_ |
1011 // anchor_ | 1011 // anchor_ |
1012 | 1012 |
1013 MoveOverFreeMemory(other); | 1013 MoveOverFreeMemory(other); |
1014 | 1014 |
1015 // Update and clear accounting statistics. | 1015 // Update and clear accounting statistics. |
1016 accounting_stats_.Merge(other->accounting_stats_); | 1016 accounting_stats_.Merge(other->accounting_stats_); |
1017 other->accounting_stats_.Reset(); | 1017 other->accounting_stats_.Clear(); |
1018 | 1018 |
1019 // Move over pages. | 1019 // Move over pages. |
1020 PageIterator it(other); | 1020 PageIterator it(other); |
1021 Page* p = nullptr; | 1021 Page* p = nullptr; |
1022 while (it.has_next()) { | 1022 while (it.has_next()) { |
1023 p = it.next(); | 1023 p = it.next(); |
1024 p->Unlink(); | 1024 p->Unlink(); |
1025 p->set_owner(this); | 1025 p->set_owner(this); |
1026 p->InsertAfter(anchor_.prev_page()); | 1026 p->InsertAfter(anchor_.prev_page()); |
1027 } | 1027 } |
(...skipping 1176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2204 intptr_t FreeList::Concatenate(FreeList* free_list) { | 2204 intptr_t FreeList::Concatenate(FreeList* free_list) { |
2205 intptr_t free_bytes = 0; | 2205 intptr_t free_bytes = 0; |
2206 free_bytes += small_list_.Concatenate(free_list->small_list()); | 2206 free_bytes += small_list_.Concatenate(free_list->small_list()); |
2207 free_bytes += medium_list_.Concatenate(free_list->medium_list()); | 2207 free_bytes += medium_list_.Concatenate(free_list->medium_list()); |
2208 free_bytes += large_list_.Concatenate(free_list->large_list()); | 2208 free_bytes += large_list_.Concatenate(free_list->large_list()); |
2209 free_bytes += huge_list_.Concatenate(free_list->huge_list()); | 2209 free_bytes += huge_list_.Concatenate(free_list->huge_list()); |
2210 return free_bytes; | 2210 return free_bytes; |
2211 } | 2211 } |
2212 | 2212 |
2213 | 2213 |
| 2214 FreeSpace* PagedSpace::TryRemoveMemory() { |
| 2215 FreeSpace* space = nullptr; |
| 2216 int node_size = 0; |
| 2217 space = free_list()->FindNodeIn(FreeList::kHuge, &node_size); |
| 2218 if (space == nullptr) |
| 2219 space = free_list()->FindNodeIn(FreeList::kLarge, &node_size); |
| 2220 if (space == nullptr) |
| 2221 space = free_list()->FindNodeIn(FreeList::kMedium, &node_size); |
| 2222 if (space == nullptr) |
| 2223 space = free_list()->FindNodeIn(FreeList::kSmall, &node_size); |
| 2224 if (space != nullptr) { |
| 2225 accounting_stats_.AllocateBytes(node_size); |
| 2226 } |
| 2227 return space; |
| 2228 } |
| 2229 |
| 2230 |
| 2231 void PagedSpace::DivideMemory(CompactionSpaceCollection** other, int num, |
| 2232 intptr_t limit) { |
| 2233 CHECK(num > 0); |
| 2234 CHECK(other != nullptr); |
| 2235 |
| 2236 if (limit == 0) limit = std::numeric_limits<intptr_t>::max(); |
| 2237 |
| 2238 EmptyAllocationInfo(); |
| 2239 |
| 2240 int index = 0; |
| 2241 FreeSpace* node = nullptr; |
| 2242 for (CompactionSpace* space = other[index]->Get(identity()); |
| 2243 ((node = TryRemoveMemory()) != nullptr) && |
| 2244 (space->free_list()->available() < limit); |
| 2245 space = other[++index % num]->Get(identity())) { |
| 2246 CHECK(space->identity() == identity()); |
| 2247 space->AddMemory(node->address(), node->size()); |
| 2248 } |
| 2249 } |
| 2250 |
| 2251 |
2214 void FreeList::Reset() { | 2252 void FreeList::Reset() { |
2215 small_list_.Reset(); | 2253 small_list_.Reset(); |
2216 medium_list_.Reset(); | 2254 medium_list_.Reset(); |
2217 large_list_.Reset(); | 2255 large_list_.Reset(); |
2218 huge_list_.Reset(); | 2256 huge_list_.Reset(); |
2219 } | 2257 } |
2220 | 2258 |
2221 | 2259 |
2222 int FreeList::Free(Address start, int size_in_bytes) { | 2260 int FreeList::Free(Address start, int size_in_bytes) { |
2223 if (size_in_bytes == 0) return 0; | 2261 if (size_in_bytes == 0) return 0; |
(...skipping 23 matching lines...) Expand all Loading... |
2247 } else { | 2285 } else { |
2248 huge_list_.Free(free_space, size_in_bytes); | 2286 huge_list_.Free(free_space, size_in_bytes); |
2249 page->add_available_in_huge_free_list(size_in_bytes); | 2287 page->add_available_in_huge_free_list(size_in_bytes); |
2250 } | 2288 } |
2251 | 2289 |
2252 DCHECK(IsVeryLong() || available() == SumFreeLists()); | 2290 DCHECK(IsVeryLong() || available() == SumFreeLists()); |
2253 return 0; | 2291 return 0; |
2254 } | 2292 } |
2255 | 2293 |
2256 | 2294 |
| 2295 void FreeList::UpdateFragmentationStats(FreeListCategoryType category, |
| 2296 Address address, int size) { |
| 2297 Page* page = Page::FromAddress(address); |
| 2298 switch (category) { |
| 2299 case kSmall: |
| 2300 page->add_available_in_small_free_list(size); |
| 2301 break; |
| 2302 case kMedium: |
| 2303 page->add_available_in_medium_free_list(size); |
| 2304 break; |
| 2305 case kLarge: |
| 2306 page->add_available_in_large_free_list(size); |
| 2307 break; |
| 2308 case kHuge: |
| 2309 page->add_available_in_huge_free_list(size); |
| 2310 break; |
| 2311 default: |
| 2312 UNREACHABLE(); |
| 2313 } |
| 2314 } |
| 2315 |
| 2316 |
| 2317 FreeSpace* FreeList::FindNodeIn(FreeListCategoryType category, int* node_size) { |
| 2318 FreeSpace* node = GetFreeListCategory(category)->PickNodeFromList(node_size); |
| 2319 if (node != nullptr) { |
| 2320 UpdateFragmentationStats(category, node->address(), -(*node_size)); |
| 2321 DCHECK(IsVeryLong() || available() == SumFreeLists()); |
| 2322 } |
| 2323 return node; |
| 2324 } |
| 2325 |
| 2326 |
2257 FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { | 2327 FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { |
2258 FreeSpace* node = NULL; | 2328 FreeSpace* node = NULL; |
2259 Page* page = NULL; | 2329 Page* page = NULL; |
2260 | 2330 |
2261 if (size_in_bytes <= kSmallAllocationMax) { | 2331 if (size_in_bytes <= kSmallAllocationMax) { |
2262 node = small_list_.PickNodeFromList(node_size); | 2332 node = FindNodeIn(kSmall, node_size); |
2263 if (node != NULL) { | 2333 if (node != nullptr) { |
2264 DCHECK(size_in_bytes <= *node_size); | 2334 DCHECK(size_in_bytes <= node->size()); |
2265 page = Page::FromAddress(node->address()); | |
2266 page->add_available_in_small_free_list(-(*node_size)); | |
2267 DCHECK(IsVeryLong() || available() == SumFreeLists()); | |
2268 return node; | 2335 return node; |
2269 } | 2336 } |
2270 } | 2337 } |
2271 | 2338 |
2272 if (size_in_bytes <= kMediumAllocationMax) { | 2339 if (size_in_bytes <= kMediumAllocationMax) { |
2273 node = medium_list_.PickNodeFromList(node_size); | 2340 node = FindNodeIn(kMedium, node_size); |
2274 if (node != NULL) { | 2341 if (node != nullptr) { |
2275 DCHECK(size_in_bytes <= *node_size); | 2342 DCHECK(size_in_bytes <= node->size()); |
2276 page = Page::FromAddress(node->address()); | |
2277 page->add_available_in_medium_free_list(-(*node_size)); | |
2278 DCHECK(IsVeryLong() || available() == SumFreeLists()); | |
2279 return node; | 2343 return node; |
2280 } | 2344 } |
2281 } | 2345 } |
2282 | 2346 |
2283 if (size_in_bytes <= kLargeAllocationMax) { | 2347 if (size_in_bytes <= kLargeAllocationMax) { |
2284 node = large_list_.PickNodeFromList(node_size); | 2348 node = FindNodeIn(kLarge, node_size); |
2285 if (node != NULL) { | 2349 if (node != nullptr) { |
2286 DCHECK(size_in_bytes <= *node_size); | 2350 DCHECK(size_in_bytes <= node->size()); |
2287 page = Page::FromAddress(node->address()); | |
2288 page->add_available_in_large_free_list(-(*node_size)); | |
2289 DCHECK(IsVeryLong() || available() == SumFreeLists()); | |
2290 return node; | 2351 return node; |
2291 } | 2352 } |
2292 } | 2353 } |
2293 | 2354 |
2294 int huge_list_available = huge_list_.available(); | 2355 int huge_list_available = huge_list_.available(); |
2295 FreeSpace* top_node = huge_list_.top(); | 2356 FreeSpace* top_node = huge_list_.top(); |
2296 for (FreeSpace** cur = &top_node; *cur != NULL; | 2357 for (FreeSpace** cur = &top_node; *cur != NULL; |
2297 cur = (*cur)->next_address()) { | 2358 cur = (*cur)->next_address()) { |
2298 FreeSpace* cur_node = *cur; | 2359 FreeSpace* cur_node = *cur; |
2299 while (cur_node != NULL && | 2360 while (cur_node != NULL && |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2535 free_list_.Reset(); | 2596 free_list_.Reset(); |
2536 } | 2597 } |
2537 | 2598 |
2538 | 2599 |
2539 intptr_t PagedSpace::SizeOfObjects() { | 2600 intptr_t PagedSpace::SizeOfObjects() { |
2540 DCHECK(!FLAG_concurrent_sweeping || | 2601 DCHECK(!FLAG_concurrent_sweeping || |
2541 heap()->mark_compact_collector()->sweeping_in_progress() || | 2602 heap()->mark_compact_collector()->sweeping_in_progress() || |
2542 (unswept_free_bytes_ == 0)); | 2603 (unswept_free_bytes_ == 0)); |
2543 const intptr_t size = Size() - unswept_free_bytes_ - (limit() - top()); | 2604 const intptr_t size = Size() - unswept_free_bytes_ - (limit() - top()); |
2544 DCHECK_GE(size, 0); | 2605 DCHECK_GE(size, 0); |
2545 USE(size); | |
2546 return size; | 2606 return size; |
2547 } | 2607 } |
2548 | 2608 |
2549 | 2609 |
2550 // After we have booted, we have created a map which represents free space | 2610 // After we have booted, we have created a map which represents free space |
2551 // on the heap. If there was already a free list then the elements on it | 2611 // on the heap. If there was already a free list then the elements on it |
2552 // were created with the wrong FreeSpaceMap (normally NULL), so we need to | 2612 // were created with the wrong FreeSpaceMap (normally NULL), so we need to |
2553 // fix them. | 2613 // fix them. |
2554 void PagedSpace::RepairFreeListsAfterDeserialization() { | 2614 void PagedSpace::RepairFreeListsAfterDeserialization() { |
2555 free_list_.RepairLists(heap()); | 2615 free_list_.RepairLists(heap()); |
(...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3139 object->ShortPrint(); | 3199 object->ShortPrint(); |
3140 PrintF("\n"); | 3200 PrintF("\n"); |
3141 } | 3201 } |
3142 printf(" --------------------------------------\n"); | 3202 printf(" --------------------------------------\n"); |
3143 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3203 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
3144 } | 3204 } |
3145 | 3205 |
3146 #endif // DEBUG | 3206 #endif // DEBUG |
3147 } // namespace internal | 3207 } // namespace internal |
3148 } // namespace v8 | 3208 } // namespace v8 |
OLD | NEW |