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 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
411 | 411 |
412 return NULL; | 412 return NULL; |
413 } | 413 } |
414 | 414 |
415 | 415 |
416 void MarkCompactCollector::CollectEvacuationCandidates(PagedSpace* space) { | 416 void MarkCompactCollector::CollectEvacuationCandidates(PagedSpace* space) { |
417 ASSERT(space->identity() == OLD_POINTER_SPACE || | 417 ASSERT(space->identity() == OLD_POINTER_SPACE || |
418 space->identity() == OLD_DATA_SPACE || | 418 space->identity() == OLD_DATA_SPACE || |
419 space->identity() == CODE_SPACE); | 419 space->identity() == CODE_SPACE); |
420 | 420 |
421 int number_of_pages = 0; | |
Michael Starzinger
2011/11/24 14:43:49
Can we instead use PagedSpace::CountTotalPages() a
Erik Corry
2011/11/24 17:02:30
Done.
| |
422 { | |
423 PageIterator counter(space); | |
424 while (counter.has_next()) { | |
425 number_of_pages++; | |
426 counter.next(); | |
427 } | |
428 } | |
429 | |
421 PageIterator it(space); | 430 PageIterator it(space); |
431 | |
432 const int kMaxMaxEvacuationCandidates = 1000; | |
Michael Starzinger
2011/11/24 14:43:49
Why two 'Max' in that constant?
Erik Corry
2011/11/24 17:02:30
You can't make the max any higher than this. Fixe
| |
433 int max_evacuation_candidates = | |
434 static_cast<int>(sqrt(number_of_pages / 2) + 1); | |
435 | |
436 if (FLAG_stress_compaction || FLAG_always_compact) { | |
437 max_evacuation_candidates = kMaxMaxEvacuationCandidates; | |
438 } | |
439 | |
440 class Candidate { | |
441 public: | |
442 Candidate() : fragmentation_(0), page_(NULL) { } | |
443 Candidate(int f, Page* p) : fragmentation_(f), page_(p) { } | |
444 | |
445 int fragmentation() { return fragmentation_; } | |
446 Page* page() { return page_; } | |
447 | |
448 private: | |
449 int fragmentation_; | |
450 Page* page_; | |
451 }; | |
452 | |
453 Candidate candidates[kMaxMaxEvacuationCandidates]; | |
454 | |
422 int count = 0; | 455 int count = 0; |
423 if (it.has_next()) it.next(); // Never compact the first page. | 456 if (it.has_next()) it.next(); // Never compact the first page. |
457 int fragmentation = 0; | |
458 Candidate* least = NULL; | |
424 while (it.has_next()) { | 459 while (it.has_next()) { |
425 Page* p = it.next(); | 460 Page* p = it.next(); |
426 bool evacuate = false; | 461 p->ClearEvacuationCandidate(); |
427 if (FLAG_stress_compaction) { | 462 if (FLAG_stress_compaction) { |
428 int counter = space->heap()->ms_count(); | 463 int counter = space->heap()->ms_count(); |
429 uintptr_t page_number = reinterpret_cast<uintptr_t>(p) >> kPageSizeBits; | 464 uintptr_t page_number = reinterpret_cast<uintptr_t>(p) >> kPageSizeBits; |
430 if ((counter & 1) == (page_number & 1)) evacuate = true; | 465 if ((counter & 1) == (page_number & 1)) fragmentation = 1; |
431 } else { | 466 } else { |
432 if (space->IsFragmented(p)) evacuate = true; | 467 fragmentation = space->Fragmentation(p); |
433 } | 468 } |
434 if (evacuate) { | 469 if (fragmentation != 0) { |
435 AddEvacuationCandidate(p); | 470 if (count < max_evacuation_candidates) { |
436 count++; | 471 candidates[count++] = Candidate(fragmentation, p); |
437 } else { | 472 } else { |
438 p->ClearEvacuationCandidate(); | 473 if (least == NULL) { |
474 for (int i = 0; i < max_evacuation_candidates; i++) { | |
475 if (least == NULL || | |
476 candidates[i].fragmentation() < least->fragmentation()) { | |
477 least = candidates + i; | |
478 } | |
479 } | |
480 } | |
481 if (least->fragmentation() < fragmentation) { | |
482 *least = Candidate(fragmentation, p); | |
483 least = NULL; | |
484 } | |
485 } | |
439 } | 486 } |
440 } | 487 } |
488 for (int i = 0; i < count; i++) { | |
489 AddEvacuationCandidate(candidates[i].page()); | |
490 } | |
441 | 491 |
442 if (count > 0 && FLAG_trace_fragmentation) { | 492 if (count > 0 && FLAG_trace_fragmentation) { |
443 PrintF("Collected %d evacuation candidates for space %s\n", | 493 PrintF("Collected %d evacuation candidates for space %s\n", |
444 count, | 494 count, |
445 AllocationSpaceName(space->identity())); | 495 AllocationSpaceName(space->identity())); |
446 } | 496 } |
447 } | 497 } |
448 | 498 |
449 | 499 |
450 void MarkCompactCollector::AbortCompaction() { | 500 void MarkCompactCollector::AbortCompaction() { |
(...skipping 2496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2947 if (code != NULL) { | 2997 if (code != NULL) { |
2948 code->Iterate(visitor); | 2998 code->Iterate(visitor); |
2949 SetMarkBitsUnderInvalidatedCode(code, false); | 2999 SetMarkBitsUnderInvalidatedCode(code, false); |
2950 } | 3000 } |
2951 } | 3001 } |
2952 invalidated_code_.Rewind(0); | 3002 invalidated_code_.Rewind(0); |
2953 } | 3003 } |
2954 | 3004 |
2955 | 3005 |
2956 void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { | 3006 void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { |
2957 bool code_slots_filtering_required = MarkInvalidatedCode(); | 3007 bool code_slots_filtering_required; |
3008 { GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP_NEWSPACE); | |
3009 code_slots_filtering_required = MarkInvalidatedCode(); | |
2958 | 3010 |
2959 EvacuateNewSpace(); | 3011 EvacuateNewSpace(); |
2960 EvacuatePages(); | 3012 } |
3013 | |
3014 | |
3015 { GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_EVACUATE_PAGES); | |
3016 EvacuatePages(); | |
3017 } | |
2961 | 3018 |
2962 // Second pass: find pointers to new space and update them. | 3019 // Second pass: find pointers to new space and update them. |
2963 PointersUpdatingVisitor updating_visitor(heap()); | 3020 PointersUpdatingVisitor updating_visitor(heap()); |
2964 | 3021 |
2965 // Update pointers in to space. | 3022 { GCTracer::Scope gc_scope(tracer_, |
2966 SemiSpaceIterator to_it(heap()->new_space()->bottom(), | 3023 GCTracer::Scope::MC_UPDATE_NEW_TO_NEW_POINTERS); |
2967 heap()->new_space()->top()); | 3024 // Update pointers in to space. |
2968 for (HeapObject* object = to_it.Next(); | 3025 SemiSpaceIterator to_it(heap()->new_space()->bottom(), |
2969 object != NULL; | 3026 heap()->new_space()->top()); |
2970 object = to_it.Next()) { | 3027 for (HeapObject* object = to_it.Next(); |
2971 Map* map = object->map(); | 3028 object != NULL; |
2972 object->IterateBody(map->instance_type(), | 3029 object = to_it.Next()) { |
2973 object->SizeFromMap(map), | 3030 Map* map = object->map(); |
2974 &updating_visitor); | 3031 object->IterateBody(map->instance_type(), |
3032 object->SizeFromMap(map), | |
3033 &updating_visitor); | |
3034 } | |
2975 } | 3035 } |
2976 | 3036 |
2977 // Update roots. | 3037 { GCTracer::Scope gc_scope(tracer_, |
2978 heap_->IterateRoots(&updating_visitor, VISIT_ALL_IN_SWEEP_NEWSPACE); | 3038 GCTracer::Scope::MC_UPDATE_ROOT_TO_NEW_POINTERS); |
2979 LiveObjectList::IterateElements(&updating_visitor); | 3039 // Update roots. |
3040 heap_->IterateRoots(&updating_visitor, VISIT_ALL_IN_SWEEP_NEWSPACE); | |
3041 LiveObjectList::IterateElements(&updating_visitor); | |
3042 } | |
2980 | 3043 |
2981 { | 3044 { GCTracer::Scope gc_scope(tracer_, |
3045 GCTracer::Scope::MC_UPDATE_OLD_TO_NEW_POINTERS); | |
2982 StoreBufferRebuildScope scope(heap_, | 3046 StoreBufferRebuildScope scope(heap_, |
2983 heap_->store_buffer(), | 3047 heap_->store_buffer(), |
2984 &Heap::ScavengeStoreBufferCallback); | 3048 &Heap::ScavengeStoreBufferCallback); |
2985 heap_->store_buffer()->IteratePointersToNewSpace(&UpdatePointer); | 3049 heap_->store_buffer()->IteratePointersToNewSpace(&UpdatePointer); |
2986 } | 3050 } |
2987 | 3051 |
2988 SlotsBuffer::UpdateSlotsRecordedIn(heap_, | 3052 { GCTracer::Scope gc_scope(tracer_, |
2989 migration_slots_buffer_, | 3053 GCTracer::Scope::MC_UPDATE_POINTERS_TO_EVACUATED); |
2990 code_slots_filtering_required); | 3054 SlotsBuffer::UpdateSlotsRecordedIn(heap_, |
2991 if (FLAG_trace_fragmentation) { | 3055 migration_slots_buffer_, |
2992 PrintF(" migration slots buffer: %d\n", | 3056 code_slots_filtering_required); |
2993 SlotsBuffer::SizeOfChain(migration_slots_buffer_)); | 3057 if (FLAG_trace_fragmentation) { |
2994 } | 3058 PrintF(" migration slots buffer: %d\n", |
3059 SlotsBuffer::SizeOfChain(migration_slots_buffer_)); | |
3060 } | |
2995 | 3061 |
2996 if (compacting_ && was_marked_incrementally_) { | 3062 if (compacting_ && was_marked_incrementally_) { |
2997 // It's difficult to filter out slots recorded for large objects. | 3063 // It's difficult to filter out slots recorded for large objects. |
2998 LargeObjectIterator it(heap_->lo_space()); | 3064 LargeObjectIterator it(heap_->lo_space()); |
2999 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { | 3065 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { |
3000 // LargeObjectSpace is not swept yet thus we have to skip | 3066 // LargeObjectSpace is not swept yet thus we have to skip |
3001 // dead objects explicitly. | 3067 // dead objects explicitly. |
3002 if (!IsMarked(obj)) continue; | 3068 if (!IsMarked(obj)) continue; |
3003 | 3069 |
3004 Page* p = Page::FromAddress(obj->address()); | 3070 Page* p = Page::FromAddress(obj->address()); |
3005 if (p->IsFlagSet(Page::RESCAN_ON_EVACUATION)) { | 3071 if (p->IsFlagSet(Page::RESCAN_ON_EVACUATION)) { |
3006 obj->Iterate(&updating_visitor); | 3072 obj->Iterate(&updating_visitor); |
3007 p->ClearFlag(Page::RESCAN_ON_EVACUATION); | 3073 p->ClearFlag(Page::RESCAN_ON_EVACUATION); |
3074 } | |
3008 } | 3075 } |
3009 } | 3076 } |
3010 } | 3077 } |
3011 | 3078 |
3012 int npages = evacuation_candidates_.length(); | 3079 int npages = evacuation_candidates_.length(); |
3013 for (int i = 0; i < npages; i++) { | 3080 { GCTracer::Scope gc_scope( |
3014 Page* p = evacuation_candidates_[i]; | 3081 tracer_, GCTracer::Scope::MC_UPDATE_POINTERS_BETWEEN_EVACUATED); |
3015 ASSERT(p->IsEvacuationCandidate() || | 3082 for (int i = 0; i < npages; i++) { |
3016 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); | 3083 Page* p = evacuation_candidates_[i]; |
3084 ASSERT(p->IsEvacuationCandidate() || | |
3085 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); | |
3017 | 3086 |
3018 if (p->IsEvacuationCandidate()) { | 3087 if (p->IsEvacuationCandidate()) { |
3019 SlotsBuffer::UpdateSlotsRecordedIn(heap_, | 3088 SlotsBuffer::UpdateSlotsRecordedIn(heap_, |
3020 p->slots_buffer(), | 3089 p->slots_buffer(), |
3021 code_slots_filtering_required); | 3090 code_slots_filtering_required); |
3022 if (FLAG_trace_fragmentation) { | 3091 if (FLAG_trace_fragmentation) { |
3023 PrintF(" page %p slots buffer: %d\n", | 3092 PrintF(" page %p slots buffer: %d\n", |
3024 reinterpret_cast<void*>(p), | 3093 reinterpret_cast<void*>(p), |
3025 SlotsBuffer::SizeOfChain(p->slots_buffer())); | 3094 SlotsBuffer::SizeOfChain(p->slots_buffer())); |
3026 } | 3095 } |
3027 | 3096 |
3028 // Important: skip list should be cleared only after roots were updated | 3097 // Important: skip list should be cleared only after roots were updated |
3029 // because root iteration traverses the stack and might have to find code | 3098 // because root iteration traverses the stack and might have to find |
3030 // objects from non-updated pc pointing into evacuation candidate. | 3099 // code objects from non-updated pc pointing into evacuation candidate. |
3031 SkipList* list = p->skip_list(); | 3100 SkipList* list = p->skip_list(); |
3032 if (list != NULL) list->Clear(); | 3101 if (list != NULL) list->Clear(); |
3033 } else { | 3102 } else { |
3034 if (FLAG_gc_verbose) { | 3103 if (FLAG_gc_verbose) { |
3035 PrintF("Sweeping 0x%" V8PRIxPTR " during evacuation.\n", | 3104 PrintF("Sweeping 0x%" V8PRIxPTR " during evacuation.\n", |
3036 reinterpret_cast<intptr_t>(p)); | 3105 reinterpret_cast<intptr_t>(p)); |
3037 } | 3106 } |
3038 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); | 3107 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); |
3039 p->ClearFlag(MemoryChunk::RESCAN_ON_EVACUATION); | 3108 p->ClearFlag(MemoryChunk::RESCAN_ON_EVACUATION); |
3040 | 3109 |
3041 switch (space->identity()) { | 3110 switch (space->identity()) { |
3042 case OLD_DATA_SPACE: | 3111 case OLD_DATA_SPACE: |
3043 SweepConservatively(space, p); | 3112 SweepConservatively(space, p); |
3044 break; | 3113 break; |
3045 case OLD_POINTER_SPACE: | 3114 case OLD_POINTER_SPACE: |
3046 SweepPrecisely<SWEEP_AND_VISIT_LIVE_OBJECTS, IGNORE_SKIP_LIST>( | 3115 SweepPrecisely<SWEEP_AND_VISIT_LIVE_OBJECTS, IGNORE_SKIP_LIST>( |
3047 space, p, &updating_visitor); | 3116 space, p, &updating_visitor); |
3048 break; | 3117 break; |
3049 case CODE_SPACE: | 3118 case CODE_SPACE: |
3050 SweepPrecisely<SWEEP_AND_VISIT_LIVE_OBJECTS, REBUILD_SKIP_LIST>( | 3119 SweepPrecisely<SWEEP_AND_VISIT_LIVE_OBJECTS, REBUILD_SKIP_LIST>( |
3051 space, p, &updating_visitor); | 3120 space, p, &updating_visitor); |
3052 break; | 3121 break; |
3053 default: | 3122 default: |
3054 UNREACHABLE(); | 3123 UNREACHABLE(); |
3055 break; | 3124 break; |
3125 } | |
3056 } | 3126 } |
3057 } | 3127 } |
3058 } | 3128 } |
3059 | 3129 |
3130 GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_UPDATE_MISC_POINTERS); | |
3131 | |
3060 // Update pointers from cells. | 3132 // Update pointers from cells. |
3061 HeapObjectIterator cell_iterator(heap_->cell_space()); | 3133 HeapObjectIterator cell_iterator(heap_->cell_space()); |
3062 for (HeapObject* cell = cell_iterator.Next(); | 3134 for (HeapObject* cell = cell_iterator.Next(); |
3063 cell != NULL; | 3135 cell != NULL; |
3064 cell = cell_iterator.Next()) { | 3136 cell = cell_iterator.Next()) { |
3065 if (cell->IsJSGlobalPropertyCell()) { | 3137 if (cell->IsJSGlobalPropertyCell()) { |
3066 Address value_address = | 3138 Address value_address = |
3067 reinterpret_cast<Address>(cell) + | 3139 reinterpret_cast<Address>(cell) + |
3068 (JSGlobalPropertyCell::kValueOffset - kHeapObjectTag); | 3140 (JSGlobalPropertyCell::kValueOffset - kHeapObjectTag); |
3069 updating_visitor.VisitPointer(reinterpret_cast<Object**>(value_address)); | 3141 updating_visitor.VisitPointer(reinterpret_cast<Object**>(value_address)); |
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3476 free_start = DigestFreeStart(free_start, free_start_cell); | 3548 free_start = DigestFreeStart(free_start, free_start_cell); |
3477 freed_bytes += space->Free(free_start, | 3549 freed_bytes += space->Free(free_start, |
3478 static_cast<int>(block_address - free_start)); | 3550 static_cast<int>(block_address - free_start)); |
3479 } | 3551 } |
3480 | 3552 |
3481 p->ResetLiveBytes(); | 3553 p->ResetLiveBytes(); |
3482 return freed_bytes; | 3554 return freed_bytes; |
3483 } | 3555 } |
3484 | 3556 |
3485 | 3557 |
3486 void MarkCompactCollector::SweepSpace(PagedSpace* space, | 3558 void MarkCompactCollector::SweepSpace(PagedSpace* space, SweeperType sweeper) { |
3487 SweeperType sweeper) { | |
3488 space->set_was_swept_conservatively(sweeper == CONSERVATIVE || | 3559 space->set_was_swept_conservatively(sweeper == CONSERVATIVE || |
3489 sweeper == LAZY_CONSERVATIVE); | 3560 sweeper == LAZY_CONSERVATIVE); |
3490 | 3561 |
3491 space->ClearStats(); | 3562 space->ClearStats(); |
3492 | 3563 |
3493 PageIterator it(space); | 3564 PageIterator it(space); |
3494 | 3565 |
3495 intptr_t freed_bytes = 0; | 3566 intptr_t freed_bytes = 0; |
3567 int pages_swept = 0; | |
3496 intptr_t newspace_size = space->heap()->new_space()->Size(); | 3568 intptr_t newspace_size = space->heap()->new_space()->Size(); |
3497 bool lazy_sweeping_active = false; | 3569 bool lazy_sweeping_active = false; |
3498 bool unused_page_present = false; | 3570 bool unused_page_present = false; |
3499 | 3571 |
3572 intptr_t old_space_size = heap()->PromotedSpaceSize(); | |
3573 intptr_t space_left = | |
3574 Min(heap()->OldGenPromotionLimit(old_space_size), | |
3575 heap()->OldGenAllocationLimit(old_space_size)) - old_space_size; | |
3576 | |
3500 while (it.has_next()) { | 3577 while (it.has_next()) { |
3501 Page* p = it.next(); | 3578 Page* p = it.next(); |
3502 | 3579 |
3503 // Clear sweeping flags indicating that marking bits are still intact. | 3580 // Clear sweeping flags indicating that marking bits are still intact. |
3504 p->ClearSweptPrecisely(); | 3581 p->ClearSweptPrecisely(); |
3505 p->ClearSweptConservatively(); | 3582 p->ClearSweptConservatively(); |
3506 | 3583 |
3507 if (p->IsEvacuationCandidate()) { | 3584 if (p->IsEvacuationCandidate()) { |
3508 ASSERT(evacuation_candidates_.length() > 0); | 3585 ASSERT(evacuation_candidates_.length() > 0); |
3509 continue; | 3586 continue; |
(...skipping 18 matching lines...) Expand all Loading... | |
3528 if (FLAG_gc_verbose) { | 3605 if (FLAG_gc_verbose) { |
3529 PrintF("Sweeping 0x%" V8PRIxPTR " released page.\n", | 3606 PrintF("Sweeping 0x%" V8PRIxPTR " released page.\n", |
3530 reinterpret_cast<intptr_t>(p)); | 3607 reinterpret_cast<intptr_t>(p)); |
3531 } | 3608 } |
3532 space->ReleasePage(p); | 3609 space->ReleasePage(p); |
3533 continue; | 3610 continue; |
3534 } | 3611 } |
3535 unused_page_present = true; | 3612 unused_page_present = true; |
3536 } | 3613 } |
3537 | 3614 |
3538 if (FLAG_gc_verbose) { | |
3539 PrintF("Sweeping 0x%" V8PRIxPTR " with sweeper %d.\n", | |
3540 reinterpret_cast<intptr_t>(p), | |
3541 sweeper); | |
3542 } | |
3543 | |
3544 switch (sweeper) { | 3615 switch (sweeper) { |
3545 case CONSERVATIVE: { | 3616 case CONSERVATIVE: { |
3617 if (FLAG_gc_verbose) { | |
3618 PrintF("Sweeping 0x%" V8PRIxPTR " conservatively.\n", | |
3619 reinterpret_cast<intptr_t>(p)); | |
3620 } | |
3546 SweepConservatively(space, p); | 3621 SweepConservatively(space, p); |
3622 pages_swept++; | |
3547 break; | 3623 break; |
3548 } | 3624 } |
3549 case LAZY_CONSERVATIVE: { | 3625 case LAZY_CONSERVATIVE: { |
3626 if (FLAG_gc_verbose) { | |
3627 PrintF("Sweeping 0x%" V8PRIxPTR " conservatively as needed.\n", | |
3628 reinterpret_cast<intptr_t>(p)); | |
3629 } | |
3550 freed_bytes += SweepConservatively(space, p); | 3630 freed_bytes += SweepConservatively(space, p); |
3551 if (freed_bytes >= newspace_size && p != space->LastPage()) { | 3631 pages_swept++; |
3632 if (space_left + freed_bytes > newspace_size) { | |
3552 space->SetPagesToSweep(p->next_page()); | 3633 space->SetPagesToSweep(p->next_page()); |
3553 lazy_sweeping_active = true; | 3634 lazy_sweeping_active = true; |
3635 } else { | |
3636 if (FLAG_gc_verbose) { | |
3637 PrintF("Only %" V8PRIdPTR " bytes freed. Still sweeping.\n", | |
3638 freed_bytes); | |
3639 } | |
3554 } | 3640 } |
3555 break; | 3641 break; |
3556 } | 3642 } |
3557 case PRECISE: { | 3643 case PRECISE: { |
3644 if (FLAG_gc_verbose) { | |
3645 PrintF("Sweeping 0x%" V8PRIxPTR " precisely.\n", | |
3646 reinterpret_cast<intptr_t>(p)); | |
3647 } | |
3558 if (space->identity() == CODE_SPACE) { | 3648 if (space->identity() == CODE_SPACE) { |
3559 SweepPrecisely<SWEEP_ONLY, REBUILD_SKIP_LIST>(space, p, NULL); | 3649 SweepPrecisely<SWEEP_ONLY, REBUILD_SKIP_LIST>(space, p, NULL); |
3560 } else { | 3650 } else { |
3561 SweepPrecisely<SWEEP_ONLY, IGNORE_SKIP_LIST>(space, p, NULL); | 3651 SweepPrecisely<SWEEP_ONLY, IGNORE_SKIP_LIST>(space, p, NULL); |
3562 } | 3652 } |
3653 pages_swept++; | |
3563 break; | 3654 break; |
3564 } | 3655 } |
3565 default: { | 3656 default: { |
3566 UNREACHABLE(); | 3657 UNREACHABLE(); |
3567 } | 3658 } |
3568 } | 3659 } |
3569 } | 3660 } |
3570 | 3661 |
3662 if (FLAG_gc_verbose) { | |
3663 PrintF("SweepSpace: %s (%d pages swept)\n", | |
3664 AllocationSpaceName(space->identity()), | |
3665 pages_swept); | |
3666 } | |
3667 | |
3571 // Give pages that are queued to be freed back to the OS. | 3668 // Give pages that are queued to be freed back to the OS. |
3572 heap()->FreeQueuedChunks(); | 3669 heap()->FreeQueuedChunks(); |
3573 } | 3670 } |
3574 | 3671 |
3575 | 3672 |
3576 void MarkCompactCollector::SweepSpaces() { | 3673 void MarkCompactCollector::SweepSpaces() { |
3577 GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP); | 3674 GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP); |
3578 #ifdef DEBUG | 3675 #ifdef DEBUG |
3579 state_ = SWEEP_SPACES; | 3676 state_ = SWEEP_SPACES; |
3580 #endif | 3677 #endif |
3581 SweeperType how_to_sweep = | 3678 SweeperType how_to_sweep = |
3582 FLAG_lazy_sweeping ? LAZY_CONSERVATIVE : CONSERVATIVE; | 3679 FLAG_lazy_sweeping ? LAZY_CONSERVATIVE : CONSERVATIVE; |
3583 if (sweep_precisely_) how_to_sweep = PRECISE; | 3680 if (sweep_precisely_) how_to_sweep = PRECISE; |
3584 // Noncompacting collections simply sweep the spaces to clear the mark | 3681 // Noncompacting collections simply sweep the spaces to clear the mark |
3585 // bits and free the nonlive blocks (for old and map spaces). We sweep | 3682 // bits and free the nonlive blocks (for old and map spaces). We sweep |
3586 // the map space last because freeing non-live maps overwrites them and | 3683 // the map space last because freeing non-live maps overwrites them and |
3587 // the other spaces rely on possibly non-live maps to get the sizes for | 3684 // the other spaces rely on possibly non-live maps to get the sizes for |
3588 // non-live objects. | 3685 // non-live objects. |
3589 SweepSpace(heap()->old_pointer_space(), how_to_sweep); | 3686 SweepSpace(heap()->old_pointer_space(), how_to_sweep); |
3590 SweepSpace(heap()->old_data_space(), how_to_sweep); | 3687 SweepSpace(heap()->old_data_space(), how_to_sweep); |
3591 | 3688 |
3592 RemoveDeadInvalidatedCode(); | 3689 RemoveDeadInvalidatedCode(); |
3593 SweepSpace(heap()->code_space(), PRECISE); | 3690 SweepSpace(heap()->code_space(), PRECISE); |
3594 | 3691 |
3595 SweepSpace(heap()->cell_space(), PRECISE); | 3692 SweepSpace(heap()->cell_space(), PRECISE); |
3596 | 3693 |
3597 { GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP_NEWSPACE); | 3694 EvacuateNewSpaceAndCandidates(); |
3598 EvacuateNewSpaceAndCandidates(); | |
3599 } | |
3600 | 3695 |
3601 // ClearNonLiveTransitions depends on precise sweeping of map space to | 3696 // ClearNonLiveTransitions depends on precise sweeping of map space to |
3602 // detect whether unmarked map became dead in this collection or in one | 3697 // detect whether unmarked map became dead in this collection or in one |
3603 // of the previous ones. | 3698 // of the previous ones. |
3604 SweepSpace(heap()->map_space(), PRECISE); | 3699 SweepSpace(heap()->map_space(), PRECISE); |
3605 | 3700 |
3606 // Deallocate unmarked objects and clear marked bits for marked objects. | 3701 // Deallocate unmarked objects and clear marked bits for marked objects. |
3607 heap_->lo_space()->FreeUnmarkedObjects(); | 3702 heap_->lo_space()->FreeUnmarkedObjects(); |
3608 } | 3703 } |
3609 | 3704 |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3775 while (buffer != NULL) { | 3870 while (buffer != NULL) { |
3776 SlotsBuffer* next_buffer = buffer->next(); | 3871 SlotsBuffer* next_buffer = buffer->next(); |
3777 DeallocateBuffer(buffer); | 3872 DeallocateBuffer(buffer); |
3778 buffer = next_buffer; | 3873 buffer = next_buffer; |
3779 } | 3874 } |
3780 *buffer_address = NULL; | 3875 *buffer_address = NULL; |
3781 } | 3876 } |
3782 | 3877 |
3783 | 3878 |
3784 } } // namespace v8::internal | 3879 } } // namespace v8::internal |
OLD | NEW |