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

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
« no previous file with comments | « src/spaces.h ('k') | src/spaces-inl.h » ('j') | 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 // 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 2197 matching lines...) Expand 10 before | Expand all | Expand 10 after
2208 } else { 2208 } else {
2209 huge_list_.Free(node, size_in_bytes); 2209 huge_list_.Free(node, size_in_bytes);
2210 page->add_available_in_huge_free_list(size_in_bytes); 2210 page->add_available_in_huge_free_list(size_in_bytes);
2211 } 2211 }
2212 2212
2213 ASSERT(IsVeryLong() || available() == SumFreeLists()); 2213 ASSERT(IsVeryLong() || available() == SumFreeLists());
2214 return 0; 2214 return 0;
2215 } 2215 }
2216 2216
2217 2217
2218 FreeListNode* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { 2218 FreeListNode* FreeList::FindNodeInHugeList(int size_in_bytes, int* node_size) {
2219 FreeListNode* node = NULL; 2219 FreeListNode* node = NULL;
2220 Page* page = NULL;
2221
2222 if (size_in_bytes <= kSmallAllocationMax) {
2223 node = small_list_.PickNodeFromList(node_size);
2224 if (node != NULL) {
2225 page = Page::FromAddress(node->address());
2226 page->add_available_in_small_free_list(-(*node_size));
2227 return node;
2228 }
2229 }
2230
2231 if (size_in_bytes <= kMediumAllocationMax) {
2232 node = medium_list_.PickNodeFromList(node_size);
2233 if (node != NULL) {
2234 page = Page::FromAddress(node->address());
2235 page->add_available_in_medium_free_list(-(*node_size));
2236 return node;
2237 }
2238 }
2239
2240 if (size_in_bytes <= kLargeAllocationMax) {
2241 node = large_list_.PickNodeFromList(node_size);
2242 if (node != NULL) {
2243 page = Page::FromAddress(node->address());
2244 page->add_available_in_large_free_list(-(*node_size));
2245 return node;
2246 }
2247 }
2248 2220
2249 int huge_list_available = huge_list_.available(); 2221 int huge_list_available = huge_list_.available();
2250 for (FreeListNode** cur = huge_list_.GetTopAddress(); 2222 for (FreeListNode** cur = huge_list_.GetTopAddress();
2251 *cur != NULL; 2223 *cur != NULL;
2252 cur = (*cur)->next_address()) { 2224 cur = (*cur)->next_address()) {
2253 FreeListNode* cur_node = *cur; 2225 FreeListNode* cur_node = *cur;
2254 while (cur_node != NULL && 2226 while (cur_node != NULL &&
2255 Page::FromAddress(cur_node->address())->IsEvacuationCandidate()) { 2227 Page::FromAddress(cur_node->address())->IsEvacuationCandidate()) {
2256 int size = reinterpret_cast<FreeSpace*>(cur_node)->Size(); 2228 int size = reinterpret_cast<FreeSpace*>(cur_node)->Size();
2257 huge_list_available -= size; 2229 huge_list_available -= size;
2258 page = Page::FromAddress(cur_node->address()); 2230 Page* page = Page::FromAddress(cur_node->address());
2259 page->add_available_in_huge_free_list(-size); 2231 page->add_available_in_huge_free_list(-size);
2260 cur_node = cur_node->next(); 2232 cur_node = cur_node->next();
2261 } 2233 }
2262 2234
2263 *cur = cur_node; 2235 *cur = cur_node;
2264 if (cur_node == NULL) { 2236 if (cur_node == NULL) {
2265 huge_list_.set_end(NULL); 2237 huge_list_.set_end(NULL);
2266 break; 2238 break;
2267 } 2239 }
2268 2240
2269 ASSERT((*cur)->map() == heap_->raw_unchecked_free_space_map()); 2241 ASSERT((*cur)->map() == heap_->raw_unchecked_free_space_map());
2270 FreeSpace* cur_as_free_space = reinterpret_cast<FreeSpace*>(*cur); 2242 FreeSpace* cur_as_free_space = reinterpret_cast<FreeSpace*>(*cur);
2271 int size = cur_as_free_space->Size(); 2243 int size = cur_as_free_space->Size();
2272 if (size >= size_in_bytes) { 2244 if (size >= size_in_bytes) {
2273 // Large enough node found. Unlink it from the list. 2245 // Large enough node found. Unlink it from the list.
2274 node = *cur; 2246 node = *cur;
2275 *cur = node->next(); 2247 *cur = node->next();
2276 *node_size = size; 2248 *node_size = size;
2277 huge_list_available -= size; 2249 huge_list_available -= size;
2278 page = Page::FromAddress(node->address()); 2250 Page* page = Page::FromAddress(node->address());
2279 page->add_available_in_huge_free_list(-size); 2251 page->add_available_in_huge_free_list(-size);
2280 break; 2252 break;
2281 } 2253 }
2282 } 2254 }
2283 2255
2284 if (huge_list_.top() == NULL) { 2256 if (huge_list_.top() == NULL) {
2285 huge_list_.set_end(NULL); 2257 huge_list_.set_end(NULL);
2286 } 2258 }
2287 2259
2288 huge_list_.set_available(huge_list_available); 2260 huge_list_.set_available(huge_list_available);
2289 ASSERT(IsVeryLong() || available() == SumFreeLists()); 2261 ASSERT(IsVeryLong() || available() == SumFreeLists());
2290 2262
2291 return node; 2263 return node;
2292 } 2264 }
2293 2265
2294 2266
2267 FreeListNode* FreeList::FindNodeForWorstFit(int size_in_bytes, int* node_size) {
2268 FreeListNode* node = FindNodeInHugeList(size_in_bytes, node_size);
2269 if (node != NULL) {
2270 return node;
2271 }
2272
2273 if (size_in_bytes <= kLargeAllocationMax) {
2274 node = large_list_.PickNodeFromList(node_size);
2275 if (node != NULL) {
2276 Page* page = Page::FromAddress(node->address());
2277 page->add_available_in_large_free_list(-(*node_size));
2278 return node;
2279 }
2280 }
2281
2282 if (size_in_bytes <= kMediumAllocationMax) {
2283 node = medium_list_.PickNodeFromList(node_size);
2284 if (node != NULL) {
2285 Page* page = Page::FromAddress(node->address());
2286 page->add_available_in_medium_free_list(-(*node_size));
2287 return node;
2288 }
2289 }
2290
2291 return node;
2292 }
2293
2294
2295 FreeListNode* FreeList::FindNodeForBestFit(int size_in_bytes, int* node_size) {
2296 FreeListNode* node = NULL;
2297
2298 if (size_in_bytes <= kSmallAllocationMax) {
2299 node = small_list_.PickNodeFromList(node_size);
2300 if (node != NULL) {
2301 Page* page = Page::FromAddress(node->address());
2302 page->add_available_in_small_free_list(-(*node_size));
2303 return node;
2304 }
2305 }
2306
2307 if (size_in_bytes <= kMediumAllocationMax) {
2308 node = medium_list_.PickNodeFromList(node_size);
2309 if (node != NULL) {
2310 Page* page = Page::FromAddress(node->address());
2311 page->add_available_in_medium_free_list(-(*node_size));
2312 return node;
2313 }
2314 }
2315
2316 if (size_in_bytes <= kLargeAllocationMax) {
2317 node = large_list_.PickNodeFromList(node_size);
2318 if (node != NULL) {
2319 Page* page = Page::FromAddress(node->address());
2320 page->add_available_in_large_free_list(-(*node_size));
2321 return node;
2322 }
2323 }
2324
2325 node = FindNodeInHugeList(size_in_bytes, node_size);
2326 return node;
2327 }
2328
2329
2330 template HeapObject* FreeList::Allocate<FreeList::BEST_FIT>(int size_in_bytes);
2331
2332
2333 template HeapObject* FreeList::Allocate<FreeList::WORST_FIT>(int size_in_bytes);
2334
2335
2295 // Allocation on the old space free list. If it succeeds then a new linear 2336 // Allocation on the old space free list. If it succeeds then a new linear
2296 // allocation space has been set up with the top and limit of the space. If 2337 // allocation space has been set up with the top and limit of the space. If
2297 // the allocation fails then NULL is returned, and the caller can perform a GC 2338 // the allocation fails then NULL is returned, and the caller can perform a GC
2298 // or allocate a new page before retrying. 2339 // or allocate a new page before retrying.
2340 template<FreeList::AllocationStrategy strategy>
2299 HeapObject* FreeList::Allocate(int size_in_bytes) { 2341 HeapObject* FreeList::Allocate(int size_in_bytes) {
2300 ASSERT(0 < size_in_bytes); 2342 ASSERT(0 < size_in_bytes);
2301 ASSERT(size_in_bytes <= kMaxBlockSize); 2343 ASSERT(size_in_bytes <= kMaxBlockSize);
2302 ASSERT(IsAligned(size_in_bytes, kPointerSize)); 2344 ASSERT(IsAligned(size_in_bytes, kPointerSize));
2303 // Don't free list allocate if there is linear space available. 2345 // Don't free list allocate if there is linear space available.
2304 ASSERT(owner_->limit() - owner_->top() < size_in_bytes); 2346 ASSERT(owner_->limit() - owner_->top() < size_in_bytes);
2305 2347
2306 int new_node_size = 0; 2348 int new_node_size = 0;
2307 FreeListNode* new_node = FindNodeFor(size_in_bytes, &new_node_size); 2349 FreeListNode* new_node;
2350 if (FreeList::BEST_FIT == strategy) {
2351 new_node = FindNodeForBestFit(size_in_bytes, &new_node_size);
2352 } else {
2353 new_node = FindNodeForWorstFit(size_in_bytes, &new_node_size);
2354 }
2308 if (new_node == NULL) return NULL; 2355 if (new_node == NULL) return NULL;
2309 2356
2310 2357
2311 int bytes_left = new_node_size - size_in_bytes; 2358 int bytes_left = new_node_size - size_in_bytes;
2312 ASSERT(bytes_left >= 0); 2359 ASSERT(bytes_left >= 0);
2313 2360
2314 int old_linear_size = static_cast<int>(owner_->limit() - owner_->top()); 2361 int old_linear_size = static_cast<int>(owner_->limit() - owner_->top());
2315 // Mark the old linear allocation area with a free space map so it can be 2362 // Mark the old linear allocation area with a free space map so it can be
2316 // skipped when scanning the heap. This also puts it back in the free list 2363 // skipped when scanning the heap. This also puts it back in the free list
2317 // if it is big enough. 2364 // if it is big enough.
(...skipping 10 matching lines...) Expand all
2328 #endif 2375 #endif
2329 2376
2330 // The old-space-step might have finished sweeping and restarted marking. 2377 // The old-space-step might have finished sweeping and restarted marking.
2331 // Verify that it did not turn the page of the new node into an evacuation 2378 // Verify that it did not turn the page of the new node into an evacuation
2332 // candidate. 2379 // candidate.
2333 ASSERT(!MarkCompactCollector::IsOnEvacuationCandidate(new_node)); 2380 ASSERT(!MarkCompactCollector::IsOnEvacuationCandidate(new_node));
2334 2381
2335 const int kThreshold = IncrementalMarking::kAllocatedThreshold; 2382 const int kThreshold = IncrementalMarking::kAllocatedThreshold;
2336 2383
2337 // Memory in the linear allocation area is counted as allocated. We may free 2384 // Memory in the linear allocation area is counted as allocated. We may free
2338 // a little of this again immediately - see below. 2385 // a little of this again immediately - see below. We try to create large
2386 // bump pointer ranges when we use worst-fit, therefore we do not give
2387 // memory back to the free-list.
2339 owner_->Allocate(new_node_size); 2388 owner_->Allocate(new_node_size);
2340 2389
2341 if (bytes_left > kThreshold && 2390 if (FreeList::WORST_FIT == strategy) {
2391 owner_->AllocatePretenure(new_node_size);
2392 }
2393
2394 if (FreeList::BEST_FIT == strategy &&
2395 bytes_left > kThreshold &&
2342 owner_->heap()->incremental_marking()->IsMarkingIncomplete() && 2396 owner_->heap()->incremental_marking()->IsMarkingIncomplete() &&
2343 FLAG_incremental_marking_steps) { 2397 FLAG_incremental_marking_steps) {
2344 int linear_size = owner_->RoundSizeDownToObjectAlignment(kThreshold); 2398 int linear_size = owner_->RoundSizeDownToObjectAlignment(kThreshold);
2345 // We don't want to give too large linear areas to the allocator while 2399 // We don't want to give too large linear areas to the allocator while
2346 // incremental marking is going on, because we won't check again whether 2400 // incremental marking is going on, because we won't check again whether
2347 // we want to do another increment until the linear area is used up. 2401 // we want to do another increment until the linear area is used up.
2348 owner_->Free(new_node->address() + size_in_bytes + linear_size, 2402 owner_->Free(new_node->address() + size_in_bytes + linear_size,
2349 new_node_size - size_in_bytes - linear_size); 2403 new_node_size - size_in_bytes - linear_size);
2350 owner_->SetTop(new_node->address() + size_in_bytes, 2404 owner_->SetTop(new_node->address() + size_in_bytes,
2351 new_node->address() + size_in_bytes + linear_size); 2405 new_node->address() + size_in_bytes + linear_size);
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
2500 } 2554 }
2501 2555
2502 2556
2503 bool PagedSpace::ReserveSpace(int size_in_bytes) { 2557 bool PagedSpace::ReserveSpace(int size_in_bytes) {
2504 ASSERT(size_in_bytes <= AreaSize()); 2558 ASSERT(size_in_bytes <= AreaSize());
2505 ASSERT(size_in_bytes == RoundSizeDownToObjectAlignment(size_in_bytes)); 2559 ASSERT(size_in_bytes == RoundSizeDownToObjectAlignment(size_in_bytes));
2506 Address current_top = allocation_info_.top; 2560 Address current_top = allocation_info_.top;
2507 Address new_top = current_top + size_in_bytes; 2561 Address new_top = current_top + size_in_bytes;
2508 if (new_top <= allocation_info_.limit) return true; 2562 if (new_top <= allocation_info_.limit) return true;
2509 2563
2510 HeapObject* new_area = free_list_.Allocate(size_in_bytes); 2564 HeapObject* new_area = free_list_.Allocate<FreeList::BEST_FIT>(size_in_bytes);
2511 if (new_area == NULL) new_area = SlowAllocateRaw(size_in_bytes); 2565 if (new_area == NULL) {
2566 new_area = SlowAllocateRaw<FreeList::BEST_FIT>(size_in_bytes);
2567 }
2512 if (new_area == NULL) return false; 2568 if (new_area == NULL) return false;
2513 2569
2514 int old_linear_size = static_cast<int>(limit() - top()); 2570 int old_linear_size = static_cast<int>(limit() - top());
2515 // Mark the old linear allocation area with a free space so it can be 2571 // Mark the old linear allocation area with a free space so it can be
2516 // skipped when scanning the heap. This also puts it back in the free list 2572 // skipped when scanning the heap. This also puts it back in the free list
2517 // if it is big enough. 2573 // if it is big enough.
2518 Free(top(), old_linear_size); 2574 Free(top(), old_linear_size);
2519 2575
2520 SetTop(new_area->address(), new_area->address() + size_in_bytes); 2576 SetTop(new_area->address(), new_area->address() + size_in_bytes);
2521 return true; 2577 return true;
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
2606 } 2662 }
2607 return false; 2663 return false;
2608 } 2664 }
2609 return true; 2665 return true;
2610 } else { 2666 } else {
2611 return AdvanceSweeper(size_in_bytes); 2667 return AdvanceSweeper(size_in_bytes);
2612 } 2668 }
2613 } 2669 }
2614 2670
2615 2671
2672 template HeapObject* PagedSpace::
2673 SlowAllocateRaw<FreeList::BEST_FIT>(int size_in_bytes);
2674
2675
2676 template HeapObject* PagedSpace::
2677 SlowAllocateRaw<FreeList::WORST_FIT>(int size_in_bytes);
2678
2679
2680 template<FreeList::AllocationStrategy strategy>
2616 HeapObject* PagedSpace::SlowAllocateRaw(int size_in_bytes) { 2681 HeapObject* PagedSpace::SlowAllocateRaw(int size_in_bytes) {
2617 // Allocation in this space has failed. 2682 // Allocation in this space has failed.
2618 2683
2619 // If there are unswept pages advance lazy sweeper a bounded number of times 2684 // If there are unswept pages advance lazy sweeper a bounded number of times
2620 // until we find a size_in_bytes contiguous piece of memory 2685 // until we find a size_in_bytes contiguous piece of memory
2621 const int kMaxSweepingTries = 5; 2686 const int kMaxSweepingTries = 5;
2622 bool sweeping_complete = false; 2687 bool sweeping_complete = false;
2623 2688
2624 for (int i = 0; i < kMaxSweepingTries && !sweeping_complete; i++) { 2689 for (int i = 0; i < kMaxSweepingTries && !sweeping_complete; i++) {
2625 sweeping_complete = EnsureSweeperProgress(size_in_bytes); 2690 sweeping_complete = EnsureSweeperProgress(size_in_bytes);
2626 2691
2627 // Retry the free list allocation. 2692 // Retry the free list allocation.
2628 HeapObject* object = free_list_.Allocate(size_in_bytes); 2693 HeapObject* object = free_list_.Allocate<strategy>(size_in_bytes);
2629 if (object != NULL) return object; 2694 if (object != NULL) return object;
2630 } 2695 }
2631 2696
2632 // Free list allocation failed and there is no next page. Fail if we have 2697 // Free list allocation failed and there is no next page. Fail if we have
2633 // hit the old generation size limit that should cause a garbage 2698 // hit the old generation size limit that should cause a garbage
2634 // collection. 2699 // collection.
2635 if (!heap()->always_allocate() && 2700 if (!heap()->always_allocate() &&
2701 !heap()->AggressivePromotionMode() &&
2636 heap()->OldGenerationAllocationLimitReached()) { 2702 heap()->OldGenerationAllocationLimitReached()) {
2637 return NULL; 2703 return NULL;
2638 } 2704 }
2639 2705
2640 // Try to expand the space and allocate in the new next page. 2706 // Try to expand the space and allocate in the new next page.
2641 if (Expand()) { 2707 if (Expand()) {
2642 return free_list_.Allocate(size_in_bytes); 2708 return free_list_.Allocate<strategy>(size_in_bytes);
2643 } 2709 }
2644 2710
2645 // Last ditch, sweep all the remaining pages to try to find space. This may 2711 // Last ditch, sweep all the remaining pages to try to find space. This may
2646 // cause a pause. 2712 // cause a pause.
2647 if (!IsLazySweepingComplete()) { 2713 if (!IsLazySweepingComplete()) {
2648 EnsureSweeperProgress(kMaxInt); 2714 EnsureSweeperProgress(kMaxInt);
2649 2715
2650 // Retry the free list allocation. 2716 // Retry the free list allocation.
2651 HeapObject* object = free_list_.Allocate(size_in_bytes); 2717 HeapObject* object = free_list_.Allocate<strategy>(size_in_bytes);
2652 if (object != NULL) return object; 2718 if (object != NULL) return object;
2653 } 2719 }
2654 2720
2655 // Finally, fail. 2721 // Finally, fail.
2656 return NULL; 2722 return NULL;
2657 } 2723 }
2658 2724
2659 2725
2660 #ifdef DEBUG 2726 #ifdef DEBUG
2661 void PagedSpace::ReportCodeStatistics() { 2727 void PagedSpace::ReportCodeStatistics() {
(...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after
3175 object->ShortPrint(); 3241 object->ShortPrint();
3176 PrintF("\n"); 3242 PrintF("\n");
3177 } 3243 }
3178 printf(" --------------------------------------\n"); 3244 printf(" --------------------------------------\n");
3179 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); 3245 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes());
3180 } 3246 }
3181 3247
3182 #endif // DEBUG 3248 #endif // DEBUG
3183 3249
3184 } } // namespace v8::internal 3250 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/spaces.h ('k') | src/spaces-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698