| 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 1190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2834 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(), | 2842 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(), |
| 2835 call->GetBlock()->try_index()); | 2843 call->GetBlock()->try_index()); |
| 2836 (*entry)->InheritDeoptTarget(I, call); | 2844 (*entry)->InheritDeoptTarget(I, call); |
| 2837 | 2845 |
| 2838 *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry); | 2846 *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry); |
| 2839 | 2847 |
| 2840 return true; | 2848 return true; |
| 2841 } | 2849 } |
| 2842 | 2850 |
| 2843 | 2851 |
| 2852 Definition* FlowGraphOptimizer::PrepareInlineStringIndexOpUnchecked( |
| 2853 Instruction* call, |
| 2854 intptr_t cid, |
| 2855 intptr_t count, |
| 2856 Definition* str, |
| 2857 Definition* index, |
| 2858 Instruction* cursor) { |
| 2859 LoadCodeUnitsInstr* load = new(I) LoadCodeUnitsInstr( |
| 2860 new(I) Value(str), |
| 2861 new(I) Value(index), |
| 2862 count, |
| 2863 cid, |
| 2864 call->token_pos()); |
| 2865 |
| 2866 cursor = flow_graph()->AppendTo(cursor, |
| 2867 load, |
| 2868 NULL, |
| 2869 FlowGraph::kValue); |
| 2870 ASSERT(cursor == load); |
| 2871 return load; |
| 2872 } |
| 2873 |
| 2874 |
| 2875 bool FlowGraphOptimizer::InlineStringCodeUnitsAt( |
| 2876 Instruction* call, |
| 2877 intptr_t cid, |
| 2878 intptr_t count, |
| 2879 TargetEntryInstr** entry, |
| 2880 Definition** last) { |
| 2881 // TODO(jgruber): Handle external strings in |
| 2882 // PrepareInlineStringIndexOpUnchecked. |
| 2883 if (RawObject::IsExternalStringClassId(cid)) { |
| 2884 return false; |
| 2885 } |
| 2886 |
| 2887 Definition* str = call->ArgumentAt(0); |
| 2888 Definition* index = call->ArgumentAt(1); |
| 2889 |
| 2890 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(), |
| 2891 call->GetBlock()->try_index()); |
| 2892 (*entry)->InheritDeoptTarget(I, call); |
| 2893 |
| 2894 *last = PrepareInlineStringIndexOpUnchecked( |
| 2895 call, cid, count, str, index, *entry); |
| 2896 |
| 2897 return true; |
| 2898 } |
| 2899 |
| 2900 |
| 2844 bool FlowGraphOptimizer::InlineStringBaseCharAt( | 2901 bool FlowGraphOptimizer::InlineStringBaseCharAt( |
| 2845 Instruction* call, | 2902 Instruction* call, |
| 2846 intptr_t cid, | 2903 intptr_t cid, |
| 2847 TargetEntryInstr** entry, | 2904 TargetEntryInstr** entry, |
| 2848 Definition** last) { | 2905 Definition** last) { |
| 2849 // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp. | 2906 // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp. |
| 2850 if (RawObject::IsExternalStringClassId(cid) || cid != kOneByteStringCid) { | 2907 if (RawObject::IsExternalStringClassId(cid) || cid != kOneByteStringCid) { |
| 2851 return false; | 2908 return false; |
| 2852 } | 2909 } |
| 2853 Definition* str = call->ArgumentAt(0); | 2910 Definition* str = call->ArgumentAt(0); |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3026 Bigint::neg_offset(), | 3083 Bigint::neg_offset(), |
| 3027 new(I) Value(bigint), | 3084 new(I) Value(bigint), |
| 3028 new(I) Value(value), | 3085 new(I) Value(value), |
| 3029 kEmitStoreBarrier, | 3086 kEmitStoreBarrier, |
| 3030 call->token_pos()); | 3087 call->token_pos()); |
| 3031 ReplaceCall(call, store); | 3088 ReplaceCall(call, store); |
| 3032 return true; | 3089 return true; |
| 3033 } | 3090 } |
| 3034 | 3091 |
| 3035 if (((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) || | 3092 if (((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) || |
| 3036 (recognized_kind == MethodRecognizer::kStringBaseCharAt)) && | 3093 (recognized_kind == MethodRecognizer::kStringBaseCharAt) || |
| 3094 (recognized_kind == MethodRecognizer::kOneByteString_oneCodeUnitAt) || |
| 3095 (recognized_kind == MethodRecognizer::kOneByteString_twoCodeUnitsAt) || |
| 3096 (recognized_kind == MethodRecognizer::kOneByteString_fourCodeUnitsAt) || |
| 3097 (recognized_kind == MethodRecognizer::kTwoByteString_oneCodeUnitAt) || |
| 3098 (recognized_kind == MethodRecognizer::kTwoByteString_twoCodeUnitsAt)) && |
| 3037 (ic_data.NumberOfChecks() == 1) && | 3099 (ic_data.NumberOfChecks() == 1) && |
| 3038 ((class_ids[0] == kOneByteStringCid) || | 3100 ((class_ids[0] == kOneByteStringCid) || |
| 3039 (class_ids[0] == kTwoByteStringCid))) { | 3101 (class_ids[0] == kTwoByteStringCid))) { |
| 3040 return TryReplaceInstanceCallWithInline(call); | 3102 return TryReplaceInstanceCallWithInline(call); |
| 3041 } | 3103 } |
| 3042 | 3104 |
| 3043 if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) { | 3105 if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) { |
| 3044 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) { | 3106 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) { |
| 3045 // This is an internal method, no need to check argument types nor | 3107 // This is an internal method, no need to check argument types nor |
| 3046 // range. | 3108 // range. |
| (...skipping 4608 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7655 } | 7717 } |
| 7656 | 7718 |
| 7657 | 7719 |
| 7658 void ConstantPropagator::VisitTargetEntry(TargetEntryInstr* block) { | 7720 void ConstantPropagator::VisitTargetEntry(TargetEntryInstr* block) { |
| 7659 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 7721 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
| 7660 it.Current()->Accept(this); | 7722 it.Current()->Accept(this); |
| 7661 } | 7723 } |
| 7662 } | 7724 } |
| 7663 | 7725 |
| 7664 | 7726 |
| 7727 void ConstantPropagator::VisitIndirectEntry(IndirectEntryInstr* block) { |
| 7728 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
| 7729 it.Current()->Accept(this); |
| 7730 } |
| 7731 } |
| 7732 |
| 7733 |
| 7665 void ConstantPropagator::VisitCatchBlockEntry(CatchBlockEntryInstr* block) { | 7734 void ConstantPropagator::VisitCatchBlockEntry(CatchBlockEntryInstr* block) { |
| 7666 const GrowableArray<Definition*>& defs = *block->initial_definitions(); | 7735 const GrowableArray<Definition*>& defs = *block->initial_definitions(); |
| 7667 for (intptr_t i = 0; i < defs.length(); ++i) { | 7736 for (intptr_t i = 0; i < defs.length(); ++i) { |
| 7668 defs[i]->Accept(this); | 7737 defs[i]->Accept(this); |
| 7669 } | 7738 } |
| 7670 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 7739 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
| 7671 it.Current()->Accept(this); | 7740 it.Current()->Accept(this); |
| 7672 } | 7741 } |
| 7673 } | 7742 } |
| 7674 | 7743 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 7702 SetReachable(instr->successor()); | 7771 SetReachable(instr->successor()); |
| 7703 | 7772 |
| 7704 // Phi value depends on the reachability of a predecessor. We have | 7773 // Phi value depends on the reachability of a predecessor. We have |
| 7705 // to revisit phis every time a predecessor becomes reachable. | 7774 // to revisit phis every time a predecessor becomes reachable. |
| 7706 for (PhiIterator it(instr->successor()); !it.Done(); it.Advance()) { | 7775 for (PhiIterator it(instr->successor()); !it.Done(); it.Advance()) { |
| 7707 it.Current()->Accept(this); | 7776 it.Current()->Accept(this); |
| 7708 } | 7777 } |
| 7709 } | 7778 } |
| 7710 | 7779 |
| 7711 | 7780 |
| 7781 void ConstantPropagator::VisitIndirectGoto(IndirectGotoInstr* instr) { |
| 7782 for (intptr_t i = 0; i < instr->SuccessorCount(); i++) { |
| 7783 SetReachable(instr->SuccessorAt(i)); |
| 7784 } |
| 7785 } |
| 7786 |
| 7787 |
| 7712 void ConstantPropagator::VisitBranch(BranchInstr* instr) { | 7788 void ConstantPropagator::VisitBranch(BranchInstr* instr) { |
| 7713 instr->comparison()->Accept(this); | 7789 instr->comparison()->Accept(this); |
| 7714 | 7790 |
| 7715 // The successors may be reachable, but only if this instruction is. (We | 7791 // The successors may be reachable, but only if this instruction is. (We |
| 7716 // might be analyzing it because the constant value of one of its inputs | 7792 // might be analyzing it because the constant value of one of its inputs |
| 7717 // has changed.) | 7793 // has changed.) |
| 7718 if (reachable_->Contains(instr->GetBlock()->preorder_number())) { | 7794 if (reachable_->Contains(instr->GetBlock()->preorder_number())) { |
| 7719 if (instr->constant_target() != NULL) { | 7795 if (instr->constant_target() != NULL) { |
| 7720 ASSERT((instr->constant_target() == instr->true_successor()) || | 7796 ASSERT((instr->constant_target() == instr->true_successor()) || |
| 7721 (instr->constant_target() == instr->false_successor())); | 7797 (instr->constant_target() == instr->false_successor())); |
| (...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8113 SetValue(instr, result); | 8189 SetValue(instr, result); |
| 8114 return; | 8190 return; |
| 8115 } | 8191 } |
| 8116 } | 8192 } |
| 8117 } | 8193 } |
| 8118 SetValue(instr, non_constant_); | 8194 SetValue(instr, non_constant_); |
| 8119 } | 8195 } |
| 8120 } | 8196 } |
| 8121 | 8197 |
| 8122 | 8198 |
| 8199 void ConstantPropagator::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) { |
| 8200 // TODO(jgruber): Implement constant propagation. |
| 8201 SetValue(instr, non_constant_); |
| 8202 } |
| 8203 |
| 8204 |
| 8123 void ConstantPropagator::VisitStoreIndexed(StoreIndexedInstr* instr) { | 8205 void ConstantPropagator::VisitStoreIndexed(StoreIndexedInstr* instr) { |
| 8124 SetValue(instr, instr->value()->definition()->constant_value()); | 8206 SetValue(instr, instr->value()->definition()->constant_value()); |
| 8125 } | 8207 } |
| 8126 | 8208 |
| 8127 | 8209 |
| 8128 void ConstantPropagator::VisitStoreInstanceField( | 8210 void ConstantPropagator::VisitStoreInstanceField( |
| 8129 StoreInstanceFieldInstr* instr) { | 8211 StoreInstanceFieldInstr* instr) { |
| 8130 SetValue(instr, instr->value()->definition()->constant_value()); | 8212 SetValue(instr, instr->value()->definition()->constant_value()); |
| 8131 } | 8213 } |
| 8132 | 8214 |
| (...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8755 const Object& right = instr->right()->definition()->constant_value(); | 8837 const Object& right = instr->right()->definition()->constant_value(); |
| 8756 if (IsNonConstant(left) || IsNonConstant(right)) { | 8838 if (IsNonConstant(left) || IsNonConstant(right)) { |
| 8757 SetValue(instr, non_constant_); | 8839 SetValue(instr, non_constant_); |
| 8758 } else if (IsConstant(left) && IsConstant(right)) { | 8840 } else if (IsConstant(left) && IsConstant(right)) { |
| 8759 // TODO(srdjan): Handle min and max. | 8841 // TODO(srdjan): Handle min and max. |
| 8760 SetValue(instr, non_constant_); | 8842 SetValue(instr, non_constant_); |
| 8761 } | 8843 } |
| 8762 } | 8844 } |
| 8763 | 8845 |
| 8764 | 8846 |
| 8847 void ConstantPropagator::VisitCaseInsensitiveCompareUC16( |
| 8848 CaseInsensitiveCompareUC16Instr *instr) { |
| 8849 SetValue(instr, non_constant_); |
| 8850 } |
| 8851 |
| 8852 |
| 8765 void ConstantPropagator::VisitUnboxDouble(UnboxDoubleInstr* instr) { | 8853 void ConstantPropagator::VisitUnboxDouble(UnboxDoubleInstr* instr) { |
| 8766 const Object& value = instr->value()->definition()->constant_value(); | 8854 const Object& value = instr->value()->definition()->constant_value(); |
| 8767 if (IsNonConstant(value)) { | 8855 if (IsNonConstant(value)) { |
| 8768 SetValue(instr, non_constant_); | 8856 SetValue(instr, non_constant_); |
| 8769 } else if (IsConstant(value)) { | 8857 } else if (IsConstant(value)) { |
| 8770 // TODO(kmillikin): Handle conversion. | 8858 // TODO(kmillikin): Handle conversion. |
| 8771 SetValue(instr, non_constant_); | 8859 SetValue(instr, non_constant_); |
| 8772 } | 8860 } |
| 8773 } | 8861 } |
| 8774 | 8862 |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8904 } else { | 8992 } else { |
| 8905 BlockEntryInstr* block = block_worklist_.RemoveLast(); | 8993 BlockEntryInstr* block = block_worklist_.RemoveLast(); |
| 8906 block->Accept(this); | 8994 block->Accept(this); |
| 8907 } | 8995 } |
| 8908 } | 8996 } |
| 8909 } | 8997 } |
| 8910 | 8998 |
| 8911 | 8999 |
| 8912 static bool IsEmptyBlock(BlockEntryInstr* block) { | 9000 static bool IsEmptyBlock(BlockEntryInstr* block) { |
| 8913 return block->next()->IsGoto() && | 9001 return block->next()->IsGoto() && |
| 8914 (!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)); | 9002 (!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)) && |
| 9003 !block->IsIndirectEntry(); |
| 8915 } | 9004 } |
| 8916 | 9005 |
| 8917 | 9006 |
| 8918 // Traverses a chain of empty blocks and returns the first reachable non-empty | 9007 // Traverses a chain of empty blocks and returns the first reachable non-empty |
| 8919 // block that is not dominated by the start block. The empty blocks are added | 9008 // block that is not dominated by the start block. The empty blocks are added |
| 8920 // to the supplied bit vector. | 9009 // to the supplied bit vector. |
| 8921 static BlockEntryInstr* FindFirstNonEmptySuccessor( | 9010 static BlockEntryInstr* FindFirstNonEmptySuccessor( |
| 8922 TargetEntryInstr* block, | 9011 TargetEntryInstr* block, |
| 8923 BitVector* empty_blocks) { | 9012 BitVector* empty_blocks) { |
| 8924 BlockEntryInstr* current = block; | 9013 BlockEntryInstr* current = block; |
| (...skipping 1170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10095 | 10184 |
| 10096 // Insert materializations at environment uses. | 10185 // Insert materializations at environment uses. |
| 10097 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 10186 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
| 10098 CreateMaterializationAt( | 10187 CreateMaterializationAt( |
| 10099 exits_collector_.exits()[i], alloc, alloc->cls(), *slots); | 10188 exits_collector_.exits()[i], alloc, alloc->cls(), *slots); |
| 10100 } | 10189 } |
| 10101 } | 10190 } |
| 10102 | 10191 |
| 10103 | 10192 |
| 10104 } // namespace dart | 10193 } // namespace dart |
| OLD | NEW |