| Index: sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
 | 
| ===================================================================
 | 
| --- sdk/lib/_internal/compiler/implementation/ssa/nodes.dart	(revision 15954)
 | 
| +++ sdk/lib/_internal/compiler/implementation/ssa/nodes.dart	(working copy)
 | 
| @@ -289,7 +289,7 @@
 | 
|    visitGreaterEqual(HGreaterEqual node) => visitRelational(node);
 | 
|    visitIdentity(HIdentity node) => visitRelational(node);
 | 
|    visitIf(HIf node) => visitConditionalBranch(node);
 | 
| -  visitIndex(HIndex node) => visitInvokeStatic(node);
 | 
| +  visitIndex(HIndex node) => visitInstruction(node);
 | 
|    visitIndexAssign(HIndexAssign node) => visitInvokeStatic(node);
 | 
|    visitIntegerCheck(HIntegerCheck node) => visitCheck(node);
 | 
|    visitInterceptor(HInterceptor node) => visitInstruction(node);
 | 
| @@ -1320,8 +1320,34 @@
 | 
|  class HInvokeDynamicMethod extends HInvokeDynamic {
 | 
|    HInvokeDynamicMethod(Selector selector, List<HInstruction> inputs)
 | 
|      : super(selector, null, inputs);
 | 
| -  toString() => 'invoke dynamic method: $selector';
 | 
| +  String toString() => 'invoke dynamic method: $selector';
 | 
|    accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this);
 | 
| +
 | 
| +  bool isIndexOperatorOnIndexablePrimitive(HTypeMap types) {
 | 
| +    return isInterceptorCall
 | 
| +        && selector.kind == SelectorKind.INDEX
 | 
| +        && inputs[1].isIndexablePrimitive(types);
 | 
| +  }
 | 
| +
 | 
| +  HType computeDesiredTypeForInput(HInstruction input,
 | 
| +                                   HTypeMap types,
 | 
| +                                   Compiler compiler) {
 | 
| +    // TODO(ngeoffray): Move this logic into a different class that
 | 
| +    // will know what type it wants for a given selector.
 | 
| +    if (selector.kind != SelectorKind.INDEX) return HType.UNKNOWN;
 | 
| +    if (!isInterceptorCall) return HType.UNKNOWN;
 | 
| +
 | 
| +    HInstruction index = inputs[2];
 | 
| +    if (input == inputs[1] &&
 | 
| +        (index.isTypeUnknown(types) || index.isNumber(types))) {
 | 
| +      return HType.INDEXABLE_PRIMITIVE;
 | 
| +    }
 | 
| +    // The index should be an int when the receiver is a string or array.
 | 
| +    // However it turns out that inserting an integer check in the optimized
 | 
| +    // version is cheaper than having another bailout case. This is true,
 | 
| +    // because the integer check will simply throw if it fails.
 | 
| +    return HType.UNKNOWN;
 | 
| +  }
 | 
|  }
 | 
|  
 | 
|  abstract class HInvokeDynamicField extends HInvokeDynamic {
 | 
| @@ -2439,42 +2465,21 @@
 | 
|    }
 | 
|  }
 | 
|  
 | 
| -class HIndex extends HInvokeStatic {
 | 
| -  HIndex(HStatic target, HInstruction receiver, HInstruction index)
 | 
| -      : super(<HInstruction>[target, receiver, index]);
 | 
| -  toString() => 'index operator';
 | 
| +class HIndex extends HInstruction {
 | 
| +  HIndex(HInstruction receiver, HInstruction index)
 | 
| +      : super(<HInstruction>[receiver, index]);
 | 
| +  String toString() => 'index operator';
 | 
|    accept(HVisitor visitor) => visitor.visitIndex(this);
 | 
|  
 | 
|    void prepareGvn(HTypeMap types) {
 | 
|      clearAllSideEffects();
 | 
| -    if (isBuiltin(types)) {
 | 
| -      setDependsOnIndexStore();
 | 
| -      setUseGvn();
 | 
| -    } else {
 | 
| -      setAllSideEffects();
 | 
| -    }
 | 
| +    setDependsOnIndexStore();
 | 
| +    setUseGvn();
 | 
|    }
 | 
|  
 | 
| -  HInstruction get receiver => inputs[1];
 | 
| -  HInstruction get index => inputs[2];
 | 
| +  HInstruction get receiver => inputs[0];
 | 
| +  HInstruction get index => inputs[1];
 | 
|  
 | 
| -  HType computeDesiredTypeForNonTargetInput(HInstruction input,
 | 
| -                                            HTypeMap types,
 | 
| -                                            Compiler compiler) {
 | 
| -    if (input == receiver &&
 | 
| -        (index.isTypeUnknown(types) || index.isNumber(types))) {
 | 
| -      return HType.INDEXABLE_PRIMITIVE;
 | 
| -    }
 | 
| -    // The index should be an int when the receiver is a string or array.
 | 
| -    // However it turns out that inserting an integer check in the optimized
 | 
| -    // version is cheaper than having another bailout case. This is true,
 | 
| -    // because the integer check will simply throw if it fails.
 | 
| -    return HType.UNKNOWN;
 | 
| -  }
 | 
| -
 | 
| -  bool isBuiltin(HTypeMap types)
 | 
| -      => receiver.isIndexablePrimitive(types) && index.isInteger(types);
 | 
| -
 | 
|    int typeCode() => HInstruction.INDEX_TYPECODE;
 | 
|    bool typeEquals(HInstruction other) => other is HIndex;
 | 
|    bool dataEquals(HIndex other) => true;
 | 
| 
 |