OLD | NEW |
---|---|
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 18 matching lines...) Expand all Loading... | |
29 | 29 |
30 #include "macro-assembler.h" | 30 #include "macro-assembler.h" |
31 #include "mark-compact.h" | 31 #include "mark-compact.h" |
32 #include "platform.h" | 32 #include "platform.h" |
33 | 33 |
34 namespace v8 { namespace internal { | 34 namespace v8 { namespace internal { |
35 | 35 |
36 // For contiguous spaces, top should be in the space (or at the end) and limit | 36 // For contiguous spaces, top should be in the space (or at the end) and limit |
37 // should be the end of the space. | 37 // should be the end of the space. |
38 #define ASSERT_SEMISPACE_ALLOCATION_INFO(info, space) \ | 38 #define ASSERT_SEMISPACE_ALLOCATION_INFO(info, space) \ |
39 ASSERT((space)->low() <= (info).top \ | 39 ASSERT((space).low() <= (info).top \ |
40 && (info).top <= (space)->high() \ | 40 && (info).top <= (space).high() \ |
41 && (info).limit == (space)->high()) | 41 && (info).limit == (space).high()) |
42 | 42 |
43 | 43 |
44 // ---------------------------------------------------------------------------- | 44 // ---------------------------------------------------------------------------- |
45 // HeapObjectIterator | 45 // HeapObjectIterator |
46 | 46 |
47 HeapObjectIterator::HeapObjectIterator(PagedSpace* space) { | 47 HeapObjectIterator::HeapObjectIterator(PagedSpace* space) { |
48 Initialize(space->bottom(), space->top(), NULL); | 48 Initialize(space->bottom(), space->top(), NULL); |
49 } | 49 } |
50 | 50 |
51 | 51 |
(...skipping 701 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
753 | 753 |
754 | 754 |
755 #ifdef DEBUG | 755 #ifdef DEBUG |
756 void PagedSpace::Print() { } | 756 void PagedSpace::Print() { } |
757 #endif | 757 #endif |
758 | 758 |
759 | 759 |
760 // ----------------------------------------------------------------------------- | 760 // ----------------------------------------------------------------------------- |
761 // NewSpace implementation | 761 // NewSpace implementation |
762 | 762 |
763 NewSpace::NewSpace(int initial_semispace_capacity, | 763 |
764 int maximum_semispace_capacity, | 764 bool NewSpace::Setup(Address start, int size) { |
765 AllocationSpace id) | 765 // Create a new space with a given allocation capacity (ie, the capacity of |
Kevin Millikin (Chromium)
2008/10/17 09:02:41
The comment is confusing because the capacity is n
| |
766 : Space(id, NOT_EXECUTABLE) { | 766 // *one* of the semispaces). The constructor does not allocate heap memory |
767 // from the OS. When the space is set up, it is given a contiguous chunk of | |
768 // memory of size 2 * semispace_capacity. To support fast containment | |
769 // testing in the new space, the size of this chunk must be a power of two | |
770 // and it must be aligned to its size. | |
771 int initial_semispace_capacity = Heap::InitialSemiSpaceSize(); | |
772 int maximum_semispace_capacity = Heap::SemiSpaceSize(); | |
773 | |
767 ASSERT(initial_semispace_capacity <= maximum_semispace_capacity); | 774 ASSERT(initial_semispace_capacity <= maximum_semispace_capacity); |
768 ASSERT(IsPowerOf2(maximum_semispace_capacity)); | 775 ASSERT(IsPowerOf2(maximum_semispace_capacity)); |
769 maximum_capacity_ = maximum_semispace_capacity; | 776 maximum_capacity_ = maximum_semispace_capacity; |
770 capacity_ = initial_semispace_capacity; | 777 capacity_ = initial_semispace_capacity; |
771 to_space_ = new SemiSpace(capacity_, maximum_capacity_, id); | |
772 from_space_ = new SemiSpace(capacity_, maximum_capacity_, id); | |
773 | 778 |
774 // Allocate and setup the histogram arrays if necessary. | 779 // Allocate and setup the histogram arrays if necessary. |
775 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) | 780 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) |
776 allocated_histogram_ = NewArray<HistogramInfo>(LAST_TYPE + 1); | 781 allocated_histogram_ = NewArray<HistogramInfo>(LAST_TYPE + 1); |
777 promoted_histogram_ = NewArray<HistogramInfo>(LAST_TYPE + 1); | 782 promoted_histogram_ = NewArray<HistogramInfo>(LAST_TYPE + 1); |
778 | 783 |
779 #define SET_NAME(name) allocated_histogram_[name].set_name(#name); \ | 784 #define SET_NAME(name) allocated_histogram_[name].set_name(#name); \ |
780 promoted_histogram_[name].set_name(#name); | 785 promoted_histogram_[name].set_name(#name); |
781 INSTANCE_TYPE_LIST(SET_NAME) | 786 INSTANCE_TYPE_LIST(SET_NAME) |
782 #undef SET_NAME | 787 #undef SET_NAME |
783 #endif | 788 #endif |
784 } | |
785 | 789 |
786 | 790 |
787 bool NewSpace::Setup(Address start, int size) { | |
788 ASSERT(size == 2 * maximum_capacity_); | 791 ASSERT(size == 2 * maximum_capacity_); |
789 ASSERT(IsAddressAligned(start, size, 0)); | 792 ASSERT(IsAddressAligned(start, size, 0)); |
790 | 793 |
791 if (to_space_ == NULL | 794 if (!to_space_.Setup(start, capacity_, maximum_capacity_)) { |
792 || !to_space_->Setup(start, maximum_capacity_)) { | |
793 return false; | 795 return false; |
794 } | 796 } |
795 if (from_space_ == NULL | 797 if (!from_space_.Setup(start + maximum_capacity_, capacity_, maximum_capacity_ )) { |
796 || !from_space_->Setup(start + maximum_capacity_, maximum_capacity_)) { | |
797 return false; | 798 return false; |
798 } | 799 } |
799 | 800 |
800 start_ = start; | 801 start_ = start; |
801 address_mask_ = ~(size - 1); | 802 address_mask_ = ~(size - 1); |
802 object_mask_ = address_mask_ | kHeapObjectTag; | 803 object_mask_ = address_mask_ | kHeapObjectTag; |
803 object_expected_ = reinterpret_cast<uint32_t>(start) | kHeapObjectTag; | 804 object_expected_ = reinterpret_cast<uint32_t>(start) | kHeapObjectTag; |
804 | 805 |
805 allocation_info_.top = to_space_->low(); | 806 allocation_info_.top = to_space_.low(); |
806 allocation_info_.limit = to_space_->high(); | 807 allocation_info_.limit = to_space_.high(); |
807 mc_forwarding_info_.top = NULL; | 808 mc_forwarding_info_.top = NULL; |
808 mc_forwarding_info_.limit = NULL; | 809 mc_forwarding_info_.limit = NULL; |
809 | 810 |
810 ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); | 811 ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); |
811 return true; | 812 return true; |
812 } | 813 } |
813 | 814 |
814 | 815 |
815 void NewSpace::TearDown() { | 816 void NewSpace::TearDown() { |
816 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) | 817 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) |
817 if (allocated_histogram_) { | 818 if (allocated_histogram_) { |
818 DeleteArray(allocated_histogram_); | 819 DeleteArray(allocated_histogram_); |
819 allocated_histogram_ = NULL; | 820 allocated_histogram_ = NULL; |
820 } | 821 } |
821 if (promoted_histogram_) { | 822 if (promoted_histogram_) { |
822 DeleteArray(promoted_histogram_); | 823 DeleteArray(promoted_histogram_); |
823 promoted_histogram_ = NULL; | 824 promoted_histogram_ = NULL; |
824 } | 825 } |
825 #endif | 826 #endif |
826 | 827 |
827 start_ = NULL; | 828 start_ = NULL; |
828 capacity_ = 0; | 829 capacity_ = 0; |
829 allocation_info_.top = NULL; | 830 allocation_info_.top = NULL; |
830 allocation_info_.limit = NULL; | 831 allocation_info_.limit = NULL; |
831 mc_forwarding_info_.top = NULL; | 832 mc_forwarding_info_.top = NULL; |
832 mc_forwarding_info_.limit = NULL; | 833 mc_forwarding_info_.limit = NULL; |
833 | 834 |
834 if (to_space_ != NULL) { | 835 to_space_.TearDown(); |
835 to_space_->TearDown(); | 836 from_space_.TearDown(); |
836 delete to_space_; | |
837 to_space_ = NULL; | |
838 } | |
839 | |
840 if (from_space_ != NULL) { | |
841 from_space_->TearDown(); | |
842 delete from_space_; | |
843 from_space_ = NULL; | |
844 } | |
845 } | 837 } |
846 | 838 |
847 | 839 |
848 void NewSpace::Flip() { | 840 void NewSpace::Flip() { |
849 SemiSpace* tmp = from_space_; | 841 SemiSpace tmp = from_space_; |
850 from_space_ = to_space_; | 842 from_space_ = to_space_; |
851 to_space_ = tmp; | 843 to_space_ = tmp; |
852 } | 844 } |
853 | 845 |
854 | 846 |
855 bool NewSpace::Double() { | 847 bool NewSpace::Double() { |
856 ASSERT(capacity_ <= maximum_capacity_ / 2); | 848 ASSERT(capacity_ <= maximum_capacity_ / 2); |
857 // TODO(1240712): Failure to double the from space can result in | 849 // TODO(1240712): Failure to double the from space can result in |
858 // semispaces of different sizes. In the event of that failure, the | 850 // semispaces of different sizes. In the event of that failure, the |
859 // to space doubling should be rolled back before returning false. | 851 // to space doubling should be rolled back before returning false. |
860 if (!to_space_->Double() || !from_space_->Double()) return false; | 852 if (!to_space_.Double() || !from_space_.Double()) return false; |
861 capacity_ *= 2; | 853 capacity_ *= 2; |
862 allocation_info_.limit = to_space_->high(); | 854 allocation_info_.limit = to_space_.high(); |
863 ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); | 855 ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); |
864 return true; | 856 return true; |
865 } | 857 } |
866 | 858 |
867 | 859 |
868 void NewSpace::ResetAllocationInfo() { | 860 void NewSpace::ResetAllocationInfo() { |
869 allocation_info_.top = to_space_->low(); | 861 allocation_info_.top = to_space_.low(); |
870 allocation_info_.limit = to_space_->high(); | 862 allocation_info_.limit = to_space_.high(); |
871 ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); | 863 ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); |
872 } | 864 } |
873 | 865 |
874 | 866 |
875 void NewSpace::MCResetRelocationInfo() { | 867 void NewSpace::MCResetRelocationInfo() { |
876 mc_forwarding_info_.top = from_space_->low(); | 868 mc_forwarding_info_.top = from_space_.low(); |
877 mc_forwarding_info_.limit = from_space_->high(); | 869 mc_forwarding_info_.limit = from_space_.high(); |
878 ASSERT_SEMISPACE_ALLOCATION_INFO(mc_forwarding_info_, from_space_); | 870 ASSERT_SEMISPACE_ALLOCATION_INFO(mc_forwarding_info_, from_space_); |
879 } | 871 } |
880 | 872 |
881 | 873 |
882 void NewSpace::MCCommitRelocationInfo() { | 874 void NewSpace::MCCommitRelocationInfo() { |
883 // Assumes that the spaces have been flipped so that mc_forwarding_info_ is | 875 // Assumes that the spaces have been flipped so that mc_forwarding_info_ is |
884 // valid allocation info for the to space. | 876 // valid allocation info for the to space. |
885 allocation_info_.top = mc_forwarding_info_.top; | 877 allocation_info_.top = mc_forwarding_info_.top; |
886 allocation_info_.limit = to_space_->high(); | 878 allocation_info_.limit = to_space_.high(); |
887 ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); | 879 ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); |
888 } | 880 } |
889 | 881 |
890 | 882 |
891 #ifdef DEBUG | 883 #ifdef DEBUG |
892 // We do not use the SemispaceIterator because verification doesn't assume | 884 // We do not use the SemispaceIterator because verification doesn't assume |
893 // that it works (it depends on the invariants we are checking). | 885 // that it works (it depends on the invariants we are checking). |
894 void NewSpace::Verify() { | 886 void NewSpace::Verify() { |
895 // The allocation pointer should be in the space or at the very end. | 887 // The allocation pointer should be in the space or at the very end. |
896 ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); | 888 ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); |
897 | 889 |
898 // There should be objects packed in from the low address up to the | 890 // There should be objects packed in from the low address up to the |
899 // allocation pointer. | 891 // allocation pointer. |
900 Address current = to_space_->low(); | 892 Address current = to_space_.low(); |
901 while (current < top()) { | 893 while (current < top()) { |
902 HeapObject* object = HeapObject::FromAddress(current); | 894 HeapObject* object = HeapObject::FromAddress(current); |
903 | 895 |
904 // The first word should be a map, and we expect all map pointers to | 896 // The first word should be a map, and we expect all map pointers to |
905 // be in map space. | 897 // be in map space. |
906 Map* map = object->map(); | 898 Map* map = object->map(); |
907 ASSERT(map->IsMap()); | 899 ASSERT(map->IsMap()); |
908 ASSERT(Heap::map_space()->Contains(map)); | 900 ASSERT(Heap::map_space()->Contains(map)); |
909 | 901 |
910 // The object should not be code or a map. | 902 // The object should not be code or a map. |
(...skipping 13 matching lines...) Expand all Loading... | |
924 | 916 |
925 // The allocation pointer should not be in the middle of an object. | 917 // The allocation pointer should not be in the middle of an object. |
926 ASSERT(current == top()); | 918 ASSERT(current == top()); |
927 } | 919 } |
928 #endif | 920 #endif |
929 | 921 |
930 | 922 |
931 // ----------------------------------------------------------------------------- | 923 // ----------------------------------------------------------------------------- |
932 // SemiSpace implementation | 924 // SemiSpace implementation |
933 | 925 |
934 SemiSpace::SemiSpace(int initial_capacity, | 926 bool SemiSpace::Setup(Address start, int initial_capacity, int maximum_capacity) { |
935 int maximum_capacity, | 927 // Creates a space in the young generation. The constructor does not |
936 AllocationSpace id) | 928 // allocate memory from the OS. A SemiSpace is given a contiguous chunk of |
937 : Space(id, NOT_EXECUTABLE), capacity_(initial_capacity), | 929 // memory of size 'capacity' when set up, and does not grow or shrink |
938 maximum_capacity_(maximum_capacity), start_(NULL), age_mark_(NULL) { | 930 // otherwise. In the mark-compact collector, the memory region of the from |
939 } | 931 // space is used as the marking stack. It requires contiguous memory |
932 // addresses. | |
933 capacity_ = initial_capacity; | |
934 maximum_capacity_ = maximum_capacity; | |
940 | 935 |
941 | 936 if (!MemoryAllocator::CommitBlock(start, capacity_, executable())) return fals e; |
942 bool SemiSpace::Setup(Address start, int size) { | |
943 ASSERT(size == maximum_capacity_); | |
944 if (!MemoryAllocator::CommitBlock(start, capacity_, executable())) { | |
945 return false; | |
946 } | |
947 | 937 |
948 start_ = start; | 938 start_ = start; |
949 address_mask_ = ~(size - 1); | 939 address_mask_ = ~(maximum_capacity - 1); |
950 object_mask_ = address_mask_ | kHeapObjectTag; | 940 object_mask_ = address_mask_ | kHeapObjectTag; |
951 object_expected_ = reinterpret_cast<uint32_t>(start) | kHeapObjectTag; | 941 object_expected_ = reinterpret_cast<uint32_t>(start) | kHeapObjectTag; |
952 | 942 |
953 age_mark_ = start_; | 943 age_mark_ = start_; |
954 return true; | 944 return true; |
955 } | 945 } |
956 | 946 |
957 | 947 |
958 void SemiSpace::TearDown() { | 948 void SemiSpace::TearDown() { |
959 start_ = NULL; | 949 start_ = NULL; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
995 Initialize(space, start, space->top(), NULL); | 985 Initialize(space, start, space->top(), NULL); |
996 } | 986 } |
997 | 987 |
998 | 988 |
999 void SemiSpaceIterator::Initialize(NewSpace* space, Address start, | 989 void SemiSpaceIterator::Initialize(NewSpace* space, Address start, |
1000 Address end, | 990 Address end, |
1001 HeapObjectCallback size_func) { | 991 HeapObjectCallback size_func) { |
1002 ASSERT(space->ToSpaceContains(start)); | 992 ASSERT(space->ToSpaceContains(start)); |
1003 ASSERT(space->ToSpaceLow() <= end | 993 ASSERT(space->ToSpaceLow() <= end |
1004 && end <= space->ToSpaceHigh()); | 994 && end <= space->ToSpaceHigh()); |
1005 space_ = space->to_space_; | 995 space_ = &space->to_space_; |
1006 current_ = start; | 996 current_ = start; |
1007 limit_ = end; | 997 limit_ = end; |
1008 size_func_ = size_func; | 998 size_func_ = size_func; |
1009 } | 999 } |
1010 | 1000 |
1011 | 1001 |
1012 #ifdef DEBUG | 1002 #ifdef DEBUG |
1013 // A static array of histogram info for each type. | 1003 // A static array of histogram info for each type. |
1014 static HistogramInfo heap_histograms[LAST_TYPE+1]; | 1004 static HistogramInfo heap_histograms[LAST_TYPE+1]; |
1015 static JSObject::SpillInformation js_spill_information; | 1005 static JSObject::SpillInformation js_spill_information; |
(...skipping 1509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2525 reinterpret_cast<Object**>(object->address() | 2515 reinterpret_cast<Object**>(object->address() |
2526 + Page::kObjectAreaSize), | 2516 + Page::kObjectAreaSize), |
2527 allocation_top); | 2517 allocation_top); |
2528 PrintF("\n"); | 2518 PrintF("\n"); |
2529 } | 2519 } |
2530 } | 2520 } |
2531 } | 2521 } |
2532 #endif // DEBUG | 2522 #endif // DEBUG |
2533 | 2523 |
2534 } } // namespace v8::internal | 2524 } } // namespace v8::internal |
OLD | NEW |