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