OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/heap/mark-compact.h" | 5 #include "src/heap/mark-compact.h" |
6 | 6 |
7 #include "src/base/atomicops.h" | 7 #include "src/base/atomicops.h" |
8 #include "src/base/bits.h" | 8 #include "src/base/bits.h" |
9 #include "src/base/sys-info.h" | 9 #include "src/base/sys-info.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 808 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
819 // marking cycle. We did not collect any slots. | 819 // marking cycle. We did not collect any slots. |
820 if (!FLAG_never_compact && !was_marked_incrementally_) { | 820 if (!FLAG_never_compact && !was_marked_incrementally_) { |
821 StartCompaction(NON_INCREMENTAL_COMPACTION); | 821 StartCompaction(NON_INCREMENTAL_COMPACTION); |
822 } | 822 } |
823 | 823 |
824 PagedSpaces spaces(heap()); | 824 PagedSpaces spaces(heap()); |
825 for (PagedSpace* space = spaces.next(); space != NULL; | 825 for (PagedSpace* space = spaces.next(); space != NULL; |
826 space = spaces.next()) { | 826 space = spaces.next()) { |
827 space->PrepareForMarkCompact(); | 827 space->PrepareForMarkCompact(); |
828 } | 828 } |
829 heap()->account_external_memory_concurrently_freed(); | 829 heap()->array_buffer_tracker()->AccountForConcurrentlyFreedMemory(); |
830 | 830 |
831 #ifdef VERIFY_HEAP | 831 #ifdef VERIFY_HEAP |
832 if (!was_marked_incrementally_ && FLAG_verify_heap) { | 832 if (!was_marked_incrementally_ && FLAG_verify_heap) { |
833 VerifyMarkbitsAreClean(); | 833 VerifyMarkbitsAreClean(); |
834 } | 834 } |
835 #endif | 835 #endif |
836 } | 836 } |
837 | 837 |
838 | 838 |
839 void MarkCompactCollector::Finish() { | 839 void MarkCompactCollector::Finish() { |
(...skipping 2278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3118 int saved_live_bytes = page->LiveBytes(); | 3118 int saved_live_bytes = page->LiveBytes(); |
3119 double evacuation_time = 0.0; | 3119 double evacuation_time = 0.0; |
3120 Heap* heap = page->heap(); | 3120 Heap* heap = page->heap(); |
3121 { | 3121 { |
3122 AlwaysAllocateScope always_allocate(heap->isolate()); | 3122 AlwaysAllocateScope always_allocate(heap->isolate()); |
3123 TimedScope timed_scope(&evacuation_time); | 3123 TimedScope timed_scope(&evacuation_time); |
3124 switch (ComputeEvacuationMode(page)) { | 3124 switch (ComputeEvacuationMode(page)) { |
3125 case kObjectsNewToOld: | 3125 case kObjectsNewToOld: |
3126 success = collector_->VisitLiveObjects(page, &new_space_visitor_, | 3126 success = collector_->VisitLiveObjects(page, &new_space_visitor_, |
3127 kClearMarkbits); | 3127 kClearMarkbits); |
3128 ArrayBufferTracker::ProcessBuffers( | 3128 |
| 3129 heap->array_buffer_tracker()->ProcessBuffers( |
3129 page, ArrayBufferTracker::kUpdateForwardedRemoveOthers); | 3130 page, ArrayBufferTracker::kUpdateForwardedRemoveOthers); |
3130 DCHECK(success); | 3131 DCHECK(success); |
3131 break; | 3132 break; |
3132 case kPageNewToOld: | 3133 case kPageNewToOld: |
3133 success = collector_->VisitLiveObjects(page, &new_space_page_visitor, | 3134 success = collector_->VisitLiveObjects(page, &new_space_page_visitor, |
3134 kKeepMarking); | 3135 kKeepMarking); |
3135 // ArrayBufferTracker will be updated during sweeping. | 3136 // ArrayBufferTracker will be updated during sweeping. |
3136 DCHECK(success); | 3137 DCHECK(success); |
3137 break; | 3138 break; |
3138 case kPageNewToNew: | 3139 case kPageNewToNew: |
3139 new_space_page_visitor.account_semispace_copied(page->LiveBytes()); | 3140 new_space_page_visitor.account_semispace_copied(page->LiveBytes()); |
3140 // ArrayBufferTracker will be updated during sweeping. | 3141 // ArrayBufferTracker will be updated during sweeping. |
3141 success = true; | 3142 success = true; |
3142 break; | 3143 break; |
3143 case kObjectsOldToOld: | 3144 case kObjectsOldToOld: |
3144 success = collector_->VisitLiveObjects(page, &old_space_visitor_, | 3145 success = collector_->VisitLiveObjects(page, &old_space_visitor_, |
3145 kClearMarkbits); | 3146 kClearMarkbits); |
3146 if (!success) { | 3147 if (!success) { |
3147 // Aborted compaction page. We have to record slots here, since we | 3148 // Aborted compaction page. We have to record slots here, since we |
3148 // might not have recorded them in first place. | 3149 // might not have recorded them in first place. |
3149 // Note: We mark the page as aborted here to be able to record slots | 3150 // Note: We mark the page as aborted here to be able to record slots |
3150 // for code objects in |RecordMigratedSlotVisitor|. | 3151 // for code objects in |RecordMigratedSlotVisitor|. |
3151 page->SetFlag(Page::COMPACTION_WAS_ABORTED); | 3152 page->SetFlag(Page::COMPACTION_WAS_ABORTED); |
3152 EvacuateRecordOnlyVisitor record_visitor(collector_->heap()); | 3153 EvacuateRecordOnlyVisitor record_visitor(collector_->heap()); |
3153 success = | 3154 success = |
3154 collector_->VisitLiveObjects(page, &record_visitor, kKeepMarking); | 3155 collector_->VisitLiveObjects(page, &record_visitor, kKeepMarking); |
3155 ArrayBufferTracker::ProcessBuffers( | 3156 heap->array_buffer_tracker()->ProcessBuffers( |
3156 page, ArrayBufferTracker::kUpdateForwardedKeepOthers); | 3157 page, ArrayBufferTracker::kUpdateForwardedKeepOthers); |
3157 DCHECK(success); | 3158 DCHECK(success); |
3158 // We need to return failure here to indicate that we want this page | 3159 // We need to return failure here to indicate that we want this page |
3159 // added to the sweeper. | 3160 // added to the sweeper. |
3160 success = false; | 3161 success = false; |
3161 } else { | 3162 } else { |
3162 ArrayBufferTracker::ProcessBuffers( | 3163 heap->array_buffer_tracker()->ProcessBuffers( |
3163 page, ArrayBufferTracker::kUpdateForwardedRemoveOthers); | 3164 page, ArrayBufferTracker::kUpdateForwardedRemoveOthers); |
3164 } | 3165 } |
3165 break; | 3166 break; |
3166 default: | 3167 default: |
3167 UNREACHABLE(); | 3168 UNREACHABLE(); |
3168 } | 3169 } |
3169 } | 3170 } |
3170 ReportCompactionProgress(evacuation_time, saved_live_bytes); | 3171 ReportCompactionProgress(evacuation_time, saved_live_bytes); |
3171 if (FLAG_trace_evacuation) { | 3172 if (FLAG_trace_evacuation) { |
3172 PrintIsolate(heap->isolate(), | 3173 PrintIsolate(heap->isolate(), |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3356 Page* p, FreeListRebuildingMode free_list_mode, | 3357 Page* p, FreeListRebuildingMode free_list_mode, |
3357 FreeSpaceTreatmentMode free_space_mode) { | 3358 FreeSpaceTreatmentMode free_space_mode) { |
3358 Space* space = p->owner(); | 3359 Space* space = p->owner(); |
3359 DCHECK_NOT_NULL(space); | 3360 DCHECK_NOT_NULL(space); |
3360 DCHECK(free_list_mode == IGNORE_FREE_LIST || space->identity() == OLD_SPACE || | 3361 DCHECK(free_list_mode == IGNORE_FREE_LIST || space->identity() == OLD_SPACE || |
3361 space->identity() == CODE_SPACE || space->identity() == MAP_SPACE); | 3362 space->identity() == CODE_SPACE || space->identity() == MAP_SPACE); |
3362 DCHECK(!p->IsEvacuationCandidate() && !p->SweepingDone()); | 3363 DCHECK(!p->IsEvacuationCandidate() && !p->SweepingDone()); |
3363 | 3364 |
3364 // Before we sweep objects on the page, we free dead array buffers which | 3365 // Before we sweep objects on the page, we free dead array buffers which |
3365 // requires valid mark bits. | 3366 // requires valid mark bits. |
3366 ArrayBufferTracker::FreeDead(p); | 3367 p->heap()->array_buffer_tracker()->FreeDead(p); |
3367 | 3368 |
3368 Address free_start = p->area_start(); | 3369 Address free_start = p->area_start(); |
3369 DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); | 3370 DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); |
3370 | 3371 |
3371 // If we use the skip list for code space pages, we have to lock the skip | 3372 // If we use the skip list for code space pages, we have to lock the skip |
3372 // list because it could be accessed concurrently by the runtime or the | 3373 // list because it could be accessed concurrently by the runtime or the |
3373 // deoptimizer. | 3374 // deoptimizer. |
3374 const bool rebuild_skip_list = | 3375 const bool rebuild_skip_list = |
3375 space->identity() == CODE_SPACE && p->skip_list() != nullptr; | 3376 space->identity() == CODE_SPACE && p->skip_list() != nullptr; |
3376 SkipList* skip_list = p->skip_list(); | 3377 SkipList* skip_list = p->skip_list(); |
(...skipping 563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3940 continue; | 3941 continue; |
3941 } | 3942 } |
3942 | 3943 |
3943 // One unused page is kept, all further are released before sweeping them. | 3944 // One unused page is kept, all further are released before sweeping them. |
3944 if (p->LiveBytes() == 0) { | 3945 if (p->LiveBytes() == 0) { |
3945 if (unused_page_present) { | 3946 if (unused_page_present) { |
3946 if (FLAG_gc_verbose) { | 3947 if (FLAG_gc_verbose) { |
3947 PrintIsolate(isolate(), "sweeping: released page: %p", | 3948 PrintIsolate(isolate(), "sweeping: released page: %p", |
3948 static_cast<void*>(p)); | 3949 static_cast<void*>(p)); |
3949 } | 3950 } |
3950 ArrayBufferTracker::FreeAll(p); | 3951 heap()->array_buffer_tracker()->FreeAll(p); |
3951 space->ReleasePage(p); | 3952 space->ReleasePage(p); |
3952 continue; | 3953 continue; |
3953 } | 3954 } |
3954 unused_page_present = true; | 3955 unused_page_present = true; |
3955 } | 3956 } |
3956 | 3957 |
3957 sweeper().AddPage(space->identity(), p); | 3958 sweeper().AddPage(space->identity(), p); |
3958 will_be_swept++; | 3959 will_be_swept++; |
3959 } | 3960 } |
3960 | 3961 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4038 // The target is always in old space, we don't have to record the slot in | 4039 // The target is always in old space, we don't have to record the slot in |
4039 // the old-to-new remembered set. | 4040 // the old-to-new remembered set. |
4040 DCHECK(!heap()->InNewSpace(target)); | 4041 DCHECK(!heap()->InNewSpace(target)); |
4041 RecordRelocSlot(host, &rinfo, target); | 4042 RecordRelocSlot(host, &rinfo, target); |
4042 } | 4043 } |
4043 } | 4044 } |
4044 } | 4045 } |
4045 | 4046 |
4046 } // namespace internal | 4047 } // namespace internal |
4047 } // namespace v8 | 4048 } // namespace v8 |
OLD | NEW |