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

Side by Side Diff: src/spaces.cc

Issue 14208005: Use worst-fit allocation in old space for prentured objects. Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 8 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 2198 matching lines...) Expand 10 before | Expand all | Expand 10 after
2209 } else { 2209 } else {
2210 huge_list_.Free(node, size_in_bytes); 2210 huge_list_.Free(node, size_in_bytes);
2211 page->add_available_in_huge_free_list(size_in_bytes); 2211 page->add_available_in_huge_free_list(size_in_bytes);
2212 } 2212 }
2213 2213
2214 ASSERT(IsVeryLong() || available() == SumFreeLists()); 2214 ASSERT(IsVeryLong() || available() == SumFreeLists());
2215 return 0; 2215 return 0;
2216 } 2216 }
2217 2217
2218 2218
2219 FreeListNode* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { 2219 FreeListNode* FreeList::FindNodeInHugeList(int size_in_bytes, int* node_size) {
2220 FreeListNode* node = NULL; 2220 FreeListNode* node = NULL;
2221 Page* page = NULL;
2222
2223 if (size_in_bytes <= kSmallAllocationMax) {
2224 node = small_list_.PickNodeFromList(node_size);
2225 if (node != NULL) {
2226 page = Page::FromAddress(node->address());
2227 page->add_available_in_small_free_list(-(*node_size));
2228 return node;
2229 }
2230 }
2231
2232 if (size_in_bytes <= kMediumAllocationMax) {
2233 node = medium_list_.PickNodeFromList(node_size);
2234 if (node != NULL) {
2235 page = Page::FromAddress(node->address());
2236 page->add_available_in_medium_free_list(-(*node_size));
2237 return node;
2238 }
2239 }
2240
2241 if (size_in_bytes <= kLargeAllocationMax) {
2242 node = large_list_.PickNodeFromList(node_size);
2243 if (node != NULL) {
2244 page = Page::FromAddress(node->address());
2245 page->add_available_in_large_free_list(-(*node_size));
2246 return node;
2247 }
2248 }
2249 2221
2250 int huge_list_available = huge_list_.available(); 2222 int huge_list_available = huge_list_.available();
2251 for (FreeListNode** cur = huge_list_.GetTopAddress(); 2223 for (FreeListNode** cur = huge_list_.GetTopAddress();
2252 *cur != NULL; 2224 *cur != NULL;
2253 cur = (*cur)->next_address()) { 2225 cur = (*cur)->next_address()) {
2254 FreeListNode* cur_node = *cur; 2226 FreeListNode* cur_node = *cur;
2255 while (cur_node != NULL && 2227 while (cur_node != NULL &&
2256 Page::FromAddress(cur_node->address())->IsEvacuationCandidate()) { 2228 Page::FromAddress(cur_node->address())->IsEvacuationCandidate()) {
2257 int size = reinterpret_cast<FreeSpace*>(cur_node)->Size(); 2229 huge_list_available -= reinterpret_cast<FreeSpace*>(cur_node)->Size();
2258 huge_list_available -= size;
2259 page = Page::FromAddress(cur_node->address());
2260 page->add_available_in_huge_free_list(-size);
2261 cur_node = cur_node->next(); 2230 cur_node = cur_node->next();
2262 } 2231 }
2263 2232
2264 *cur = cur_node; 2233 *cur = cur_node;
2265 if (cur_node == NULL) { 2234 if (cur_node == NULL) {
2266 huge_list_.set_end(NULL); 2235 huge_list_.set_end(NULL);
2267 break; 2236 break;
2268 } 2237 }
2269 2238
2270 ASSERT((*cur)->map() == heap_->raw_unchecked_free_space_map()); 2239 ASSERT((*cur)->map() == heap_->raw_unchecked_free_space_map());
2271 FreeSpace* cur_as_free_space = reinterpret_cast<FreeSpace*>(*cur); 2240 FreeSpace* cur_as_free_space = reinterpret_cast<FreeSpace*>(*cur);
2272 int size = cur_as_free_space->Size(); 2241 int size = cur_as_free_space->Size();
2273 if (size >= size_in_bytes) { 2242 if (size >= size_in_bytes) {
2274 // Large enough node found. Unlink it from the list. 2243 // Large enough node found. Unlink it from the list.
2275 node = *cur; 2244 node = *cur;
2276 *cur = node->next(); 2245 *cur = node->next();
2277 *node_size = size; 2246 *node_size = size;
2278 huge_list_available -= size; 2247 huge_list_available -= size;
2279 page = Page::FromAddress(node->address());
2280 page->add_available_in_huge_free_list(-size);
2281 break; 2248 break;
2282 } 2249 }
2283 } 2250 }
2284 2251
2285 if (huge_list_.top() == NULL) { 2252 if (huge_list_.top() == NULL) {
2286 huge_list_.set_end(NULL); 2253 huge_list_.set_end(NULL);
2287 } 2254 }
2288 2255
2289 huge_list_.set_available(huge_list_available); 2256 huge_list_.set_available(huge_list_available);
2290 ASSERT(IsVeryLong() || available() == SumFreeLists()); 2257 ASSERT(IsVeryLong() || available() == SumFreeLists());
2291 2258
2292 return node; 2259 return node;
2293 } 2260 }
2294 2261
2295 2262
2263 FreeListNode* FreeList::FindNodeForWorstFit(int size_in_bytes, int* node_size) {
2264 FreeListNode* node = FindNodeInHugeList(size_in_bytes, node_size);
2265 if (node != NULL) return node;
Michael Starzinger 2013/04/16 13:29:27 Missing statistical book-keeping about available_i
Hannes Payer (out of office) 2013/04/16 13:41:04 Done.
2266
2267 if (size_in_bytes <= kLargeAllocationMax) {
2268 node = large_list_.PickNodeFromList(node_size);
2269 if (node != NULL) return node;
Michael Starzinger 2013/04/16 13:29:27 Missing statistical book-keeping about available_i
Hannes Payer (out of office) 2013/04/16 13:41:04 Done.
2270 }
2271
2272 if (size_in_bytes <= kMediumAllocationMax) {
2273 node = medium_list_.PickNodeFromList(node_size);
2274 if (node != NULL) return node;
Michael Starzinger 2013/04/16 13:29:27 Missing statistical book-keeping about available_i
Hannes Payer (out of office) 2013/04/16 13:41:04 Done.
2275 }
2276
2277 return node;
2278 }
2279
2280
2281 FreeListNode* FreeList::FindNodeForBestFit(int size_in_bytes, int* node_size) {
2282 FreeListNode* node = NULL;
2283 Page* page = NULL;
Michael Starzinger 2013/04/16 13:29:27 nit: Move the declaration of "page" down into the
Hannes Payer (out of office) 2013/04/16 13:41:04 Done.
2284
2285 if (size_in_bytes <= kSmallAllocationMax) {
2286 node = small_list_.PickNodeFromList(node_size);
2287 if (node != NULL) {
2288 page = Page::FromAddress(node->address());
2289 page->add_available_in_small_free_list(-(*node_size));
2290 return node;
2291 }
2292 }
2293
2294 if (size_in_bytes <= kMediumAllocationMax) {
2295 node = medium_list_.PickNodeFromList(node_size);
2296 if (node != NULL) {
2297 page = Page::FromAddress(node->address());
2298 page->add_available_in_medium_free_list(-(*node_size));
2299 return node;
2300 }
2301 }
2302
2303 if (size_in_bytes <= kLargeAllocationMax) {
2304 node = large_list_.PickNodeFromList(node_size);
2305 if (node != NULL) {
2306 page = Page::FromAddress(node->address());
2307 page->add_available_in_large_free_list(-(*node_size));
2308 return node;
2309 }
2310 }
2311
2312 return FindNodeInHugeList(size_in_bytes, node_size);
Michael Starzinger 2013/04/16 13:29:27 Missing statistical book-keeping about available_i
Hannes Payer (out of office) 2013/04/16 13:41:04 Done.
2313 }
2314
2315
2316 template HeapObject* FreeList::Allocate<FreeList::BEST_FIT>(int size_in_bytes);
2317
2318 template HeapObject* FreeList::Allocate<FreeList::WORST_FIT>(int size_in_bytes);
2319
Michael Starzinger 2013/04/16 13:29:27 nit: Add second empty newline.
Hannes Payer (out of office) 2013/04/16 13:41:04 Done.
2296 // Allocation on the old space free list. If it succeeds then a new linear 2320 // Allocation on the old space free list. If it succeeds then a new linear
2297 // allocation space has been set up with the top and limit of the space. If 2321 // allocation space has been set up with the top and limit of the space. If
2298 // the allocation fails then NULL is returned, and the caller can perform a GC 2322 // the allocation fails then NULL is returned, and the caller can perform a GC
2299 // or allocate a new page before retrying. 2323 // or allocate a new page before retrying.
2324 template<FreeList::AllocationStrategy strategy>
2300 HeapObject* FreeList::Allocate(int size_in_bytes) { 2325 HeapObject* FreeList::Allocate(int size_in_bytes) {
2301 ASSERT(0 < size_in_bytes); 2326 ASSERT(0 < size_in_bytes);
2302 ASSERT(size_in_bytes <= kMaxBlockSize); 2327 ASSERT(size_in_bytes <= kMaxBlockSize);
2303 ASSERT(IsAligned(size_in_bytes, kPointerSize)); 2328 ASSERT(IsAligned(size_in_bytes, kPointerSize));
2304 // Don't free list allocate if there is linear space available. 2329 // Don't free list allocate if there is linear space available.
2305 ASSERT(owner_->limit() - owner_->top() < size_in_bytes); 2330 ASSERT(owner_->limit() - owner_->top() < size_in_bytes);
2306 2331
2307 int new_node_size = 0; 2332 int new_node_size = 0;
2308 FreeListNode* new_node = FindNodeFor(size_in_bytes, &new_node_size); 2333 FreeListNode* new_node;
2334 if (FreeList::BEST_FIT == strategy) {
2335 new_node = FindNodeForBestFit(size_in_bytes, &new_node_size);
2336 } else {
2337 new_node = FindNodeForWorstFit(size_in_bytes, &new_node_size);
2338 }
2309 if (new_node == NULL) return NULL; 2339 if (new_node == NULL) return NULL;
2310 2340
2311 2341
2312 int bytes_left = new_node_size - size_in_bytes; 2342 int bytes_left = new_node_size - size_in_bytes;
2313 ASSERT(bytes_left >= 0); 2343 ASSERT(bytes_left >= 0);
2314 2344
2315 int old_linear_size = static_cast<int>(owner_->limit() - owner_->top()); 2345 int old_linear_size = static_cast<int>(owner_->limit() - owner_->top());
2316 // Mark the old linear allocation area with a free space map so it can be 2346 // Mark the old linear allocation area with a free space map so it can be
2317 // skipped when scanning the heap. This also puts it back in the free list 2347 // skipped when scanning the heap. This also puts it back in the free list
2318 // if it is big enough. 2348 // if it is big enough.
(...skipping 10 matching lines...) Expand all
2329 #endif 2359 #endif
2330 2360
2331 // The old-space-step might have finished sweeping and restarted marking. 2361 // The old-space-step might have finished sweeping and restarted marking.
2332 // Verify that it did not turn the page of the new node into an evacuation 2362 // Verify that it did not turn the page of the new node into an evacuation
2333 // candidate. 2363 // candidate.
2334 ASSERT(!MarkCompactCollector::IsOnEvacuationCandidate(new_node)); 2364 ASSERT(!MarkCompactCollector::IsOnEvacuationCandidate(new_node));
2335 2365
2336 const int kThreshold = IncrementalMarking::kAllocatedThreshold; 2366 const int kThreshold = IncrementalMarking::kAllocatedThreshold;
2337 2367
2338 // Memory in the linear allocation area is counted as allocated. We may free 2368 // Memory in the linear allocation area is counted as allocated. We may free
2339 // a little of this again immediately - see below. 2369 // a little of this again immediately - see below. We try to create large
2340 owner_->Allocate(new_node_size); 2370 // bump pointer ranges when we use worst-fit, therefore we do not give
2371 // memory back to the free-list.
2372 if (FreeList::BEST_FIT == strategy) {
2373 owner_->Allocate(new_node_size);
2374 }
2341 2375
2342 if (bytes_left > kThreshold && 2376 if (FreeList::BEST_FIT == strategy &&
2377 bytes_left > kThreshold &&
2343 owner_->heap()->incremental_marking()->IsMarkingIncomplete() && 2378 owner_->heap()->incremental_marking()->IsMarkingIncomplete() &&
2344 FLAG_incremental_marking_steps) { 2379 FLAG_incremental_marking_steps) {
2345 int linear_size = owner_->RoundSizeDownToObjectAlignment(kThreshold); 2380 int linear_size = owner_->RoundSizeDownToObjectAlignment(kThreshold);
2346 // We don't want to give too large linear areas to the allocator while 2381 // We don't want to give too large linear areas to the allocator while
2347 // incremental marking is going on, because we won't check again whether 2382 // incremental marking is going on, because we won't check again whether
2348 // we want to do another increment until the linear area is used up. 2383 // we want to do another increment until the linear area is used up.
2349 owner_->Free(new_node->address() + size_in_bytes + linear_size, 2384 owner_->Free(new_node->address() + size_in_bytes + linear_size,
2350 new_node_size - size_in_bytes - linear_size); 2385 new_node_size - size_in_bytes - linear_size);
2351 owner_->SetTop(new_node->address() + size_in_bytes, 2386 owner_->SetTop(new_node->address() + size_in_bytes,
2352 new_node->address() + size_in_bytes + linear_size); 2387 new_node->address() + size_in_bytes + linear_size);
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
2501 } 2536 }
2502 2537
2503 2538
2504 bool PagedSpace::ReserveSpace(int size_in_bytes) { 2539 bool PagedSpace::ReserveSpace(int size_in_bytes) {
2505 ASSERT(size_in_bytes <= AreaSize()); 2540 ASSERT(size_in_bytes <= AreaSize());
2506 ASSERT(size_in_bytes == RoundSizeDownToObjectAlignment(size_in_bytes)); 2541 ASSERT(size_in_bytes == RoundSizeDownToObjectAlignment(size_in_bytes));
2507 Address current_top = allocation_info_.top; 2542 Address current_top = allocation_info_.top;
2508 Address new_top = current_top + size_in_bytes; 2543 Address new_top = current_top + size_in_bytes;
2509 if (new_top <= allocation_info_.limit) return true; 2544 if (new_top <= allocation_info_.limit) return true;
2510 2545
2511 HeapObject* new_area = free_list_.Allocate(size_in_bytes); 2546 HeapObject* new_area = free_list_.Allocate<FreeList::BEST_FIT>(size_in_bytes);
2512 if (new_area == NULL) new_area = SlowAllocateRaw(size_in_bytes); 2547 if (new_area == NULL) {
2548 new_area = SlowAllocateRaw<FreeList::BEST_FIT>(size_in_bytes);
2549 }
2513 if (new_area == NULL) return false; 2550 if (new_area == NULL) return false;
2514 2551
2515 int old_linear_size = static_cast<int>(limit() - top()); 2552 int old_linear_size = static_cast<int>(limit() - top());
2516 // Mark the old linear allocation area with a free space so it can be 2553 // Mark the old linear allocation area with a free space so it can be
2517 // skipped when scanning the heap. This also puts it back in the free list 2554 // skipped when scanning the heap. This also puts it back in the free list
2518 // if it is big enough. 2555 // if it is big enough.
2519 Free(top(), old_linear_size); 2556 Free(top(), old_linear_size);
2520 2557
2521 SetTop(new_area->address(), new_area->address() + size_in_bytes); 2558 SetTop(new_area->address(), new_area->address() + size_in_bytes);
2522 return true; 2559 return true;
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
2607 } 2644 }
2608 return false; 2645 return false;
2609 } 2646 }
2610 return true; 2647 return true;
2611 } else { 2648 } else {
2612 return AdvanceSweeper(size_in_bytes); 2649 return AdvanceSweeper(size_in_bytes);
2613 } 2650 }
2614 } 2651 }
2615 2652
2616 2653
2654 template HeapObject* PagedSpace::
2655 SlowAllocateRaw<FreeList::BEST_FIT>(int size_in_bytes);
2656
2657
2658 template HeapObject* PagedSpace::
2659 SlowAllocateRaw<FreeList::WORST_FIT>(int size_in_bytes);
2660
2661
2662 template<FreeList::AllocationStrategy strategy>
2617 HeapObject* PagedSpace::SlowAllocateRaw(int size_in_bytes) { 2663 HeapObject* PagedSpace::SlowAllocateRaw(int size_in_bytes) {
2618 // Allocation in this space has failed. 2664 // Allocation in this space has failed.
2619 2665
2620 // If there are unswept pages advance lazy sweeper a bounded number of times 2666 // If there are unswept pages advance lazy sweeper a bounded number of times
2621 // until we find a size_in_bytes contiguous piece of memory 2667 // until we find a size_in_bytes contiguous piece of memory
2622 const int kMaxSweepingTries = 5; 2668 const int kMaxSweepingTries = 5;
2623 bool sweeping_complete = false; 2669 bool sweeping_complete = false;
2624 2670
2625 for (int i = 0; i < kMaxSweepingTries && !sweeping_complete; i++) { 2671 for (int i = 0; i < kMaxSweepingTries && !sweeping_complete; i++) {
2626 sweeping_complete = EnsureSweeperProgress(size_in_bytes); 2672 sweeping_complete = EnsureSweeperProgress(size_in_bytes);
2627 2673
2628 // Retry the free list allocation. 2674 // Retry the free list allocation.
2629 HeapObject* object = free_list_.Allocate(size_in_bytes); 2675 HeapObject* object = free_list_.Allocate<strategy>(size_in_bytes);
2630 if (object != NULL) return object; 2676 if (object != NULL) return object;
2631 } 2677 }
2632 2678
2633 // Free list allocation failed and there is no next page. Fail if we have 2679 // Free list allocation failed and there is no next page. Fail if we have
2634 // hit the old generation size limit that should cause a garbage 2680 // hit the old generation size limit that should cause a garbage
2635 // collection. 2681 // collection.
2636 if (!heap()->always_allocate() && 2682 if (!heap()->always_allocate() &&
2637 heap()->OldGenerationAllocationLimitReached()) { 2683 heap()->OldGenerationAllocationLimitReached()) {
2638 return NULL; 2684 return NULL;
2639 } 2685 }
2640 2686
2641 // Try to expand the space and allocate in the new next page. 2687 // Try to expand the space and allocate in the new next page.
2642 if (Expand()) { 2688 if (Expand()) {
2643 return free_list_.Allocate(size_in_bytes); 2689 return free_list_.Allocate<strategy>(size_in_bytes);
2644 } 2690 }
2645 2691
2646 // Last ditch, sweep all the remaining pages to try to find space. This may 2692 // Last ditch, sweep all the remaining pages to try to find space. This may
2647 // cause a pause. 2693 // cause a pause.
2648 if (!IsLazySweepingComplete()) { 2694 if (!IsLazySweepingComplete()) {
2649 EnsureSweeperProgress(kMaxInt); 2695 EnsureSweeperProgress(kMaxInt);
2650 2696
2651 // Retry the free list allocation. 2697 // Retry the free list allocation.
2652 HeapObject* object = free_list_.Allocate(size_in_bytes); 2698 HeapObject* object = free_list_.Allocate<strategy>(size_in_bytes);
2653 if (object != NULL) return object; 2699 if (object != NULL) return object;
2654 } 2700 }
2655 2701
2656 // Finally, fail. 2702 // Finally, fail.
2657 return NULL; 2703 return NULL;
2658 } 2704 }
2659 2705
2660 2706
2661 #ifdef DEBUG 2707 #ifdef DEBUG
2662 void PagedSpace::ReportCodeStatistics() { 2708 void PagedSpace::ReportCodeStatistics() {
(...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after
3176 object->ShortPrint(); 3222 object->ShortPrint();
3177 PrintF("\n"); 3223 PrintF("\n");
3178 } 3224 }
3179 printf(" --------------------------------------\n"); 3225 printf(" --------------------------------------\n");
3180 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); 3226 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes());
3181 } 3227 }
3182 3228
3183 #endif // DEBUG 3229 #endif // DEBUG
3184 3230
3185 } } // namespace v8::internal 3231 } } // namespace v8::internal
OLDNEW
« src/spaces.h ('K') | « src/spaces.h ('k') | src/spaces-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698