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 ecf555d8352063689c44345637fc81cb1c18edd7..7cc944c6dd049fe22fb99df111591762d73d0a31 100644 |
--- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart |
+++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart |
@@ -1806,8 +1806,29 @@ class TransformingVisitor extends LeafVisitor { |
Primitive visitTypeTest(TypeTest node) { |
Primitive prim = node.value.definition; |
+ |
+ Primitive unaryBuiltinOperator(BuiltinOperator operator) => |
+ new ApplyBuiltinOperator( |
+ operator, <Primitive>[prim], node.sourceInformation); |
+ |
+ void unlinkInterceptor() { |
+ if (node.interceptor != null) { |
+ node.interceptor.unlink(); |
+ node.interceptor = null; |
+ } |
+ } |
+ |
AbstractValue value = getValue(prim); |
- if (node.dartType == dartTypes.coreTypes.intType) { |
+ types.DartType dartType = node.dartType; |
+ |
+ if (!(dartType.isInterfaceType && dartType.isRaw)) { |
+ // TODO(23685): Efficient function arity check. |
+ // TODO(sra): Pass interceptor to runtime subtype functions. |
+ unlinkInterceptor(); |
+ return null; |
+ } |
+ |
+ if (dartType == 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. |
@@ -1819,23 +1840,52 @@ class TransformingVisitor extends LeafVisitor { |
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], |
- node.sourceInformation); |
+ return unaryBuiltinOperator(BuiltinOperator.IsNumber); |
} |
return new ApplyBuiltinOperator( |
BuiltinOperator.IsNumberAndFloor, |
<Primitive>[prim, prim, prim], |
node.sourceInformation); |
} |
- if (node.dartType == dartTypes.coreTypes.numType || |
- node.dartType == dartTypes.coreTypes.doubleType) { |
- return new ApplyBuiltinOperator( |
- BuiltinOperator.IsNumber, |
- <Primitive>[prim], |
- node.sourceInformation); |
+ if (dartType == dartTypes.coreTypes.numType || |
+ dartType == dartTypes.coreTypes.doubleType) { |
+ return unaryBuiltinOperator(BuiltinOperator.IsNumber); |
+ } |
+ |
+ if (dartType.element == functionCompiler.glue.jsFixedArrayClass) { |
+ // TODO(sra): Check input is restricted to JSArray. |
+ return unaryBuiltinOperator(BuiltinOperator.IsFixedLengthJSArray); |
+ } |
+ |
+ if (dartType.element == functionCompiler.glue.jsExtendableArrayClass) { |
+ // TODO(sra): Check input is restricted to JSArray. |
+ return unaryBuiltinOperator(BuiltinOperator.IsExtendableJSArray); |
} |
+ |
+ if (dartType.element == functionCompiler.glue.jsMutableArrayClass) { |
+ // TODO(sra): Check input is restricted to JSArray. |
+ return unaryBuiltinOperator(BuiltinOperator.IsModifiableJSArray); |
+ } |
+ |
+ if (dartType.element == functionCompiler.glue.jsUnmodifiableArrayClass) { |
+ // TODO(sra): Check input is restricted to JSArray. |
+ return unaryBuiltinOperator(BuiltinOperator.IsUnmodifiableJSArray); |
+ } |
+ |
+ if (dartType == dartTypes.coreTypes.stringType || |
+ dartType == dartTypes.coreTypes.boolType) { |
+ // These types are recognized in tree_ir TypeOperator codegen. |
+ unlinkInterceptor(); |
+ return null; |
+ } |
+ |
+ // TODO(sra): Propagate sourceInformation. |
+ // TODO(sra): If getInterceptor(x) === x or JSNull, rewrite |
+ // getInterceptor(x).$isFoo ---> x != null && x.$isFoo |
+ return new TypeTestViaFlag(node.interceptor.definition, dartType); |
+ } |
+ |
+ Primitive visitTypeTestViaFlag(TypeTestViaFlag node) { |
return null; |
} |
@@ -2263,6 +2313,13 @@ class TypePropagationVisitor implements Visitor { |
case BuiltinOperator.IsNumberAndFloor: |
setValue(node, nonConstant(typeSystem.boolType)); |
break; |
+ |
+ case BuiltinOperator.IsFixedLengthJSArray: |
+ case BuiltinOperator.IsExtendableJSArray: |
+ case BuiltinOperator.IsUnmodifiableJSArray: |
+ case BuiltinOperator.IsModifiableJSArray: |
+ setValue(node, nonConstant(typeSystem.boolType)); |
+ break; |
} |
} |
@@ -2316,9 +2373,21 @@ class TypePropagationVisitor implements Visitor { |
} |
void visitTypeTest(TypeTest node) { |
- AbstractValue input = getValue(node.value.definition); |
+ handleTypeTest(node, getValue(node.value.definition), node.dartType); |
+ } |
+ |
+ void visitTypeTestViaFlag(TypeTestViaFlag node) { |
+ // TODO(sra): We could see if we can find the value in the interceptor |
+ // expression. It would p[robably have no benefit - we only see |
+ // TypeTestViaFlag after rewriting TypeTest and the rewrite of TypeTest |
+ // would already have done the interesting optimizations. |
+ setValue(node, nonConstant(typeSystem.boolType)); |
+ } |
+ |
+ void handleTypeTest( |
+ Primitive node, AbstractValue input, types.DartType dartType) { |
TypeMask boolType = typeSystem.boolType; |
- switch(lattice.isSubtypeOf(input, node.dartType, allowNull: false)) { |
+ switch(lattice.isSubtypeOf(input, dartType, allowNull: false)) { |
case AbstractBool.Nothing: |
break; // And come back later. |