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 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 Heap* heap = map->GetHeap(); | 185 Heap* heap = map->GetHeap(); |
186 SharedFunctionInfo* shared = SharedFunctionInfo::cast(object); | 186 SharedFunctionInfo* shared = SharedFunctionInfo::cast(object); |
187 if (shared->ic_age() != heap->global_ic_age()) { | 187 if (shared->ic_age() != heap->global_ic_age()) { |
188 shared->ResetForNewContext(heap->global_ic_age()); | 188 shared->ResetForNewContext(heap->global_ic_age()); |
189 } | 189 } |
190 FixedBodyVisitor<IncrementalMarkingMarkingVisitor, | 190 FixedBodyVisitor<IncrementalMarkingMarkingVisitor, |
191 SharedFunctionInfo::BodyDescriptor, | 191 SharedFunctionInfo::BodyDescriptor, |
192 void>::Visit(map, object); | 192 void>::Visit(map, object); |
193 } | 193 } |
194 | 194 |
195 static const int kScanningChunk = 32 * 1024; | |
196 | |
197 static int VisitHugeArray(FixedArray* array) { | |
198 Heap* heap = array->GetHeap(); | |
199 MemoryChunk* chunk = MemoryChunk::FromAddress(array->address()); | |
200 Object** start = array->data_start(); | |
201 int length = array->length(); | |
202 | |
203 if (chunk->owner()->identity() != LO_SPACE) { | |
204 VisitPointers(heap, start, start + length); | |
205 return length; | |
206 } | |
207 | |
208 int from = | |
209 chunk->IsPartiallyScanned() ? chunk->PartiallyScannedProgress() : 0; | |
210 int to = Min(from + kScanningChunk, length); | |
211 | |
212 VisitPointers(heap, start + from, start + to); | |
213 | |
214 if (to == length) { | |
215 // If it went from black to grey while it was waiting for the next bit to | |
216 // be scanned then we have to start the scan again. | |
217 MarkBit mark_bit = Marking::MarkBitFrom(array); | |
218 if (!Marking::IsBlack(mark_bit)) { | |
219 ASSERT(Marking::IsGrey(mark_bit)); | |
220 chunk->SetPartiallyScannedProgress(0); | |
221 } else { | |
222 chunk->SetCompletelyScanned(); | |
223 } | |
224 } else { | |
225 chunk->SetPartiallyScannedProgress(to); | |
226 } | |
227 return to - from; | |
228 } | |
229 | |
230 static inline void VisitJSFunction(Map* map, HeapObject* object) { | 195 static inline void VisitJSFunction(Map* map, HeapObject* object) { |
231 Heap* heap = map->GetHeap(); | 196 Heap* heap = map->GetHeap(); |
232 // Iterate over all fields in the body but take care in dealing with | 197 // Iterate over all fields in the body but take care in dealing with |
233 // the code entry and skip weak fields. | 198 // the code entry and skip weak fields. |
234 VisitPointers(heap, | 199 VisitPointers(heap, |
235 HeapObject::RawField(object, JSFunction::kPropertiesOffset), | 200 HeapObject::RawField(object, JSFunction::kPropertiesOffset), |
236 HeapObject::RawField(object, JSFunction::kCodeEntryOffset)); | 201 HeapObject::RawField(object, JSFunction::kCodeEntryOffset)); |
237 VisitCodeEntry(heap, object->address() + JSFunction::kCodeEntryOffset); | 202 VisitCodeEntry(heap, object->address() + JSFunction::kCodeEntryOffset); |
238 VisitPointers(heap, | 203 VisitPointers(heap, |
239 HeapObject::RawField(object, | 204 HeapObject::RawField(object, |
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
649 } | 614 } |
650 } else if (obj->map() != filler_map) { | 615 } else if (obj->map() != filler_map) { |
651 // Skip one word filler objects that appear on the | 616 // Skip one word filler objects that appear on the |
652 // stack when we perform in place array shift. | 617 // stack when we perform in place array shift. |
653 array[new_top] = obj; | 618 array[new_top] = obj; |
654 new_top = ((new_top + 1) & mask); | 619 new_top = ((new_top + 1) & mask); |
655 ASSERT(new_top != marking_deque_.bottom()); | 620 ASSERT(new_top != marking_deque_.bottom()); |
656 #ifdef DEBUG | 621 #ifdef DEBUG |
657 MarkBit mark_bit = Marking::MarkBitFrom(obj); | 622 MarkBit mark_bit = Marking::MarkBitFrom(obj); |
658 ASSERT(Marking::IsGrey(mark_bit) || | 623 ASSERT(Marking::IsGrey(mark_bit) || |
659 (obj->IsFiller() && Marking::IsWhite(mark_bit)) || | 624 (obj->IsFiller() && Marking::IsWhite(mark_bit))); |
660 MemoryChunk::FromAddress(obj->address())->IsPartiallyScanned()); | |
661 #endif | 625 #endif |
662 } | 626 } |
663 } | 627 } |
664 marking_deque_.set_top(new_top); | 628 marking_deque_.set_top(new_top); |
665 | 629 |
666 steps_took_since_last_gc_ = 0; | 630 steps_took_since_last_gc_ = 0; |
667 steps_count_since_last_gc_ = 0; | 631 steps_count_since_last_gc_ = 0; |
668 longest_step_ = 0.0; | 632 longest_step_ = 0.0; |
669 } | 633 } |
670 | 634 |
671 | 635 |
672 void IncrementalMarking::Hurry() { | 636 void IncrementalMarking::Hurry() { |
673 if (state() == MARKING) { | 637 if (state() == MARKING) { |
674 double start = 0.0; | 638 double start = 0.0; |
675 if (FLAG_trace_incremental_marking) { | 639 if (FLAG_trace_incremental_marking) { |
676 PrintF("[IncrementalMarking] Hurry\n"); | 640 PrintF("[IncrementalMarking] Hurry\n"); |
677 start = OS::TimeCurrentMillis(); | 641 start = OS::TimeCurrentMillis(); |
678 } | 642 } |
679 // TODO(gc) hurry can mark objects it encounters black as mutator | 643 // TODO(gc) hurry can mark objects it encounters black as mutator |
680 // was stopped. | 644 // was stopped. |
681 Map* filler_map = heap_->one_pointer_filler_map(); | 645 Map* filler_map = heap_->one_pointer_filler_map(); |
682 Map* native_context_map = heap_->native_context_map(); | 646 Map* native_context_map = heap_->native_context_map(); |
683 do { | 647 while (!marking_deque_.IsEmpty()) { |
684 while (!marking_deque_.IsEmpty()) { | 648 HeapObject* obj = marking_deque_.Pop(); |
685 HeapObject* obj = marking_deque_.Pop(); | |
686 | 649 |
687 // Explicitly skip one word fillers. Incremental markbit patterns are | 650 // Explicitly skip one word fillers. Incremental markbit patterns are |
688 // correct only for objects that occupy at least two words. | 651 // correct only for objects that occupy at least two words. |
689 Map* map = obj->map(); | 652 Map* map = obj->map(); |
690 if (map == filler_map) { | 653 if (map == filler_map) { |
691 continue; | 654 continue; |
692 } else if (map == native_context_map) { | 655 } else if (map == native_context_map) { |
693 // Native contexts have weak fields. | 656 // Native contexts have weak fields. |
694 IncrementalMarkingMarkingVisitor::VisitNativeContext(map, obj); | 657 IncrementalMarkingMarkingVisitor::VisitNativeContext(map, obj); |
695 ASSERT(!Marking::IsBlack(Marking::MarkBitFrom(obj))); | 658 } else { |
696 MemoryChunk::IncrementLiveBytesFromGC(obj->address(), obj->Size()); | 659 MarkBit map_mark_bit = Marking::MarkBitFrom(map); |
697 } else if (map->instance_type() == FIXED_ARRAY_TYPE && | 660 if (Marking::IsWhite(map_mark_bit)) { |
698 FixedArray::cast(obj)->length() > | 661 WhiteToGreyAndPush(map, map_mark_bit); |
699 IncrementalMarkingMarkingVisitor::kScanningChunk) { | |
700 MarkBit map_mark_bit = Marking::MarkBitFrom(map); | |
701 if (Marking::IsWhite(map_mark_bit)) { | |
702 WhiteToGreyAndPush(map, map_mark_bit); | |
703 } | |
704 MarkBit mark_bit = Marking::MarkBitFrom(obj); | |
705 if (!Marking::IsBlack(mark_bit)) { | |
706 MemoryChunk::IncrementLiveBytesFromGC(obj->address(), obj->Size()); | |
707 } else { | |
708 ASSERT( | |
709 MemoryChunk::FromAddress(obj->address())->IsPartiallyScanned()); | |
710 } | |
711 IncrementalMarkingMarkingVisitor::VisitHugeArray( | |
712 FixedArray::cast(obj)); | |
713 } else { | |
714 MarkBit map_mark_bit = Marking::MarkBitFrom(map); | |
715 if (Marking::IsWhite(map_mark_bit)) { | |
716 WhiteToGreyAndPush(map, map_mark_bit); | |
717 } | |
718 IncrementalMarkingMarkingVisitor::IterateBody(map, obj); | |
719 ASSERT(!Marking::IsBlack(Marking::MarkBitFrom(obj))); | |
720 MemoryChunk::IncrementLiveBytesFromGC(obj->address(), obj->Size()); | |
721 } | 662 } |
| 663 IncrementalMarkingMarkingVisitor::IterateBody(map, obj); |
| 664 } |
722 | 665 |
723 MarkBit mark_bit = Marking::MarkBitFrom(obj); | 666 MarkBit mark_bit = Marking::MarkBitFrom(obj); |
724 Marking::MarkBlack(mark_bit); | 667 ASSERT(!Marking::IsBlack(mark_bit)); |
725 } | 668 Marking::MarkBlack(mark_bit); |
726 state_ = COMPLETE; | 669 MemoryChunk::IncrementLiveBytesFromGC(obj->address(), obj->Size()); |
727 if (FLAG_trace_incremental_marking) { | 670 } |
728 double end = OS::TimeCurrentMillis(); | 671 state_ = COMPLETE; |
729 PrintF("[IncrementalMarking] Complete (hurry), spent %d ms.\n", | 672 if (FLAG_trace_incremental_marking) { |
730 static_cast<int>(end - start)); | 673 double end = OS::TimeCurrentMillis(); |
731 } | 674 PrintF("[IncrementalMarking] Complete (hurry), spent %d ms.\n", |
732 MarkCompactCollector::ProcessLargePostponedArrays(heap_, &marking_deque_); | 675 static_cast<int>(end - start)); |
733 } while (!marking_deque_.IsEmpty()); | 676 } |
734 } | 677 } |
735 | 678 |
736 if (FLAG_cleanup_code_caches_at_gc) { | 679 if (FLAG_cleanup_code_caches_at_gc) { |
737 PolymorphicCodeCache* poly_cache = heap_->polymorphic_code_cache(); | 680 PolymorphicCodeCache* poly_cache = heap_->polymorphic_code_cache(); |
738 Marking::GreyToBlack(Marking::MarkBitFrom(poly_cache)); | 681 Marking::GreyToBlack(Marking::MarkBitFrom(poly_cache)); |
739 MemoryChunk::IncrementLiveBytesFromGC(poly_cache->address(), | 682 MemoryChunk::IncrementLiveBytesFromGC(poly_cache->address(), |
740 PolymorphicCodeCache::kSize); | 683 PolymorphicCodeCache::kSize); |
741 } | 684 } |
742 | 685 |
743 Object* context = heap_->native_contexts_list(); | 686 Object* context = heap_->native_contexts_list(); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
844 } | 787 } |
845 | 788 |
846 if (state_ == SWEEPING) { | 789 if (state_ == SWEEPING) { |
847 if (heap_->AdvanceSweepers(static_cast<int>(bytes_to_process))) { | 790 if (heap_->AdvanceSweepers(static_cast<int>(bytes_to_process))) { |
848 bytes_scanned_ = 0; | 791 bytes_scanned_ = 0; |
849 StartMarking(PREVENT_COMPACTION); | 792 StartMarking(PREVENT_COMPACTION); |
850 } | 793 } |
851 } else if (state_ == MARKING) { | 794 } else if (state_ == MARKING) { |
852 Map* filler_map = heap_->one_pointer_filler_map(); | 795 Map* filler_map = heap_->one_pointer_filler_map(); |
853 Map* native_context_map = heap_->native_context_map(); | 796 Map* native_context_map = heap_->native_context_map(); |
854 while (true) { | 797 while (!marking_deque_.IsEmpty() && bytes_to_process > 0) { |
855 while (!marking_deque_.IsEmpty() && bytes_to_process > 0) { | 798 HeapObject* obj = marking_deque_.Pop(); |
856 HeapObject* obj = marking_deque_.Pop(); | |
857 | 799 |
858 // Explicitly skip one word fillers. Incremental markbit patterns are | 800 // Explicitly skip one word fillers. Incremental markbit patterns are |
859 // correct only for objects that occupy at least two words. | 801 // correct only for objects that occupy at least two words. |
860 Map* map = obj->map(); | 802 Map* map = obj->map(); |
861 if (map == filler_map) continue; | 803 if (map == filler_map) continue; |
862 | 804 |
863 int size = obj->SizeFromMap(map); | 805 int size = obj->SizeFromMap(map); |
864 MarkBit map_mark_bit = Marking::MarkBitFrom(map); | 806 bytes_to_process -= size; |
865 if (Marking::IsWhite(map_mark_bit)) { | 807 MarkBit map_mark_bit = Marking::MarkBitFrom(map); |
866 WhiteToGreyAndPush(map, map_mark_bit); | 808 if (Marking::IsWhite(map_mark_bit)) { |
867 } | 809 WhiteToGreyAndPush(map, map_mark_bit); |
| 810 } |
868 | 811 |
869 // TODO(gc) switch to static visitor instead of normal visitor. | 812 // TODO(gc) switch to static visitor instead of normal visitor. |
870 if (map == native_context_map) { | 813 if (map == native_context_map) { |
871 // Native contexts have weak fields. | 814 // Native contexts have weak fields. |
872 Context* ctx = Context::cast(obj); | 815 Context* ctx = Context::cast(obj); |
873 | 816 |
874 // We will mark cache black with a separate pass | 817 // We will mark cache black with a separate pass |
875 // when we finish marking. | 818 // when we finish marking. |
876 MarkObjectGreyDoNotEnqueue(ctx->normalized_map_cache()); | 819 MarkObjectGreyDoNotEnqueue(ctx->normalized_map_cache()); |
877 | 820 |
878 IncrementalMarkingMarkingVisitor::VisitNativeContext(map, ctx); | 821 IncrementalMarkingMarkingVisitor::VisitNativeContext(map, ctx); |
879 bytes_to_process -= size; | 822 } else { |
880 SLOW_ASSERT(Marking::IsGrey(Marking::MarkBitFrom(obj))); | 823 IncrementalMarkingMarkingVisitor::IterateBody(map, obj); |
881 MemoryChunk::IncrementLiveBytesFromGC(obj->address(), size); | 824 } |
882 } else if (map->instance_type() == FIXED_ARRAY_TYPE && | |
883 FixedArray::cast(obj)->length() > | |
884 IncrementalMarkingMarkingVisitor::kScanningChunk) { | |
885 SLOW_ASSERT( | |
886 Marking::IsGrey(Marking::MarkBitFrom(obj)) || | |
887 MemoryChunk::FromAddress(obj->address())->IsPartiallyScanned()); | |
888 bytes_to_process -= | |
889 IncrementalMarkingMarkingVisitor::VisitHugeArray( | |
890 FixedArray::cast(obj)); | |
891 MarkBit obj_mark_bit = Marking::MarkBitFrom(obj); | |
892 if (!Marking::IsBlack(obj_mark_bit)) { | |
893 MemoryChunk::IncrementLiveBytesFromGC(obj->address(), size); | |
894 } | |
895 } else { | |
896 IncrementalMarkingMarkingVisitor::IterateBody(map, obj); | |
897 bytes_to_process -= size; | |
898 SLOW_ASSERT( | |
899 Marking::IsGrey(Marking::MarkBitFrom(obj)) || | |
900 (obj->IsFiller() && Marking::IsWhite(Marking::MarkBitFrom(obj)))); | |
901 MemoryChunk::IncrementLiveBytesFromGC(obj->address(), size); | |
902 } | |
903 | 825 |
904 MarkBit obj_mark_bit = Marking::MarkBitFrom(obj); | 826 MarkBit obj_mark_bit = Marking::MarkBitFrom(obj); |
905 Marking::MarkBlack(obj_mark_bit); | 827 SLOW_ASSERT(Marking::IsGrey(obj_mark_bit) || |
906 } | 828 (obj->IsFiller() && Marking::IsWhite(obj_mark_bit))); |
907 if (marking_deque_.IsEmpty()) { | 829 Marking::MarkBlack(obj_mark_bit); |
908 MarkCompactCollector::ProcessLargePostponedArrays(heap_, | 830 MemoryChunk::IncrementLiveBytesFromGC(obj->address(), size); |
909 &marking_deque_); | |
910 if (marking_deque_.IsEmpty()) { | |
911 MarkingComplete(action); | |
912 break; | |
913 } | |
914 } else { | |
915 ASSERT(bytes_to_process <= 0); | |
916 break; | |
917 } | |
918 } | 831 } |
| 832 if (marking_deque_.IsEmpty()) MarkingComplete(action); |
919 } | 833 } |
920 | 834 |
921 allocated_ = 0; | 835 allocated_ = 0; |
922 | 836 |
923 steps_count_++; | 837 steps_count_++; |
924 steps_count_since_last_gc_++; | 838 steps_count_since_last_gc_++; |
925 | 839 |
926 bool speed_up = false; | 840 bool speed_up = false; |
927 | 841 |
928 if ((steps_count_ % kAllocationMarkingFactorSpeedupInterval) == 0) { | 842 if ((steps_count_ % kAllocationMarkingFactorSpeedupInterval) == 0) { |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1010 allocation_marking_factor_ = kInitialAllocationMarkingFactor; | 924 allocation_marking_factor_ = kInitialAllocationMarkingFactor; |
1011 bytes_scanned_ = 0; | 925 bytes_scanned_ = 0; |
1012 } | 926 } |
1013 | 927 |
1014 | 928 |
1015 int64_t IncrementalMarking::SpaceLeftInOldSpace() { | 929 int64_t IncrementalMarking::SpaceLeftInOldSpace() { |
1016 return heap_->MaxOldGenerationSize() - heap_->PromotedSpaceSizeOfObjects(); | 930 return heap_->MaxOldGenerationSize() - heap_->PromotedSpaceSizeOfObjects(); |
1017 } | 931 } |
1018 | 932 |
1019 } } // namespace v8::internal | 933 } } // namespace v8::internal |
OLD | NEW |