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 f0e3eb070edf6ff0c5fafe497e779fde359bea2d..f66f370dc05476b13461929317e052593f001b7a 100644 |
--- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart |
+++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart |
@@ -2,7 +2,22 @@ |
// for details. All rights reserved. Use of this source code is governed by a |
// BSD-style license that can be found in the LICENSE file. |
-part of dart2js.cps_ir.optimizers; |
+import 'optimizers.dart' show Pass, ParentVisitor; |
+ |
+import '../constants/constant_system.dart'; |
+import '../constants/expressions.dart'; |
+import '../resolution/operators.dart'; |
+import '../constants/values.dart'; |
+import '../dart_types.dart' as types; |
+import '../dart2jslib.dart' as dart2js; |
+import '../tree/tree.dart' show LiteralDartString; |
+import 'cps_ir_nodes.dart'; |
+import '../types/types.dart' show TypeMask, TypesTask; |
+import '../types/constants.dart' show computeTypeMask; |
+import '../elements/elements.dart' show ClassElement, Element, Entity, |
+ FieldElement, FunctionElement, ParameterElement; |
+import '../dart2jslib.dart' show ClassWorld; |
+import '../universe/universe.dart'; |
abstract class TypeSystem<T> { |
T get dynamicType; |
@@ -15,9 +30,13 @@ abstract class TypeSystem<T> { |
T get mapType; |
T getReturnType(FunctionElement element); |
+ T getSelectorReturnType(Selector selector); |
T getParameterType(ParameterElement element); |
T join(T a, T b); |
T typeOf(ConstantValue constant); |
+ |
+ /// True if all values satisfying [type] are booleans (null is not a boolean). |
+ bool isDefinitelyBool(T type); |
} |
class UnitTypeSystem implements TypeSystem<String> { |
@@ -34,8 +53,11 @@ class UnitTypeSystem implements TypeSystem<String> { |
getParameterType(_) => UNIT; |
getReturnType(_) => UNIT; |
+ getSelectorReturnType(_) => UNIT; |
join(a, b) => UNIT; |
typeOf(_) => UNIT; |
+ |
+ bool isDefinitelyBool(_) => false; |
} |
class TypeMaskSystem implements TypeSystem<TypeMask> { |
@@ -64,6 +86,10 @@ class TypeMaskSystem implements TypeSystem<TypeMask> { |
return inferrer.getGuaranteedReturnTypeOfElement(function); |
} |
+ TypeMask getSelectorReturnType(Selector selector) { |
+ return inferrer.getGuaranteedTypeOfSelector(selector); |
+ } |
+ |
@override |
TypeMask join(TypeMask a, TypeMask b) { |
return a.union(b, classWorld); |
@@ -73,6 +99,10 @@ class TypeMaskSystem implements TypeSystem<TypeMask> { |
TypeMask typeOf(ConstantValue constant) { |
return computeTypeMask(inferrer.compiler, constant); |
} |
+ |
+ bool isDefinitelyBool(TypeMask t) { |
+ return t.containsOnlyBool(classWorld) && !t.isNullable; |
+ } |
} |
/** |
@@ -124,8 +154,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. |
- _TransformingVisitor transformer = new _TransformingVisitor( |
- analyzer.reachableNodes, analyzer.values, _internalError); |
+ _TransformingVisitor<T> transformer = new _TransformingVisitor<T>( |
+ analyzer.reachableNodes, analyzer.values, _internalError, _typeSystem); |
transformer.transform(root); |
} |
@@ -136,13 +166,17 @@ class TypePropagator<T> extends Pass { |
* Uses the information from a preceding analysis pass in order to perform the |
* actual transformations on the CPS graph. |
*/ |
-class _TransformingVisitor extends RecursiveVisitor { |
+class _TransformingVisitor<T> extends RecursiveVisitor { |
final Set<Node> reachable; |
final Map<Node, _AbstractValue> values; |
+ final TypeSystem<T> typeSystem; |
final dart2js.InternalErrorFunction internalError; |
- _TransformingVisitor(this.reachable, this.values, this.internalError); |
+ _TransformingVisitor(this.reachable, |
+ this.values, |
+ this.internalError, |
+ this.typeSystem); |
void transform(RootNode root) { |
visit(root); |
@@ -277,6 +311,24 @@ class _TransformingVisitor extends RecursiveVisitor { |
visitLetPrim(letPrim); |
} |
} |
+ |
+ _AbstractValue<T> getValue(Primitive primitive) { |
+ _AbstractValue<T> 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); |
+ // Replace identical(x, true) by x when x is known to be a boolean. |
+ if (leftValue.isDefinitelyBool(typeSystem) && |
+ rightValue.isConstant && |
+ rightValue.constant.isTrue) { |
+ left.substituteFor(node); |
+ } |
+ } |
} |
/** |
@@ -505,7 +557,7 @@ class _TypePropagationVisitor<T> implements Visitor { |
if (lhs.isNothing) { |
return; // And come back later. |
} else if (lhs.isNonConst) { |
- setValues(nonConstant()); |
+ setValues(nonConstant(typeSystem.getSelectorReturnType(node.selector))); |
return; |
} else if (!node.selector.isOperator) { |
// TODO(jgruber): Handle known methods on constants such as String.length. |
@@ -917,6 +969,12 @@ class _AbstractValue<T> { |
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); |
+ } |
} |
class ConstantExpressionCreator |