OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/flow_graph_optimizer.h" | 5 #include "vm/flow_graph_optimizer.h" |
6 | 6 |
7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
9 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 1613 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1624 if (!ShouldInlineSimd()) { | 1624 if (!ShouldInlineSimd()) { |
1625 return false; | 1625 return false; |
1626 } | 1626 } |
1627 return InlineByteArrayViewStore(target, call, receiver, receiver_cid, | 1627 return InlineByteArrayViewStore(target, call, receiver, receiver_cid, |
1628 kTypedDataInt32x4ArrayCid, | 1628 kTypedDataInt32x4ArrayCid, |
1629 ic_data, entry, last); | 1629 ic_data, entry, last); |
1630 case MethodRecognizer::kStringBaseCodeUnitAt: | 1630 case MethodRecognizer::kStringBaseCodeUnitAt: |
1631 return InlineStringCodeUnitAt(call, receiver_cid, entry, last); | 1631 return InlineStringCodeUnitAt(call, receiver_cid, entry, last); |
1632 case MethodRecognizer::kStringBaseCharAt: | 1632 case MethodRecognizer::kStringBaseCharAt: |
1633 return InlineStringBaseCharAt(call, receiver_cid, entry, last); | 1633 return InlineStringBaseCharAt(call, receiver_cid, entry, last); |
1634 case MethodRecognizer::kOneByteString_oneCodeUnitAt: | |
1635 case MethodRecognizer::kTwoByteString_oneCodeUnitAt: | |
1636 return InlineStringCodeUnitsAt(call, receiver_cid, 1, entry, last); | |
1637 case MethodRecognizer::kOneByteString_twoCodeUnitsAt: | |
1638 case MethodRecognizer::kTwoByteString_twoCodeUnitsAt: | |
1639 return InlineStringCodeUnitsAt(call, receiver_cid, 2, entry, last); | |
1640 case MethodRecognizer::kOneByteString_fourCodeUnitsAt: | |
1641 return InlineStringCodeUnitsAt(call, receiver_cid, 4, entry, last); | |
1634 case MethodRecognizer::kDoubleAdd: | 1642 case MethodRecognizer::kDoubleAdd: |
1635 return InlineDoubleOp(Token::kADD, call, entry, last); | 1643 return InlineDoubleOp(Token::kADD, call, entry, last); |
1636 case MethodRecognizer::kDoubleSub: | 1644 case MethodRecognizer::kDoubleSub: |
1637 return InlineDoubleOp(Token::kSUB, call, entry, last); | 1645 return InlineDoubleOp(Token::kSUB, call, entry, last); |
1638 case MethodRecognizer::kDoubleMul: | 1646 case MethodRecognizer::kDoubleMul: |
1639 return InlineDoubleOp(Token::kMUL, call, entry, last); | 1647 return InlineDoubleOp(Token::kMUL, call, entry, last); |
1640 case MethodRecognizer::kDoubleDiv: | 1648 case MethodRecognizer::kDoubleDiv: |
1641 return InlineDoubleOp(Token::kDIV, call, entry, last); | 1649 return InlineDoubleOp(Token::kDIV, call, entry, last); |
1642 default: | 1650 default: |
1643 return false; | 1651 return false; |
(...skipping 1189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2833 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(), | 2841 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(), |
2834 call->GetBlock()->try_index()); | 2842 call->GetBlock()->try_index()); |
2835 (*entry)->InheritDeoptTarget(I, call); | 2843 (*entry)->InheritDeoptTarget(I, call); |
2836 | 2844 |
2837 *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry); | 2845 *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry); |
2838 | 2846 |
2839 return true; | 2847 return true; |
2840 } | 2848 } |
2841 | 2849 |
2842 | 2850 |
2851 Definition* FlowGraphOptimizer::PrepareInlineStringIndexOpUnchecked( | |
2852 Instruction* call, | |
2853 intptr_t cid, | |
2854 intptr_t count, | |
2855 Definition* str, | |
2856 Definition* index, | |
2857 Instruction* cursor) { | |
2858 LoadCodeUnitsInstr* load = new(I) LoadCodeUnitsInstr( | |
2859 new(I) Value(str), | |
2860 new(I) Value(index), | |
2861 count, | |
2862 cid, | |
2863 call->token_pos()); | |
2864 | |
2865 cursor = flow_graph()->AppendTo(cursor, | |
2866 load, | |
2867 NULL, | |
2868 FlowGraph::kValue); | |
2869 ASSERT(cursor == load); | |
2870 return load; | |
2871 } | |
2872 | |
2873 | |
2874 bool FlowGraphOptimizer::InlineStringCodeUnitsAt( | |
2875 Instruction* call, | |
2876 intptr_t cid, | |
2877 intptr_t count, | |
2878 TargetEntryInstr** entry, | |
2879 Definition** last) { | |
2880 // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp. | |
2881 if (RawObject::IsExternalStringClassId(cid)) { | |
2882 return false; | |
Ivan Posva
2014/10/09 09:54:15
What will be generated when we return false here?
jgruber1
2014/10/09 13:36:16
The inlined version of String::_codeUnitsAt().
| |
2883 } | |
2884 | |
2885 Definition* str = call->ArgumentAt(0); | |
2886 Definition* index = call->ArgumentAt(1); | |
2887 | |
2888 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(), | |
2889 call->GetBlock()->try_index()); | |
2890 (*entry)->InheritDeoptTarget(I, call); | |
2891 | |
2892 *last = PrepareInlineStringIndexOpUnchecked( | |
2893 call, cid, count, str, index, *entry); | |
2894 | |
2895 return true; | |
2896 } | |
2897 | |
2898 | |
2843 bool FlowGraphOptimizer::InlineStringBaseCharAt( | 2899 bool FlowGraphOptimizer::InlineStringBaseCharAt( |
2844 Instruction* call, | 2900 Instruction* call, |
2845 intptr_t cid, | 2901 intptr_t cid, |
2846 TargetEntryInstr** entry, | 2902 TargetEntryInstr** entry, |
2847 Definition** last) { | 2903 Definition** last) { |
2848 // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp. | 2904 // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp. |
2849 if (RawObject::IsExternalStringClassId(cid) || cid != kOneByteStringCid) { | 2905 if (RawObject::IsExternalStringClassId(cid) || cid != kOneByteStringCid) { |
2850 return false; | 2906 return false; |
2851 } | 2907 } |
2852 Definition* str = call->ArgumentAt(0); | 2908 Definition* str = call->ArgumentAt(0); |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3025 Bigint::neg_offset(), | 3081 Bigint::neg_offset(), |
3026 new(I) Value(bigint), | 3082 new(I) Value(bigint), |
3027 new(I) Value(value), | 3083 new(I) Value(value), |
3028 kEmitStoreBarrier, | 3084 kEmitStoreBarrier, |
3029 call->token_pos()); | 3085 call->token_pos()); |
3030 ReplaceCall(call, store); | 3086 ReplaceCall(call, store); |
3031 return true; | 3087 return true; |
3032 } | 3088 } |
3033 | 3089 |
3034 if (((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) || | 3090 if (((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) || |
3035 (recognized_kind == MethodRecognizer::kStringBaseCharAt)) && | 3091 (recognized_kind == MethodRecognizer::kStringBaseCharAt) || |
3092 (recognized_kind == MethodRecognizer::kOneByteString_oneCodeUnitAt) || | |
3093 (recognized_kind == MethodRecognizer::kOneByteString_twoCodeUnitsAt) || | |
3094 (recognized_kind == MethodRecognizer::kOneByteString_fourCodeUnitsAt) || | |
3095 (recognized_kind == MethodRecognizer::kTwoByteString_oneCodeUnitAt) || | |
3096 (recognized_kind == MethodRecognizer::kTwoByteString_twoCodeUnitsAt)) && | |
3036 (ic_data.NumberOfChecks() == 1) && | 3097 (ic_data.NumberOfChecks() == 1) && |
3037 ((class_ids[0] == kOneByteStringCid) || | 3098 ((class_ids[0] == kOneByteStringCid) || |
3038 (class_ids[0] == kTwoByteStringCid))) { | 3099 (class_ids[0] == kTwoByteStringCid))) { |
3039 return TryReplaceInstanceCallWithInline(call); | 3100 return TryReplaceInstanceCallWithInline(call); |
3040 } | 3101 } |
3041 | 3102 |
3042 if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) { | 3103 if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) { |
3043 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) { | 3104 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) { |
3044 // This is an internal method, no need to check argument types nor | 3105 // This is an internal method, no need to check argument types nor |
3045 // range. | 3106 // range. |
(...skipping 4634 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7680 } | 7741 } |
7681 | 7742 |
7682 | 7743 |
7683 void ConstantPropagator::VisitTargetEntry(TargetEntryInstr* block) { | 7744 void ConstantPropagator::VisitTargetEntry(TargetEntryInstr* block) { |
7684 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 7745 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
7685 it.Current()->Accept(this); | 7746 it.Current()->Accept(this); |
7686 } | 7747 } |
7687 } | 7748 } |
7688 | 7749 |
7689 | 7750 |
7751 void ConstantPropagator::VisitIndirectEntry(IndirectEntryInstr* block) { | |
7752 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | |
7753 it.Current()->Accept(this); | |
7754 } | |
7755 } | |
7756 | |
7757 | |
7690 void ConstantPropagator::VisitCatchBlockEntry(CatchBlockEntryInstr* block) { | 7758 void ConstantPropagator::VisitCatchBlockEntry(CatchBlockEntryInstr* block) { |
7691 const GrowableArray<Definition*>& defs = *block->initial_definitions(); | 7759 const GrowableArray<Definition*>& defs = *block->initial_definitions(); |
7692 for (intptr_t i = 0; i < defs.length(); ++i) { | 7760 for (intptr_t i = 0; i < defs.length(); ++i) { |
7693 defs[i]->Accept(this); | 7761 defs[i]->Accept(this); |
7694 } | 7762 } |
7695 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 7763 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
7696 it.Current()->Accept(this); | 7764 it.Current()->Accept(this); |
7697 } | 7765 } |
7698 } | 7766 } |
7699 | 7767 |
(...skipping 27 matching lines...) Expand all Loading... | |
7727 SetReachable(instr->successor()); | 7795 SetReachable(instr->successor()); |
7728 | 7796 |
7729 // Phi value depends on the reachability of a predecessor. We have | 7797 // Phi value depends on the reachability of a predecessor. We have |
7730 // to revisit phis every time a predecessor becomes reachable. | 7798 // to revisit phis every time a predecessor becomes reachable. |
7731 for (PhiIterator it(instr->successor()); !it.Done(); it.Advance()) { | 7799 for (PhiIterator it(instr->successor()); !it.Done(); it.Advance()) { |
7732 it.Current()->Accept(this); | 7800 it.Current()->Accept(this); |
7733 } | 7801 } |
7734 } | 7802 } |
7735 | 7803 |
7736 | 7804 |
7805 void ConstantPropagator::VisitIndirectGoto(IndirectGotoInstr* instr) { | |
7806 for (intptr_t i = 0; i < instr->SuccessorCount(); i++) { | |
7807 SetReachable(instr->SuccessorAt(i)); | |
7808 } | |
7809 } | |
7810 | |
7811 | |
7737 void ConstantPropagator::VisitBranch(BranchInstr* instr) { | 7812 void ConstantPropagator::VisitBranch(BranchInstr* instr) { |
7738 instr->comparison()->Accept(this); | 7813 instr->comparison()->Accept(this); |
7739 | 7814 |
7740 // The successors may be reachable, but only if this instruction is. (We | 7815 // The successors may be reachable, but only if this instruction is. (We |
7741 // might be analyzing it because the constant value of one of its inputs | 7816 // might be analyzing it because the constant value of one of its inputs |
7742 // has changed.) | 7817 // has changed.) |
7743 if (reachable_->Contains(instr->GetBlock()->preorder_number())) { | 7818 if (reachable_->Contains(instr->GetBlock()->preorder_number())) { |
7744 if (instr->constant_target() != NULL) { | 7819 if (instr->constant_target() != NULL) { |
7745 ASSERT((instr->constant_target() == instr->true_successor()) || | 7820 ASSERT((instr->constant_target() == instr->true_successor()) || |
7746 (instr->constant_target() == instr->false_successor())); | 7821 (instr->constant_target() == instr->false_successor())); |
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8138 SetValue(instr, result); | 8213 SetValue(instr, result); |
8139 return; | 8214 return; |
8140 } | 8215 } |
8141 } | 8216 } |
8142 } | 8217 } |
8143 SetValue(instr, non_constant_); | 8218 SetValue(instr, non_constant_); |
8144 } | 8219 } |
8145 } | 8220 } |
8146 | 8221 |
8147 | 8222 |
8223 void ConstantPropagator::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) { | |
8224 // TODO(jgruber): Implement constant propagation. | |
8225 SetValue(instr, non_constant_); | |
8226 } | |
8227 | |
8228 | |
8148 void ConstantPropagator::VisitStoreIndexed(StoreIndexedInstr* instr) { | 8229 void ConstantPropagator::VisitStoreIndexed(StoreIndexedInstr* instr) { |
8149 SetValue(instr, instr->value()->definition()->constant_value()); | 8230 SetValue(instr, instr->value()->definition()->constant_value()); |
8150 } | 8231 } |
8151 | 8232 |
8152 | 8233 |
8153 void ConstantPropagator::VisitStoreInstanceField( | 8234 void ConstantPropagator::VisitStoreInstanceField( |
8154 StoreInstanceFieldInstr* instr) { | 8235 StoreInstanceFieldInstr* instr) { |
8155 SetValue(instr, instr->value()->definition()->constant_value()); | 8236 SetValue(instr, instr->value()->definition()->constant_value()); |
8156 } | 8237 } |
8157 | 8238 |
(...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8780 const Object& right = instr->right()->definition()->constant_value(); | 8861 const Object& right = instr->right()->definition()->constant_value(); |
8781 if (IsNonConstant(left) || IsNonConstant(right)) { | 8862 if (IsNonConstant(left) || IsNonConstant(right)) { |
8782 SetValue(instr, non_constant_); | 8863 SetValue(instr, non_constant_); |
8783 } else if (IsConstant(left) && IsConstant(right)) { | 8864 } else if (IsConstant(left) && IsConstant(right)) { |
8784 // TODO(srdjan): Handle min and max. | 8865 // TODO(srdjan): Handle min and max. |
8785 SetValue(instr, non_constant_); | 8866 SetValue(instr, non_constant_); |
8786 } | 8867 } |
8787 } | 8868 } |
8788 | 8869 |
8789 | 8870 |
8871 void ConstantPropagator::VisitCaseInsensitiveCompareUC16( | |
8872 CaseInsensitiveCompareUC16Instr *instr) { | |
8873 SetValue(instr, non_constant_); | |
8874 } | |
8875 | |
8876 | |
8790 void ConstantPropagator::VisitUnboxDouble(UnboxDoubleInstr* instr) { | 8877 void ConstantPropagator::VisitUnboxDouble(UnboxDoubleInstr* instr) { |
8791 const Object& value = instr->value()->definition()->constant_value(); | 8878 const Object& value = instr->value()->definition()->constant_value(); |
8792 if (IsNonConstant(value)) { | 8879 if (IsNonConstant(value)) { |
8793 SetValue(instr, non_constant_); | 8880 SetValue(instr, non_constant_); |
8794 } else if (IsConstant(value)) { | 8881 } else if (IsConstant(value)) { |
8795 // TODO(kmillikin): Handle conversion. | 8882 // TODO(kmillikin): Handle conversion. |
8796 SetValue(instr, non_constant_); | 8883 SetValue(instr, non_constant_); |
8797 } | 8884 } |
8798 } | 8885 } |
8799 | 8886 |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8929 } else { | 9016 } else { |
8930 BlockEntryInstr* block = block_worklist_.RemoveLast(); | 9017 BlockEntryInstr* block = block_worklist_.RemoveLast(); |
8931 block->Accept(this); | 9018 block->Accept(this); |
8932 } | 9019 } |
8933 } | 9020 } |
8934 } | 9021 } |
8935 | 9022 |
8936 | 9023 |
8937 static bool IsEmptyBlock(BlockEntryInstr* block) { | 9024 static bool IsEmptyBlock(BlockEntryInstr* block) { |
8938 return block->next()->IsGoto() && | 9025 return block->next()->IsGoto() && |
8939 (!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)); | 9026 (!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)) && |
9027 !block->IsIndirectEntry(); | |
8940 } | 9028 } |
8941 | 9029 |
8942 | 9030 |
8943 // Traverses a chain of empty blocks and returns the first reachable non-empty | 9031 // Traverses a chain of empty blocks and returns the first reachable non-empty |
8944 // block that is not dominated by the start block. The empty blocks are added | 9032 // block that is not dominated by the start block. The empty blocks are added |
8945 // to the supplied bit vector. | 9033 // to the supplied bit vector. |
8946 static BlockEntryInstr* FindFirstNonEmptySuccessor( | 9034 static BlockEntryInstr* FindFirstNonEmptySuccessor( |
8947 TargetEntryInstr* block, | 9035 TargetEntryInstr* block, |
8948 BitVector* empty_blocks) { | 9036 BitVector* empty_blocks) { |
8949 BlockEntryInstr* current = block; | 9037 BlockEntryInstr* current = block; |
(...skipping 1170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
10120 | 10208 |
10121 // Insert materializations at environment uses. | 10209 // Insert materializations at environment uses. |
10122 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 10210 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
10123 CreateMaterializationAt( | 10211 CreateMaterializationAt( |
10124 exits_collector_.exits()[i], alloc, alloc->cls(), *slots); | 10212 exits_collector_.exits()[i], alloc, alloc->cls(), *slots); |
10125 } | 10213 } |
10126 } | 10214 } |
10127 | 10215 |
10128 | 10216 |
10129 } // namespace dart | 10217 } // namespace dart |
OLD | NEW |