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 758 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
769 return MemoryChunk::Initialize(heap, base, chunk_size, area_start, area_end, | 769 return MemoryChunk::Initialize(heap, base, chunk_size, area_start, area_end, |
770 executable, owner, &reservation); | 770 executable, owner, &reservation); |
771 } | 771 } |
772 | 772 |
773 | 773 |
774 void Page::ResetFreeListStatistics() { | 774 void Page::ResetFreeListStatistics() { |
775 wasted_memory_ = 0; | 775 wasted_memory_ = 0; |
776 available_in_free_list_ = 0; | 776 available_in_free_list_ = 0; |
777 } | 777 } |
778 | 778 |
| 779 size_t Page::AvailableInFreeList() { |
| 780 size_t sum = 0; |
| 781 ForAllFreeListCategories([this, &sum](FreeListCategory* category) { |
| 782 sum += category->available(); |
| 783 }); |
| 784 return sum; |
| 785 } |
| 786 |
779 size_t Page::ShrinkToHighWaterMark() { | 787 size_t Page::ShrinkToHighWaterMark() { |
780 // Shrink pages to high water mark. The water mark points either to a filler | 788 // Shrink pages to high water mark. The water mark points either to a filler |
781 // or the area_end. | 789 // or the area_end. |
782 HeapObject* filler = HeapObject::FromAddress(HighWaterMark()); | 790 HeapObject* filler = HeapObject::FromAddress(HighWaterMark()); |
783 if (filler->address() == area_end()) return 0; | 791 if (filler->address() == area_end()) return 0; |
784 CHECK(filler->IsFiller()); | 792 CHECK(filler->IsFiller()); |
785 if (!filler->IsFreeSpace()) return 0; | 793 if (!filler->IsFreeSpace()) return 0; |
786 | 794 |
787 #ifdef DEBUG | 795 #ifdef DEBUG |
788 // Check the the filler is indeed the last filler on the page. | 796 // Check the the filler is indeed the last filler on the page. |
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1238 for (auto it = other->begin(); it != other->end();) { | 1246 for (auto it = other->begin(); it != other->end();) { |
1239 Page* p = *(it++); | 1247 Page* p = *(it++); |
1240 | 1248 |
1241 // Relinking requires the category to be unlinked. | 1249 // Relinking requires the category to be unlinked. |
1242 other->UnlinkFreeListCategories(p); | 1250 other->UnlinkFreeListCategories(p); |
1243 | 1251 |
1244 p->Unlink(); | 1252 p->Unlink(); |
1245 p->set_owner(this); | 1253 p->set_owner(this); |
1246 p->InsertAfter(anchor_.prev_page()); | 1254 p->InsertAfter(anchor_.prev_page()); |
1247 RelinkFreeListCategories(p); | 1255 RelinkFreeListCategories(p); |
| 1256 DCHECK_EQ(p->AvailableInFreeList(), p->available_in_free_list()); |
1248 } | 1257 } |
1249 } | 1258 } |
1250 | 1259 |
1251 | 1260 |
1252 size_t PagedSpace::CommittedPhysicalMemory() { | 1261 size_t PagedSpace::CommittedPhysicalMemory() { |
1253 if (!base::VirtualMemory::HasLazyCommits()) return CommittedMemory(); | 1262 if (!base::VirtualMemory::HasLazyCommits()) return CommittedMemory(); |
1254 MemoryChunk::UpdateHighWaterMark(allocation_info_.top()); | 1263 MemoryChunk::UpdateHighWaterMark(allocation_info_.top()); |
1255 size_t size = 0; | 1264 size_t size = 0; |
1256 for (Page* page : *this) { | 1265 for (Page* page : *this) { |
1257 size += page->CommittedPhysicalMemory(); | 1266 size += page->CommittedPhysicalMemory(); |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1382 | 1391 |
1383 // Clear the bits in the unused black area. | 1392 // Clear the bits in the unused black area. |
1384 if (current_top != current_limit) { | 1393 if (current_top != current_limit) { |
1385 page->markbits()->ClearRange(page->AddressToMarkbitIndex(current_top), | 1394 page->markbits()->ClearRange(page->AddressToMarkbitIndex(current_top), |
1386 page->AddressToMarkbitIndex(current_limit)); | 1395 page->AddressToMarkbitIndex(current_limit)); |
1387 page->IncrementLiveBytes(-static_cast<int>(current_limit - current_top)); | 1396 page->IncrementLiveBytes(-static_cast<int>(current_limit - current_top)); |
1388 } | 1397 } |
1389 } | 1398 } |
1390 | 1399 |
1391 SetTopAndLimit(NULL, NULL); | 1400 SetTopAndLimit(NULL, NULL); |
1392 Free(current_top, static_cast<int>(current_limit - current_top)); | 1401 DCHECK_GE(current_limit, current_top); |
| 1402 Free(current_top, current_limit - current_top); |
1393 } | 1403 } |
1394 | 1404 |
1395 void PagedSpace::IncreaseCapacity(size_t bytes) { | 1405 void PagedSpace::IncreaseCapacity(size_t bytes) { |
1396 accounting_stats_.ExpandSpace(bytes); | 1406 accounting_stats_.ExpandSpace(bytes); |
1397 } | 1407 } |
1398 | 1408 |
1399 void PagedSpace::ReleasePage(Page* page) { | 1409 void PagedSpace::ReleasePage(Page* page) { |
1400 DCHECK_EQ(page->LiveBytes(), 0); | 1410 DCHECK_EQ(page->LiveBytes(), 0); |
1401 DCHECK_EQ(page->owner(), this); | 1411 DCHECK_EQ(page->owner(), this); |
1402 | 1412 |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1592 current_page = | 1602 current_page = |
1593 heap()->memory_allocator()->AllocatePage<MemoryAllocator::kPooled>( | 1603 heap()->memory_allocator()->AllocatePage<MemoryAllocator::kPooled>( |
1594 Page::kAllocatableMemory, this, executable()); | 1604 Page::kAllocatableMemory, this, executable()); |
1595 if (current_page == nullptr) return false; | 1605 if (current_page == nullptr) return false; |
1596 DCHECK_NOT_NULL(current_page); | 1606 DCHECK_NOT_NULL(current_page); |
1597 current_page->InsertAfter(anchor()); | 1607 current_page->InsertAfter(anchor()); |
1598 current_page->ClearLiveness(); | 1608 current_page->ClearLiveness(); |
1599 current_page->SetFlags(anchor()->prev_page()->GetFlags(), | 1609 current_page->SetFlags(anchor()->prev_page()->GetFlags(), |
1600 Page::kCopyAllFlags); | 1610 Page::kCopyAllFlags); |
1601 heap()->CreateFillerObjectAt(current_page->area_start(), | 1611 heap()->CreateFillerObjectAt(current_page->area_start(), |
1602 current_page->area_size(), | 1612 static_cast<int>(current_page->area_size()), |
1603 ClearRecordedSlots::kNo); | 1613 ClearRecordedSlots::kNo); |
1604 } | 1614 } |
1605 } | 1615 } |
1606 return true; | 1616 return true; |
1607 } | 1617 } |
1608 | 1618 |
1609 void LocalAllocationBuffer::Close() { | 1619 void LocalAllocationBuffer::Close() { |
1610 if (IsValid()) { | 1620 if (IsValid()) { |
1611 heap_->CreateFillerObjectAt( | 1621 heap_->CreateFillerObjectAt( |
1612 allocation_info_.top(), | 1622 allocation_info_.top(), |
(...skipping 718 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2331 // Free lists for old object spaces implementation | 2341 // Free lists for old object spaces implementation |
2332 | 2342 |
2333 | 2343 |
2334 void FreeListCategory::Reset() { | 2344 void FreeListCategory::Reset() { |
2335 set_top(nullptr); | 2345 set_top(nullptr); |
2336 set_prev(nullptr); | 2346 set_prev(nullptr); |
2337 set_next(nullptr); | 2347 set_next(nullptr); |
2338 available_ = 0; | 2348 available_ = 0; |
2339 } | 2349 } |
2340 | 2350 |
2341 FreeSpace* FreeListCategory::PickNodeFromList(int* node_size) { | 2351 FreeSpace* FreeListCategory::PickNodeFromList(size_t* node_size) { |
2342 DCHECK(page()->CanAllocate()); | 2352 DCHECK(page()->CanAllocate()); |
2343 | 2353 |
2344 FreeSpace* node = top(); | 2354 FreeSpace* node = top(); |
2345 if (node == nullptr) return nullptr; | 2355 if (node == nullptr) return nullptr; |
2346 set_top(node->next()); | 2356 set_top(node->next()); |
2347 *node_size = node->Size(); | 2357 *node_size = node->Size(); |
2348 available_ -= *node_size; | 2358 available_ -= *node_size; |
2349 return node; | 2359 return node; |
2350 } | 2360 } |
2351 | 2361 |
2352 FreeSpace* FreeListCategory::TryPickNodeFromList(int minimum_size, | 2362 FreeSpace* FreeListCategory::TryPickNodeFromList(size_t minimum_size, |
2353 int* node_size) { | 2363 size_t* node_size) { |
2354 DCHECK(page()->CanAllocate()); | 2364 DCHECK(page()->CanAllocate()); |
2355 | 2365 |
2356 FreeSpace* node = PickNodeFromList(node_size); | 2366 FreeSpace* node = PickNodeFromList(node_size); |
2357 if ((node != nullptr) && (*node_size < minimum_size)) { | 2367 if ((node != nullptr) && (*node_size < minimum_size)) { |
2358 Free(node, *node_size, kLinkCategory); | 2368 Free(node, *node_size, kLinkCategory); |
2359 *node_size = 0; | 2369 *node_size = 0; |
2360 return nullptr; | 2370 return nullptr; |
2361 } | 2371 } |
2362 return node; | 2372 return node; |
2363 } | 2373 } |
2364 | 2374 |
2365 FreeSpace* FreeListCategory::SearchForNodeInList(int minimum_size, | 2375 FreeSpace* FreeListCategory::SearchForNodeInList(size_t minimum_size, |
2366 int* node_size) { | 2376 size_t* node_size) { |
2367 DCHECK(page()->CanAllocate()); | 2377 DCHECK(page()->CanAllocate()); |
2368 | 2378 |
2369 FreeSpace* prev_non_evac_node = nullptr; | 2379 FreeSpace* prev_non_evac_node = nullptr; |
2370 for (FreeSpace* cur_node = top(); cur_node != nullptr; | 2380 for (FreeSpace* cur_node = top(); cur_node != nullptr; |
2371 cur_node = cur_node->next()) { | 2381 cur_node = cur_node->next()) { |
2372 int size = cur_node->size(); | 2382 size_t size = cur_node->size(); |
2373 if (size >= minimum_size) { | 2383 if (size >= minimum_size) { |
| 2384 DCHECK_GE(available_, size); |
2374 available_ -= size; | 2385 available_ -= size; |
2375 if (cur_node == top()) { | 2386 if (cur_node == top()) { |
2376 set_top(cur_node->next()); | 2387 set_top(cur_node->next()); |
2377 } | 2388 } |
2378 if (prev_non_evac_node != nullptr) { | 2389 if (prev_non_evac_node != nullptr) { |
2379 prev_non_evac_node->set_next(cur_node->next()); | 2390 prev_non_evac_node->set_next(cur_node->next()); |
2380 } | 2391 } |
2381 *node_size = size; | 2392 *node_size = size; |
2382 return cur_node; | 2393 return cur_node; |
2383 } | 2394 } |
2384 | 2395 |
2385 prev_non_evac_node = cur_node; | 2396 prev_non_evac_node = cur_node; |
2386 } | 2397 } |
2387 return nullptr; | 2398 return nullptr; |
2388 } | 2399 } |
2389 | 2400 |
2390 bool FreeListCategory::Free(FreeSpace* free_space, int size_in_bytes, | 2401 bool FreeListCategory::Free(FreeSpace* free_space, size_t size_in_bytes, |
2391 FreeMode mode) { | 2402 FreeMode mode) { |
2392 if (!page()->CanAllocate()) return false; | 2403 if (!page()->CanAllocate()) return false; |
2393 | 2404 |
2394 free_space->set_next(top()); | 2405 free_space->set_next(top()); |
2395 set_top(free_space); | 2406 set_top(free_space); |
2396 available_ += size_in_bytes; | 2407 available_ += size_in_bytes; |
2397 if ((mode == kLinkCategory) && (prev() == nullptr) && (next() == nullptr)) { | 2408 if ((mode == kLinkCategory) && (prev() == nullptr) && (next() == nullptr)) { |
2398 owner()->AddCategory(this); | 2409 owner()->AddCategory(this); |
2399 } | 2410 } |
2400 return true; | 2411 return true; |
(...skipping 12 matching lines...) Expand all Loading... |
2413 n = n->next(); | 2424 n = n->next(); |
2414 } | 2425 } |
2415 } | 2426 } |
2416 | 2427 |
2417 void FreeListCategory::Relink() { | 2428 void FreeListCategory::Relink() { |
2418 DCHECK(!is_linked()); | 2429 DCHECK(!is_linked()); |
2419 owner()->AddCategory(this); | 2430 owner()->AddCategory(this); |
2420 } | 2431 } |
2421 | 2432 |
2422 void FreeListCategory::Invalidate() { | 2433 void FreeListCategory::Invalidate() { |
2423 page()->add_available_in_free_list(-available()); | 2434 page()->remove_available_in_free_list(available()); |
2424 Reset(); | 2435 Reset(); |
2425 type_ = kInvalidCategory; | 2436 type_ = kInvalidCategory; |
2426 } | 2437 } |
2427 | 2438 |
2428 FreeList::FreeList(PagedSpace* owner) : owner_(owner), wasted_bytes_(0) { | 2439 FreeList::FreeList(PagedSpace* owner) : owner_(owner), wasted_bytes_(0) { |
2429 for (int i = kFirstCategory; i < kNumberOfCategories; i++) { | 2440 for (int i = kFirstCategory; i < kNumberOfCategories; i++) { |
2430 categories_[i] = nullptr; | 2441 categories_[i] = nullptr; |
2431 } | 2442 } |
2432 Reset(); | 2443 Reset(); |
2433 } | 2444 } |
2434 | 2445 |
2435 | 2446 |
2436 void FreeList::Reset() { | 2447 void FreeList::Reset() { |
2437 ForAllFreeListCategories( | 2448 ForAllFreeListCategories( |
2438 [](FreeListCategory* category) { category->Reset(); }); | 2449 [](FreeListCategory* category) { category->Reset(); }); |
2439 for (int i = kFirstCategory; i < kNumberOfCategories; i++) { | 2450 for (int i = kFirstCategory; i < kNumberOfCategories; i++) { |
2440 categories_[i] = nullptr; | 2451 categories_[i] = nullptr; |
2441 } | 2452 } |
2442 ResetStats(); | 2453 ResetStats(); |
2443 } | 2454 } |
2444 | 2455 |
2445 int FreeList::Free(Address start, int size_in_bytes, FreeMode mode) { | 2456 size_t FreeList::Free(Address start, size_t size_in_bytes, FreeMode mode) { |
2446 if (size_in_bytes == 0) return 0; | 2457 if (size_in_bytes == 0) return 0; |
2447 | 2458 |
2448 owner()->heap()->CreateFillerObjectAt(start, size_in_bytes, | 2459 owner()->heap()->CreateFillerObjectAt(start, static_cast<int>(size_in_bytes), |
2449 ClearRecordedSlots::kNo); | 2460 ClearRecordedSlots::kNo); |
2450 | 2461 |
2451 Page* page = Page::FromAddress(start); | 2462 Page* page = Page::FromAddress(start); |
2452 | 2463 |
2453 // Blocks have to be a minimum size to hold free list items. | 2464 // Blocks have to be a minimum size to hold free list items. |
2454 if (size_in_bytes < kMinBlockSize) { | 2465 if (size_in_bytes < kMinBlockSize) { |
2455 page->add_wasted_memory(size_in_bytes); | 2466 page->add_wasted_memory(size_in_bytes); |
2456 wasted_bytes_.Increment(size_in_bytes); | 2467 wasted_bytes_.Increment(size_in_bytes); |
2457 return size_in_bytes; | 2468 return size_in_bytes; |
2458 } | 2469 } |
2459 | 2470 |
2460 FreeSpace* free_space = FreeSpace::cast(HeapObject::FromAddress(start)); | 2471 FreeSpace* free_space = FreeSpace::cast(HeapObject::FromAddress(start)); |
2461 // Insert other blocks at the head of a free list of the appropriate | 2472 // Insert other blocks at the head of a free list of the appropriate |
2462 // magnitude. | 2473 // magnitude. |
2463 FreeListCategoryType type = SelectFreeListCategoryType(size_in_bytes); | 2474 FreeListCategoryType type = SelectFreeListCategoryType(size_in_bytes); |
2464 if (page->free_list_category(type)->Free(free_space, size_in_bytes, mode)) { | 2475 if (page->free_list_category(type)->Free(free_space, size_in_bytes, mode)) { |
2465 page->add_available_in_free_list(size_in_bytes); | 2476 page->add_available_in_free_list(size_in_bytes); |
2466 } | 2477 } |
| 2478 DCHECK_EQ(page->AvailableInFreeList(), page->available_in_free_list()); |
2467 return 0; | 2479 return 0; |
2468 } | 2480 } |
2469 | 2481 |
2470 FreeSpace* FreeList::FindNodeIn(FreeListCategoryType type, int* node_size) { | 2482 FreeSpace* FreeList::FindNodeIn(FreeListCategoryType type, size_t* node_size) { |
2471 FreeListCategoryIterator it(this, type); | 2483 FreeListCategoryIterator it(this, type); |
2472 FreeSpace* node = nullptr; | 2484 FreeSpace* node = nullptr; |
2473 while (it.HasNext()) { | 2485 while (it.HasNext()) { |
2474 FreeListCategory* current = it.Next(); | 2486 FreeListCategory* current = it.Next(); |
2475 node = current->PickNodeFromList(node_size); | 2487 node = current->PickNodeFromList(node_size); |
2476 if (node != nullptr) { | 2488 if (node != nullptr) { |
2477 Page::FromAddress(node->address()) | 2489 Page::FromAddress(node->address()) |
2478 ->add_available_in_free_list(-(*node_size)); | 2490 ->remove_available_in_free_list(*node_size); |
2479 DCHECK(IsVeryLong() || Available() == SumFreeLists()); | 2491 DCHECK(IsVeryLong() || Available() == SumFreeLists()); |
2480 return node; | 2492 return node; |
2481 } | 2493 } |
2482 RemoveCategory(current); | 2494 RemoveCategory(current); |
2483 } | 2495 } |
2484 return node; | 2496 return node; |
2485 } | 2497 } |
2486 | 2498 |
2487 FreeSpace* FreeList::TryFindNodeIn(FreeListCategoryType type, int* node_size, | 2499 FreeSpace* FreeList::TryFindNodeIn(FreeListCategoryType type, size_t* node_size, |
2488 int minimum_size) { | 2500 size_t minimum_size) { |
2489 if (categories_[type] == nullptr) return nullptr; | 2501 if (categories_[type] == nullptr) return nullptr; |
2490 FreeSpace* node = | 2502 FreeSpace* node = |
2491 categories_[type]->TryPickNodeFromList(minimum_size, node_size); | 2503 categories_[type]->TryPickNodeFromList(minimum_size, node_size); |
2492 if (node != nullptr) { | 2504 if (node != nullptr) { |
2493 Page::FromAddress(node->address()) | 2505 Page::FromAddress(node->address()) |
2494 ->add_available_in_free_list(-(*node_size)); | 2506 ->remove_available_in_free_list(*node_size); |
2495 DCHECK(IsVeryLong() || Available() == SumFreeLists()); | 2507 DCHECK(IsVeryLong() || Available() == SumFreeLists()); |
2496 } | 2508 } |
2497 return node; | 2509 return node; |
2498 } | 2510 } |
2499 | 2511 |
2500 FreeSpace* FreeList::SearchForNodeInList(FreeListCategoryType type, | 2512 FreeSpace* FreeList::SearchForNodeInList(FreeListCategoryType type, |
2501 int* node_size, int minimum_size) { | 2513 size_t* node_size, |
| 2514 size_t minimum_size) { |
2502 FreeListCategoryIterator it(this, type); | 2515 FreeListCategoryIterator it(this, type); |
2503 FreeSpace* node = nullptr; | 2516 FreeSpace* node = nullptr; |
2504 while (it.HasNext()) { | 2517 while (it.HasNext()) { |
2505 FreeListCategory* current = it.Next(); | 2518 FreeListCategory* current = it.Next(); |
2506 node = current->SearchForNodeInList(minimum_size, node_size); | 2519 node = current->SearchForNodeInList(minimum_size, node_size); |
2507 if (node != nullptr) { | 2520 if (node != nullptr) { |
2508 Page::FromAddress(node->address()) | 2521 Page::FromAddress(node->address()) |
2509 ->add_available_in_free_list(-(*node_size)); | 2522 ->remove_available_in_free_list(*node_size); |
2510 DCHECK(IsVeryLong() || Available() == SumFreeLists()); | 2523 DCHECK(IsVeryLong() || Available() == SumFreeLists()); |
2511 return node; | 2524 return node; |
2512 } | 2525 } |
2513 if (current->is_empty()) { | 2526 if (current->is_empty()) { |
2514 RemoveCategory(current); | 2527 RemoveCategory(current); |
2515 } | 2528 } |
2516 } | 2529 } |
2517 return node; | 2530 return node; |
2518 } | 2531 } |
2519 | 2532 |
2520 FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { | 2533 FreeSpace* FreeList::FindNodeFor(size_t size_in_bytes, size_t* node_size) { |
2521 FreeSpace* node = nullptr; | 2534 FreeSpace* node = nullptr; |
2522 | 2535 |
2523 // First try the allocation fast path: try to allocate the minimum element | 2536 // First try the allocation fast path: try to allocate the minimum element |
2524 // size of a free list category. This operation is constant time. | 2537 // size of a free list category. This operation is constant time. |
2525 FreeListCategoryType type = | 2538 FreeListCategoryType type = |
2526 SelectFastAllocationFreeListCategoryType(size_in_bytes); | 2539 SelectFastAllocationFreeListCategoryType(size_in_bytes); |
2527 for (int i = type; i < kHuge; i++) { | 2540 for (int i = type; i < kHuge; i++) { |
2528 node = FindNodeIn(static_cast<FreeListCategoryType>(i), node_size); | 2541 node = FindNodeIn(static_cast<FreeListCategoryType>(i), node_size); |
2529 if (node != nullptr) return node; | 2542 if (node != nullptr) return node; |
2530 } | 2543 } |
(...skipping 16 matching lines...) Expand all Loading... |
2547 node = TryFindNodeIn(type, node_size, size_in_bytes); | 2560 node = TryFindNodeIn(type, node_size, size_in_bytes); |
2548 | 2561 |
2549 DCHECK(IsVeryLong() || Available() == SumFreeLists()); | 2562 DCHECK(IsVeryLong() || Available() == SumFreeLists()); |
2550 return node; | 2563 return node; |
2551 } | 2564 } |
2552 | 2565 |
2553 // Allocation on the old space free list. If it succeeds then a new linear | 2566 // Allocation on the old space free list. If it succeeds then a new linear |
2554 // allocation space has been set up with the top and limit of the space. If | 2567 // allocation space has been set up with the top and limit of the space. If |
2555 // the allocation fails then NULL is returned, and the caller can perform a GC | 2568 // the allocation fails then NULL is returned, and the caller can perform a GC |
2556 // or allocate a new page before retrying. | 2569 // or allocate a new page before retrying. |
2557 HeapObject* FreeList::Allocate(int size_in_bytes) { | 2570 HeapObject* FreeList::Allocate(size_t size_in_bytes) { |
2558 DCHECK(0 < size_in_bytes); | |
2559 DCHECK(size_in_bytes <= kMaxBlockSize); | 2571 DCHECK(size_in_bytes <= kMaxBlockSize); |
2560 DCHECK(IsAligned(size_in_bytes, kPointerSize)); | 2572 DCHECK(IsAligned(size_in_bytes, kPointerSize)); |
2561 // Don't free list allocate if there is linear space available. | 2573 // Don't free list allocate if there is linear space available. |
2562 DCHECK(owner_->limit() - owner_->top() < size_in_bytes); | 2574 DCHECK_LT(static_cast<size_t>(owner_->limit() - owner_->top()), |
| 2575 size_in_bytes); |
2563 | 2576 |
2564 // Mark the old linear allocation area with a free space map so it can be | 2577 // Mark the old linear allocation area with a free space map so it can be |
2565 // skipped when scanning the heap. This also puts it back in the free list | 2578 // skipped when scanning the heap. This also puts it back in the free list |
2566 // if it is big enough. | 2579 // if it is big enough. |
2567 owner_->EmptyAllocationInfo(); | 2580 owner_->EmptyAllocationInfo(); |
2568 | 2581 |
2569 owner_->heap()->StartIncrementalMarkingIfAllocationLimitIsReached( | 2582 owner_->heap()->StartIncrementalMarkingIfAllocationLimitIsReached( |
2570 Heap::kNoGCFlags, kNoGCCallbackFlags); | 2583 Heap::kNoGCFlags, kNoGCCallbackFlags); |
2571 | 2584 |
2572 int new_node_size = 0; | 2585 size_t new_node_size = 0; |
2573 FreeSpace* new_node = FindNodeFor(size_in_bytes, &new_node_size); | 2586 FreeSpace* new_node = FindNodeFor(size_in_bytes, &new_node_size); |
2574 if (new_node == nullptr) return nullptr; | 2587 if (new_node == nullptr) return nullptr; |
2575 | 2588 |
2576 int bytes_left = new_node_size - size_in_bytes; | 2589 DCHECK_GE(new_node_size, size_in_bytes); |
2577 DCHECK(bytes_left >= 0); | 2590 size_t bytes_left = new_node_size - size_in_bytes; |
2578 | 2591 |
2579 #ifdef DEBUG | 2592 #ifdef DEBUG |
2580 for (int i = 0; i < size_in_bytes / kPointerSize; i++) { | 2593 for (size_t i = 0; i < size_in_bytes / kPointerSize; i++) { |
2581 reinterpret_cast<Object**>(new_node->address())[i] = | 2594 reinterpret_cast<Object**>(new_node->address())[i] = |
2582 Smi::FromInt(kCodeZapValue); | 2595 Smi::FromInt(kCodeZapValue); |
2583 } | 2596 } |
2584 #endif | 2597 #endif |
2585 | 2598 |
2586 // The old-space-step might have finished sweeping and restarted marking. | 2599 // The old-space-step might have finished sweeping and restarted marking. |
2587 // Verify that it did not turn the page of the new node into an evacuation | 2600 // Verify that it did not turn the page of the new node into an evacuation |
2588 // candidate. | 2601 // candidate. |
2589 DCHECK(!MarkCompactCollector::IsOnEvacuationCandidate(new_node)); | 2602 DCHECK(!MarkCompactCollector::IsOnEvacuationCandidate(new_node)); |
2590 | 2603 |
2591 const int kThreshold = IncrementalMarking::kAllocatedThreshold; | 2604 const size_t kThreshold = IncrementalMarking::kAllocatedThreshold; |
2592 | 2605 |
2593 // Memory in the linear allocation area is counted as allocated. We may free | 2606 // Memory in the linear allocation area is counted as allocated. We may free |
2594 // a little of this again immediately - see below. | 2607 // a little of this again immediately - see below. |
2595 owner_->Allocate(new_node_size); | 2608 owner_->Allocate(static_cast<int>(new_node_size)); |
2596 | 2609 |
2597 if (owner_->heap()->inline_allocation_disabled()) { | 2610 if (owner_->heap()->inline_allocation_disabled()) { |
2598 // Keep the linear allocation area empty if requested to do so, just | 2611 // Keep the linear allocation area empty if requested to do so, just |
2599 // return area back to the free list instead. | 2612 // return area back to the free list instead. |
2600 owner_->Free(new_node->address() + size_in_bytes, bytes_left); | 2613 owner_->Free(new_node->address() + size_in_bytes, bytes_left); |
2601 owner_->SetAllocationInfo(new_node->address() + size_in_bytes, | 2614 owner_->SetAllocationInfo(new_node->address() + size_in_bytes, |
2602 new_node->address() + size_in_bytes); | 2615 new_node->address() + size_in_bytes); |
2603 } else if (bytes_left > kThreshold && | 2616 } else if (bytes_left > kThreshold && |
2604 owner_->heap()->incremental_marking()->IsMarkingIncomplete() && | 2617 owner_->heap()->incremental_marking()->IsMarkingIncomplete() && |
2605 FLAG_incremental_marking) { | 2618 FLAG_incremental_marking) { |
2606 int linear_size = owner_->RoundSizeDownToObjectAlignment(kThreshold); | 2619 size_t linear_size = owner_->RoundSizeDownToObjectAlignment(kThreshold); |
2607 // We don't want to give too large linear areas to the allocator while | 2620 // We don't want to give too large linear areas to the allocator while |
2608 // incremental marking is going on, because we won't check again whether | 2621 // incremental marking is going on, because we won't check again whether |
2609 // we want to do another increment until the linear area is used up. | 2622 // we want to do another increment until the linear area is used up. |
| 2623 DCHECK_GE(new_node_size, size_in_bytes + linear_size); |
2610 owner_->Free(new_node->address() + size_in_bytes + linear_size, | 2624 owner_->Free(new_node->address() + size_in_bytes + linear_size, |
2611 new_node_size - size_in_bytes - linear_size); | 2625 new_node_size - size_in_bytes - linear_size); |
2612 owner_->SetAllocationInfo( | 2626 owner_->SetAllocationInfo( |
2613 new_node->address() + size_in_bytes, | 2627 new_node->address() + size_in_bytes, |
2614 new_node->address() + size_in_bytes + linear_size); | 2628 new_node->address() + size_in_bytes + linear_size); |
2615 } else { | 2629 } else { |
2616 DCHECK(bytes_left >= 0); | |
2617 // Normally we give the rest of the node to the allocator as its new | 2630 // Normally we give the rest of the node to the allocator as its new |
2618 // linear allocation area. | 2631 // linear allocation area. |
2619 owner_->SetAllocationInfo(new_node->address() + size_in_bytes, | 2632 owner_->SetAllocationInfo(new_node->address() + size_in_bytes, |
2620 new_node->address() + new_node_size); | 2633 new_node->address() + new_node_size); |
2621 } | 2634 } |
2622 | 2635 |
2623 return new_node; | 2636 return new_node; |
2624 } | 2637 } |
2625 | 2638 |
2626 intptr_t FreeList::EvictFreeListItems(Page* page) { | 2639 size_t FreeList::EvictFreeListItems(Page* page) { |
2627 intptr_t sum = 0; | 2640 size_t sum = 0; |
2628 page->ForAllFreeListCategories( | 2641 page->ForAllFreeListCategories( |
2629 [this, &sum, page](FreeListCategory* category) { | 2642 [this, &sum, page](FreeListCategory* category) { |
2630 DCHECK_EQ(this, category->owner()); | 2643 DCHECK_EQ(this, category->owner()); |
2631 sum += category->available(); | 2644 sum += category->available(); |
2632 RemoveCategory(category); | 2645 RemoveCategory(category); |
2633 category->Invalidate(); | 2646 category->Invalidate(); |
2634 }); | 2647 }); |
2635 return sum; | 2648 return sum; |
2636 } | 2649 } |
2637 | 2650 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2691 static_cast<void*>(categories_[type]), type); | 2704 static_cast<void*>(categories_[type]), type); |
2692 while (it.HasNext()) { | 2705 while (it.HasNext()) { |
2693 FreeListCategory* current = it.Next(); | 2706 FreeListCategory* current = it.Next(); |
2694 PrintF("%p -> ", static_cast<void*>(current)); | 2707 PrintF("%p -> ", static_cast<void*>(current)); |
2695 } | 2708 } |
2696 PrintF("null\n"); | 2709 PrintF("null\n"); |
2697 } | 2710 } |
2698 | 2711 |
2699 | 2712 |
2700 #ifdef DEBUG | 2713 #ifdef DEBUG |
2701 intptr_t FreeListCategory::SumFreeList() { | 2714 size_t FreeListCategory::SumFreeList() { |
2702 intptr_t sum = 0; | 2715 size_t sum = 0; |
2703 FreeSpace* cur = top(); | 2716 FreeSpace* cur = top(); |
2704 while (cur != NULL) { | 2717 while (cur != NULL) { |
2705 DCHECK(cur->map() == cur->GetHeap()->root(Heap::kFreeSpaceMapRootIndex)); | 2718 DCHECK(cur->map() == cur->GetHeap()->root(Heap::kFreeSpaceMapRootIndex)); |
2706 sum += cur->nobarrier_size(); | 2719 sum += cur->nobarrier_size(); |
2707 cur = cur->next(); | 2720 cur = cur->next(); |
2708 } | 2721 } |
2709 return sum; | 2722 return sum; |
2710 } | 2723 } |
2711 | 2724 |
2712 int FreeListCategory::FreeListLength() { | 2725 int FreeListCategory::FreeListLength() { |
(...skipping 16 matching lines...) Expand all Loading... |
2729 if (len >= FreeListCategory::kVeryLongFreeList) return true; | 2742 if (len >= FreeListCategory::kVeryLongFreeList) return true; |
2730 } | 2743 } |
2731 } | 2744 } |
2732 return false; | 2745 return false; |
2733 } | 2746 } |
2734 | 2747 |
2735 | 2748 |
2736 // This can take a very long time because it is linear in the number of entries | 2749 // This can take a very long time because it is linear in the number of entries |
2737 // on the free list, so it should not be called if FreeListLength returns | 2750 // on the free list, so it should not be called if FreeListLength returns |
2738 // kVeryLongFreeList. | 2751 // kVeryLongFreeList. |
2739 intptr_t FreeList::SumFreeLists() { | 2752 size_t FreeList::SumFreeLists() { |
2740 intptr_t sum = 0; | 2753 size_t sum = 0; |
2741 ForAllFreeListCategories( | 2754 ForAllFreeListCategories( |
2742 [&sum](FreeListCategory* category) { sum += category->SumFreeList(); }); | 2755 [&sum](FreeListCategory* category) { sum += category->SumFreeList(); }); |
2743 return sum; | 2756 return sum; |
2744 } | 2757 } |
2745 #endif | 2758 #endif |
2746 | 2759 |
2747 | 2760 |
2748 // ----------------------------------------------------------------------------- | 2761 // ----------------------------------------------------------------------------- |
2749 // OldSpace implementation | 2762 // OldSpace implementation |
2750 | 2763 |
(...skipping 18 matching lines...) Expand all Loading... |
2769 | 2782 |
2770 // After we have booted, we have created a map which represents free space | 2783 // After we have booted, we have created a map which represents free space |
2771 // on the heap. If there was already a free list then the elements on it | 2784 // on the heap. If there was already a free list then the elements on it |
2772 // were created with the wrong FreeSpaceMap (normally NULL), so we need to | 2785 // were created with the wrong FreeSpaceMap (normally NULL), so we need to |
2773 // fix them. | 2786 // fix them. |
2774 void PagedSpace::RepairFreeListsAfterDeserialization() { | 2787 void PagedSpace::RepairFreeListsAfterDeserialization() { |
2775 free_list_.RepairLists(heap()); | 2788 free_list_.RepairLists(heap()); |
2776 // Each page may have a small free space that is not tracked by a free list. | 2789 // Each page may have a small free space that is not tracked by a free list. |
2777 // Update the maps for those free space objects. | 2790 // Update the maps for those free space objects. |
2778 for (Page* page : *this) { | 2791 for (Page* page : *this) { |
2779 int size = static_cast<int>(page->wasted_memory()); | 2792 size_t size = page->wasted_memory(); |
2780 if (size == 0) continue; | 2793 if (size == 0) continue; |
| 2794 DCHECK_GE(static_cast<size_t>(Page::kPageSize), size); |
2781 Address address = page->OffsetToAddress(Page::kPageSize - size); | 2795 Address address = page->OffsetToAddress(Page::kPageSize - size); |
2782 heap()->CreateFillerObjectAt(address, size, ClearRecordedSlots::kNo); | 2796 heap()->CreateFillerObjectAt(address, static_cast<int>(size), |
| 2797 ClearRecordedSlots::kNo); |
2783 } | 2798 } |
2784 } | 2799 } |
2785 | 2800 |
2786 | 2801 |
2787 void PagedSpace::EvictEvacuationCandidatesFromLinearAllocationArea() { | 2802 void PagedSpace::EvictEvacuationCandidatesFromLinearAllocationArea() { |
2788 if (allocation_info_.top() >= allocation_info_.limit()) return; | 2803 if (allocation_info_.top() >= allocation_info_.limit()) return; |
2789 | 2804 |
2790 if (!Page::FromAllocationAreaAddress(allocation_info_.top())->CanAllocate()) { | 2805 if (!Page::FromAllocationAreaAddress(allocation_info_.top())->CanAllocate()) { |
2791 // Create filler object to keep page iterable if it was iterable. | 2806 // Create filler object to keep page iterable if it was iterable. |
2792 int remaining = | 2807 int remaining = |
(...skipping 21 matching lines...) Expand all Loading... |
2814 | 2829 |
2815 HeapObject* CompactionSpace::SweepAndRetryAllocation(int size_in_bytes) { | 2830 HeapObject* CompactionSpace::SweepAndRetryAllocation(int size_in_bytes) { |
2816 MarkCompactCollector* collector = heap()->mark_compact_collector(); | 2831 MarkCompactCollector* collector = heap()->mark_compact_collector(); |
2817 if (collector->sweeping_in_progress()) { | 2832 if (collector->sweeping_in_progress()) { |
2818 collector->SweepAndRefill(this); | 2833 collector->SweepAndRefill(this); |
2819 return free_list_.Allocate(size_in_bytes); | 2834 return free_list_.Allocate(size_in_bytes); |
2820 } | 2835 } |
2821 return nullptr; | 2836 return nullptr; |
2822 } | 2837 } |
2823 | 2838 |
2824 | |
2825 HeapObject* PagedSpace::SlowAllocateRaw(int size_in_bytes) { | 2839 HeapObject* PagedSpace::SlowAllocateRaw(int size_in_bytes) { |
2826 const int kMaxPagesToSweep = 1; | 2840 const int kMaxPagesToSweep = 1; |
2827 | 2841 |
2828 // Allocation in this space has failed. | 2842 // Allocation in this space has failed. |
2829 | 2843 |
2830 MarkCompactCollector* collector = heap()->mark_compact_collector(); | 2844 MarkCompactCollector* collector = heap()->mark_compact_collector(); |
2831 // Sweeping is still in progress. | 2845 // Sweeping is still in progress. |
2832 if (collector->sweeping_in_progress()) { | 2846 if (collector->sweeping_in_progress()) { |
2833 // First try to refill the free-list, concurrent sweeper threads | 2847 // First try to refill the free-list, concurrent sweeper threads |
2834 // may have freed some objects in the meantime. | 2848 // may have freed some objects in the meantime. |
2835 RefillFreeList(); | 2849 RefillFreeList(); |
2836 | 2850 |
2837 // Retry the free list allocation. | 2851 // Retry the free list allocation. |
2838 HeapObject* object = free_list_.Allocate(size_in_bytes); | 2852 HeapObject* object = |
| 2853 free_list_.Allocate(static_cast<size_t>(size_in_bytes)); |
2839 if (object != NULL) return object; | 2854 if (object != NULL) return object; |
2840 | 2855 |
2841 // If sweeping is still in progress try to sweep pages on the main thread. | 2856 // If sweeping is still in progress try to sweep pages on the main thread. |
2842 int max_freed = collector->sweeper().ParallelSweepSpace( | 2857 int max_freed = collector->sweeper().ParallelSweepSpace( |
2843 identity(), size_in_bytes, kMaxPagesToSweep); | 2858 identity(), size_in_bytes, kMaxPagesToSweep); |
2844 RefillFreeList(); | 2859 RefillFreeList(); |
2845 if (max_freed >= size_in_bytes) { | 2860 if (max_freed >= size_in_bytes) { |
2846 object = free_list_.Allocate(size_in_bytes); | 2861 object = free_list_.Allocate(static_cast<size_t>(size_in_bytes)); |
2847 if (object != nullptr) return object; | 2862 if (object != nullptr) return object; |
2848 } | 2863 } |
2849 } | 2864 } |
2850 | 2865 |
2851 if (heap()->ShouldExpandOldGenerationOnAllocationFailure() && Expand()) { | 2866 if (heap()->ShouldExpandOldGenerationOnAllocationFailure() && Expand()) { |
2852 DCHECK((CountTotalPages() > 1) || | 2867 DCHECK((CountTotalPages() > 1) || |
2853 (size_in_bytes <= free_list_.Available())); | 2868 (size_in_bytes <= free_list_.Available())); |
2854 return free_list_.Allocate(size_in_bytes); | 2869 return free_list_.Allocate(static_cast<size_t>(size_in_bytes)); |
2855 } | 2870 } |
2856 | 2871 |
2857 // If sweeper threads are active, wait for them at that point and steal | 2872 // If sweeper threads are active, wait for them at that point and steal |
2858 // elements form their free-lists. Allocation may still fail their which | 2873 // elements form their free-lists. Allocation may still fail their which |
2859 // would indicate that there is not enough memory for the given allocation. | 2874 // would indicate that there is not enough memory for the given allocation. |
2860 return SweepAndRetryAllocation(size_in_bytes); | 2875 return SweepAndRetryAllocation(size_in_bytes); |
2861 } | 2876 } |
2862 | 2877 |
2863 #ifdef DEBUG | 2878 #ifdef DEBUG |
2864 void PagedSpace::ReportStatistics() { | 2879 void PagedSpace::ReportStatistics() { |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2964 Executability executable) { | 2979 Executability executable) { |
2965 // Check if we want to force a GC before growing the old space further. | 2980 // Check if we want to force a GC before growing the old space further. |
2966 // If so, fail the allocation. | 2981 // If so, fail the allocation. |
2967 if (!heap()->CanExpandOldGeneration(object_size)) { | 2982 if (!heap()->CanExpandOldGeneration(object_size)) { |
2968 return AllocationResult::Retry(identity()); | 2983 return AllocationResult::Retry(identity()); |
2969 } | 2984 } |
2970 | 2985 |
2971 LargePage* page = heap()->memory_allocator()->AllocateLargePage( | 2986 LargePage* page = heap()->memory_allocator()->AllocateLargePage( |
2972 object_size, this, executable); | 2987 object_size, this, executable); |
2973 if (page == NULL) return AllocationResult::Retry(identity()); | 2988 if (page == NULL) return AllocationResult::Retry(identity()); |
2974 DCHECK(page->area_size() >= object_size); | 2989 DCHECK_GE(page->area_size(), static_cast<size_t>(object_size)); |
2975 | 2990 |
2976 size_ += static_cast<int>(page->size()); | 2991 size_ += static_cast<int>(page->size()); |
2977 AccountCommitted(page->size()); | 2992 AccountCommitted(page->size()); |
2978 objects_size_ += object_size; | 2993 objects_size_ += object_size; |
2979 page_count_++; | 2994 page_count_++; |
2980 page->set_next_page(first_page_); | 2995 page->set_next_page(first_page_); |
2981 first_page_ = page; | 2996 first_page_ = page; |
2982 | 2997 |
2983 InsertChunkMapEntries(page); | 2998 InsertChunkMapEntries(page); |
2984 | 2999 |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3230 object->ShortPrint(); | 3245 object->ShortPrint(); |
3231 PrintF("\n"); | 3246 PrintF("\n"); |
3232 } | 3247 } |
3233 printf(" --------------------------------------\n"); | 3248 printf(" --------------------------------------\n"); |
3234 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3249 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
3235 } | 3250 } |
3236 | 3251 |
3237 #endif // DEBUG | 3252 #endif // DEBUG |
3238 } // namespace internal | 3253 } // namespace internal |
3239 } // namespace v8 | 3254 } // namespace v8 |
OLD | NEW |