| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 49 | 49 |
| 50 const char* Marking::kWhiteBitPattern = "00"; | 50 const char* Marking::kWhiteBitPattern = "00"; |
| 51 const char* Marking::kBlackBitPattern = "10"; | 51 const char* Marking::kBlackBitPattern = "10"; |
| 52 const char* Marking::kGreyBitPattern = "11"; | 52 const char* Marking::kGreyBitPattern = "11"; |
| 53 const char* Marking::kImpossibleBitPattern = "01"; | 53 const char* Marking::kImpossibleBitPattern = "01"; |
| 54 | 54 |
| 55 | 55 |
| 56 // ------------------------------------------------------------------------- | 56 // ------------------------------------------------------------------------- |
| 57 // MarkCompactCollector | 57 // MarkCompactCollector |
| 58 | 58 |
| 59 MarkCompactCollector::MarkCompactCollector() : // NOLINT | 59 MarkCompactCollector::MarkCompactCollector(Heap* heap) : // NOLINT |
| 60 #ifdef DEBUG | 60 #ifdef DEBUG |
| 61 state_(IDLE), | 61 state_(IDLE), |
| 62 #endif | 62 #endif |
| 63 sweep_precisely_(false), | 63 sweep_precisely_(false), |
| 64 reduce_memory_footprint_(false), | 64 reduce_memory_footprint_(false), |
| 65 abort_incremental_marking_(false), | 65 abort_incremental_marking_(false), |
| 66 marking_parity_(ODD_MARKING_PARITY), | 66 marking_parity_(ODD_MARKING_PARITY), |
| 67 compacting_(false), | 67 compacting_(false), |
| 68 was_marked_incrementally_(false), | 68 was_marked_incrementally_(false), |
| 69 sweeping_pending_(false), | 69 sweeping_pending_(false), |
| 70 sequential_sweeping_(false), | 70 sequential_sweeping_(false), |
| 71 tracer_(NULL), | 71 tracer_(NULL), |
| 72 migration_slots_buffer_(NULL), | 72 migration_slots_buffer_(NULL), |
| 73 heap_(NULL), | 73 heap_(heap), |
| 74 code_flusher_(NULL), | 74 code_flusher_(NULL), |
| 75 encountered_weak_collections_(NULL), | 75 encountered_weak_collections_(NULL), |
| 76 have_code_to_deoptimize_(false) { } | 76 have_code_to_deoptimize_(false) { } |
| 77 | 77 |
| 78 #ifdef VERIFY_HEAP | 78 #ifdef VERIFY_HEAP |
| 79 class VerifyMarkingVisitor: public ObjectVisitor { | 79 class VerifyMarkingVisitor: public ObjectVisitor { |
| 80 public: | 80 public: |
| 81 explicit VerifyMarkingVisitor(Heap* heap) : heap_(heap) {} | 81 explicit VerifyMarkingVisitor(Heap* heap) : heap_(heap) {} |
| 82 | 82 |
| 83 void VisitPointers(Object** start, Object** end) { | 83 void VisitPointers(Object** start, Object** end) { |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 HeapObjectIterator it(heap->code_space()); | 341 HeapObjectIterator it(heap->code_space()); |
| 342 | 342 |
| 343 for (Object* object = it.Next(); object != NULL; object = it.Next()) { | 343 for (Object* object = it.Next(); object != NULL; object = it.Next()) { |
| 344 VerifyNativeContextSeparationVisitor visitor; | 344 VerifyNativeContextSeparationVisitor visitor; |
| 345 Code::cast(object)->CodeIterateBody(&visitor); | 345 Code::cast(object)->CodeIterateBody(&visitor); |
| 346 } | 346 } |
| 347 } | 347 } |
| 348 #endif | 348 #endif |
| 349 | 349 |
| 350 | 350 |
| 351 void MarkCompactCollector::SetUp() { |
| 352 free_list_old_data_space_.Reset(new FreeList(heap_->old_data_space())); |
| 353 free_list_old_pointer_space_.Reset(new FreeList(heap_->old_pointer_space())); |
| 354 } |
| 355 |
| 356 |
| 351 void MarkCompactCollector::TearDown() { | 357 void MarkCompactCollector::TearDown() { |
| 352 AbortCompaction(); | 358 AbortCompaction(); |
| 353 } | 359 } |
| 354 | 360 |
| 355 | 361 |
| 356 void MarkCompactCollector::AddEvacuationCandidate(Page* p) { | 362 void MarkCompactCollector::AddEvacuationCandidate(Page* p) { |
| 357 p->MarkEvacuationCandidate(); | 363 p->MarkEvacuationCandidate(); |
| 358 evacuation_candidates_.Add(p); | 364 evacuation_candidates_.Add(p); |
| 359 } | 365 } |
| 360 | 366 |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 557 MarkBit mark_bit = Marking::MarkBitFrom(obj); | 563 MarkBit mark_bit = Marking::MarkBitFrom(obj); |
| 558 mark_bit.Clear(); | 564 mark_bit.Clear(); |
| 559 mark_bit.Next().Clear(); | 565 mark_bit.Next().Clear(); |
| 560 Page::FromAddress(obj->address())->ResetProgressBar(); | 566 Page::FromAddress(obj->address())->ResetProgressBar(); |
| 561 Page::FromAddress(obj->address())->ResetLiveBytes(); | 567 Page::FromAddress(obj->address())->ResetLiveBytes(); |
| 562 } | 568 } |
| 563 } | 569 } |
| 564 | 570 |
| 565 | 571 |
| 566 void MarkCompactCollector::StartSweeperThreads() { | 572 void MarkCompactCollector::StartSweeperThreads() { |
| 573 // TODO(hpayer): This check is just used for debugging purpose and |
| 574 // should be removed or turned into an assert after investigating the |
| 575 // crash in concurrent sweeping. |
| 576 CHECK(free_list_old_pointer_space_.get()->IsEmpty()); |
| 577 CHECK(free_list_old_data_space_.get()->IsEmpty()); |
| 567 sweeping_pending_ = true; | 578 sweeping_pending_ = true; |
| 568 for (int i = 0; i < isolate()->num_sweeper_threads(); i++) { | 579 for (int i = 0; i < isolate()->num_sweeper_threads(); i++) { |
| 569 isolate()->sweeper_threads()[i]->StartSweeping(); | 580 isolate()->sweeper_threads()[i]->StartSweeping(); |
| 570 } | 581 } |
| 571 } | 582 } |
| 572 | 583 |
| 573 | 584 |
| 574 void MarkCompactCollector::WaitUntilSweepingCompleted() { | 585 void MarkCompactCollector::WaitUntilSweepingCompleted() { |
| 575 ASSERT(sweeping_pending_ == true); | 586 ASSERT(sweeping_pending_ == true); |
| 576 for (int i = 0; i < isolate()->num_sweeper_threads(); i++) { | 587 for (int i = 0; i < isolate()->num_sweeper_threads(); i++) { |
| 577 isolate()->sweeper_threads()[i]->WaitForSweeperThread(); | 588 isolate()->sweeper_threads()[i]->WaitForSweeperThread(); |
| 578 } | 589 } |
| 579 sweeping_pending_ = false; | 590 sweeping_pending_ = false; |
| 580 StealMemoryFromSweeperThreads(heap()->paged_space(OLD_DATA_SPACE)); | 591 RefillFreeLists(heap()->paged_space(OLD_DATA_SPACE)); |
| 581 StealMemoryFromSweeperThreads(heap()->paged_space(OLD_POINTER_SPACE)); | 592 RefillFreeLists(heap()->paged_space(OLD_POINTER_SPACE)); |
| 582 heap()->paged_space(OLD_DATA_SPACE)->ResetUnsweptFreeBytes(); | 593 heap()->paged_space(OLD_DATA_SPACE)->ResetUnsweptFreeBytes(); |
| 583 heap()->paged_space(OLD_POINTER_SPACE)->ResetUnsweptFreeBytes(); | 594 heap()->paged_space(OLD_POINTER_SPACE)->ResetUnsweptFreeBytes(); |
| 584 } | 595 } |
| 585 | 596 |
| 586 | 597 |
| 587 intptr_t MarkCompactCollector:: | 598 intptr_t MarkCompactCollector::RefillFreeLists(PagedSpace* space) { |
| 588 StealMemoryFromSweeperThreads(PagedSpace* space) { | 599 FreeList* free_list; |
| 589 intptr_t freed_bytes = 0; | 600 |
| 590 for (int i = 0; i < isolate()->num_sweeper_threads(); i++) { | 601 if (space == heap()->old_pointer_space()) { |
| 591 freed_bytes += isolate()->sweeper_threads()[i]->StealMemory(space); | 602 free_list = free_list_old_pointer_space_.get(); |
| 603 } else if (space == heap()->old_data_space()) { |
| 604 free_list = free_list_old_data_space_.get(); |
| 605 } else { |
| 606 // Any PagedSpace might invoke RefillFreeLists, so we need to make sure |
| 607 // to only refill them for old data and pointer spaces. |
| 608 return 0; |
| 592 } | 609 } |
| 610 |
| 611 intptr_t freed_bytes = space->free_list()->Concatenate(free_list); |
| 593 space->AddToAccountingStats(freed_bytes); | 612 space->AddToAccountingStats(freed_bytes); |
| 594 space->DecrementUnsweptFreeBytes(freed_bytes); | 613 space->DecrementUnsweptFreeBytes(freed_bytes); |
| 595 return freed_bytes; | 614 return freed_bytes; |
| 596 } | 615 } |
| 597 | 616 |
| 598 | 617 |
| 599 bool MarkCompactCollector::AreSweeperThreadsActivated() { | 618 bool MarkCompactCollector::AreSweeperThreadsActivated() { |
| 600 return isolate()->sweeper_threads() != NULL; | 619 return isolate()->sweeper_threads() != NULL; |
| 601 } | 620 } |
| 602 | 621 |
| (...skipping 2444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3047 *cell = 0; | 3066 *cell = 0; |
| 3048 } | 3067 } |
| 3049 p->ResetLiveBytes(); | 3068 p->ResetLiveBytes(); |
| 3050 } | 3069 } |
| 3051 | 3070 |
| 3052 | 3071 |
| 3053 void MarkCompactCollector::EvacuatePages() { | 3072 void MarkCompactCollector::EvacuatePages() { |
| 3054 int npages = evacuation_candidates_.length(); | 3073 int npages = evacuation_candidates_.length(); |
| 3055 for (int i = 0; i < npages; i++) { | 3074 for (int i = 0; i < npages; i++) { |
| 3056 Page* p = evacuation_candidates_[i]; | 3075 Page* p = evacuation_candidates_[i]; |
| 3057 ASSERT(p->IsEvacuationCandidate() || | 3076 // TODO(hpayer): This check is just used for debugging purpose and |
| 3058 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); | 3077 // should be removed or turned into an assert after investigating the |
| 3078 // crash in concurrent sweeping. |
| 3079 CHECK(p->IsEvacuationCandidate() || |
| 3080 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); |
| 3081 CHECK_EQ(static_cast<int>(p->parallel_sweeping()), 0); |
| 3059 if (p->IsEvacuationCandidate()) { | 3082 if (p->IsEvacuationCandidate()) { |
| 3060 // During compaction we might have to request a new page. | 3083 // During compaction we might have to request a new page. |
| 3061 // Check that space still have room for that. | 3084 // Check that space still have room for that. |
| 3062 if (static_cast<PagedSpace*>(p->owner())->CanExpand()) { | 3085 if (static_cast<PagedSpace*>(p->owner())->CanExpand()) { |
| 3063 EvacuateLiveObjectsFromPage(p); | 3086 EvacuateLiveObjectsFromPage(p); |
| 3064 } else { | 3087 } else { |
| 3065 // Without room for expansion evacuation is not guaranteed to succeed. | 3088 // Without room for expansion evacuation is not guaranteed to succeed. |
| 3066 // Pessimistically abandon unevacuated pages. | 3089 // Pessimistically abandon unevacuated pages. |
| 3067 for (int j = i; j < npages; j++) { | 3090 for (int j = i; j < npages; j++) { |
| 3068 Page* page = evacuation_candidates_[j]; | 3091 Page* page = evacuation_candidates_[j]; |
| (...skipping 810 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3879 // spaces have been put on the free list and the smaller ones have been | 3902 // spaces have been put on the free list and the smaller ones have been |
| 3880 // ignored and left untouched. A free space is always either ignored or put | 3903 // ignored and left untouched. A free space is always either ignored or put |
| 3881 // on the free list, never split up into two parts. This is important | 3904 // on the free list, never split up into two parts. This is important |
| 3882 // because it means that any FreeSpace maps left actually describe a region of | 3905 // because it means that any FreeSpace maps left actually describe a region of |
| 3883 // memory that can be ignored when scanning. Dead objects other than free | 3906 // memory that can be ignored when scanning. Dead objects other than free |
| 3884 // spaces will not contain the free space map. | 3907 // spaces will not contain the free space map. |
| 3885 template<MarkCompactCollector::SweepingParallelism mode> | 3908 template<MarkCompactCollector::SweepingParallelism mode> |
| 3886 intptr_t MarkCompactCollector::SweepConservatively(PagedSpace* space, | 3909 intptr_t MarkCompactCollector::SweepConservatively(PagedSpace* space, |
| 3887 FreeList* free_list, | 3910 FreeList* free_list, |
| 3888 Page* p) { | 3911 Page* p) { |
| 3889 ASSERT(!p->IsEvacuationCandidate() && !p->WasSwept()); | 3912 // TODO(hpayer): This check is just used for debugging purpose and |
| 3913 // should be removed or turned into an assert after investigating the |
| 3914 // crash in concurrent sweeping. |
| 3915 CHECK(!p->IsEvacuationCandidate() && !p->WasSwept()); |
| 3890 ASSERT((mode == MarkCompactCollector::SWEEP_IN_PARALLEL && | 3916 ASSERT((mode == MarkCompactCollector::SWEEP_IN_PARALLEL && |
| 3891 free_list != NULL) || | 3917 free_list != NULL) || |
| 3892 (mode == MarkCompactCollector::SWEEP_SEQUENTIALLY && | 3918 (mode == MarkCompactCollector::SWEEP_SEQUENTIALLY && |
| 3893 free_list == NULL)); | 3919 free_list == NULL)); |
| 3894 | 3920 |
| 3895 p->MarkSweptConservatively(); | 3921 p->MarkSweptConservatively(); |
| 3896 | 3922 |
| 3897 intptr_t freed_bytes = 0; | 3923 intptr_t freed_bytes = 0; |
| 3898 size_t size = 0; | 3924 size_t size = 0; |
| 3899 | 3925 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3963 free_start = DigestFreeStart(free_start, free_start_cell); | 3989 free_start = DigestFreeStart(free_start, free_start_cell); |
| 3964 freed_bytes += Free<mode>(space, free_list, free_start, | 3990 freed_bytes += Free<mode>(space, free_list, free_start, |
| 3965 static_cast<int>(p->area_end() - free_start)); | 3991 static_cast<int>(p->area_end() - free_start)); |
| 3966 } | 3992 } |
| 3967 | 3993 |
| 3968 p->ResetLiveBytes(); | 3994 p->ResetLiveBytes(); |
| 3969 return freed_bytes; | 3995 return freed_bytes; |
| 3970 } | 3996 } |
| 3971 | 3997 |
| 3972 | 3998 |
| 3973 void MarkCompactCollector::SweepInParallel(PagedSpace* space, | 3999 void MarkCompactCollector::SweepInParallel(PagedSpace* space) { |
| 3974 FreeList* private_free_list, | |
| 3975 FreeList* free_list) { | |
| 3976 PageIterator it(space); | 4000 PageIterator it(space); |
| 4001 FreeList* free_list = space == heap()->old_pointer_space() |
| 4002 ? free_list_old_pointer_space_.get() |
| 4003 : free_list_old_data_space_.get(); |
| 4004 FreeList private_free_list(space); |
| 3977 while (it.has_next()) { | 4005 while (it.has_next()) { |
| 3978 Page* p = it.next(); | 4006 Page* p = it.next(); |
| 3979 | 4007 |
| 3980 if (p->TryParallelSweeping()) { | 4008 if (p->TryParallelSweeping()) { |
| 3981 SweepConservatively<SWEEP_IN_PARALLEL>(space, private_free_list, p); | 4009 SweepConservatively<SWEEP_IN_PARALLEL>(space, &private_free_list, p); |
| 3982 free_list->Concatenate(private_free_list); | 4010 free_list->Concatenate(&private_free_list); |
| 3983 } | 4011 } |
| 3984 } | 4012 } |
| 3985 } | 4013 } |
| 3986 | 4014 |
| 3987 | 4015 |
| 3988 void MarkCompactCollector::SweepSpace(PagedSpace* space, SweeperType sweeper) { | 4016 void MarkCompactCollector::SweepSpace(PagedSpace* space, SweeperType sweeper) { |
| 3989 space->set_was_swept_conservatively(sweeper == CONSERVATIVE || | 4017 space->set_was_swept_conservatively(sweeper == CONSERVATIVE || |
| 3990 sweeper == LAZY_CONSERVATIVE || | 4018 sweeper == LAZY_CONSERVATIVE || |
| 3991 sweeper == PARALLEL_CONSERVATIVE || | 4019 sweeper == PARALLEL_CONSERVATIVE || |
| 3992 sweeper == CONCURRENT_CONSERVATIVE); | 4020 sweeper == CONCURRENT_CONSERVATIVE); |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4114 GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP); | 4142 GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP); |
| 4115 #ifdef DEBUG | 4143 #ifdef DEBUG |
| 4116 state_ = SWEEP_SPACES; | 4144 state_ = SWEEP_SPACES; |
| 4117 #endif | 4145 #endif |
| 4118 SweeperType how_to_sweep = | 4146 SweeperType how_to_sweep = |
| 4119 FLAG_lazy_sweeping ? LAZY_CONSERVATIVE : CONSERVATIVE; | 4147 FLAG_lazy_sweeping ? LAZY_CONSERVATIVE : CONSERVATIVE; |
| 4120 if (isolate()->num_sweeper_threads() > 0) { | 4148 if (isolate()->num_sweeper_threads() > 0) { |
| 4121 if (FLAG_parallel_sweeping) how_to_sweep = PARALLEL_CONSERVATIVE; | 4149 if (FLAG_parallel_sweeping) how_to_sweep = PARALLEL_CONSERVATIVE; |
| 4122 if (FLAG_concurrent_sweeping) how_to_sweep = CONCURRENT_CONSERVATIVE; | 4150 if (FLAG_concurrent_sweeping) how_to_sweep = CONCURRENT_CONSERVATIVE; |
| 4123 } | 4151 } |
| 4124 if (FLAG_expose_gc) how_to_sweep = CONSERVATIVE; | |
| 4125 if (sweep_precisely_) how_to_sweep = PRECISE; | 4152 if (sweep_precisely_) how_to_sweep = PRECISE; |
| 4126 | 4153 |
| 4127 // Unlink evacuation candidates before sweeper threads access the list of | 4154 // Unlink evacuation candidates before sweeper threads access the list of |
| 4128 // pages to avoid race condition. | 4155 // pages to avoid race condition. |
| 4129 UnlinkEvacuationCandidates(); | 4156 UnlinkEvacuationCandidates(); |
| 4130 | 4157 |
| 4131 // Noncompacting collections simply sweep the spaces to clear the mark | 4158 // Noncompacting collections simply sweep the spaces to clear the mark |
| 4132 // bits and free the nonlive blocks (for old and map spaces). We sweep | 4159 // bits and free the nonlive blocks (for old and map spaces). We sweep |
| 4133 // the map space last because freeing non-live maps overwrites them and | 4160 // the map space last because freeing non-live maps overwrites them and |
| 4134 // the other spaces rely on possibly non-live maps to get the sizes for | 4161 // the other spaces rely on possibly non-live maps to get the sizes for |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4369 while (buffer != NULL) { | 4396 while (buffer != NULL) { |
| 4370 SlotsBuffer* next_buffer = buffer->next(); | 4397 SlotsBuffer* next_buffer = buffer->next(); |
| 4371 DeallocateBuffer(buffer); | 4398 DeallocateBuffer(buffer); |
| 4372 buffer = next_buffer; | 4399 buffer = next_buffer; |
| 4373 } | 4400 } |
| 4374 *buffer_address = NULL; | 4401 *buffer_address = NULL; |
| 4375 } | 4402 } |
| 4376 | 4403 |
| 4377 | 4404 |
| 4378 } } // namespace v8::internal | 4405 } } // namespace v8::internal |
| OLD | NEW |