| 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 8a4daba9fcc0099edb0f97a34fe1801d79662306..f558d756a785c5aa8beff40962ed29cb35233c34 100644
|
| --- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart
|
| +++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
|
| @@ -591,6 +591,46 @@ class ConstantPropagationLattice {
|
| return constant(new StringConstantValue(new ast.DartString.literal(value)));
|
| }
|
|
|
| + AbstractConstantValue indexSpecial(AbstractConstantValue left,
|
| + AbstractConstantValue right) {
|
| + if (left.isNothing || right.isNothing) return nothing;
|
| + if (right.isConstant) {
|
| + ConstantValue index = right.constant;
|
| + if (left.isConstant) {
|
| + ConstantValue receiver = left.constant;
|
| + if (receiver is StringConstantValue) {
|
| + if (index is IntConstantValue) {
|
| + String stringValue = receiver.primitiveValue.slowToString();
|
| + int indexValue = index.primitiveValue;
|
| + if (0 <= indexValue && indexValue < stringValue.length) {
|
| + return stringConstant(stringValue[indexValue]);
|
| + } else {
|
| + return nothing; // Will throw.
|
| + }
|
| + }
|
| + } else if (receiver is ListConstantValue) {
|
| + if (index is IntConstantValue) {
|
| + int indexValue = index.primitiveValue;
|
| + if (0 <= indexValue && indexValue < receiver.length) {
|
| + return constant(receiver.entries[indexValue]);
|
| + } else {
|
| + return nothing; // Will throw.
|
| + }
|
| + }
|
| + } else if (receiver is MapConstantValue) {
|
| + ConstantValue result = receiver.lookup(index);
|
| + if (result != null) {
|
| + return constant(result);
|
| + }
|
| + return constant(new NullConstantValue());
|
| + }
|
| + }
|
| + TypeMask type = typeSystem.indexWithConstant(left.type, index);
|
| + if (type != null) return nonConstant(type);
|
| + }
|
| + return null; // The caller will use return type from type inference.
|
| + }
|
| +
|
| AbstractConstantValue stringify(AbstractConstantValue value) {
|
| if (value.isNothing) return nothing;
|
| if (value.isNonConst) return nonConstant(typeSystem.stringType);
|
| @@ -2607,6 +2647,14 @@ class TypePropagationVisitor implements Visitor {
|
| return; // And come back later.
|
| }
|
|
|
| + void finish(AbstractConstantValue result) {
|
| + if (result == null) {
|
| + setResult(node, lattice.getInvokeReturnType(node.selector, node.mask));
|
| + } else {
|
| + setResult(node, result, canReplace: true);
|
| + }
|
| + }
|
| +
|
| if (node.selector.isGetter) {
|
| // Constant fold known length of containers.
|
| if (node.selector == Selectors.length) {
|
| @@ -2615,10 +2663,11 @@ class TypePropagationVisitor implements Visitor {
|
| AbstractConstantValue length = lattice.lengthSpecial(object);
|
| if (length != null) {
|
| setResult(node, length, canReplace: !object.isNullable);
|
| + return;
|
| }
|
| }
|
| }
|
| - setResult(node, lattice.getInvokeReturnType(node.selector, node.mask));
|
| + finish(null);
|
| return;
|
| }
|
|
|
| @@ -2629,16 +2678,20 @@ class TypePropagationVisitor implements Visitor {
|
| AbstractConstantValue right = getValue(node.dartArgument(0));
|
| result = lattice.codeUnitAtSpecial(object, right);
|
| }
|
| - if (result == null) {
|
| - setResult(node, lattice.getInvokeReturnType(node.selector, node.mask));
|
| - } else {
|
| - setResult(node, result, canReplace: true);
|
| - }
|
| + finish(result);
|
| + return;
|
| + }
|
| +
|
| + if (node.selector == Selectors.index) {
|
| + AbstractConstantValue object = getValue(node.dartReceiver);
|
| + AbstractConstantValue right = getValue(node.dartArgument(0));
|
| + AbstractConstantValue result = lattice.indexSpecial(object, right);
|
| + finish(result);
|
| return;
|
| }
|
|
|
| if (!node.selector.isOperator) {
|
| - setResult(node, lattice.getInvokeReturnType(node.selector, node.mask));
|
| + finish(null);
|
| return;
|
| }
|
|
|
| @@ -2660,14 +2713,7 @@ class TypePropagationVisitor implements Visitor {
|
| BinaryOperator operator = BinaryOperator.parse(opname);
|
| result = lattice.binaryOp(operator, left, right);
|
| }
|
| -
|
| - // Update value of the continuation parameter. Again, this is effectively
|
| - // a phi.
|
| - if (result == null) {
|
| - setResult(node, lattice.getInvokeReturnType(node.selector, node.mask));
|
| - } else {
|
| - setResult(node, result, canReplace: true);
|
| - }
|
| + finish(result);
|
| }
|
|
|
| void visitApplyBuiltinOperator(ApplyBuiltinOperator node) {
|
|
|