[vm/bytecode] Replace InstanceCall instruction with InterfaceCall and DynamicCall.

Dispatch interface calls via hashtable rather than inline cache.
InterfaceCall doesn't need to take arguments descriptor into account
when doing method lookup.

Change-Id: I30eae6ea638d1d2ad2cf3ff073c653fee3377f31
Reviewed-on: https://dart-review.googlesource.com/c/86106
Reviewed-by: Zach Anderson <zra@google.com>
Commit-Queue: Régis Crelier <regis@google.com>
diff --git a/pkg/vm/lib/bytecode/assembler.dart b/pkg/vm/lib/bytecode/assembler.dart
index f937116..eaab503 100644
--- a/pkg/vm/lib/bytecode/assembler.dart
+++ b/pkg/vm/lib/bytecode/assembler.dart
@@ -271,9 +271,14 @@
     emitWord(_encodeAD(Opcode.kIndirectStaticCall, ra, rd));
   }
 
-  void emitInstanceCall(int ra, int rd) {
+  void emitInterfaceCall(int ra, int rd) {
     emitSourcePosition();
-    emitWord(_encodeAD(Opcode.kInstanceCall, ra, rd));
+    emitWord(_encodeAD(Opcode.kInterfaceCall, ra, rd));
+  }
+
+  void emitDynamicCall(int ra, int rd) {
+    emitSourcePosition();
+    emitWord(_encodeAD(Opcode.kDynamicCall, ra, rd));
   }
 
   void emitNativeCall(int rd) {
diff --git a/pkg/vm/lib/bytecode/constant_pool.dart b/pkg/vm/lib/bytecode/constant_pool.dart
index fda38ee..e4c77c1 100644
--- a/pkg/vm/lib/bytecode/constant_pool.dart
+++ b/pkg/vm/lib/bytecode/constant_pool.dart
@@ -169,6 +169,15 @@
   PackedObject name;
 }
 
+// Occupies 2 entries in the constant pool.
+type ConstantInterfaceCall extends ConstantPoolEntry {
+  Byte tag = 26;
+  Byte flags(invocationKindBit0, invocationKindBit1);
+             // Where invocationKind is index into InvocationKind.
+  PackedObject targetName;
+  ConstantIndex argDesc;
+}
+
 */
 
 enum ConstantTag {
@@ -198,6 +207,7 @@
   kPartialTearOffInstantiation,
   kEmptyTypeArguments,
   kSymbol,
+  kInterfaceCall,
 }
 
 abstract class ConstantPoolEntry {
@@ -271,6 +281,8 @@
         return new ConstantEmptyTypeArguments.read(reader);
       case ConstantTag.kSymbol:
         return new ConstantSymbol.read(reader);
+      case ConstantTag.kInterfaceCall:
+        return new ConstantInterfaceCall.read(reader);
     }
     throw 'Unexpected constant tag $tag';
   }
@@ -1071,6 +1083,50 @@
   bool operator ==(other) => other is ConstantSymbol && this.name == other.name;
 }
 
+class ConstantInterfaceCall extends ConstantPoolEntry {
+  final InvocationKind invocationKind;
+  final ObjectHandle targetName;
+  final int argDescConstantIndex;
+
+  ConstantInterfaceCall(
+      this.invocationKind, this.targetName, this.argDescConstantIndex);
+
+  // Reserve 1 extra slot for arguments descriptor, following target name slot.
+  int get numReservedEntries => 1;
+
+  @override
+  ConstantTag get tag => ConstantTag.kInterfaceCall;
+
+  @override
+  void writeValue(BufferedWriter writer) {
+    writer.writeByte(invocationKind.index);
+    writer.writePackedObject(targetName);
+    writer.writePackedUInt30(argDescConstantIndex);
+  }
+
+  ConstantInterfaceCall.read(BufferedReader reader)
+      : invocationKind = InvocationKind.values[reader.readByte()],
+        targetName = reader.readPackedObject(),
+        argDescConstantIndex = reader.readPackedUInt30();
+
+  @override
+  String toString() => 'InterfaceCall '
+      '${_invocationKindToString(invocationKind)}'
+      'target-name \'$targetName\', arg-desc CP#$argDescConstantIndex';
+
+  @override
+  int get hashCode => _combineHashes(
+      _combineHashes(invocationKind.index, targetName.hashCode),
+      argDescConstantIndex);
+
+  @override
+  bool operator ==(other) =>
+      other is ConstantInterfaceCall &&
+      this.invocationKind == other.invocationKind &&
+      this.targetName == other.targetName &&
+      this.argDescConstantIndex == other.argDescConstantIndex;
+}
+
 /// Reserved constant pool entry.
 class _ReservedConstantPoolEntry extends ConstantPoolEntry {
   const _ReservedConstantPoolEntry();
@@ -1131,6 +1187,23 @@
               isSetter: invocationKind == InvocationKind.setter),
           argDescCpIndex));
 
+  int addInterfaceCall(
+          InvocationKind invocationKind, Name targetName, int argDescCpIndex) =>
+      _add(new ConstantInterfaceCall(
+          invocationKind,
+          objectTable.getSelectorNameHandle(targetName,
+              isGetter: invocationKind == InvocationKind.getter,
+              isSetter: invocationKind == InvocationKind.setter),
+          argDescCpIndex));
+
+  int addInstanceCall(
+          InvocationKind invocationKind, Name targetName, int argDescCpIndex,
+          {bool isDynamic: false}) =>
+      isDynamic
+          ? addICData(invocationKind, targetName, argDescCpIndex,
+              isDynamic: true)
+          : addInterfaceCall(invocationKind, targetName, argDescCpIndex);
+
   int addStaticField(Field field) =>
       _add(new ConstantStaticField(objectTable.getHandle(field)));
 
diff --git a/pkg/vm/lib/bytecode/dbc.dart b/pkg/vm/lib/bytecode/dbc.dart
index 1092e14..6f7923a 100644
--- a/pkg/vm/lib/bytecode/dbc.dart
+++ b/pkg/vm/lib/bytecode/dbc.dart
@@ -82,7 +82,8 @@
 
   // Calls.
   kIndirectStaticCall,
-  kInstanceCall,
+  kInterfaceCall,
+  kDynamicCall,
   kNativeCall,
   kReturnTOS,
 
@@ -235,7 +236,9 @@
       Encoding.kT, const [Operand.tgt, Operand.none, Operand.none]),
   Opcode.kIndirectStaticCall: const Format(
       Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]),
-  Opcode.kInstanceCall: const Format(
+  Opcode.kInterfaceCall: const Format(
+      Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]),
+  Opcode.kDynamicCall: const Format(
       Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]),
   Opcode.kNativeCall: const Format(
       Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
@@ -312,7 +315,8 @@
 bool isCall(Opcode opcode) {
   switch (opcode) {
     case Opcode.kIndirectStaticCall:
-    case Opcode.kInstanceCall:
+    case Opcode.kInterfaceCall:
+    case Opcode.kDynamicCall:
     case Opcode.kNativeCall:
       return true;
     default:
diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart
index 6dd7960..7bd5dc3 100644
--- a/pkg/vm/lib/bytecode/gen_bytecode.dart
+++ b/pkg/vm/lib/bytecode/gen_bytecode.dart
@@ -772,9 +772,9 @@
       assert(type.classNode.typeParameters.isEmpty);
       asm.emitPushConstant(cp.addType(type));
       final argDescIndex = cp.addArgDesc(2);
-      final icdataIndex = cp.addICData(
+      final icdataIndex = cp.addInterfaceCall(
           InvocationKind.method, objectSimpleInstanceOf.name, argDescIndex);
-      asm.emitInstanceCall(2, icdataIndex);
+      asm.emitInterfaceCall(2, icdataIndex);
       return;
     }
 
@@ -786,9 +786,9 @@
     }
     asm.emitPushConstant(cp.addType(type));
     final argDescIndex = cp.addArgDesc(4);
-    final icdataIndex = cp.addICData(
+    final icdataIndex = cp.addInterfaceCall(
         InvocationKind.method, objectInstanceOf.name, argDescIndex);
-    asm.emitInstanceCall(4, icdataIndex);
+    asm.emitInterfaceCall(4, icdataIndex);
   }
 
   void start(Member node) {
@@ -1945,6 +1945,14 @@
     asm.emitBytecode0(opcode);
   }
 
+  void _genInstanceCall(int totalArgCount, int icdataCpIndex, bool isDynamic) {
+    if (isDynamic) {
+      asm.emitDynamicCall(totalArgCount, icdataCpIndex);
+    } else {
+      asm.emitInterfaceCall(totalArgCount, icdataCpIndex);
+    }
+  }
+
   @override
   visitMethodInvocation(MethodInvocation node) {
     final Opcode opcode = recognizedMethods.specializedBytecodeFor(node);
@@ -1953,26 +1961,28 @@
       return;
     }
     final args = node.arguments;
+    final isDynamic = node.interfaceTarget == null;
     _genArguments(node.receiver, args);
     final argDescIndex = cp.addArgDescByArguments(args, hasReceiver: true);
-    final icdataIndex = cp.addICData(
+    final icdataIndex = cp.addInstanceCall(
         InvocationKind.method, node.name, argDescIndex,
-        isDynamic: node.interfaceTarget == null);
+        isDynamic: isDynamic);
     final totalArgCount = args.positional.length +
         args.named.length +
         1 /* receiver */ +
         (args.types.isNotEmpty ? 1 : 0) /* type arguments */;
-    asm.emitInstanceCall(totalArgCount, icdataIndex);
+    _genInstanceCall(totalArgCount, icdataIndex, isDynamic);
   }
 
   @override
   visitPropertyGet(PropertyGet node) {
     _generateNode(node.receiver);
+    final isDynamic = node.interfaceTarget == null;
     final argDescIndex = cp.addArgDesc(1);
-    final icdataIndex = cp.addICData(
+    final icdataIndex = cp.addInstanceCall(
         InvocationKind.getter, node.name, argDescIndex,
-        isDynamic: node.interfaceTarget == null);
-    asm.emitInstanceCall(1, icdataIndex);
+        isDynamic: isDynamic);
+    _genInstanceCall(1, icdataIndex, isDynamic);
   }
 
   @override
@@ -1987,11 +1997,12 @@
       asm.emitStoreLocal(temp);
     }
 
+    final isDynamic = node.interfaceTarget == null;
     final argDescIndex = cp.addArgDesc(2);
-    final icdataIndex = cp.addICData(
+    final icdataIndex = cp.addInstanceCall(
         InvocationKind.setter, node.name, argDescIndex,
-        isDynamic: node.interfaceTarget == null);
-    asm.emitInstanceCall(2, icdataIndex);
+        isDynamic: isDynamic);
+    _genInstanceCall(2, icdataIndex, isDynamic);
     asm.emitDrop1();
 
     if (hasResult) {
@@ -2402,9 +2413,11 @@
     const kMoveNext = 'moveNext'; // Iterator.moveNext
     const kCurrent = 'current'; // Iterator.current
 
-    asm.emitInstanceCall(
+    // Front-end inserts implicit cast (type check) which ensures that
+    // result of iterable expression is Iterable<dynamic>.
+    asm.emitInterfaceCall(
         1,
-        cp.addICData(
+        cp.addInterfaceCall(
             InvocationKind.getter, new Name(kIterator), cp.addArgDesc(1)));
 
     final iteratorTemp = locals.tempIndexInFrame(node);
@@ -2436,9 +2449,9 @@
       asm.emitPush(iteratorTemp);
     }
 
-    asm.emitInstanceCall(
+    asm.emitInterfaceCall(
         1,
-        cp.addICData(
+        cp.addInterfaceCall(
             InvocationKind.method, new Name(kMoveNext), cp.addArgDesc(1)));
     _genJumpIfFalse(/* negated = */ false, done);
 
@@ -2447,9 +2460,9 @@
     _genPushContextIfCaptured(node.variable);
 
     asm.emitPush(iteratorTemp);
-    asm.emitInstanceCall(
+    asm.emitInterfaceCall(
         1,
-        cp.addICData(
+        cp.addInterfaceCall(
             InvocationKind.getter, new Name(kCurrent), cp.addArgDesc(1)));
 
     _genStoreVar(node.variable);
@@ -2606,9 +2619,9 @@
         for (var expr in switchCase.expressions) {
           asm.emitPush(temp);
           _genPushConstExpr(expr);
-          asm.emitInstanceCall(
+          asm.emitInterfaceCall(
               2,
-              cp.addICData(
+              cp.addInterfaceCall(
                   InvocationKind.method, new Name('=='), equalsArgDesc));
           _genJumpIfTrue(/* negated = */ false, caseLabel);
         }
diff --git a/pkg/vm/testcases/bytecode/asserts.dart.expect b/pkg/vm/testcases/bytecode/asserts.dart.expect
index a7706b7..575ae5f 100644
--- a/pkg/vm/testcases/bytecode/asserts.dart.expect
+++ b/pkg/vm/testcases/bytecode/asserts.dart.expect
@@ -33,13 +33,13 @@
   CheckStack           0
   JumpIfNoAsserts      L1
   Push                 FP[-6]
-  InstanceCall         1, CP#1
+  DynamicCall          1, CP#1
   AssertBoolean        0
   JumpIfTrue           L1
   PushInt              0
   PushInt              0
   Push                 FP[-5]
-  InstanceCall         1, CP#2
+  DynamicCall          1, CP#2
   PushConstant         CP#4
   IndirectStaticCall   3, CP#3
   Drop1
diff --git a/pkg/vm/testcases/bytecode/async.dart.expect b/pkg/vm/testcases/bytecode/async.dart.expect
index db9690f..dc84539 100644
--- a/pkg/vm/testcases/bytecode/async.dart.expect
+++ b/pkg/vm/testcases/bytecode/async.dart.expect
@@ -7,20 +7,20 @@
 Bytecode {
   Entry                3
   CheckStack           0
-  Allocate             CP#19
+  Allocate             CP#20
   StoreLocal           r2
   Push                 r2
   PushNull
-  StoreFieldTOS        CP#20
+  StoreFieldTOS        CP#21
   Push                 r2
   PushNull
-  StoreFieldTOS        CP#22
+  StoreFieldTOS        CP#23
   Push                 r2
-  PushConstant         CP#24
-  StoreFieldTOS        CP#25
+  PushConstant         CP#25
+  StoreFieldTOS        CP#26
   Push                 r2
   PushConstant         CP#0
-  StoreFieldTOS        CP#27
+  StoreFieldTOS        CP#28
   Push                 r2
   Push                 r0
   StoreFieldTOS        CP#1
@@ -44,25 +44,27 @@
   [14] = StaticICData target 'dart:async::_completeOnAsyncReturn', arg-desc CP#13
   [15] = Type dynamic
   [16] = ArgDesc num-args 3, num-type-args 0, names []
-  [17] = ICData target-name 'completeError', arg-desc CP#16
-  [18] = EndClosureFunctionScope
-  [19] = Class dart:core::_Closure
-  [20] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
-  [21] = Reserved
-  [22] = InstanceField dart:core::_Closure::_function_type_arguments (field)
-  [23] = Reserved
-  [24] = EmptyTypeArguments
-  [25] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [26] = Reserved
-  [27] = InstanceField dart:core::_Closure::_function (field)
-  [28] = Reserved
-  [29] = StaticICData target 'dart:async::_asyncStackTraceHelper', arg-desc CP#7
-  [30] = StaticICData target 'dart:async::_asyncThenWrapperHelper', arg-desc CP#7
-  [31] = StaticICData target 'dart:async::_asyncErrorWrapperHelper', arg-desc CP#7
-  [32] = TypeArgumentsForInstanceAllocation dart:async::Future [dynamic]
-  [33] = StaticICData target 'dart:async::Future::microtask (constructor)', arg-desc CP#13
-  [34] = ICData get target-name 'get:future', arg-desc CP#7
-  [35] = EndClosureFunctionScope
+  [17] = InterfaceCall target-name 'completeError', arg-desc CP#16
+  [18] = Reserved
+  [19] = EndClosureFunctionScope
+  [20] = Class dart:core::_Closure
+  [21] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+  [22] = Reserved
+  [23] = InstanceField dart:core::_Closure::_function_type_arguments (field)
+  [24] = Reserved
+  [25] = EmptyTypeArguments
+  [26] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
+  [27] = Reserved
+  [28] = InstanceField dart:core::_Closure::_function (field)
+  [29] = Reserved
+  [30] = StaticICData target 'dart:async::_asyncStackTraceHelper', arg-desc CP#7
+  [31] = StaticICData target 'dart:async::_asyncThenWrapperHelper', arg-desc CP#7
+  [32] = StaticICData target 'dart:async::_asyncErrorWrapperHelper', arg-desc CP#7
+  [33] = TypeArgumentsForInstanceAllocation dart:async::Future [dynamic]
+  [34] = StaticICData target 'dart:async::Future::microtask (constructor)', arg-desc CP#13
+  [35] = InterfaceCall get target-name 'get:future', arg-desc CP#7
+  [36] = Reserved
+  [37] = EndClosureFunctionScope
 }
 Closure #lib::asyncInFieldInitializer (field)::<anonymous closure> (dart:async::Future < dart:core::int > x) -> dart:async::Future < dart:core::Null >
 ClosureBytecode {
@@ -109,50 +111,50 @@
   PushNull
   StoreContextVar      0, 7
   Push                 r0
-  Allocate             CP#19
+  Allocate             CP#20
   StoreLocal           r3
   Push                 r3
   PushNull
-  StoreFieldTOS        CP#20
+  StoreFieldTOS        CP#21
   Push                 r3
   PushNull
-  StoreFieldTOS        CP#22
+  StoreFieldTOS        CP#23
   Push                 r3
-  PushConstant         CP#24
-  StoreFieldTOS        CP#25
+  PushConstant         CP#25
+  StoreFieldTOS        CP#26
   Push                 r3
   PushConstant         CP#9
-  StoreFieldTOS        CP#27
+  StoreFieldTOS        CP#28
   Push                 r3
   Push                 r0
   StoreFieldTOS        CP#1
   StoreContextVar      0, 8
   Push                 r0
   LoadContextVar       0, 8
-  PushConstant         CP#29
+  PushConstant         CP#30
   IndirectStaticCall   1, CP#7
   PopLocal             r2
   Push                 r0
   Push                 r0
   LoadContextVar       0, 8
-  PushConstant         CP#30
+  PushConstant         CP#31
   IndirectStaticCall   1, CP#7
   StoreContextVar      0, 3
   Push                 r0
   Push                 r0
   LoadContextVar       0, 8
-  PushConstant         CP#31
+  PushConstant         CP#32
   IndirectStaticCall   1, CP#7
   StoreContextVar      0, 4
-  PushConstant         CP#32
+  PushConstant         CP#33
   Push                 r0
   LoadContextVar       0, 8
-  PushConstant         CP#33
+  PushConstant         CP#34
   IndirectStaticCall   2, CP#13
   Drop1
   Push                 r0
   LoadContextVar       0, 1
-  InstanceCall         1, CP#34
+  InterfaceCall        1, CP#35
   ReturnTOS
 
 }
@@ -233,7 +235,7 @@
   LoadContextVar       0, 1
   Push                 r8
   Push                 r9
-  InstanceCall         3, CP#17
+  InterfaceCall        3, CP#17
   Drop1
   Jump                 L3
 L3:
@@ -300,44 +302,44 @@
   Push                 r0
   PushNull
   StoreContextVar      0, 3
-  Allocate             CP#13
+  Allocate             CP#14
   StoreLocal           r6
   Push                 r6
   PushNull
-  StoreFieldTOS        CP#14
+  StoreFieldTOS        CP#15
   Push                 r6
   PushNull
-  StoreFieldTOS        CP#16
+  StoreFieldTOS        CP#17
   Push                 r6
-  PushConstant         CP#18
-  StoreFieldTOS        CP#19
+  PushConstant         CP#19
+  StoreFieldTOS        CP#20
   Push                 r6
   PushConstant         CP#3
-  StoreFieldTOS        CP#21
+  StoreFieldTOS        CP#22
   Push                 r6
   Push                 r0
   StoreFieldTOS        CP#5
   PopLocal             r5
   Push                 r5
-  PushConstant         CP#23
+  PushConstant         CP#24
   IndirectStaticCall   1, CP#1
   PopLocal             r2
   Push                 r5
-  PushConstant         CP#24
+  PushConstant         CP#25
   IndirectStaticCall   1, CP#1
   PopLocal             r3
   Push                 r5
-  PushConstant         CP#25
+  PushConstant         CP#26
   IndirectStaticCall   1, CP#1
   PopLocal             r4
-  PushConstant         CP#26
-  Push                 r5
   PushConstant         CP#27
+  Push                 r5
+  PushConstant         CP#28
   IndirectStaticCall   2, CP#7
   Drop1
   Push                 r0
   LoadContextVar       0, 0
-  InstanceCall         1, CP#28
+  InterfaceCall        1, CP#29
   ReturnTOS
 }
 ConstantPool {
@@ -352,24 +354,26 @@
   [8] = StaticICData target 'dart:async::_completeOnAsyncReturn', arg-desc CP#7
   [9] = Type dynamic
   [10] = ArgDesc num-args 3, num-type-args 0, names []
-  [11] = ICData target-name 'completeError', arg-desc CP#10
-  [12] = EndClosureFunctionScope
-  [13] = Class dart:core::_Closure
-  [14] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
-  [15] = Reserved
-  [16] = InstanceField dart:core::_Closure::_function_type_arguments (field)
-  [17] = Reserved
-  [18] = EmptyTypeArguments
-  [19] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [20] = Reserved
-  [21] = InstanceField dart:core::_Closure::_function (field)
-  [22] = Reserved
-  [23] = StaticICData target 'dart:async::_asyncStackTraceHelper', arg-desc CP#1
-  [24] = StaticICData target 'dart:async::_asyncThenWrapperHelper', arg-desc CP#1
-  [25] = StaticICData target 'dart:async::_asyncErrorWrapperHelper', arg-desc CP#1
-  [26] = TypeArgumentsForInstanceAllocation dart:async::Future [dynamic]
-  [27] = StaticICData target 'dart:async::Future::microtask (constructor)', arg-desc CP#7
-  [28] = ICData get target-name 'get:future', arg-desc CP#1
+  [11] = InterfaceCall target-name 'completeError', arg-desc CP#10
+  [12] = Reserved
+  [13] = EndClosureFunctionScope
+  [14] = Class dart:core::_Closure
+  [15] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+  [16] = Reserved
+  [17] = InstanceField dart:core::_Closure::_function_type_arguments (field)
+  [18] = Reserved
+  [19] = EmptyTypeArguments
+  [20] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
+  [21] = Reserved
+  [22] = InstanceField dart:core::_Closure::_function (field)
+  [23] = Reserved
+  [24] = StaticICData target 'dart:async::_asyncStackTraceHelper', arg-desc CP#1
+  [25] = StaticICData target 'dart:async::_asyncThenWrapperHelper', arg-desc CP#1
+  [26] = StaticICData target 'dart:async::_asyncErrorWrapperHelper', arg-desc CP#1
+  [27] = TypeArgumentsForInstanceAllocation dart:async::Future [dynamic]
+  [28] = StaticICData target 'dart:async::Future::microtask (constructor)', arg-desc CP#7
+  [29] = InterfaceCall get target-name 'get:future', arg-desc CP#1
+  [30] = Reserved
 }
 Closure #lib::foo:::async_op ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
 ClosureBytecode {
@@ -419,7 +423,7 @@
   LoadContextVar       0, 0
   Push                 r8
   Push                 r9
-  InstanceCall         3, CP#11
+  InterfaceCall        3, CP#11
   Drop1
   Jump                 L3
 L3:
@@ -497,50 +501,50 @@
   PushNull
   StoreContextVar      0, 9
   Push                 r0
-  Allocate             CP#17
+  Allocate             CP#19
   StoreLocal           r3
   Push                 r3
   PushNull
-  StoreFieldTOS        CP#18
-  Push                 r3
-  PushNull
   StoreFieldTOS        CP#20
   Push                 r3
-  PushConstant         CP#22
-  StoreFieldTOS        CP#23
+  PushNull
+  StoreFieldTOS        CP#22
+  Push                 r3
+  PushConstant         CP#24
+  StoreFieldTOS        CP#25
   Push                 r3
   PushConstant         CP#3
-  StoreFieldTOS        CP#25
+  StoreFieldTOS        CP#27
   Push                 r3
   Push                 r0
   StoreFieldTOS        CP#5
   StoreContextVar      0, 10
   Push                 r0
   LoadContextVar       0, 10
-  PushConstant         CP#27
+  PushConstant         CP#29
   IndirectStaticCall   1, CP#1
   PopLocal             r2
   Push                 r0
   Push                 r0
   LoadContextVar       0, 10
-  PushConstant         CP#28
+  PushConstant         CP#30
   IndirectStaticCall   1, CP#1
   StoreContextVar      0, 4
   Push                 r0
   Push                 r0
   LoadContextVar       0, 10
-  PushConstant         CP#29
+  PushConstant         CP#31
   IndirectStaticCall   1, CP#1
   StoreContextVar      0, 5
-  PushConstant         CP#30
+  PushConstant         CP#32
   Push                 r0
   LoadContextVar       0, 10
-  PushConstant         CP#31
+  PushConstant         CP#33
   IndirectStaticCall   2, CP#10
   Drop1
   Push                 r0
   LoadContextVar       0, 2
-  InstanceCall         1, CP#32
+  InterfaceCall        1, CP#34
   ReturnTOS
 }
 ConstantPool {
@@ -555,28 +559,31 @@
   [8] = StaticICData target 'dart:async::_awaitHelper', arg-desc CP#7
   [9] = StaticICData target 'dart:async::_awaitHelper', arg-desc CP#7
   [10] = ArgDesc num-args 2, num-type-args 0, names []
-  [11] = ICData target-name '+', arg-desc CP#10
-  [12] = StaticICData target 'dart:async::_completeOnAsyncReturn', arg-desc CP#10
-  [13] = Type dynamic
-  [14] = ArgDesc num-args 3, num-type-args 0, names []
-  [15] = ICData target-name 'completeError', arg-desc CP#14
-  [16] = EndClosureFunctionScope
-  [17] = Class dart:core::_Closure
-  [18] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
-  [19] = Reserved
-  [20] = InstanceField dart:core::_Closure::_function_type_arguments (field)
+  [11] = InterfaceCall target-name '+', arg-desc CP#10
+  [12] = Reserved
+  [13] = StaticICData target 'dart:async::_completeOnAsyncReturn', arg-desc CP#10
+  [14] = Type dynamic
+  [15] = ArgDesc num-args 3, num-type-args 0, names []
+  [16] = InterfaceCall target-name 'completeError', arg-desc CP#15
+  [17] = Reserved
+  [18] = EndClosureFunctionScope
+  [19] = Class dart:core::_Closure
+  [20] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
   [21] = Reserved
-  [22] = EmptyTypeArguments
-  [23] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [24] = Reserved
-  [25] = InstanceField dart:core::_Closure::_function (field)
+  [22] = InstanceField dart:core::_Closure::_function_type_arguments (field)
+  [23] = Reserved
+  [24] = EmptyTypeArguments
+  [25] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
   [26] = Reserved
-  [27] = StaticICData target 'dart:async::_asyncStackTraceHelper', arg-desc CP#1
-  [28] = StaticICData target 'dart:async::_asyncThenWrapperHelper', arg-desc CP#1
-  [29] = StaticICData target 'dart:async::_asyncErrorWrapperHelper', arg-desc CP#1
-  [30] = TypeArgumentsForInstanceAllocation dart:async::Future [dynamic]
-  [31] = StaticICData target 'dart:async::Future::microtask (constructor)', arg-desc CP#10
-  [32] = ICData get target-name 'get:future', arg-desc CP#1
+  [27] = InstanceField dart:core::_Closure::_function (field)
+  [28] = Reserved
+  [29] = StaticICData target 'dart:async::_asyncStackTraceHelper', arg-desc CP#1
+  [30] = StaticICData target 'dart:async::_asyncThenWrapperHelper', arg-desc CP#1
+  [31] = StaticICData target 'dart:async::_asyncErrorWrapperHelper', arg-desc CP#1
+  [32] = TypeArgumentsForInstanceAllocation dart:async::Future [dynamic]
+  [33] = StaticICData target 'dart:async::Future::microtask (constructor)', arg-desc CP#10
+  [34] = InterfaceCall get target-name 'get:future', arg-desc CP#1
+  [35] = Reserved
 }
 Closure #lib::simpleAsyncAwait:::async_op ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
 ClosureBytecode {
@@ -657,7 +664,7 @@
   Push                 r4
   LoadContextVar       0, 9
   Push                 r1
-  InstanceCall         2, CP#11
+  InterfaceCall        2, CP#11
   StoreContextVar      0, 3
   Jump                 L4
 L4:
@@ -665,7 +672,7 @@
   LoadContextVar       0, 2
   Push                 r4
   LoadContextVar       0, 3
-  PushConstant         CP#12
+  PushConstant         CP#13
   IndirectStaticCall   2, CP#10
   Drop1
   PushNull
@@ -689,7 +696,7 @@
   LoadContextVar       0, 2
   Push                 r8
   Push                 r9
-  InstanceCall         3, CP#15
+  InterfaceCall        3, CP#16
   Drop1
   Jump                 L5
 L5:
@@ -778,50 +785,50 @@
   PushNull
   StoreContextVar      0, 9
   Push                 r0
-  Allocate             CP#22
+  Allocate             CP#26
   StoreLocal           r3
   Push                 r3
   PushNull
-  StoreFieldTOS        CP#23
+  StoreFieldTOS        CP#27
   Push                 r3
   PushNull
-  StoreFieldTOS        CP#25
+  StoreFieldTOS        CP#29
   Push                 r3
-  PushConstant         CP#27
-  StoreFieldTOS        CP#28
+  PushConstant         CP#31
+  StoreFieldTOS        CP#32
   Push                 r3
   PushConstant         CP#3
-  StoreFieldTOS        CP#30
+  StoreFieldTOS        CP#34
   Push                 r3
   Push                 r0
   StoreFieldTOS        CP#5
   StoreContextVar      0, 10
   Push                 r0
   LoadContextVar       0, 10
-  PushConstant         CP#32
+  PushConstant         CP#36
   IndirectStaticCall   1, CP#1
   PopLocal             r2
   Push                 r0
   Push                 r0
   LoadContextVar       0, 10
-  PushConstant         CP#33
+  PushConstant         CP#37
   IndirectStaticCall   1, CP#1
   StoreContextVar      0, 3
   Push                 r0
   Push                 r0
   LoadContextVar       0, 10
-  PushConstant         CP#34
+  PushConstant         CP#38
   IndirectStaticCall   1, CP#1
   StoreContextVar      0, 4
-  PushConstant         CP#35
+  PushConstant         CP#39
   Push                 r0
   LoadContextVar       0, 10
-  PushConstant         CP#36
-  IndirectStaticCall   2, CP#14
+  PushConstant         CP#40
+  IndirectStaticCall   2, CP#17
   Drop1
   Push                 r0
   LoadContextVar       0, 1
-  InstanceCall         1, CP#37
+  InterfaceCall        1, CP#41
   ReturnTOS
 }
 ConstantPool {
@@ -832,37 +839,42 @@
   [4] = Null
   [5] = InstanceField dart:core::_Closure::_context (field)
   [6] = Reserved
-  [7] = ICData get target-name 'get:iterator', arg-desc CP#1
-  [8] = ICData target-name 'moveNext', arg-desc CP#1
-  [9] = ICData get target-name 'get:current', arg-desc CP#1
-  [10] = ArgDesc num-args 0, num-type-args 0, names []
-  [11] = StaticICData target '#lib::foo', arg-desc CP#10
-  [12] = ArgDesc num-args 4, num-type-args 0, names []
-  [13] = StaticICData target 'dart:async::_awaitHelper', arg-desc CP#12
-  [14] = ArgDesc num-args 2, num-type-args 0, names []
-  [15] = ICData target-name '+', arg-desc CP#14
-  [16] = ICData target-name '+', arg-desc CP#14
-  [17] = StaticICData target 'dart:async::_completeOnAsyncReturn', arg-desc CP#14
-  [18] = Type dynamic
-  [19] = ArgDesc num-args 3, num-type-args 0, names []
-  [20] = ICData target-name 'completeError', arg-desc CP#19
-  [21] = EndClosureFunctionScope
-  [22] = Class dart:core::_Closure
-  [23] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+  [7] = InterfaceCall get target-name 'get:iterator', arg-desc CP#1
+  [8] = Reserved
+  [9] = InterfaceCall target-name 'moveNext', arg-desc CP#1
+  [10] = Reserved
+  [11] = InterfaceCall get target-name 'get:current', arg-desc CP#1
+  [12] = Reserved
+  [13] = ArgDesc num-args 0, num-type-args 0, names []
+  [14] = StaticICData target '#lib::foo', arg-desc CP#13
+  [15] = ArgDesc num-args 4, num-type-args 0, names []
+  [16] = StaticICData target 'dart:async::_awaitHelper', arg-desc CP#15
+  [17] = ArgDesc num-args 2, num-type-args 0, names []
+  [18] = InterfaceCall target-name '+', arg-desc CP#17
+  [19] = Reserved
+  [20] = StaticICData target 'dart:async::_completeOnAsyncReturn', arg-desc CP#17
+  [21] = Type dynamic
+  [22] = ArgDesc num-args 3, num-type-args 0, names []
+  [23] = InterfaceCall target-name 'completeError', arg-desc CP#22
   [24] = Reserved
-  [25] = InstanceField dart:core::_Closure::_function_type_arguments (field)
-  [26] = Reserved
-  [27] = EmptyTypeArguments
-  [28] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [29] = Reserved
-  [30] = InstanceField dart:core::_Closure::_function (field)
-  [31] = Reserved
-  [32] = StaticICData target 'dart:async::_asyncStackTraceHelper', arg-desc CP#1
-  [33] = StaticICData target 'dart:async::_asyncThenWrapperHelper', arg-desc CP#1
-  [34] = StaticICData target 'dart:async::_asyncErrorWrapperHelper', arg-desc CP#1
-  [35] = TypeArgumentsForInstanceAllocation dart:async::Future [dynamic]
-  [36] = StaticICData target 'dart:async::Future::microtask (constructor)', arg-desc CP#14
-  [37] = ICData get target-name 'get:future', arg-desc CP#1
+  [25] = EndClosureFunctionScope
+  [26] = Class dart:core::_Closure
+  [27] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+  [28] = Reserved
+  [29] = InstanceField dart:core::_Closure::_function_type_arguments (field)
+  [30] = Reserved
+  [31] = EmptyTypeArguments
+  [32] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
+  [33] = Reserved
+  [34] = InstanceField dart:core::_Closure::_function (field)
+  [35] = Reserved
+  [36] = StaticICData target 'dart:async::_asyncStackTraceHelper', arg-desc CP#1
+  [37] = StaticICData target 'dart:async::_asyncThenWrapperHelper', arg-desc CP#1
+  [38] = StaticICData target 'dart:async::_asyncErrorWrapperHelper', arg-desc CP#1
+  [39] = TypeArgumentsForInstanceAllocation dart:async::Future [dynamic]
+  [40] = StaticICData target 'dart:async::Future::microtask (constructor)', arg-desc CP#17
+  [41] = InterfaceCall get target-name 'get:future', arg-desc CP#1
+  [42] = Reserved
 }
 Closure #lib::loops:::async_op ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
 ClosureBytecode {
@@ -913,7 +925,7 @@
   LoadContextParent
   LoadContextParent
   LoadContextVar       0, 0
-  InstanceCall         1, CP#7
+  InterfaceCall        1, CP#7
   PopLocal             r8
   Push                 r4
   Push                 r8
@@ -923,7 +935,7 @@
   Push                 r4
   LoadContextVar       2, 1
   StoreLocal           r8
-  InstanceCall         1, CP#8
+  InterfaceCall        1, CP#9
   JumpIfFalse          L3
   AllocateContext      3, 1
   StoreLocal           r5
@@ -933,7 +945,7 @@
   PopLocal             r4
   Push                 r4
   Push                 r8
-  InstanceCall         1, CP#9
+  InterfaceCall        1, CP#11
   StoreContextVar      3, 0
   Push                 r4
   LoadContextParent
@@ -967,8 +979,8 @@
   LoadContextParent
   Push                 r4
   StoreContextVar      0, 6
-  PushConstant         CP#11
-  IndirectStaticCall   0, CP#10
+  PushConstant         CP#14
+  IndirectStaticCall   0, CP#13
   Push                 r4
   LoadContextParent
   LoadContextParent
@@ -984,8 +996,8 @@
   LoadContextParent
   LoadContextParent
   LoadContextVar       0, 10
-  PushConstant         CP#13
-  IndirectStaticCall   4, CP#12
+  PushConstant         CP#16
+  IndirectStaticCall   4, CP#15
   PopLocal             r10
   PushNull
   ReturnTOS
@@ -1010,8 +1022,8 @@
   LoadContextParent
   LoadContextVar       0, 8
   Push                 r1
-  InstanceCall         2, CP#15
-  InstanceCall         2, CP#16
+  InterfaceCall        2, CP#18
+  InterfaceCall        2, CP#18
   StoreContextVar      1, 0
   Push                 r4
   LoadContextParent
@@ -1070,8 +1082,8 @@
   LoadContextVar       0, 1
   Push                 r4
   LoadContextVar       0, 2
-  PushConstant         CP#17
-  IndirectStaticCall   2, CP#14
+  PushConstant         CP#20
+  IndirectStaticCall   2, CP#17
   Drop1
   PushNull
   ReturnTOS
@@ -1094,7 +1106,7 @@
   LoadContextVar       0, 1
   Push                 r8
   Push                 r9
-  InstanceCall         3, CP#20
+  InterfaceCall        3, CP#23
   Drop1
   Jump                 L10
 L10:
@@ -1205,50 +1217,50 @@
   PushNull
   StoreContextVar      0, 14
   Push                 r0
-  Allocate             CP#30
+  Allocate             CP#29
   StoreLocal           r3
   Push                 r3
   PushNull
-  StoreFieldTOS        CP#31
+  StoreFieldTOS        CP#30
   Push                 r3
   PushNull
-  StoreFieldTOS        CP#33
+  StoreFieldTOS        CP#32
   Push                 r3
-  PushConstant         CP#35
-  StoreFieldTOS        CP#36
+  PushConstant         CP#34
+  StoreFieldTOS        CP#35
   Push                 r3
   PushConstant         CP#3
-  StoreFieldTOS        CP#38
+  StoreFieldTOS        CP#37
   Push                 r3
   Push                 r0
   StoreFieldTOS        CP#5
   StoreContextVar      0, 15
   Push                 r0
   LoadContextVar       0, 15
-  PushConstant         CP#40
+  PushConstant         CP#39
   IndirectStaticCall   1, CP#1
   PopLocal             r2
   Push                 r0
   Push                 r0
   LoadContextVar       0, 15
-  PushConstant         CP#41
+  PushConstant         CP#40
   IndirectStaticCall   1, CP#1
   StoreContextVar      0, 5
   Push                 r0
   Push                 r0
   LoadContextVar       0, 15
-  PushConstant         CP#42
+  PushConstant         CP#41
   IndirectStaticCall   1, CP#1
   StoreContextVar      0, 6
-  PushConstant         CP#43
+  PushConstant         CP#42
   Push                 r0
   LoadContextVar       0, 15
-  PushConstant         CP#44
+  PushConstant         CP#43
   IndirectStaticCall   2, CP#9
   Drop1
   Push                 r0
   LoadContextVar       0, 3
-  InstanceCall         1, CP#45
+  InterfaceCall        1, CP#44
   ReturnTOS
 }
 ConstantPool {
@@ -1262,42 +1274,42 @@
   [7] = ArgDesc num-args 4, num-type-args 0, names []
   [8] = StaticICData target 'dart:async::_awaitHelper', arg-desc CP#7
   [9] = ArgDesc num-args 2, num-type-args 0, names []
-  [10] = ICData target-name '+', arg-desc CP#9
-  [11] = Type dynamic
-  [12] = Type dart:core::Error
-  [13] = ICData target-name '_simpleInstanceOf', arg-desc CP#9
-  [14] = StaticICData target 'dart:async::_awaitHelper', arg-desc CP#7
-  [15] = ICData target-name '+', arg-desc CP#9
-  [16] = String 'fin'
-  [17] = StaticICData target 'dart:core::print', arg-desc CP#1
-  [18] = StaticICData target 'dart:async::_awaitHelper', arg-desc CP#7
-  [19] = ICData target-name '+', arg-desc CP#9
+  [10] = InterfaceCall target-name '+', arg-desc CP#9
+  [11] = Reserved
+  [12] = Type dynamic
+  [13] = Type dart:core::Error
+  [14] = InterfaceCall target-name '_simpleInstanceOf', arg-desc CP#9
+  [15] = Reserved
+  [16] = StaticICData target 'dart:async::_awaitHelper', arg-desc CP#7
+  [17] = String 'fin'
+  [18] = StaticICData target 'dart:core::print', arg-desc CP#1
+  [19] = StaticICData target 'dart:async::_awaitHelper', arg-desc CP#7
   [20] = StaticICData target 'dart:core::print', arg-desc CP#1
   [21] = StaticICData target 'dart:async::_awaitHelper', arg-desc CP#7
-  [22] = ICData target-name '+', arg-desc CP#9
-  [23] = StaticICData target 'dart:core::print', arg-desc CP#1
-  [24] = StaticICData target 'dart:async::_awaitHelper', arg-desc CP#7
-  [25] = ICData target-name '+', arg-desc CP#9
-  [26] = StaticICData target 'dart:async::_completeOnAsyncReturn', arg-desc CP#9
-  [27] = ArgDesc num-args 3, num-type-args 0, names []
-  [28] = ICData target-name 'completeError', arg-desc CP#27
-  [29] = EndClosureFunctionScope
-  [30] = Class dart:core::_Closure
-  [31] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
-  [32] = Reserved
-  [33] = InstanceField dart:core::_Closure::_function_type_arguments (field)
-  [34] = Reserved
-  [35] = EmptyTypeArguments
-  [36] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [37] = Reserved
-  [38] = InstanceField dart:core::_Closure::_function (field)
-  [39] = Reserved
-  [40] = StaticICData target 'dart:async::_asyncStackTraceHelper', arg-desc CP#1
-  [41] = StaticICData target 'dart:async::_asyncThenWrapperHelper', arg-desc CP#1
-  [42] = StaticICData target 'dart:async::_asyncErrorWrapperHelper', arg-desc CP#1
-  [43] = TypeArgumentsForInstanceAllocation dart:async::Future [dynamic]
-  [44] = StaticICData target 'dart:async::Future::microtask (constructor)', arg-desc CP#9
-  [45] = ICData get target-name 'get:future', arg-desc CP#1
+  [22] = StaticICData target 'dart:core::print', arg-desc CP#1
+  [23] = StaticICData target 'dart:async::_awaitHelper', arg-desc CP#7
+  [24] = StaticICData target 'dart:async::_completeOnAsyncReturn', arg-desc CP#9
+  [25] = ArgDesc num-args 3, num-type-args 0, names []
+  [26] = InterfaceCall target-name 'completeError', arg-desc CP#25
+  [27] = Reserved
+  [28] = EndClosureFunctionScope
+  [29] = Class dart:core::_Closure
+  [30] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+  [31] = Reserved
+  [32] = InstanceField dart:core::_Closure::_function_type_arguments (field)
+  [33] = Reserved
+  [34] = EmptyTypeArguments
+  [35] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
+  [36] = Reserved
+  [37] = InstanceField dart:core::_Closure::_function (field)
+  [38] = Reserved
+  [39] = StaticICData target 'dart:async::_asyncStackTraceHelper', arg-desc CP#1
+  [40] = StaticICData target 'dart:async::_asyncThenWrapperHelper', arg-desc CP#1
+  [41] = StaticICData target 'dart:async::_asyncErrorWrapperHelper', arg-desc CP#1
+  [42] = TypeArgumentsForInstanceAllocation dart:async::Future [dynamic]
+  [43] = StaticICData target 'dart:async::Future::microtask (constructor)', arg-desc CP#9
+  [44] = InterfaceCall get target-name 'get:future', arg-desc CP#1
+  [45] = Reserved
 }
 Closure #lib::tryCatchRethrow:::async_op ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
 ClosureBytecode {
@@ -1380,7 +1392,7 @@
   LoadContextParent
   LoadContextVar       0, 14
   Push                 r1
-  InstanceCall         2, CP#10
+  InterfaceCall        2, CP#10
   StoreContextVar      1, 0
   Jump                 L3
 Try #2 end:
@@ -1407,8 +1419,8 @@
   StoreContextVar      1, 1
   Push                 r4
   LoadContextVar       1, 1
-  PushConstant         CP#12
-  InstanceCall         2, CP#13
+  PushConstant         CP#13
+  InterfaceCall        2, CP#14
   JumpIfFalse          L4
   Push                 r4
   LoadContextParent
@@ -1441,7 +1453,7 @@
   Push                 r4
   LoadContextParent
   LoadContextVar       0, 15
-  PushConstant         CP#14
+  PushConstant         CP#16
   IndirectStaticCall   4, CP#7
   PopLocal             r13
   PushNull
@@ -1458,7 +1470,7 @@
   LoadContextParent
   LoadContextVar       0, 14
   Push                 r1
-  InstanceCall         2, CP#15
+  InterfaceCall        2, CP#10
   StoreContextVar      1, 0
   Push                 r4
   LoadContextParent
@@ -1488,8 +1500,8 @@
   LoadContextParent
   Push                 r9
   StoreContextVar      0, 13
-  PushConstant         CP#16
   PushConstant         CP#17
+  PushConstant         CP#18
   IndirectStaticCall   1, CP#1
   Drop1
   Push                 r4
@@ -1517,7 +1529,7 @@
   Push                 r4
   LoadContextParent
   LoadContextVar       0, 15
-  PushConstant         CP#18
+  PushConstant         CP#19
   IndirectStaticCall   4, CP#7
   PopLocal             r12
   PushNull
@@ -1534,7 +1546,7 @@
   LoadContextParent
   LoadContextVar       0, 14
   Push                 r1
-  InstanceCall         2, CP#19
+  InterfaceCall        2, CP#10
   StoreContextVar      1, 0
   Push                 r4
   LoadContextParent
@@ -1552,7 +1564,7 @@
   Push                 r4
   LoadContextVar       0, 10
   PopLocal             r4
-  PushConstant         CP#16
+  PushConstant         CP#17
   PushConstant         CP#20
   IndirectStaticCall   1, CP#1
   Drop1
@@ -1598,7 +1610,7 @@
   LoadContextParent
   LoadContextVar       0, 14
   Push                 r1
-  InstanceCall         2, CP#22
+  InterfaceCall        2, CP#10
   StoreContextVar      1, 0
   Push                 r4
   LoadContextParent
@@ -1616,8 +1628,8 @@
   Push                 r4
   LoadContextVar       0, 10
   PopLocal             r4
-  PushConstant         CP#16
-  PushConstant         CP#23
+  PushConstant         CP#17
+  PushConstant         CP#22
   IndirectStaticCall   1, CP#1
   Drop1
   Push                 r4
@@ -1645,7 +1657,7 @@
   Push                 r4
   LoadContextParent
   LoadContextVar       0, 15
-  PushConstant         CP#24
+  PushConstant         CP#23
   IndirectStaticCall   4, CP#7
   PopLocal             r12
   PushNull
@@ -1662,7 +1674,7 @@
   LoadContextParent
   LoadContextVar       0, 14
   Push                 r1
-  InstanceCall         2, CP#25
+  InterfaceCall        2, CP#10
   StoreContextVar      1, 0
   Push                 r4
   LoadContextParent
@@ -1678,7 +1690,7 @@
   LoadContextVar       0, 3
   Push                 r4
   LoadContextVar       0, 4
-  PushConstant         CP#26
+  PushConstant         CP#24
   IndirectStaticCall   2, CP#9
   Drop1
   PushNull
@@ -1702,7 +1714,7 @@
   LoadContextVar       0, 3
   Push                 r8
   Push                 r9
-  InstanceCall         3, CP#28
+  InterfaceCall        3, CP#26
   Drop1
   Jump                 L12
 L12:
@@ -1795,20 +1807,20 @@
   Push                 r0
   PushInt              3
   StoreContextVar      0, 1
-  Allocate             CP#19
+  Allocate             CP#20
   StoreLocal           r3
   Push                 r3
   PushNull
-  StoreFieldTOS        CP#20
+  StoreFieldTOS        CP#21
   Push                 r3
   PushNull
-  StoreFieldTOS        CP#22
+  StoreFieldTOS        CP#23
   Push                 r3
-  PushConstant         CP#24
-  StoreFieldTOS        CP#25
+  PushConstant         CP#25
+  StoreFieldTOS        CP#26
   Push                 r3
   PushConstant         CP#0
-  StoreFieldTOS        CP#27
+  StoreFieldTOS        CP#28
   Push                 r3
   Push                 r0
   StoreFieldTOS        CP#1
@@ -1834,25 +1846,27 @@
   [14] = ArgDesc num-args 2, num-type-args 0, names []
   [15] = StaticICData target 'dart:async::_completeOnAsyncReturn', arg-desc CP#14
   [16] = ArgDesc num-args 3, num-type-args 0, names []
-  [17] = ICData target-name 'completeError', arg-desc CP#16
-  [18] = EndClosureFunctionScope
-  [19] = Class dart:core::_Closure
-  [20] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
-  [21] = Reserved
-  [22] = InstanceField dart:core::_Closure::_function_type_arguments (field)
-  [23] = Reserved
-  [24] = EmptyTypeArguments
-  [25] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [26] = Reserved
-  [27] = InstanceField dart:core::_Closure::_function (field)
-  [28] = Reserved
-  [29] = StaticICData target 'dart:async::_asyncStackTraceHelper', arg-desc CP#4
-  [30] = StaticICData target 'dart:async::_asyncThenWrapperHelper', arg-desc CP#4
-  [31] = StaticICData target 'dart:async::_asyncErrorWrapperHelper', arg-desc CP#4
-  [32] = TypeArgumentsForInstanceAllocation dart:async::Future [dynamic]
-  [33] = StaticICData target 'dart:async::Future::microtask (constructor)', arg-desc CP#14
-  [34] = ICData get target-name 'get:future', arg-desc CP#4
-  [35] = EndClosureFunctionScope
+  [17] = InterfaceCall target-name 'completeError', arg-desc CP#16
+  [18] = Reserved
+  [19] = EndClosureFunctionScope
+  [20] = Class dart:core::_Closure
+  [21] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+  [22] = Reserved
+  [23] = InstanceField dart:core::_Closure::_function_type_arguments (field)
+  [24] = Reserved
+  [25] = EmptyTypeArguments
+  [26] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
+  [27] = Reserved
+  [28] = InstanceField dart:core::_Closure::_function (field)
+  [29] = Reserved
+  [30] = StaticICData target 'dart:async::_asyncStackTraceHelper', arg-desc CP#4
+  [31] = StaticICData target 'dart:async::_asyncThenWrapperHelper', arg-desc CP#4
+  [32] = StaticICData target 'dart:async::_asyncErrorWrapperHelper', arg-desc CP#4
+  [33] = TypeArgumentsForInstanceAllocation dart:async::Future [dynamic]
+  [34] = StaticICData target 'dart:async::Future::microtask (constructor)', arg-desc CP#14
+  [35] = InterfaceCall get target-name 'get:future', arg-desc CP#4
+  [36] = Reserved
+  [37] = EndClosureFunctionScope
 }
 Closure #lib::closure::nested () -> dart:async::Future < dart:core::int >
 ClosureBytecode {
@@ -1896,50 +1910,50 @@
   PushNull
   StoreContextVar      1, 7
   Push                 r0
-  Allocate             CP#19
+  Allocate             CP#20
   StoreLocal           r3
   Push                 r3
   PushNull
-  StoreFieldTOS        CP#20
+  StoreFieldTOS        CP#21
   Push                 r3
   PushNull
-  StoreFieldTOS        CP#22
+  StoreFieldTOS        CP#23
   Push                 r3
-  PushConstant         CP#24
-  StoreFieldTOS        CP#25
+  PushConstant         CP#25
+  StoreFieldTOS        CP#26
   Push                 r3
   PushConstant         CP#6
-  StoreFieldTOS        CP#27
+  StoreFieldTOS        CP#28
   Push                 r3
   Push                 r0
   StoreFieldTOS        CP#1
   StoreContextVar      1, 8
   Push                 r0
   LoadContextVar       1, 8
-  PushConstant         CP#29
+  PushConstant         CP#30
   IndirectStaticCall   1, CP#4
   PopLocal             r2
   Push                 r0
   Push                 r0
   LoadContextVar       1, 8
-  PushConstant         CP#30
+  PushConstant         CP#31
   IndirectStaticCall   1, CP#4
   StoreContextVar      1, 2
   Push                 r0
   Push                 r0
   LoadContextVar       1, 8
-  PushConstant         CP#31
+  PushConstant         CP#32
   IndirectStaticCall   1, CP#4
   StoreContextVar      1, 3
-  PushConstant         CP#32
+  PushConstant         CP#33
   Push                 r0
   LoadContextVar       1, 8
-  PushConstant         CP#33
+  PushConstant         CP#34
   IndirectStaticCall   2, CP#14
   Drop1
   Push                 r0
   LoadContextVar       1, 0
-  InstanceCall         1, CP#34
+  InterfaceCall        1, CP#35
   ReturnTOS
 
 }
@@ -2092,7 +2106,7 @@
   LoadContextVar       1, 0
   Push                 r8
   Push                 r9
-  InstanceCall         3, CP#17
+  InterfaceCall        3, CP#17
   Drop1
   Jump                 L5
 L5:
@@ -2182,50 +2196,50 @@
   PushNull
   StoreContextVar      0, 7
   Push                 r0
-  Allocate             CP#17
+  Allocate             CP#19
   StoreLocal           r3
   Push                 r3
   PushNull
-  StoreFieldTOS        CP#18
-  Push                 r3
-  PushNull
   StoreFieldTOS        CP#20
   Push                 r3
-  PushConstant         CP#22
-  StoreFieldTOS        CP#23
+  PushNull
+  StoreFieldTOS        CP#22
+  Push                 r3
+  PushConstant         CP#24
+  StoreFieldTOS        CP#25
   Push                 r3
   PushConstant         CP#3
-  StoreFieldTOS        CP#25
+  StoreFieldTOS        CP#27
   Push                 r3
   Push                 r0
   StoreFieldTOS        CP#5
   StoreContextVar      0, 8
   Push                 r0
   LoadContextVar       0, 8
-  PushConstant         CP#27
+  PushConstant         CP#29
   IndirectStaticCall   1, CP#1
   PopLocal             r2
   Push                 r0
   Push                 r0
   LoadContextVar       0, 8
-  PushConstant         CP#28
+  PushConstant         CP#30
   IndirectStaticCall   1, CP#1
   StoreContextVar      0, 3
   Push                 r0
   Push                 r0
   LoadContextVar       0, 8
-  PushConstant         CP#29
+  PushConstant         CP#31
   IndirectStaticCall   1, CP#1
   StoreContextVar      0, 4
-  PushConstant         CP#30
+  PushConstant         CP#32
   Push                 r0
   LoadContextVar       0, 8
-  PushConstant         CP#31
+  PushConstant         CP#33
   IndirectStaticCall   2, CP#9
   Drop1
   Push                 r0
   LoadContextVar       0, 1
-  InstanceCall         1, CP#32
+  InterfaceCall        1, CP#34
   ReturnTOS
 }
 ConstantPool {
@@ -2239,29 +2253,32 @@
   [7] = ArgDesc num-args 4, num-type-args 0, names []
   [8] = StaticICData target 'dart:async::_awaitHelper', arg-desc CP#7
   [9] = ArgDesc num-args 2, num-type-args 0, names []
-  [10] = ICData target-name '==', arg-desc CP#9
-  [11] = ArgDesc num-args 3, num-type-args 0, names []
-  [12] = StaticICData target 'dart:core::_AssertionError::_throwNew', arg-desc CP#11
-  [13] = StaticICData target 'dart:async::_completeOnAsyncReturn', arg-desc CP#9
-  [14] = Type dynamic
-  [15] = ICData target-name 'completeError', arg-desc CP#11
-  [16] = EndClosureFunctionScope
-  [17] = Class dart:core::_Closure
-  [18] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
-  [19] = Reserved
-  [20] = InstanceField dart:core::_Closure::_function_type_arguments (field)
+  [10] = InterfaceCall target-name '==', arg-desc CP#9
+  [11] = Reserved
+  [12] = ArgDesc num-args 3, num-type-args 0, names []
+  [13] = StaticICData target 'dart:core::_AssertionError::_throwNew', arg-desc CP#12
+  [14] = StaticICData target 'dart:async::_completeOnAsyncReturn', arg-desc CP#9
+  [15] = Type dynamic
+  [16] = InterfaceCall target-name 'completeError', arg-desc CP#12
+  [17] = Reserved
+  [18] = EndClosureFunctionScope
+  [19] = Class dart:core::_Closure
+  [20] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
   [21] = Reserved
-  [22] = EmptyTypeArguments
-  [23] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [24] = Reserved
-  [25] = InstanceField dart:core::_Closure::_function (field)
+  [22] = InstanceField dart:core::_Closure::_function_type_arguments (field)
+  [23] = Reserved
+  [24] = EmptyTypeArguments
+  [25] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
   [26] = Reserved
-  [27] = StaticICData target 'dart:async::_asyncStackTraceHelper', arg-desc CP#1
-  [28] = StaticICData target 'dart:async::_asyncThenWrapperHelper', arg-desc CP#1
-  [29] = StaticICData target 'dart:async::_asyncErrorWrapperHelper', arg-desc CP#1
-  [30] = TypeArgumentsForInstanceAllocation dart:async::Future [dynamic]
-  [31] = StaticICData target 'dart:async::Future::microtask (constructor)', arg-desc CP#9
-  [32] = ICData get target-name 'get:future', arg-desc CP#1
+  [27] = InstanceField dart:core::_Closure::_function (field)
+  [28] = Reserved
+  [29] = StaticICData target 'dart:async::_asyncStackTraceHelper', arg-desc CP#1
+  [30] = StaticICData target 'dart:async::_asyncThenWrapperHelper', arg-desc CP#1
+  [31] = StaticICData target 'dart:async::_asyncErrorWrapperHelper', arg-desc CP#1
+  [32] = TypeArgumentsForInstanceAllocation dart:async::Future [dynamic]
+  [33] = StaticICData target 'dart:async::Future::microtask (constructor)', arg-desc CP#9
+  [34] = InterfaceCall get target-name 'get:future', arg-desc CP#1
+  [35] = Reserved
 }
 Closure #lib::testAssert:::async_op ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
 ClosureBytecode {
@@ -2313,14 +2330,14 @@
   JumpIfNoAsserts      L2
   Push                 r1
   PushInt              42
-  InstanceCall         2, CP#10
+  InterfaceCall        2, CP#10
   AssertBoolean        0
   JumpIfTrue           L2
   PushInt              0
   PushInt              0
   PushNull
-  PushConstant         CP#12
-  IndirectStaticCall   3, CP#11
+  PushConstant         CP#13
+  IndirectStaticCall   3, CP#12
   Drop1
 L2:
   Push                 r4
@@ -2332,7 +2349,7 @@
   LoadContextVar       0, 1
   Push                 r4
   LoadContextVar       0, 2
-  PushConstant         CP#13
+  PushConstant         CP#14
   IndirectStaticCall   2, CP#9
   Drop1
   PushNull
@@ -2356,7 +2373,7 @@
   LoadContextVar       0, 1
   Push                 r8
   Push                 r9
-  InstanceCall         3, CP#15
+  InterfaceCall        3, CP#16
   Drop1
   Jump                 L5
 L5:
diff --git a/pkg/vm/testcases/bytecode/bootstrapping.dart.expect b/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
index 5b7b1bf..ed981f0 100644
--- a/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
+++ b/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
@@ -308,7 +308,7 @@
   JumpIfFalse          L3
   PushConstant         CP#1
   PushStatic           CP#1
-  InstanceCall         1, CP#3
+  DynamicCall          1, CP#3
   StoreStaticTOS       CP#0
 L3:
   PushConstant         CP#0
@@ -402,8 +402,8 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  InstanceCall         1, CP#1
-  PushConstant         CP#2
+  InterfaceCall        1, CP#1
+  PushConstant         CP#3
   IndirectStaticCall   1, CP#0
   Drop1
   PushNull
@@ -411,8 +411,9 @@
 }
 ConstantPool {
   [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = ICData target-name 'toString', arg-desc CP#0
-  [2] = StaticICData target '#lib::_printString', arg-desc CP#0
+  [1] = InterfaceCall target-name 'toString', arg-desc CP#0
+  [2] = Reserved
+  [3] = StaticICData target '#lib::_printString', arg-desc CP#0
 }
 ]static method _print(dynamic arg) → void {
   self::_printString(arg.{core::Object::toString}());
@@ -474,13 +475,13 @@
   PushConstant         CP#0
   PushStatic           CP#0
   PushConstant         CP#1
-  InstanceCall         2, CP#3
+  InterfaceCall        2, CP#3
   AssertBoolean        0
   JumpIfTrue           L1
   PushConstant         CP#0
   PushStatic           CP#0
-  PushConstant         CP#4
-  InstanceCall         2, CP#5
+  PushConstant         CP#5
+  InterfaceCall        2, CP#3
   AssertBoolean        0
   PopLocal             r1
   Jump                 L2
@@ -493,7 +494,7 @@
   PushConstant         CP#0
   PushStatic           CP#0
   PushConstant         CP#6
-  InstanceCall         2, CP#7
+  InterfaceCall        2, CP#3
   AssertBoolean        0
   PopLocal             r0
   Jump                 L4
@@ -505,35 +506,35 @@
   JumpIfFalse          L5
   PushConstant         CP#0
   PushStatic           CP#0
-  PushConstant         CP#9
-  IndirectStaticCall   1, CP#8
+  PushConstant         CP#8
+  IndirectStaticCall   1, CP#7
   ReturnTOS
 L5:
-  PushConstant         CP#11
-  IndirectStaticCall   0, CP#10
+  PushConstant         CP#10
+  IndirectStaticCall   0, CP#9
   PushNull
   PushConstant         CP#0
   PushStatic           CP#0
-  PushConstant         CP#12
+  PushConstant         CP#11
   IndirectStaticCall   2, CP#2
-  InstanceCall         2, CP#13
+  InterfaceCall        2, CP#12
   ReturnTOS
 }
 ConstantPool {
   [0] = StaticField #lib::_rawScript (field)
   [1] = String 'http:'
   [2] = ArgDesc num-args 2, num-type-args 0, names []
-  [3] = ICData target-name 'startsWith', arg-desc CP#2
-  [4] = String 'https:'
-  [5] = ICData target-name 'startsWith', arg-desc CP#2
+  [3] = InterfaceCall target-name 'startsWith', arg-desc CP#2
+  [4] = Reserved
+  [5] = String 'https:'
   [6] = String 'file:'
-  [7] = ICData target-name 'startsWith', arg-desc CP#2
-  [8] = ArgDesc num-args 1, num-type-args 0, names []
-  [9] = StaticICData target 'dart:core::Uri::parse', arg-desc CP#8
-  [10] = ArgDesc num-args 0, num-type-args 0, names []
-  [11] = StaticICData target 'dart:core::Uri::get:base', arg-desc CP#10
-  [12] = StaticICData target 'dart:core::_Uri::file (constructor)', arg-desc CP#2
-  [13] = ICData target-name 'resolveUri', arg-desc CP#2
+  [7] = ArgDesc num-args 1, num-type-args 0, names []
+  [8] = StaticICData target 'dart:core::Uri::parse', arg-desc CP#7
+  [9] = ArgDesc num-args 0, num-type-args 0, names []
+  [10] = StaticICData target 'dart:core::Uri::get:base', arg-desc CP#9
+  [11] = StaticICData target 'dart:core::_Uri::file (constructor)', arg-desc CP#2
+  [12] = InterfaceCall target-name 'resolveUri', arg-desc CP#2
+  [13] = Reserved
 }
 ]static method _scriptUri() → core::Uri {
   if(self::_rawScript.{core::String::startsWith}("http:") || self::_rawScript.{core::String::startsWith}("https:") || self::_rawScript.{core::String::startsWith}("file:")) {
diff --git a/pkg/vm/testcases/bytecode/closures.dart.expect b/pkg/vm/testcases/bytecode/closures.dart.expect
index cf8425c..f801084 100644
--- a/pkg/vm/testcases/bytecode/closures.dart.expect
+++ b/pkg/vm/testcases/bytecode/closures.dart.expect
@@ -213,11 +213,11 @@
   PopLocal             r3
   PushConstant         CP#44
   Push                 r3
-  InstanceCall         2, CP#45
+  DynamicCall          2, CP#45
   Drop1
   PushConstant         CP#46
   Push                 r3
-  InstanceCall         2, CP#47
+  DynamicCall          2, CP#47
   Drop1
   PushNull
   ReturnTOS
@@ -319,11 +319,11 @@
   PopLocal             r3
   PushConstant         CP#38
   Push                 r3
-  InstanceCall         2, CP#40
+  DynamicCall          2, CP#40
   Drop1
   PushConstant         CP#41
   Push                 r3
-  InstanceCall         2, CP#42
+  DynamicCall          2, CP#42
   Drop1
   PushNull
   ReturnTOS
@@ -376,7 +376,7 @@
   StoreFieldTOS        CP#1
   PopLocal             r3
   Push                 r3
-  InstanceCall         1, CP#36
+  DynamicCall          1, CP#36
   Drop1
   PushNull
   ReturnTOS
@@ -522,69 +522,69 @@
   Push                 r0
   PushInt              3
   StoreContextVar      0, 2
-  Allocate             CP#10
+  Allocate             CP#11
   StoreLocal           r4
   Push                 r4
   PushNull
-  StoreFieldTOS        CP#11
+  StoreFieldTOS        CP#12
   Push                 r4
   PushNull
-  StoreFieldTOS        CP#13
+  StoreFieldTOS        CP#14
   Push                 r4
-  PushConstant         CP#15
-  StoreFieldTOS        CP#16
+  PushConstant         CP#16
+  StoreFieldTOS        CP#17
   Push                 r4
   PushConstant         CP#0
-  StoreFieldTOS        CP#18
+  StoreFieldTOS        CP#19
   Push                 r4
   Push                 r0
   StoreFieldTOS        CP#1
   PopLocal             r3
   Push                 r3
   PushInt              10
-  InstanceCall         2, CP#24
+  DynamicCall          2, CP#25
   Drop1
   Push                 r3
   PushInt              11
-  InstanceCall         2, CP#25
+  DynamicCall          2, CP#26
   Drop1
   Push                 r2
-  PushConstant         CP#26
-  IndirectStaticCall   1, CP#7
-  Drop1
-  Push                 r0
-  LoadContextVar       0, 2
   PushConstant         CP#27
   IndirectStaticCall   1, CP#7
   Drop1
   Push                 r0
-  LoadContextVar       0, 1
+  LoadContextVar       0, 2
   PushConstant         CP#28
   IndirectStaticCall   1, CP#7
   Drop1
   Push                 r0
+  LoadContextVar       0, 1
+  PushConstant         CP#29
+  IndirectStaticCall   1, CP#7
+  Drop1
+  Push                 r0
   PushInt              42
   StoreContextVar      0, 3
-  Allocate             CP#10
+  Allocate             CP#11
   StoreLocal           r3
   Push                 r3
   PushNull
-  StoreFieldTOS        CP#11
+  StoreFieldTOS        CP#12
   Push                 r3
   PushNull
-  StoreFieldTOS        CP#13
+  StoreFieldTOS        CP#14
   Push                 r3
-  PushConstant         CP#15
-  StoreFieldTOS        CP#16
+  PushConstant         CP#16
+  StoreFieldTOS        CP#17
   Push                 r3
-  PushConstant         CP#29
-  StoreFieldTOS        CP#18
+  PushConstant         CP#30
+  StoreFieldTOS        CP#19
   Push                 r3
   Push                 r0
   StoreFieldTOS        CP#1
   PopLocal             r2
   Push                 r2
-  InstanceCall         1, CP#32
+  DynamicCall          1, CP#34
   Drop1
   PushNull
   ReturnTOS
@@ -598,31 +598,33 @@
   [5] = SubtypeTestCache
   [6] = ClosureFunction 1
   [7] = ArgDesc num-args 1, num-type-args 0, names []
-  [8] = ICData get target-name 'get:foo', arg-desc CP#7
-  [9] = EndClosureFunctionScope
-  [10] = Class dart:core::_Closure
-  [11] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
-  [12] = Reserved
-  [13] = InstanceField dart:core::_Closure::_function_type_arguments (field)
-  [14] = Reserved
-  [15] = EmptyTypeArguments
-  [16] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [17] = Reserved
-  [18] = InstanceField dart:core::_Closure::_function (field)
-  [19] = Reserved
-  [20] = ICData dynamic target-name 'call', arg-desc CP#7
-  [21] = StaticICData target 'dart:core::print', arg-desc CP#7
-  [22] = EndClosureFunctionScope
-  [23] = ArgDesc num-args 2, num-type-args 0, names []
-  [24] = ICData dynamic target-name 'call', arg-desc CP#23
-  [25] = ICData dynamic target-name 'call', arg-desc CP#23
-  [26] = StaticICData target 'dart:core::print', arg-desc CP#7
+  [8] = InterfaceCall get target-name 'get:foo', arg-desc CP#7
+  [9] = Reserved
+  [10] = EndClosureFunctionScope
+  [11] = Class dart:core::_Closure
+  [12] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+  [13] = Reserved
+  [14] = InstanceField dart:core::_Closure::_function_type_arguments (field)
+  [15] = Reserved
+  [16] = EmptyTypeArguments
+  [17] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
+  [18] = Reserved
+  [19] = InstanceField dart:core::_Closure::_function (field)
+  [20] = Reserved
+  [21] = ICData dynamic target-name 'call', arg-desc CP#7
+  [22] = StaticICData target 'dart:core::print', arg-desc CP#7
+  [23] = EndClosureFunctionScope
+  [24] = ArgDesc num-args 2, num-type-args 0, names []
+  [25] = ICData dynamic target-name 'call', arg-desc CP#24
+  [26] = ICData dynamic target-name 'call', arg-desc CP#24
   [27] = StaticICData target 'dart:core::print', arg-desc CP#7
   [28] = StaticICData target 'dart:core::print', arg-desc CP#7
-  [29] = ClosureFunction 2
-  [30] = ICData set target-name 'set:foo', arg-desc CP#23
-  [31] = EndClosureFunctionScope
-  [32] = ICData dynamic target-name 'call', arg-desc CP#7
+  [29] = StaticICData target 'dart:core::print', arg-desc CP#7
+  [30] = ClosureFunction 2
+  [31] = InterfaceCall set target-name 'set:foo', arg-desc CP#24
+  [32] = Reserved
+  [33] = EndClosureFunctionScope
+  [34] = ICData dynamic target-name 'call', arg-desc CP#7
 }
 Closure #lib::B::topLevel::<anonymous closure> (dart:core::int y) -> dart:core::Null
 ClosureBytecode {
@@ -663,30 +665,30 @@
   Push                 r0
   PushInt              4
   StoreContextVar      1, 1
-  Allocate             CP#10
+  Allocate             CP#11
   StoreLocal           r2
   Push                 r2
   PushNull
-  StoreFieldTOS        CP#11
+  StoreFieldTOS        CP#12
   Push                 r2
   PushNull
-  StoreFieldTOS        CP#13
+  StoreFieldTOS        CP#14
   Push                 r2
-  PushConstant         CP#15
-  StoreFieldTOS        CP#16
+  PushConstant         CP#16
+  StoreFieldTOS        CP#17
   Push                 r2
   PushConstant         CP#6
-  StoreFieldTOS        CP#18
+  StoreFieldTOS        CP#19
   Push                 r2
   Push                 r0
   StoreFieldTOS        CP#1
   PopLocal             r3
   Push                 r3
-  InstanceCall         1, CP#20
+  DynamicCall          1, CP#21
   Drop1
   Push                 r0
   LoadContextVar       1, 1
-  PushConstant         CP#21
+  PushConstant         CP#22
   IndirectStaticCall   1, CP#7
   Drop1
 L1:
@@ -714,7 +716,7 @@
   Push                 r0
   LoadContextParent
   LoadContextVar       0, 0
-  InstanceCall         1, CP#8
+  InterfaceCall        1, CP#8
   Push                 r0
   LoadContextVar       1, 0
   AddInt
@@ -735,7 +737,7 @@
   LoadContextVar       0, 0
   Push                 r0
   LoadContextVar       0, 3
-  InstanceCall         2, CP#30
+  InterfaceCall        2, CP#31
   Drop1
   PushNull
   ReturnTOS
@@ -855,7 +857,7 @@
   Push                 r3
   Push                 r0
   StoreFieldTOS        CP#5
-  InstanceCall         2, CP#18
+  InterfaceCall        2, CP#18
   Drop1
   Push                 r4
   Allocate             CP#8
@@ -870,12 +872,12 @@
   PushConstant         CP#13
   StoreFieldTOS        CP#14
   Push                 r3
-  PushConstant         CP#19
+  PushConstant         CP#20
   StoreFieldTOS        CP#16
   Push                 r3
   Push                 r0
   StoreFieldTOS        CP#5
-  InstanceCall         2, CP#24
+  InterfaceCall        2, CP#18
   Drop1
   Push                 r0
   CloneContext         1, 1
@@ -919,13 +921,13 @@
   [15] = Reserved
   [16] = InstanceField dart:core::_Closure::_function (field)
   [17] = Reserved
-  [18] = ICData target-name 'add', arg-desc CP#1
-  [19] = ClosureFunction 1
-  [20] = Type dart:core::int
-  [21] = String 'ii'
-  [22] = SubtypeTestCache
-  [23] = EndClosureFunctionScope
-  [24] = ICData target-name 'add', arg-desc CP#1
+  [18] = InterfaceCall target-name 'add', arg-desc CP#1
+  [19] = Reserved
+  [20] = ClosureFunction 1
+  [21] = Type dart:core::int
+  [22] = String 'ii'
+  [23] = SubtypeTestCache
+  [24] = EndClosureFunctionScope
 }
 Closure #lib::C::testForLoop::<anonymous closure> () -> dart:core::int
 ClosureBytecode {
@@ -952,11 +954,11 @@
   LoadFieldTOS         CP#5
   PopLocal             r0
   Push                 FP[-5]
-  PushConstant         CP#20
-  PushNull
-  PushNull
   PushConstant         CP#21
-  AssertAssignable     1, CP#22
+  PushNull
+  PushNull
+  PushConstant         CP#22
+  AssertAssignable     1, CP#23
   Drop1
   Push                 r0
   Push                 FP[-5]
@@ -985,43 +987,43 @@
   Entry                5
   CheckStack           0
   Push                 FP[-5]
-  InstanceCall         1, CP#1
+  InterfaceCall        1, CP#1
   PopLocal             r2
 L2:
   CheckStack           1
   Push                 r2
-  InstanceCall         1, CP#2
+  InterfaceCall        1, CP#3
   JumpIfFalse          L1
   AllocateContext      0, 1
   PopLocal             r0
   Push                 r0
   Push                 r2
-  InstanceCall         1, CP#3
+  InterfaceCall        1, CP#5
   StoreContextVar      0, 0
-  Allocate             CP#8
+  Allocate             CP#11
   StoreLocal           r4
   Push                 r4
   PushNull
-  StoreFieldTOS        CP#9
+  StoreFieldTOS        CP#12
   Push                 r4
   PushNull
-  StoreFieldTOS        CP#11
-  Push                 r4
-  PushConstant         CP#13
   StoreFieldTOS        CP#14
   Push                 r4
-  PushConstant         CP#4
-  StoreFieldTOS        CP#16
+  PushConstant         CP#16
+  StoreFieldTOS        CP#17
+  Push                 r4
+  PushConstant         CP#7
+  StoreFieldTOS        CP#19
   Push                 r4
   Push                 r0
-  StoreFieldTOS        CP#5
+  StoreFieldTOS        CP#8
   PopLocal             r3
   Push                 r3
-  InstanceCall         1, CP#18
+  DynamicCall          1, CP#21
   Drop1
   Push                 r0
   LoadContextVar       0, 0
-  PushConstant         CP#19
+  PushConstant         CP#22
   IndirectStaticCall   1, CP#0
   Drop1
   Push                 r0
@@ -1034,32 +1036,35 @@
 }
 ConstantPool {
   [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = ICData get target-name 'get:iterator', arg-desc CP#0
-  [2] = ICData target-name 'moveNext', arg-desc CP#0
-  [3] = ICData get target-name 'get:current', arg-desc CP#0
-  [4] = ClosureFunction 0
-  [5] = InstanceField dart:core::_Closure::_context (field)
+  [1] = InterfaceCall get target-name 'get:iterator', arg-desc CP#0
+  [2] = Reserved
+  [3] = InterfaceCall target-name 'moveNext', arg-desc CP#0
+  [4] = Reserved
+  [5] = InterfaceCall get target-name 'get:current', arg-desc CP#0
   [6] = Reserved
-  [7] = EndClosureFunctionScope
-  [8] = Class dart:core::_Closure
-  [9] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
-  [10] = Reserved
-  [11] = InstanceField dart:core::_Closure::_function_type_arguments (field)
-  [12] = Reserved
-  [13] = EmptyTypeArguments
-  [14] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
+  [7] = ClosureFunction 0
+  [8] = InstanceField dart:core::_Closure::_context (field)
+  [9] = Reserved
+  [10] = EndClosureFunctionScope
+  [11] = Class dart:core::_Closure
+  [12] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+  [13] = Reserved
+  [14] = InstanceField dart:core::_Closure::_function_type_arguments (field)
   [15] = Reserved
-  [16] = InstanceField dart:core::_Closure::_function (field)
-  [17] = Reserved
-  [18] = ICData dynamic target-name 'call', arg-desc CP#0
-  [19] = StaticICData target 'dart:core::print', arg-desc CP#0
+  [16] = EmptyTypeArguments
+  [17] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
+  [18] = Reserved
+  [19] = InstanceField dart:core::_Closure::_function (field)
+  [20] = Reserved
+  [21] = ICData dynamic target-name 'call', arg-desc CP#0
+  [22] = StaticICData target 'dart:core::print', arg-desc CP#0
 }
 Closure #lib::C::testForInLoop::<anonymous closure> () -> dart:core::Null
 ClosureBytecode {
   EntryFixed           1, 3
   CheckStack           0
   Push                 FP[-5]
-  LoadFieldTOS         CP#5
+  LoadFieldTOS         CP#8
   PopLocal             r0
   Push                 r0
   Push                 r0
@@ -1202,7 +1207,7 @@
   PopLocal             r2
   Push                 r2
   PushInt              3
-  InstanceCall         2, CP#18
+  DynamicCall          2, CP#18
   Drop1
   Push                 r0
   LoadContextVar       0, 0
@@ -1359,20 +1364,20 @@
   PushConstant         CP#4
   IndirectStaticCall   1, CP#3
   Drop1
-  InstanceCall         2, CP#6
+  InterfaceCall        2, CP#6
   Drop1
-  PushConstant         CP#7
+  PushConstant         CP#8
   PushConstant         CP#2
   PushConstant         CP#1
   AllocateT
   StoreLocal           r0
   Push                 r0
-  PushConstant         CP#8
+  PushConstant         CP#9
   IndirectStaticCall   1, CP#3
   Drop1
-  InstanceCall         2, CP#9
+  InterfaceCall        2, CP#6
   Drop1
-  PushConstant         CP#7
+  PushConstant         CP#8
   PushConstant         CP#10
   PushConstant         CP#1
   AllocateT
@@ -1381,7 +1386,7 @@
   PushConstant         CP#11
   IndirectStaticCall   1, CP#3
   Drop1
-  InstanceCall         2, CP#12
+  InterfaceCall        2, CP#6
   Drop1
   PushNull
   ReturnTOS
@@ -1393,13 +1398,12 @@
   [3] = ArgDesc num-args 1, num-type-args 0, names []
   [4] = StaticICData target '#lib::A::'' (constructor)', arg-desc CP#3
   [5] = ArgDesc num-args 1, num-type-args 2, names []
-  [6] = ICData target-name 'foo', arg-desc CP#5
-  [7] = TypeArgs [dart:core::List < #lib::C3 >, dart:core::List < #lib::C4 >]
-  [8] = StaticICData target '#lib::A::'' (constructor)', arg-desc CP#3
-  [9] = ICData target-name 'foo', arg-desc CP#5
+  [6] = InterfaceCall target-name 'foo', arg-desc CP#5
+  [7] = Reserved
+  [8] = TypeArgs [dart:core::List < #lib::C3 >, dart:core::List < #lib::C4 >]
+  [9] = StaticICData target '#lib::A::'' (constructor)', arg-desc CP#3
   [10] = TypeArgumentsForInstanceAllocation #lib::A [dart:core::List < #lib::C1 >, dart:core::List < #lib::C2 >]
   [11] = StaticICData target '#lib::A::'' (constructor)', arg-desc CP#3
-  [12] = ICData target-name 'foo', arg-desc CP#5
 }
 ]static method callA() → void {
   new self::A::•<self::C1, self::C2>().{self::A::foo}<self::C3, self::C4>();
diff --git a/pkg/vm/testcases/bytecode/literals.dart.expect b/pkg/vm/testcases/bytecode/literals.dart.expect
index 233eed7..4649642 100644
--- a/pkg/vm/testcases/bytecode/literals.dart.expect
+++ b/pkg/vm/testcases/bytecode/literals.dart.expect
@@ -483,15 +483,15 @@
   Push                 r0
   PushInt              1
   Push                 FP[-5]
-  InstanceCall         1, CP#7
+  InterfaceCall        1, CP#7
   StoreIndexedTOS
   Push                 r0
   PushInt              2
-  PushConstant         CP#8
-  StoreIndexedTOS
   PushConstant         CP#9
-  IndirectStaticCall   2, CP#1
+  StoreIndexedTOS
   PushConstant         CP#10
+  IndirectStaticCall   2, CP#1
+  PushConstant         CP#11
   IndirectStaticCall   1, CP#3
   Drop1
   PushNull
@@ -505,10 +505,11 @@
   [4] = StaticICData target 'dart:core::print', arg-desc CP#3
   [5] = TypeArgs [dart:core::String]
   [6] = String 'a'
-  [7] = ICData target-name 'toString', arg-desc CP#3
-  [8] = String 'b'
-  [9] = StaticICData target 'dart:core::List::_fromLiteral (constructor)', arg-desc CP#1
-  [10] = StaticICData target 'dart:core::print', arg-desc CP#3
+  [7] = InterfaceCall target-name 'toString', arg-desc CP#3
+  [8] = Reserved
+  [9] = String 'b'
+  [10] = StaticICData target 'dart:core::List::_fromLiteral (constructor)', arg-desc CP#1
+  [11] = StaticICData target 'dart:core::print', arg-desc CP#3
 }
 ]static method test_list_literal(core::int a) → void {
   core::print(<core::int>[1, a, 3]);
@@ -561,29 +562,29 @@
   Push                 r1
   PushInt              2
   Push                 FP[-6]
-  InstanceCall         1, CP#8
+  InterfaceCall        1, CP#8
   StoreIndexedTOS
   Push                 r1
   PushInt              3
   PushInt              3
   StoreIndexedTOS
-  PushConstant         CP#9
-  IndirectStaticCall   2, CP#2
   PushConstant         CP#10
-  IndirectStaticCall   1, CP#4
-  Drop1
-  PushNull
-  Push                 r0
-  InstantiateTypeArgumentsTOS 0, CP#11
-  PushConstant         CP#12
-  PushConstant         CP#13
   IndirectStaticCall   2, CP#2
-  PushConstant         CP#14
+  PushConstant         CP#11
   IndirectStaticCall   1, CP#4
   Drop1
   PushNull
   Push                 r0
-  InstantiateTypeArgumentsTOS 0, CP#15
+  InstantiateTypeArgumentsTOS 0, CP#12
+  PushConstant         CP#13
+  PushConstant         CP#14
+  IndirectStaticCall   2, CP#2
+  PushConstant         CP#15
+  IndirectStaticCall   1, CP#4
+  Drop1
+  PushNull
+  Push                 r0
+  InstantiateTypeArgumentsTOS 0, CP#16
   PushConstant         CP#1
   PushInt              2
   CreateArrayTOS
@@ -596,9 +597,9 @@
   PushInt              1
   PushInt              4
   StoreIndexedTOS
-  PushConstant         CP#16
-  IndirectStaticCall   2, CP#2
   PushConstant         CP#17
+  IndirectStaticCall   2, CP#2
+  PushConstant         CP#18
   IndirectStaticCall   1, CP#4
   Drop1
   PushNull
@@ -613,16 +614,17 @@
   [5] = StaticICData target 'dart:core::print', arg-desc CP#4
   [6] = TypeArgs [dart:core::String, dart:core::int]
   [7] = String 'foo'
-  [8] = ICData target-name 'toString', arg-desc CP#4
-  [9] = StaticICData target 'dart:core::Map::_fromLiteral (constructor)', arg-desc CP#2
-  [10] = StaticICData target 'dart:core::print', arg-desc CP#4
-  [11] = TypeArgs [dart:core::String, #lib::test_map_literal::TypeParam/0]
-  [12] = List type-arg dynamic, entries CP# []
-  [13] = StaticICData target 'dart:core::Map::_fromLiteral (constructor)', arg-desc CP#2
-  [14] = StaticICData target 'dart:core::print', arg-desc CP#4
-  [15] = TypeArgs [#lib::test_map_literal::TypeParam/0, dart:core::int]
-  [16] = StaticICData target 'dart:core::Map::_fromLiteral (constructor)', arg-desc CP#2
-  [17] = StaticICData target 'dart:core::print', arg-desc CP#4
+  [8] = InterfaceCall target-name 'toString', arg-desc CP#4
+  [9] = Reserved
+  [10] = StaticICData target 'dart:core::Map::_fromLiteral (constructor)', arg-desc CP#2
+  [11] = StaticICData target 'dart:core::print', arg-desc CP#4
+  [12] = TypeArgs [dart:core::String, #lib::test_map_literal::TypeParam/0]
+  [13] = List type-arg dynamic, entries CP# []
+  [14] = StaticICData target 'dart:core::Map::_fromLiteral (constructor)', arg-desc CP#2
+  [15] = StaticICData target 'dart:core::print', arg-desc CP#4
+  [16] = TypeArgs [#lib::test_map_literal::TypeParam/0, dart:core::int]
+  [17] = StaticICData target 'dart:core::Map::_fromLiteral (constructor)', arg-desc CP#2
+  [18] = StaticICData target 'dart:core::print', arg-desc CP#4
 }
 ]static method test_map_literal<T extends core::Object = dynamic>(core::int a, core::int b, self::test_map_literal::T c) → void {
   core::print(<core::int, core::int>{1: a, b: 2});
diff --git a/pkg/vm/testcases/bytecode/loops.dart.expect b/pkg/vm/testcases/bytecode/loops.dart.expect
index b3714bd..4fbdb3b 100644
--- a/pkg/vm/testcases/bytecode/loops.dart.expect
+++ b/pkg/vm/testcases/bytecode/loops.dart.expect
@@ -14,13 +14,13 @@
   CheckStack           1
   Push                 r1
   Push                 FP[-5]
-  InstanceCall         1, CP#1
+  InterfaceCall        1, CP#1
   CompareIntLt
   JumpIfFalse          L1
   Push                 r0
   Push                 FP[-5]
   Push                 r1
-  InstanceCall         2, CP#3
+  InterfaceCall        2, CP#4
   AddInt
   PopLocal             r0
   Push                 r1
@@ -35,9 +35,11 @@
 }
 ConstantPool {
   [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = ICData get target-name 'get:length', arg-desc CP#0
-  [2] = ArgDesc num-args 2, num-type-args 0, names []
-  [3] = ICData target-name '[]', arg-desc CP#2
+  [1] = InterfaceCall get target-name 'get:length', arg-desc CP#0
+  [2] = Reserved
+  [3] = ArgDesc num-args 2, num-type-args 0, names []
+  [4] = InterfaceCall target-name '[]', arg-desc CP#3
+  [5] = Reserved
 }
 ]static method test_for(core::List<core::int> list) → core::int {
   core::int sum = 0;
@@ -62,7 +64,7 @@
   JumpIfFalse          L1
   Push                 r1
   Push                 FP[-5]
-  InstanceCall         1, CP#1
+  InterfaceCall        1, CP#1
   CompareIntGe
   JumpIfFalse          L2
   Jump                 L1
@@ -70,7 +72,7 @@
   Push                 r0
   Push                 FP[-5]
   Push                 r1
-  InstanceCall         2, CP#3
+  InterfaceCall        2, CP#4
   AddInt
   PopLocal             r0
   Push                 r1
@@ -85,9 +87,11 @@
 }
 ConstantPool {
   [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = ICData get target-name 'get:length', arg-desc CP#0
-  [2] = ArgDesc num-args 2, num-type-args 0, names []
-  [3] = ICData target-name '[]', arg-desc CP#2
+  [1] = InterfaceCall get target-name 'get:length', arg-desc CP#0
+  [2] = Reserved
+  [3] = ArgDesc num-args 2, num-type-args 0, names []
+  [4] = InterfaceCall target-name '[]', arg-desc CP#3
+  [5] = Reserved
 }
 ]static method test_for_break(core::List<core::int> list) → core::int {
   core::int sum = 0;
@@ -113,7 +117,7 @@
   CheckStack           1
   Push                 r1
   Push                 FP[-5]
-  InstanceCall         1, CP#1
+  InterfaceCall        1, CP#1
   CompareIntLt
   JumpIfFalse          L1
   Push                 r1
@@ -125,7 +129,7 @@
   Push                 r0
   Push                 FP[-5]
   Push                 r1
-  InstanceCall         2, CP#3
+  InterfaceCall        2, CP#4
   AddInt
   PopLocal             r0
 L3:
@@ -141,9 +145,11 @@
 }
 ConstantPool {
   [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = ICData get target-name 'get:length', arg-desc CP#0
-  [2] = ArgDesc num-args 2, num-type-args 0, names []
-  [3] = ICData target-name '[]', arg-desc CP#2
+  [1] = InterfaceCall get target-name 'get:length', arg-desc CP#0
+  [2] = Reserved
+  [3] = ArgDesc num-args 2, num-type-args 0, names []
+  [4] = InterfaceCall target-name '[]', arg-desc CP#3
+  [5] = Reserved
 }
 ]static method test_for_continue(core::List<core::int> list) → core::int {
   core::int sum = 0;
@@ -169,7 +175,7 @@
   CheckStack           1
   Push                 r1
   Push                 FP[-5]
-  InstanceCall         1, CP#1
+  InterfaceCall        1, CP#1
   CompareIntLt
   JumpIfFalse          L1
   Push                 r0
@@ -182,7 +188,7 @@
   StoreLocal           r1
   PopLocal             r3
   Push                 r2
-  InstanceCall         2, CP#3
+  InterfaceCall        2, CP#4
   AddInt
   PopLocal             r0
   Jump                 L2
@@ -192,9 +198,11 @@
 }
 ConstantPool {
   [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = ICData get target-name 'get:length', arg-desc CP#0
-  [2] = ArgDesc num-args 2, num-type-args 0, names []
-  [3] = ICData target-name '[]', arg-desc CP#2
+  [1] = InterfaceCall get target-name 'get:length', arg-desc CP#0
+  [2] = Reserved
+  [3] = ArgDesc num-args 2, num-type-args 0, names []
+  [4] = InterfaceCall target-name '[]', arg-desc CP#3
+  [5] = Reserved
 }
 ]static method test_while(core::List<core::int> list) → core::int {
   core::int sum = 0;
@@ -217,7 +225,7 @@
   Push                 r0
   Push                 FP[-5]
   Push                 r1
-  InstanceCall         2, CP#1
+  InterfaceCall        2, CP#1
   AddInt
   PopLocal             r0
   Push                 r1
@@ -226,7 +234,7 @@
   PopLocal             r1
   Push                 r1
   Push                 FP[-5]
-  InstanceCall         1, CP#3
+  InterfaceCall        1, CP#4
   CompareIntLt
   JumpIfTrue           L1
   Push                 r0
@@ -234,9 +242,11 @@
 }
 ConstantPool {
   [0] = ArgDesc num-args 2, num-type-args 0, names []
-  [1] = ICData target-name '[]', arg-desc CP#0
-  [2] = ArgDesc num-args 1, num-type-args 0, names []
-  [3] = ICData get target-name 'get:length', arg-desc CP#2
+  [1] = InterfaceCall target-name '[]', arg-desc CP#0
+  [2] = Reserved
+  [3] = ArgDesc num-args 1, num-type-args 0, names []
+  [4] = InterfaceCall get target-name 'get:length', arg-desc CP#3
+  [5] = Reserved
 }
 ]static method test_do_while(core::List<core::int> list) → core::int {
   core::int sum = 0;
@@ -255,15 +265,15 @@
   PushInt              0
   PopLocal             r0
   Push                 FP[-5]
-  InstanceCall         1, CP#1
+  InterfaceCall        1, CP#1
   PopLocal             r1
 L2:
   CheckStack           1
   Push                 r1
-  InstanceCall         1, CP#2
+  InterfaceCall        1, CP#3
   JumpIfFalse          L1
   Push                 r1
-  InstanceCall         1, CP#3
+  InterfaceCall        1, CP#5
   PopLocal             r2
   Push                 r0
   Push                 r2
@@ -276,9 +286,12 @@
 }
 ConstantPool {
   [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = ICData get target-name 'get:iterator', arg-desc CP#0
-  [2] = ICData target-name 'moveNext', arg-desc CP#0
-  [3] = ICData get target-name 'get:current', arg-desc CP#0
+  [1] = InterfaceCall get target-name 'get:iterator', arg-desc CP#0
+  [2] = Reserved
+  [3] = InterfaceCall target-name 'moveNext', arg-desc CP#0
+  [4] = Reserved
+  [5] = InterfaceCall get target-name 'get:current', arg-desc CP#0
+  [6] = Reserved
 }
 ]static method test_for_in(core::List<core::int> list) → core::int {
   core::int sum = 0;
@@ -296,15 +309,15 @@
   PushInt              42
   PopLocal             r1
   Push                 FP[-5]
-  InstanceCall         1, CP#1
+  InterfaceCall        1, CP#1
   PopLocal             r2
 L2:
   CheckStack           1
   Push                 r2
-  InstanceCall         1, CP#2
+  InterfaceCall        1, CP#3
   JumpIfFalse          L1
   Push                 r2
-  InstanceCall         1, CP#3
+  InterfaceCall        1, CP#5
   PopLocal             r3
   Push                 r3
   PopLocal             r1
@@ -319,9 +332,12 @@
 }
 ConstantPool {
   [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = ICData get target-name 'get:iterator', arg-desc CP#0
-  [2] = ICData target-name 'moveNext', arg-desc CP#0
-  [3] = ICData get target-name 'get:current', arg-desc CP#0
+  [1] = InterfaceCall get target-name 'get:iterator', arg-desc CP#0
+  [2] = Reserved
+  [3] = InterfaceCall target-name 'moveNext', arg-desc CP#0
+  [4] = Reserved
+  [5] = InterfaceCall get target-name 'get:current', arg-desc CP#0
+  [6] = Reserved
 }
 ]static method test_for_in_with_outer_var(core::List<core::int> list) → core::int {
   core::int sum = 0;
diff --git a/pkg/vm/testcases/bytecode/super_calls.dart.expect b/pkg/vm/testcases/bytecode/super_calls.dart.expect
index 9ee6e1e..346cd8a 100644
--- a/pkg/vm/testcases/bytecode/super_calls.dart.expect
+++ b/pkg/vm/testcases/bytecode/super_calls.dart.expect
@@ -132,7 +132,7 @@
   PushConstant         CP#2
   IndirectStaticCall   1, CP#1
   PushConstant         CP#3
-  InstanceCall         3, CP#5
+  DynamicCall          3, CP#5
   ReturnTOS
 }
 ConstantPool {
@@ -347,7 +347,7 @@
   PushConstant         CP#7
   IndirectStaticCall   2, CP#6
   PushConstant         CP#8
-  InstanceCall         3, CP#10
+  DynamicCall          3, CP#10
   ReturnTOS
 }
 ConstantPool {
diff --git a/pkg/vm/testcases/bytecode/switch.dart.expect b/pkg/vm/testcases/bytecode/switch.dart.expect
index fe265d6..93301c3 100644
--- a/pkg/vm/testcases/bytecode/switch.dart.expect
+++ b/pkg/vm/testcases/bytecode/switch.dart.expect
@@ -12,15 +12,15 @@
   PopLocal             r1
   Push                 r1
   PushInt              1
-  InstanceCall         2, CP#1
+  InterfaceCall        2, CP#1
   JumpIfTrue           L1
   Push                 r1
   PushInt              2
-  InstanceCall         2, CP#2
+  InterfaceCall        2, CP#1
   JumpIfTrue           L2
   Push                 r1
   PushInt              3
-  InstanceCall         2, CP#3
+  InterfaceCall        2, CP#1
   JumpIfTrue           L3
   Jump                 L4
 L1:
@@ -41,9 +41,8 @@
 }
 ConstantPool {
   [0] = ArgDesc num-args 2, num-type-args 0, names []
-  [1] = ICData target-name '==', arg-desc CP#0
-  [2] = ICData target-name '==', arg-desc CP#0
-  [3] = ICData target-name '==', arg-desc CP#0
+  [1] = InterfaceCall target-name '==', arg-desc CP#0
+  [2] = Reserved
 }
 ]static method foo1(core::int x) → core::int {
   core::int y;
@@ -80,27 +79,27 @@
   PopLocal             r1
   Push                 r1
   PushInt              1
-  InstanceCall         2, CP#1
+  InterfaceCall        2, CP#1
   JumpIfTrue           L1
   Push                 r1
   PushInt              2
-  InstanceCall         2, CP#2
+  InterfaceCall        2, CP#1
   JumpIfTrue           L1
   Push                 r1
   PushInt              3
-  InstanceCall         2, CP#3
+  InterfaceCall        2, CP#1
   JumpIfTrue           L1
   Push                 r1
   PushInt              4
-  InstanceCall         2, CP#4
+  InterfaceCall        2, CP#1
   JumpIfTrue           L2
   Push                 r1
   PushInt              5
-  InstanceCall         2, CP#5
+  InterfaceCall        2, CP#1
   JumpIfTrue           L2
   Push                 r1
   PushInt              6
-  InstanceCall         2, CP#6
+  InterfaceCall        2, CP#1
   JumpIfTrue           L2
   Jump                 L3
 L1:
@@ -120,12 +119,8 @@
 }
 ConstantPool {
   [0] = ArgDesc num-args 2, num-type-args 0, names []
-  [1] = ICData target-name '==', arg-desc CP#0
-  [2] = ICData target-name '==', arg-desc CP#0
-  [3] = ICData target-name '==', arg-desc CP#0
-  [4] = ICData target-name '==', arg-desc CP#0
-  [5] = ICData target-name '==', arg-desc CP#0
-  [6] = ICData target-name '==', arg-desc CP#0
+  [1] = InterfaceCall target-name '==', arg-desc CP#0
+  [2] = Reserved
 }
 ]static method foo2(core::int x) → core::int {
   core::int y;
@@ -165,27 +160,27 @@
   PopLocal             r1
   Push                 r1
   PushInt              1
-  InstanceCall         2, CP#1
+  InterfaceCall        2, CP#1
   JumpIfTrue           L1
   Push                 r1
   PushInt              2
-  InstanceCall         2, CP#2
+  InterfaceCall        2, CP#1
   JumpIfTrue           L1
   Push                 r1
   PushInt              3
-  InstanceCall         2, CP#3
+  InterfaceCall        2, CP#1
   JumpIfTrue           L1
   Push                 r1
   PushInt              4
-  InstanceCall         2, CP#4
+  InterfaceCall        2, CP#1
   JumpIfTrue           L2
   Push                 r1
   PushInt              5
-  InstanceCall         2, CP#5
+  InterfaceCall        2, CP#1
   JumpIfTrue           L2
   Push                 r1
   PushInt              6
-  InstanceCall         2, CP#6
+  InterfaceCall        2, CP#1
   JumpIfTrue           L2
   Jump                 L3
 L1:
@@ -205,12 +200,8 @@
 }
 ConstantPool {
   [0] = ArgDesc num-args 2, num-type-args 0, names []
-  [1] = ICData target-name '==', arg-desc CP#0
-  [2] = ICData target-name '==', arg-desc CP#0
-  [3] = ICData target-name '==', arg-desc CP#0
-  [4] = ICData target-name '==', arg-desc CP#0
-  [5] = ICData target-name '==', arg-desc CP#0
-  [6] = ICData target-name '==', arg-desc CP#0
+  [1] = InterfaceCall target-name '==', arg-desc CP#0
+  [2] = Reserved
 }
 ]static method foo3(core::int x) → core::int {
   core::int y;
diff --git a/pkg/vm/testcases/bytecode/try_blocks.dart.expect b/pkg/vm/testcases/bytecode/try_blocks.dart.expect
index e50ba42..e946fb1 100644
--- a/pkg/vm/testcases/bytecode/try_blocks.dart.expect
+++ b/pkg/vm/testcases/bytecode/try_blocks.dart.expect
@@ -78,17 +78,17 @@
   MoveSpecial          stackTrace, r1
   Push                 r0
   PushConstant         CP#3
-  InstanceCall         2, CP#5
+  InterfaceCall        2, CP#5
   JumpIfFalse          L2
-  PushConstant         CP#6
   PushConstant         CP#7
+  PushConstant         CP#8
   IndirectStaticCall   1, CP#1
   Drop1
   Jump                 L1
 L2:
   Push                 r0
-  PushConstant         CP#8
-  InstanceCall         2, CP#9
+  PushConstant         CP#9
+  InterfaceCall        2, CP#5
   JumpIfFalse          L3
   Push                 r0
   PopLocal             r2
@@ -113,7 +113,7 @@
 L3:
   Push                 r0
   PushConstant         CP#13
-  InstanceCall         2, CP#14
+  InterfaceCall        2, CP#5
   JumpIfFalse          L4
   Push                 r0
   PopLocal             r2
@@ -125,7 +125,7 @@
   StoreLocal           r4
   Push                 r4
   PushInt              0
-  PushConstant         CP#15
+  PushConstant         CP#14
   StoreIndexedTOS
   Push                 r4
   PushInt              1
@@ -133,15 +133,15 @@
   StoreIndexedTOS
   Push                 r4
   PushInt              2
-  PushConstant         CP#16
+  PushConstant         CP#15
   StoreIndexedTOS
   Push                 r4
   PushInt              3
   Push                 r3
   StoreIndexedTOS
-  PushConstant         CP#17
+  PushConstant         CP#16
   IndirectStaticCall   1, CP#1
-  PushConstant         CP#18
+  PushConstant         CP#17
   IndirectStaticCall   1, CP#1
   Drop1
   Jump                 L1
@@ -156,7 +156,7 @@
   StoreLocal           r4
   Push                 r4
   PushInt              0
-  PushConstant         CP#20
+  PushConstant         CP#19
   StoreIndexedTOS
   Push                 r4
   PushInt              1
@@ -164,15 +164,15 @@
   StoreIndexedTOS
   Push                 r4
   PushInt              2
-  PushConstant         CP#16
+  PushConstant         CP#15
   StoreIndexedTOS
   Push                 r4
   PushInt              3
   Push                 r3
   StoreIndexedTOS
-  PushConstant         CP#21
+  PushConstant         CP#20
   IndirectStaticCall   1, CP#1
-  PushConstant         CP#22
+  PushConstant         CP#21
   IndirectStaticCall   1, CP#1
   Drop1
   Jump                 L1
@@ -181,7 +181,7 @@
   ReturnTOS
 }
 ExceptionsTable {
-  try-index 0, outer -1, start 2, end 7, handler 7, needs-stack-trace, types [CP#3, CP#8, CP#13, CP#19]
+  try-index 0, outer -1, start 2, end 7, handler 7, needs-stack-trace, types [CP#3, CP#9, CP#13, CP#18]
 }
 ConstantPool {
   [0] = String 'danger!'
@@ -189,24 +189,23 @@
   [2] = StaticICData target 'dart:core::print', arg-desc CP#1
   [3] = Type dart:core::TypeError
   [4] = ArgDesc num-args 2, num-type-args 0, names []
-  [5] = ICData target-name '_simpleInstanceOf', arg-desc CP#4
-  [6] = String 'caught type error'
-  [7] = StaticICData target 'dart:core::print', arg-desc CP#1
-  [8] = Type dart:core::AssertionError
-  [9] = ICData target-name '_simpleInstanceOf', arg-desc CP#4
+  [5] = InterfaceCall target-name '_simpleInstanceOf', arg-desc CP#4
+  [6] = Reserved
+  [7] = String 'caught type error'
+  [8] = StaticICData target 'dart:core::print', arg-desc CP#1
+  [9] = Type dart:core::AssertionError
   [10] = String 'caught assertion error '
   [11] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#1
   [12] = StaticICData target 'dart:core::print', arg-desc CP#1
   [13] = Type dart:core::Error
-  [14] = ICData target-name '_simpleInstanceOf', arg-desc CP#4
-  [15] = String 'caught error '
-  [16] = String ' '
-  [17] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#1
-  [18] = StaticICData target 'dart:core::print', arg-desc CP#1
-  [19] = Type dynamic
-  [20] = String 'caught something '
-  [21] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#1
-  [22] = StaticICData target 'dart:core::print', arg-desc CP#1
+  [14] = String 'caught error '
+  [15] = String ' '
+  [16] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#1
+  [17] = StaticICData target 'dart:core::print', arg-desc CP#1
+  [18] = Type dynamic
+  [19] = String 'caught something '
+  [20] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#1
+  [21] = StaticICData target 'dart:core::print', arg-desc CP#1
 }
 ]static method testTryCatch2() → dynamic {
   try {
@@ -259,7 +258,7 @@
   StoreFieldTOS        CP#1
   PopLocal             r4
   Push                 r4
-  InstanceCall         1, CP#19
+  DynamicCall          1, CP#19
   Drop1
   Push                 r0
   LoadContextVar       0, 1
@@ -366,12 +365,13 @@
   [27] = StaticICData target 'dart:core::print', arg-desc CP#4
   [28] = Type dart:core::Error
   [29] = ArgDesc num-args 2, num-type-args 0, names []
-  [30] = ICData target-name '_simpleInstanceOf', arg-desc CP#29
-  [31] = String 'error '
-  [32] = String ', captured stack trace: '
-  [33] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#4
-  [34] = StaticICData target 'dart:core::print', arg-desc CP#4
-  [35] = EndClosureFunctionScope
+  [30] = InterfaceCall target-name '_simpleInstanceOf', arg-desc CP#29
+  [31] = Reserved
+  [32] = String 'error '
+  [33] = String ', captured stack trace: '
+  [34] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#4
+  [35] = StaticICData target 'dart:core::print', arg-desc CP#4
+  [36] = EndClosureFunctionScope
 }
 Closure #lib::testTryCatch3::foo () -> void
 ClosureBytecode {
@@ -436,7 +436,7 @@
   MoveSpecial          stackTrace, r3
   Push                 r2
   PushConstant         CP#28
-  InstanceCall         2, CP#30
+  InterfaceCall        2, CP#30
   JumpIfFalse          L2
   Push                 r2
   PopLocal             r4
@@ -446,7 +446,7 @@
   StoreLocal           r5
   Push                 r5
   PushInt              0
-  PushConstant         CP#31
+  PushConstant         CP#32
   StoreIndexedTOS
   Push                 r5
   PushInt              1
@@ -454,17 +454,17 @@
   StoreIndexedTOS
   Push                 r5
   PushInt              2
-  PushConstant         CP#32
+  PushConstant         CP#33
   StoreIndexedTOS
   Push                 r5
   PushInt              3
   Push                 r0
   LoadContextVar       0, 2
   StoreIndexedTOS
-  PushConstant         CP#33
-  IndirectStaticCall   1, CP#4
   PushConstant         CP#34
   IndirectStaticCall   1, CP#4
+  PushConstant         CP#35
+  IndirectStaticCall   1, CP#4
   Drop1
   Jump                 L1
 L2:
@@ -704,11 +704,11 @@
   PopLocal             r2
   Push                 r2
   PushInt              1
-  InstanceCall         2, CP#1
+  InterfaceCall        2, CP#1
   JumpIfTrue           L1
   Push                 r2
   PushInt              2
-  InstanceCall         2, CP#2
+  InterfaceCall        2, CP#1
   JumpIfTrue           L2
   Jump                 L3
 L1:
@@ -748,7 +748,7 @@
   StoreFieldTOS        CP#9
   PopLocal             r7
   Push                 r7
-  InstanceCall         1, CP#24
+  DynamicCall          1, CP#24
   Drop1
   Jump                 L4
 Try #1 end:
@@ -811,8 +811,8 @@
 }
 ConstantPool {
   [0] = ArgDesc num-args 2, num-type-args 0, names []
-  [1] = ICData target-name '==', arg-desc CP#0
-  [2] = ICData target-name '==', arg-desc CP#0
+  [1] = InterfaceCall target-name '==', arg-desc CP#0
+  [2] = Reserved
   [3] = String 'before try 1'
   [4] = ArgDesc num-args 1, num-type-args 0, names []
   [5] = StaticICData target 'dart:core::print', arg-desc CP#4
@@ -950,7 +950,7 @@
   IndirectStaticCall   1, CP#3
   Drop1
   Push                 r2
-  InstanceCall         1, CP#27
+  DynamicCall          1, CP#27
   Drop1
   Push                 r3
   Push                 r4
@@ -964,7 +964,7 @@
   IndirectStaticCall   1, CP#3
   Drop1
   Push                 r2
-  InstanceCall         1, CP#29
+  DynamicCall          1, CP#29
   Drop1
   Push                 r0
   LoadContextParent
diff --git a/pkg/vm/testcases/bytecode/type_ops.dart.expect b/pkg/vm/testcases/bytecode/type_ops.dart.expect
index 43203fc..04a4e32 100644
--- a/pkg/vm/testcases/bytecode/type_ops.dart.expect
+++ b/pkg/vm/testcases/bytecode/type_ops.dart.expect
@@ -106,23 +106,23 @@
   LoadTypeArgumentsField CP#0
   PushNull
   PushConstant         CP#1
-  InstanceCall         4, CP#3
+  InterfaceCall        4, CP#3
   JumpIfFalse          L1
-  PushConstant         CP#4
-  PushConstant         CP#6
-  IndirectStaticCall   1, CP#5
+  PushConstant         CP#5
+  PushConstant         CP#7
+  IndirectStaticCall   1, CP#6
   Drop1
 L1:
   Push                 FP[-5]
   Push                 FP[-6]
   LoadTypeArgumentsField CP#0
   PushNull
-  PushConstant         CP#7
-  InstanceCall         4, CP#8
+  PushConstant         CP#8
+  InterfaceCall        4, CP#3
   JumpIfFalse          L2
   PushConstant         CP#9
   PushConstant         CP#10
-  IndirectStaticCall   1, CP#5
+  IndirectStaticCall   1, CP#6
   Drop1
 L2:
   Push                 FP[-6]
@@ -133,7 +133,7 @@
   PushNull
   PushConstant         CP#12
   AssertAssignable     0, CP#13
-  InstanceCall         2, CP#15
+  InterfaceCall        2, CP#15
   Drop1
   PushNull
   ReturnTOS
@@ -142,19 +142,20 @@
   [0] = TypeArgumentsField #lib::D
   [1] = Type #lib::A < #lib::D::TypeParam/0 >
   [2] = ArgDesc num-args 4, num-type-args 0, names []
-  [3] = ICData target-name '_instanceOf', arg-desc CP#2
-  [4] = String '21'
-  [5] = ArgDesc num-args 1, num-type-args 0, names []
-  [6] = StaticICData target 'dart:core::print', arg-desc CP#5
-  [7] = Type #lib::C < dynamic, #lib::D::TypeParam/1, dart:core::List < #lib::D::TypeParam/0 > >
-  [8] = ICData target-name '_instanceOf', arg-desc CP#2
+  [3] = InterfaceCall target-name '_instanceOf', arg-desc CP#2
+  [4] = Reserved
+  [5] = String '21'
+  [6] = ArgDesc num-args 1, num-type-args 0, names []
+  [7] = StaticICData target 'dart:core::print', arg-desc CP#6
+  [8] = Type #lib::C < dynamic, #lib::D::TypeParam/1, dart:core::List < #lib::D::TypeParam/0 > >
   [9] = String '22'
-  [10] = StaticICData target 'dart:core::print', arg-desc CP#5
+  [10] = StaticICData target 'dart:core::print', arg-desc CP#6
   [11] = Type dart:core::Map < #lib::D::TypeParam/0, #lib::D::TypeParam/1 >
   [12] = String ''
   [13] = SubtypeTestCache
   [14] = ArgDesc num-args 2, num-type-args 0, names []
-  [15] = ICData set target-name 'set:foo', arg-desc CP#14
+  [15] = InterfaceCall set target-name 'set:foo', arg-desc CP#14
+  [16] = Reserved
 }
 ]  method foo2(dynamic y) → dynamic {
     if(y is self::A<self::D::P>) {
@@ -174,51 +175,52 @@
   PushNull
   Push                 r0
   PushConstant         CP#0
-  InstanceCall         4, CP#2
+  InterfaceCall        4, CP#2
   JumpIfFalse          L1
-  PushConstant         CP#3
-  PushConstant         CP#5
-  IndirectStaticCall   1, CP#4
+  PushConstant         CP#4
+  PushConstant         CP#6
+  IndirectStaticCall   1, CP#5
   Drop1
 L1:
   Push                 FP[-5]
   Push                 FP[-6]
-  LoadTypeArgumentsField CP#6
+  LoadTypeArgumentsField CP#7
   Push                 r0
-  PushConstant         CP#7
-  InstanceCall         4, CP#8
+  PushConstant         CP#8
+  InterfaceCall        4, CP#2
   JumpIfFalse          L2
   PushConstant         CP#9
   PushConstant         CP#10
-  IndirectStaticCall   1, CP#4
+  IndirectStaticCall   1, CP#5
   Drop1
 L2:
   Push                 FP[-5]
   PushConstant         CP#11
   Push                 FP[-6]
-  LoadTypeArgumentsField CP#6
+  LoadTypeArgumentsField CP#7
   Push                 r0
   PushConstant         CP#12
   AssertAssignable     0, CP#13
-  InstanceCall         1, CP#14
+  InterfaceCall        1, CP#14
   ReturnTOS
 }
 ConstantPool {
   [0] = Type #lib::A < #lib::D::foo3::TypeParam/0 >
   [1] = ArgDesc num-args 4, num-type-args 0, names []
-  [2] = ICData target-name '_instanceOf', arg-desc CP#1
-  [3] = String '31'
-  [4] = ArgDesc num-args 1, num-type-args 0, names []
-  [5] = StaticICData target 'dart:core::print', arg-desc CP#4
-  [6] = TypeArgumentsField #lib::D
-  [7] = Type #lib::C < dart:core::Map < #lib::D::foo3::TypeParam/0, #lib::D::TypeParam/0 >, dart:core::List < #lib::D::foo3::TypeParam/1 >, #lib::D::TypeParam/1 >
-  [8] = ICData target-name '_instanceOf', arg-desc CP#1
+  [2] = InterfaceCall target-name '_instanceOf', arg-desc CP#1
+  [3] = Reserved
+  [4] = String '31'
+  [5] = ArgDesc num-args 1, num-type-args 0, names []
+  [6] = StaticICData target 'dart:core::print', arg-desc CP#5
+  [7] = TypeArgumentsField #lib::D
+  [8] = Type #lib::C < dart:core::Map < #lib::D::foo3::TypeParam/0, #lib::D::TypeParam/0 >, dart:core::List < #lib::D::foo3::TypeParam/1 >, #lib::D::TypeParam/1 >
   [9] = String '32'
-  [10] = StaticICData target 'dart:core::print', arg-desc CP#4
+  [10] = StaticICData target 'dart:core::print', arg-desc CP#5
   [11] = Type dart:core::Map < #lib::D::foo3::TypeParam/1, #lib::D::TypeParam/1 >
   [12] = String ' in type cast'
   [13] = SubtypeTestCache
-  [14] = ICData get target-name 'get:values', arg-desc CP#4
+  [14] = InterfaceCall get target-name 'get:values', arg-desc CP#5
+  [15] = Reserved
 }
 ]  method foo3<T1 extends core::Object = dynamic, T2 extends core::Object = dynamic>(dynamic z) → dynamic {
     if(z is self::A<self::D::foo3::T1>) {
@@ -329,47 +331,49 @@
   CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#0
-  InstanceCall         2, CP#2
+  InterfaceCall        2, CP#2
   JumpIfFalse          L1
-  PushConstant         CP#3
-  PushConstant         CP#5
-  IndirectStaticCall   1, CP#4
+  PushConstant         CP#4
+  PushConstant         CP#6
+  IndirectStaticCall   1, CP#5
   Drop1
 L1:
   Push                 FP[-5]
   PushNull
   PushNull
-  PushConstant         CP#6
-  InstanceCall         4, CP#8
+  PushConstant         CP#7
+  InterfaceCall        4, CP#9
   JumpIfFalse          L2
-  PushConstant         CP#9
-  PushConstant         CP#10
-  IndirectStaticCall   1, CP#4
+  PushConstant         CP#11
+  PushConstant         CP#12
+  IndirectStaticCall   1, CP#5
   Drop1
 L2:
   Push                 FP[-5]
-  PushConstant         CP#11
+  PushConstant         CP#13
   PushNull
   PushNull
-  PushConstant         CP#12
-  AssertAssignable     0, CP#13
+  PushConstant         CP#14
+  AssertAssignable     0, CP#15
   ReturnTOS
 }
 ConstantPool {
   [0] = Type #lib::B
   [1] = ArgDesc num-args 2, num-type-args 0, names []
-  [2] = ICData target-name '_simpleInstanceOf', arg-desc CP#1
-  [3] = String '11'
-  [4] = ArgDesc num-args 1, num-type-args 0, names []
-  [5] = StaticICData target 'dart:core::print', arg-desc CP#4
-  [6] = Type #lib::C < dart:core::int, dart:core::Object, dynamic >
-  [7] = ArgDesc num-args 4, num-type-args 0, names []
-  [8] = ICData target-name '_instanceOf', arg-desc CP#7
-  [9] = String '12'
-  [10] = StaticICData target 'dart:core::print', arg-desc CP#4
-  [11] = Type #lib::A < dart:core::int >
-  [12] = String ' in type cast'
-  [13] = SubtypeTestCache
+  [2] = InterfaceCall target-name '_simpleInstanceOf', arg-desc CP#1
+  [3] = Reserved
+  [4] = String '11'
+  [5] = ArgDesc num-args 1, num-type-args 0, names []
+  [6] = StaticICData target 'dart:core::print', arg-desc CP#5
+  [7] = Type #lib::C < dart:core::int, dart:core::Object, dynamic >
+  [8] = ArgDesc num-args 4, num-type-args 0, names []
+  [9] = InterfaceCall target-name '_instanceOf', arg-desc CP#8
+  [10] = Reserved
+  [11] = String '12'
+  [12] = StaticICData target 'dart:core::print', arg-desc CP#5
+  [13] = Type #lib::A < dart:core::int >
+  [14] = String ' in type cast'
+  [15] = SubtypeTestCache
 }
 ]static method foo1(dynamic x) → dynamic {
   if(x is self::B) {
diff --git a/runtime/vm/compiler/assembler/disassembler_kbc.cc b/runtime/vm/compiler/assembler/disassembler_kbc.cc
index 9102f84..151429a 100644
--- a/runtime/vm/compiler/assembler/disassembler_kbc.cc
+++ b/runtime/vm/compiler/assembler/disassembler_kbc.cc
@@ -214,7 +214,8 @@
     case KernelBytecode::kLoadConstant:
     case KernelBytecode::kPushConstant:
     case KernelBytecode::kIndirectStaticCall:
-    case KernelBytecode::kInstanceCall:
+    case KernelBytecode::kInterfaceCall:
+    case KernelBytecode::kDynamicCall:
     case KernelBytecode::kStoreStaticTOS:
     case KernelBytecode::kPushStatic:
     case KernelBytecode::kAllocate:
diff --git a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
index 20cb6a0..a5723f9 100644
--- a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
@@ -701,7 +701,47 @@
   B->Push(call);
 }
 
-void BytecodeFlowGraphBuilder::BuildInstanceCall() {
+void BytecodeFlowGraphBuilder::BuildInterfaceCall() {
+  if (is_generating_interpreter()) {
+    UNIMPLEMENTED();  // TODO(alexmarkov): interpreter
+  }
+
+  const String& name = String::Cast(ConstantAt(DecodeOperandD()).value());
+  ASSERT(name.IsSymbol());
+
+  const Array& arg_desc_array =
+      Array::Cast(ConstantAt(DecodeOperandD(), 1).value());
+  const ArgumentsDescriptor arg_desc(arg_desc_array);
+
+  const intptr_t argc = DecodeOperandA().value();
+  const Token::Kind token_kind =
+      MethodTokenRecognizer::RecognizeTokenKind(name);
+
+  intptr_t checked_argument_count = 1;
+  if ((token_kind != Token::kILLEGAL) ||
+      (name.raw() ==
+       Library::PrivateCoreLibName(Symbols::_simpleInstanceOf()).raw())) {
+    intptr_t argument_count = arg_desc.Count();
+    ASSERT(argument_count <= 2);
+    checked_argument_count = argument_count;
+  }
+
+  const ArgumentArray arguments = GetArguments(argc);
+
+  // TODO(alexmarkov): store interface_target in bytecode and pass it here.
+
+  InstanceCallInstr* call = new (Z) InstanceCallInstr(
+      position_, name, token_kind, arguments, arg_desc.TypeArgsLen(),
+      Array::ZoneHandle(Z, arg_desc.GetArgumentNames()), checked_argument_count,
+      *ic_data_array_, B->GetNextDeoptId());
+
+  // TODO(alexmarkov): add type info - call->SetResultType()
+
+  code_ <<= call;
+  B->Push(call);
+}
+
+void BytecodeFlowGraphBuilder::BuildDynamicCall() {
   if (is_generating_interpreter()) {
     UNIMPLEMENTED();  // TODO(alexmarkov): interpreter
   }
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc
index 55f932f..f24f405 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.cc
+++ b/runtime/vm/compiler/frontend/bytecode_reader.cc
@@ -344,6 +344,7 @@
     kPartialTearOffInstantiation,
     kEmptyTypeArguments,
     kSymbol,
+    kInterfaceCall,
   };
 
   enum InvocationKind {
@@ -618,6 +619,22 @@
         Instance::Cast(obj).SetField(*symbol_name_field, name);
         obj = H.Canonicalize(Instance::Cast(obj));
       } break;
+      case ConstantPoolTag::kInterfaceCall: {
+        helper_->ReadByte();  // TODO(regis): Remove, unneeded.
+        name ^= ReadObject();
+        ASSERT(name.IsSymbol());
+        intptr_t arg_desc_index = helper_->ReadUInt();
+        ASSERT(arg_desc_index < i);
+        array ^= pool.ObjectAt(arg_desc_index);
+        // InterfaceCall constant occupies 2 entries.
+        // The first entry is used for selector name.
+        pool.SetTypeAt(i, ObjectPool::kTaggedObject, ObjectPool::kNotPatchable);
+        pool.SetObjectAt(i, name);
+        ++i;
+        ASSERT(i < obj_count);
+        // The second entry is used for arguments descriptor.
+        obj = array.raw();
+      } break;
       default:
         UNREACHABLE();
     }
diff --git a/runtime/vm/constants_kbc.h b/runtime/vm/constants_kbc.h
index 67772ab..15506e5 100644
--- a/runtime/vm/constants_kbc.h
+++ b/runtime/vm/constants_kbc.h
@@ -271,7 +271,16 @@
 //    SP[-(1+ArgC)], ..., SP[-1] and argument descriptor PP[D], which
 //    indicates whether the first argument is a type argument vector.
 //
-//  - InstanceCall ArgC, D
+//  - InterfaceCall ArgC, D
+//
+//    Lookup and invoke method using ICData in PP[D]
+//    with arguments SP[-(1+ArgC)], ..., SP[-1].
+//    Method has to be declared (explicitly or implicitly) in an interface
+//    implemented by a receiver, and passed arguments are valid for the
+//    interface method declaration.
+//    The ICData indicates whether the first argument is a type argument vector.
+//
+//  - DynamicCall ArgC, D
 //
 //    Lookup and invoke method using ICData in PP[D]
 //    with arguments SP[-(1+ArgC)], ..., SP[-1].
@@ -439,7 +448,8 @@
   V(JumpIfNull,                            T, tgt, ___, ___)                   \
   V(JumpIfNotNull,                         T, tgt, ___, ___)                   \
   V(IndirectStaticCall,                  A_D, num, num, ___)                   \
-  V(InstanceCall,                        A_D, num, num, ___)                   \
+  V(InterfaceCall,                       A_D, num, num, ___)                   \
+  V(DynamicCall,                         A_D, num, num, ___)                   \
   V(NativeCall,                            D, lit, ___, ___)                   \
   V(ReturnTOS,                             0, ___, ___, ___)                   \
   V(AssertAssignable,                    A_D, num, lit, ___)                   \
@@ -595,7 +605,8 @@
   DART_FORCE_INLINE static bool IsCallOpcode(KBCInstr instr) {
     switch (DecodeOpcode(instr)) {
       case KernelBytecode::kIndirectStaticCall:
-      case KernelBytecode::kInstanceCall:
+      case KernelBytecode::kInterfaceCall:
+      case KernelBytecode::kDynamicCall:
         return true;
 
       default:
diff --git a/runtime/vm/dart_entry.h b/runtime/vm/dart_entry.h
index 65a6f0d..23342d3 100644
--- a/runtime/vm/dart_entry.h
+++ b/runtime/vm/dart_entry.h
@@ -86,7 +86,6 @@
   enum {
     kTypeArgsLenIndex,
     kCountIndex,
-
     kPositionalCountIndex,
     kFirstNamedEntryIndex,
   };
diff --git a/runtime/vm/heap/marker.cc b/runtime/vm/heap/marker.cc
index 1dcd875..23fe586 100644
--- a/runtime/vm/heap/marker.cc
+++ b/runtime/vm/heap/marker.cc
@@ -479,6 +479,15 @@
 
 void GCMarker::Prologue() {
   isolate_->ReleaseStoreBuffers();
+
+#ifndef DART_PRECOMPILED_RUNTIME
+  if (isolate_->IsMutatorThreadScheduled()) {
+    Interpreter* interpreter = isolate_->mutator_thread()->interpreter();
+    if (interpreter != NULL) {
+      interpreter->MajorGC();
+    }
+  }
+#endif
 }
 
 void GCMarker::Epilogue() {
diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc
index 688dfeb..bdfec17 100644
--- a/runtime/vm/interpreter.cc
+++ b/runtime/vm/interpreter.cc
@@ -499,6 +499,66 @@
   return function;
 }
 
+void LookupCache::Clear() {
+  for (intptr_t i = 0; i < kNumEntries; i++) {
+    entries_[i].receiver_cid = kIllegalCid;
+  }
+}
+
+bool LookupCache::Lookup(intptr_t receiver_cid,
+                         RawString* function_name,
+                         RawFunction** target) const {
+  ASSERT(receiver_cid != kIllegalCid);  // Sentinel value.
+
+  const intptr_t hash =
+      receiver_cid ^ reinterpret_cast<intptr_t>(function_name);
+  const intptr_t probe1 = hash & kTableMask;
+  if (entries_[probe1].receiver_cid == receiver_cid &&
+      entries_[probe1].function_name == function_name) {
+    *target = entries_[probe1].target;
+    return true;
+  }
+
+  intptr_t probe2 = (hash >> 3) & kTableMask;
+  if (entries_[probe2].receiver_cid == receiver_cid &&
+      entries_[probe2].function_name == function_name) {
+    *target = entries_[probe2].target;
+    return true;
+  }
+
+  return false;
+}
+
+void LookupCache::Insert(intptr_t receiver_cid,
+                         RawString* function_name,
+                         RawFunction* target) {
+  // Otherwise we have to clear the cache or rehash on scavenges too.
+  ASSERT(function_name->IsOldObject());
+  ASSERT(target->IsOldObject());
+
+  const intptr_t hash =
+      receiver_cid ^ reinterpret_cast<intptr_t>(function_name);
+  const intptr_t probe1 = hash & kTableMask;
+  if (entries_[probe1].receiver_cid == kIllegalCid) {
+    entries_[probe1].receiver_cid = receiver_cid;
+    entries_[probe1].function_name = function_name;
+    entries_[probe1].target = target;
+    return;
+  }
+
+  const intptr_t probe2 = (hash >> 3) & kTableMask;
+  if (entries_[probe2].receiver_cid == kIllegalCid) {
+    entries_[probe2].receiver_cid = receiver_cid;
+    entries_[probe2].function_name = function_name;
+    entries_[probe2].target = target;
+    return;
+  }
+
+  entries_[probe1].receiver_cid = receiver_cid;
+  entries_[probe1].function_name = function_name;
+  entries_[probe1].target = target;
+}
+
 IntrinsicHandler Interpreter::intrinsics_[Interpreter::kIntrinsicCount];
 
 // Synchronization primitives support.
@@ -545,7 +605,7 @@
 }
 
 Interpreter::Interpreter()
-    : stack_(NULL), fp_(NULL), pp_(NULL), argdesc_(NULL) {
+    : stack_(NULL), fp_(NULL), pp_(NULL), argdesc_(NULL), lookup_cache_() {
   // Setup interpreter support first. Some of this information is needed to
   // setup the architecture state.
   // We allocate the stack here, the size is computed as the sum of
@@ -584,6 +644,8 @@
 
 Interpreter::~Interpreter() {
   delete[] stack_;
+  pp_ = NULL;
+  argdesc_ = NULL;
 #if defined(DEBUG)
   if (trace_file_ != NULL) {
     FlushTraceBuffer();
@@ -601,8 +663,10 @@
 
 // Get the active Interpreter for the current isolate.
 Interpreter* Interpreter::Current() {
-  Interpreter* interpreter = Thread::Current()->interpreter();
+  Thread* thread = Thread::Current();
+  Interpreter* interpreter = thread->interpreter();
   if (interpreter == NULL) {
+    TransitionGeneratedToVM transition(thread);
     interpreter = new Interpreter();
     Thread::Current()->set_interpreter(interpreter);
   }
@@ -697,19 +761,6 @@
 #endif
 }
 
-void Interpreter::CallRuntime(Thread* thread,
-                              RawObject** base,
-                              RawObject** exit_frame,
-                              uint32_t* pc,
-                              intptr_t argc_tag,
-                              RawObject** args,
-                              RawObject** result,
-                              uword target) {
-  Exit(thread, base, exit_frame, pc);
-  NativeArguments native_args(thread, argc_tag, args, result);
-  reinterpret_cast<RuntimeFunction>(target)(native_args);
-}
-
 // Calling into runtime may trigger garbage collection and relocate objects,
 // so all RawObject* pointers become outdated and should not be used across
 // runtime calls.
@@ -1171,8 +1222,48 @@
   // Handler arguments: arguments to check and an ICData object.
   const intptr_t miss_handler_argc = checked_args + 1;
   RawObject** exit_frame = miss_handler_args + miss_handler_argc;
-  CallRuntime(thread, FP, exit_frame, pc, miss_handler_argc, miss_handler_args,
-              result, reinterpret_cast<uword>(handler));
+  Exit(thread, FP, exit_frame, pc);
+  NativeArguments native_args(thread, miss_handler_argc, miss_handler_args,
+                              result);
+  handler(native_args);
+}
+
+DART_FORCE_INLINE bool Interpreter::InterfaceCall(Thread* thread,
+                                                  RawString* target_name,
+                                                  RawObject** call_base,
+                                                  RawObject** top,
+                                                  uint32_t** pc,
+                                                  RawObject*** FP,
+                                                  RawObject*** SP) {
+  const intptr_t type_args_len =
+      InterpreterHelpers::ArgDescTypeArgsLen(argdesc_);
+  const intptr_t receiver_idx = type_args_len > 0 ? 1 : 0;
+
+  intptr_t receiver_cid =
+      InterpreterHelpers::GetClassId(call_base[receiver_idx]);
+
+  RawFunction* target;
+  if (UNLIKELY(!lookup_cache_.Lookup(receiver_cid, target_name, &target))) {
+    // Table lookup miss.
+    top[1] = call_base[receiver_idx];
+    top[2] = target_name;
+    top[3] = argdesc_;
+    top[4] = 0;  // Result slot.
+
+    Exit(thread, *FP, top + 5, *pc);
+    NativeArguments native_args(thread, 3, /* argv */ top + 1,
+                                /* result */ top + 4);
+    DRT_InterpretedInterfaceCallMissHandler(native_args);
+
+    target = static_cast<RawFunction*>(top[4]);
+    target_name = static_cast<RawString*>(top[2]);
+    argdesc_ = static_cast<RawArray*>(top[3]);
+    ASSERT(target->IsFunction());
+    lookup_cache_.Insert(receiver_cid, target_name, target);
+  }
+
+  top[0] = target;
+  return Invoke(thread, call_base, top, pc, FP, SP);
 }
 
 DART_FORCE_INLINE bool Interpreter::InstanceCall1(Thread* thread,
@@ -2111,7 +2202,36 @@
   }
 
   {
-    BYTECODE(InstanceCall, A_D);
+    BYTECODE(InterfaceCall, A_D);
+
+    // Check if single stepping.
+    if (thread->isolate()->single_step()) {
+      Exit(thread, FP, SP + 1, pc);
+      NativeArguments args(thread, 0, NULL, NULL);
+      INVOKE_RUNTIME(DRT_SingleStepHandler, args);
+    }
+
+    {
+      const uint16_t argc = rA;
+      const uint16_t kidx = rD;
+
+      RawObject** call_base = SP - argc + 1;
+      RawObject** call_top = SP + 1;
+
+      InterpreterHelpers::IncrementUsageCounter(FrameFunction(FP));
+      RawString* target_name = static_cast<RawString*>(LOAD_CONSTANT(kidx));
+      argdesc_ = static_cast<RawArray*>(LOAD_CONSTANT(kidx + 1));
+      if (!InterfaceCall(thread, target_name, call_base, call_top, &pc, &FP,
+                         &SP)) {
+        HANDLE_EXCEPTION;
+      }
+    }
+
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(DynamicCall, A_D);
 
     // Check if single stepping.
     if (thread->isolate()->single_step()) {
diff --git a/runtime/vm/interpreter.h b/runtime/vm/interpreter.h
index 4d4fd91..45d476e 100644
--- a/runtime/vm/interpreter.h
+++ b/runtime/vm/interpreter.h
@@ -27,6 +27,36 @@
 class RawSubtypeTestCache;
 class ObjectPointerVisitor;
 
+class LookupCache : public ValueObject {
+ public:
+  LookupCache() {
+    ASSERT(Utils::IsPowerOfTwo(sizeof(Entry)));
+    ASSERT(Utils::IsPowerOfTwo(sizeof(kNumEntries)));
+    Clear();
+  }
+
+  void Clear();
+  bool Lookup(intptr_t receiver_cid,
+              RawString* function_name,
+              RawFunction** target) const;
+  void Insert(intptr_t receiver_cid,
+              RawString* function_name,
+              RawFunction* target);
+
+ private:
+  struct Entry {
+    intptr_t receiver_cid;
+    RawString* function_name;
+    RawFunction* target;
+    intptr_t padding;
+  };
+
+  static const intptr_t kNumEntries = 1024;
+  static const intptr_t kTableMask = kNumEntries - 1;
+
+  Entry entries_[kNumEntries];
+};
+
 // Interpreter intrinsic handler. It is invoked on entry to the intrinsified
 // function via Intrinsic bytecode before the frame is setup.
 // If the handler returns true then Intrinsic bytecode works as a return
@@ -97,6 +127,7 @@
   }
 
   void VisitObjectPointers(ObjectPointerVisitor* visitor);
+  void MajorGC() { lookup_cache_.Clear(); }
 
  private:
   uintptr_t* stack_;
@@ -115,6 +146,8 @@
                        // call instruction and the function entry.
   RawObject* special_[KernelBytecode::kSpecialIndexCount];
 
+  LookupCache lookup_cache_;
+
   static IntrinsicHandler intrinsics_[kIntrinsicCount];
 
   void Exit(Thread* thread,
@@ -122,15 +155,6 @@
             RawObject** exit_frame,
             uint32_t* pc);
 
-  void CallRuntime(Thread* thread,
-                   RawObject** base,
-                   RawObject** exit_frame,
-                   uint32_t* pc,
-                   intptr_t argc_tag,
-                   RawObject** args,
-                   RawObject** result,
-                   uword target);
-
   bool Invoke(Thread* thread,
               RawObject** call_base,
               RawObject** call_top,
@@ -164,6 +188,14 @@
                        RawObject** FP,
                        RawObject** SP);
 
+  bool InterfaceCall(Thread* thread,
+                     RawString* target_name,
+                     RawObject** call_base,
+                     RawObject** call_top,
+                     uint32_t** pc,
+                     RawObject*** FP,
+                     RawObject*** SP);
+
   bool InstanceCall1(Thread* thread,
                      RawICData* icdata,
                      RawObject** call_base,
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index 2829c76..2ae6c18 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -1618,6 +1618,37 @@
 #endif  // !defined(TARGET_ARCH_DBC)
 }
 
+// Handles interpreted interface call cache miss.
+//   Arg0: receiver
+//   Arg1: target name
+//   Arg2: arguments descriptor
+//   Returns: target function
+// Modifies the instance call table in current interpreter.
+DEFINE_RUNTIME_ENTRY(InterpretedInterfaceCallMissHandler, 3) {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  UNREACHABLE();
+#else
+  ASSERT(FLAG_enable_interpreter);
+  const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0));
+  const String& target_name = String::CheckedHandle(zone, arguments.ArgAt(1));
+  const Array& arg_desc = Array::CheckedHandle(zone, arguments.ArgAt(2));
+
+  ArgumentsDescriptor arguments_descriptor(arg_desc);
+  Function& target_function = Function::Handle(
+      zone,
+      Resolver::ResolveDynamic(receiver, target_name, arguments_descriptor));
+
+  // TODO(regis): In order to substitute 'simple_instance_of_function', the 2nd
+  // arg to the call, the type, is needed.
+
+  if (target_function.IsNull()) {
+    target_function = InlineCacheMissHelper(receiver, arg_desc, target_name);
+  }
+  ASSERT(!target_function.IsNull());
+  arguments.SetReturn(target_function);
+#endif
+}
+
 // Invoke appropriate noSuchMethod or closure from getter.
 // Arg0: receiver
 // Arg1: ICData or MegamorphicCache
diff --git a/runtime/vm/runtime_entry_list.h b/runtime/vm/runtime_entry_list.h
index 5bafc0e..fa97c63 100644
--- a/runtime/vm/runtime_entry_list.h
+++ b/runtime/vm/runtime_entry_list.h
@@ -24,6 +24,7 @@
   V(InlineCacheMissHandlerTwoArgs)                                             \
   V(StaticCallMissHandlerOneArg)                                               \
   V(StaticCallMissHandlerTwoArgs)                                              \
+  V(InterpretedInterfaceCallMissHandler)                                       \
   V(Instanceof)                                                                \
   V(SubtypeCheck)                                                              \
   V(TypeCheck)                                                                 \
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index b7a8f14..109ccd4 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -716,15 +716,15 @@
   // Only the mutator thread can run Dart code.
   if (IsMutatorThread()) {
     // The MarkTask, which calls this method, can run on a different thread.  We
-    // therefore assume the mutator is at a safepoint and we can iterate it's
+    // therefore assume the mutator is at a safepoint and we can iterate its
     // stack.
     // TODO(vm-team): It would be beneficial to be able to ask the mutator
     // thread whether it is in fact blocked at the moment (at a "safepoint") so
-    // we can safely iterate it's stack.
+    // we can safely iterate its stack.
     //
     // Unfortunately we cannot use `this->IsAtSafepoint()` here because that
     // will return `false` even though the mutator thread is waiting for mark
-    // tasks (which iterate it's stack) to finish.
+    // tasks (which iterate its stack) to finish.
     const StackFrameIterator::CrossThreadPolicy cross_thread_policy =
         StackFrameIterator::kAllowCrossThreadIteration;