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

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

Issue 1512303002: dart2js cps: Add instruction for bounds checks. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years 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 f716f05e023f7479bd72b9f731accc4b9f2a9dcb..1a1929e310c4997e31f5c838f2c5d4dae808f0c3 100644
--- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart
+++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
@@ -683,6 +683,21 @@ class ConstantPropagationLattice {
if (constantValue != null) return constant(constantValue, mask);
return nonConstant(mask);
}
+
+ AbstractConstantValue nonNullable(AbstractConstantValue value) {
+ if (value.isNullConstant) return nothing;
+ if (!value.isNullable) return value;
+ return nonConstant(value.type.nonNullable());
+ }
+
+ /// If [value] is an integer constant, returns its value, otherwise `null`.
+ int intValue(AbstractConstantValue value) {
+ if (value.isConstant && value.constant.isInt) {
+ PrimitiveConstantValue constant = value.constant;
+ return constant.primitiveValue;
+ }
+ return null;
+ }
}
/**
@@ -1247,7 +1262,8 @@ class TransformingVisitor extends DeepRecursiveVisitor {
if (lattice.isDefinitelyString(receiverValue) &&
lattice.isDefinitelyInt(getValue(index))) {
SourceInformation sourceInfo = node.sourceInformation;
- CpsFragment cps = makeBoundsCheck(receiver, index, sourceInfo);
+ CpsFragment cps = new CpsFragment(node.sourceInformation);
+ receiver = makeBoundsCheck(cps, receiver, index);
ApplyBuiltinOperator get =
cps.applyBuiltin(BuiltinOperator.CharCodeAt,
<Primitive>[receiver, index]);
@@ -1303,28 +1319,18 @@ class TransformingVisitor extends DeepRecursiveVisitor {
///
/// Returns a CPS fragment whose context is the branch where no error
/// was thrown.
- CpsFragment makeBoundsCheck(Primitive list,
- Primitive index,
- SourceInformation sourceInfo) {
- CpsFragment cps = new CpsFragment(sourceInfo);
+ Primitive makeBoundsCheck(CpsFragment cps,
+ Primitive list,
+ Primitive index,
+ [int checkKind = BoundsCheck.BOTH_BOUNDS]) {
if (compiler.trustPrimitives) {
- return cps;
+ return cps.letPrim(new BoundsCheck.noCheck(list, cps.sourceInformation));
+ } else {
+ GetLength length = cps.letPrim(new GetLength(list));
+ list = cps.refine(list, typeSystem.nonNullType);
+ return cps.letPrim(new BoundsCheck(list, index, length, checkKind,
+ cps.sourceInformation));
}
- Continuation fail = cps.letCont();
- if (!typeSystem.isDefinitelyNonNegativeInt(index.type)) {
- Primitive isTooSmall = cps.applyBuiltin(
- BuiltinOperator.NumLt,
- <Primitive>[index, cps.makeZero()]);
- cps.ifTruthy(isTooSmall).invokeContinuation(fail);
- }
- Primitive isTooLarge = cps.applyBuiltin(
- BuiltinOperator.NumGe,
- <Primitive>[index, cps.letPrim(new GetLength(list))]);
- cps.ifTruthy(isTooLarge).invokeContinuation(fail);
- cps.insideContinuation(fail).invokeStaticThrower(
- helpers.throwIndexOutOfBoundsError,
- <Primitive>[list, index]);
- return cps;
}
/// Create a check that throws if the length of [list] is not equal to
@@ -1364,7 +1370,8 @@ class TransformingVisitor extends DeepRecursiveVisitor {
case '[]':
Primitive index = node.dartArgument(0);
if (!lattice.isDefinitelyInt(getValue(index))) return null;
- CpsFragment cps = makeBoundsCheck(receiver, index, sourceInfo);
+ CpsFragment cps = new CpsFragment(node.sourceInformation);
+ receiver = makeBoundsCheck(cps, receiver, index);
GetIndex get = cps.letPrim(new GetIndex(receiver, index));
node.replaceUsesWith(get);
// TODO(asgerf): Make replaceUsesWith set the hint?
@@ -1379,7 +1386,8 @@ class TransformingVisitor extends DeepRecursiveVisitor {
Primitive index = node.dartArgument(0);
Primitive value = node.dartArgument(1);
if (!lattice.isDefinitelyInt(getValue(index))) return null;
- CpsFragment cps = makeBoundsCheck(receiver, index, sourceInfo);
+ CpsFragment cps = new CpsFragment(node.sourceInformation);
+ receiver = makeBoundsCheck(cps, receiver, index);
cps.letPrim(new SetIndex(receiver, index, value));
assert(node.hasNoUses);
return cps;
@@ -1431,14 +1439,8 @@ class TransformingVisitor extends DeepRecursiveVisitor {
}
if (!isExtendable) return null;
CpsFragment cps = new CpsFragment(sourceInfo);
- Primitive length = cps.letPrim(new GetLength(list));
- Primitive isEmpty = cps.applyBuiltin(
- BuiltinOperator.StrictEq,
- [length, cps.makeZero()]);
- CpsFragment fail = cps.ifTruthy(isEmpty);
- fail.invokeStaticThrower(
- helpers.throwIndexOutOfBoundsError,
- [list, fail.makeConstant(new IntConstantValue(-1))]);
+ list = makeBoundsCheck(cps, list, cps.makeMinusOne(),
+ BoundsCheck.EMPTINESS);
Primitive removedItem = cps.invokeBuiltin(BuiltinMethod.Pop,
list,
<Primitive>[]);
@@ -1481,7 +1483,8 @@ class TransformingVisitor extends DeepRecursiveVisitor {
if (listValue.isNullable) return null;
Primitive index = node.dartArgument(0);
if (!lattice.isDefinitelyInt(getValue(index))) return null;
- CpsFragment cps = makeBoundsCheck(list, index, sourceInfo);
+ CpsFragment cps = new CpsFragment(node.sourceInformation);
+ list = makeBoundsCheck(cps, list, index);
GetIndex get = cps.letPrim(new GetIndex(list, index));
get.hint = node.hint;
node.replaceUsesWith(get);
@@ -2397,6 +2400,41 @@ class TransformingVisitor extends DeepRecursiveVisitor {
}
return true;
}
+
+ visitBoundsCheck(BoundsCheck node) {
+ // Eliminate bounds checks using constant folding.
+ // The [BoundsChecker] pass does not try to eliminate checks that could be
+ // eliminated by constant folding.
+ if (node.hasNoChecks) return null;
+ int index = lattice.intValue(getValue(node.index.definition));
+ int length = node.length == null
+ ? null
+ : lattice.intValue(getValue(node.length.definition));
+ if (index != null && length != null && index < length) {
+ node.checks &= ~BoundsCheck.UPPER_BOUND;
+ }
+ if (index != null && index >= 0) {
+ node.checks &= ~BoundsCheck.LOWER_BOUND;
+ }
+ if (length != null && length > 0) {
+ node.checks &= ~BoundsCheck.EMPTINESS;
+ }
+ if (!node.checkNeedsLength && node.length != null) {
+ node..length.unlink()..length = null;
+ }
+ if (node.checks == BoundsCheck.NONE) {
+ // We can't remove the bounds check node because it may still be used to
+ // restrict code motion. But the index is no longer needed.
+ // TODO(asgerf): Since this was eliminated by constant folding, it should
+ // be safe to remove because any path-sensitive information we relied
+ // upon to do this are expressed by other refinement nodes that also
+ // restrict code motion. However, if we want to run this pass after
+ // [BoundsChecker] that would not be safe any more, so for now we
+ // keep the node for forward compatibilty.
+ node..index.unlink()..index = null;
+ }
+ return null;
+ }
}
/**
@@ -3184,6 +3222,11 @@ class TypePropagationVisitor implements Visitor {
nonConstant(value.type.intersection(node.refineType, classWorld)));
}
}
+
+ @override
+ void visitBoundsCheck(BoundsCheck node) {
+ setValue(node, getValue(node.object.definition));
+ }
}
/// Represents the abstract value of a primitive value at some point in the

Powered by Google App Engine
This is Rietveld 408576698