| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 library tree_ir.optimization.statement_rewriter; | 5 library tree_ir.optimization.statement_rewriter; |
| 6 | 6 |
| 7 import 'optimization.dart' show Pass; | 7 import 'optimization.dart' show Pass; |
| 8 import '../tree_ir_nodes.dart'; | 8 import '../tree_ir_nodes.dart'; |
| 9 import '../../io/source_information.dart'; | 9 import '../../io/source_information.dart'; |
| 10 import '../../elements/elements.dart'; | 10 import '../../elements/elements.dart'; |
| (...skipping 734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 745 } | 745 } |
| 746 return node; | 746 return node; |
| 747 } | 747 } |
| 748 | 748 |
| 749 Expression visitTypeOperator(TypeOperator node) { | 749 Expression visitTypeOperator(TypeOperator node) { |
| 750 _rewriteList(node.typeArguments); | 750 _rewriteList(node.typeArguments); |
| 751 node.value = visitExpression(node.value); | 751 node.value = visitExpression(node.value); |
| 752 return node; | 752 return node; |
| 753 } | 753 } |
| 754 | 754 |
| 755 bool sameVariable(Expression e1, Expression e2) { | |
| 756 return e1 is VariableUse && e2 is VariableUse && e1.variable == e2.variable; | |
| 757 } | |
| 758 | |
| 759 bool isCompoundableBuiltin(Expression e) { | 755 bool isCompoundableBuiltin(Expression e) { |
| 760 return e is ApplyBuiltinOperator && | 756 return e is ApplyBuiltinOperator && |
| 761 e.arguments.length == 2 && | 757 e.arguments.length >= 2 && |
| 762 isCompoundableOperator(e.operator); | 758 isCompoundableOperator(e.operator); |
| 763 } | 759 } |
| 764 | 760 |
| 761 /// Converts a compoundable operator application into the right-hand side for |
| 762 /// use in a compound assignment, discarding the left-hand value. |
| 763 /// |
| 764 /// For example, for `x + y + z` it returns `y + z`. |
| 765 Expression contractCompoundableBuiltin(ApplyBuiltinOperator e) { |
| 766 assert(isCompoundableBuiltin(e)); |
| 767 if (e.arguments.length > 2) { |
| 768 assert(e.operator == BuiltinOperator.StringConcatenate); |
| 769 return new ApplyBuiltinOperator(e.operator, e.arguments.skip(1).toList()); |
| 770 } else { |
| 771 return e.arguments[1]; |
| 772 } |
| 773 } |
| 774 |
| 765 void destroyVariableUse(VariableUse node) { | 775 void destroyVariableUse(VariableUse node) { |
| 766 --node.variable.readCount; | 776 --node.variable.readCount; |
| 767 } | 777 } |
| 768 | 778 |
| 769 Expression visitSetField(SetField node) { | 779 Expression visitSetField(SetField node) { |
| 770 allowRhsPropagation.add(true); | 780 allowRhsPropagation.add(true); |
| 771 node.value = visitExpression(node.value); | 781 node.value = visitExpression(node.value); |
| 772 if (isCompoundableBuiltin(node.value)) { | 782 if (isCompoundableBuiltin(node.value)) { |
| 773 ApplyBuiltinOperator rhs = node.value; | 783 ApplyBuiltinOperator rhs = node.value; |
| 774 Expression left = rhs.arguments[0]; | 784 Expression left = rhs.arguments[0]; |
| 775 Expression right = rhs.arguments[1]; | |
| 776 if (left is GetField && | 785 if (left is GetField && |
| 777 left.field == node.field && | 786 left.field == node.field && |
| 778 sameVariable(left.object, node.object)) { | 787 samePrimary(left.object, node.object)) { |
| 779 destroyVariableUse(left.object); | 788 destroyPrimaryExpression(left.object); |
| 780 node.compound = rhs.operator; | 789 node.compound = rhs.operator; |
| 781 node.value = right; | 790 node.value = contractCompoundableBuiltin(rhs); |
| 782 } | 791 } |
| 783 } | 792 } |
| 784 node.object = visitExpression(node.object); | 793 node.object = visitExpression(node.object); |
| 785 allowRhsPropagation.removeLast(); | 794 allowRhsPropagation.removeLast(); |
| 786 return node; | 795 return node; |
| 787 } | 796 } |
| 788 | 797 |
| 789 Expression visitGetField(GetField node) { | 798 Expression visitGetField(GetField node) { |
| 790 node.object = visitExpression(node.object); | 799 node.object = visitExpression(node.object); |
| 791 return node; | 800 return node; |
| 792 } | 801 } |
| 793 | 802 |
| 794 Expression visitGetStatic(GetStatic node) { | 803 Expression visitGetStatic(GetStatic node) { |
| 795 return node; | 804 return node; |
| 796 } | 805 } |
| 797 | 806 |
| 798 Expression visitSetStatic(SetStatic node) { | 807 Expression visitSetStatic(SetStatic node) { |
| 799 allowRhsPropagation.add(true); | 808 allowRhsPropagation.add(true); |
| 800 node.value = visitExpression(node.value); | 809 node.value = visitExpression(node.value); |
| 810 if (isCompoundableBuiltin(node.value)) { |
| 811 ApplyBuiltinOperator rhs = node.value; |
| 812 Expression left = rhs.arguments[0]; |
| 813 if (left is GetStatic && |
| 814 left.element == node.element && |
| 815 !left.useLazyGetter) { |
| 816 node.compound = rhs.operator; |
| 817 node.value = contractCompoundableBuiltin(rhs); |
| 818 } |
| 819 } |
| 801 allowRhsPropagation.removeLast(); | 820 allowRhsPropagation.removeLast(); |
| 802 return node; | 821 return node; |
| 803 } | 822 } |
| 804 | 823 |
| 805 Expression visitGetTypeTestProperty(GetTypeTestProperty node) { | 824 Expression visitGetTypeTestProperty(GetTypeTestProperty node) { |
| 806 node.object = visitExpression(node.object); | 825 node.object = visitExpression(node.object); |
| 807 return node; | 826 return node; |
| 808 } | 827 } |
| 809 | 828 |
| 810 Expression visitCreateBox(CreateBox node) { | 829 Expression visitCreateBox(CreateBox node) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 850 node.index = visitExpression(node.index); | 869 node.index = visitExpression(node.index); |
| 851 node.object = visitExpression(node.object); | 870 node.object = visitExpression(node.object); |
| 852 return node; | 871 return node; |
| 853 } | 872 } |
| 854 | 873 |
| 855 Expression visitSetIndex(SetIndex node) { | 874 Expression visitSetIndex(SetIndex node) { |
| 856 node.value = visitExpression(node.value); | 875 node.value = visitExpression(node.value); |
| 857 if (isCompoundableBuiltin(node.value)) { | 876 if (isCompoundableBuiltin(node.value)) { |
| 858 ApplyBuiltinOperator rhs = node.value; | 877 ApplyBuiltinOperator rhs = node.value; |
| 859 Expression left = rhs.arguments[0]; | 878 Expression left = rhs.arguments[0]; |
| 860 Expression right = rhs.arguments[1]; | |
| 861 if (left is GetIndex && | 879 if (left is GetIndex && |
| 862 sameVariable(left.object, node.object) && | 880 samePrimary(left.object, node.object) && |
| 863 sameVariable(left.index, node.index)) { | 881 samePrimary(left.index, node.index)) { |
| 864 destroyVariableUse(left.object); | 882 destroyPrimaryExpression(left.object); |
| 865 destroyVariableUse(left.index); | 883 destroyPrimaryExpression(left.index); |
| 866 node.compound = rhs.operator; | 884 node.compound = rhs.operator; |
| 867 node.value = right; | 885 node.value = contractCompoundableBuiltin(rhs); |
| 868 } | 886 } |
| 869 } | 887 } |
| 870 node.index = visitExpression(node.index); | 888 node.index = visitExpression(node.index); |
| 871 node.object = visitExpression(node.object); | 889 node.object = visitExpression(node.object); |
| 872 return node; | 890 return node; |
| 873 } | 891 } |
| 874 | 892 |
| 875 /// True if [operator] is a binary operator that always has the same value | 893 /// True if [operator] is a binary operator that always has the same value |
| 876 /// if its arguments are swapped. | 894 /// if its arguments are swapped. |
| 877 bool isSymmetricOperator(BuiltinOperator operator) { | 895 bool isSymmetricOperator(BuiltinOperator operator) { |
| (...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1349 VariableUseCallback callback; | 1367 VariableUseCallback callback; |
| 1350 | 1368 |
| 1351 VariableUseVisitor(this.callback); | 1369 VariableUseVisitor(this.callback); |
| 1352 | 1370 |
| 1353 visitVariableUse(VariableUse use) => callback(use); | 1371 visitVariableUse(VariableUse use) => callback(use); |
| 1354 | 1372 |
| 1355 static void visit(Expression node, VariableUseCallback callback) { | 1373 static void visit(Expression node, VariableUseCallback callback) { |
| 1356 new VariableUseVisitor(callback).visitExpression(node); | 1374 new VariableUseVisitor(callback).visitExpression(node); |
| 1357 } | 1375 } |
| 1358 } | 1376 } |
| 1377 |
| 1378 bool sameVariable(Expression e1, Expression e2) { |
| 1379 return e1 is VariableUse && e2 is VariableUse && e1.variable == e2.variable; |
| 1380 } |
| 1381 |
| 1382 /// True if [e1] and [e2] are primary expressions (expressions without |
| 1383 /// subexpressions) with the same value. |
| 1384 bool samePrimary(Expression e1, Expression e2) { |
| 1385 return sameVariable(e1, e2) || (e1 is This && e2 is This); |
| 1386 } |
| 1387 |
| 1388 /// Decrement the reference count for [e] if it is a variable use. |
| 1389 void destroyPrimaryExpression(Expression e) { |
| 1390 if (e is VariableUse) { |
| 1391 --e.variable.readCount; |
| 1392 } else { |
| 1393 assert(e is This); |
| 1394 } |
| 1395 } |
| OLD | NEW |