| 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 75a473e891ee3d213d14b37aa177069b73748ae6..6c394f89f828afd475b8b10a717bd86a64070f95 100644
|
| --- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart
|
| +++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
|
| @@ -19,76 +19,11 @@ import '../elements/elements.dart' show ClassElement, Element, Entity,
|
| import '../dart2jslib.dart' show ClassWorld;
|
| import '../universe/universe.dart';
|
|
|
| -abstract class TypeSystem<T> {
|
| - T get dynamicType;
|
| - T get typeType;
|
| - T get functionType;
|
| - T get boolType;
|
| - T get intType;
|
| - T get numType;
|
| - 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 exact(ClassElement element);
|
| - T getTypeOf(ConstantValue constant);
|
| -
|
| - bool areDisjoint(T leftType, T rightType);
|
| -
|
| - /// True if all values satisfying [type] are booleans (null is not a boolean).
|
| - bool isDefinitelyBool(T type);
|
| -
|
| - bool isDefinitelyNotNull(T type);
|
| -
|
| - AbstractBool isSubtypeOf(T value, types.DartType type, {bool allowNull});
|
| -}
|
| -
|
| -class UnitTypeSystem implements TypeSystem<String> {
|
| - static const String UNIT = 'unit';
|
| -
|
| - get boolType => UNIT;
|
| - get dynamicType => UNIT;
|
| - get functionType => UNIT;
|
| - get intType => UNIT;
|
| - get numType => UNIT;
|
| - get listType => UNIT;
|
| - get mapType => UNIT;
|
| - get stringType => UNIT;
|
| - get typeType => UNIT;
|
| - get nonNullType => UNIT;
|
| -
|
| - getParameterType(_) => UNIT;
|
| - getReturnType(_) => UNIT;
|
| - getSelectorReturnType(_) => UNIT;
|
| - getFieldType(_) => UNIT;
|
| - join(a, b) => UNIT;
|
| - exact(_) => UNIT;
|
| - getTypeOf(_) => UNIT;
|
| -
|
| - bool areDisjoint(String leftType, String rightType) {
|
| - return false;
|
| - }
|
| -
|
| - bool isDefinitelyBool(_) => false;
|
| -
|
| - bool isDefinitelyNotNull(_) => false;
|
| -
|
| - AbstractBool isSubtypeOf(value, type, {bool allowNull}) {
|
| - return AbstractBool.Maybe;
|
| - }
|
| -}
|
| -
|
| enum AbstractBool {
|
| True, False, Maybe, Nothing
|
| }
|
|
|
| -class TypeMaskSystem implements TypeSystem<TypeMask> {
|
| +class TypeMaskSystem {
|
| final TypesTask inferrer;
|
| final ClassWorld classWorld;
|
|
|
| @@ -124,12 +59,10 @@ class TypeMaskSystem implements TypeSystem<TypeMask> {
|
| return inferrer.getGuaranteedTypeOfElement(field);
|
| }
|
|
|
| - @override
|
| TypeMask join(TypeMask a, TypeMask b) {
|
| return a.union(b, classWorld);
|
| }
|
|
|
| - @override
|
| TypeMask getTypeOf(ConstantValue constant) {
|
| return computeTypeMask(inferrer.compiler, constant);
|
| }
|
| @@ -148,7 +81,6 @@ class TypeMaskSystem implements TypeSystem<TypeMask> {
|
|
|
| bool isDefinitelyNotNull(TypeMask t) => !t.isNullable;
|
|
|
| - @override
|
| bool areDisjoint(TypeMask leftType, TypeMask rightType) {
|
| TypeMask intersection = leftType.intersection(rightType, classWorld);
|
| return intersection.isEmpty && !intersection.isNullable;
|
| @@ -189,28 +121,56 @@ class TypeMaskSystem implements TypeSystem<TypeMask> {
|
| }
|
| }
|
|
|
| -class ConstantPropagationLattice<T> {
|
| - final TypeSystem<T> typeSystem;
|
| +class ConstantPropagationLattice {
|
| + final TypeMaskSystem typeSystem;
|
| final ConstantSystem constantSystem;
|
| final types.DartTypes dartTypes;
|
| + final AbstractValue anything;
|
|
|
| - ConstantPropagationLattice(this.typeSystem,
|
| + ConstantPropagationLattice(TypeMaskSystem typeSystem,
|
| this.constantSystem,
|
| - this.dartTypes);
|
| + this.dartTypes)
|
| + : this.typeSystem = typeSystem,
|
| + anything = new AbstractValue.nonConstant(typeSystem.dynamicType);
|
|
|
| - final _AbstractValue<T> nothing = new _AbstractValue<T>.nothing();
|
| + final AbstractValue nothing = new AbstractValue.nothing();
|
|
|
| - _AbstractValue<T> constant(ConstantValue value) {
|
| - return new _AbstractValue<T>.constantValue(value,
|
| - typeSystem.getTypeOf(value));
|
| + AbstractValue constant(ConstantValue value, [TypeMask type]) {
|
| + if (type == null) type = typeSystem.getTypeOf(value);
|
| + return new AbstractValue.constantValue(value, type);
|
| }
|
|
|
| - _AbstractValue<T> nonConstant(T type) {
|
| - return new _AbstractValue<T>.nonConstant(type);
|
| + AbstractValue nonConstant([TypeMask type]) {
|
| + if (type == null) type = typeSystem.dynamicType;
|
| + return new AbstractValue.nonConstant(type);
|
| }
|
|
|
| - _AbstractValue<T> get anything {
|
| - return new _AbstractValue<T>.nonConstant(typeSystem.dynamicType);
|
| + /// Compute the join of two values in the lattice.
|
| + AbstractValue join(AbstractValue x, AbstractValue y) {
|
| + assert(x != null);
|
| + assert(y != null);
|
| +
|
| + if (x.isNothing) {
|
| + return y;
|
| + } else if (y.isNothing) {
|
| + return x;
|
| + } else if (x.isConstant && y.isConstant && x.constant == y.constant) {
|
| + return x;
|
| + } else {
|
| + return new AbstractValue.nonConstant(typeSystem.join(x.type, y.type));
|
| + }
|
| + }
|
| +
|
| + /// True if all members of this value are booleans.
|
| + bool isDefinitelyBool(AbstractValue value) {
|
| + return value.isNothing || typeSystem.isDefinitelyBool(value.type);
|
| + }
|
| +
|
| + /// True if null is not a member of this value.
|
| + bool isDefinitelyNotNull(AbstractValue value) {
|
| + if (value.isNothing) return true;
|
| + if (value.isConstant) return !value.constant.isNull;
|
| + return typeSystem.isDefinitelyNotNull(value.type);
|
| }
|
|
|
| /// Returns whether the given [value] is an instance of [type].
|
| @@ -223,7 +183,7 @@ class ConstantPropagationLattice<T> {
|
| /// If [allowNull] is true, `null` is considered to an instance of anything,
|
| /// otherwise it is only considered an instance of [Object], [dynamic], and
|
| /// [Null].
|
| - AbstractBool isSubtypeOf(_AbstractValue<T> value,
|
| + AbstractBool isSubtypeOf(AbstractValue value,
|
| types.DartType type,
|
| {bool allowNull}) {
|
| assert(allowNull != null);
|
| @@ -261,8 +221,8 @@ class ConstantPropagationLattice<T> {
|
| /// Because we do not explicitly track thrown values, we currently use the
|
| /// convention that constant values are returned from this method only
|
| /// if the operation is known not to throw.
|
| - _AbstractValue<T> unaryOp(UnaryOperator operator,
|
| - _AbstractValue<T> value) {
|
| + AbstractValue unaryOp(UnaryOperator operator,
|
| + AbstractValue value) {
|
| // TODO(asgerf): Also return information about whether this can throw?
|
| if (value.isNothing) {
|
| return nothing;
|
| @@ -282,9 +242,9 @@ class ConstantPropagationLattice<T> {
|
| /// Because we do not explicitly track thrown values, we currently use the
|
| /// convention that constant values are returned from this method only
|
| /// if the operation is known not to throw.
|
| - _AbstractValue<T> binaryOp(BinaryOperator operator,
|
| - _AbstractValue<T> left,
|
| - _AbstractValue<T> right) {
|
| + AbstractValue binaryOp(BinaryOperator operator,
|
| + AbstractValue left,
|
| + AbstractValue right) {
|
| if (left.isNothing || right.isNothing) {
|
| return nothing;
|
| }
|
| @@ -308,37 +268,34 @@ class ConstantPropagationLattice<T> {
|
| * Implemented according to 'Constant Propagation with Conditional Branches'
|
| * by Wegman, Zadeck.
|
| */
|
| -class TypePropagator<T> extends Pass {
|
| +class TypePropagator extends Pass {
|
| String get passName => 'Sparse constant propagation';
|
|
|
| - final types.DartTypes _dartTypes;
|
| -
|
| // The constant system is used for evaluation of expressions with constant
|
| // arguments.
|
| - final ConstantSystem _constantSystem;
|
| - final TypeSystem _typeSystem;
|
| + final ConstantPropagationLattice _lattice;
|
| final dart2js.InternalErrorFunction _internalError;
|
| - final Map<Primitive, _AbstractValue> _types = <Primitive, _AbstractValue>{};
|
| + final Map<Definition, AbstractValue> _values = <Definition, AbstractValue>{};
|
|
|
| - TypePropagator(this._dartTypes,
|
| - this._constantSystem,
|
| - this._typeSystem,
|
| - this._internalError);
|
| + TypePropagator(dart2js.Compiler compiler)
|
| + : _internalError = compiler.internalError,
|
| + _lattice = new ConstantPropagationLattice(
|
| + new TypeMaskSystem(compiler),
|
| + compiler.backend.constantSystem,
|
| + compiler.types);
|
|
|
| @override
|
| void rewrite(FunctionDefinition root) {
|
| // Set all parent pointers.
|
| new ParentVisitor().visit(root);
|
|
|
| - ConstantPropagationLattice<T> lattice = new ConstantPropagationLattice<T>(
|
| - _typeSystem, _constantSystem, _dartTypes);
|
| Map<Expression, ConstantValue> replacements = <Expression, ConstantValue>{};
|
|
|
| // Analyze. In this phase, the entire term is analyzed for reachability
|
| // and the abstract value of each expression.
|
| - _TypePropagationVisitor<T> analyzer = new _TypePropagationVisitor<T>(
|
| - lattice,
|
| - _types,
|
| + TypePropagationVisitor analyzer = new TypePropagationVisitor(
|
| + _lattice,
|
| + _values,
|
| replacements,
|
| _internalError);
|
|
|
| @@ -347,8 +304,8 @@ class TypePropagator<T> extends Pass {
|
| // Transform. Uses the data acquired in the previous analysis phase to
|
| // replace branches with fixed targets and side-effect-free expressions
|
| // with constant results or existing values that are in scope.
|
| - _TransformingVisitor<T> transformer = new _TransformingVisitor<T>(
|
| - lattice,
|
| + TransformingVisitor transformer = new TransformingVisitor(
|
| + _lattice,
|
| analyzer.reachableNodes,
|
| analyzer.values,
|
| replacements,
|
| @@ -356,28 +313,28 @@ class TypePropagator<T> extends Pass {
|
| transformer.transform(root);
|
| }
|
|
|
| - getType(Node node) => _types[node];
|
| + getType(Node node) => _values[node];
|
| }
|
|
|
| /**
|
| * Uses the information from a preceding analysis pass in order to perform the
|
| * actual transformations on the CPS graph.
|
| */
|
| -class _TransformingVisitor<T> extends RecursiveVisitor {
|
| +class TransformingVisitor extends RecursiveVisitor {
|
| final Set<Node> reachable;
|
| - final Map<Node, _AbstractValue> values;
|
| + final Map<Node, AbstractValue> values;
|
| final Map<Expression, ConstantValue> replacements;
|
| - final ConstantPropagationLattice<T> valueLattice;
|
| + final ConstantPropagationLattice lattice;
|
|
|
| - TypeSystem<T> get typeSystem => valueLattice.typeSystem;
|
| + TypeMaskSystem get typeSystem => lattice.typeSystem;
|
|
|
| final dart2js.InternalErrorFunction internalError;
|
|
|
| - _TransformingVisitor(this.valueLattice,
|
| - this.reachable,
|
| - this.values,
|
| - this.replacements,
|
| - this.internalError);
|
| + TransformingVisitor(this.lattice,
|
| + this.reachable,
|
| + this.values,
|
| + this.replacements,
|
| + this.internalError);
|
|
|
| void transform(FunctionDefinition root) {
|
| visit(root);
|
| @@ -387,7 +344,7 @@ class _TransformingVisitor<T> extends RecursiveVisitor {
|
| ConstantExpression constExp =
|
| const ConstantExpressionCreator().convert(constant);
|
| Constant primitive = new Constant(constExp, constant);
|
| - values[primitive] = new _AbstractValue.constantValue(constant,
|
| + values[primitive] = new AbstractValue.constantValue(constant,
|
| typeSystem.getTypeOf(constant));
|
| return primitive;
|
| }
|
| @@ -476,8 +433,8 @@ class _TransformingVisitor<T> extends RecursiveVisitor {
|
| });
|
|
|
| if (letPrim == null) {
|
| - _AbstractValue<T> receiver = getValue(node.receiver.definition);
|
| - node.receiverIsNotNull = receiver.isDefinitelyNotNull(typeSystem);
|
| + AbstractValue receiver = getValue(node.receiver.definition);
|
| + node.receiverIsNotNull = lattice.isDefinitelyNotNull(receiver);
|
| super.visitInvokeMethod(node);
|
| } else {
|
| visitLetPrim(letPrim);
|
| @@ -503,8 +460,8 @@ class _TransformingVisitor<T> extends RecursiveVisitor {
|
| Continuation cont = node.continuation.definition;
|
| InteriorNode parent = node.parent;
|
|
|
| - _AbstractValue<T> value = getValue(node.value.definition);
|
| - switch (valueLattice.isSubtypeOf(value, node.type, allowNull: true)) {
|
| + AbstractValue value = getValue(node.value.definition);
|
| + switch (lattice.isSubtypeOf(value, node.type, allowNull: true)) {
|
| case AbstractBool.Maybe:
|
| case AbstractBool.Nothing:
|
| break;
|
| @@ -529,18 +486,18 @@ class _TransformingVisitor<T> extends RecursiveVisitor {
|
| super.visitTypeCast(node);
|
| }
|
|
|
| - _AbstractValue<T> getValue(Primitive primitive) {
|
| - _AbstractValue<T> value = values[primitive];
|
| - return value == null ? new _AbstractValue.nothing() : value;
|
| + AbstractValue getValue(Primitive primitive) {
|
| + AbstractValue value = values[primitive];
|
| + return value == null ? new AbstractValue.nothing() : value;
|
| }
|
|
|
| void visitIdentical(Identical node) {
|
| Primitive left = node.left.definition;
|
| Primitive right = node.right.definition;
|
| - _AbstractValue<T> leftValue = getValue(left);
|
| - _AbstractValue<T> rightValue = getValue(right);
|
| + AbstractValue leftValue = getValue(left);
|
| + AbstractValue rightValue = getValue(right);
|
| // Replace identical(x, true) by x when x is known to be a boolean.
|
| - if (leftValue.isDefinitelyBool(typeSystem) &&
|
| + if (lattice.isDefinitelyBool(leftValue) &&
|
| rightValue.isConstant &&
|
| rightValue.constant.isTrue) {
|
| left.substituteFor(node);
|
| @@ -548,7 +505,7 @@ class _TransformingVisitor<T> extends RecursiveVisitor {
|
| }
|
|
|
| void visitLetPrim(LetPrim node) {
|
| - _AbstractValue<T> value = getValue(node.primitive);
|
| + AbstractValue value = getValue(node.primitive);
|
| if (node.primitive is! Constant && value.isConstant) {
|
| // If the value is a known constant, compile it as a constant.
|
| Constant newPrim = makeConstantPrimitive(value.constant);
|
| @@ -571,7 +528,7 @@ class _TransformingVisitor<T> extends RecursiveVisitor {
|
| * const-ness as well as reachability, both of which are used in the subsequent
|
| * transformation pass.
|
| */
|
| -class _TypePropagationVisitor<T> implements Visitor {
|
| +class TypePropagationVisitor implements Visitor {
|
| // The node worklist stores nodes that are both reachable and need to be
|
| // processed, but have not been processed yet. Using a worklist avoids deep
|
| // recursion.
|
| @@ -588,37 +545,31 @@ class _TypePropagationVisitor<T> implements Visitor {
|
| // since their lattice value has changed.
|
| final Set<Definition> defWorkset = new Set<Definition>();
|
|
|
| - final ConstantPropagationLattice<T> valueLattice;
|
| + final ConstantPropagationLattice lattice;
|
| final dart2js.InternalErrorFunction internalError;
|
|
|
| - TypeSystem get typeSystem => valueLattice.typeSystem;
|
| + TypeMaskSystem get typeSystem => lattice.typeSystem;
|
|
|
| - _AbstractValue<T> nothing = new _AbstractValue.nothing();
|
| + AbstractValue get nothing => lattice.nothing;
|
|
|
| - _AbstractValue<T> nonConstant([T type]) {
|
| - if (type == null) {
|
| - type = typeSystem.dynamicType;
|
| - }
|
| - return new _AbstractValue<T>.nonConstant(type);
|
| - }
|
| + AbstractValue nonConstant([TypeMask type]) => lattice.nonConstant(type);
|
|
|
| - _AbstractValue<T> constantValue(ConstantValue constant, T type) {
|
| - return new _AbstractValue<T>.constantValue(constant, type);
|
| + AbstractValue constantValue(ConstantValue constant, [TypeMask type]) {
|
| + return lattice.constant(constant, type);
|
| }
|
|
|
| - // Stores the current lattice value for nodes. Note that it contains not only
|
| - // definitions as keys, but also expressions such as method invokes.
|
| + // Stores the current lattice value for primitives and mutable variables.
|
| // Access through [getValue] and [setValue].
|
| - final Map<Primitive, _AbstractValue<T>> values;
|
| + final Map<Definition, AbstractValue> values;
|
|
|
| /// Expressions that invoke their call continuation with a constant value
|
| /// and without any side effects. These can be replaced by the constant.
|
| final Map<Expression, ConstantValue> replacements;
|
|
|
| - _TypePropagationVisitor(this.valueLattice,
|
| - this.values,
|
| - this.replacements,
|
| - this.internalError);
|
| + TypePropagationVisitor(this.lattice,
|
| + this.values,
|
| + this.replacements,
|
| + this.internalError);
|
|
|
| void analyze(FunctionDefinition root) {
|
| reachableNodes.clear();
|
| @@ -662,17 +613,17 @@ class _TypePropagationVisitor<T> implements Visitor {
|
| /// Returns the lattice value corresponding to [node], defaulting to nothing.
|
| ///
|
| /// Never returns null.
|
| - _AbstractValue<T> getValue(Node node) {
|
| - _AbstractValue<T> value = values[node];
|
| + AbstractValue getValue(Node node) {
|
| + AbstractValue value = values[node];
|
| return (value == null) ? nothing : value;
|
| }
|
|
|
| /// Joins the passed lattice [updateValue] to the current value of [node],
|
| /// and adds it to the definition work set if it has changed and [node] is
|
| /// a definition.
|
| - void setValue(Node node, _AbstractValue<T> updateValue) {
|
| - _AbstractValue<T> oldValue = getValue(node);
|
| - _AbstractValue<T> newValue = updateValue.join(oldValue, typeSystem);
|
| + void setValue(Node node, AbstractValue updateValue) {
|
| + AbstractValue oldValue = getValue(node);
|
| + AbstractValue newValue = lattice.join(oldValue, updateValue);
|
| if (oldValue == newValue) {
|
| return;
|
| }
|
| @@ -736,7 +687,7 @@ class _TypePropagationVisitor<T> implements Visitor {
|
| assert(cont.parameters.length == 1);
|
| Parameter returnValue = cont.parameters[0];
|
| Entity target = node.target;
|
| - T returnType = target is FieldElement
|
| + TypeMask returnType = target is FieldElement
|
| ? typeSystem.dynamicType
|
| : typeSystem.getReturnType(node.target);
|
| setValue(returnValue, nonConstant(returnType));
|
| @@ -750,7 +701,7 @@ class _TypePropagationVisitor<T> implements Visitor {
|
| // continuation. Note that this is effectively a phi node in SSA terms.
|
| for (int i = 0; i < node.arguments.length; i++) {
|
| Definition def = node.arguments[i].definition;
|
| - _AbstractValue<T> cell = getValue(def);
|
| + AbstractValue cell = getValue(def);
|
| setValue(cont.parameters[i], cell);
|
| }
|
| }
|
| @@ -761,7 +712,7 @@ class _TypePropagationVisitor<T> implements Visitor {
|
|
|
| /// Sets the value of the target continuation parameter, and possibly
|
| /// try to replace the whole invocation with a constant.
|
| - void setResult(_AbstractValue<T> updateValue, {bool canReplace: false}) {
|
| + void setResult(AbstractValue updateValue, {bool canReplace: false}) {
|
| Parameter returnValue = cont.parameters[0];
|
| setValue(returnValue, updateValue);
|
| if (canReplace && updateValue.isConstant) {
|
| @@ -772,7 +723,7 @@ class _TypePropagationVisitor<T> implements Visitor {
|
| }
|
| }
|
|
|
| - _AbstractValue<T> lhs = getValue(node.receiver.definition);
|
| + AbstractValue lhs = getValue(node.receiver.definition);
|
| if (lhs.isNothing) {
|
| return; // And come back later.
|
| }
|
| @@ -785,7 +736,7 @@ class _TypePropagationVisitor<T> implements Visitor {
|
| // TODO(asgerf): Support constant folding on intercepted calls!
|
|
|
| // Calculate the resulting constant if possible.
|
| - _AbstractValue<T> result;
|
| + AbstractValue result;
|
| String opname = node.selector.name;
|
| if (node.selector.argumentCount == 0) {
|
| // Unary operator.
|
| @@ -793,12 +744,12 @@ class _TypePropagationVisitor<T> implements Visitor {
|
| opname = "-";
|
| }
|
| UnaryOperator operator = UnaryOperator.parse(opname);
|
| - result = valueLattice.unaryOp(operator, lhs);
|
| + result = lattice.unaryOp(operator, lhs);
|
| } else if (node.selector.argumentCount == 1) {
|
| // Binary operator.
|
| - _AbstractValue<T> rhs = getValue(node.arguments[0].definition);
|
| + AbstractValue rhs = getValue(node.arguments[0].definition);
|
| BinaryOperator operator = BinaryOperator.parse(opname);
|
| - result = valueLattice.binaryOp(operator, lhs, rhs);
|
| + result = lattice.binaryOp(operator, lhs, rhs);
|
| }
|
|
|
| // Update value of the continuation parameter. Again, this is effectively
|
| @@ -835,7 +786,7 @@ class _TypePropagationVisitor<T> implements Visitor {
|
|
|
| /// Sets the value of the target continuation parameter, and possibly
|
| /// try to replace the whole invocation with a constant.
|
| - void setResult(_AbstractValue<T> updateValue, {bool canReplace: false}) {
|
| + void setResult(AbstractValue updateValue, {bool canReplace: false}) {
|
| Parameter returnValue = cont.parameters[0];
|
| setValue(returnValue, updateValue);
|
| if (canReplace && updateValue.isConstant) {
|
| @@ -856,7 +807,7 @@ class _TypePropagationVisitor<T> implements Visitor {
|
| return constant != null && constant.value.isString;
|
| });
|
|
|
| - T type = typeSystem.stringType;
|
| + TypeMask type = typeSystem.stringType;
|
| assert(cont.parameters.length == 1);
|
| if (allStringConstants) {
|
| // All constant, we can concatenate ourselves.
|
| @@ -888,7 +839,7 @@ class _TypePropagationVisitor<T> implements Visitor {
|
|
|
| void visitBranch(Branch node) {
|
| IsTrue isTrue = node.condition;
|
| - _AbstractValue<T> conditionCell = getValue(isTrue.value.definition);
|
| + AbstractValue conditionCell = getValue(isTrue.value.definition);
|
|
|
| if (conditionCell.isNothing) {
|
| return; // And come back later.
|
| @@ -910,9 +861,9 @@ class _TypePropagationVisitor<T> implements Visitor {
|
| }
|
|
|
| void visitTypeTest(TypeTest node) {
|
| - _AbstractValue<T> input = getValue(node.value.definition);
|
| - T boolType = typeSystem.boolType;
|
| - switch(valueLattice.isSubtypeOf(input, node.type, allowNull: false)) {
|
| + AbstractValue input = getValue(node.value.definition);
|
| + TypeMask boolType = typeSystem.boolType;
|
| + switch(lattice.isSubtypeOf(input, node.type, allowNull: false)) {
|
| case AbstractBool.Nothing:
|
| break; // And come back later.
|
|
|
| @@ -932,8 +883,8 @@ class _TypePropagationVisitor<T> implements Visitor {
|
|
|
| void visitTypeCast(TypeCast node) {
|
| Continuation cont = node.continuation.definition;
|
| - _AbstractValue<T> input = getValue(node.value.definition);
|
| - switch (valueLattice.isSubtypeOf(input, node.type, allowNull: true)) {
|
| + AbstractValue input = getValue(node.value.definition);
|
| + switch (lattice.isSubtypeOf(input, node.type, allowNull: true)) {
|
| case AbstractBool.Nothing:
|
| break; // And come back later.
|
|
|
| @@ -994,7 +945,7 @@ class _TypePropagationVisitor<T> implements Visitor {
|
| // never constant.
|
| // TODO(karlklose): remove reference to the element model.
|
| Entity source = node.hint;
|
| - T type = (source is ParameterElement)
|
| + TypeMask type = (source is ParameterElement)
|
| ? typeSystem.getParameterType(source)
|
| : typeSystem.dynamicType;
|
| setValue(node, nonConstant(type));
|
| @@ -1008,7 +959,7 @@ class _TypePropagationVisitor<T> implements Visitor {
|
| void visitParameter(Parameter node) {
|
| Entity source = node.hint;
|
| // TODO(karlklose): remove reference to the element model.
|
| - T type = (source is ParameterElement)
|
| + TypeMask type = (source is ParameterElement)
|
| ? typeSystem.getParameterType(source)
|
| : typeSystem.dynamicType;
|
| if (node.parent is FunctionDefinition) {
|
| @@ -1057,16 +1008,16 @@ class _TypePropagationVisitor<T> implements Visitor {
|
| }
|
|
|
| void visitIdentical(Identical node) {
|
| - _AbstractValue<T> leftConst = getValue(node.left.definition);
|
| - _AbstractValue<T> rightConst = getValue(node.right.definition);
|
| + AbstractValue leftConst = getValue(node.left.definition);
|
| + AbstractValue rightConst = getValue(node.right.definition);
|
| ConstantValue leftValue = leftConst.constant;
|
| ConstantValue rightValue = rightConst.constant;
|
| if (leftConst.isNothing || rightConst.isNothing) {
|
| // Come back later.
|
| return;
|
| } else if (!leftConst.isConstant || !rightConst.isConstant) {
|
| - T leftType = leftConst.type;
|
| - T rightType = rightConst.type;
|
| + TypeMask leftType = leftConst.type;
|
| + TypeMask rightType = rightConst.type;
|
| if (typeSystem.areDisjoint(leftType, rightType)) {
|
| setValue(node,
|
| constantValue(new FalseConstantValue(), typeSystem.boolType));
|
| @@ -1085,7 +1036,7 @@ class _TypePropagationVisitor<T> implements Visitor {
|
|
|
| void visitInterceptor(Interceptor node) {
|
| setReachable(node.input.definition);
|
| - _AbstractValue<T> value = getValue(node.input.definition);
|
| + AbstractValue value = getValue(node.input.definition);
|
| if (!value.isNothing) {
|
| setValue(node, nonConstant(typeSystem.nonNullType));
|
| }
|
| @@ -1139,26 +1090,26 @@ class _TypePropagationVisitor<T> implements Visitor {
|
| /// CONSTANT: is a constant. The value is stored in the [constant] field,
|
| /// and the type of the constant is in the [type] field.
|
| /// NONCONST: not a constant, but [type] may hold some information.
|
| -class _AbstractValue<T> {
|
| +class AbstractValue {
|
| static const int NOTHING = 0;
|
| static const int CONSTANT = 1;
|
| static const int NONCONST = 2;
|
|
|
| final int kind;
|
| final ConstantValue constant;
|
| - final T type;
|
| + final TypeMask type;
|
|
|
| - _AbstractValue._internal(this.kind, this.constant, this.type) {
|
| + AbstractValue._internal(this.kind, this.constant, this.type) {
|
| assert(kind != CONSTANT || constant != null);
|
| }
|
|
|
| - _AbstractValue.nothing()
|
| + AbstractValue.nothing()
|
| : this._internal(NOTHING, null, null);
|
|
|
| - _AbstractValue.constantValue(ConstantValue constant, T type)
|
| + AbstractValue.constantValue(ConstantValue constant, TypeMask type)
|
| : this._internal(CONSTANT, constant, type);
|
|
|
| - _AbstractValue.nonConstant(T type)
|
| + AbstractValue.nonConstant(TypeMask type)
|
| : this._internal(NONCONST, null, type);
|
|
|
| bool get isNothing => (kind == NOTHING);
|
| @@ -1170,7 +1121,7 @@ class _AbstractValue<T> {
|
| return hash & 0x3fffffff;
|
| }
|
|
|
| - bool operator ==(_AbstractValue that) {
|
| + bool operator ==(AbstractValue that) {
|
| return that.kind == this.kind &&
|
| that.constant == this.constant &&
|
| that.type == this.type;
|
| @@ -1185,35 +1136,6 @@ class _AbstractValue<T> {
|
| }
|
| return null;
|
| }
|
| -
|
| - /// Compute the join of two values in the lattice.
|
| - _AbstractValue join(_AbstractValue that, TypeSystem typeSystem) {
|
| - assert(that != null);
|
| -
|
| - if (isNothing) {
|
| - return that;
|
| - } else if (that.isNothing) {
|
| - return this;
|
| - } else if (isConstant && that.isConstant && constant == that.constant) {
|
| - return this;
|
| - } else {
|
| - return new _AbstractValue.nonConstant(
|
| - typeSystem.join(this.type, that.type));
|
| - }
|
| - }
|
| -
|
| - /// True if all members of this value are booleans.
|
| - bool isDefinitelyBool(TypeSystem<T> typeSystem) {
|
| - 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
|
|
|