| 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 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 abstract class HVisitor<R> { | 7 abstract class HVisitor<R> { |
| 8 R visitAdd(HAdd node); | 8 R visitAdd(HAdd node); |
| 9 R visitBailoutTarget(HBailoutTarget node); | 9 R visitBailoutTarget(HBailoutTarget node); |
| 10 R visitBitAnd(HBitAnd node); | 10 R visitBitAnd(HBitAnd node); |
| (...skipping 881 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 892 * than the provided type for [this]. | 892 * than the provided type for [this]. |
| 893 * | 893 * |
| 894 * Examples: the likely type of [:x == y:] is a boolean. In most cases this | 894 * Examples: the likely type of [:x == y:] is a boolean. In most cases this |
| 895 * cannot be guaranteed, but when merging types we still want to use this | 895 * cannot be guaranteed, but when merging types we still want to use this |
| 896 * information. | 896 * information. |
| 897 * | 897 * |
| 898 * Similarily the [HAdd] instruction is likely a number. Note that, even if | 898 * Similarily the [HAdd] instruction is likely a number. Note that, even if |
| 899 * the incoming type is already set to integer, the likely type might still | 899 * the incoming type is already set to integer, the likely type might still |
| 900 * just return the number type. | 900 * just return the number type. |
| 901 */ | 901 */ |
| 902 HType computeLikelyType(HTypeMap types) => types[this]; | 902 HType computeLikelyType(HTypeMap types, Compiler compiler) => types[this]; |
| 903 | 903 |
| 904 /** | 904 /** |
| 905 * Compute the type of the instruction by propagating the input types through | 905 * Compute the type of the instruction by propagating the input types through |
| 906 * the instruction. | 906 * the instruction. |
| 907 * | 907 * |
| 908 * By default just copy the guaranteed type. | 908 * By default just copy the guaranteed type. |
| 909 */ | 909 */ |
| 910 HType computeTypeFromInputTypes(HTypeMap types) => guaranteedType; | 910 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) { |
| 911 return guaranteedType; |
| 912 } |
| 911 | 913 |
| 912 /** | 914 /** |
| 913 * Compute the desired type for the the given [input]. Aside from using | 915 * Compute the desired type for the the given [input]. Aside from using |
| 914 * other inputs to compute the desired type one should also use | 916 * other inputs to compute the desired type one should also use |
| 915 * the given [types] which, during the invocation of this method, | 917 * the given [types] which, during the invocation of this method, |
| 916 * represents the desired type of [this]. | 918 * represents the desired type of [this]. |
| 917 */ | 919 */ |
| 918 HType computeDesiredTypeForInput(HInstruction input, HTypeMap types) { | 920 HType computeDesiredTypeForInput(HInstruction input, |
| 921 HTypeMap types, |
| 922 Compiler compiler) { |
| 919 return HType.UNKNOWN; | 923 return HType.UNKNOWN; |
| 920 } | 924 } |
| 921 | 925 |
| 922 bool isInBasicBlock() => block != null; | 926 bool isInBasicBlock() => block != null; |
| 923 | 927 |
| 924 String inputsToString() { | 928 String inputsToString() { |
| 925 void addAsCommaSeparated(StringBuffer buffer, List<HInstruction> list) { | 929 void addAsCommaSeparated(StringBuffer buffer, List<HInstruction> list) { |
| 926 for (int i = 0; i < list.length; i++) { | 930 for (int i = 0; i < list.length; i++) { |
| 927 if (i != 0) buffer.add(', '); | 931 if (i != 0) buffer.add(', '); |
| 928 buffer.add("@${list[i].id}"); | 932 buffer.add("@${list[i].id}"); |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1202 bool isEnabled = false; | 1206 bool isEnabled = false; |
| 1203 | 1207 |
| 1204 HTypeGuard(this.guardedType, HInstruction guarded, HInstruction bailoutTarget) | 1208 HTypeGuard(this.guardedType, HInstruction guarded, HInstruction bailoutTarget) |
| 1205 : super(<HInstruction>[guarded, bailoutTarget]); | 1209 : super(<HInstruction>[guarded, bailoutTarget]); |
| 1206 | 1210 |
| 1207 HInstruction get guarded => inputs[0]; | 1211 HInstruction get guarded => inputs[0]; |
| 1208 HInstruction get checkedInput => guarded; | 1212 HInstruction get checkedInput => guarded; |
| 1209 HBailoutTarget get bailoutTarget => inputs[1]; | 1213 HBailoutTarget get bailoutTarget => inputs[1]; |
| 1210 int get state => bailoutTarget.state; | 1214 int get state => bailoutTarget.state; |
| 1211 | 1215 |
| 1212 HType computeTypeFromInputTypes(HTypeMap types) { | 1216 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) { |
| 1213 return isEnabled ? guardedType : types[guarded]; | 1217 return isEnabled ? guardedType : types[guarded]; |
| 1214 } | 1218 } |
| 1215 | 1219 |
| 1216 HType get guaranteedType => isEnabled ? guardedType : HType.UNKNOWN; | 1220 HType get guaranteedType => isEnabled ? guardedType : HType.UNKNOWN; |
| 1217 | 1221 |
| 1218 bool isControlFlow() => true; | 1222 bool isControlFlow() => true; |
| 1219 | 1223 |
| 1220 bool isJsStatement(HTypeMap types) => isEnabled; | 1224 bool isJsStatement(HTypeMap types) => isEnabled; |
| 1221 | 1225 |
| 1222 accept(HVisitor visitor) => visitor.visitTypeGuard(this); | 1226 accept(HVisitor visitor) => visitor.visitTypeGuard(this); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1254 class HIntegerCheck extends HCheck { | 1258 class HIntegerCheck extends HCheck { |
| 1255 bool alwaysFalse = false; | 1259 bool alwaysFalse = false; |
| 1256 | 1260 |
| 1257 HIntegerCheck(value) : super(<HInstruction>[value]); | 1261 HIntegerCheck(value) : super(<HInstruction>[value]); |
| 1258 | 1262 |
| 1259 HInstruction get value => inputs[0]; | 1263 HInstruction get value => inputs[0]; |
| 1260 bool isControlFlow() => true; | 1264 bool isControlFlow() => true; |
| 1261 | 1265 |
| 1262 HType get guaranteedType => HType.INTEGER; | 1266 HType get guaranteedType => HType.INTEGER; |
| 1263 | 1267 |
| 1264 HType computeDesiredTypeForInput(HInstruction input, HTypeMap types) { | 1268 HType computeDesiredTypeForInput(HInstruction input, |
| 1269 HTypeMap types, |
| 1270 Compiler compiler) { |
| 1265 // If the desired type of the input is already a number, we want | 1271 // If the desired type of the input is already a number, we want |
| 1266 // to specialize it to an integer. | 1272 // to specialize it to an integer. |
| 1267 return input.isNumber(types) | 1273 return input.isNumber(types) |
| 1268 ? HType.INTEGER | 1274 ? HType.INTEGER |
| 1269 : super.computeDesiredTypeForInput(input, types); | 1275 : super.computeDesiredTypeForInput(input, types, compiler); |
| 1270 } | 1276 } |
| 1271 | 1277 |
| 1272 accept(HVisitor visitor) => visitor.visitIntegerCheck(this); | 1278 accept(HVisitor visitor) => visitor.visitIntegerCheck(this); |
| 1273 int typeCode() => HInstruction.INTEGER_CHECK_TYPECODE; | 1279 int typeCode() => HInstruction.INTEGER_CHECK_TYPECODE; |
| 1274 bool typeEquals(other) => other is HIntegerCheck; | 1280 bool typeEquals(other) => other is HIntegerCheck; |
| 1275 bool dataEquals(HInstruction other) => true; | 1281 bool dataEquals(HInstruction other) => true; |
| 1276 } | 1282 } |
| 1277 | 1283 |
| 1278 abstract class HConditionalBranch extends HControlFlow { | 1284 abstract class HConditionalBranch extends HControlFlow { |
| 1279 HConditionalBranch(inputs) : super(inputs); | 1285 HConditionalBranch(inputs) : super(inputs); |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1387 HInvokeStatic(inputs, [HType knownType = HType.UNKNOWN]) : super(inputs) { | 1393 HInvokeStatic(inputs, [HType knownType = HType.UNKNOWN]) : super(inputs) { |
| 1388 guaranteedType = knownType; | 1394 guaranteedType = knownType; |
| 1389 } | 1395 } |
| 1390 | 1396 |
| 1391 toString() => 'invoke static: ${element.name}'; | 1397 toString() => 'invoke static: ${element.name}'; |
| 1392 accept(HVisitor visitor) => visitor.visitInvokeStatic(this); | 1398 accept(HVisitor visitor) => visitor.visitInvokeStatic(this); |
| 1393 int typeCode() => HInstruction.INVOKE_STATIC_TYPECODE; | 1399 int typeCode() => HInstruction.INVOKE_STATIC_TYPECODE; |
| 1394 Element get element => target.element; | 1400 Element get element => target.element; |
| 1395 HStatic get target => inputs[0]; | 1401 HStatic get target => inputs[0]; |
| 1396 | 1402 |
| 1397 HType computeDesiredTypeForInput(HInstruction input, HTypeMap types) { | 1403 HType computeDesiredTypeForInput(HInstruction input, |
| 1404 HTypeMap types, |
| 1405 Compiler compiler) { |
| 1398 // TODO(floitsch): we want the target to be a function. | 1406 // TODO(floitsch): we want the target to be a function. |
| 1399 if (input == target) return HType.UNKNOWN; | 1407 if (input == target) return HType.UNKNOWN; |
| 1400 return computeDesiredTypeForNonTargetInput(input, types); | 1408 return computeDesiredTypeForNonTargetInput(input, types, compiler); |
| 1401 } | 1409 } |
| 1402 | 1410 |
| 1403 HType computeDesiredTypeForNonTargetInput(HInstruction input, | 1411 HType computeDesiredTypeForNonTargetInput(HInstruction input, |
| 1404 HTypeMap types) { | 1412 HTypeMap types, |
| 1413 Compiler compiler) { |
| 1405 return HType.UNKNOWN; | 1414 return HType.UNKNOWN; |
| 1406 } | 1415 } |
| 1407 } | 1416 } |
| 1408 | 1417 |
| 1409 class HInvokeSuper extends HInvokeStatic { | 1418 class HInvokeSuper extends HInvokeStatic { |
| 1410 final bool isSetter; | 1419 final bool isSetter; |
| 1411 HInvokeSuper(inputs, {this.isSetter: false}) : super(inputs); | 1420 HInvokeSuper(inputs, {this.isSetter: false}) : super(inputs); |
| 1412 toString() => 'invoke super: ${element.name}'; | 1421 toString() => 'invoke super: ${element.name}'; |
| 1413 accept(HVisitor visitor) => visitor.visitInvokeSuper(this); | 1422 accept(HVisitor visitor) => visitor.visitInvokeSuper(this); |
| 1414 | 1423 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1440 return selector.isCall() | 1449 return selector.isCall() |
| 1441 && inputs[1].isExtendableArray(types) | 1450 && inputs[1].isExtendableArray(types) |
| 1442 && selector.name == const SourceString('removeLast') | 1451 && selector.name == const SourceString('removeLast') |
| 1443 && selector.argumentCount == 0; | 1452 && selector.argumentCount == 0; |
| 1444 } | 1453 } |
| 1445 | 1454 |
| 1446 bool isLengthGetterOnStringOrArray(HTypeMap types) { | 1455 bool isLengthGetterOnStringOrArray(HTypeMap types) { |
| 1447 return isLengthGetter() && inputs[1].isIndexablePrimitive(types); | 1456 return isLengthGetter() && inputs[1].isIndexablePrimitive(types); |
| 1448 } | 1457 } |
| 1449 | 1458 |
| 1450 HType computeLikelyType(HTypeMap types) { | 1459 HType computeLikelyType(HTypeMap types, Compiler compiler) { |
| 1451 // In general a length getter or method returns an int. | 1460 // In general a length getter or method returns an int. |
| 1452 if (isLengthGetter()) return HType.INTEGER; | 1461 if (isLengthGetter()) return HType.INTEGER; |
| 1453 return HType.UNKNOWN; | 1462 return HType.UNKNOWN; |
| 1454 } | 1463 } |
| 1455 | 1464 |
| 1456 HType computeTypeFromInputTypes(HTypeMap types) { | 1465 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) { |
| 1457 if (isLengthGetterOnStringOrArray(types)) return HType.INTEGER; | 1466 if (isLengthGetterOnStringOrArray(types)) return HType.INTEGER; |
| 1458 return HType.UNKNOWN; | 1467 return HType.UNKNOWN; |
| 1459 } | 1468 } |
| 1460 | 1469 |
| 1461 HType computeDesiredTypeForNonTargetInput(HInstruction input, | 1470 HType computeDesiredTypeForNonTargetInput(HInstruction input, |
| 1462 HTypeMap types) { | 1471 HTypeMap types, |
| 1472 Compiler compiler) { |
| 1463 // If the first argument is a string or an array and we invoke methods | 1473 // If the first argument is a string or an array and we invoke methods |
| 1464 // on it that mutate it, then we want to restrict the incoming type to be | 1474 // on it that mutate it, then we want to restrict the incoming type to be |
| 1465 // a mutable array. | 1475 // a mutable array. |
| 1466 if (input == inputs[1] && input.isIndexablePrimitive(types)) { | 1476 if (input == inputs[1] && input.isIndexablePrimitive(types)) { |
| 1467 // TODO(kasperl): Should we check that the selector is a call selector? | 1477 // TODO(kasperl): Should we check that the selector is a call selector? |
| 1468 if (selector.name == const SourceString('add') | 1478 if (selector.name == const SourceString('add') |
| 1469 || selector.name == const SourceString('removeLast')) { | 1479 || selector.name == const SourceString('removeLast')) { |
| 1470 return HType.MUTABLE_ARRAY; | 1480 return HType.MUTABLE_ARRAY; |
| 1471 } | 1481 } |
| 1472 } | 1482 } |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1632 if (isBuiltin(types)) { | 1642 if (isBuiltin(types)) { |
| 1633 setUseGvn(); | 1643 setUseGvn(); |
| 1634 } else { | 1644 } else { |
| 1635 setAllSideEffects(); | 1645 setAllSideEffects(); |
| 1636 } | 1646 } |
| 1637 } | 1647 } |
| 1638 | 1648 |
| 1639 bool isBuiltin(HTypeMap types) | 1649 bool isBuiltin(HTypeMap types) |
| 1640 => left.isNumber(types) && right.isNumber(types); | 1650 => left.isNumber(types) && right.isNumber(types); |
| 1641 | 1651 |
| 1642 HType computeTypeFromInputTypes(HTypeMap types) { | 1652 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) { |
| 1643 if (left.isInteger(types) && right.isInteger(types)) return HType.INTEGER; | 1653 if (left.isInteger(types) && right.isInteger(types)) return HType.INTEGER; |
| 1644 if (left.isNumber(types)) { | 1654 if (left.isNumber(types)) { |
| 1645 if (left.isDouble(types) || right.isDouble(types)) return HType.DOUBLE; | 1655 if (left.isDouble(types) || right.isDouble(types)) return HType.DOUBLE; |
| 1646 return HType.NUMBER; | 1656 return HType.NUMBER; |
| 1647 } | 1657 } |
| 1648 return HType.UNKNOWN; | 1658 return HType.UNKNOWN; |
| 1649 } | 1659 } |
| 1650 | 1660 |
| 1651 HType computeDesiredTypeForNonTargetInput(HInstruction input, | 1661 HType computeDesiredTypeForNonTargetInput(HInstruction input, |
| 1652 HTypeMap types) { | 1662 HTypeMap types, |
| 1663 Compiler compiler) { |
| 1653 HType propagatedType = types[this]; | 1664 HType propagatedType = types[this]; |
| 1654 // If the desired output type should be an integer we want to get two | 1665 // If the desired output type should be an integer we want to get two |
| 1655 // integers as arguments. | 1666 // integers as arguments. |
| 1656 if (propagatedType.isInteger()) return HType.INTEGER; | 1667 if (propagatedType.isInteger()) return HType.INTEGER; |
| 1657 // If the outgoing type should be a number we can get that if both inputs | 1668 // If the outgoing type should be a number we can get that if both inputs |
| 1658 // are numbers. If we don't know the outgoing type we try to make it a | 1669 // are numbers. If we don't know the outgoing type we try to make it a |
| 1659 // number. | 1670 // number. |
| 1660 if (propagatedType.isUnknown() || propagatedType.isNumber()) { | 1671 if (propagatedType.isUnknown() || propagatedType.isNumber()) { |
| 1661 return HType.NUMBER; | 1672 return HType.NUMBER; |
| 1662 } | 1673 } |
| 1663 // Even if the desired outgoing type is not a number we still want the | 1674 // Even if the desired outgoing type is not a number we still want the |
| 1664 // second argument to be a number if the first one is a number. This will | 1675 // second argument to be a number if the first one is a number. This will |
| 1665 // not help for the outgoing type, but at least the binary arithmetic | 1676 // not help for the outgoing type, but at least the binary arithmetic |
| 1666 // operation will not have type problems. | 1677 // operation will not have type problems. |
| 1667 // TODO(floitsch): normally we shouldn't request a number, but simply | 1678 // TODO(floitsch): normally we shouldn't request a number, but simply |
| 1668 // throw an ArgumentError if it isn't. This would be similar | 1679 // throw an ArgumentError if it isn't. This would be similar |
| 1669 // to the array case. | 1680 // to the array case. |
| 1670 if (input == right && left.isNumber(types)) return HType.NUMBER; | 1681 if (input == right && left.isNumber(types)) return HType.NUMBER; |
| 1671 return HType.UNKNOWN; | 1682 return HType.UNKNOWN; |
| 1672 } | 1683 } |
| 1673 | 1684 |
| 1674 HType computeLikelyType(HTypeMap types) { | 1685 HType computeLikelyType(HTypeMap types, Compiler compiler) { |
| 1675 if (left.isTypeUnknown(types)) return HType.NUMBER; | 1686 if (left.isTypeUnknown(types)) return HType.NUMBER; |
| 1676 return HType.UNKNOWN; | 1687 return HType.UNKNOWN; |
| 1677 } | 1688 } |
| 1678 | 1689 |
| 1679 abstract BinaryOperation operation(ConstantSystem constantSystem); | 1690 abstract BinaryOperation operation(ConstantSystem constantSystem); |
| 1680 } | 1691 } |
| 1681 | 1692 |
| 1682 class HAdd extends HBinaryArithmetic { | 1693 class HAdd extends HBinaryArithmetic { |
| 1683 HAdd(HStatic target, HInstruction left, HInstruction right) | 1694 HAdd(HStatic target, HInstruction left, HInstruction right) |
| 1684 : super(target, left, right); | 1695 : super(target, left, right); |
| 1685 accept(HVisitor visitor) => visitor.visitAdd(this); | 1696 accept(HVisitor visitor) => visitor.visitAdd(this); |
| 1686 | 1697 |
| 1687 BinaryOperation operation(ConstantSystem constantSystem) | 1698 BinaryOperation operation(ConstantSystem constantSystem) |
| 1688 => constantSystem.add; | 1699 => constantSystem.add; |
| 1689 int typeCode() => HInstruction.ADD_TYPECODE; | 1700 int typeCode() => HInstruction.ADD_TYPECODE; |
| 1690 bool typeEquals(other) => other is HAdd; | 1701 bool typeEquals(other) => other is HAdd; |
| 1691 bool dataEquals(HInstruction other) => true; | 1702 bool dataEquals(HInstruction other) => true; |
| 1692 } | 1703 } |
| 1693 | 1704 |
| 1694 class HDivide extends HBinaryArithmetic { | 1705 class HDivide extends HBinaryArithmetic { |
| 1695 HDivide(HStatic target, HInstruction left, HInstruction right) | 1706 HDivide(HStatic target, HInstruction left, HInstruction right) |
| 1696 : super(target, left, right); | 1707 : super(target, left, right); |
| 1697 accept(HVisitor visitor) => visitor.visitDivide(this); | 1708 accept(HVisitor visitor) => visitor.visitDivide(this); |
| 1698 | 1709 |
| 1699 HType computeTypeFromInputTypes(HTypeMap types) { | 1710 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) { |
| 1700 if (left.isNumber(types)) return HType.DOUBLE; | 1711 if (left.isNumber(types)) return HType.DOUBLE; |
| 1701 return HType.UNKNOWN; | 1712 return HType.UNKNOWN; |
| 1702 } | 1713 } |
| 1703 | 1714 |
| 1704 HType computeDesiredTypeForNonTargetInput(HInstruction input, | 1715 HType computeDesiredTypeForNonTargetInput(HInstruction input, |
| 1705 HTypeMap types) { | 1716 HTypeMap types, |
| 1717 Compiler compiler) { |
| 1706 // A division can never return an integer. So don't ask for integer inputs. | 1718 // A division can never return an integer. So don't ask for integer inputs. |
| 1707 if (isInteger(types)) return HType.UNKNOWN; | 1719 if (isInteger(types)) return HType.UNKNOWN; |
| 1708 return super.computeDesiredTypeForNonTargetInput(input, types); | 1720 return super.computeDesiredTypeForNonTargetInput(input, types, compiler); |
| 1709 } | 1721 } |
| 1710 | 1722 |
| 1711 BinaryOperation operation(ConstantSystem constantSystem) | 1723 BinaryOperation operation(ConstantSystem constantSystem) |
| 1712 => constantSystem.divide; | 1724 => constantSystem.divide; |
| 1713 int typeCode() => HInstruction.DIVIDE_TYPECODE; | 1725 int typeCode() => HInstruction.DIVIDE_TYPECODE; |
| 1714 bool typeEquals(other) => other is HDivide; | 1726 bool typeEquals(other) => other is HDivide; |
| 1715 bool dataEquals(HInstruction other) => true; | 1727 bool dataEquals(HInstruction other) => true; |
| 1716 } | 1728 } |
| 1717 | 1729 |
| 1718 class HModulo extends HBinaryArithmetic { | 1730 class HModulo extends HBinaryArithmetic { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1786 bool dataEquals(HInstruction other) => true; | 1798 bool dataEquals(HInstruction other) => true; |
| 1787 } | 1799 } |
| 1788 | 1800 |
| 1789 | 1801 |
| 1790 // TODO(floitsch): Should HBinaryArithmetic really be the super class of | 1802 // TODO(floitsch): Should HBinaryArithmetic really be the super class of |
| 1791 // HBinaryBitOp? | 1803 // HBinaryBitOp? |
| 1792 abstract class HBinaryBitOp extends HBinaryArithmetic { | 1804 abstract class HBinaryBitOp extends HBinaryArithmetic { |
| 1793 HBinaryBitOp(HStatic target, HInstruction left, HInstruction right) | 1805 HBinaryBitOp(HStatic target, HInstruction left, HInstruction right) |
| 1794 : super(target, left, right); | 1806 : super(target, left, right); |
| 1795 | 1807 |
| 1796 HType computeTypeFromInputTypes(HTypeMap types) { | 1808 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) { |
| 1797 // All bitwise operations on primitive types either produce an | 1809 // All bitwise operations on primitive types either produce an |
| 1798 // integer or throw an error. | 1810 // integer or throw an error. |
| 1799 if (left.isPrimitive(types)) return HType.INTEGER; | 1811 if (left.isPrimitive(types)) return HType.INTEGER; |
| 1800 return HType.UNKNOWN; | 1812 return HType.UNKNOWN; |
| 1801 } | 1813 } |
| 1802 | 1814 |
| 1803 HType computeDesiredTypeForNonTargetInput(HInstruction input, | 1815 HType computeDesiredTypeForNonTargetInput(HInstruction input, |
| 1804 HTypeMap types) { | 1816 HTypeMap types, |
| 1817 Compiler compiler) { |
| 1805 HType propagatedType = types[this]; | 1818 HType propagatedType = types[this]; |
| 1806 // If the outgoing type should be a number we can get that only if both | 1819 // If the outgoing type should be a number we can get that only if both |
| 1807 // inputs are integers. If we don't know the outgoing type we try to make | 1820 // inputs are integers. If we don't know the outgoing type we try to make |
| 1808 // it an integer. | 1821 // it an integer. |
| 1809 if (propagatedType.isUnknown() || propagatedType.isNumber()) { | 1822 if (propagatedType.isUnknown() || propagatedType.isNumber()) { |
| 1810 return HType.INTEGER; | 1823 return HType.INTEGER; |
| 1811 } | 1824 } |
| 1812 return HType.UNKNOWN; | 1825 return HType.UNKNOWN; |
| 1813 } | 1826 } |
| 1814 | 1827 |
| 1815 HType computeLikelyType(HTypeMap types) { | 1828 HType computeLikelyType(HTypeMap types, Compiler compiler) { |
| 1816 if (left.isTypeUnknown(types)) return HType.INTEGER; | 1829 if (left.isTypeUnknown(types)) return HType.INTEGER; |
| 1817 return HType.UNKNOWN; | 1830 return HType.UNKNOWN; |
| 1818 } | 1831 } |
| 1819 | 1832 |
| 1820 // TODO(floitsch): make class abstract instead of adding an abstract method. | 1833 // TODO(floitsch): make class abstract instead of adding an abstract method. |
| 1821 abstract accept(HVisitor visitor); | 1834 abstract accept(HVisitor visitor); |
| 1822 } | 1835 } |
| 1823 | 1836 |
| 1824 class HShiftLeft extends HBinaryBitOp { | 1837 class HShiftLeft extends HBinaryBitOp { |
| 1825 HShiftLeft(HStatic target, HInstruction left, HInstruction right) | 1838 HShiftLeft(HStatic target, HInstruction left, HInstruction right) |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1907 // number. | 1920 // number. |
| 1908 if (isBuiltin(types)) { | 1921 if (isBuiltin(types)) { |
| 1909 setUseGvn(); | 1922 setUseGvn(); |
| 1910 } else { | 1923 } else { |
| 1911 setAllSideEffects(); | 1924 setAllSideEffects(); |
| 1912 } | 1925 } |
| 1913 } | 1926 } |
| 1914 | 1927 |
| 1915 bool isBuiltin(HTypeMap types) => operand.isNumber(types); | 1928 bool isBuiltin(HTypeMap types) => operand.isNumber(types); |
| 1916 | 1929 |
| 1917 HType computeTypeFromInputTypes(HTypeMap types) { | 1930 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) { |
| 1918 HType operandType = types[operand]; | 1931 HType operandType = types[operand]; |
| 1919 if (operandType.isNumber()) return operandType; | 1932 if (operandType.isNumber()) return operandType; |
| 1920 return HType.UNKNOWN; | 1933 return HType.UNKNOWN; |
| 1921 } | 1934 } |
| 1922 | 1935 |
| 1923 HType computeDesiredTypeForNonTargetInput(HInstruction input, | 1936 HType computeDesiredTypeForNonTargetInput(HInstruction input, |
| 1924 HTypeMap types) { | 1937 HTypeMap types, |
| 1938 Compiler compiler) { |
| 1925 HType propagatedType = types[this]; | 1939 HType propagatedType = types[this]; |
| 1926 // If the outgoing type should be a number (integer, double or both) we | 1940 // If the outgoing type should be a number (integer, double or both) we |
| 1927 // want the outgoing type to be the input too. | 1941 // want the outgoing type to be the input too. |
| 1928 // If we don't know the outgoing type we try to make it a number. | 1942 // If we don't know the outgoing type we try to make it a number. |
| 1929 if (propagatedType.isNumber()) return propagatedType; | 1943 if (propagatedType.isNumber()) return propagatedType; |
| 1930 if (propagatedType.isUnknown()) return HType.NUMBER; | 1944 if (propagatedType.isUnknown()) return HType.NUMBER; |
| 1931 return HType.UNKNOWN; | 1945 return HType.UNKNOWN; |
| 1932 } | 1946 } |
| 1933 | 1947 |
| 1934 HType computeLikelyType(HTypeMap types) => HType.NUMBER; | 1948 HType computeLikelyType(HTypeMap types, Compiler compiler) => HType.NUMBER; |
| 1935 | 1949 |
| 1936 abstract UnaryOperation operation(ConstantSystem constantSystem); | 1950 abstract UnaryOperation operation(ConstantSystem constantSystem); |
| 1937 } | 1951 } |
| 1938 | 1952 |
| 1939 class HNegate extends HInvokeUnary { | 1953 class HNegate extends HInvokeUnary { |
| 1940 HNegate(HStatic target, HInstruction input) : super(target, input); | 1954 HNegate(HStatic target, HInstruction input) : super(target, input); |
| 1941 accept(HVisitor visitor) => visitor.visitNegate(this); | 1955 accept(HVisitor visitor) => visitor.visitNegate(this); |
| 1942 | 1956 |
| 1943 UnaryOperation operation(ConstantSystem constantSystem) | 1957 UnaryOperation operation(ConstantSystem constantSystem) |
| 1944 => constantSystem.negate; | 1958 => constantSystem.negate; |
| 1945 int typeCode() => HInstruction.NEGATE_TYPECODE; | 1959 int typeCode() => HInstruction.NEGATE_TYPECODE; |
| 1946 bool typeEquals(other) => other is HNegate; | 1960 bool typeEquals(other) => other is HNegate; |
| 1947 bool dataEquals(HInstruction other) => true; | 1961 bool dataEquals(HInstruction other) => true; |
| 1948 } | 1962 } |
| 1949 | 1963 |
| 1950 class HBitNot extends HInvokeUnary { | 1964 class HBitNot extends HInvokeUnary { |
| 1951 HBitNot(HStatic target, HInstruction input) : super(target, input); | 1965 HBitNot(HStatic target, HInstruction input) : super(target, input); |
| 1952 accept(HVisitor visitor) => visitor.visitBitNot(this); | 1966 accept(HVisitor visitor) => visitor.visitBitNot(this); |
| 1953 | 1967 |
| 1954 HType computeTypeFromInputTypes(HTypeMap types) { | 1968 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) { |
| 1955 // All bitwise operations on primitive types either produce an | 1969 // All bitwise operations on primitive types either produce an |
| 1956 // integer or throw an error. | 1970 // integer or throw an error. |
| 1957 if (operand.isPrimitive(types)) return HType.INTEGER; | 1971 if (operand.isPrimitive(types)) return HType.INTEGER; |
| 1958 return HType.UNKNOWN; | 1972 return HType.UNKNOWN; |
| 1959 } | 1973 } |
| 1960 | 1974 |
| 1961 HType computeDesiredTypeForNonTargetInput(HInstruction input, | 1975 HType computeDesiredTypeForNonTargetInput(HInstruction input, |
| 1962 HTypeMap types) { | 1976 HTypeMap types, |
| 1977 Compiler compiler) { |
| 1963 HType propagatedType = types[this]; | 1978 HType propagatedType = types[this]; |
| 1964 // Bit operations only work on integers. If there is no desired output | 1979 // Bit operations only work on integers. If there is no desired output |
| 1965 // type or if it as a number we want to get an integer as input. | 1980 // type or if it as a number we want to get an integer as input. |
| 1966 if (propagatedType.isUnknown() || propagatedType.isNumber()) { | 1981 if (propagatedType.isUnknown() || propagatedType.isNumber()) { |
| 1967 return HType.INTEGER; | 1982 return HType.INTEGER; |
| 1968 } | 1983 } |
| 1969 return HType.UNKNOWN; | 1984 return HType.UNKNOWN; |
| 1970 } | 1985 } |
| 1971 | 1986 |
| 1972 UnaryOperation operation(ConstantSystem constantSystem) | 1987 UnaryOperation operation(ConstantSystem constantSystem) |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2088 class HNot extends HInstruction { | 2103 class HNot extends HInstruction { |
| 2089 HNot(HInstruction value) : super(<HInstruction>[value]); | 2104 HNot(HInstruction value) : super(<HInstruction>[value]); |
| 2090 void prepareGvn(HTypeMap types) { | 2105 void prepareGvn(HTypeMap types) { |
| 2091 assert(!hasSideEffects(types)); | 2106 assert(!hasSideEffects(types)); |
| 2092 setUseGvn(); | 2107 setUseGvn(); |
| 2093 } | 2108 } |
| 2094 | 2109 |
| 2095 HType get guaranteedType => HType.BOOLEAN; | 2110 HType get guaranteedType => HType.BOOLEAN; |
| 2096 | 2111 |
| 2097 // 'Not' only works on booleans. That's what we want as input. | 2112 // 'Not' only works on booleans. That's what we want as input. |
| 2098 HType computeDesiredTypeForInput(HInstruction input, HTypeMap types) { | 2113 HType computeDesiredTypeForInput(HInstruction input, |
| 2114 HTypeMap types, |
| 2115 Compiler compiler) { |
| 2099 return HType.BOOLEAN; | 2116 return HType.BOOLEAN; |
| 2100 } | 2117 } |
| 2101 | 2118 |
| 2102 accept(HVisitor visitor) => visitor.visitNot(this); | 2119 accept(HVisitor visitor) => visitor.visitNot(this); |
| 2103 int typeCode() => HInstruction.NOT_TYPECODE; | 2120 int typeCode() => HInstruction.NOT_TYPECODE; |
| 2104 bool typeEquals(other) => other is HNot; | 2121 bool typeEquals(other) => other is HNot; |
| 2105 bool dataEquals(HInstruction other) => true; | 2122 bool dataEquals(HInstruction other) => true; |
| 2106 } | 2123 } |
| 2107 | 2124 |
| 2108 /** | 2125 /** |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2160 void addInput(HInstruction input) { | 2177 void addInput(HInstruction input) { |
| 2161 assert(isInBasicBlock()); | 2178 assert(isInBasicBlock()); |
| 2162 inputs.add(input); | 2179 inputs.add(input); |
| 2163 input.usedBy.add(this); | 2180 input.usedBy.add(this); |
| 2164 } | 2181 } |
| 2165 | 2182 |
| 2166 // Compute the (shared) type of the inputs if any. If all inputs | 2183 // Compute the (shared) type of the inputs if any. If all inputs |
| 2167 // have the same known type return it. If any two inputs have | 2184 // have the same known type return it. If any two inputs have |
| 2168 // different known types, we'll return a conflict -- otherwise we'll | 2185 // different known types, we'll return a conflict -- otherwise we'll |
| 2169 // simply return an unknown type. | 2186 // simply return an unknown type. |
| 2170 HType computeInputsType(bool ignoreUnknowns, HTypeMap types) { | 2187 HType computeInputsType(bool ignoreUnknowns, |
| 2188 HTypeMap types, |
| 2189 Compiler compiler) { |
| 2171 HType candidateType = HType.CONFLICTING; | 2190 HType candidateType = HType.CONFLICTING; |
| 2172 for (int i = 0, length = inputs.length; i < length; i++) { | 2191 for (int i = 0, length = inputs.length; i < length; i++) { |
| 2173 HType inputType = types[inputs[i]]; | 2192 HType inputType = types[inputs[i]]; |
| 2174 if (ignoreUnknowns && inputType.isUnknown()) continue; | 2193 if (ignoreUnknowns && inputType.isUnknown()) continue; |
| 2175 // Phis need to combine the incoming types using the union operation. | 2194 // Phis need to combine the incoming types using the union operation. |
| 2176 // For example, if one incoming edge has type integer and the other has | 2195 // For example, if one incoming edge has type integer and the other has |
| 2177 // type double, then the phi is either an integer or double and thus has | 2196 // type double, then the phi is either an integer or double and thus has |
| 2178 // type number. | 2197 // type number. |
| 2179 candidateType = candidateType.union(inputType); | 2198 candidateType = candidateType.union(inputType, compiler); |
| 2180 if (candidateType.isUnknown()) return HType.UNKNOWN; | 2199 if (candidateType.isUnknown()) return HType.UNKNOWN; |
| 2181 } | 2200 } |
| 2182 return candidateType; | 2201 return candidateType; |
| 2183 } | 2202 } |
| 2184 | 2203 |
| 2185 HType computeTypeFromInputTypes(HTypeMap types) { | 2204 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) { |
| 2186 HType inputsType = computeInputsType(false, types); | 2205 HType inputsType = computeInputsType(false, types, compiler); |
| 2187 if (inputsType.isConflicting()) return HType.UNKNOWN; | 2206 if (inputsType.isConflicting()) return HType.UNKNOWN; |
| 2188 return inputsType; | 2207 return inputsType; |
| 2189 } | 2208 } |
| 2190 | 2209 |
| 2191 HType computeDesiredTypeForInput(HInstruction input, HTypeMap types) { | 2210 HType computeDesiredTypeForInput(HInstruction input, |
| 2211 HTypeMap types, |
| 2212 Compiler compiler) { |
| 2192 HType propagatedType = types[this]; | 2213 HType propagatedType = types[this]; |
| 2193 // Best case scenario for a phi is, when all inputs have the same type. If | 2214 // Best case scenario for a phi is, when all inputs have the same type. If |
| 2194 // there is no desired outgoing type we therefore try to unify the input | 2215 // there is no desired outgoing type we therefore try to unify the input |
| 2195 // types (which is basically the [likelyType]). | 2216 // types (which is basically the [likelyType]). |
| 2196 if (propagatedType.isUnknown()) return computeLikelyType(types); | 2217 if (propagatedType.isUnknown()) return computeLikelyType(types, compiler); |
| 2197 // When the desired outgoing type is conflicting we don't need to give any | 2218 // When the desired outgoing type is conflicting we don't need to give any |
| 2198 // requirements on the inputs. | 2219 // requirements on the inputs. |
| 2199 if (propagatedType.isConflicting()) return HType.UNKNOWN; | 2220 if (propagatedType.isConflicting()) return HType.UNKNOWN; |
| 2200 // Otherwise the input type must match the desired outgoing type. | 2221 // Otherwise the input type must match the desired outgoing type. |
| 2201 return propagatedType; | 2222 return propagatedType; |
| 2202 } | 2223 } |
| 2203 | 2224 |
| 2204 HType computeLikelyType(HTypeMap types) { | 2225 HType computeLikelyType(HTypeMap types, Compiler compiler) { |
| 2205 HType agreedType = computeInputsType(true, types); | 2226 HType agreedType = computeInputsType(true, types, compiler); |
| 2206 if (agreedType.isConflicting()) return HType.UNKNOWN; | 2227 if (agreedType.isConflicting()) return HType.UNKNOWN; |
| 2207 // Don't be too restrictive. If the agreed type is integer or double just | 2228 // Don't be too restrictive. If the agreed type is integer or double just |
| 2208 // say that the likely type is number. If more is expected the type will be | 2229 // say that the likely type is number. If more is expected the type will be |
| 2209 // propagated back. | 2230 // propagated back. |
| 2210 if (agreedType.isNumber()) return HType.NUMBER; | 2231 if (agreedType.isNumber()) return HType.NUMBER; |
| 2211 return agreedType; | 2232 return agreedType; |
| 2212 } | 2233 } |
| 2213 | 2234 |
| 2214 bool isLogicalOperator() => logicalOperatorType != IS_NOT_LOGICAL_OPERATOR; | 2235 bool isLogicalOperator() => logicalOperatorType != IS_NOT_LOGICAL_OPERATOR; |
| 2215 | 2236 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2234 // Relational expressions can take part in global value numbering | 2255 // Relational expressions can take part in global value numbering |
| 2235 // and do not have any side-effects if we know all the inputs are | 2256 // and do not have any side-effects if we know all the inputs are |
| 2236 // numbers. This can be improved for at least equality. | 2257 // numbers. This can be improved for at least equality. |
| 2237 if (isBuiltin(types)) { | 2258 if (isBuiltin(types)) { |
| 2238 setUseGvn(); | 2259 setUseGvn(); |
| 2239 } else { | 2260 } else { |
| 2240 setAllSideEffects(); | 2261 setAllSideEffects(); |
| 2241 } | 2262 } |
| 2242 } | 2263 } |
| 2243 | 2264 |
| 2244 HType computeTypeFromInputTypes(HTypeMap types) { | 2265 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) { |
| 2245 if (left.isNumber(types) || usesBoolifiedInterceptor) return HType.BOOLEAN; | 2266 if (left.isNumber(types) || usesBoolifiedInterceptor) return HType.BOOLEAN; |
| 2246 return HType.UNKNOWN; | 2267 return HType.UNKNOWN; |
| 2247 } | 2268 } |
| 2248 | 2269 |
| 2249 HType get guaranteedType { | 2270 HType get guaranteedType { |
| 2250 if (usesBoolifiedInterceptor) return HType.BOOLEAN; | 2271 if (usesBoolifiedInterceptor) return HType.BOOLEAN; |
| 2251 return HType.UNKNOWN; | 2272 return HType.UNKNOWN; |
| 2252 } | 2273 } |
| 2253 | 2274 |
| 2254 HType computeDesiredTypeForNonTargetInput(HInstruction input, | 2275 HType computeDesiredTypeForNonTargetInput(HInstruction input, |
| 2255 HTypeMap types) { | 2276 HTypeMap types, |
| 2277 Compiler compiler) { |
| 2256 HType propagatedType = types[this]; | 2278 HType propagatedType = types[this]; |
| 2257 // For all relational operations exept HEquals, we expect to get numbers | 2279 // For all relational operations exept HEquals, we expect to get numbers |
| 2258 // only. With numbers the outgoing type is a boolean. If something else | 2280 // only. With numbers the outgoing type is a boolean. If something else |
| 2259 // is desired, then numbers are incorrect, though. | 2281 // is desired, then numbers are incorrect, though. |
| 2260 if (propagatedType.isUnknown() || propagatedType.isBoolean()) { | 2282 if (propagatedType.isUnknown() || propagatedType.isBoolean()) { |
| 2261 if (left.isTypeUnknown(types) || left.isNumber(types)) { | 2283 if (left.isTypeUnknown(types) || left.isNumber(types)) { |
| 2262 return HType.NUMBER; | 2284 return HType.NUMBER; |
| 2263 } | 2285 } |
| 2264 } | 2286 } |
| 2265 return HType.UNKNOWN; | 2287 return HType.UNKNOWN; |
| 2266 } | 2288 } |
| 2267 | 2289 |
| 2268 HType computeLikelyType(HTypeMap types) => HType.BOOLEAN; | 2290 HType computeLikelyType(HTypeMap types, Compiler compiler) => HType.BOOLEAN; |
| 2269 | 2291 |
| 2270 bool isBuiltin(HTypeMap types) | 2292 bool isBuiltin(HTypeMap types) |
| 2271 => left.isNumber(types) && right.isNumber(types); | 2293 => left.isNumber(types) && right.isNumber(types); |
| 2272 // TODO(1603): the class should be marked as abstract. | 2294 // TODO(1603): the class should be marked as abstract. |
| 2273 abstract BinaryOperation operation(ConstantSystem constantSystem); | 2295 abstract BinaryOperation operation(ConstantSystem constantSystem); |
| 2274 } | 2296 } |
| 2275 | 2297 |
| 2276 class HEquals extends HRelational { | 2298 class HEquals extends HRelational { |
| 2277 HEquals(HStatic target, HInstruction left, HInstruction right) | 2299 HEquals(HStatic target, HInstruction left, HInstruction right) |
| 2278 : super(target, left, right); | 2300 : super(target, left, right); |
| 2279 accept(HVisitor visitor) => visitor.visitEquals(this); | 2301 accept(HVisitor visitor) => visitor.visitEquals(this); |
| 2280 | 2302 |
| 2281 bool isBuiltin(HTypeMap types) { | 2303 bool isBuiltin(HTypeMap types) { |
| 2282 // All primitive types have === semantics. | 2304 // All primitive types have === semantics. |
| 2283 // Note that this includes all constants except the user-constructed | 2305 // Note that this includes all constants except the user-constructed |
| 2284 // objects. | 2306 // objects. |
| 2285 return types[left].isPrimitiveOrNull() || right.isConstantNull(); | 2307 return types[left].isPrimitiveOrNull() || right.isConstantNull(); |
| 2286 } | 2308 } |
| 2287 | 2309 |
| 2288 HType computeTypeFromInputTypes(HTypeMap types) { | 2310 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) { |
| 2289 if (isBuiltin(types) || usesBoolifiedInterceptor) return HType.BOOLEAN; | 2311 if (isBuiltin(types) || usesBoolifiedInterceptor) return HType.BOOLEAN; |
| 2290 return HType.UNKNOWN; | 2312 return HType.UNKNOWN; |
| 2291 } | 2313 } |
| 2292 | 2314 |
| 2293 HType computeDesiredTypeForNonTargetInput(HInstruction input, | 2315 HType computeDesiredTypeForNonTargetInput(HInstruction input, |
| 2294 HTypeMap types) { | 2316 HTypeMap types, |
| 2317 Compiler compiler) { |
| 2295 HType propagatedType = types[this]; | 2318 HType propagatedType = types[this]; |
| 2296 if (input == left && types[right].isUseful()) { | 2319 if (input == left && types[right].isUseful()) { |
| 2297 // All our useful types have === semantics. But we don't want to | 2320 // All our useful types have === semantics. But we don't want to |
| 2298 // speculatively test for all possible types. Therefore we try to match | 2321 // speculatively test for all possible types. Therefore we try to match |
| 2299 // the two types. That is, if we see x == 3, then we speculatively test | 2322 // the two types. That is, if we see x == 3, then we speculatively test |
| 2300 // if x is a number and bailout if it isn't. | 2323 // if x is a number and bailout if it isn't. |
| 2301 // If right is a number we don't need more than a number (no need to match | 2324 // If right is a number we don't need more than a number (no need to match |
| 2302 // the exact type of right). | 2325 // the exact type of right). |
| 2303 if (right.isNumber(types)) return HType.NUMBER; | 2326 if (right.isNumber(types)) return HType.NUMBER; |
| 2304 // String equality testing is much more common than array equality | 2327 // String equality testing is much more common than array equality |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2325 } | 2348 } |
| 2326 | 2349 |
| 2327 class HIdentity extends HRelational { | 2350 class HIdentity extends HRelational { |
| 2328 HIdentity(HStatic target, HInstruction left, HInstruction right) | 2351 HIdentity(HStatic target, HInstruction left, HInstruction right) |
| 2329 : super(target, left, right); | 2352 : super(target, left, right); |
| 2330 accept(HVisitor visitor) => visitor.visitIdentity(this); | 2353 accept(HVisitor visitor) => visitor.visitIdentity(this); |
| 2331 | 2354 |
| 2332 bool isBuiltin(HTypeMap types) => true; | 2355 bool isBuiltin(HTypeMap types) => true; |
| 2333 | 2356 |
| 2334 HType get guaranteedType => HType.BOOLEAN; | 2357 HType get guaranteedType => HType.BOOLEAN; |
| 2335 HType computeTypeFromInputTypes(HTypeMap types) | 2358 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) |
| 2336 => HType.BOOLEAN; | 2359 => HType.BOOLEAN; |
| 2337 // Note that the identity operator really does not care for its input types. | 2360 // Note that the identity operator really does not care for its input types. |
| 2338 HType computeDesiredTypeForInput(HInstruction input, HTypeMap types) | 2361 HType computeDesiredTypeForInput(HInstruction input, |
| 2339 => HType.UNKNOWN; | 2362 HTypeMap types, |
| 2363 Compiler compiler) { |
| 2364 return HType.UNKNOWN; |
| 2365 } |
| 2340 | 2366 |
| 2341 BinaryOperation operation(ConstantSystem constantSystem) | 2367 BinaryOperation operation(ConstantSystem constantSystem) |
| 2342 => constantSystem.identity; | 2368 => constantSystem.identity; |
| 2343 int typeCode() => HInstruction.IDENTITY_TYPECODE; | 2369 int typeCode() => HInstruction.IDENTITY_TYPECODE; |
| 2344 bool typeEquals(other) => other is HIdentity; | 2370 bool typeEquals(other) => other is HIdentity; |
| 2345 bool dataEquals(HInstruction other) => true; | 2371 bool dataEquals(HInstruction other) => true; |
| 2346 } | 2372 } |
| 2347 | 2373 |
| 2348 class HGreater extends HRelational { | 2374 class HGreater extends HRelational { |
| 2349 HGreater(HStatic target, HInstruction left, HInstruction right) | 2375 HGreater(HStatic target, HInstruction left, HInstruction right) |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2490 setUseGvn(); | 2516 setUseGvn(); |
| 2491 } else { | 2517 } else { |
| 2492 setAllSideEffects(); | 2518 setAllSideEffects(); |
| 2493 } | 2519 } |
| 2494 } | 2520 } |
| 2495 | 2521 |
| 2496 HInstruction get receiver => inputs[1]; | 2522 HInstruction get receiver => inputs[1]; |
| 2497 HInstruction get index => inputs[2]; | 2523 HInstruction get index => inputs[2]; |
| 2498 | 2524 |
| 2499 HType computeDesiredTypeForNonTargetInput(HInstruction input, | 2525 HType computeDesiredTypeForNonTargetInput(HInstruction input, |
| 2500 HTypeMap types) { | 2526 HTypeMap types, |
| 2527 Compiler compiler) { |
| 2501 if (input == receiver && | 2528 if (input == receiver && |
| 2502 (index.isTypeUnknown(types) || index.isNumber(types))) { | 2529 (index.isTypeUnknown(types) || index.isNumber(types))) { |
| 2503 return HType.INDEXABLE_PRIMITIVE; | 2530 return HType.INDEXABLE_PRIMITIVE; |
| 2504 } | 2531 } |
| 2505 // The index should be an int when the receiver is a string or array. | 2532 // The index should be an int when the receiver is a string or array. |
| 2506 // However it turns out that inserting an integer check in the optimized | 2533 // However it turns out that inserting an integer check in the optimized |
| 2507 // version is cheaper than having another bailout case. This is true, | 2534 // version is cheaper than having another bailout case. This is true, |
| 2508 // because the integer check will simply throw if it fails. | 2535 // because the integer check will simply throw if it fails. |
| 2509 return HType.UNKNOWN; | 2536 return HType.UNKNOWN; |
| 2510 } | 2537 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2536 setChangesIndex(); | 2563 setChangesIndex(); |
| 2537 } else { | 2564 } else { |
| 2538 setAllSideEffects(); | 2565 setAllSideEffects(); |
| 2539 } | 2566 } |
| 2540 } | 2567 } |
| 2541 | 2568 |
| 2542 // Note, that we don't have a computeTypeFromInputTypes, since [HIndexAssign] | 2569 // Note, that we don't have a computeTypeFromInputTypes, since [HIndexAssign] |
| 2543 // is never used as input. | 2570 // is never used as input. |
| 2544 | 2571 |
| 2545 HType computeDesiredTypeForNonTargetInput(HInstruction input, | 2572 HType computeDesiredTypeForNonTargetInput(HInstruction input, |
| 2546 HTypeMap types) { | 2573 HTypeMap types, |
| 2574 Compiler compiler) { |
| 2547 if (input == receiver && | 2575 if (input == receiver && |
| 2548 (index.isTypeUnknown(types) || index.isNumber(types))) { | 2576 (index.isTypeUnknown(types) || index.isNumber(types))) { |
| 2549 return HType.MUTABLE_ARRAY; | 2577 return HType.MUTABLE_ARRAY; |
| 2550 } | 2578 } |
| 2551 // The index should be an int when the receiver is a string or array. | 2579 // The index should be an int when the receiver is a string or array. |
| 2552 // However it turns out that inserting an integer check in the optimized | 2580 // However it turns out that inserting an integer check in the optimized |
| 2553 // version is cheaper than having another bailout case. This is true, | 2581 // version is cheaper than having another bailout case. This is true, |
| 2554 // because the integer check will simply throw if it fails. | 2582 // because the integer check will simply throw if it fails. |
| 2555 return HType.UNKNOWN; | 2583 return HType.UNKNOWN; |
| 2556 } | 2584 } |
| (...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2976 HBasicBlock get start => expression.start; | 3004 HBasicBlock get start => expression.start; |
| 2977 HBasicBlock get end { | 3005 HBasicBlock get end { |
| 2978 // We don't create a switch block if there are no cases. | 3006 // We don't create a switch block if there are no cases. |
| 2979 assert(!statements.isEmpty); | 3007 assert(!statements.isEmpty); |
| 2980 return statements.last.end; | 3008 return statements.last.end; |
| 2981 } | 3009 } |
| 2982 | 3010 |
| 2983 bool accept(HStatementInformationVisitor visitor) => | 3011 bool accept(HStatementInformationVisitor visitor) => |
| 2984 visitor.visitSwitchInfo(this); | 3012 visitor.visitSwitchInfo(this); |
| 2985 } | 3013 } |
| OLD | NEW |