| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 abstract class HVisitor<R> { | 5 abstract class HVisitor<R> { |
| 6 R visitAdd(HAdd node); | 6 R visitAdd(HAdd node); |
| 7 R visitBailoutTarget(HBailoutTarget node); | 7 R visitBailoutTarget(HBailoutTarget node); |
| 8 R visitBitAnd(HBitAnd node); | 8 R visitBitAnd(HBitAnd node); |
| 9 R visitBitNot(HBitNot node); | 9 R visitBitNot(HBitNot node); |
| 10 R visitBitOr(HBitOr node); | 10 R visitBitOr(HBitOr node); |
| (...skipping 723 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 734 bool dominates(HBasicBlock other) { | 734 bool dominates(HBasicBlock other) { |
| 735 do { | 735 do { |
| 736 if (this === other) return true; | 736 if (this === other) return true; |
| 737 other = other.dominator; | 737 other = other.dominator; |
| 738 } while (other !== null && other.id >= id); | 738 } while (other !== null && other.id >= id); |
| 739 return false; | 739 return false; |
| 740 } | 740 } |
| 741 } | 741 } |
| 742 | 742 |
| 743 | 743 |
| 744 class HInstruction implements Spannable { | 744 abstract class HInstruction implements Spannable { |
| 745 Element sourceElement; | 745 Element sourceElement; |
| 746 SourceFileLocation sourcePosition; | 746 SourceFileLocation sourcePosition; |
| 747 | 747 |
| 748 final int id; | 748 final int id; |
| 749 static int idCounter; | 749 static int idCounter; |
| 750 | 750 |
| 751 final List<HInstruction> inputs; | 751 final List<HInstruction> inputs; |
| 752 final List<HInstruction> usedBy; | 752 final List<HInstruction> usedBy; |
| 753 | 753 |
| 754 HBasicBlock block; | 754 HBasicBlock block; |
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1053 bool isConstant() => false; | 1053 bool isConstant() => false; |
| 1054 bool isConstantBoolean() => false; | 1054 bool isConstantBoolean() => false; |
| 1055 bool isConstantNull() => false; | 1055 bool isConstantNull() => false; |
| 1056 bool isConstantNumber() => false; | 1056 bool isConstantNumber() => false; |
| 1057 bool isConstantInteger() => false; | 1057 bool isConstantInteger() => false; |
| 1058 bool isConstantString() => false; | 1058 bool isConstantString() => false; |
| 1059 bool isConstantList() => false; | 1059 bool isConstantList() => false; |
| 1060 bool isConstantMap() => false; | 1060 bool isConstantMap() => false; |
| 1061 bool isConstantFalse() => false; | 1061 bool isConstantFalse() => false; |
| 1062 bool isConstantTrue() => false; | 1062 bool isConstantTrue() => false; |
| 1063 bool isConstantSentinel() => false; |
| 1063 | 1064 |
| 1064 bool isValid() { | 1065 bool isValid() { |
| 1065 HValidator validator = new HValidator(); | 1066 HValidator validator = new HValidator(); |
| 1066 validator.currentBlock = block; | 1067 validator.currentBlock = block; |
| 1067 validator.visitInstruction(this); | 1068 validator.visitInstruction(this); |
| 1068 return validator.isValid; | 1069 return validator.isValid; |
| 1069 } | 1070 } |
| 1070 | 1071 |
| 1071 /** | 1072 /** |
| 1072 * The code for computing a bailout environment, and the code | 1073 * The code for computing a bailout environment, and the code |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1233 ? HType.INTEGER | 1234 ? HType.INTEGER |
| 1234 : super.computeDesiredTypeForInput(input, types); | 1235 : super.computeDesiredTypeForInput(input, types); |
| 1235 } | 1236 } |
| 1236 | 1237 |
| 1237 accept(HVisitor visitor) => visitor.visitIntegerCheck(this); | 1238 accept(HVisitor visitor) => visitor.visitIntegerCheck(this); |
| 1238 int typeCode() => HInstruction.INTEGER_CHECK_TYPECODE; | 1239 int typeCode() => HInstruction.INTEGER_CHECK_TYPECODE; |
| 1239 bool typeEquals(other) => other is HIntegerCheck; | 1240 bool typeEquals(other) => other is HIntegerCheck; |
| 1240 bool dataEquals(HInstruction other) => true; | 1241 bool dataEquals(HInstruction other) => true; |
| 1241 } | 1242 } |
| 1242 | 1243 |
| 1243 class HConditionalBranch extends HControlFlow { | 1244 abstract class HConditionalBranch extends HControlFlow { |
| 1244 HConditionalBranch(inputs) : super(inputs); | 1245 HConditionalBranch(inputs) : super(inputs); |
| 1245 HInstruction get condition => inputs[0]; | 1246 HInstruction get condition => inputs[0]; |
| 1246 HBasicBlock get trueBranch => block.successors[0]; | 1247 HBasicBlock get trueBranch => block.successors[0]; |
| 1247 HBasicBlock get falseBranch => block.successors[1]; | 1248 HBasicBlock get falseBranch => block.successors[1]; |
| 1248 abstract toString(); | 1249 abstract toString(); |
| 1249 } | 1250 } |
| 1250 | 1251 |
| 1251 class HControlFlow extends HInstruction { | 1252 abstract class HControlFlow extends HInstruction { |
| 1252 HControlFlow(inputs) : super(inputs); | 1253 HControlFlow(inputs) : super(inputs); |
| 1253 abstract toString(); | 1254 abstract toString(); |
| 1254 void prepareGvn(HTypeMap types) { | 1255 void prepareGvn(HTypeMap types) { |
| 1255 // Control flow does not have side-effects. | 1256 // Control flow does not have side-effects. |
| 1256 } | 1257 } |
| 1257 bool isControlFlow() => true; | 1258 bool isControlFlow() => true; |
| 1258 bool isJsStatement(HTypeMap types) => true; | 1259 bool isJsStatement(HTypeMap types) => true; |
| 1259 } | 1260 } |
| 1260 | 1261 |
| 1261 class HInvoke extends HInstruction { | 1262 abstract class HInvoke extends HInstruction { |
| 1262 /** | 1263 /** |
| 1263 * The first argument must be the target: either an [HStatic] node, or | 1264 * The first argument must be the target: either an [HStatic] node, or |
| 1264 * the receiver of a method-call. The remaining inputs are the arguments | 1265 * the receiver of a method-call. The remaining inputs are the arguments |
| 1265 * to the invocation. | 1266 * to the invocation. |
| 1266 */ | 1267 */ |
| 1267 HInvoke(List<HInstruction> inputs) : super(inputs); | 1268 HInvoke(List<HInstruction> inputs) : super(inputs); |
| 1268 static const int ARGUMENTS_OFFSET = 1; | 1269 static const int ARGUMENTS_OFFSET = 1; |
| 1269 | 1270 |
| 1270 // TODO(floitsch): make class abstract instead of adding an abstract method. | 1271 // TODO(floitsch): make class abstract instead of adding an abstract method. |
| 1271 abstract accept(HVisitor visitor); | 1272 abstract accept(HVisitor visitor); |
| 1272 } | 1273 } |
| 1273 | 1274 |
| 1274 class HInvokeDynamic extends HInvoke { | 1275 abstract class HInvokeDynamic extends HInvoke { |
| 1275 final Selector selector; | 1276 final Selector selector; |
| 1276 Element element; | 1277 Element element; |
| 1277 | 1278 |
| 1278 HInvokeDynamic(this.selector, this.element, List<HInstruction> inputs) | 1279 HInvokeDynamic(this.selector, this.element, List<HInstruction> inputs) |
| 1279 : super(inputs); | 1280 : super(inputs); |
| 1280 toString() => 'invoke dynamic: $selector'; | 1281 toString() => 'invoke dynamic: $selector'; |
| 1281 HInstruction get receiver => inputs[0]; | 1282 HInstruction get receiver => inputs[0]; |
| 1282 | 1283 |
| 1283 // TODO(floitsch): make class abstract instead of adding an abstract method. | 1284 // TODO(floitsch): make class abstract instead of adding an abstract method. |
| 1284 abstract accept(HVisitor visitor); | 1285 abstract accept(HVisitor visitor); |
| 1285 } | 1286 } |
| 1286 | 1287 |
| 1287 class HInvokeClosure extends HInvokeDynamic { | 1288 class HInvokeClosure extends HInvokeDynamic { |
| 1288 HInvokeClosure(Selector selector, List<HInstruction> inputs) | 1289 HInvokeClosure(Selector selector, List<HInstruction> inputs) |
| 1289 : super(selector, null, inputs); | 1290 : super(selector, null, inputs); |
| 1290 accept(HVisitor visitor) => visitor.visitInvokeClosure(this); | 1291 accept(HVisitor visitor) => visitor.visitInvokeClosure(this); |
| 1291 } | 1292 } |
| 1292 | 1293 |
| 1293 class HInvokeDynamicMethod extends HInvokeDynamic { | 1294 class HInvokeDynamicMethod extends HInvokeDynamic { |
| 1294 HInvokeDynamicMethod(Selector selector, List<HInstruction> inputs) | 1295 HInvokeDynamicMethod(Selector selector, List<HInstruction> inputs) |
| 1295 : super(selector, null, inputs); | 1296 : super(selector, null, inputs); |
| 1296 toString() => 'invoke dynamic method: $selector'; | 1297 toString() => 'invoke dynamic method: $selector'; |
| 1297 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this); | 1298 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this); |
| 1298 } | 1299 } |
| 1299 | 1300 |
| 1300 class HInvokeDynamicField extends HInvokeDynamic { | 1301 abstract class HInvokeDynamicField extends HInvokeDynamic { |
| 1301 HInvokeDynamicField(Selector selector, Element element, | 1302 HInvokeDynamicField(Selector selector, Element element, |
| 1302 List<HInstruction> inputs) | 1303 List<HInstruction> inputs) |
| 1303 : super(selector, element, inputs); | 1304 : super(selector, element, inputs); |
| 1304 toString() => 'invoke dynamic field: $selector'; | 1305 toString() => 'invoke dynamic field: $selector'; |
| 1305 | 1306 |
| 1306 // TODO(floitsch): make class abstract instead of adding an abstract method. | 1307 // TODO(floitsch): make class abstract instead of adding an abstract method. |
| 1307 abstract accept(HVisitor visitor); | 1308 abstract accept(HVisitor visitor); |
| 1308 } | 1309 } |
| 1309 | 1310 |
| 1310 class HInvokeDynamicGetter extends HInvokeDynamicField { | 1311 class HInvokeDynamicGetter extends HInvokeDynamicField { |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1563 } | 1564 } |
| 1564 | 1565 |
| 1565 class HForeignNew extends HForeign { | 1566 class HForeignNew extends HForeign { |
| 1566 ClassElement element; | 1567 ClassElement element; |
| 1567 HForeignNew(this.element, List<HInstruction> inputs) | 1568 HForeignNew(this.element, List<HInstruction> inputs) |
| 1568 : super(const LiteralDartString("new"), | 1569 : super(const LiteralDartString("new"), |
| 1569 const LiteralDartString("Object"), inputs); | 1570 const LiteralDartString("Object"), inputs); |
| 1570 accept(HVisitor visitor) => visitor.visitForeignNew(this); | 1571 accept(HVisitor visitor) => visitor.visitForeignNew(this); |
| 1571 } | 1572 } |
| 1572 | 1573 |
| 1573 class HInvokeBinary extends HInvokeStatic { | 1574 abstract class HInvokeBinary extends HInvokeStatic { |
| 1574 HInvokeBinary(HStatic target, HInstruction left, HInstruction right) | 1575 HInvokeBinary(HStatic target, HInstruction left, HInstruction right) |
| 1575 : super(<HInstruction>[target, left, right]); | 1576 : super(<HInstruction>[target, left, right]); |
| 1576 | 1577 |
| 1577 HInstruction get left => inputs[1]; | 1578 HInstruction get left => inputs[1]; |
| 1578 HInstruction get right => inputs[2]; | 1579 HInstruction get right => inputs[2]; |
| 1579 | 1580 |
| 1580 abstract BinaryOperation operation(ConstantSystem constantSystem); | 1581 abstract BinaryOperation operation(ConstantSystem constantSystem); |
| 1581 abstract isBuiltin(HTypeMap types); | 1582 abstract isBuiltin(HTypeMap types); |
| 1582 } | 1583 } |
| 1583 | 1584 |
| 1584 class HBinaryArithmetic extends HInvokeBinary { | 1585 abstract class HBinaryArithmetic extends HInvokeBinary { |
| 1585 HBinaryArithmetic(HStatic target, HInstruction left, HInstruction right) | 1586 HBinaryArithmetic(HStatic target, HInstruction left, HInstruction right) |
| 1586 : super(target, left, right); | 1587 : super(target, left, right); |
| 1587 | 1588 |
| 1588 void prepareGvn(HTypeMap types) { | 1589 void prepareGvn(HTypeMap types) { |
| 1589 // An arithmetic expression can take part in global value | 1590 // An arithmetic expression can take part in global value |
| 1590 // numbering and do not have any side-effects if we know that all | 1591 // numbering and do not have any side-effects if we know that all |
| 1591 // inputs are numbers. | 1592 // inputs are numbers. |
| 1592 if (isBuiltin(types)) { | 1593 if (isBuiltin(types)) { |
| 1593 clearAllSideEffects(); | 1594 clearAllSideEffects(); |
| 1594 setUseGvn(); | 1595 setUseGvn(); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1630 // to the array case. | 1631 // to the array case. |
| 1631 if (input == right && left.isNumber(types)) return HType.NUMBER; | 1632 if (input == right && left.isNumber(types)) return HType.NUMBER; |
| 1632 return HType.UNKNOWN; | 1633 return HType.UNKNOWN; |
| 1633 } | 1634 } |
| 1634 | 1635 |
| 1635 HType computeLikelyType(HTypeMap types) { | 1636 HType computeLikelyType(HTypeMap types) { |
| 1636 if (left.isTypeUnknown(types)) return HType.NUMBER; | 1637 if (left.isTypeUnknown(types)) return HType.NUMBER; |
| 1637 return HType.UNKNOWN; | 1638 return HType.UNKNOWN; |
| 1638 } | 1639 } |
| 1639 | 1640 |
| 1640 // TODO(1603): The class should be marked as abstract. | |
| 1641 abstract BinaryOperation operation(ConstantSystem constantSystem); | 1641 abstract BinaryOperation operation(ConstantSystem constantSystem); |
| 1642 } | 1642 } |
| 1643 | 1643 |
| 1644 class HAdd extends HBinaryArithmetic { | 1644 class HAdd extends HBinaryArithmetic { |
| 1645 HAdd(HStatic target, HInstruction left, HInstruction right) | 1645 HAdd(HStatic target, HInstruction left, HInstruction right) |
| 1646 : super(target, left, right); | 1646 : super(target, left, right); |
| 1647 accept(HVisitor visitor) => visitor.visitAdd(this); | 1647 accept(HVisitor visitor) => visitor.visitAdd(this); |
| 1648 | 1648 |
| 1649 BinaryOperation operation(ConstantSystem constantSystem) | 1649 BinaryOperation operation(ConstantSystem constantSystem) |
| 1650 => constantSystem.add; | 1650 => constantSystem.add; |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1744 BinaryOperation operation(ConstantSystem constantSystem) | 1744 BinaryOperation operation(ConstantSystem constantSystem) |
| 1745 => constantSystem.truncatingDivide; | 1745 => constantSystem.truncatingDivide; |
| 1746 int typeCode() => HInstruction.TRUNCATING_DIVIDE_TYPECODE; | 1746 int typeCode() => HInstruction.TRUNCATING_DIVIDE_TYPECODE; |
| 1747 bool typeEquals(other) => other is HTruncatingDivide; | 1747 bool typeEquals(other) => other is HTruncatingDivide; |
| 1748 bool dataEquals(HInstruction other) => true; | 1748 bool dataEquals(HInstruction other) => true; |
| 1749 } | 1749 } |
| 1750 | 1750 |
| 1751 | 1751 |
| 1752 // TODO(floitsch): Should HBinaryArithmetic really be the super class of | 1752 // TODO(floitsch): Should HBinaryArithmetic really be the super class of |
| 1753 // HBinaryBitOp? | 1753 // HBinaryBitOp? |
| 1754 class HBinaryBitOp extends HBinaryArithmetic { | 1754 abstract class HBinaryBitOp extends HBinaryArithmetic { |
| 1755 HBinaryBitOp(HStatic target, HInstruction left, HInstruction right) | 1755 HBinaryBitOp(HStatic target, HInstruction left, HInstruction right) |
| 1756 : super(target, left, right); | 1756 : super(target, left, right); |
| 1757 | 1757 |
| 1758 HType computeTypeFromInputTypes(HTypeMap types) { | 1758 HType computeTypeFromInputTypes(HTypeMap types) { |
| 1759 // All bitwise operations on primitive types either produce an | 1759 // All bitwise operations on primitive types either produce an |
| 1760 // integer or throw an error. | 1760 // integer or throw an error. |
| 1761 if (left.isPrimitive(types)) return HType.INTEGER; | 1761 if (left.isPrimitive(types)) return HType.INTEGER; |
| 1762 return HType.UNKNOWN; | 1762 return HType.UNKNOWN; |
| 1763 } | 1763 } |
| 1764 | 1764 |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1849 : super(target, left, right); | 1849 : super(target, left, right); |
| 1850 accept(HVisitor visitor) => visitor.visitBitXor(this); | 1850 accept(HVisitor visitor) => visitor.visitBitXor(this); |
| 1851 | 1851 |
| 1852 BinaryOperation operation(ConstantSystem constantSystem) | 1852 BinaryOperation operation(ConstantSystem constantSystem) |
| 1853 => constantSystem.bitXor; | 1853 => constantSystem.bitXor; |
| 1854 int typeCode() => HInstruction.BIT_XOR_TYPECODE; | 1854 int typeCode() => HInstruction.BIT_XOR_TYPECODE; |
| 1855 bool typeEquals(other) => other is HBitXor; | 1855 bool typeEquals(other) => other is HBitXor; |
| 1856 bool dataEquals(HInstruction other) => true; | 1856 bool dataEquals(HInstruction other) => true; |
| 1857 } | 1857 } |
| 1858 | 1858 |
| 1859 class HInvokeUnary extends HInvokeStatic { | 1859 abstract class HInvokeUnary extends HInvokeStatic { |
| 1860 HInvokeUnary(HStatic target, HInstruction input) | 1860 HInvokeUnary(HStatic target, HInstruction input) |
| 1861 : super(<HInstruction>[target, input]); | 1861 : super(<HInstruction>[target, input]); |
| 1862 | 1862 |
| 1863 HInstruction get operand => inputs[1]; | 1863 HInstruction get operand => inputs[1]; |
| 1864 | 1864 |
| 1865 void prepareGvn(HTypeMap types) { | 1865 void prepareGvn(HTypeMap types) { |
| 1866 // A unary arithmetic expression can take part in global value | 1866 // A unary arithmetic expression can take part in global value |
| 1867 // numbering and does not have any side-effects if its input is a | 1867 // numbering and does not have any side-effects if its input is a |
| 1868 // number. | 1868 // number. |
| 1869 if (isBuiltin(types)) { | 1869 if (isBuiltin(types)) { |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2179 assert(isLogicalOperator()); | 2179 assert(isLogicalOperator()); |
| 2180 if (logicalOperatorType == IS_AND) return "&&"; | 2180 if (logicalOperatorType == IS_AND) return "&&"; |
| 2181 assert(logicalOperatorType == IS_OR); | 2181 assert(logicalOperatorType == IS_OR); |
| 2182 return "||"; | 2182 return "||"; |
| 2183 } | 2183 } |
| 2184 | 2184 |
| 2185 toString() => 'phi'; | 2185 toString() => 'phi'; |
| 2186 accept(HVisitor visitor) => visitor.visitPhi(this); | 2186 accept(HVisitor visitor) => visitor.visitPhi(this); |
| 2187 } | 2187 } |
| 2188 | 2188 |
| 2189 class HRelational extends HInvokeBinary { | 2189 abstract class HRelational extends HInvokeBinary { |
| 2190 bool usesBoolifiedInterceptor = false; | 2190 bool usesBoolifiedInterceptor = false; |
| 2191 HRelational(HStatic target, HInstruction left, HInstruction right) | 2191 HRelational(HStatic target, HInstruction left, HInstruction right) |
| 2192 : super(target, left, right); | 2192 : super(target, left, right); |
| 2193 | 2193 |
| 2194 void prepareGvn(HTypeMap types) { | 2194 void prepareGvn(HTypeMap types) { |
| 2195 // Relational expressions can take part in global value numbering | 2195 // Relational expressions can take part in global value numbering |
| 2196 // and do not have any side-effects if we know all the inputs are | 2196 // and do not have any side-effects if we know all the inputs are |
| 2197 // numbers. This can be improved for at least equality. | 2197 // numbers. This can be improved for at least equality. |
| 2198 if (isBuiltin(types)) { | 2198 if (isBuiltin(types)) { |
| 2199 clearAllSideEffects(); | 2199 clearAllSideEffects(); |
| (...skipping 717 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2917 HBasicBlock get start => expression.start; | 2917 HBasicBlock get start => expression.start; |
| 2918 HBasicBlock get end { | 2918 HBasicBlock get end { |
| 2919 // We don't create a switch block if there are no cases. | 2919 // We don't create a switch block if there are no cases. |
| 2920 assert(!statements.isEmpty()); | 2920 assert(!statements.isEmpty()); |
| 2921 return statements.last().end; | 2921 return statements.last().end; |
| 2922 } | 2922 } |
| 2923 | 2923 |
| 2924 bool accept(HStatementInformationVisitor visitor) => | 2924 bool accept(HStatementInformationVisitor visitor) => |
| 2925 visitor.visitSwitchInfo(this); | 2925 visitor.visitSwitchInfo(this); |
| 2926 } | 2926 } |
| OLD | NEW |