| 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 |