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

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

Issue 1077153004: Reland: Fix logic for incremental marking steps on tenured allocation (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Don't start incremental marking while the linear allocation area is in an inconsistent state Created 5 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
« 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/v8.h" 5 #include "src/v8.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.h" 9 #include "src/full-codegen.h"
10 #include "src/heap/mark-compact.h" 10 #include "src/heap/mark-compact.h"
(...skipping 2182 matching lines...) Expand 10 before | Expand all | Expand 10 after
2193 free_bytes += huge_list_.Concatenate(free_list->huge_list()); 2193 free_bytes += huge_list_.Concatenate(free_list->huge_list());
2194 return free_bytes; 2194 return free_bytes;
2195 } 2195 }
2196 2196
2197 2197
2198 void FreeList::Reset() { 2198 void FreeList::Reset() {
2199 small_list_.Reset(); 2199 small_list_.Reset();
2200 medium_list_.Reset(); 2200 medium_list_.Reset();
2201 large_list_.Reset(); 2201 large_list_.Reset();
2202 huge_list_.Reset(); 2202 huge_list_.Reset();
2203 unreported_allocation_ = 0;
2203 } 2204 }
2204 2205
2205 2206
2206 int FreeList::Free(Address start, int size_in_bytes) { 2207 int FreeList::Free(Address start, int size_in_bytes) {
2207 if (size_in_bytes == 0) return 0; 2208 if (size_in_bytes == 0) return 0;
2208 2209
2209 heap_->CreateFillerObjectAt(start, size_in_bytes); 2210 heap_->CreateFillerObjectAt(start, size_in_bytes);
2210 2211
2211 Page* page = Page::FromAddress(start); 2212 Page* page = Page::FromAddress(start);
2212 2213
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
2340 page = Page::FromAddress(node->address()); 2341 page = Page::FromAddress(node->address());
2341 page->add_available_in_large_free_list(-(*node_size)); 2342 page->add_available_in_large_free_list(-(*node_size));
2342 } 2343 }
2343 } 2344 }
2344 2345
2345 DCHECK(IsVeryLong() || available() == SumFreeLists()); 2346 DCHECK(IsVeryLong() || available() == SumFreeLists());
2346 return node; 2347 return node;
2347 } 2348 }
2348 2349
2349 2350
2351 void PagedSpace::SetTopAndLimit(Address top, Address limit) {
2352 DCHECK(top == limit ||
2353 Page::FromAddress(top) == Page::FromAddress(limit - 1));
2354 MemoryChunk::UpdateHighWaterMark(allocation_info_.top());
2355 allocation_info_.set_top(top);
2356 allocation_info_.set_limit(limit);
2357 }
2358
2359
2350 // Allocation on the old space free list. If it succeeds then a new linear 2360 // Allocation on the old space free list. If it succeeds then a new linear
2351 // allocation space has been set up with the top and limit of the space. If 2361 // allocation space has been set up with the top and limit of the space. If
2352 // the allocation fails then NULL is returned, and the caller can perform a GC 2362 // the allocation fails then NULL is returned, and the caller can perform a GC
2353 // or allocate a new page before retrying. 2363 // or allocate a new page before retrying.
2354 HeapObject* FreeList::Allocate(int size_in_bytes) { 2364 HeapObject* FreeList::Allocate(int size_in_bytes) {
2355 DCHECK(0 < size_in_bytes); 2365 DCHECK(0 < size_in_bytes);
2356 DCHECK(size_in_bytes <= kMaxBlockSize); 2366 DCHECK(size_in_bytes <= kMaxBlockSize);
2357 DCHECK(IsAligned(size_in_bytes, kPointerSize)); 2367 DCHECK(IsAligned(size_in_bytes, kPointerSize));
2358 // Don't free list allocate if there is linear space available. 2368 // Don't free list allocate if there is linear space available.
2359 DCHECK(owner_->limit() - owner_->top() < size_in_bytes); 2369 DCHECK(owner_->limit() - owner_->top() < size_in_bytes);
2360 2370
2361 int old_linear_size = static_cast<int>(owner_->limit() - owner_->top()); 2371 int old_linear_size = static_cast<int>(owner_->limit() - owner_->top());
2362 // Mark the old linear allocation area with a free space map so it can be 2372 // Mark the old linear allocation area with a free space map so it can be
2363 // skipped when scanning the heap. This also puts it back in the free list 2373 // skipped when scanning the heap. This also puts it back in the free list
2364 // if it is big enough. 2374 // if it is big enough.
2365 owner_->Free(owner_->top(), old_linear_size); 2375 owner_->Free(owner_->top(), old_linear_size);
2366 2376
2367 owner_->heap()->incremental_marking()->OldSpaceStep(size_in_bytes -
2368 old_linear_size);
2369
2370 int new_node_size = 0; 2377 int new_node_size = 0;
2371 FreeSpace* new_node = FindNodeFor(size_in_bytes, &new_node_size); 2378 FreeSpace* new_node = FindNodeFor(size_in_bytes, &new_node_size);
2372 if (new_node == NULL) { 2379 if (new_node == NULL) {
2373 owner_->SetTopAndLimit(NULL, NULL); 2380 owner_->SetTopAndLimit(NULL, NULL);
2374 return NULL; 2381 return NULL;
2375 } 2382 }
2376 2383
2377 int bytes_left = new_node_size - size_in_bytes; 2384 int bytes_left = new_node_size - size_in_bytes;
2378 DCHECK(bytes_left >= 0); 2385 DCHECK(bytes_left >= 0);
2379 2386
2380 #ifdef DEBUG 2387 #ifdef DEBUG
2381 for (int i = 0; i < size_in_bytes / kPointerSize; i++) { 2388 for (int i = 0; i < size_in_bytes / kPointerSize; i++) {
2382 reinterpret_cast<Object**>(new_node->address())[i] = 2389 reinterpret_cast<Object**>(new_node->address())[i] =
2383 Smi::FromInt(kCodeZapValue); 2390 Smi::FromInt(kCodeZapValue);
2384 } 2391 }
2385 #endif 2392 #endif
2386 2393
2387 // The old-space-step might have finished sweeping and restarted marking. 2394 // The old-space-step might have finished sweeping and restarted marking.
2388 // Verify that it did not turn the page of the new node into an evacuation 2395 // Verify that it did not turn the page of the new node into an evacuation
2389 // candidate. 2396 // candidate.
2390 DCHECK(!MarkCompactCollector::IsOnEvacuationCandidate(new_node)); 2397 DCHECK(!MarkCompactCollector::IsOnEvacuationCandidate(new_node));
2391 2398
2392 const int kThreshold = IncrementalMarking::kAllocatedThreshold; 2399 // An old-space step will mark more data per byte allocated, because old space
2400 // allocation is more serious. We don't want the pause to be bigger, so we
2401 // do marking after a smaller amount of allocation.
2402 const int kThreshold = IncrementalMarking::kAllocatedThreshold *
2403 IncrementalMarking::kOldSpaceAllocationMarkingFactor;
2393 2404
2394 // Memory in the linear allocation area is counted as allocated. We may free 2405 // Memory in the linear allocation area is counted as allocated. We may free
2395 // a little of this again immediately - see below. 2406 // a little of this again immediately - see below.
2396 owner_->Allocate(new_node_size); 2407 owner_->Allocate(new_node_size);
2397 2408
2409 unreported_allocation_ += new_node_size;
2410
2398 if (owner_->heap()->inline_allocation_disabled()) { 2411 if (owner_->heap()->inline_allocation_disabled()) {
2399 // Keep the linear allocation area empty if requested to do so, just 2412 // Keep the linear allocation area empty if requested to do so, just
2400 // return area back to the free list instead. 2413 // return area back to the free list instead.
2401 owner_->Free(new_node->address() + size_in_bytes, bytes_left); 2414 owner_->Free(new_node->address() + size_in_bytes, bytes_left);
2402 DCHECK(owner_->top() == NULL && owner_->limit() == NULL); 2415 DCHECK(owner_->top() == NULL && owner_->limit() == NULL);
2403 } else if (bytes_left > kThreshold && 2416 } else if (bytes_left > kThreshold &&
2404 owner_->heap()->incremental_marking()->IsMarkingIncomplete() && 2417 owner_->heap()->incremental_marking()->CanDoSteps()) {
2405 FLAG_incremental_marking_steps) {
2406 int linear_size = owner_->RoundSizeDownToObjectAlignment(kThreshold); 2418 int linear_size = owner_->RoundSizeDownToObjectAlignment(kThreshold);
2419
2407 // We don't want to give too large linear areas to the allocator while 2420 // We don't want to give too large linear areas to the allocator while
2408 // incremental marking is going on, because we won't check again whether 2421 // incremental marking is going on, because we won't check again whether
2409 // we want to do another increment until the linear area is used up. 2422 // we want to do another increment until the linear area is used up.
2410 owner_->Free(new_node->address() + size_in_bytes + linear_size, 2423 owner_->Free(new_node->address() + size_in_bytes + linear_size,
2411 new_node_size - size_in_bytes - linear_size); 2424 new_node_size - size_in_bytes - linear_size);
2412 owner_->SetTopAndLimit(new_node->address() + size_in_bytes, 2425 owner_->SetTopAndLimit(new_node->address() + size_in_bytes,
2413 new_node->address() + size_in_bytes + linear_size); 2426 new_node->address() + size_in_bytes + linear_size);
2414 } else if (bytes_left > 0) { 2427 // It is important that we are done updating top and limit before we call
2415 // Normally we give the rest of the node to the allocator as its new 2428 // this.
Hannes Payer (out of office) 2015/04/22 14:06:21 Can you say way in the comment to make it clear?
Erik Corry Chromium.org 2015/06/29 14:45:30 Done.
2416 // linear allocation area. 2429 owner_->heap()->incremental_marking()->OldSpaceStep(size_in_bytes +
2417 owner_->SetTopAndLimit(new_node->address() + size_in_bytes, 2430 linear_size);
2418 new_node->address() + new_node_size); 2431 unreported_allocation_ = 0;
2419 } else { 2432 } else {
Hannes Payer (out of office) 2015/04/22 14:06:21 Please add the same comment from above also here.
Erik Corry Chromium.org 2015/06/29 14:45:30 The comment is there, just before the call to OldS
2420 // TODO(gc) Try not freeing linear allocation region when bytes_left 2433 if (bytes_left > 0) {
2421 // are zero. 2434 // Normally we give the rest of the node to the allocator as its new
2422 owner_->SetTopAndLimit(NULL, NULL); 2435 // linear allocation area.
2436 owner_->SetTopAndLimit(new_node->address() + size_in_bytes,
2437 new_node->address() + new_node_size);
2438 } else {
2439 // TODO(gc) Try not freeing linear allocation region when bytes_left
2440 // are zero.
2441 owner_->SetTopAndLimit(NULL, NULL);
2442 }
2443 if (unreported_allocation_ > kThreshold) {
2444 // This may start the incremental marker, or do a little work if it's
2445 // already started. It is important that we are finished updating top
2446 // and limit before we call this.
2447 owner_->heap()->incremental_marking()->OldSpaceStep(
2448 Min(kThreshold, unreported_allocation_));
2449 unreported_allocation_ = 0;
2450 }
2423 } 2451 }
2424 2452
2425 return new_node; 2453 return new_node;
2426 } 2454 }
2427 2455
2428 2456
2429 intptr_t FreeList::EvictFreeListItems(Page* p) { 2457 intptr_t FreeList::EvictFreeListItems(Page* p) {
2430 intptr_t sum = huge_list_.EvictFreeListItemsInList(p); 2458 intptr_t sum = huge_list_.EvictFreeListItemsInList(p);
2431 p->set_available_in_huge_free_list(0); 2459 p->set_available_in_huge_free_list(0);
2432 2460
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after
2899 MSAN_ALLOCATED_UNINITIALIZED_MEMORY(object->address(), object_size); 2927 MSAN_ALLOCATED_UNINITIALIZED_MEMORY(object->address(), object_size);
2900 2928
2901 if (Heap::ShouldZapGarbage()) { 2929 if (Heap::ShouldZapGarbage()) {
2902 // Make the object consistent so the heap can be verified in OldSpaceStep. 2930 // Make the object consistent so the heap can be verified in OldSpaceStep.
2903 // We only need to do this in debug builds or if verify_heap is on. 2931 // We only need to do this in debug builds or if verify_heap is on.
2904 reinterpret_cast<Object**>(object->address())[0] = 2932 reinterpret_cast<Object**>(object->address())[0] =
2905 heap()->fixed_array_map(); 2933 heap()->fixed_array_map();
2906 reinterpret_cast<Object**>(object->address())[1] = Smi::FromInt(0); 2934 reinterpret_cast<Object**>(object->address())[1] = Smi::FromInt(0);
2907 } 2935 }
2908 2936
2909 heap()->incremental_marking()->OldSpaceStep(object_size); 2937 // We would like to tell the incremental marker to do a lot of work, since
2938 // we just made a large allocation in old space, but that might cause a huge
2939 // pause. Underreporting here may cause the marker to speed up because it
2940 // will perceive that it is not keeping up with allocation. Although this
2941 // causes some big incremental marking steps they are not as big as this one
2942 // might have been. In testing, a very large pause was divided up into about
2943 // 12 parts.
2944 const int kThreshold = IncrementalMarking::kAllocatedThreshold *
2945 IncrementalMarking::kOldSpaceAllocationMarkingFactor;
2946 heap()->incremental_marking()->OldSpaceStep(kThreshold);
2910 return object; 2947 return object;
2911 } 2948 }
2912 2949
2913 2950
2914 size_t LargeObjectSpace::CommittedPhysicalMemory() { 2951 size_t LargeObjectSpace::CommittedPhysicalMemory() {
2915 if (!base::VirtualMemory::HasLazyCommits()) return CommittedMemory(); 2952 if (!base::VirtualMemory::HasLazyCommits()) return CommittedMemory();
2916 size_t size = 0; 2953 size_t size = 0;
2917 LargePage* current = first_page_; 2954 LargePage* current = first_page_;
2918 while (current != NULL) { 2955 while (current != NULL) {
2919 size += current->CommittedPhysicalMemory(); 2956 size += current->CommittedPhysicalMemory();
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
3122 object->ShortPrint(); 3159 object->ShortPrint();
3123 PrintF("\n"); 3160 PrintF("\n");
3124 } 3161 }
3125 printf(" --------------------------------------\n"); 3162 printf(" --------------------------------------\n");
3126 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); 3163 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes());
3127 } 3164 }
3128 3165
3129 #endif // DEBUG 3166 #endif // DEBUG
3130 } 3167 }
3131 } // namespace v8::internal 3168 } // namespace v8::internal
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