Chromium Code Reviews| Index: pkg/compiler/lib/src/cps_ir/type_propagation.dart |
| diff --git a/pkg/compiler/lib/src/cps_ir/type_propagation.dart b/pkg/compiler/lib/src/cps_ir/type_propagation.dart |
| index 615b4c44f0d1e369ca9844b8650da20fe6b9debc..798f2fc981d5a82c5daab8e81ffa80a8eff28823 100644 |
| --- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart |
| +++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart |
| @@ -32,6 +32,7 @@ class TypeMaskSystem { |
| TypeMask get functionType => inferrer.functionType; |
| TypeMask get boolType => inferrer.boolType; |
| TypeMask get intType => inferrer.intType; |
| + TypeMask get doubleType => inferrer.doubleType; |
| TypeMask get numType => inferrer.numType; |
| TypeMask get stringType => inferrer.stringType; |
| TypeMask get listType => inferrer.listType; |
| @@ -105,6 +106,20 @@ class TypeMaskSystem { |
| return areDisjoint(t, numStringBoolType); |
| } |
| + /// True if all values of [t] are either integers or not numbers at all. |
| + /// |
| + /// This does not imply that the value is an integer, since most other values |
| + /// such as null are also not a non-integer double. |
| + bool isDefinitelyNotNonIntegerDouble(TypeMask t) { |
| + // Even though int is a subclass of double in the JS type system, we can |
| + // still check this with disjointness, because [doubleType] is the *exact* |
| + // double class, so this excludes things that are known to be instances of a |
| + // more specific class. |
| + // We currently exploit that there are no subclasses of double that are |
| + // not integers (e.g. there is no UnsignedDouble class or whatever). |
| + return areDisjoint(t, doubleType); |
| + } |
| + |
| bool areDisjoint(TypeMask leftType, TypeMask rightType) { |
| TypeMask intersection = leftType.intersection(rightType, classWorld); |
| return intersection.isEmpty && !intersection.isNullable; |
| @@ -214,6 +229,16 @@ class ConstantPropagationLattice { |
| typeSystem.isDefinitelyNotNumStringBool(value.type); |
| } |
| + /// True if this value cannot be a non-integer double. |
| + /// |
| + /// In other words, if true is returned, and IF the value is a number, then |
|
karlklose
2015/06/18 07:36:56
Remove 'IF'.
asgerf
2015/06/18 09:08:49
Done.
|
| + /// it is a whole number and is not NaN, Infinity, or minus Infinity. |
| + bool isDefinitelyNotNonIntegerDouble(AbstractValue value) { |
| + return value.isNothing || |
| + value.isConstant && !value.constant.isDouble || |
| + typeSystem.isDefinitelyNotNonIntegerDouble(value.type); |
| + } |
| + |
| /// Returns whether the given [value] is an instance of [type]. |
| /// |
| /// Since [value] and [type] are not always known, [AbstractBool.Maybe] is |
| @@ -400,6 +425,7 @@ class TransformingVisitor extends RecursiveVisitor { |
| final ConstantPropagationLattice lattice; |
| TypeMaskSystem get typeSystem => lattice.typeSystem; |
| + types.DartTypes get dartTypes => lattice.dartTypes; |
| final dart2js.InternalErrorFunction internalError; |
| @@ -670,6 +696,31 @@ class TransformingVisitor extends RecursiveVisitor { |
| } |
| } |
| + Primitive visitTypeTest(TypeTest node) { |
| + Primitive prim = node.value.definition; |
| + AbstractValue value = getValue(prim); |
| + if (node.type == dartTypes.coreTypes.intType) { |
| + // Compile as typeof x === 'number' && Math.floor(x) === x |
| + if (lattice.isDefinitelyNum(value, allowNull: true)) { |
| + // If value is null or a number, we can skip the typeof test. |
| + return new ApplyBuiltinOperator( |
| + BuiltinOperator.IsFloor, |
| + <Primitive>[prim, prim]); |
| + } |
| + if (lattice.isDefinitelyNotNonIntegerDouble(value)) { |
| + // If the value cannot be a non-integer double, but might not be a |
| + // number at all, we can skip the Math.floor test. |
| + return new ApplyBuiltinOperator( |
| + BuiltinOperator.IsNumber, |
| + <Primitive>[prim]); |
| + } |
| + return new ApplyBuiltinOperator( |
| + BuiltinOperator.IsNumberAndFloor, |
| + <Primitive>[prim, prim, prim]); |
| + } |
| + return null; |
| + } |
| + |
| void visitLetPrim(LetPrim node) { |
| AbstractValue value = getValue(node.primitive); |
| if (node.primitive is! Constant && value.isConstant) { |
| @@ -678,8 +729,15 @@ class TransformingVisitor extends RecursiveVisitor { |
| newPrim.substituteFor(node.primitive); |
| RemovalVisitor.remove(node.primitive); |
| node.primitive = newPrim; |
| + } else { |
| + Primitive newPrim = visit(node.primitive); |
| + if (newPrim != null) { |
| + newPrim.substituteFor(node.primitive); |
| + RemovalVisitor.remove(node.primitive); |
| + node.primitive = newPrim; |
| + } |
| } |
| - super.visitLetPrim(node); |
| + visit(node.body); |
| } |
| } |