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 1641 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1652 if (!ShouldInlineSimd()) { | 1652 if (!ShouldInlineSimd()) { |
1653 return false; | 1653 return false; |
1654 } | 1654 } |
1655 return InlineByteArrayViewStore(target, call, receiver, receiver_cid, | 1655 return InlineByteArrayViewStore(target, call, receiver, receiver_cid, |
1656 kTypedDataInt32x4ArrayCid, | 1656 kTypedDataInt32x4ArrayCid, |
1657 ic_data, entry, last); | 1657 ic_data, entry, last); |
1658 case MethodRecognizer::kStringBaseCodeUnitAt: | 1658 case MethodRecognizer::kStringBaseCodeUnitAt: |
1659 return InlineStringCodeUnitAt(call, receiver_cid, entry, last); | 1659 return InlineStringCodeUnitAt(call, receiver_cid, entry, last); |
1660 case MethodRecognizer::kStringBaseCharAt: | 1660 case MethodRecognizer::kStringBaseCharAt: |
1661 return InlineStringBaseCharAt(call, receiver_cid, entry, last); | 1661 return InlineStringBaseCharAt(call, receiver_cid, entry, last); |
| 1662 case MethodRecognizer::kOneByteString_oneCodeUnitAt: |
| 1663 case MethodRecognizer::kTwoByteString_oneCodeUnitAt: |
| 1664 return InlineStringCodeUnitsAt(call, receiver_cid, 1, entry, last); |
| 1665 case MethodRecognizer::kOneByteString_twoCodeUnitsAt: |
| 1666 case MethodRecognizer::kTwoByteString_twoCodeUnitsAt: |
| 1667 return InlineStringCodeUnitsAt(call, receiver_cid, 2, entry, last); |
| 1668 case MethodRecognizer::kOneByteString_fourCodeUnitsAt: |
| 1669 return InlineStringCodeUnitsAt(call, receiver_cid, 4, entry, last); |
1662 case MethodRecognizer::kDoubleAdd: | 1670 case MethodRecognizer::kDoubleAdd: |
1663 return InlineDoubleOp(Token::kADD, call, entry, last); | 1671 return InlineDoubleOp(Token::kADD, call, entry, last); |
1664 case MethodRecognizer::kDoubleSub: | 1672 case MethodRecognizer::kDoubleSub: |
1665 return InlineDoubleOp(Token::kSUB, call, entry, last); | 1673 return InlineDoubleOp(Token::kSUB, call, entry, last); |
1666 case MethodRecognizer::kDoubleMul: | 1674 case MethodRecognizer::kDoubleMul: |
1667 return InlineDoubleOp(Token::kMUL, call, entry, last); | 1675 return InlineDoubleOp(Token::kMUL, call, entry, last); |
1668 case MethodRecognizer::kDoubleDiv: | 1676 case MethodRecognizer::kDoubleDiv: |
1669 return InlineDoubleOp(Token::kDIV, call, entry, last); | 1677 return InlineDoubleOp(Token::kDIV, call, entry, last); |
1670 default: | 1678 default: |
1671 return false; | 1679 return false; |
(...skipping 1190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2862 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(), | 2870 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(), |
2863 call->GetBlock()->try_index()); | 2871 call->GetBlock()->try_index()); |
2864 (*entry)->InheritDeoptTarget(I, call); | 2872 (*entry)->InheritDeoptTarget(I, call); |
2865 | 2873 |
2866 *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry); | 2874 *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry); |
2867 | 2875 |
2868 return true; | 2876 return true; |
2869 } | 2877 } |
2870 | 2878 |
2871 | 2879 |
| 2880 Definition* FlowGraphOptimizer::PrepareInlineStringIndexOpUnchecked( |
| 2881 Instruction* call, |
| 2882 intptr_t cid, |
| 2883 intptr_t count, |
| 2884 Definition* str, |
| 2885 Definition* index, |
| 2886 Instruction* cursor) { |
| 2887 LoadCodeUnitsInstr* load = new(I) LoadCodeUnitsInstr( |
| 2888 new(I) Value(str), |
| 2889 new(I) Value(index), |
| 2890 count, |
| 2891 cid, |
| 2892 call->token_pos()); |
| 2893 |
| 2894 cursor = flow_graph()->AppendTo(cursor, |
| 2895 load, |
| 2896 NULL, |
| 2897 FlowGraph::kValue); |
| 2898 ASSERT(cursor == load); |
| 2899 return load; |
| 2900 } |
| 2901 |
| 2902 |
| 2903 bool FlowGraphOptimizer::InlineStringCodeUnitsAt( |
| 2904 Instruction* call, |
| 2905 intptr_t cid, |
| 2906 intptr_t count, |
| 2907 TargetEntryInstr** entry, |
| 2908 Definition** last) { |
| 2909 // TODO(jgruber): Handle external strings in |
| 2910 // PrepareInlineStringIndexOpUnchecked. |
| 2911 if (RawObject::IsExternalStringClassId(cid)) { |
| 2912 return false; |
| 2913 } |
| 2914 |
| 2915 Definition* str = call->ArgumentAt(0); |
| 2916 Definition* index = call->ArgumentAt(1); |
| 2917 |
| 2918 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(), |
| 2919 call->GetBlock()->try_index()); |
| 2920 (*entry)->InheritDeoptTarget(I, call); |
| 2921 |
| 2922 *last = PrepareInlineStringIndexOpUnchecked( |
| 2923 call, cid, count, str, index, *entry); |
| 2924 |
| 2925 return true; |
| 2926 } |
| 2927 |
| 2928 |
2872 bool FlowGraphOptimizer::InlineStringBaseCharAt( | 2929 bool FlowGraphOptimizer::InlineStringBaseCharAt( |
2873 Instruction* call, | 2930 Instruction* call, |
2874 intptr_t cid, | 2931 intptr_t cid, |
2875 TargetEntryInstr** entry, | 2932 TargetEntryInstr** entry, |
2876 Definition** last) { | 2933 Definition** last) { |
2877 // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp. | 2934 // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp. |
2878 if (RawObject::IsExternalStringClassId(cid) || cid != kOneByteStringCid) { | 2935 if (RawObject::IsExternalStringClassId(cid) || cid != kOneByteStringCid) { |
2879 return false; | 2936 return false; |
2880 } | 2937 } |
2881 Definition* str = call->ArgumentAt(0); | 2938 Definition* str = call->ArgumentAt(0); |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3054 Bigint::neg_offset(), | 3111 Bigint::neg_offset(), |
3055 new(I) Value(bigint), | 3112 new(I) Value(bigint), |
3056 new(I) Value(value), | 3113 new(I) Value(value), |
3057 kEmitStoreBarrier, | 3114 kEmitStoreBarrier, |
3058 call->token_pos()); | 3115 call->token_pos()); |
3059 ReplaceCall(call, store); | 3116 ReplaceCall(call, store); |
3060 return true; | 3117 return true; |
3061 } | 3118 } |
3062 | 3119 |
3063 if (((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) || | 3120 if (((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) || |
3064 (recognized_kind == MethodRecognizer::kStringBaseCharAt)) && | 3121 (recognized_kind == MethodRecognizer::kStringBaseCharAt) || |
| 3122 (recognized_kind == MethodRecognizer::kOneByteString_oneCodeUnitAt) || |
| 3123 (recognized_kind == MethodRecognizer::kOneByteString_twoCodeUnitsAt) || |
| 3124 (recognized_kind == MethodRecognizer::kOneByteString_fourCodeUnitsAt) || |
| 3125 (recognized_kind == MethodRecognizer::kTwoByteString_oneCodeUnitAt) || |
| 3126 (recognized_kind == MethodRecognizer::kTwoByteString_twoCodeUnitsAt)) && |
3065 (ic_data.NumberOfChecks() == 1) && | 3127 (ic_data.NumberOfChecks() == 1) && |
3066 ((class_ids[0] == kOneByteStringCid) || | 3128 ((class_ids[0] == kOneByteStringCid) || |
3067 (class_ids[0] == kTwoByteStringCid))) { | 3129 (class_ids[0] == kTwoByteStringCid))) { |
3068 return TryReplaceInstanceCallWithInline(call); | 3130 return TryReplaceInstanceCallWithInline(call); |
3069 } | 3131 } |
3070 | 3132 |
3071 if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) { | 3133 if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) { |
3072 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) { | 3134 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) { |
3073 // This is an internal method, no need to check argument types nor | 3135 // This is an internal method, no need to check argument types nor |
3074 // range. | 3136 // range. |
(...skipping 4607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7682 } | 7744 } |
7683 | 7745 |
7684 | 7746 |
7685 void ConstantPropagator::VisitTargetEntry(TargetEntryInstr* block) { | 7747 void ConstantPropagator::VisitTargetEntry(TargetEntryInstr* block) { |
7686 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 7748 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
7687 it.Current()->Accept(this); | 7749 it.Current()->Accept(this); |
7688 } | 7750 } |
7689 } | 7751 } |
7690 | 7752 |
7691 | 7753 |
| 7754 void ConstantPropagator::VisitIndirectEntry(IndirectEntryInstr* block) { |
| 7755 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
| 7756 it.Current()->Accept(this); |
| 7757 } |
| 7758 } |
| 7759 |
| 7760 |
7692 void ConstantPropagator::VisitCatchBlockEntry(CatchBlockEntryInstr* block) { | 7761 void ConstantPropagator::VisitCatchBlockEntry(CatchBlockEntryInstr* block) { |
7693 const GrowableArray<Definition*>& defs = *block->initial_definitions(); | 7762 const GrowableArray<Definition*>& defs = *block->initial_definitions(); |
7694 for (intptr_t i = 0; i < defs.length(); ++i) { | 7763 for (intptr_t i = 0; i < defs.length(); ++i) { |
7695 defs[i]->Accept(this); | 7764 defs[i]->Accept(this); |
7696 } | 7765 } |
7697 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 7766 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
7698 it.Current()->Accept(this); | 7767 it.Current()->Accept(this); |
7699 } | 7768 } |
7700 } | 7769 } |
7701 | 7770 |
(...skipping 27 matching lines...) Expand all Loading... |
7729 SetReachable(instr->successor()); | 7798 SetReachable(instr->successor()); |
7730 | 7799 |
7731 // Phi value depends on the reachability of a predecessor. We have | 7800 // Phi value depends on the reachability of a predecessor. We have |
7732 // to revisit phis every time a predecessor becomes reachable. | 7801 // to revisit phis every time a predecessor becomes reachable. |
7733 for (PhiIterator it(instr->successor()); !it.Done(); it.Advance()) { | 7802 for (PhiIterator it(instr->successor()); !it.Done(); it.Advance()) { |
7734 it.Current()->Accept(this); | 7803 it.Current()->Accept(this); |
7735 } | 7804 } |
7736 } | 7805 } |
7737 | 7806 |
7738 | 7807 |
| 7808 void ConstantPropagator::VisitIndirectGoto(IndirectGotoInstr* instr) { |
| 7809 for (intptr_t i = 0; i < instr->SuccessorCount(); i++) { |
| 7810 SetReachable(instr->SuccessorAt(i)); |
| 7811 } |
| 7812 } |
| 7813 |
| 7814 |
7739 void ConstantPropagator::VisitBranch(BranchInstr* instr) { | 7815 void ConstantPropagator::VisitBranch(BranchInstr* instr) { |
7740 instr->comparison()->Accept(this); | 7816 instr->comparison()->Accept(this); |
7741 | 7817 |
7742 // The successors may be reachable, but only if this instruction is. (We | 7818 // The successors may be reachable, but only if this instruction is. (We |
7743 // might be analyzing it because the constant value of one of its inputs | 7819 // might be analyzing it because the constant value of one of its inputs |
7744 // has changed.) | 7820 // has changed.) |
7745 if (reachable_->Contains(instr->GetBlock()->preorder_number())) { | 7821 if (reachable_->Contains(instr->GetBlock()->preorder_number())) { |
7746 if (instr->constant_target() != NULL) { | 7822 if (instr->constant_target() != NULL) { |
7747 ASSERT((instr->constant_target() == instr->true_successor()) || | 7823 ASSERT((instr->constant_target() == instr->true_successor()) || |
7748 (instr->constant_target() == instr->false_successor())); | 7824 (instr->constant_target() == instr->false_successor())); |
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8140 SetValue(instr, result); | 8216 SetValue(instr, result); |
8141 return; | 8217 return; |
8142 } | 8218 } |
8143 } | 8219 } |
8144 } | 8220 } |
8145 SetValue(instr, non_constant_); | 8221 SetValue(instr, non_constant_); |
8146 } | 8222 } |
8147 } | 8223 } |
8148 | 8224 |
8149 | 8225 |
| 8226 void ConstantPropagator::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) { |
| 8227 // TODO(jgruber): Implement constant propagation. |
| 8228 SetValue(instr, non_constant_); |
| 8229 } |
| 8230 |
| 8231 |
8150 void ConstantPropagator::VisitStoreIndexed(StoreIndexedInstr* instr) { | 8232 void ConstantPropagator::VisitStoreIndexed(StoreIndexedInstr* instr) { |
8151 SetValue(instr, instr->value()->definition()->constant_value()); | 8233 SetValue(instr, instr->value()->definition()->constant_value()); |
8152 } | 8234 } |
8153 | 8235 |
8154 | 8236 |
8155 void ConstantPropagator::VisitStoreInstanceField( | 8237 void ConstantPropagator::VisitStoreInstanceField( |
8156 StoreInstanceFieldInstr* instr) { | 8238 StoreInstanceFieldInstr* instr) { |
8157 SetValue(instr, instr->value()->definition()->constant_value()); | 8239 SetValue(instr, instr->value()->definition()->constant_value()); |
8158 } | 8240 } |
8159 | 8241 |
(...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8782 const Object& right = instr->right()->definition()->constant_value(); | 8864 const Object& right = instr->right()->definition()->constant_value(); |
8783 if (IsNonConstant(left) || IsNonConstant(right)) { | 8865 if (IsNonConstant(left) || IsNonConstant(right)) { |
8784 SetValue(instr, non_constant_); | 8866 SetValue(instr, non_constant_); |
8785 } else if (IsConstant(left) && IsConstant(right)) { | 8867 } else if (IsConstant(left) && IsConstant(right)) { |
8786 // TODO(srdjan): Handle min and max. | 8868 // TODO(srdjan): Handle min and max. |
8787 SetValue(instr, non_constant_); | 8869 SetValue(instr, non_constant_); |
8788 } | 8870 } |
8789 } | 8871 } |
8790 | 8872 |
8791 | 8873 |
| 8874 void ConstantPropagator::VisitCaseInsensitiveCompareUC16( |
| 8875 CaseInsensitiveCompareUC16Instr *instr) { |
| 8876 SetValue(instr, non_constant_); |
| 8877 } |
| 8878 |
| 8879 |
8792 void ConstantPropagator::VisitUnboxDouble(UnboxDoubleInstr* instr) { | 8880 void ConstantPropagator::VisitUnboxDouble(UnboxDoubleInstr* instr) { |
8793 const Object& value = instr->value()->definition()->constant_value(); | 8881 const Object& value = instr->value()->definition()->constant_value(); |
8794 if (IsNonConstant(value)) { | 8882 if (IsNonConstant(value)) { |
8795 SetValue(instr, non_constant_); | 8883 SetValue(instr, non_constant_); |
8796 } else if (IsConstant(value)) { | 8884 } else if (IsConstant(value)) { |
8797 // TODO(kmillikin): Handle conversion. | 8885 // TODO(kmillikin): Handle conversion. |
8798 SetValue(instr, non_constant_); | 8886 SetValue(instr, non_constant_); |
8799 } | 8887 } |
8800 } | 8888 } |
8801 | 8889 |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8931 } else { | 9019 } else { |
8932 BlockEntryInstr* block = block_worklist_.RemoveLast(); | 9020 BlockEntryInstr* block = block_worklist_.RemoveLast(); |
8933 block->Accept(this); | 9021 block->Accept(this); |
8934 } | 9022 } |
8935 } | 9023 } |
8936 } | 9024 } |
8937 | 9025 |
8938 | 9026 |
8939 static bool IsEmptyBlock(BlockEntryInstr* block) { | 9027 static bool IsEmptyBlock(BlockEntryInstr* block) { |
8940 return block->next()->IsGoto() && | 9028 return block->next()->IsGoto() && |
8941 (!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)); | 9029 (!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)) && |
| 9030 !block->IsIndirectEntry(); |
8942 } | 9031 } |
8943 | 9032 |
8944 | 9033 |
8945 // Traverses a chain of empty blocks and returns the first reachable non-empty | 9034 // Traverses a chain of empty blocks and returns the first reachable non-empty |
8946 // block that is not dominated by the start block. The empty blocks are added | 9035 // block that is not dominated by the start block. The empty blocks are added |
8947 // to the supplied bit vector. | 9036 // to the supplied bit vector. |
8948 static BlockEntryInstr* FindFirstNonEmptySuccessor( | 9037 static BlockEntryInstr* FindFirstNonEmptySuccessor( |
8949 TargetEntryInstr* block, | 9038 TargetEntryInstr* block, |
8950 BitVector* empty_blocks) { | 9039 BitVector* empty_blocks) { |
8951 BlockEntryInstr* current = block; | 9040 BlockEntryInstr* current = block; |
(...skipping 1170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10122 | 10211 |
10123 // Insert materializations at environment uses. | 10212 // Insert materializations at environment uses. |
10124 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 10213 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
10125 CreateMaterializationAt( | 10214 CreateMaterializationAt( |
10126 exits_collector_.exits()[i], alloc, alloc->cls(), *slots); | 10215 exits_collector_.exits()[i], alloc, alloc->cls(), *slots); |
10127 } | 10216 } |
10128 } | 10217 } |
10129 | 10218 |
10130 | 10219 |
10131 } // namespace dart | 10220 } // namespace dart |
OLD | NEW |