Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(252)

Unified Diff: pkg/compiler/lib/src/cps_ir/type_propagation.dart

Issue 1276843008: dart2js cps: Change rewriting of equality operators. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Update test + minor improvement in logical rewriter Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 d987a24514ebbc6b2a9b8ac6bab1acb90fd02e31..4f5164c66add32423595151cec9029615245ecc9 100644
--- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart
+++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
@@ -51,8 +51,18 @@ class TypeMaskSystem {
: inferrer = compiler.typesTask,
classWorld = compiler.world,
backend = compiler.backend {
+
+ // Build the number+string+bool type. To make containment tests more
+ // inclusive, we use the num, String, bool types for this, not
+ // the JSNumber, JSString, JSBool subclasses.
+ TypeMask anyNum =
+ new TypeMask.nonNullSubtype(classWorld.numClass, classWorld);
+ TypeMask anyString =
+ new TypeMask.nonNullSubtype(classWorld.stringClass, classWorld);
+ TypeMask anyBool =
+ new TypeMask.nonNullSubtype(classWorld.boolClass, classWorld);
numStringBoolType =
- new TypeMask.unionOf(<TypeMask>[numType, stringType, boolType],
+ new TypeMask.unionOf(<TypeMask>[anyNum, anyString, anyBool],
classWorld);
}
@@ -108,22 +118,22 @@ class TypeMaskSystem {
bool isDefinitelyBool(TypeMask t, {bool allowNull: false}) {
if (!allowNull && t.isNullable) return false;
- return t.containsOnlyBool(classWorld);
+ return t.nonNullable().containsOnlyBool(classWorld);
}
bool isDefinitelyNum(TypeMask t, {bool allowNull: false}) {
if (!allowNull && t.isNullable) return false;
- return t.containsOnlyNum(classWorld);
+ return t.nonNullable().containsOnlyNum(classWorld);
}
bool isDefinitelyString(TypeMask t, {bool allowNull: false}) {
if (!allowNull && t.isNullable) return false;
- return t.containsOnlyString(classWorld);
+ return t.nonNullable().containsOnlyString(classWorld);
}
bool isDefinitelyNumStringBool(TypeMask t, {bool allowNull: false}) {
if (!allowNull && t.isNullable) return false;
- return numStringBoolType.containsMask(t, classWorld);
+ return numStringBoolType.containsMask(t.nonNullable(), classWorld);
}
bool isDefinitelyNotNumStringBool(TypeMask t) {
@@ -151,17 +161,17 @@ class TypeMaskSystem {
bool isDefinitelyNativeList(TypeMask t, {bool allowNull: false}) {
if (!allowNull && t.isNullable) return false;
- return t.satisfies(backend.jsArrayClass, classWorld);
+ return t.nonNullable().satisfies(backend.jsArrayClass, classWorld);
}
bool isDefinitelyMutableNativeList(TypeMask t, {bool allowNull: false}) {
if (!allowNull && t.isNullable) return false;
- return t.satisfies(backend.jsMutableArrayClass, classWorld);
+ return t.nonNullable().satisfies(backend.jsMutableArrayClass, classWorld);
}
bool isDefinitelyFixedNativeList(TypeMask t, {bool allowNull: false}) {
if (!allowNull && t.isNullable) return false;
- return t.satisfies(backend.jsFixedArrayClass, classWorld);
+ return t.nonNullable().satisfies(backend.jsFixedArrayClass, classWorld);
}
bool areDisjoint(TypeMask leftType, TypeMask rightType) {
@@ -420,6 +430,16 @@ class ConstantPropagationLattice {
}
return null;
+ case BinaryOperatorKind.EQ:
+ bool behavesLikeIdentity =
+ isDefinitelyNumStringBool(left, allowNull: true) ||
+ right.isNullConstant;
+ if (behavesLikeIdentity &&
+ typeSystem.areDisjoint(left.type, right.type)) {
+ return constant(new FalseConstantValue());
+ }
+ return null;
+
default:
return null; // The caller will use return type from type inference.
}
@@ -604,7 +624,9 @@ class TransformingVisitor extends LeafVisitor {
void visitLetPrim(LetPrim node) {
AbstractValue value = getValue(node.primitive);
- if (node.primitive is! Constant && value.isConstant) {
+ if (node.primitive is! Constant &&
+ node.primitive.isSafeForElimination &&
+ value.isConstant) {
// If the value is a known constant, compile it as a constant.
Constant newPrim = makeConstantPrimitive(value.constant);
newPrim.substituteFor(node.primitive);
@@ -762,7 +784,8 @@ class TransformingVisitor extends LeafVisitor {
}
if (condition is ApplyBuiltinOperator &&
- condition.operator == BuiltinOperator.LooseEq) {
+ (condition.operator == BuiltinOperator.LooseEq ||
+ condition.operator == BuiltinOperator.StrictEq)) {
Primitive leftArg = condition.arguments[0].definition;
Primitive rightArg = condition.arguments[1].definition;
AbstractValue left = getValue(leftArg);
@@ -781,6 +804,20 @@ class TransformingVisitor extends LeafVisitor {
Branch branch = new Branch(new IsTrue(rightArg), falseCont, trueCont);
replaceSubtree(node, branch);
return;
+ } else if (right.isTrueConstant &&
+ lattice.isDefinitelyBool(left, allowNull: true)) {
+ // Rewrite:
+ // if (x == true) S1 else S2
+ // =>
+ // if (x) S1 else S2
+ Branch branch = new Branch(new IsTrue(leftArg), trueCont, falseCont);
+ replaceSubtree(node, branch);
+ return;
+ } else if (left.isTrueConstant &&
+ lattice.isDefinitelyBool(right, allowNull: true)) {
+ Branch branch = new Branch(new IsTrue(rightArg), trueCont, falseCont);
+ replaceSubtree(node, branch);
+ return;
}
}
}
@@ -845,26 +882,10 @@ class TransformingVisitor extends LeafVisitor {
// Equality is special due to its treatment of null values and the
// fact that Dart-null corresponds to both JS-null and JS-undefined.
// Please see documentation for IsFalsy, StrictEq, and LooseEq.
- if (left.isNullConstant || right.isNullConstant) {
- return replaceWithBinary(BuiltinOperator.LooseEq, leftArg, rightArg);
- }
- // Comparison of numbers, strings, and booleans.
- if (lattice.isDefinitelyNumStringBool(left, allowNull: true) &&
- lattice.isDefinitelyNumStringBool(right, allowNull: true) &&
- !(left.isNullable && right.isNullable)) {
- return replaceWithBinary(BuiltinOperator.StrictEq, leftArg, rightArg);
- }
- if (lattice.isDefinitelyNum(left, allowNull: true) &&
- lattice.isDefinitelyNum(right, allowNull: true)) {
- return replaceWithBinary(BuiltinOperator.LooseEq, leftArg, rightArg);
- }
- if (lattice.isDefinitelyString(left, allowNull: true) &&
- lattice.isDefinitelyString(right, allowNull: true)) {
- return replaceWithBinary(BuiltinOperator.LooseEq, leftArg, rightArg);
- }
- if (lattice.isDefinitelyBool(left, allowNull: true) &&
- lattice.isDefinitelyBool(right, allowNull: true)) {
- return replaceWithBinary(BuiltinOperator.LooseEq, leftArg, rightArg);
+ if (lattice.isDefinitelyNumStringBool(left, allowNull: true) ||
+ right.isNullConstant) {
+ return replaceWithBinary(BuiltinOperator.Identical,
+ leftArg, rightArg);
}
} else {
if (lattice.isDefinitelyNum(left, allowNull: false) &&
@@ -1561,15 +1582,41 @@ class TransformingVisitor extends LeafVisitor {
break;
case BuiltinOperator.Identical:
- Primitive left = node.arguments[0].definition;
- Primitive right = node.arguments[1].definition;
- AbstractValue leftValue = getValue(left);
- AbstractValue rightValue = getValue(right);
- // Replace identical(x, true) by x when x is known to be a boolean.
- if (lattice.isDefinitelyBool(leftValue) &&
- rightValue.isConstant &&
- rightValue.constant.isTrue) {
- left.substituteFor(node);
+ Primitive leftArg = node.arguments[0].definition;
+ Primitive rightArg = node.arguments[1].definition;
+ AbstractValue left = getValue(leftArg);
+ AbstractValue right = getValue(rightArg);
+ if (lattice.isDefinitelyBool(left) &&
+ right.isConstant &&
+ right.constant.isTrue) {
+ // Replace identical(x, true) by x when x is known to be a boolean.
+ // Note that this is not safe if x is null, because the value might
+ // not be used as a condition. A rule for [IsTrue] handles that case.
+ leftArg.substituteFor(node);
+ } else if (lattice.isDefinitelyBool(right) &&
+ left.isConstant &&
+ left.constant.isTrue) {
+ rightArg.substituteFor(node);
+ } else if (left.isNullConstant || right.isNullConstant) {
+ // Use `==` for comparing against null, so JS undefined and JS null
+ // are considered equal.
+ node.operator = BuiltinOperator.LooseEq;
+ } else if (!left.isNullable || !right.isNullable) {
+ // If at most one operand can be Dart null, we can use `===`.
+ // This is not safe when we might compare JS null and JS undefined.
+ node.operator = BuiltinOperator.StrictEq;
+ } else if (lattice.isDefinitelyNum(left, allowNull: true) &&
+ lattice.isDefinitelyNum(right, allowNull: true)) {
+ // If both operands can be null, but otherwise are of the same type,
+ // we can use `==` for comparison.
+ // This is not safe e.g. for comparing strings against numbers.
+ node.operator = BuiltinOperator.LooseEq;
+ } else if (lattice.isDefinitelyString(left, allowNull: true) &&
+ lattice.isDefinitelyString(right, allowNull: true)) {
+ node.operator = BuiltinOperator.LooseEq;
+ } else if (lattice.isDefinitelyBool(left, allowNull: true) &&
+ lattice.isDefinitelyBool(right, allowNull: true)) {
+ node.operator = BuiltinOperator.LooseEq;
}
break;
@@ -1925,6 +1972,8 @@ class TypePropagationVisitor implements Visitor {
break;
case BuiltinOperator.Identical:
+ case BuiltinOperator.StrictEq:
+ case BuiltinOperator.LooseEq:
AbstractValue leftConst = getValue(node.arguments[0].definition);
AbstractValue rightConst = getValue(node.arguments[1].definition);
ConstantValue leftValue = leftConst.constant;
@@ -1975,9 +2024,7 @@ class TypePropagationVisitor implements Visitor {
case BuiltinOperator.NumLe:
case BuiltinOperator.NumGt:
case BuiltinOperator.NumGe:
- case BuiltinOperator.StrictEq:
case BuiltinOperator.StrictNeq:
- case BuiltinOperator.LooseEq:
case BuiltinOperator.LooseNeq:
case BuiltinOperator.IsFalsy:
case BuiltinOperator.IsNumber:
@@ -2308,6 +2355,7 @@ class AbstractValue {
bool get isConstant => (kind == CONSTANT);
bool get isNonConst => (kind == NONCONST);
bool get isNullConstant => kind == CONSTANT && constant.isNull;
+ bool get isTrueConstant => kind == CONSTANT && constant.isTrue;
bool get isNullable => kind != NOTHING && type.isNullable;
bool get isDefinitelyNotNull => kind == NOTHING || !type.isNullable;
« no previous file with comments | « no previous file | pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698