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

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: Update gvn_test output 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
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/finalize.dart ('k') | pkg/compiler/lib/src/js_backend/codegen/task.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 081f80c998d78192d18bb569ceab4434d4a6d56a..b5a36ec7fa8e05b66034508e0ea1798a2c65e986 100644
--- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart
+++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
@@ -689,6 +689,15 @@ class ConstantPropagationLattice {
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 +1256,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 +1313,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.throwIndexOutOfRangeException,
- <Primitive>[list, index]);
- return cps;
}
/// Create a check that throws if the length of [list] is not equal to
@@ -1364,7 +1364,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 +1380,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 +1433,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.throwIndexOutOfRangeException,
- [list, fail.makeConstant(new IntConstantValue(-1))]);
+ list = makeBoundsCheck(cps, list, cps.makeMinusOne(),
+ BoundsCheck.EMPTINESS);
Primitive removedItem = cps.invokeBuiltin(BuiltinMethod.Pop,
list,
<Primitive>[]);
@@ -1481,7 +1477,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);
@@ -2398,6 +2395,40 @@ 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;
+ 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.lengthUsedInCheck && 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;
+ }
+ }
+
visitNullCheck(NullCheck node) {
if (!getValue(node.value.definition).isNullable) {
node.replaceUsesWith(node.value.definition);
@@ -3194,6 +3225,11 @@ class TypePropagationVisitor implements Visitor {
}
@override
+ void visitBoundsCheck(BoundsCheck node) {
+ setValue(node, getValue(node.object.definition));
+ }
+
+ @override
void visitNullCheck(NullCheck node) {
setValue(node, lattice.nonNullable(getValue(node.value.definition)));
}
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/finalize.dart ('k') | pkg/compiler/lib/src/js_backend/codegen/task.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698