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

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

Issue 1184963006: dart2js cps: Better 'is int' checks. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Update comment Created 5 years, 6 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
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 615b4c44f0d1e369ca9844b8650da20fe6b9debc..96d5e458999227a3cd8534afa8e0c5401c64fccc 100644
--- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart
+++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
@@ -32,6 +32,7 @@ class TypeMaskSystem {
TypeMask get functionType => inferrer.functionType;
TypeMask get boolType => inferrer.boolType;
TypeMask get intType => inferrer.intType;
+ TypeMask get doubleType => inferrer.doubleType;
TypeMask get numType => inferrer.numType;
TypeMask get stringType => inferrer.stringType;
TypeMask get listType => inferrer.listType;
@@ -105,6 +106,20 @@ class TypeMaskSystem {
return areDisjoint(t, numStringBoolType);
}
+ /// True if all values of [t] are either integers or not numbers at all.
+ ///
+ /// This does not imply that the value is an integer, since most other values
+ /// such as null are also not a non-integer double.
+ bool isDefinitelyNotNonIntegerDouble(TypeMask t) {
+ // Even though int is a subclass of double in the JS type system, we can
+ // still check this with disjointness, because [doubleType] is the *exact*
+ // double class, so this excludes things that are known to be instances of a
+ // more specific class.
+ // We currently exploit that there are no subclasses of double that are
+ // not integers (e.g. there is no UnsignedDouble class or whatever).
+ return areDisjoint(t, doubleType);
+ }
+
bool areDisjoint(TypeMask leftType, TypeMask rightType) {
TypeMask intersection = leftType.intersection(rightType, classWorld);
return intersection.isEmpty && !intersection.isNullable;
@@ -214,6 +229,16 @@ class ConstantPropagationLattice {
typeSystem.isDefinitelyNotNumStringBool(value.type);
}
+ /// True if this value cannot be a non-integer double.
+ ///
+ /// In other words, if true is returned, and the value is a number, then
+ /// it is a whole number and is not NaN, Infinity, or minus Infinity.
+ bool isDefinitelyNotNonIntegerDouble(AbstractValue value) {
+ return value.isNothing ||
+ value.isConstant && !value.constant.isDouble ||
+ typeSystem.isDefinitelyNotNonIntegerDouble(value.type);
+ }
+
/// Returns whether the given [value] is an instance of [type].
///
/// Since [value] and [type] are not always known, [AbstractBool.Maybe] is
@@ -400,6 +425,7 @@ class TransformingVisitor extends RecursiveVisitor {
final ConstantPropagationLattice lattice;
TypeMaskSystem get typeSystem => lattice.typeSystem;
+ types.DartTypes get dartTypes => lattice.dartTypes;
final dart2js.InternalErrorFunction internalError;
@@ -670,6 +696,31 @@ class TransformingVisitor extends RecursiveVisitor {
}
}
+ Primitive visitTypeTest(TypeTest node) {
+ Primitive prim = node.value.definition;
+ AbstractValue value = getValue(prim);
+ if (node.type == 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.
+ return new ApplyBuiltinOperator(
+ BuiltinOperator.IsFloor,
+ <Primitive>[prim, prim]);
+ }
+ 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]);
+ }
+ return new ApplyBuiltinOperator(
+ BuiltinOperator.IsNumberAndFloor,
+ <Primitive>[prim, prim, prim]);
+ }
+ return null;
+ }
+
void visitLetPrim(LetPrim node) {
AbstractValue value = getValue(node.primitive);
if (node.primitive is! Constant && value.isConstant) {
@@ -678,8 +729,15 @@ class TransformingVisitor extends RecursiveVisitor {
newPrim.substituteFor(node.primitive);
RemovalVisitor.remove(node.primitive);
node.primitive = newPrim;
+ } else {
+ Primitive newPrim = visit(node.primitive);
+ if (newPrim != null) {
+ newPrim.substituteFor(node.primitive);
+ RemovalVisitor.remove(node.primitive);
+ node.primitive = newPrim;
+ }
}
- super.visitLetPrim(node);
+ visit(node.body);
}
}
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/builtin_operator.dart ('k') | pkg/compiler/lib/src/js_backend/codegen/codegen.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698