Chromium Code Reviews| 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 631aaf2d4529da1be85c90e0c82c7f331c10e84e..506e07bef15206b09183fca4bd30123079bf16ca 100644 |
| --- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart |
| +++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart |
| @@ -112,6 +112,13 @@ class ConstantPropagationLattice { |
| typeSystem.isDefinitelyNotNonIntegerDouble(value.type); |
| } |
| + bool isDefinitelyUInt32(AbstractValue value, |
| + {bool allowNull: false}) { |
| + return value.isNothing || |
| + typeSystem.isDefinitelyUInt32(value.type, allowNull: allowNull); |
| + } |
| + |
| + |
| bool isDefinitelyInt(AbstractValue value, |
| {bool allowNull: false}) { |
| return value.isNothing || |
| @@ -145,11 +152,6 @@ class ConstantPropagationLattice { |
| allowNull: allowNull); |
| } |
| - bool isDefinitelyIndexable(AbstractValue value, {bool allowNull: false}) { |
| - return value.isNothing || |
| - typeSystem.isDefinitelyIndexable(value.type, allowNull: allowNull); |
| - } |
| - |
| /// Returns whether the given [value] is an instance of [type]. |
| /// |
| /// Since [value] and [type] are not always known, [AbstractBool.Maybe] is |
| @@ -252,6 +254,16 @@ class ConstantPropagationLattice { |
| } |
| return null; |
| + case BinaryOperatorKind.SHL: |
| + case BinaryOperatorKind.SHR: |
| + case BinaryOperatorKind.AND: |
| + case BinaryOperatorKind.OR: |
| + case BinaryOperatorKind.XOR: |
| + if (isDefinitelyNum(left) && isDefinitelyNum(right)) { |
| + return nonConstant(typeSystem.uint32Type); |
| + } |
| + return null; |
| + |
| case BinaryOperatorKind.EQ: |
| bool behavesLikeIdentity = |
| isDefinitelyNumStringBool(left, allowNull: true) || |
| @@ -890,37 +902,16 @@ class TransformingVisitor extends LeafVisitor { |
| return cps; |
| } |
| - /// Counts number of index accesses on [receiver] and determines based on |
| - /// that number if we should try to inline them. |
| - /// |
| - /// This is a short-term solution to avoid inserting a lot of bounds checks, |
| - /// since there is currently no optimization for eliminating them. |
| - bool hasTooManyIndexAccesses(Primitive receiver) { |
| - receiver = receiver.effectiveDefinition; |
| - int count = 0; |
| - for (Reference ref in receiver.effectiveUses) { |
| - Node use = ref.parent; |
| - if (use is InvokeMethod && |
| - (use.selector.isIndex || use.selector.isIndexSet) && |
| - getDartReceiver(use).sameValue(receiver)) { |
| - ++count; |
| - } else if (use is GetIndex && use.object.definition.sameValue(receiver)) { |
| - ++count; |
| - } else if (use is SetIndex && use.object.definition.sameValue(receiver)) { |
| - ++count; |
| - } |
| - if (count > 2) return true; |
| - } |
| - return false; |
| - } |
| - |
| /// Tries to replace [node] with a direct `length` or index access. |
| /// |
| /// Returns `true` if the node was replaced. |
| bool specializeIndexableAccess(InvokeMethod node) { |
| Primitive receiver = getDartReceiver(node); |
| AbstractValue receiverValue = getValue(receiver); |
| - if (!lattice.isDefinitelyIndexable(receiverValue)) return false; |
| + if (!typeSystem.isDefinitelyIndexable(receiverValue.type, |
| + allowNull: true)) { |
| + return false; |
| + } |
| SourceInformation sourceInfo = node.sourceInformation; |
| Continuation cont = node.continuation.definition; |
| switch (node.selector.name) { |
| @@ -933,7 +924,7 @@ class TransformingVisitor extends LeafVisitor { |
| return true; |
| case '[]': |
| - if (hasTooManyIndexAccesses(receiver)) return false; |
| + if (receiverValue.isNullable) return false; |
|
sra1
2015/09/30 21:54:20
Since a.length and a[i] throw when a==null, do we
asgerf
2015/10/01 09:49:34
I guess not. Removed.
|
| Primitive index = getDartArgument(node, 0); |
| if (!lattice.isDefinitelyInt(getValue(index))) return false; |
| CpsFragment cps = makeBoundsCheck(receiver, index, sourceInfo); |
| @@ -943,6 +934,23 @@ class TransformingVisitor extends LeafVisitor { |
| push(cps.result); |
| return true; |
| + case '[]=': |
| + if (receiverValue.isNullable) return false; |
| + if (!typeSystem.isDefinitelyMutableIndexable(receiverValue.type)) { |
| + return false; |
| + } |
| + Primitive index = getDartArgument(node, 0); |
| + Primitive value = getDartArgument(node, 1); |
| + if (!lattice.isDefinitelyInt(getValue(index))) return false; |
| + CpsFragment cps = makeBoundsCheck(receiver, index, sourceInfo); |
| + cps.letPrim(new SetIndex(receiver, index, value)); |
| + assert(cont.parameters.single.hasNoUses); |
| + cont.parameters.clear(); |
| + cps.invokeContinuation(cont, []); |
| + replaceSubtree(node, cps.result); |
| + push(cps.result); |
| + return true; |
| + |
| default: |
| return false; |
| } |
| @@ -1041,7 +1049,6 @@ class TransformingVisitor extends LeafVisitor { |
| return false; |
| } |
| if (listValue.isNullable) return false; |
| - if (hasTooManyIndexAccesses(list)) return false; |
| Primitive index = getDartArgument(node, 0); |
| if (!lattice.isDefinitelyInt(getValue(index))) return false; |
| CpsFragment cps = makeBoundsCheck(list, index, sourceInfo); |
| @@ -1051,22 +1058,6 @@ class TransformingVisitor extends LeafVisitor { |
| push(cps.result); |
| return true; |
| - case '[]=': |
| - if (listValue.isNullable) return false; |
| - if (hasTooManyIndexAccesses(list)) return false; |
| - Primitive index = getDartArgument(node, 0); |
| - Primitive value = getDartArgument(node, 1); |
| - if (!isMutable) return false; |
| - if (!lattice.isDefinitelyInt(getValue(index))) return false; |
| - CpsFragment cps = makeBoundsCheck(list, index, sourceInfo); |
| - cps.letPrim(new SetIndex(list, index, value)); |
| - assert(cont.parameters.single.hasNoUses); |
| - cont.parameters.clear(); |
| - cps.invokeContinuation(cont, []); |
| - replaceSubtree(node, cps.result); |
| - push(cps.result); |
| - return true; |
| - |
| case 'forEach': |
| Element element = |
| compiler.world.locateSingleElement(node.selector, listValue.type); |