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