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

Side by Side Diff: src/mark-compact.cc

Issue 6970004: Introduce lazy sweeping. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/gc
Patch Set: Created 9 years, 7 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 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 156
157 void MarkCompactCollector::CollectGarbage() { 157 void MarkCompactCollector::CollectGarbage() {
158 // Make sure that Prepare() has been called. The individual steps below will 158 // Make sure that Prepare() has been called. The individual steps below will
159 // update the state as they proceed. 159 // update the state as they proceed.
160 ASSERT(state_ == PREPARE_GC); 160 ASSERT(state_ == PREPARE_GC);
161 161
162 // Prepare has selected whether to compact the old generation or not. 162 // Prepare has selected whether to compact the old generation or not.
163 // Tell the tracer. 163 // Tell the tracer.
164 if (IsCompacting()) tracer_->set_is_compacting(); 164 if (IsCompacting()) tracer_->set_is_compacting();
165 165
166 if (heap_->incremental_marking()->IsStopped()) { 166 if (!heap_->incremental_marking()->IsMarking()) {
167 heap_->incremental_marking()->Abort();
167 MarkLiveObjects(); 168 MarkLiveObjects();
168 } else { 169 } else {
169 { 170 {
170 GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_MARK); 171 GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_MARK);
171 heap_->incremental_marking()->Finalize(); 172 heap_->incremental_marking()->Finalize();
172 ASSERT(heap_->incremental_marking()->IsStopped());
173 } 173 }
174 MarkLiveObjects(); 174 MarkLiveObjects();
175 } 175 }
176 ASSERT(heap_->incremental_marking()->IsStopped());
176 177
177 if (FLAG_collect_maps) ClearNonLiveTransitions(); 178 if (FLAG_collect_maps) ClearNonLiveTransitions();
178 179
179 #ifdef DEBUG 180 #ifdef DEBUG
180 VerifyMarking(); 181 VerifyMarking();
181 #endif 182 #endif
182 183
183 SweepSpaces(); 184 SweepSpaces();
184 185
185 // TODO(gc) ISOLATES 186 // TODO(gc) ISOLATES
(...skipping 2194 matching lines...) Expand 10 before | Expand all | Expand 10 after
2380 } 2381 }
2381 2382
2382 2383
2383 // Sweeps a space conservatively. After this has been done the larger free 2384 // Sweeps a space conservatively. After this has been done the larger free
2384 // spaces have been put on the free list and the smaller ones have been 2385 // spaces have been put on the free list and the smaller ones have been
2385 // ignored and left untouched. A free space is always either ignored or put 2386 // ignored and left untouched. A free space is always either ignored or put
2386 // on the free list, never split up into two parts. This is important 2387 // on the free list, never split up into two parts. This is important
2387 // because it means that any FreeSpace maps left actually describe a region of 2388 // because it means that any FreeSpace maps left actually describe a region of
2388 // memory that can be ignored when scanning. Dead objects other than free 2389 // memory that can be ignored when scanning. Dead objects other than free
2389 // spaces will not contain the free space map. 2390 // spaces will not contain the free space map.
2390 static void SweepConservatively(PagedSpace* space, 2391 int MarkCompactCollector::SweepConservatively(PagedSpace* space, Page* p) {
2391 Page* p) { 2392 int freed_bytes = 0;
2393
2392 MarkBit::CellType* cells = p->markbits()->cells(); 2394 MarkBit::CellType* cells = p->markbits()->cells();
2393 2395
2394 p->SetFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY); 2396 p->SetFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY);
2395 2397
2396 // This is the start of the 32 word block that we are currently looking at. 2398 // This is the start of the 32 word block that we are currently looking at.
2397 Address block_address = p->ObjectAreaStart(); 2399 Address block_address = p->ObjectAreaStart();
2398 2400
2399 int last_cell_index = 2401 int last_cell_index =
2400 Page::MarkbitsBitmap::IndexToCell( 2402 Page::MarkbitsBitmap::IndexToCell(
2401 Page::MarkbitsBitmap::CellAlignIndex( 2403 Page::MarkbitsBitmap::CellAlignIndex(
2402 p->AddressToMarkbitIndex(p->ObjectAreaEnd()))); 2404 p->AddressToMarkbitIndex(p->ObjectAreaEnd())));
2403 2405
2404 int cell_index = Page::kFirstUsedCell; 2406 int cell_index = Page::kFirstUsedCell;
2405 2407
2406 // Skip over all the dead objects at the start of the page and mark them free. 2408 // Skip over all the dead objects at the start of the page and mark them free.
2407 for (cell_index = Page::kFirstUsedCell; 2409 for (cell_index = Page::kFirstUsedCell;
2408 cell_index < last_cell_index; 2410 cell_index < last_cell_index;
2409 cell_index++, block_address += 32 * kPointerSize) { 2411 cell_index++, block_address += 32 * kPointerSize) {
2410 if (cells[cell_index] != 0) break; 2412 if (cells[cell_index] != 0) break;
2411 } 2413 }
2412 int size = block_address - p->ObjectAreaStart(); 2414 int size = block_address - p->ObjectAreaStart();
2413 if (cell_index == last_cell_index) { 2415 if (cell_index == last_cell_index) {
2414 space->Free(p->ObjectAreaStart(), size); 2416 freed_bytes += space->Free(p->ObjectAreaStart(), size);
2415 return; 2417 return freed_bytes;
2416 } 2418 }
2417 // Grow the size of the start-of-page free space a little to get up to the 2419 // Grow the size of the start-of-page free space a little to get up to the
2418 // first live object. 2420 // first live object.
2419 Address free_end = StartOfLiveObject(block_address, cells[cell_index]); 2421 Address free_end = StartOfLiveObject(block_address, cells[cell_index]);
2420 // Free the first free space. 2422 // Free the first free space.
2421 size = free_end - p->ObjectAreaStart(); 2423 size = free_end - p->ObjectAreaStart();
2422 space->Free(p->ObjectAreaStart(), size); 2424 freed_bytes += space->Free(p->ObjectAreaStart(), size);
2423 // The start of the current free area is represented in undigested form by 2425 // The start of the current free area is represented in undigested form by
2424 // the address of the last 32-word section that contained a live object and 2426 // the address of the last 32-word section that contained a live object and
2425 // the marking bitmap for that cell, which describes where the live object 2427 // the marking bitmap for that cell, which describes where the live object
2426 // started. Unless we find a large free space in the bitmap we will not 2428 // started. Unless we find a large free space in the bitmap we will not
2427 // digest this pair into a real address. We start the iteration here at the 2429 // digest this pair into a real address. We start the iteration here at the
2428 // first word in the marking bit map that indicates a live object. 2430 // first word in the marking bit map that indicates a live object.
2429 Address free_start = block_address; 2431 Address free_start = block_address;
2430 uint32_t free_start_cell = cells[cell_index]; 2432 uint32_t free_start_cell = cells[cell_index];
2431 2433
2432 for ( ; 2434 for ( ;
2433 cell_index < last_cell_index; 2435 cell_index < last_cell_index;
2434 cell_index++, block_address += 32 * kPointerSize) { 2436 cell_index++, block_address += 32 * kPointerSize) {
2435 ASSERT((unsigned)cell_index == 2437 ASSERT((unsigned)cell_index ==
2436 Page::MarkbitsBitmap::IndexToCell( 2438 Page::MarkbitsBitmap::IndexToCell(
2437 Page::MarkbitsBitmap::CellAlignIndex( 2439 Page::MarkbitsBitmap::CellAlignIndex(
2438 p->AddressToMarkbitIndex(block_address)))); 2440 p->AddressToMarkbitIndex(block_address))));
2439 uint32_t cell = cells[cell_index]; 2441 uint32_t cell = cells[cell_index];
2440 if (cell != 0) { 2442 if (cell != 0) {
2441 // We have a live object. Check approximately whether it is more than 32 2443 // We have a live object. Check approximately whether it is more than 32
2442 // words since the last live object. 2444 // words since the last live object.
2443 if (block_address - free_start > 32 * kPointerSize) { 2445 if (block_address - free_start > 32 * kPointerSize) {
2444 free_start = DigestFreeStart(free_start, free_start_cell); 2446 free_start = DigestFreeStart(free_start, free_start_cell);
2445 if (block_address - free_start > 32 * kPointerSize) { 2447 if (block_address - free_start > 32 * kPointerSize) {
2446 // Now that we know the exact start of the free space it still looks 2448 // Now that we know the exact start of the free space it still looks
2447 // like we have a large enough free space to be worth bothering with. 2449 // like we have a large enough free space to be worth bothering with.
2448 // so now we need to find the start of the first live object at the 2450 // so now we need to find the start of the first live object at the
2449 // end of the free space. 2451 // end of the free space.
2450 free_end = StartOfLiveObject(block_address, cell); 2452 free_end = StartOfLiveObject(block_address, cell);
2451 space->Free(free_start, free_end - free_start); 2453 freed_bytes += space->Free(free_start, free_end - free_start);
2452 } 2454 }
2453 } 2455 }
2454 // Update our undigested record of where the current free area started. 2456 // Update our undigested record of where the current free area started.
2455 free_start = block_address; 2457 free_start = block_address;
2456 free_start_cell = cell; 2458 free_start_cell = cell;
2457 } 2459 }
2458 } 2460 }
2459 2461
2460 // Handle the free space at the end of the page. 2462 // Handle the free space at the end of the page.
2461 if (block_address - free_start > 32 * kPointerSize) { 2463 if (block_address - free_start > 32 * kPointerSize) {
2462 free_start = DigestFreeStart(free_start, free_start_cell); 2464 free_start = DigestFreeStart(free_start, free_start_cell);
2463 space->Free(free_start, block_address - free_start); 2465 freed_bytes += space->Free(free_start, block_address - free_start);
2464 } 2466 }
2467
2468 return freed_bytes;
2465 } 2469 }
2466 2470
2467 2471
2468 // Sweep a space precisely. After this has been done the space can 2472 // Sweep a space precisely. After this has been done the space can
2469 // be iterated precisely, hitting only the live objects. Code space 2473 // be iterated precisely, hitting only the live objects. Code space
2470 // is always swept precisely because we want to be able to iterate 2474 // is always swept precisely because we want to be able to iterate
2471 // over it. Map space is swept precisely, because it is not compacted. 2475 // over it. Map space is swept precisely, because it is not compacted.
2472 static void SweepPrecisely(PagedSpace* space, 2476 static void SweepPrecisely(PagedSpace* space,
2473 Page* p) { 2477 Page* p) {
2474 MarkBit::CellType* cells = p->markbits()->cells(); 2478 MarkBit::CellType* cells = p->markbits()->cells();
(...skipping 30 matching lines...) Expand all
2505 } 2509 }
2506 } 2510 }
2507 if (free_start != p->ObjectAreaEnd()) { 2511 if (free_start != p->ObjectAreaEnd()) {
2508 space->Free(free_start, p->ObjectAreaEnd() - free_start); 2512 space->Free(free_start, p->ObjectAreaEnd() - free_start);
2509 } 2513 }
2510 } 2514 }
2511 2515
2512 2516
2513 void MarkCompactCollector::SweepSpace(PagedSpace* space, 2517 void MarkCompactCollector::SweepSpace(PagedSpace* space,
2514 SweeperType sweeper) { 2518 SweeperType sweeper) {
2515 space->set_was_swept_conservatively(sweeper == CONSERVATIVE); 2519 space->set_was_swept_conservatively(sweeper == CONSERVATIVE ||
2520 sweeper == LAZY_CONSERVATIVE);
2516 2521
2517 space->ClearStats(); 2522 space->ClearStats();
2518 2523
2519 PageIterator it(space); 2524 PageIterator it(space);
2520 2525
2521 // During sweeping of paged space we are trying to find longest sequences 2526 int freed_bytes = 0;
2522 // of pages without live objects and free them (instead of putting them on 2527 int newspace_size = space->heap()->new_space()->Size();
2523 // the free list).
2524
2525 // Page preceding current.
2526 Page* prev = Page::FromAddress(NULL);
2527 2528
2528 while (it.has_next()) { 2529 while (it.has_next()) {
2529 Page* p = it.next(); 2530 Page* p = it.next();
2530 space->IncreaseCapacity(p->ObjectAreaEnd() - p->ObjectAreaStart());
2531 2531
2532 if (sweeper == CONSERVATIVE) { 2532 switch (sweeper) {
2533 SweepConservatively(space, p); 2533 case CONSERVATIVE:
2534 } else { 2534 SweepConservatively(space, p);
2535 ASSERT(sweeper == PRECISE); 2535 break;
2536 SweepPrecisely(space, p); 2536 case LAZY_CONSERVATIVE:
2537 freed_bytes += SweepConservatively(space, p);
2538 if (freed_bytes >= newspace_size && p != space->LastPage()) {
2539 space->SetPagesToSweep(p->next_page(), space->LastPage());
2540 return;
Erik Corry 2011/05/09 21:20:11 I think we will want to tune this heuristic. If w
2541 }
2542 break;
2543 case PRECISE:
2544 SweepPrecisely(space, p);
2545 break;
2546 default:
2547 UNREACHABLE();
2537 } 2548 }
2538 prev = p;
2539 } 2549 }
2550
2540 // TODO(gc): set up allocation top and limit using the free list. 2551 // TODO(gc): set up allocation top and limit using the free list.
2541 } 2552 }
2542 2553
2543 2554
2544 void MarkCompactCollector::SweepSpaces() { 2555 void MarkCompactCollector::SweepSpaces() {
2545 GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP); 2556 GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP);
2546 #ifdef DEBUG 2557 #ifdef DEBUG
2547 state_ = SWEEP_SPACES; 2558 state_ = SWEEP_SPACES;
2548 #endif 2559 #endif
2549 2560
2550 ASSERT(!IsCompacting()); 2561 ASSERT(!IsCompacting());
2551 SweeperType how_to_sweep = CONSERVATIVE; 2562 SweeperType how_to_sweep =
2563 FLAG_lazy_sweeping ? LAZY_CONSERVATIVE : CONSERVATIVE;
2552 if (sweep_precisely_) how_to_sweep = PRECISE; 2564 if (sweep_precisely_) how_to_sweep = PRECISE;
2553 // Noncompacting collections simply sweep the spaces to clear the mark 2565 // Noncompacting collections simply sweep the spaces to clear the mark
2554 // bits and free the nonlive blocks (for old and map spaces). We sweep 2566 // bits and free the nonlive blocks (for old and map spaces). We sweep
2555 // the map space last because freeing non-live maps overwrites them and 2567 // the map space last because freeing non-live maps overwrites them and
2556 // the other spaces rely on possibly non-live maps to get the sizes for 2568 // the other spaces rely on possibly non-live maps to get the sizes for
2557 // non-live objects. 2569 // non-live objects.
2558 SweepSpace(HEAP->old_pointer_space(), how_to_sweep); 2570 SweepSpace(HEAP->old_pointer_space(), how_to_sweep);
2559 SweepSpace(HEAP->old_data_space(), how_to_sweep); 2571 SweepSpace(HEAP->old_data_space(), how_to_sweep);
2560 SweepSpace(HEAP->code_space(), PRECISE); 2572 SweepSpace(HEAP->code_space(), PRECISE);
2561 // TODO(gc): implement specialized sweeper for cell space. 2573 // TODO(gc): implement specialized sweeper for cell space.
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
2655 } 2667 }
2656 2668
2657 2669
2658 void MarkCompactCollector::Initialize() { 2670 void MarkCompactCollector::Initialize() {
2659 StaticPointersToNewGenUpdatingVisitor::Initialize(); 2671 StaticPointersToNewGenUpdatingVisitor::Initialize();
2660 StaticMarkingVisitor::Initialize(); 2672 StaticMarkingVisitor::Initialize();
2661 } 2673 }
2662 2674
2663 2675
2664 } } // namespace v8::internal 2676 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698