| Index: lib/compiler/implementation/ssa/nodes.dart
|
| diff --git a/lib/compiler/implementation/ssa/nodes.dart b/lib/compiler/implementation/ssa/nodes.dart
|
| index 52fc8ea178e86e06452d53d907fd6402e1670f89..6a8143291acbb73ab906a513a8d7d35f288f650f 100644
|
| --- a/lib/compiler/implementation/ssa/nodes.dart
|
| +++ b/lib/compiler/implementation/ssa/nodes.dart
|
| @@ -909,7 +909,7 @@ class HInstruction implements Hashable {
|
| /**
|
| * Some instructions have a good idea of their return type, but cannot
|
| * guarantee the type. The [likelyType] does not need to be more specialized
|
| - * than the [propagatedType].
|
| + * than the [propagatedType].
|
| *
|
| * Examples: the [likelyType] of [:x == y:] is a boolean. In most cases this
|
| * cannot be guaranteed, but when merging types we still want to use this
|
| @@ -917,8 +917,8 @@ class HInstruction implements Hashable {
|
| *
|
| * Similarily the [HAdd] instruction is likely a number. Note that, even if
|
| * the [propagatedType] is already set to integer, the [likelyType] still
|
| - * might just return the number type.
|
| - */
|
| + * might just return the number type.
|
| + */
|
| HType get likelyType() => propagatedType;
|
|
|
| /**
|
| @@ -1067,8 +1067,10 @@ class HCheck extends HInstruction {
|
| }
|
|
|
| class HTypeGuard extends HInstruction {
|
| - int state;
|
| - HTypeGuard(int this.state, List<HInstruction> env) : super(env);
|
| + final int state;
|
| + final HType guardedType;
|
| + bool isOn = false;
|
| + HTypeGuard(this.guardedType, this.state, List<HInstruction> env) : super(env);
|
|
|
| void prepareGvn() {
|
| assert(!hasSideEffects());
|
| @@ -1077,12 +1079,18 @@ class HTypeGuard extends HInstruction {
|
|
|
| HInstruction get guarded() => inputs.last();
|
|
|
| + HType computeTypeFromInputTypes() {
|
| + return isOn ? guardedType : guarded.propagatedType;
|
| + }
|
| +
|
| + HType get guaranteedType() => isOn ? guardedType : HType.UNKNOWN;
|
| +
|
| bool isControlFlow() => true;
|
|
|
| accept(HVisitor visitor) => visitor.visitTypeGuard(this);
|
| int typeCode() => 1;
|
| bool typeEquals(other) => other is HTypeGuard;
|
| - bool dataEquals(HTypeGuard other) => propagatedType == other.propagatedType;
|
| + bool dataEquals(HTypeGuard other) => guardedType == other.guardedType;
|
| }
|
|
|
| class HBoundsCheck extends HCheck {
|
| @@ -1418,6 +1426,14 @@ class HBinaryArithmetic extends HInvokeBinary {
|
| if (propagatedType.isUnknown() || propagatedType.isNumber()) {
|
| return HType.NUMBER;
|
| }
|
| + // Even if the desired outgoing type is not a number we still want the
|
| + // second argument to be a number if the first one is a number. This will
|
| + // not help for the outgoing type, but at least the binary arithmetic
|
| + // operation will not have type problems.
|
| + // TODO(floitsch): normally we shouldn't request a number, but simply
|
| + // throw an IllegalArgumentException if it isn't. This would be similar
|
| + // to the array case.
|
| + if (input == right && left.isNumber()) return HType.NUMBER;
|
| return HType.UNKNOWN;
|
| }
|
|
|
| @@ -2007,7 +2023,7 @@ class HEquals extends HRelational {
|
| if (right.isNumber()) return HType.NUMBER; // No need to be more precise.
|
| // String equality testing is much more common than array equality
|
| // testing.
|
| - if (right.isStringOrArray()) return HType.STRING;
|
| + if (right.isStringOrArray()) return HType.STRING;
|
| return right.propagatedType;
|
| }
|
| // String equality testing is much more common than array equality testing.
|
|
|