| 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_.Clear(); | 1017 other->accounting_stats_.Reset(); |
| 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 | |
| 2252 void FreeList::Reset() { | 2214 void FreeList::Reset() { |
| 2253 small_list_.Reset(); | 2215 small_list_.Reset(); |
| 2254 medium_list_.Reset(); | 2216 medium_list_.Reset(); |
| 2255 large_list_.Reset(); | 2217 large_list_.Reset(); |
| 2256 huge_list_.Reset(); | 2218 huge_list_.Reset(); |
| 2257 } | 2219 } |
| 2258 | 2220 |
| 2259 | 2221 |
| 2260 int FreeList::Free(Address start, int size_in_bytes) { | 2222 int FreeList::Free(Address start, int size_in_bytes) { |
| 2261 if (size_in_bytes == 0) return 0; | 2223 if (size_in_bytes == 0) return 0; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2285 } else { | 2247 } else { |
| 2286 huge_list_.Free(free_space, size_in_bytes); | 2248 huge_list_.Free(free_space, size_in_bytes); |
| 2287 page->add_available_in_huge_free_list(size_in_bytes); | 2249 page->add_available_in_huge_free_list(size_in_bytes); |
| 2288 } | 2250 } |
| 2289 | 2251 |
| 2290 DCHECK(IsVeryLong() || available() == SumFreeLists()); | 2252 DCHECK(IsVeryLong() || available() == SumFreeLists()); |
| 2291 return 0; | 2253 return 0; |
| 2292 } | 2254 } |
| 2293 | 2255 |
| 2294 | 2256 |
| 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 | |
| 2327 FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { | 2257 FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { |
| 2328 FreeSpace* node = NULL; | 2258 FreeSpace* node = NULL; |
| 2329 Page* page = NULL; | 2259 Page* page = NULL; |
| 2330 | 2260 |
| 2331 if (size_in_bytes <= kSmallAllocationMax) { | 2261 if (size_in_bytes <= kSmallAllocationMax) { |
| 2332 node = FindNodeIn(kSmall, node_size); | 2262 node = small_list_.PickNodeFromList(node_size); |
| 2333 if (node != nullptr) { | 2263 if (node != NULL) { |
| 2334 DCHECK(size_in_bytes <= node->size()); | 2264 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()); |
| 2335 return node; | 2268 return node; |
| 2336 } | 2269 } |
| 2337 } | 2270 } |
| 2338 | 2271 |
| 2339 if (size_in_bytes <= kMediumAllocationMax) { | 2272 if (size_in_bytes <= kMediumAllocationMax) { |
| 2340 node = FindNodeIn(kMedium, node_size); | 2273 node = medium_list_.PickNodeFromList(node_size); |
| 2341 if (node != nullptr) { | 2274 if (node != NULL) { |
| 2342 DCHECK(size_in_bytes <= node->size()); | 2275 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()); |
| 2343 return node; | 2279 return node; |
| 2344 } | 2280 } |
| 2345 } | 2281 } |
| 2346 | 2282 |
| 2347 if (size_in_bytes <= kLargeAllocationMax) { | 2283 if (size_in_bytes <= kLargeAllocationMax) { |
| 2348 node = FindNodeIn(kLarge, node_size); | 2284 node = large_list_.PickNodeFromList(node_size); |
| 2349 if (node != nullptr) { | 2285 if (node != NULL) { |
| 2350 DCHECK(size_in_bytes <= node->size()); | 2286 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()); |
| 2351 return node; | 2290 return node; |
| 2352 } | 2291 } |
| 2353 } | 2292 } |
| 2354 | 2293 |
| 2355 int huge_list_available = huge_list_.available(); | 2294 int huge_list_available = huge_list_.available(); |
| 2356 FreeSpace* top_node = huge_list_.top(); | 2295 FreeSpace* top_node = huge_list_.top(); |
| 2357 for (FreeSpace** cur = &top_node; *cur != NULL; | 2296 for (FreeSpace** cur = &top_node; *cur != NULL; |
| 2358 cur = (*cur)->next_address()) { | 2297 cur = (*cur)->next_address()) { |
| 2359 FreeSpace* cur_node = *cur; | 2298 FreeSpace* cur_node = *cur; |
| 2360 while (cur_node != NULL && | 2299 while (cur_node != NULL && |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2596 free_list_.Reset(); | 2535 free_list_.Reset(); |
| 2597 } | 2536 } |
| 2598 | 2537 |
| 2599 | 2538 |
| 2600 intptr_t PagedSpace::SizeOfObjects() { | 2539 intptr_t PagedSpace::SizeOfObjects() { |
| 2601 DCHECK(!FLAG_concurrent_sweeping || | 2540 DCHECK(!FLAG_concurrent_sweeping || |
| 2602 heap()->mark_compact_collector()->sweeping_in_progress() || | 2541 heap()->mark_compact_collector()->sweeping_in_progress() || |
| 2603 (unswept_free_bytes_ == 0)); | 2542 (unswept_free_bytes_ == 0)); |
| 2604 const intptr_t size = Size() - unswept_free_bytes_ - (limit() - top()); | 2543 const intptr_t size = Size() - unswept_free_bytes_ - (limit() - top()); |
| 2605 DCHECK_GE(size, 0); | 2544 DCHECK_GE(size, 0); |
| 2545 USE(size); |
| 2606 return size; | 2546 return size; |
| 2607 } | 2547 } |
| 2608 | 2548 |
| 2609 | 2549 |
| 2610 // After we have booted, we have created a map which represents free space | 2550 // After we have booted, we have created a map which represents free space |
| 2611 // on the heap. If there was already a free list then the elements on it | 2551 // on the heap. If there was already a free list then the elements on it |
| 2612 // were created with the wrong FreeSpaceMap (normally NULL), so we need to | 2552 // were created with the wrong FreeSpaceMap (normally NULL), so we need to |
| 2613 // fix them. | 2553 // fix them. |
| 2614 void PagedSpace::RepairFreeListsAfterDeserialization() { | 2554 void PagedSpace::RepairFreeListsAfterDeserialization() { |
| 2615 free_list_.RepairLists(heap()); | 2555 free_list_.RepairLists(heap()); |
| (...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3199 object->ShortPrint(); | 3139 object->ShortPrint(); |
| 3200 PrintF("\n"); | 3140 PrintF("\n"); |
| 3201 } | 3141 } |
| 3202 printf(" --------------------------------------\n"); | 3142 printf(" --------------------------------------\n"); |
| 3203 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3143 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
| 3204 } | 3144 } |
| 3205 | 3145 |
| 3206 #endif // DEBUG | 3146 #endif // DEBUG |
| 3207 } // namespace internal | 3147 } // namespace internal |
| 3208 } // namespace v8 | 3148 } // namespace v8 |
| OLD | NEW |