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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/double.h" | 7 #include "src/double.h" |
8 #include "src/factory.h" | 8 #include "src/factory.h" |
9 #include "src/hydrogen-infer-representation.h" | 9 #include "src/hydrogen-infer-representation.h" |
10 #include "src/property-details-inl.h" | 10 #include "src/property-details-inl.h" |
(...skipping 3739 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3750 // Check whether we are folding within the same block for local folding. | 3750 // Check whether we are folding within the same block for local folding. |
3751 if (FLAG_use_local_allocation_folding && dominator->block() != block()) { | 3751 if (FLAG_use_local_allocation_folding && dominator->block() != block()) { |
3752 if (FLAG_trace_allocation_folding) { | 3752 if (FLAG_trace_allocation_folding) { |
3753 PrintF("#%d (%s) cannot fold into #%d (%s), crosses basic blocks\n", | 3753 PrintF("#%d (%s) cannot fold into #%d (%s), crosses basic blocks\n", |
3754 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); | 3754 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); |
3755 } | 3755 } |
3756 return false; | 3756 return false; |
3757 } | 3757 } |
3758 | 3758 |
3759 HAllocate* dominator_allocate = HAllocate::cast(dominator); | 3759 HAllocate* dominator_allocate = HAllocate::cast(dominator); |
| 3760 HValue* dominator_size = dominator_allocate->size(); |
| 3761 HValue* current_size = size(); |
| 3762 |
| 3763 // TODO(hpayer): Add support for non-constant allocation in dominator. |
| 3764 if (!dominator_size->IsInteger32Constant()) { |
| 3765 if (FLAG_trace_allocation_folding) { |
| 3766 PrintF("#%d (%s) cannot fold into #%d (%s), " |
| 3767 "dynamic allocation size in dominator\n", |
| 3768 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); |
| 3769 } |
| 3770 return false; |
| 3771 } |
3760 | 3772 |
3761 dominator_allocate = GetFoldableDominator(dominator_allocate); | 3773 dominator_allocate = GetFoldableDominator(dominator_allocate); |
3762 if (dominator_allocate == NULL) { | 3774 if (dominator_allocate == NULL) { |
3763 return false; | 3775 return false; |
3764 } | 3776 } |
3765 | 3777 |
3766 if (!has_size_upper_bound() || !dominator_allocate->has_size_upper_bound()) { | 3778 if (!has_size_upper_bound()) { |
3767 if (FLAG_trace_allocation_folding) { | 3779 if (FLAG_trace_allocation_folding) { |
3768 PrintF("#%d (%s) cannot fold into #%d (%s), " | 3780 PrintF("#%d (%s) cannot fold into #%d (%s), " |
3769 "can't estimate total allocation size\n", | 3781 "can't estimate total allocation size\n", |
3770 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); | 3782 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); |
3771 } | 3783 } |
3772 return false; | 3784 return false; |
3773 } | 3785 } |
3774 | 3786 |
3775 HValue* dominator_size = dominator_allocate->size(); | |
3776 // TODO(ishell): support folding of dynamic size allocation with | |
3777 // double aligned allocation. | |
3778 if (!dominator_size->IsInteger32Constant() && MustAllocateDoubleAligned()) { | |
3779 if (FLAG_trace_allocation_folding) { | |
3780 PrintF("#%d (%s) cannot fold into #%d (%s), dynamic size " | |
3781 "in dominator and double aligned requirement\n", | |
3782 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); | |
3783 } | |
3784 return false; | |
3785 } | |
3786 | |
3787 HValue* current_size = size(); | |
3788 if (!current_size->IsInteger32Constant()) { | 3787 if (!current_size->IsInteger32Constant()) { |
3789 // If it's not constant then it is a size_in_bytes calculation graph | 3788 // If it's not constant then it is a size_in_bytes calculation graph |
3790 // like this: (const_header_size + const_element_size * size). | 3789 // like this: (const_header_size + const_element_size * size). |
3791 ASSERT(current_size->IsInstruction()); | 3790 ASSERT(current_size->IsInstruction()); |
3792 | 3791 |
3793 HInstruction* current_instr = HInstruction::cast(current_size); | 3792 HInstruction* current_instr = HInstruction::cast(current_size); |
3794 if (!current_instr->Dominates(dominator_allocate)) { | 3793 if (!current_instr->Dominates(dominator_allocate)) { |
3795 if (FLAG_trace_allocation_folding) { | 3794 if (FLAG_trace_allocation_folding) { |
3796 PrintF("#%d (%s) cannot fold into #%d (%s), dynamic size " | 3795 PrintF("#%d (%s) cannot fold into #%d (%s), dynamic size " |
3797 "value does not dominate target allocation\n", | 3796 "value does not dominate target allocation\n", |
3798 id(), Mnemonic(), dominator_allocate->id(), | 3797 id(), Mnemonic(), dominator_allocate->id(), |
3799 dominator_allocate->Mnemonic()); | 3798 dominator_allocate->Mnemonic()); |
3800 } | 3799 } |
3801 return false; | 3800 return false; |
3802 } | 3801 } |
3803 } | 3802 } |
3804 | 3803 |
3805 ASSERT((IsNewSpaceAllocation() && | 3804 ASSERT((IsNewSpaceAllocation() && |
3806 dominator_allocate->IsNewSpaceAllocation()) || | 3805 dominator_allocate->IsNewSpaceAllocation()) || |
3807 (IsOldDataSpaceAllocation() && | 3806 (IsOldDataSpaceAllocation() && |
3808 dominator_allocate->IsOldDataSpaceAllocation()) || | 3807 dominator_allocate->IsOldDataSpaceAllocation()) || |
3809 (IsOldPointerSpaceAllocation() && | 3808 (IsOldPointerSpaceAllocation() && |
3810 dominator_allocate->IsOldPointerSpaceAllocation())); | 3809 dominator_allocate->IsOldPointerSpaceAllocation())); |
3811 | 3810 |
3812 // First update the size and size upper bound of the dominator allocate | 3811 // First update the size of the dominator allocate instruction. |
3813 // instruction. | 3812 dominator_size = dominator_allocate->size(); |
3814 int32_t dominator_size_upper_bound_value = | 3813 int32_t original_object_size = |
3815 dominator_allocate->size_upper_bound()->GetInteger32Constant(); | 3814 HConstant::cast(dominator_size)->GetInteger32Constant(); |
| 3815 int32_t dominator_size_constant = original_object_size; |
3816 | 3816 |
3817 if (MustAllocateDoubleAligned()) { | 3817 if (MustAllocateDoubleAligned()) { |
3818 if ((dominator_size_upper_bound_value & kDoubleAlignmentMask) != 0) { | 3818 if ((dominator_size_constant & kDoubleAlignmentMask) != 0) { |
3819 dominator_size_upper_bound_value += kDoubleSize / 2; | 3819 dominator_size_constant += kDoubleSize / 2; |
3820 } | 3820 } |
3821 } | 3821 } |
3822 | 3822 |
3823 int32_t new_dominator_size_upper_bound_value = | 3823 int32_t current_size_max_value = size_upper_bound()->GetInteger32Constant(); |
3824 dominator_size_upper_bound_value + | 3824 int32_t new_dominator_size = dominator_size_constant + current_size_max_value; |
3825 size_upper_bound()->GetInteger32Constant(); | |
3826 | 3825 |
3827 // Since we clear the first word after folded memory, we cannot use the | 3826 // Since we clear the first word after folded memory, we cannot use the |
3828 // whole Page::kMaxRegularHeapObjectSize memory. | 3827 // whole Page::kMaxRegularHeapObjectSize memory. |
3829 if (new_dominator_size_upper_bound_value > | 3828 if (new_dominator_size > Page::kMaxRegularHeapObjectSize - kPointerSize) { |
3830 Page::kMaxRegularHeapObjectSize - kPointerSize) { | |
3831 if (FLAG_trace_allocation_folding) { | 3829 if (FLAG_trace_allocation_folding) { |
3832 PrintF("#%d (%s) cannot fold into #%d (%s) due to size: %d\n", | 3830 PrintF("#%d (%s) cannot fold into #%d (%s) due to size: %d\n", |
3833 id(), Mnemonic(), dominator_allocate->id(), | 3831 id(), Mnemonic(), dominator_allocate->id(), |
3834 dominator_allocate->Mnemonic(), new_dominator_size_upper_bound_value); | 3832 dominator_allocate->Mnemonic(), new_dominator_size); |
3835 } | 3833 } |
3836 return false; | 3834 return false; |
3837 } | 3835 } |
3838 | 3836 |
3839 HValue* aligned_dominator_size; | 3837 HInstruction* new_dominator_size_value; |
3840 if (dominator_size->IsInteger32Constant()) { | 3838 |
3841 aligned_dominator_size = | 3839 if (current_size->IsInteger32Constant()) { |
| 3840 new_dominator_size_value = |
3842 HConstant::CreateAndInsertBefore(zone, | 3841 HConstant::CreateAndInsertBefore(zone, |
3843 context(), | 3842 context(), |
3844 dominator_size_upper_bound_value, | 3843 new_dominator_size, |
| 3844 Representation::None(), |
| 3845 dominator_allocate); |
| 3846 } else { |
| 3847 HValue* new_dominator_size_constant = |
| 3848 HConstant::CreateAndInsertBefore(zone, |
| 3849 context(), |
| 3850 dominator_size_constant, |
3845 Representation::Integer32(), | 3851 Representation::Integer32(), |
3846 dominator_allocate); | 3852 dominator_allocate); |
3847 | 3853 |
3848 } else { | 3854 // Add old and new size together and insert. |
3849 aligned_dominator_size = dominator_size; | 3855 current_size->ChangeRepresentation(Representation::Integer32()); |
| 3856 |
| 3857 new_dominator_size_value = HAdd::New(zone, context(), |
| 3858 new_dominator_size_constant, current_size); |
| 3859 new_dominator_size_value->ClearFlag(HValue::kCanOverflow); |
| 3860 new_dominator_size_value->ChangeRepresentation(Representation::Integer32()); |
| 3861 |
| 3862 new_dominator_size_value->InsertBefore(dominator_allocate); |
3850 } | 3863 } |
3851 | 3864 |
3852 HConstant* new_dominator_size_upper_bound = | 3865 dominator_allocate->UpdateSize(new_dominator_size_value); |
3853 HConstant::CreateAndInsertBefore(zone, | |
3854 context(), | |
3855 new_dominator_size_upper_bound_value, | |
3856 Representation::None(), | |
3857 dominator_allocate); | |
3858 | |
3859 HInstruction* new_dominator_size; | |
3860 if (current_size->IsInteger32Constant() && | |
3861 dominator_size->IsInteger32Constant()) { | |
3862 new_dominator_size = new_dominator_size_upper_bound; | |
3863 | |
3864 } else { | |
3865 // Add old and new size together and insert. | |
3866 if (current_size->IsInteger32Constant()) { | |
3867 // Create a copy of constant and put it into the right place | |
3868 current_size = | |
3869 HConstant::CreateAndInsertBefore(zone, | |
3870 context(), | |
3871 current_size->GetInteger32Constant(), | |
3872 Representation::Integer32(), | |
3873 dominator_allocate); | |
3874 } else { | |
3875 current_size->ChangeRepresentation(Representation::Integer32()); | |
3876 } | |
3877 | |
3878 new_dominator_size = HAdd::New(zone, context(), | |
3879 aligned_dominator_size, current_size); | |
3880 new_dominator_size->ClearFlag(HValue::kCanOverflow); | |
3881 new_dominator_size->ChangeRepresentation(Representation::Integer32()); | |
3882 | |
3883 new_dominator_size->InsertBefore(dominator_allocate); | |
3884 } | |
3885 | |
3886 dominator_allocate->UpdateSize(new_dominator_size, | |
3887 new_dominator_size_upper_bound); | |
3888 | 3866 |
3889 if (MustAllocateDoubleAligned()) { | 3867 if (MustAllocateDoubleAligned()) { |
3890 if (!dominator_allocate->MustAllocateDoubleAligned()) { | 3868 if (!dominator_allocate->MustAllocateDoubleAligned()) { |
3891 dominator_allocate->MakeDoubleAligned(); | 3869 dominator_allocate->MakeDoubleAligned(); |
3892 } | 3870 } |
3893 } | 3871 } |
3894 | 3872 |
3895 bool keep_new_space_iterable = FLAG_log_gc || FLAG_heap_stats; | 3873 bool keep_new_space_iterable = FLAG_log_gc || FLAG_heap_stats; |
3896 #ifdef VERIFY_HEAP | 3874 #ifdef VERIFY_HEAP |
3897 keep_new_space_iterable = keep_new_space_iterable || FLAG_verify_heap; | 3875 keep_new_space_iterable = keep_new_space_iterable || FLAG_verify_heap; |
3898 #endif | 3876 #endif |
3899 | 3877 |
3900 if (keep_new_space_iterable && dominator_allocate->IsNewSpaceAllocation()) { | 3878 if (keep_new_space_iterable && dominator_allocate->IsNewSpaceAllocation()) { |
3901 dominator_allocate->MakePrefillWithFiller(); | 3879 dominator_allocate->MakePrefillWithFiller(); |
3902 } else { | 3880 } else { |
3903 // TODO(hpayer): This is a short-term hack to make allocation mementos | 3881 // TODO(hpayer): This is a short-term hack to make allocation mementos |
3904 // work again in new space. | 3882 // work again in new space. |
3905 dominator_allocate->ClearNextMapWord(dominator_size); | 3883 dominator_allocate->ClearNextMapWord(original_object_size); |
3906 } | 3884 } |
3907 | 3885 |
3908 dominator_allocate->UpdateClearNextMapWord(MustClearNextMapWord()); | 3886 dominator_allocate->UpdateClearNextMapWord(MustClearNextMapWord()); |
3909 | 3887 |
3910 // After that replace the dominated allocate instruction. | 3888 // After that replace the dominated allocate instruction. |
| 3889 HInstruction* inner_offset = HConstant::CreateAndInsertBefore( |
| 3890 zone, |
| 3891 context(), |
| 3892 dominator_size_constant, |
| 3893 Representation::None(), |
| 3894 this); |
| 3895 |
3911 HInstruction* dominated_allocate_instr = | 3896 HInstruction* dominated_allocate_instr = |
3912 HInnerAllocatedObject::New(zone, | 3897 HInnerAllocatedObject::New(zone, |
3913 context(), | 3898 context(), |
3914 dominator_allocate, | 3899 dominator_allocate, |
3915 aligned_dominator_size, | 3900 inner_offset, |
3916 type()); | 3901 type()); |
3917 dominated_allocate_instr->InsertBefore(this); | 3902 dominated_allocate_instr->InsertBefore(this); |
3918 DeleteAndReplaceWith(dominated_allocate_instr); | 3903 DeleteAndReplaceWith(dominated_allocate_instr); |
3919 if (FLAG_trace_allocation_folding) { | 3904 if (FLAG_trace_allocation_folding) { |
3920 PrintF("#%d (%s) folded into #%d (%s)\n", | 3905 PrintF("#%d (%s) folded into #%d (%s)\n", |
3921 id(), Mnemonic(), dominator_allocate->id(), | 3906 id(), Mnemonic(), dominator_allocate->id(), |
3922 dominator_allocate->Mnemonic()); | 3907 dominator_allocate->Mnemonic()); |
3923 } | 3908 } |
3924 return true; | 3909 return true; |
3925 } | 3910 } |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4032 FreeSpace::kSizeOffset, | 4017 FreeSpace::kSizeOffset, |
4033 Representation::Smi()); | 4018 Representation::Smi()); |
4034 HStoreNamedField* store_size = HStoreNamedField::New(zone, context(), | 4019 HStoreNamedField* store_size = HStoreNamedField::New(zone, context(), |
4035 free_space_instr, access, filler_size); | 4020 free_space_instr, access, filler_size); |
4036 store_size->SetFlag(HValue::kHasNoObservableSideEffects); | 4021 store_size->SetFlag(HValue::kHasNoObservableSideEffects); |
4037 store_size->InsertAfter(filler_size); | 4022 store_size->InsertAfter(filler_size); |
4038 filler_free_space_size_ = store_size; | 4023 filler_free_space_size_ = store_size; |
4039 } | 4024 } |
4040 | 4025 |
4041 | 4026 |
4042 void HAllocate::ClearNextMapWord(HValue* offset) { | 4027 void HAllocate::ClearNextMapWord(int offset) { |
4043 if (MustClearNextMapWord()) { | 4028 if (MustClearNextMapWord()) { |
4044 Zone* zone = block()->zone(); | 4029 Zone* zone = block()->zone(); |
4045 | 4030 HObjectAccess access = |
4046 HInstruction* clear_next_map; | 4031 HObjectAccess::ForObservableJSObjectOffset(offset); |
4047 if (offset->IsInteger32Constant()) { | 4032 HStoreNamedField* clear_next_map = |
4048 int offset_value = HConstant::cast(offset)->GetInteger32Constant(); | 4033 HStoreNamedField::New(zone, context(), this, access, |
4049 HObjectAccess access = | 4034 block()->graph()->GetConstant0()); |
4050 HObjectAccess::ForObservableJSObjectOffset(offset_value); | |
4051 clear_next_map = | |
4052 HStoreNamedField::New(zone, context(), this, access, | |
4053 block()->graph()->GetConstant0()); | |
4054 } else { | |
4055 clear_next_map = | |
4056 HStoreKeyed::New(zone, context(), | |
4057 this, offset, | |
4058 block()->graph()->GetConstant0(), | |
4059 FAST_HOLEY_SMI_ELEMENTS); | |
4060 } | |
4061 clear_next_map->ClearAllSideEffects(); | 4035 clear_next_map->ClearAllSideEffects(); |
4062 clear_next_map->InsertAfter(this); | 4036 clear_next_map->InsertAfter(this); |
4063 } | 4037 } |
4064 } | 4038 } |
4065 | 4039 |
4066 | 4040 |
4067 void HAllocate::PrintDataTo(StringStream* stream) { | 4041 void HAllocate::PrintDataTo(StringStream* stream) { |
4068 size()->PrintNameTo(stream); | 4042 size()->PrintNameTo(stream); |
4069 stream->Add(" ("); | 4043 stream->Add(" ("); |
4070 if (IsNewSpaceAllocation()) stream->Add("N"); | 4044 if (IsNewSpaceAllocation()) stream->Add("N"); |
(...skipping 782 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4853 break; | 4827 break; |
4854 case kExternalMemory: | 4828 case kExternalMemory: |
4855 stream->Add("[external-memory]"); | 4829 stream->Add("[external-memory]"); |
4856 break; | 4830 break; |
4857 } | 4831 } |
4858 | 4832 |
4859 stream->Add("@%d", offset()); | 4833 stream->Add("@%d", offset()); |
4860 } | 4834 } |
4861 | 4835 |
4862 } } // namespace v8::internal | 4836 } } // namespace v8::internal |
OLD | NEW |