| OLD | NEW |
| 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 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 | 273 |
| 274 heap_->isolate()->pc_to_code_cache()->Flush(); | 274 heap_->isolate()->pc_to_code_cache()->Flush(); |
| 275 | 275 |
| 276 Finish(); | 276 Finish(); |
| 277 | 277 |
| 278 tracer_ = NULL; | 278 tracer_ = NULL; |
| 279 } | 279 } |
| 280 | 280 |
| 281 | 281 |
| 282 #ifdef DEBUG | 282 #ifdef DEBUG |
| 283 static void VerifyMarkbitsAreClean(PagedSpace* space) { | 283 void MarkCompactCollector::VerifyMarkbitsAreClean(PagedSpace* space) { |
| 284 PageIterator it(space); | 284 PageIterator it(space); |
| 285 | 285 |
| 286 while (it.has_next()) { | 286 while (it.has_next()) { |
| 287 Page* p = it.next(); | 287 Page* p = it.next(); |
| 288 ASSERT(p->markbits()->IsClean()); | 288 ASSERT(p->markbits()->IsClean()); |
| 289 } | 289 } |
| 290 } | 290 } |
| 291 | 291 |
| 292 static void VerifyMarkbitsAreClean(NewSpace* space) { | 292 void MarkCompactCollector::VerifyMarkbitsAreClean(NewSpace* space) { |
| 293 NewSpacePageIterator it(space->bottom(), space->top()); | 293 NewSpacePageIterator it(space->bottom(), space->top()); |
| 294 | 294 |
| 295 while (it.has_next()) { | 295 while (it.has_next()) { |
| 296 NewSpacePage* p = it.next(); | 296 NewSpacePage* p = it.next(); |
| 297 ASSERT(p->markbits()->IsClean()); | 297 ASSERT(p->markbits()->IsClean()); |
| 298 } | 298 } |
| 299 } | 299 } |
| 300 | 300 |
| 301 static void VerifyMarkbitsAreClean(Heap* heap) { | 301 void MarkCompactCollector::VerifyMarkbitsAreClean() { |
| 302 VerifyMarkbitsAreClean(heap->old_pointer_space()); | 302 VerifyMarkbitsAreClean(heap_->old_pointer_space()); |
| 303 VerifyMarkbitsAreClean(heap->old_data_space()); | 303 VerifyMarkbitsAreClean(heap_->old_data_space()); |
| 304 VerifyMarkbitsAreClean(heap->code_space()); | 304 VerifyMarkbitsAreClean(heap_->code_space()); |
| 305 VerifyMarkbitsAreClean(heap->cell_space()); | 305 VerifyMarkbitsAreClean(heap_->cell_space()); |
| 306 VerifyMarkbitsAreClean(heap->map_space()); | 306 VerifyMarkbitsAreClean(heap_->map_space()); |
| 307 VerifyMarkbitsAreClean(heap->new_space()); | 307 VerifyMarkbitsAreClean(heap_->new_space()); |
| 308 } | 308 } |
| 309 #endif | 309 #endif |
| 310 | 310 |
| 311 | 311 |
| 312 static void ClearMarkbits(PagedSpace* space) { | 312 static void ClearMarkbits(PagedSpace* space) { |
| 313 PageIterator it(space); | 313 PageIterator it(space); |
| 314 | 314 |
| 315 while (it.has_next()) { | 315 while (it.has_next()) { |
| 316 Bitmap::Clear(it.next()); | 316 Bitmap::Clear(it.next()); |
| 317 } | 317 } |
| 318 } | 318 } |
| 319 | 319 |
| 320 | 320 |
| 321 static void ClearMarkbits(NewSpace* space) { | 321 static void ClearMarkbits(NewSpace* space) { |
| 322 NewSpacePageIterator it(space->ToSpaceStart(), space->ToSpaceEnd()); | 322 NewSpacePageIterator it(space->ToSpaceStart(), space->ToSpaceEnd()); |
| 323 | 323 |
| 324 while (it.has_next()) { | 324 while (it.has_next()) { |
| 325 Bitmap::Clear(it.next()); | 325 Bitmap::Clear(it.next()); |
| 326 } | 326 } |
| 327 } | 327 } |
| 328 | 328 |
| 329 | 329 |
| 330 static void ClearMarkbits(Heap* heap) { | 330 static void ClearMarkbits(Heap* heap) { |
| 331 // TODO(gc): Clean the mark bits while sweeping. | |
| 332 ClearMarkbits(heap->code_space()); | 331 ClearMarkbits(heap->code_space()); |
| 333 ClearMarkbits(heap->map_space()); | 332 ClearMarkbits(heap->map_space()); |
| 334 ClearMarkbits(heap->old_pointer_space()); | 333 ClearMarkbits(heap->old_pointer_space()); |
| 335 ClearMarkbits(heap->old_data_space()); | 334 ClearMarkbits(heap->old_data_space()); |
| 336 ClearMarkbits(heap->cell_space()); | 335 ClearMarkbits(heap->cell_space()); |
| 337 ClearMarkbits(heap->new_space()); | 336 ClearMarkbits(heap->new_space()); |
| 338 } | 337 } |
| 339 | 338 |
| 340 | 339 |
| 341 bool Marking::TransferMark(Address old_start, Address new_start) { | 340 bool Marking::TransferMark(Address old_start, Address new_start) { |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 425 ASSERT(!FLAG_always_compact || !FLAG_never_compact); | 424 ASSERT(!FLAG_always_compact || !FLAG_never_compact); |
| 426 | 425 |
| 427 if (collect_maps_) CreateBackPointers(); | 426 if (collect_maps_) CreateBackPointers(); |
| 428 #ifdef ENABLE_GDB_JIT_INTERFACE | 427 #ifdef ENABLE_GDB_JIT_INTERFACE |
| 429 if (FLAG_gdbjit) { | 428 if (FLAG_gdbjit) { |
| 430 // If GDBJIT interface is active disable compaction. | 429 // If GDBJIT interface is active disable compaction. |
| 431 compacting_collection_ = false; | 430 compacting_collection_ = false; |
| 432 } | 431 } |
| 433 #endif | 432 #endif |
| 434 | 433 |
| 434 // Clear marking bits for precise sweeping to collect all garbage. |
| 435 if (heap()->incremental_marking()->IsMarking() && PreciseSweepingRequired()) { | 435 if (heap()->incremental_marking()->IsMarking() && PreciseSweepingRequired()) { |
| 436 heap()->incremental_marking()->Abort(); | 436 heap()->incremental_marking()->Abort(); |
| 437 ClearMarkbits(heap_); |
| 437 } | 438 } |
| 438 | 439 |
| 439 if (!FLAG_never_compact) StartCompaction(); | 440 if (!FLAG_never_compact) StartCompaction(); |
| 440 | 441 |
| 441 PagedSpaces spaces; | 442 PagedSpaces spaces; |
| 442 for (PagedSpace* space = spaces.next(); | 443 for (PagedSpace* space = spaces.next(); |
| 443 space != NULL; | 444 space != NULL; |
| 444 space = spaces.next()) { | 445 space = spaces.next()) { |
| 445 space->PrepareForMarkCompact(); | 446 space->PrepareForMarkCompact(); |
| 446 } | 447 } |
| 447 | 448 |
| 449 #ifdef DEBUG |
| 448 if (!heap()->incremental_marking()->IsMarking()) { | 450 if (!heap()->incremental_marking()->IsMarking()) { |
| 449 ClearMarkbits(heap_); | 451 VerifyMarkbitsAreClean(); |
| 450 #ifdef DEBUG | 452 } |
| 451 VerifyMarkbitsAreClean(heap_); | |
| 452 #endif | 453 #endif |
| 453 } | |
| 454 | 454 |
| 455 #ifdef DEBUG | 455 #ifdef DEBUG |
| 456 live_bytes_ = 0; | 456 live_bytes_ = 0; |
| 457 live_young_objects_size_ = 0; | 457 live_young_objects_size_ = 0; |
| 458 live_old_pointer_objects_size_ = 0; | 458 live_old_pointer_objects_size_ = 0; |
| 459 live_old_data_objects_size_ = 0; | 459 live_old_data_objects_size_ = 0; |
| 460 live_code_objects_size_ = 0; | 460 live_code_objects_size_ = 0; |
| 461 live_map_objects_size_ = 0; | 461 live_map_objects_size_ = 0; |
| 462 live_cell_objects_size_ = 0; | 462 live_cell_objects_size_ = 0; |
| 463 live_lo_objects_size_ = 0; | 463 live_lo_objects_size_ = 0; |
| (...skipping 2153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2617 | 2617 |
| 2618 | 2618 |
| 2619 // Sweep a space precisely. After this has been done the space can | 2619 // Sweep a space precisely. After this has been done the space can |
| 2620 // be iterated precisely, hitting only the live objects. Code space | 2620 // be iterated precisely, hitting only the live objects. Code space |
| 2621 // is always swept precisely because we want to be able to iterate | 2621 // is always swept precisely because we want to be able to iterate |
| 2622 // over it. Map space is swept precisely, because it is not compacted. | 2622 // over it. Map space is swept precisely, because it is not compacted. |
| 2623 // Slots in live objects pointing into evacuation candidates are updated | 2623 // Slots in live objects pointing into evacuation candidates are updated |
| 2624 // if requested. | 2624 // if requested. |
| 2625 static void SweepPrecisely(PagedSpace* space, Page* p, SweepingMode mode) { | 2625 static void SweepPrecisely(PagedSpace* space, Page* p, SweepingMode mode) { |
| 2626 ASSERT(!p->IsEvacuationCandidate() && !p->WasSwept()); | 2626 ASSERT(!p->IsEvacuationCandidate() && !p->WasSwept()); |
| 2627 ASSERT(!p->IsFlagSet(MemoryChunk::WAS_SWEPT_CONSERVATIVELY)); |
| 2627 MarkBit::CellType* cells = p->markbits()->cells(); | 2628 MarkBit::CellType* cells = p->markbits()->cells(); |
| 2628 | |
| 2629 p->ClearFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY); | |
| 2630 p->MarkSwept(); | 2629 p->MarkSwept(); |
| 2631 | 2630 |
| 2632 int last_cell_index = | 2631 int last_cell_index = |
| 2633 Bitmap::IndexToCell( | 2632 Bitmap::IndexToCell( |
| 2634 Bitmap::CellAlignIndex( | 2633 Bitmap::CellAlignIndex( |
| 2635 p->AddressToMarkbitIndex(p->ObjectAreaEnd()))); | 2634 p->AddressToMarkbitIndex(p->ObjectAreaEnd()))); |
| 2636 | 2635 |
| 2637 int cell_index = Page::kFirstUsedCell; | 2636 int cell_index = Page::kFirstUsedCell; |
| 2638 Address free_start = p->ObjectAreaStart(); | 2637 Address free_start = p->ObjectAreaStart(); |
| 2639 ASSERT(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); | 2638 ASSERT(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2656 } | 2655 } |
| 2657 HeapObject* live_object = HeapObject::FromAddress(free_end); | 2656 HeapObject* live_object = HeapObject::FromAddress(free_end); |
| 2658 ASSERT(Marking::IsBlack(Marking::MarkBitFrom(live_object))); | 2657 ASSERT(Marking::IsBlack(Marking::MarkBitFrom(live_object))); |
| 2659 int size = live_object->Size(); | 2658 int size = live_object->Size(); |
| 2660 if (mode == SWEEP_AND_UPDATE_SLOTS) { | 2659 if (mode == SWEEP_AND_UPDATE_SLOTS) { |
| 2661 UpdateSlotsInRange(HeapObject::RawField(live_object, kPointerSize), | 2660 UpdateSlotsInRange(HeapObject::RawField(live_object, kPointerSize), |
| 2662 HeapObject::RawField(live_object, size)); | 2661 HeapObject::RawField(live_object, size)); |
| 2663 } | 2662 } |
| 2664 free_start = free_end + size; | 2663 free_start = free_end + size; |
| 2665 } | 2664 } |
| 2665 // Clear marking bits for current cell. |
| 2666 cells[cell_index] = 0; |
| 2666 } | 2667 } |
| 2667 if (free_start != p->ObjectAreaEnd()) { | 2668 if (free_start != p->ObjectAreaEnd()) { |
| 2668 space->Free(free_start, static_cast<int>(p->ObjectAreaEnd() - free_start)); | 2669 space->Free(free_start, static_cast<int>(p->ObjectAreaEnd() - free_start)); |
| 2669 } | 2670 } |
| 2670 } | 2671 } |
| 2671 | 2672 |
| 2672 | 2673 |
| 2673 void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { | 2674 void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { |
| 2674 EvacuateNewSpace(); | 2675 EvacuateNewSpace(); |
| 2675 EvacuatePages(); | 2676 EvacuatePages(); |
| (...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3096 | 3097 |
| 3097 // Sweeps a space conservatively. After this has been done the larger free | 3098 // Sweeps a space conservatively. After this has been done the larger free |
| 3098 // spaces have been put on the free list and the smaller ones have been | 3099 // spaces have been put on the free list and the smaller ones have been |
| 3099 // ignored and left untouched. A free space is always either ignored or put | 3100 // ignored and left untouched. A free space is always either ignored or put |
| 3100 // on the free list, never split up into two parts. This is important | 3101 // on the free list, never split up into two parts. This is important |
| 3101 // because it means that any FreeSpace maps left actually describe a region of | 3102 // because it means that any FreeSpace maps left actually describe a region of |
| 3102 // memory that can be ignored when scanning. Dead objects other than free | 3103 // memory that can be ignored when scanning. Dead objects other than free |
| 3103 // spaces will not contain the free space map. | 3104 // spaces will not contain the free space map. |
| 3104 intptr_t MarkCompactCollector::SweepConservatively(PagedSpace* space, Page* p) { | 3105 intptr_t MarkCompactCollector::SweepConservatively(PagedSpace* space, Page* p) { |
| 3105 ASSERT(!p->IsEvacuationCandidate() && !p->WasSwept()); | 3106 ASSERT(!p->IsEvacuationCandidate() && !p->WasSwept()); |
| 3106 | |
| 3107 intptr_t freed_bytes = 0; | |
| 3108 | |
| 3109 MarkBit::CellType* cells = p->markbits()->cells(); | 3107 MarkBit::CellType* cells = p->markbits()->cells(); |
| 3110 | |
| 3111 p->SetFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY); | 3108 p->SetFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY); |
| 3112 | 3109 |
| 3113 // This is the start of the 32 word block that we are currently looking at. | |
| 3114 Address block_address = p->ObjectAreaStart(); | |
| 3115 | |
| 3116 int last_cell_index = | 3110 int last_cell_index = |
| 3117 Bitmap::IndexToCell( | 3111 Bitmap::IndexToCell( |
| 3118 Bitmap::CellAlignIndex( | 3112 Bitmap::CellAlignIndex( |
| 3119 p->AddressToMarkbitIndex(p->ObjectAreaEnd()))); | 3113 p->AddressToMarkbitIndex(p->ObjectAreaEnd()))); |
| 3120 | 3114 |
| 3121 int cell_index = Page::kFirstUsedCell; | 3115 int cell_index = Page::kFirstUsedCell; |
| 3116 intptr_t freed_bytes = 0; |
| 3117 |
| 3118 // This is the start of the 32 word block that we are currently looking at. |
| 3119 Address block_address = p->ObjectAreaStart(); |
| 3122 | 3120 |
| 3123 // Skip over all the dead objects at the start of the page and mark them free. | 3121 // Skip over all the dead objects at the start of the page and mark them free. |
| 3124 for (cell_index = Page::kFirstUsedCell; | 3122 for (cell_index = Page::kFirstUsedCell; |
| 3125 cell_index < last_cell_index; | 3123 cell_index < last_cell_index; |
| 3126 cell_index++, block_address += 32 * kPointerSize) { | 3124 cell_index++, block_address += 32 * kPointerSize) { |
| 3127 if (cells[cell_index] != 0) break; | 3125 if (cells[cell_index] != 0) break; |
| 3128 } | 3126 } |
| 3129 size_t size = block_address - p->ObjectAreaStart(); | 3127 size_t size = block_address - p->ObjectAreaStart(); |
| 3130 if (cell_index == last_cell_index) { | 3128 if (cell_index == last_cell_index) { |
| 3131 freed_bytes += static_cast<int>(space->Free(p->ObjectAreaStart(), | 3129 freed_bytes += static_cast<int>(space->Free(p->ObjectAreaStart(), |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3167 // so now we need to find the start of the first live object at the | 3165 // so now we need to find the start of the first live object at the |
| 3168 // end of the free space. | 3166 // end of the free space. |
| 3169 free_end = StartOfLiveObject(block_address, cell); | 3167 free_end = StartOfLiveObject(block_address, cell); |
| 3170 freed_bytes += space->Free(free_start, | 3168 freed_bytes += space->Free(free_start, |
| 3171 static_cast<int>(free_end - free_start)); | 3169 static_cast<int>(free_end - free_start)); |
| 3172 } | 3170 } |
| 3173 } | 3171 } |
| 3174 // Update our undigested record of where the current free area started. | 3172 // Update our undigested record of where the current free area started. |
| 3175 free_start = block_address; | 3173 free_start = block_address; |
| 3176 free_start_cell = cell; | 3174 free_start_cell = cell; |
| 3175 // Clear marking bits for current cell. |
| 3176 cells[cell_index] = 0; |
| 3177 } | 3177 } |
| 3178 } | 3178 } |
| 3179 | 3179 |
| 3180 // Handle the free space at the end of the page. | 3180 // Handle the free space at the end of the page. |
| 3181 if (block_address - free_start > 32 * kPointerSize) { | 3181 if (block_address - free_start > 32 * kPointerSize) { |
| 3182 free_start = DigestFreeStart(free_start, free_start_cell); | 3182 free_start = DigestFreeStart(free_start, free_start_cell); |
| 3183 freed_bytes += space->Free(free_start, | 3183 freed_bytes += space->Free(free_start, |
| 3184 static_cast<int>(block_address - free_start)); | 3184 static_cast<int>(block_address - free_start)); |
| 3185 } | 3185 } |
| 3186 | 3186 |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3394 while (buffer != NULL) { | 3394 while (buffer != NULL) { |
| 3395 SlotsBuffer* next_buffer = buffer->next(); | 3395 SlotsBuffer* next_buffer = buffer->next(); |
| 3396 DeallocateBuffer(buffer); | 3396 DeallocateBuffer(buffer); |
| 3397 buffer = next_buffer; | 3397 buffer = next_buffer; |
| 3398 } | 3398 } |
| 3399 *buffer_address = NULL; | 3399 *buffer_address = NULL; |
| 3400 } | 3400 } |
| 3401 | 3401 |
| 3402 | 3402 |
| 3403 } } // namespace v8::internal | 3403 } } // namespace v8::internal |
| OLD | NEW |