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 87f9abeb58e426b238675eff6af539112b913ace..d8892fd01f24a1015571258cf8446673655001eb 100644 |
| --- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart |
| +++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart |
| @@ -28,15 +28,20 @@ abstract class TypeSystem<T> { |
| T get stringType; |
| T get listType; |
| T get mapType; |
| + T get nonNullType; |
| T getReturnType(FunctionElement element); |
| T getSelectorReturnType(Selector selector); |
| T getParameterType(ParameterElement element); |
| + T getFieldType(FieldElement element); |
| T join(T a, T b); |
| T typeOf(ConstantValue constant); |
| + T exact(ClassElement element); |
| /// True if all values satisfying [type] are booleans (null is not a boolean). |
| bool isDefinitelyBool(T type); |
| + |
| + bool isDefinitelyNotNull(T type); |
| } |
| class UnitTypeSystem implements TypeSystem<String> { |
| @@ -50,14 +55,19 @@ class UnitTypeSystem implements TypeSystem<String> { |
| get mapType => UNIT; |
| get stringType => UNIT; |
| get typeType => UNIT; |
| + get nonNullType => UNIT; |
| getParameterType(_) => UNIT; |
| getReturnType(_) => UNIT; |
| getSelectorReturnType(_) => UNIT; |
| + getFieldType(_) => UNIT; |
| join(a, b) => UNIT; |
| typeOf(_) => UNIT; |
| + exact(_) => UNIT; |
| bool isDefinitelyBool(_) => false; |
| + |
| + bool isDefinitelyNotNull(_) => false; |
| } |
| class TypeMaskSystem implements TypeSystem<TypeMask> { |
| @@ -72,6 +82,7 @@ class TypeMaskSystem implements TypeSystem<TypeMask> { |
| TypeMask get stringType => inferrer.stringType; |
| TypeMask get listType => inferrer.listType; |
| TypeMask get mapType => inferrer.mapType; |
| + TypeMask get nonNullType => inferrer.nonNullType; |
| // TODO(karlklose): remove compiler here. |
| TypeMaskSystem(dart2js.Compiler compiler) |
| @@ -90,6 +101,10 @@ class TypeMaskSystem implements TypeSystem<TypeMask> { |
| return inferrer.getGuaranteedTypeOfSelector(selector); |
| } |
| + TypeMask getFieldType(FieldElement field) { |
| + return inferrer.getGuaranteedTypeOfElement(field); |
| + } |
| + |
| @override |
| TypeMask join(TypeMask a, TypeMask b) { |
| return a.union(b, classWorld); |
| @@ -100,9 +115,19 @@ class TypeMaskSystem implements TypeSystem<TypeMask> { |
| return computeTypeMask(inferrer.compiler, constant); |
| } |
| + TypeMask exact(ClassElement element) { |
| + // The class world does not know about classes created by |
| + // closure conversion, so just treat those as a subtypes of Function. |
| + // TODO(asgerf): Maybe closure conversion should create a new ClassWorld? |
| + if (element.isClosure) return functionType; |
|
karlklose
2015/06/02 12:53:22
We could also create ForwardingTypeMasks that unde
|
| + return new TypeMask.exact(element, classWorld); |
| + } |
| + |
| bool isDefinitelyBool(TypeMask t) { |
| return t.containsOnlyBool(classWorld) && !t.isNullable; |
| } |
| + |
| + bool isDefinitelyNotNull(TypeMask t) => !t.isNullable; |
| } |
| /** |
| @@ -274,6 +299,8 @@ class _TransformingVisitor<T> extends RecursiveVisitor { |
| }); |
| if (letPrim == null) { |
| + _AbstractValue<T> receiver = getValue(node.receiver.definition); |
| + node.receiverIsNotNull = receiver.isDefinitelyNotNull(typeSystem); |
| super.visitInvokeMethod(node); |
| } else { |
| visitLetPrim(letPrim); |
| @@ -453,7 +480,8 @@ class _TypePropagationVisitor<T> implements Visitor { |
| void visitFunctionDefinition(FunctionDefinition node) { |
| if (node.thisParameter != null) { |
| - setValue(node.thisParameter, nonConstant()); |
| + // TODO(asgerf): Use a more precise type for 'this'. |
| + setValue(node.thisParameter, nonConstant(typeSystem.nonNullType)); |
| } |
| node.parameters.forEach(visit); |
| setReachable(node.body); |
| @@ -596,7 +624,7 @@ class _TypePropagationVisitor<T> implements Visitor { |
| assert(cont.parameters.length == 1); |
| Parameter returnValue = cont.parameters[0]; |
| - setValue(returnValue, nonConstant()); |
| + setValue(returnValue, nonConstant(typeSystem.getReturnType(node.target))); |
| } |
| void visitConcatenateStrings(ConcatenateStrings node) { |
| @@ -794,7 +822,11 @@ class _TypePropagationVisitor<T> implements Visitor { |
| } |
| void visitGetStatic(GetStatic node) { |
| - setValue(node, nonConstant()); |
| + if (node.element.isFunction) { |
| + setValue(node, nonConstant(typeSystem.functionType)); |
| + } else { |
| + setValue(node, nonConstant(typeSystem.getFieldType(node.element))); |
| + } |
| } |
| void visitSetStatic(SetStatic node) { |
| @@ -807,7 +839,7 @@ class _TypePropagationVisitor<T> implements Visitor { |
| assert(cont.parameters.length == 1); |
| Parameter returnValue = cont.parameters[0]; |
| - setValue(returnValue, nonConstant()); |
| + setValue(returnValue, nonConstant(typeSystem.getFieldType(node.element))); |
| } |
| void visitIsTrue(IsTrue node) { |
| @@ -841,12 +873,12 @@ class _TypePropagationVisitor<T> implements Visitor { |
| setReachable(node.input.definition); |
| _AbstractValue<T> value = getValue(node.input.definition); |
| if (!value.isNothing) { |
| - setValue(node, nonConstant()); |
| + setValue(node, nonConstant(typeSystem.nonNullType)); |
| } |
| } |
| void visitGetField(GetField node) { |
| - setValue(node, nonConstant()); |
| + setValue(node, nonConstant(typeSystem.getFieldType(node.field))); |
| } |
| void visitSetField(SetField node) { |
| @@ -854,11 +886,11 @@ class _TypePropagationVisitor<T> implements Visitor { |
| } |
| void visitCreateBox(CreateBox node) { |
| - setValue(node, nonConstant()); |
| + setValue(node, nonConstant(typeSystem.nonNullType)); |
| } |
| void visitCreateInstance(CreateInstance node) { |
| - setValue(node, nonConstant()); |
| + setValue(node, nonConstant(typeSystem.exact(node.classElement))); |
| } |
| void visitReifyRuntimeType(ReifyRuntimeType node) { |
| @@ -879,7 +911,8 @@ class _TypePropagationVisitor<T> implements Visitor { |
| } |
| void visitCreateInvocationMirror(CreateInvocationMirror node) { |
| - setValue(node, nonConstant()); |
| + // TODO(asgerf): Expose [Invocation] type. |
| + setValue(node, nonConstant(typeSystem.nonNullType)); |
| } |
| } |
| @@ -960,6 +993,13 @@ class _AbstractValue<T> { |
| if (kind == NOTHING) return true; |
| return typeSystem.isDefinitelyBool(type); |
| } |
| + |
| + /// True if null is not a member of this value. |
| + bool isDefinitelyNotNull(TypeSystem<T> typeSystem) { |
| + if (kind == NOTHING) return true; |
| + if (kind == CONSTANT) return !constant.isNull; |
| + return typeSystem.isDefinitelyNotNull(type); |
| + } |
| } |
| class ConstantExpressionCreator |