| 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 650 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 661 } | 661 } |
| 662 | 662 |
| 663 | 663 |
| 664 void MarkCompactCollector::CollectEvacuationCandidates(PagedSpace* space) { | 664 void MarkCompactCollector::CollectEvacuationCandidates(PagedSpace* space) { |
| 665 DCHECK(space->identity() == OLD_SPACE || space->identity() == CODE_SPACE); | 665 DCHECK(space->identity() == OLD_SPACE || space->identity() == CODE_SPACE); |
| 666 | 666 |
| 667 int number_of_pages = space->CountTotalPages(); | 667 int number_of_pages = space->CountTotalPages(); |
| 668 int area_size = space->AreaSize(); | 668 int area_size = space->AreaSize(); |
| 669 | 669 |
| 670 // Pairs of (live_bytes_in_page, page). | 670 // Pairs of (live_bytes_in_page, page). |
| 671 std::vector<std::pair<int, Page*> > pages; | 671 typedef std::pair<int, Page*> LiveBytesPagePair; |
| 672 std::vector<LiveBytesPagePair> pages; |
| 672 pages.reserve(number_of_pages); | 673 pages.reserve(number_of_pages); |
| 673 | 674 |
| 674 PageIterator it(space); | 675 PageIterator it(space); |
| 675 while (it.has_next()) { | 676 while (it.has_next()) { |
| 676 Page* p = it.next(); | 677 Page* p = it.next(); |
| 677 if (p->NeverEvacuate()) continue; | 678 if (p->NeverEvacuate()) continue; |
| 678 if (p->IsFlagSet(Page::POPULAR_PAGE)) { | 679 if (p->IsFlagSet(Page::POPULAR_PAGE)) { |
| 679 // This page had slots buffer overflow on previous GC, skip it. | 680 // This page had slots buffer overflow on previous GC, skip it. |
| 680 p->ClearFlag(Page::POPULAR_PAGE); | 681 p->ClearFlag(Page::POPULAR_PAGE); |
| 681 continue; | 682 continue; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 732 max_evacuated_bytes = kMaxEvacuatedBytes; | 733 max_evacuated_bytes = kMaxEvacuatedBytes; |
| 733 } | 734 } |
| 734 intptr_t free_bytes_threshold = | 735 intptr_t free_bytes_threshold = |
| 735 target_fragmentation_percent * (area_size / 100); | 736 target_fragmentation_percent * (area_size / 100); |
| 736 | 737 |
| 737 // Sort pages from the most free to the least free, then select | 738 // Sort pages from the most free to the least free, then select |
| 738 // the first n pages for evacuation such that: | 739 // the first n pages for evacuation such that: |
| 739 // - the total size of evacuated objects does not exceed the specified | 740 // - the total size of evacuated objects does not exceed the specified |
| 740 // limit. | 741 // limit. |
| 741 // - fragmentation of (n+1)-th page does not exceed the specified limit. | 742 // - fragmentation of (n+1)-th page does not exceed the specified limit. |
| 742 std::sort(pages.begin(), pages.end()); | 743 std::sort(pages.begin(), pages.end(), |
| 744 [](const LiveBytesPagePair& a, const LiveBytesPagePair& b) { |
| 745 return a.first < b.first; |
| 746 }); |
| 743 for (size_t i = 0; i < pages.size(); i++) { | 747 for (size_t i = 0; i < pages.size(); i++) { |
| 744 int live_bytes = pages[i].first; | 748 int live_bytes = pages[i].first; |
| 745 int free_bytes = area_size - live_bytes; | 749 int free_bytes = area_size - live_bytes; |
| 746 if (FLAG_always_compact || | 750 if (FLAG_always_compact || |
| 747 (free_bytes >= free_bytes_threshold && | 751 (free_bytes >= free_bytes_threshold && |
| 748 total_live_bytes + live_bytes <= max_evacuated_bytes)) { | 752 total_live_bytes + live_bytes <= max_evacuated_bytes)) { |
| 749 candidate_count++; | 753 candidate_count++; |
| 750 total_live_bytes += live_bytes; | 754 total_live_bytes += live_bytes; |
| 751 } | 755 } |
| 752 if (FLAG_trace_fragmentation_verbose) { | 756 if (FLAG_trace_fragmentation_verbose) { |
| (...skipping 1208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1961 DCHECK(in_use_); | 1965 DCHECK(in_use_); |
| 1962 top_ = bottom_ = 0xdecbad; | 1966 top_ = bottom_ = 0xdecbad; |
| 1963 in_use_ = false; | 1967 in_use_ = false; |
| 1964 } | 1968 } |
| 1965 | 1969 |
| 1966 | 1970 |
| 1967 void MarkCompactCollector::MarkLiveObjects() { | 1971 void MarkCompactCollector::MarkLiveObjects() { |
| 1968 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_MARK); | 1972 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_MARK); |
| 1969 double start_time = 0.0; | 1973 double start_time = 0.0; |
| 1970 if (FLAG_print_cumulative_gc_stat) { | 1974 if (FLAG_print_cumulative_gc_stat) { |
| 1971 start_time = base::OS::TimeCurrentMillis(); | 1975 start_time = heap_->MonotonicallyIncreasingTimeInMs(); |
| 1972 } | 1976 } |
| 1973 // The recursive GC marker detects when it is nearing stack overflow, | 1977 // The recursive GC marker detects when it is nearing stack overflow, |
| 1974 // and switches to a different marking system. JS interrupts interfere | 1978 // and switches to a different marking system. JS interrupts interfere |
| 1975 // with the C stack limit check. | 1979 // with the C stack limit check. |
| 1976 PostponeInterruptsScope postpone(isolate()); | 1980 PostponeInterruptsScope postpone(isolate()); |
| 1977 | 1981 |
| 1978 { | 1982 { |
| 1979 GCTracer::Scope gc_scope(heap()->tracer(), | 1983 GCTracer::Scope gc_scope(heap()->tracer(), |
| 1980 GCTracer::Scope::MC_MARK_FINISH_INCREMENTAL); | 1984 GCTracer::Scope::MC_MARK_FINISH_INCREMENTAL); |
| 1981 IncrementalMarking* incremental_marking = heap_->incremental_marking(); | 1985 IncrementalMarking* incremental_marking = heap_->incremental_marking(); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2051 // the weak roots we just marked as pending destruction. | 2055 // the weak roots we just marked as pending destruction. |
| 2052 // | 2056 // |
| 2053 // We only process harmony collections, as all object groups have been fully | 2057 // We only process harmony collections, as all object groups have been fully |
| 2054 // processed and no weakly reachable node can discover new objects groups. | 2058 // processed and no weakly reachable node can discover new objects groups. |
| 2055 ProcessEphemeralMarking(&root_visitor, true); | 2059 ProcessEphemeralMarking(&root_visitor, true); |
| 2056 } | 2060 } |
| 2057 | 2061 |
| 2058 AfterMarking(); | 2062 AfterMarking(); |
| 2059 | 2063 |
| 2060 if (FLAG_print_cumulative_gc_stat) { | 2064 if (FLAG_print_cumulative_gc_stat) { |
| 2061 heap_->tracer()->AddMarkingTime(base::OS::TimeCurrentMillis() - start_time); | 2065 heap_->tracer()->AddMarkingTime(heap_->MonotonicallyIncreasingTimeInMs() - |
| 2066 start_time); |
| 2062 } | 2067 } |
| 2063 } | 2068 } |
| 2064 | 2069 |
| 2065 | 2070 |
| 2066 void MarkCompactCollector::AfterMarking() { | 2071 void MarkCompactCollector::AfterMarking() { |
| 2067 { | 2072 { |
| 2068 GCTracer::Scope gc_scope(heap()->tracer(), | 2073 GCTracer::Scope gc_scope(heap()->tracer(), |
| 2069 GCTracer::Scope::MC_MARK_STRING_TABLE); | 2074 GCTracer::Scope::MC_MARK_STRING_TABLE); |
| 2070 | 2075 |
| 2071 // Prune the string table removing all strings only pointed to by the | 2076 // Prune the string table removing all strings only pointed to by the |
| (...skipping 2325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4397 PrintF("SweepSpace: %s (%d pages swept)\n", | 4402 PrintF("SweepSpace: %s (%d pages swept)\n", |
| 4398 AllocationSpaceName(space->identity()), pages_swept); | 4403 AllocationSpaceName(space->identity()), pages_swept); |
| 4399 } | 4404 } |
| 4400 } | 4405 } |
| 4401 | 4406 |
| 4402 | 4407 |
| 4403 void MarkCompactCollector::SweepSpaces() { | 4408 void MarkCompactCollector::SweepSpaces() { |
| 4404 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_SWEEP); | 4409 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_SWEEP); |
| 4405 double start_time = 0.0; | 4410 double start_time = 0.0; |
| 4406 if (FLAG_print_cumulative_gc_stat) { | 4411 if (FLAG_print_cumulative_gc_stat) { |
| 4407 start_time = base::OS::TimeCurrentMillis(); | 4412 start_time = heap_->MonotonicallyIncreasingTimeInMs(); |
| 4408 } | 4413 } |
| 4409 | 4414 |
| 4410 #ifdef DEBUG | 4415 #ifdef DEBUG |
| 4411 state_ = SWEEP_SPACES; | 4416 state_ = SWEEP_SPACES; |
| 4412 #endif | 4417 #endif |
| 4413 | 4418 |
| 4414 MoveEvacuationCandidatesToEndOfPagesList(); | 4419 MoveEvacuationCandidatesToEndOfPagesList(); |
| 4415 | 4420 |
| 4416 { | 4421 { |
| 4417 { | 4422 { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4449 // needed to properly free them. | 4454 // needed to properly free them. |
| 4450 heap()->array_buffer_tracker()->FreeDead(false); | 4455 heap()->array_buffer_tracker()->FreeDead(false); |
| 4451 | 4456 |
| 4452 // Clear the marking state of live large objects. | 4457 // Clear the marking state of live large objects. |
| 4453 heap_->lo_space()->ClearMarkingStateOfLiveObjects(); | 4458 heap_->lo_space()->ClearMarkingStateOfLiveObjects(); |
| 4454 | 4459 |
| 4455 // Deallocate evacuated candidate pages. | 4460 // Deallocate evacuated candidate pages. |
| 4456 ReleaseEvacuationCandidates(); | 4461 ReleaseEvacuationCandidates(); |
| 4457 | 4462 |
| 4458 if (FLAG_print_cumulative_gc_stat) { | 4463 if (FLAG_print_cumulative_gc_stat) { |
| 4459 heap_->tracer()->AddSweepingTime(base::OS::TimeCurrentMillis() - | 4464 heap_->tracer()->AddSweepingTime(heap_->MonotonicallyIncreasingTimeInMs() - |
| 4460 start_time); | 4465 start_time); |
| 4461 } | 4466 } |
| 4462 | 4467 |
| 4463 #ifdef VERIFY_HEAP | 4468 #ifdef VERIFY_HEAP |
| 4464 if (FLAG_verify_heap && !sweeping_in_progress_) { | 4469 if (FLAG_verify_heap && !sweeping_in_progress_) { |
| 4465 VerifyEvacuation(heap()); | 4470 VerifyEvacuation(heap()); |
| 4466 } | 4471 } |
| 4467 #endif | 4472 #endif |
| 4468 } | 4473 } |
| 4469 | 4474 |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4575 MarkBit mark_bit = Marking::MarkBitFrom(host); | 4580 MarkBit mark_bit = Marking::MarkBitFrom(host); |
| 4576 if (Marking::IsBlack(mark_bit)) { | 4581 if (Marking::IsBlack(mark_bit)) { |
| 4577 RelocInfo rinfo(pc, RelocInfo::CODE_TARGET, 0, host); | 4582 RelocInfo rinfo(pc, RelocInfo::CODE_TARGET, 0, host); |
| 4578 RecordRelocSlot(&rinfo, target); | 4583 RecordRelocSlot(&rinfo, target); |
| 4579 } | 4584 } |
| 4580 } | 4585 } |
| 4581 } | 4586 } |
| 4582 | 4587 |
| 4583 } // namespace internal | 4588 } // namespace internal |
| 4584 } // namespace v8 | 4589 } // namespace v8 |
| OLD | NEW |