Chromium Code Reviews| 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 |