Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(363)

Side by Side Diff: src/heap/spaces.cc

Issue 1696413002: [heap] Refactor free list counters in Page. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/heap/spaces.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/slot-set.h" 10 #include "src/heap/slot-set.h"
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after
481 chunk->slots_buffer_ = nullptr; 481 chunk->slots_buffer_ = nullptr;
482 chunk->old_to_new_slots_ = nullptr; 482 chunk->old_to_new_slots_ = nullptr;
483 chunk->old_to_old_slots_ = nullptr; 483 chunk->old_to_old_slots_ = nullptr;
484 chunk->skip_list_ = nullptr; 484 chunk->skip_list_ = nullptr;
485 chunk->write_barrier_counter_ = kWriteBarrierCounterGranularity; 485 chunk->write_barrier_counter_ = kWriteBarrierCounterGranularity;
486 chunk->progress_bar_ = 0; 486 chunk->progress_bar_ = 0;
487 chunk->high_water_mark_.SetValue(static_cast<intptr_t>(area_start - base)); 487 chunk->high_water_mark_.SetValue(static_cast<intptr_t>(area_start - base));
488 chunk->concurrent_sweeping_state().SetValue(kSweepingDone); 488 chunk->concurrent_sweeping_state().SetValue(kSweepingDone);
489 chunk->parallel_compaction_state().SetValue(kCompactingDone); 489 chunk->parallel_compaction_state().SetValue(kCompactingDone);
490 chunk->mutex_ = nullptr; 490 chunk->mutex_ = nullptr;
491 chunk->available_in_small_free_list_ = 0; 491 chunk->available_in_free_list_ = 0;
492 chunk->available_in_medium_free_list_ = 0; 492 chunk->wasted_memory_ = 0;
493 chunk->available_in_large_free_list_ = 0;
494 chunk->available_in_huge_free_list_ = 0;
495 chunk->non_available_small_blocks_ = 0;
496 chunk->ResetLiveBytes(); 493 chunk->ResetLiveBytes();
497 Bitmap::Clear(chunk); 494 Bitmap::Clear(chunk);
498 chunk->set_next_chunk(nullptr); 495 chunk->set_next_chunk(nullptr);
499 chunk->set_prev_chunk(nullptr); 496 chunk->set_prev_chunk(nullptr);
500 497
501 DCHECK(OFFSET_OF(MemoryChunk, flags_) == kFlagsOffset); 498 DCHECK(OFFSET_OF(MemoryChunk, flags_) == kFlagsOffset);
502 DCHECK(OFFSET_OF(MemoryChunk, live_byte_count_) == kLiveBytesOffset); 499 DCHECK(OFFSET_OF(MemoryChunk, live_byte_count_) == kLiveBytesOffset);
503 500
504 if (executable == EXECUTABLE) { 501 if (executable == EXECUTABLE) {
505 chunk->SetFlag(IS_EXECUTABLE); 502 chunk->SetFlag(IS_EXECUTABLE);
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
709 ObjectSpace space = static_cast<ObjectSpace>(1 << owner->identity()); 706 ObjectSpace space = static_cast<ObjectSpace>(1 << owner->identity());
710 PerformAllocationCallback(space, kAllocationActionAllocate, chunk_size); 707 PerformAllocationCallback(space, kAllocationActionAllocate, chunk_size);
711 } 708 }
712 709
713 return MemoryChunk::Initialize(heap, base, chunk_size, area_start, area_end, 710 return MemoryChunk::Initialize(heap, base, chunk_size, area_start, area_end,
714 executable, owner, &reservation); 711 executable, owner, &reservation);
715 } 712 }
716 713
717 714
718 void Page::ResetFreeListStatistics() { 715 void Page::ResetFreeListStatistics() {
719 non_available_small_blocks_ = 0; 716 wasted_memory_ = 0;
720 available_in_small_free_list_ = 0; 717 available_in_free_list_ = 0;
721 available_in_medium_free_list_ = 0;
722 available_in_large_free_list_ = 0;
723 available_in_huge_free_list_ = 0;
724 } 718 }
725 719
726 720
727 Page* MemoryAllocator::AllocatePage(intptr_t size, PagedSpace* owner, 721 Page* MemoryAllocator::AllocatePage(intptr_t size, PagedSpace* owner,
728 Executability executable) { 722 Executability executable) {
729 MemoryChunk* chunk = AllocateChunk(size, size, executable, owner); 723 MemoryChunk* chunk = AllocateChunk(size, size, executable, owner);
730 if (chunk == NULL) return NULL; 724 if (chunk == NULL) return NULL;
731 return Page::Initialize(isolate_->heap(), chunk, executable, owner); 725 return Page::Initialize(isolate_->heap(), chunk, executable, owner);
732 } 726 }
733 727
(...skipping 1467 matching lines...) Expand 10 before | Expand all | Expand 10 after
2201 if (cur_node == end()) { 2195 if (cur_node == end()) {
2202 set_end(prev_node); 2196 set_end(prev_node);
2203 } 2197 }
2204 if (prev_node != nullptr) { 2198 if (prev_node != nullptr) {
2205 prev_node->set_next(cur_node->next()); 2199 prev_node->set_next(cur_node->next());
2206 } 2200 }
2207 continue; 2201 continue;
2208 } 2202 }
2209 prev_node = cur_node; 2203 prev_node = cur_node;
2210 } 2204 }
2211 DCHECK_EQ(p->available_in_free_list(type_), sum); 2205 p->add_available_in_free_list(-sum);
2212 p->add_available_in_free_list(type_, -sum);
2213 available_ -= sum; 2206 available_ -= sum;
2214 return sum; 2207 return sum;
2215 } 2208 }
2216 2209
2217 2210
2218 bool FreeListCategory::ContainsPageFreeListItemsInList(Page* p) { 2211 bool FreeListCategory::ContainsPageFreeListItemsInList(Page* p) {
2219 FreeSpace* node = top(); 2212 FreeSpace* node = top();
2220 while (node != NULL) { 2213 while (node != NULL) {
2221 if (Page::FromAddress(node->address()) == p) return true; 2214 if (Page::FromAddress(node->address()) == p) return true;
2222 node = node->next(); 2215 node = node->next();
2223 } 2216 }
2224 return false; 2217 return false;
2225 } 2218 }
2226 2219
2227 2220
2228 FreeSpace* FreeListCategory::PickNodeFromList(int* node_size) { 2221 FreeSpace* FreeListCategory::PickNodeFromList(int* node_size) {
2229 FreeSpace* node = top(); 2222 FreeSpace* node = top();
2230 if (node == nullptr) return nullptr; 2223 if (node == nullptr) return nullptr;
2231 2224
2232 Page* page = Page::FromAddress(node->address()); 2225 Page* page = Page::FromAddress(node->address());
2233 while ((node != nullptr) && !page->CanAllocate()) { 2226 while ((node != nullptr) && !page->CanAllocate()) {
2234 available_ -= node->size(); 2227 available_ -= node->size();
2235 page->add_available_in_free_list(type_, -(node->Size())); 2228 page->add_available_in_free_list(-(node->Size()));
2236 node = node->next(); 2229 node = node->next();
2237 } 2230 }
2238 2231
2239 if (node != nullptr) { 2232 if (node != nullptr) {
2240 set_top(node->next()); 2233 set_top(node->next());
2241 *node_size = node->Size(); 2234 *node_size = node->Size();
2242 available_ -= *node_size; 2235 available_ -= *node_size;
2243 } else { 2236 } else {
2244 set_top(nullptr); 2237 set_top(nullptr);
2245 } 2238 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
2280 set_top(cur_node->next()); 2273 set_top(cur_node->next());
2281 } 2274 }
2282 if (cur_node == end()) { 2275 if (cur_node == end()) {
2283 set_end(prev_non_evac_node); 2276 set_end(prev_non_evac_node);
2284 } 2277 }
2285 if (prev_non_evac_node != nullptr) { 2278 if (prev_non_evac_node != nullptr) {
2286 prev_non_evac_node->set_next(cur_node->next()); 2279 prev_non_evac_node->set_next(cur_node->next());
2287 } 2280 }
2288 // For evacuation candidates we continue. 2281 // For evacuation candidates we continue.
2289 if (!page_for_node->CanAllocate()) { 2282 if (!page_for_node->CanAllocate()) {
2290 page_for_node->add_available_in_free_list(type_, -size); 2283 page_for_node->add_available_in_free_list(-size);
2291 continue; 2284 continue;
2292 } 2285 }
2293 // Otherwise we have a large enough node and can return. 2286 // Otherwise we have a large enough node and can return.
2294 *node_size = size; 2287 *node_size = size;
2295 return cur_node; 2288 return cur_node;
2296 } 2289 }
2297 2290
2298 prev_non_evac_node = cur_node; 2291 prev_non_evac_node = cur_node;
2299 } 2292 }
2300 return nullptr; 2293 return nullptr;
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
2368 2361
2369 int FreeList::Free(Address start, int size_in_bytes) { 2362 int FreeList::Free(Address start, int size_in_bytes) {
2370 if (size_in_bytes == 0) return 0; 2363 if (size_in_bytes == 0) return 0;
2371 2364
2372 owner()->heap()->CreateFillerObjectAt(start, size_in_bytes); 2365 owner()->heap()->CreateFillerObjectAt(start, size_in_bytes);
2373 2366
2374 Page* page = Page::FromAddress(start); 2367 Page* page = Page::FromAddress(start);
2375 2368
2376 // Early return to drop too-small blocks on the floor. 2369 // Early return to drop too-small blocks on the floor.
2377 if (size_in_bytes <= kSmallListMin) { 2370 if (size_in_bytes <= kSmallListMin) {
2378 page->add_non_available_small_blocks(size_in_bytes); 2371 page->add_wasted_memory(size_in_bytes);
2379 wasted_bytes_ += size_in_bytes; 2372 wasted_bytes_ += size_in_bytes;
2380 return size_in_bytes; 2373 return size_in_bytes;
2381 } 2374 }
2382 2375
2383 FreeSpace* free_space = FreeSpace::cast(HeapObject::FromAddress(start)); 2376 FreeSpace* free_space = FreeSpace::cast(HeapObject::FromAddress(start));
2384 // Insert other blocks at the head of a free list of the appropriate 2377 // Insert other blocks at the head of a free list of the appropriate
2385 // magnitude. 2378 // magnitude.
2386 if (size_in_bytes <= kSmallListMax) { 2379 FreeListCategoryType type = SelectFreeListCategoryType(size_in_bytes);
2387 category_[kSmall].Free(free_space, size_in_bytes); 2380 category_[type].Free(free_space, size_in_bytes);
2388 page->add_available_in_small_free_list(size_in_bytes); 2381 page->add_available_in_free_list(size_in_bytes);
2389 } else if (size_in_bytes <= kMediumListMax) {
2390 category_[kMedium].Free(free_space, size_in_bytes);
2391 page->add_available_in_medium_free_list(size_in_bytes);
2392 } else if (size_in_bytes <= kLargeListMax) {
2393 category_[kLarge].Free(free_space, size_in_bytes);
2394 page->add_available_in_large_free_list(size_in_bytes);
2395 } else {
2396 category_[kHuge].Free(free_space, size_in_bytes);
2397 page->add_available_in_huge_free_list(size_in_bytes);
2398 }
2399 2382
2400 DCHECK(IsVeryLong() || Available() == SumFreeLists()); 2383 DCHECK(IsVeryLong() || Available() == SumFreeLists());
2401 return 0; 2384 return 0;
2402 } 2385 }
2403 2386
2404 2387
2405 FreeSpace* FreeList::FindNodeIn(FreeListCategoryType category, int* node_size) { 2388 FreeSpace* FreeList::FindNodeIn(FreeListCategoryType category, int* node_size) {
2406 FreeSpace* node = GetFreeListCategory(category)->PickNodeFromList(node_size); 2389 FreeSpace* node = GetFreeListCategory(category)->PickNodeFromList(node_size);
2407 if (node != nullptr) { 2390 if (node != nullptr) {
2408 Page::FromAddress(node->address()) 2391 Page::FromAddress(node->address())
2409 ->add_available_in_free_list(category, -(*node_size)); 2392 ->add_available_in_free_list(-(*node_size));
2410 DCHECK(IsVeryLong() || Available() == SumFreeLists()); 2393 DCHECK(IsVeryLong() || Available() == SumFreeLists());
2411 } 2394 }
2412 return node; 2395 return node;
2413 } 2396 }
2414 2397
2415 2398
2416 FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { 2399 FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) {
2417 FreeSpace* node = nullptr; 2400 FreeSpace* node = nullptr;
2418 Page* page = nullptr; 2401 Page* page = nullptr;
2419 2402
2420 if (size_in_bytes <= kSmallAllocationMax) { 2403 // First try the allocation fast path: try to allocate the minimum element
2421 node = FindNodeIn(kSmall, node_size); 2404 // size of a free list category. This operation is constant time.
2405 FreeListCategoryType type =
2406 SelectFastAllocationFreeListCategoryType(size_in_bytes);
2407 for (int i = type; i < kHuge; i++) {
2408 node = FindNodeIn(static_cast<FreeListCategoryType>(i), node_size);
2422 if (node != nullptr) return node; 2409 if (node != nullptr) return node;
2423 } 2410 }
2424 2411
2425 if (size_in_bytes <= kMediumAllocationMax) { 2412 // Next search the huge list for free list nodes. This takes linear time in
2426 node = FindNodeIn(kMedium, node_size); 2413 // the number of huge elements.
2427 if (node != nullptr) return node;
2428 }
2429
2430 if (size_in_bytes <= kLargeAllocationMax) {
2431 node = FindNodeIn(kLarge, node_size);
2432 if (node != nullptr) return node;
2433 }
2434
2435 node = category_[kHuge].SearchForNodeInList(size_in_bytes, node_size); 2414 node = category_[kHuge].SearchForNodeInList(size_in_bytes, node_size);
2436 if (node != nullptr) { 2415 if (node != nullptr) {
2437 page = Page::FromAddress(node->address()); 2416 page = Page::FromAddress(node->address());
2438 page->add_available_in_large_free_list(-(*node_size)); 2417 page->add_available_in_free_list(-(*node_size));
2439 DCHECK(IsVeryLong() || Available() == SumFreeLists()); 2418 DCHECK(IsVeryLong() || Available() == SumFreeLists());
2440 return node; 2419 return node;
2441 } 2420 }
2442 2421
2443 if (size_in_bytes <= kSmallListMax) { 2422 // We need a huge block of memory, but we didn't find anything in the huge
2444 node = category_[kSmall].PickNodeFromList(size_in_bytes, node_size); 2423 // list.
2445 if (node != NULL) { 2424 if (type == kHuge) return nullptr;
2446 DCHECK(size_in_bytes <= *node_size); 2425
2447 page = Page::FromAddress(node->address()); 2426 // Now search the best fitting free list for a node that has at least the
2448 page->add_available_in_small_free_list(-(*node_size)); 2427 // requested size. This takes linear time in the number of elements.
2449 } 2428 type = SelectFreeListCategoryType(size_in_bytes);
2450 } else if (size_in_bytes <= kMediumListMax) { 2429 node = category_[type].PickNodeFromList(size_in_bytes, node_size);
2451 node = category_[kMedium].PickNodeFromList(size_in_bytes, node_size); 2430 if (node != nullptr) {
2452 if (node != NULL) { 2431 DCHECK(size_in_bytes <= *node_size);
2453 DCHECK(size_in_bytes <= *node_size); 2432 page = Page::FromAddress(node->address());
2454 page = Page::FromAddress(node->address()); 2433 page->add_available_in_free_list(-(*node_size));
2455 page->add_available_in_medium_free_list(-(*node_size));
2456 }
2457 } else if (size_in_bytes <= kLargeListMax) {
2458 node = category_[kLarge].PickNodeFromList(size_in_bytes, node_size);
2459 if (node != NULL) {
2460 DCHECK(size_in_bytes <= *node_size);
2461 page = Page::FromAddress(node->address());
2462 page->add_available_in_large_free_list(-(*node_size));
2463 }
2464 } 2434 }
2465 2435
2466 DCHECK(IsVeryLong() || Available() == SumFreeLists()); 2436 DCHECK(IsVeryLong() || Available() == SumFreeLists());
2467 return node; 2437 return node;
2468 } 2438 }
2469 2439
2470 2440
2471 FreeSpace* FreeList::TryRemoveMemory(intptr_t hint_size_in_bytes) { 2441 FreeSpace* FreeList::TryRemoveMemory(intptr_t hint_size_in_bytes) {
2472 hint_size_in_bytes = RoundDown(hint_size_in_bytes, kPointerSize); 2442 hint_size_in_bytes = RoundDown(hint_size_in_bytes, kPointerSize);
2473 base::LockGuard<base::Mutex> guard(&mutex_); 2443 base::LockGuard<base::Mutex> guard(&mutex_);
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
2680 // on the heap. If there was already a free list then the elements on it 2650 // on the heap. If there was already a free list then the elements on it
2681 // were created with the wrong FreeSpaceMap (normally NULL), so we need to 2651 // were created with the wrong FreeSpaceMap (normally NULL), so we need to
2682 // fix them. 2652 // fix them.
2683 void PagedSpace::RepairFreeListsAfterDeserialization() { 2653 void PagedSpace::RepairFreeListsAfterDeserialization() {
2684 free_list_.RepairLists(heap()); 2654 free_list_.RepairLists(heap());
2685 // Each page may have a small free space that is not tracked by a free list. 2655 // Each page may have a small free space that is not tracked by a free list.
2686 // Update the maps for those free space objects. 2656 // Update the maps for those free space objects.
2687 PageIterator iterator(this); 2657 PageIterator iterator(this);
2688 while (iterator.has_next()) { 2658 while (iterator.has_next()) {
2689 Page* page = iterator.next(); 2659 Page* page = iterator.next();
2690 int size = static_cast<int>(page->non_available_small_blocks()); 2660 int size = static_cast<int>(page->wasted_memory());
2691 if (size == 0) continue; 2661 if (size == 0) continue;
2692 Address address = page->OffsetToAddress(Page::kPageSize - size); 2662 Address address = page->OffsetToAddress(Page::kPageSize - size);
2693 heap()->CreateFillerObjectAt(address, size); 2663 heap()->CreateFillerObjectAt(address, size);
2694 } 2664 }
2695 } 2665 }
2696 2666
2697 2667
2698 void PagedSpace::EvictEvacuationCandidatesFromLinearAllocationArea() { 2668 void PagedSpace::EvictEvacuationCandidatesFromLinearAllocationArea() {
2699 if (allocation_info_.top() >= allocation_info_.limit()) return; 2669 if (allocation_info_.top() >= allocation_info_.limit()) return;
2700 2670
(...skipping 559 matching lines...) Expand 10 before | Expand all | Expand 10 after
3260 object->ShortPrint(); 3230 object->ShortPrint();
3261 PrintF("\n"); 3231 PrintF("\n");
3262 } 3232 }
3263 printf(" --------------------------------------\n"); 3233 printf(" --------------------------------------\n");
3264 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); 3234 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes());
3265 } 3235 }
3266 3236
3267 #endif // DEBUG 3237 #endif // DEBUG
3268 } // namespace internal 3238 } // namespace internal
3269 } // namespace v8 3239 } // namespace v8
OLDNEW
« no previous file with comments | « src/heap/spaces.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698