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 "v8.h" | 5 #include "v8.h" |
6 | 6 |
7 #include "code-stubs.h" | 7 #include "code-stubs.h" |
8 #include "compilation-cache.h" | 8 #include "compilation-cache.h" |
9 #include "cpu-profiler.h" | 9 #include "cpu-profiler.h" |
10 #include "deoptimizer.h" | 10 #include "deoptimizer.h" |
(...skipping 3158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3169 if (static_cast<PagedSpace*>(p->owner())->CanExpand()) { | 3169 if (static_cast<PagedSpace*>(p->owner())->CanExpand()) { |
3170 EvacuateLiveObjectsFromPage(p); | 3170 EvacuateLiveObjectsFromPage(p); |
3171 } else { | 3171 } else { |
3172 // Without room for expansion evacuation is not guaranteed to succeed. | 3172 // Without room for expansion evacuation is not guaranteed to succeed. |
3173 // Pessimistically abandon unevacuated pages. | 3173 // Pessimistically abandon unevacuated pages. |
3174 for (int j = i; j < npages; j++) { | 3174 for (int j = i; j < npages; j++) { |
3175 Page* page = evacuation_candidates_[j]; | 3175 Page* page = evacuation_candidates_[j]; |
3176 slots_buffer_allocator_.DeallocateChain(page->slots_buffer_address()); | 3176 slots_buffer_allocator_.DeallocateChain(page->slots_buffer_address()); |
3177 page->ClearEvacuationCandidate(); | 3177 page->ClearEvacuationCandidate(); |
3178 page->SetFlag(Page::RESCAN_ON_EVACUATION); | 3178 page->SetFlag(Page::RESCAN_ON_EVACUATION); |
3179 page->InsertAfter(static_cast<PagedSpace*>(page->owner())->anchor()); | |
3180 } | 3179 } |
3181 return; | 3180 return; |
3182 } | 3181 } |
3183 } | 3182 } |
3184 } | 3183 } |
3185 } | 3184 } |
3186 | 3185 |
3187 | 3186 |
3188 class EvacuationWeakObjectRetainer : public WeakObjectRetainer { | 3187 class EvacuationWeakObjectRetainer : public WeakObjectRetainer { |
3189 public: | 3188 public: |
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3660 if (FLAG_verify_heap) { | 3659 if (FLAG_verify_heap) { |
3661 VerifyEvacuation(heap_); | 3660 VerifyEvacuation(heap_); |
3662 } | 3661 } |
3663 #endif | 3662 #endif |
3664 | 3663 |
3665 slots_buffer_allocator_.DeallocateChain(&migration_slots_buffer_); | 3664 slots_buffer_allocator_.DeallocateChain(&migration_slots_buffer_); |
3666 ASSERT(migration_slots_buffer_ == NULL); | 3665 ASSERT(migration_slots_buffer_ == NULL); |
3667 } | 3666 } |
3668 | 3667 |
3669 | 3668 |
3670 void MarkCompactCollector::UnlinkEvacuationCandidates() { | 3669 void MarkCompactCollector::MoveEvacuationCandidatesToEndOfPagesList() { |
3671 int npages = evacuation_candidates_.length(); | 3670 int npages = evacuation_candidates_.length(); |
3672 for (int i = 0; i < npages; i++) { | 3671 for (int i = 0; i < npages; i++) { |
3673 Page* p = evacuation_candidates_[i]; | 3672 Page* p = evacuation_candidates_[i]; |
3674 if (!p->IsEvacuationCandidate()) continue; | 3673 if (!p->IsEvacuationCandidate()) continue; |
3675 p->Unlink(); | 3674 p->Unlink(); |
3676 p->ClearSweptPrecisely(); | 3675 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); |
3677 p->ClearSweptConservatively(); | 3676 p->InsertAfter(space->LastPage()); |
3678 } | 3677 } |
3679 } | 3678 } |
3680 | 3679 |
3681 | 3680 |
3682 void MarkCompactCollector::ReleaseEvacuationCandidates() { | 3681 void MarkCompactCollector::ReleaseEvacuationCandidates() { |
3683 int npages = evacuation_candidates_.length(); | 3682 int npages = evacuation_candidates_.length(); |
3684 for (int i = 0; i < npages; i++) { | 3683 for (int i = 0; i < npages; i++) { |
3685 Page* p = evacuation_candidates_[i]; | 3684 Page* p = evacuation_candidates_[i]; |
3686 if (!p->IsEvacuationCandidate()) continue; | 3685 if (!p->IsEvacuationCandidate()) continue; |
3687 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); | 3686 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); |
3688 space->Free(p->area_start(), p->area_size()); | 3687 space->Free(p->area_start(), p->area_size()); |
3689 p->set_scan_on_scavenge(false); | 3688 p->set_scan_on_scavenge(false); |
3690 slots_buffer_allocator_.DeallocateChain(p->slots_buffer_address()); | 3689 slots_buffer_allocator_.DeallocateChain(p->slots_buffer_address()); |
3691 p->ResetLiveBytes(); | 3690 p->ResetLiveBytes(); |
3692 space->ReleasePage(p, false); | 3691 space->ReleasePage(p); |
3693 } | 3692 } |
3694 evacuation_candidates_.Rewind(0); | 3693 evacuation_candidates_.Rewind(0); |
3695 compacting_ = false; | 3694 compacting_ = false; |
3696 heap()->FreeQueuedChunks(); | 3695 heap()->FreeQueuedChunks(); |
3697 } | 3696 } |
3698 | 3697 |
3699 | 3698 |
3700 static const int kStartTableEntriesPerLine = 5; | 3699 static const int kStartTableEntriesPerLine = 5; |
3701 static const int kStartTableLines = 171; | 3700 static const int kStartTableLines = 171; |
3702 static const int kStartTableInvalidLine = 127; | 3701 static const int kStartTableInvalidLine = 127; |
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4106 : free_list_old_data_space_.get(); | 4105 : free_list_old_data_space_.get(); |
4107 FreeList private_free_list(space); | 4106 FreeList private_free_list(space); |
4108 while (it.has_next()) { | 4107 while (it.has_next()) { |
4109 Page* p = it.next(); | 4108 Page* p = it.next(); |
4110 | 4109 |
4111 if (p->TryParallelSweeping()) { | 4110 if (p->TryParallelSweeping()) { |
4112 SweepConservatively<SWEEP_IN_PARALLEL>(space, &private_free_list, p); | 4111 SweepConservatively<SWEEP_IN_PARALLEL>(space, &private_free_list, p); |
4113 free_list->Concatenate(&private_free_list); | 4112 free_list->Concatenate(&private_free_list); |
4114 p->set_parallel_sweeping(MemoryChunk::PARALLEL_SWEEPING_FINALIZE); | 4113 p->set_parallel_sweeping(MemoryChunk::PARALLEL_SWEEPING_FINALIZE); |
4115 } | 4114 } |
| 4115 if (p == space->end_of_unswept_pages()) break; |
4116 } | 4116 } |
4117 } | 4117 } |
4118 | 4118 |
4119 | 4119 |
4120 void MarkCompactCollector::SweepSpace(PagedSpace* space, SweeperType sweeper) { | 4120 void MarkCompactCollector::SweepSpace(PagedSpace* space, SweeperType sweeper) { |
4121 space->set_was_swept_conservatively(sweeper == CONSERVATIVE || | 4121 space->set_was_swept_conservatively(sweeper == CONSERVATIVE || |
4122 sweeper == PARALLEL_CONSERVATIVE || | 4122 sweeper == PARALLEL_CONSERVATIVE || |
4123 sweeper == CONCURRENT_CONSERVATIVE); | 4123 sweeper == CONCURRENT_CONSERVATIVE); |
4124 space->ClearStats(); | 4124 space->ClearStats(); |
4125 | 4125 |
| 4126 // We defensively initialize end_of_unswept_pages_ here with the first page |
| 4127 // of the pages list. |
| 4128 space->set_end_of_unswept_pages(space->FirstPage()); |
| 4129 |
4126 PageIterator it(space); | 4130 PageIterator it(space); |
4127 | 4131 |
4128 int pages_swept = 0; | 4132 int pages_swept = 0; |
4129 bool unused_page_present = false; | 4133 bool unused_page_present = false; |
4130 bool parallel_sweeping_active = false; | 4134 bool parallel_sweeping_active = false; |
4131 | 4135 |
4132 while (it.has_next()) { | 4136 while (it.has_next()) { |
4133 Page* p = it.next(); | 4137 Page* p = it.next(); |
4134 | |
4135 ASSERT(p->parallel_sweeping() == MemoryChunk::PARALLEL_SWEEPING_DONE); | 4138 ASSERT(p->parallel_sweeping() == MemoryChunk::PARALLEL_SWEEPING_DONE); |
4136 ASSERT(!p->IsEvacuationCandidate()); | |
4137 | 4139 |
4138 // Clear sweeping flags indicating that marking bits are still intact. | 4140 // Clear sweeping flags indicating that marking bits are still intact. |
4139 p->ClearSweptPrecisely(); | 4141 p->ClearSweptPrecisely(); |
4140 p->ClearSweptConservatively(); | 4142 p->ClearSweptConservatively(); |
4141 | 4143 |
4142 if (p->IsFlagSet(Page::RESCAN_ON_EVACUATION)) { | 4144 if (p->IsFlagSet(Page::RESCAN_ON_EVACUATION) || |
| 4145 p->IsEvacuationCandidate()) { |
4143 // Will be processed in EvacuateNewSpaceAndCandidates. | 4146 // Will be processed in EvacuateNewSpaceAndCandidates. |
4144 ASSERT(evacuation_candidates_.length() > 0); | 4147 ASSERT(evacuation_candidates_.length() > 0); |
4145 continue; | 4148 continue; |
4146 } | 4149 } |
4147 | 4150 |
4148 // One unused page is kept, all further are released before sweeping them. | 4151 // One unused page is kept, all further are released before sweeping them. |
4149 if (p->LiveBytes() == 0) { | 4152 if (p->LiveBytes() == 0) { |
4150 if (unused_page_present) { | 4153 if (unused_page_present) { |
4151 if (FLAG_gc_verbose) { | 4154 if (FLAG_gc_verbose) { |
4152 PrintF("Sweeping 0x%" V8PRIxPTR " released page.\n", | 4155 PrintF("Sweeping 0x%" V8PRIxPTR " released page.\n", |
4153 reinterpret_cast<intptr_t>(p)); | 4156 reinterpret_cast<intptr_t>(p)); |
4154 } | 4157 } |
4155 // Adjust unswept free bytes because releasing a page expects said | 4158 // Adjust unswept free bytes because releasing a page expects said |
4156 // counter to be accurate for unswept pages. | 4159 // counter to be accurate for unswept pages. |
4157 space->IncreaseUnsweptFreeBytes(p); | 4160 space->IncreaseUnsweptFreeBytes(p); |
4158 space->ReleasePage(p, true); | 4161 space->ReleasePage(p); |
4159 continue; | 4162 continue; |
4160 } | 4163 } |
4161 unused_page_present = true; | 4164 unused_page_present = true; |
4162 } | 4165 } |
4163 | 4166 |
4164 switch (sweeper) { | 4167 switch (sweeper) { |
4165 case CONSERVATIVE: { | 4168 case CONSERVATIVE: { |
4166 if (FLAG_gc_verbose) { | 4169 if (FLAG_gc_verbose) { |
4167 PrintF("Sweeping 0x%" V8PRIxPTR " conservatively.\n", | 4170 PrintF("Sweeping 0x%" V8PRIxPTR " conservatively.\n", |
4168 reinterpret_cast<intptr_t>(p)); | 4171 reinterpret_cast<intptr_t>(p)); |
(...skipping 13 matching lines...) Expand all Loading... |
4182 pages_swept++; | 4185 pages_swept++; |
4183 parallel_sweeping_active = true; | 4186 parallel_sweeping_active = true; |
4184 } else { | 4187 } else { |
4185 if (FLAG_gc_verbose) { | 4188 if (FLAG_gc_verbose) { |
4186 PrintF("Sweeping 0x%" V8PRIxPTR " conservatively in parallel.\n", | 4189 PrintF("Sweeping 0x%" V8PRIxPTR " conservatively in parallel.\n", |
4187 reinterpret_cast<intptr_t>(p)); | 4190 reinterpret_cast<intptr_t>(p)); |
4188 } | 4191 } |
4189 p->set_parallel_sweeping(MemoryChunk::PARALLEL_SWEEPING_PENDING); | 4192 p->set_parallel_sweeping(MemoryChunk::PARALLEL_SWEEPING_PENDING); |
4190 space->IncreaseUnsweptFreeBytes(p); | 4193 space->IncreaseUnsweptFreeBytes(p); |
4191 } | 4194 } |
| 4195 space->set_end_of_unswept_pages(p); |
4192 break; | 4196 break; |
4193 } | 4197 } |
4194 case PRECISE: { | 4198 case PRECISE: { |
4195 if (FLAG_gc_verbose) { | 4199 if (FLAG_gc_verbose) { |
4196 PrintF("Sweeping 0x%" V8PRIxPTR " precisely.\n", | 4200 PrintF("Sweeping 0x%" V8PRIxPTR " precisely.\n", |
4197 reinterpret_cast<intptr_t>(p)); | 4201 reinterpret_cast<intptr_t>(p)); |
4198 } | 4202 } |
4199 if (space->identity() == CODE_SPACE && FLAG_zap_code_space) { | 4203 if (space->identity() == CODE_SPACE && FLAG_zap_code_space) { |
4200 SweepPrecisely<SWEEP_ONLY, REBUILD_SKIP_LIST, ZAP_FREE_SPACE>( | 4204 SweepPrecisely<SWEEP_ONLY, REBUILD_SKIP_LIST, ZAP_FREE_SPACE>( |
4201 space, p, NULL); | 4205 space, p, NULL); |
(...skipping 29 matching lines...) Expand all Loading... |
4231 #ifdef DEBUG | 4235 #ifdef DEBUG |
4232 state_ = SWEEP_SPACES; | 4236 state_ = SWEEP_SPACES; |
4233 #endif | 4237 #endif |
4234 SweeperType how_to_sweep = CONSERVATIVE; | 4238 SweeperType how_to_sweep = CONSERVATIVE; |
4235 if (AreSweeperThreadsActivated()) { | 4239 if (AreSweeperThreadsActivated()) { |
4236 if (FLAG_parallel_sweeping) how_to_sweep = PARALLEL_CONSERVATIVE; | 4240 if (FLAG_parallel_sweeping) how_to_sweep = PARALLEL_CONSERVATIVE; |
4237 if (FLAG_concurrent_sweeping) how_to_sweep = CONCURRENT_CONSERVATIVE; | 4241 if (FLAG_concurrent_sweeping) how_to_sweep = CONCURRENT_CONSERVATIVE; |
4238 } | 4242 } |
4239 if (sweep_precisely_) how_to_sweep = PRECISE; | 4243 if (sweep_precisely_) how_to_sweep = PRECISE; |
4240 | 4244 |
4241 // Unlink evacuation candidates before sweeper threads access the list of | 4245 MoveEvacuationCandidatesToEndOfPagesList(); |
4242 // pages to avoid race condition. | |
4243 UnlinkEvacuationCandidates(); | |
4244 | 4246 |
4245 // Noncompacting collections simply sweep the spaces to clear the mark | 4247 // Noncompacting collections simply sweep the spaces to clear the mark |
4246 // bits and free the nonlive blocks (for old and map spaces). We sweep | 4248 // bits and free the nonlive blocks (for old and map spaces). We sweep |
4247 // the map space last because freeing non-live maps overwrites them and | 4249 // the map space last because freeing non-live maps overwrites them and |
4248 // the other spaces rely on possibly non-live maps to get the sizes for | 4250 // the other spaces rely on possibly non-live maps to get the sizes for |
4249 // non-live objects. | 4251 // non-live objects. |
4250 { GCTracer::Scope sweep_scope(tracer_, GCTracer::Scope::MC_SWEEP_OLDSPACE); | 4252 { GCTracer::Scope sweep_scope(tracer_, GCTracer::Scope::MC_SWEEP_OLDSPACE); |
4251 { SequentialSweepingScope scope(this); | 4253 { SequentialSweepingScope scope(this); |
4252 SweepSpace(heap()->old_pointer_space(), how_to_sweep); | 4254 SweepSpace(heap()->old_pointer_space(), how_to_sweep); |
4253 SweepSpace(heap()->old_data_space(), how_to_sweep); | 4255 SweepSpace(heap()->old_data_space(), how_to_sweep); |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4520 while (buffer != NULL) { | 4522 while (buffer != NULL) { |
4521 SlotsBuffer* next_buffer = buffer->next(); | 4523 SlotsBuffer* next_buffer = buffer->next(); |
4522 DeallocateBuffer(buffer); | 4524 DeallocateBuffer(buffer); |
4523 buffer = next_buffer; | 4525 buffer = next_buffer; |
4524 } | 4526 } |
4525 *buffer_address = NULL; | 4527 *buffer_address = NULL; |
4526 } | 4528 } |
4527 | 4529 |
4528 | 4530 |
4529 } } // namespace v8::internal | 4531 } } // namespace v8::internal |
OLD | NEW |