Cleanup invoke in interpreter.

Some cleanup in invocation stuff:
- Get the number of invoke arguments from instruction (vA) rather than get it
from its code item. This benefits to native invoke since we no longer need to
parse the method's shorty. Also pass the low 16 bits of instructions to avoid
fetching it twice when reading vA.
- Remove "is_static" tests by taking advantage of invoke type template argument
rather than testing method's access flags.
- Ensure Instruction::GetArgs is inlined.
- Check exception when initializing method's class when transitioning from
interpreter to compiled code (artInterpreterToCompiledCodeBridge).
- Move UnstartedRuntimeInvoke function to interpreter_common.cc and make it
static as it's only used by DoInvoke and DoInvokeVirtualQuick functions.
- Avoid duplicating code in ShadowFrame::Create.

Performance remains the same according to benchmarks. Hopefully, this should be
addressed in next CLs, especially by improving new shadow frame initialization.

Bug: 10668955
Change-Id: I514b8f098d0ef3e35921ceb770383aac1a9c7902
diff --git a/runtime/dex_instruction-inl.h b/runtime/dex_instruction-inl.h
index 4d39024..207b0b6 100644
--- a/runtime/dex_instruction-inl.h
+++ b/runtime/dex_instruction-inl.h
@@ -281,7 +281,7 @@
   return Fetch16(2);
 }
 
-inline void Instruction::GetArgs(uint32_t arg[5]) const {
+inline void Instruction::GetArgs(uint32_t arg[5], uint16_t inst_data) const {
   DCHECK_EQ(FormatOf(Opcode()), k35c);
 
   /*
@@ -295,7 +295,8 @@
    * method constant (or equivalent) is always in vB.
    */
   uint16_t regList = Fetch16(2);
-  uint4_t count = InstB();  // This is labeled A in the spec.
+  uint4_t count = InstB(inst_data);  // This is labeled A in the spec.
+  DCHECK_LE(count, 5U) << "Invalid arg count in 35c (" << count << ")";
 
   /*
    * Copy the argument registers into the arg[] array, and
@@ -305,15 +306,13 @@
    * copies of those.) Note that cases 5..2 fall through.
    */
   switch (count) {
-    case 5: arg[4] = InstA();
+    case 5: arg[4] = InstA(inst_data);
     case 4: arg[3] = (regList >> 12) & 0x0f;
     case 3: arg[2] = (regList >> 8) & 0x0f;
     case 2: arg[1] = (regList >> 4) & 0x0f;
     case 1: arg[0] = regList & 0x0f; break;
-    case 0: break;  // Valid, but no need to do anything.
-    default:
-      LOG(ERROR) << "Invalid arg count in 35c (" << count << ")";
-      return;
+    default:  // case 0
+      break;  // Valid, but no need to do anything.
   }
 }
 
diff --git a/runtime/dex_instruction.h b/runtime/dex_instruction.h
index e8db3bc..c434cdd 100644
--- a/runtime/dex_instruction.h
+++ b/runtime/dex_instruction.h
@@ -365,7 +365,10 @@
   uint16_t VRegC_3rc() const;
 
   // Fills the given array with the 'arg' array of the instruction.
-  void GetArgs(uint32_t args[5]) const;
+  void GetArgs(uint32_t args[5], uint16_t inst_data) const;
+  void GetArgs(uint32_t args[5]) const {
+    return GetArgs(args, Fetch16(0));
+  }
 
   // Returns the opcode field of the instruction. The given "inst_data" parameter must be the first
   // 16 bits of instruction.
diff --git a/runtime/entrypoints/interpreter/interpreter_entrypoints.cc b/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
index ecf98bc..05c02f2 100644
--- a/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
+++ b/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
@@ -31,7 +31,15 @@
   mirror::ArtMethod* method = shadow_frame->GetMethod();
   // Ensure static methods are initialized.
   if (method->IsStatic()) {
-    Runtime::Current()->GetClassLinker()->EnsureInitialized(method->GetDeclaringClass(), true, true);
+    mirror::Class* declaringClass = method->GetDeclaringClass();
+    if (UNLIKELY(!declaringClass->IsInitializing())) {
+      if (UNLIKELY(!Runtime::Current()->GetClassLinker()->EnsureInitialized(declaringClass,
+                                                                            true, true))) {
+        DCHECK(Thread::Current()->IsExceptionPending());
+        return;
+      }
+      CHECK(declaringClass->IsInitializing());
+    }
   }
   uint16_t arg_offset = (code_item == NULL) ? 0 : code_item->registers_size_ - code_item->ins_size_;
 #if defined(ART_USE_PORTABLE_COMPILER)
@@ -40,7 +48,7 @@
   method->Invoke(self, arg_array.GetArray(), arg_array.GetNumBytes(), result, mh.GetShorty()[0]);
 #else
   method->Invoke(self, shadow_frame->GetVRegArgs(arg_offset),
-                 (shadow_frame->NumberOfVRegs() - arg_offset) * 4,
+                 (shadow_frame->NumberOfVRegs() - arg_offset) * sizeof(uint32_t),
                  result, mh.GetShorty()[0]);
 #endif
 }
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index fd92e06..8aa6fa2 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -422,15 +422,18 @@
   }
 
   ArtMethod* method = shadow_frame->GetMethod();
-  if (method->IsStatic() && !method->GetDeclaringClass()->IsInitializing()) {
-    if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(method->GetDeclaringClass(),
-                                                                 true, true)) {
-      DCHECK(Thread::Current()->IsExceptionPending());
-      return;
+  // Ensure static methods are initialized.
+  if (method->IsStatic()) {
+    Class* declaringClass = method->GetDeclaringClass();
+    if (UNLIKELY(!declaringClass->IsInitializing())) {
+      if (UNLIKELY(!Runtime::Current()->GetClassLinker()->EnsureInitialized(declaringClass,
+                                                                            true, true))) {
+        DCHECK(Thread::Current()->IsExceptionPending());
+        return;
+      }
+      CHECK(declaringClass->IsInitializing());
     }
-    CHECK(method->GetDeclaringClass()->IsInitializing());
   }
-
   self->PushShadowFrame(shadow_frame);
 
   if (LIKELY(!method->IsNative())) {
@@ -445,7 +448,6 @@
   }
 
   self->PopShadowFrame();
-  return;
 }
 
 }  // namespace interpreter
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 36b250c..4992031 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -19,62 +19,59 @@
 namespace art {
 namespace interpreter {
 
-template<InvokeType type, bool is_range, bool do_access_check>
-bool DoInvoke(Thread* self, ShadowFrame& shadow_frame,
-              const Instruction* inst, JValue* result) {
-  bool do_assignability_check = do_access_check;
-  uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
-  uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
-  Object* receiver = (type == kStatic) ? NULL : shadow_frame.GetVRegReference(vregC);
-  ArtMethod* method = FindMethodFromCode(method_idx, receiver, shadow_frame.GetMethod(), self,
-                                         do_access_check, type);
-  if (UNLIKELY(method == NULL)) {
-    CHECK(self->IsExceptionPending());
-    result->SetJ(0);
-    return false;
-  } else if (UNLIKELY(method->IsAbstract())) {
-    ThrowAbstractMethodError(method);
-    result->SetJ(0);
-    return false;
-  }
+static void UnstartedRuntimeInvoke(Thread* self, MethodHelper& mh,
+                                   const DexFile::CodeItem* code_item, ShadowFrame* shadow_frame,
+                                   JValue* result, size_t arg_offset)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+template<bool is_range, bool do_assignability_check>
+bool DoCall(ArtMethod* method, Object* receiver, Thread* self, ShadowFrame& shadow_frame,
+            const Instruction* inst, uint16_t inst_data, JValue* result) {
+  // Compute method information.
   MethodHelper mh(method);
   const DexFile::CodeItem* code_item = mh.GetCodeItem();
+  const uint16_t num_ins = (is_range) ? inst->VRegA_3rc(inst_data) : inst->VRegA_35c(inst_data);
   uint16_t num_regs;
-  uint16_t num_ins;
   if (LIKELY(code_item != NULL)) {
     num_regs = code_item->registers_size_;
-    num_ins = code_item->ins_size_;
+    DCHECK_EQ(num_ins, code_item->ins_size_);
   } else {
     DCHECK(method->IsNative() || method->IsProxyMethod());
-    num_regs = num_ins = ArtMethod::NumArgRegisters(mh.GetShorty());
-    if (!method->IsStatic()) {
-      num_regs++;
-      num_ins++;
-    }
+    num_regs = num_ins;
   }
 
+  // Allocate shadow frame on the stack.
   void* memory = alloca(ShadowFrame::ComputeSize(num_regs));
   ShadowFrame* new_shadow_frame(ShadowFrame::Create(num_regs, &shadow_frame, method, 0, memory));
+
+  // Initialize new shadow frame.
   size_t cur_reg = num_regs - num_ins;
+  size_t arg_offset = 0;
   if (receiver != NULL) {
+    DCHECK(!method->IsStatic());
     new_shadow_frame->SetVRegReference(cur_reg, receiver);
     ++cur_reg;
+    ++arg_offset;
+  } else {
+    DCHECK(method->IsStatic());
   }
 
   const DexFile::TypeList* params;
   if (do_assignability_check) {
     params = mh.GetParameterTypeList();
   }
-  size_t arg_offset = (receiver == NULL) ? 0 : 1;
   const char* shorty = mh.GetShorty();
-  uint32_t arg[5];
-  if (!is_range) {
-    inst->GetArgs(arg);
+  // TODO: find a cleaner way to separate non-range and range information.
+  uint32_t arg[5];  // only used in invoke-XXX.
+  uint32_t vregC;   // only used in invoke-XXX-range.
+  if (is_range) {
+    vregC = inst->VRegC_3rc();
+  } else {
+    inst->GetArgs(arg, inst_data);
   }
-  for (size_t shorty_pos = 0; cur_reg < num_regs; ++shorty_pos, cur_reg++, arg_offset++) {
+  for (size_t shorty_pos = 0; cur_reg < num_regs; ++shorty_pos, ++cur_reg, ++arg_offset) {
     DCHECK_LT(shorty_pos + 1, mh.GetShortyLength());
-    size_t arg_pos = is_range ? vregC + arg_offset : arg[arg_offset];
+    size_t arg_pos = (is_range) ? vregC + arg_offset : arg[arg_offset];
     switch (shorty[shorty_pos + 1]) {
       case 'L': {
         Object* o = shadow_frame.GetVRegReference(arg_pos);
@@ -102,8 +99,8 @@
         uint64_t wide_value = (static_cast<uint64_t>(shadow_frame.GetVReg(arg_pos + 1)) << 32) |
                               static_cast<uint32_t>(shadow_frame.GetVReg(arg_pos));
         new_shadow_frame->SetVRegLong(cur_reg, wide_value);
-        cur_reg++;
-        arg_offset++;
+        ++cur_reg;
+        ++arg_offset;
         break;
       }
       default:
@@ -112,92 +109,7 @@
     }
   }
 
-  if (LIKELY(Runtime::Current()->IsStarted())) {
-    (method->GetEntryPointFromInterpreter())(self, mh, code_item, new_shadow_frame, result);
-  } else {
-    UnstartedRuntimeInvoke(self, mh, code_item, new_shadow_frame, result, num_regs - num_ins);
-  }
-  return !self->IsExceptionPending();
-}
-
-template<bool is_range>
-bool DoInvokeVirtualQuick(Thread* self, ShadowFrame& shadow_frame,
-                          const Instruction* inst, JValue* result) {
-  uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
-  Object* receiver = shadow_frame.GetVRegReference(vregC);
-  if (UNLIKELY(receiver == NULL)) {
-    // We lost the reference to the method index so we cannot get a more
-    // precised exception message.
-    ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
-    return false;
-  }
-  uint32_t vtable_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
-  // TODO: use ObjectArray<T>::GetWithoutChecks ?
-  ArtMethod* method = receiver->GetClass()->GetVTable()->Get(vtable_idx);
-  if (UNLIKELY(method == NULL)) {
-    CHECK(self->IsExceptionPending());
-    result->SetJ(0);
-    return false;
-  } else if (UNLIKELY(method->IsAbstract())) {
-    ThrowAbstractMethodError(method);
-    result->SetJ(0);
-    return false;
-  }
-
-  MethodHelper mh(method);
-  const DexFile::CodeItem* code_item = mh.GetCodeItem();
-  uint16_t num_regs;
-  uint16_t num_ins;
-  if (code_item != NULL) {
-    num_regs = code_item->registers_size_;
-    num_ins = code_item->ins_size_;
-  } else {
-    DCHECK(method->IsNative() || method->IsProxyMethod());
-    num_regs = num_ins = ArtMethod::NumArgRegisters(mh.GetShorty());
-    if (!method->IsStatic()) {
-      num_regs++;
-      num_ins++;
-    }
-  }
-
-  void* memory = alloca(ShadowFrame::ComputeSize(num_regs));
-  ShadowFrame* new_shadow_frame(ShadowFrame::Create(num_regs, &shadow_frame,
-                                                    method, 0, memory));
-  size_t cur_reg = num_regs - num_ins;
-  if (receiver != NULL) {
-    new_shadow_frame->SetVRegReference(cur_reg, receiver);
-    ++cur_reg;
-  }
-
-  size_t arg_offset = (receiver == NULL) ? 0 : 1;
-  const char* shorty = mh.GetShorty();
-  uint32_t arg[5];
-  if (!is_range) {
-    inst->GetArgs(arg);
-  }
-  for (size_t shorty_pos = 0; cur_reg < num_regs; ++shorty_pos, cur_reg++, arg_offset++) {
-    DCHECK_LT(shorty_pos + 1, mh.GetShortyLength());
-    size_t arg_pos = is_range ? vregC + arg_offset : arg[arg_offset];
-    switch (shorty[shorty_pos + 1]) {
-      case 'L': {
-        Object* o = shadow_frame.GetVRegReference(arg_pos);
-        new_shadow_frame->SetVRegReference(cur_reg, o);
-        break;
-      }
-      case 'J': case 'D': {
-        uint64_t wide_value = (static_cast<uint64_t>(shadow_frame.GetVReg(arg_pos + 1)) << 32) |
-                              static_cast<uint32_t>(shadow_frame.GetVReg(arg_pos));
-        new_shadow_frame->SetVRegLong(cur_reg, wide_value);
-        cur_reg++;
-        arg_offset++;
-        break;
-      }
-      default:
-        new_shadow_frame->SetVReg(cur_reg, shadow_frame.GetVReg(arg_pos));
-        break;
-    }
-  }
-
+  // Do the call now.
   if (LIKELY(Runtime::Current()->IsStarted())) {
     (method->GetEntryPointFromInterpreter())(self, mh, code_item, new_shadow_frame, result);
   } else {
@@ -273,9 +185,9 @@
   return true;
 }
 
-void UnstartedRuntimeInvoke(Thread* self, MethodHelper& mh,
-                            const DexFile::CodeItem* code_item, ShadowFrame* shadow_frame,
-                            JValue* result, size_t arg_offset) {
+static void UnstartedRuntimeInvoke(Thread* self, MethodHelper& mh,
+                                   const DexFile::CodeItem* code_item, ShadowFrame* shadow_frame,
+                                   JValue* result, size_t arg_offset) {
   // In a runtime that's not started we intercept certain methods to avoid complicated dependency
   // problems in core libraries.
   std::string name(PrettyMethod(shadow_frame->GetMethod()));
@@ -367,34 +279,17 @@
   }
 }
 
-// Explicit DoInvoke template function declarations.
-#define EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, _is_range_, _check) \
-  template bool DoInvoke<_type, _is_range_, _check>(Thread* self, ShadowFrame& shadow_frame, \
-                                                    const Instruction* inst, JValue* result)
-
-#define EXPLICIT_DO_INVOKE_TEMPLATE_DECL_VARIANTS(_type) \
-  EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, false, false); \
-  EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, false, true);  \
-  EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, true, false);  \
-  EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, true, true)
-
-EXPLICIT_DO_INVOKE_TEMPLATE_DECL_VARIANTS(kStatic);
-EXPLICIT_DO_INVOKE_TEMPLATE_DECL_VARIANTS(kDirect);
-EXPLICIT_DO_INVOKE_TEMPLATE_DECL_VARIANTS(kVirtual);
-EXPLICIT_DO_INVOKE_TEMPLATE_DECL_VARIANTS(kSuper);
-EXPLICIT_DO_INVOKE_TEMPLATE_DECL_VARIANTS(kInterface);
-
-#undef EXPLICIT_DO_INVOKE_TEMPLATE_DECL_VARIANTS
-#undef EXPLICIT_DO_INVOKE_TEMPLATE_DECL
-
-// Explicit DoInvokeVirtualQuick template function declarations.
-#define EXPLICIT_DO_INVOKE_VIRTUAL_QUICK_TEMPLATE_DECL(_is_range)                       \
-template bool DoInvokeVirtualQuick<_is_range>(Thread* self, ShadowFrame& shadow_frame,  \
-                                              const Instruction* inst, JValue* result)
-
-EXPLICIT_DO_INVOKE_VIRTUAL_QUICK_TEMPLATE_DECL(false);
-EXPLICIT_DO_INVOKE_VIRTUAL_QUICK_TEMPLATE_DECL(true);
-#undef EXPLICIT_DO_INVOKE_VIRTUAL_QUICK_TEMPLATE_DECL
+// Explicit DoCall template function declarations.
+#define EXPLICIT_DO_CALL_TEMPLATE_DECL(_is_range, _do_assignability_check)                        \
+template bool DoCall<_is_range, _do_assignability_check>(ArtMethod* method, Object* receiver,     \
+                                                         Thread* self, ShadowFrame& shadow_frame, \
+                                                         const Instruction* inst,                 \
+                                                         uint16_t inst_data, JValue* result)
+EXPLICIT_DO_CALL_TEMPLATE_DECL(false, false);
+EXPLICIT_DO_CALL_TEMPLATE_DECL(false, true);
+EXPLICIT_DO_CALL_TEMPLATE_DECL(true, false);
+EXPLICIT_DO_CALL_TEMPLATE_DECL(true, true);
+#undef EXPLICIT_DO_CALL_TEMPLATE_DECL
 
 // Explicit DoFilledNewArray template function declarations.
 #define EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(_is_range_, _check)                \
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index 3ad1935..80502b4 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -71,7 +71,7 @@
 extern JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh,
                                 const DexFile::CodeItem* code_item,
                                 ShadowFrame& shadow_frame, JValue result_register)
-    NO_THREAD_SAFETY_ANALYSIS __attribute__((hot));
+    NO_THREAD_SAFETY_ANALYSIS HOT_ATTR;
 
 // TODO: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) which is failing due to template
 // specialization.
@@ -79,12 +79,7 @@
 extern JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh,
                               const DexFile::CodeItem* code_item,
                               ShadowFrame& shadow_frame, JValue result_register)
-    NO_THREAD_SAFETY_ANALYSIS __attribute__((hot));
-
-void UnstartedRuntimeInvoke(Thread* self, MethodHelper& mh,
-                            const DexFile::CodeItem* code_item, ShadowFrame* shadow_frame,
-                            JValue* result, size_t arg_offset)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+    NO_THREAD_SAFETY_ANALYSIS HOT_ATTR;
 
 static inline void DoMonitorEnter(Thread* self, Object* ref) NO_THREAD_SAFETY_ANALYSIS {
   ref->MonitorEnter(self);
@@ -96,16 +91,72 @@
 
 // TODO: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) which is failing due to template
 // specialization.
+template<bool is_range, bool do_assignability_check>
+bool DoCall(ArtMethod* method, Object* receiver, Thread* self, ShadowFrame& shadow_frame,
+            const Instruction* inst, uint16_t inst_data, JValue* result) NO_THREAD_SAFETY_ANALYSIS;
+
+// TODO: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) which is failing due to template
+// specialization.
 template<InvokeType type, bool is_range, bool do_access_check>
-bool DoInvoke(Thread* self, ShadowFrame& shadow_frame,
-              const Instruction* inst, JValue* result) NO_THREAD_SAFETY_ANALYSIS;
+static bool DoInvoke(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst,
+                     uint16_t inst_data, JValue* result) NO_THREAD_SAFETY_ANALYSIS ALWAYS_INLINE;
+
+template<InvokeType type, bool is_range, bool do_access_check>
+static inline bool DoInvoke(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst,
+                            uint16_t inst_data, JValue* result) {
+  const uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
+  const uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
+  Object* const receiver = (type == kStatic) ? NULL : shadow_frame.GetVRegReference(vregC);
+  ArtMethod* const method = FindMethodFromCode(method_idx, receiver, shadow_frame.GetMethod(), self,
+                                               do_access_check, type);
+  if (UNLIKELY(method == NULL)) {
+    CHECK(self->IsExceptionPending());
+    result->SetJ(0);
+    return false;
+  } else if (UNLIKELY(method->IsAbstract())) {
+    ThrowAbstractMethodError(method);
+    result->SetJ(0);
+    return false;
+  } else {
+    return DoCall<is_range, do_access_check>(method, receiver, self, shadow_frame, inst,
+                                             inst_data, result);
+  }
+}
 
 // TODO: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) which is failing due to template
 // specialization.
 template<bool is_range>
-bool DoInvokeVirtualQuick(Thread* self, ShadowFrame& shadow_frame,
-                          const Instruction* inst, JValue* result)
-    NO_THREAD_SAFETY_ANALYSIS;
+static bool DoInvokeVirtualQuick(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst,
+                                 uint16_t inst_data, JValue* result)
+    NO_THREAD_SAFETY_ANALYSIS ALWAYS_INLINE;
+
+template<bool is_range>
+static inline bool DoInvokeVirtualQuick(Thread* self, ShadowFrame& shadow_frame,
+                                        const Instruction* inst, uint16_t inst_data,
+                                        JValue* result) {
+  const uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
+  Object* const receiver = shadow_frame.GetVRegReference(vregC);
+  if (UNLIKELY(receiver == NULL)) {
+    // We lost the reference to the method index so we cannot get a more
+    // precised exception message.
+    ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
+    return false;
+  }
+  const uint32_t vtable_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
+  ArtMethod* const method = receiver->GetClass()->GetVTable()->GetWithoutChecks(vtable_idx);
+  if (UNLIKELY(method == NULL)) {
+    CHECK(self->IsExceptionPending());
+    result->SetJ(0);
+    return false;
+  } else if (UNLIKELY(method->IsAbstract())) {
+    ThrowAbstractMethodError(method);
+    result->SetJ(0);
+    return false;
+  } else {
+    // No need to check since we've been quickened.
+    return DoCall<is_range, false>(method, receiver, self, shadow_frame, inst, inst_data, result);
+  }
+}
 
 // We use template functions to optimize compiler inlining process. Otherwise,
 // some parts of the code (like a switch statement) which depend on a constant
@@ -283,11 +334,11 @@
 // TODO: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) which is failing due to template
 // specialization.
 template<Primitive::Type field_type>
-static bool DoIPutQuick(ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data)
+static bool DoIPutQuick(const ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data)
     NO_THREAD_SAFETY_ANALYSIS ALWAYS_INLINE;
 
 template<Primitive::Type field_type>
-static inline bool DoIPutQuick(ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data) {
+static inline bool DoIPutQuick(const ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data) {
   Object* obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
   if (UNLIKELY(obj == NULL)) {
     // We lost the reference to the field index so we cannot get a more
diff --git a/runtime/interpreter/interpreter_goto_table_impl.cc b/runtime/interpreter/interpreter_goto_table_impl.cc
index 018add3..5a00831 100644
--- a/runtime/interpreter/interpreter_goto_table_impl.cc
+++ b/runtime/interpreter/interpreter_goto_table_impl.cc
@@ -29,7 +29,6 @@
 // - "currentHandlersTable": the current table of pointer to each instruction handler.
 
 // Advance to the next instruction and updates interpreter state.
-// TODO: move check suspend to backward branch, return and exception handling.
 #define ADVANCE(_offset)                                                    \
   do {                                                                      \
     int32_t disp = static_cast<int32_t>(_offset);                           \
@@ -1339,84 +1338,84 @@
   HANDLE_INSTRUCTION_END();
 
   HANDLE_INSTRUCTION_START(INVOKE_VIRTUAL) {
-    bool success = DoInvoke<kVirtual, false, do_access_check>(self, shadow_frame, inst, &result_register);
+    bool success = DoInvoke<kVirtual, false, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
     UPDATE_HANDLER_TABLE();
     POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
   }
   HANDLE_INSTRUCTION_END();
 
   HANDLE_INSTRUCTION_START(INVOKE_VIRTUAL_RANGE) {
-    bool success = DoInvoke<kVirtual, true, do_access_check>(self, shadow_frame, inst, &result_register);
+    bool success = DoInvoke<kVirtual, true, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
     UPDATE_HANDLER_TABLE();
     POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
   }
   HANDLE_INSTRUCTION_END();
 
   HANDLE_INSTRUCTION_START(INVOKE_SUPER) {
-    bool success = DoInvoke<kSuper, false, do_access_check>(self, shadow_frame, inst, &result_register);
+    bool success = DoInvoke<kSuper, false, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
     UPDATE_HANDLER_TABLE();
     POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
   }
   HANDLE_INSTRUCTION_END();
 
   HANDLE_INSTRUCTION_START(INVOKE_SUPER_RANGE) {
-    bool success = DoInvoke<kSuper, true, do_access_check>(self, shadow_frame, inst, &result_register);
+    bool success = DoInvoke<kSuper, true, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
     UPDATE_HANDLER_TABLE();
     POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
   }
   HANDLE_INSTRUCTION_END();
 
   HANDLE_INSTRUCTION_START(INVOKE_DIRECT) {
-    bool success = DoInvoke<kDirect, false, do_access_check>(self, shadow_frame, inst, &result_register);
+    bool success = DoInvoke<kDirect, false, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
     UPDATE_HANDLER_TABLE();
     POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
   }
   HANDLE_INSTRUCTION_END();
 
   HANDLE_INSTRUCTION_START(INVOKE_DIRECT_RANGE) {
-    bool success = DoInvoke<kDirect, true, do_access_check>(self, shadow_frame, inst, &result_register);
+    bool success = DoInvoke<kDirect, true, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
     UPDATE_HANDLER_TABLE();
     POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
   }
   HANDLE_INSTRUCTION_END();
 
   HANDLE_INSTRUCTION_START(INVOKE_INTERFACE) {
-    bool success = DoInvoke<kInterface, false, do_access_check>(self, shadow_frame, inst, &result_register);
+    bool success = DoInvoke<kInterface, false, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
     UPDATE_HANDLER_TABLE();
     POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
   }
   HANDLE_INSTRUCTION_END();
 
   HANDLE_INSTRUCTION_START(INVOKE_INTERFACE_RANGE) {
-    bool success = DoInvoke<kInterface, true, do_access_check>(self, shadow_frame, inst, &result_register);
+    bool success = DoInvoke<kInterface, true, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
     UPDATE_HANDLER_TABLE();
     POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
   }
   HANDLE_INSTRUCTION_END();
 
   HANDLE_INSTRUCTION_START(INVOKE_STATIC) {
-    bool success = DoInvoke<kStatic, false, do_access_check>(self, shadow_frame, inst, &result_register);
+    bool success = DoInvoke<kStatic, false, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
     UPDATE_HANDLER_TABLE();
     POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
   }
   HANDLE_INSTRUCTION_END();
 
   HANDLE_INSTRUCTION_START(INVOKE_STATIC_RANGE) {
-    bool success = DoInvoke<kStatic, true, do_access_check>(self, shadow_frame, inst, &result_register);
+    bool success = DoInvoke<kStatic, true, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
     UPDATE_HANDLER_TABLE();
     POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
   }
   HANDLE_INSTRUCTION_END();
 
   HANDLE_INSTRUCTION_START(INVOKE_VIRTUAL_QUICK) {
-    bool success = DoInvokeVirtualQuick<false>(self, shadow_frame, inst, &result_register);
+    bool success = DoInvokeVirtualQuick<false>(self, shadow_frame, inst, inst_data, &result_register);
     UPDATE_HANDLER_TABLE();
     POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
   }
   HANDLE_INSTRUCTION_END();
 
   HANDLE_INSTRUCTION_START(INVOKE_VIRTUAL_RANGE_QUICK) {
-    bool success = DoInvokeVirtualQuick<true>(self, shadow_frame, inst, &result_register);
+    bool success = DoInvokeVirtualQuick<true>(self, shadow_frame, inst, inst_data, &result_register);
     UPDATE_HANDLER_TABLE();
     POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
   }
diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc
index 2d658b3..82f216a 100644
--- a/runtime/interpreter/interpreter_switch_impl.cc
+++ b/runtime/interpreter/interpreter_switch_impl.cc
@@ -1283,73 +1283,73 @@
       }
       case Instruction::INVOKE_VIRTUAL: {
         PREAMBLE();
-        bool success = DoInvoke<kVirtual, false, do_access_check>(self, shadow_frame, inst, &result_register);
+        bool success = DoInvoke<kVirtual, false, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
         POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
         break;
       }
       case Instruction::INVOKE_VIRTUAL_RANGE: {
         PREAMBLE();
-        bool success = DoInvoke<kVirtual, true, do_access_check>(self, shadow_frame, inst, &result_register);
+        bool success = DoInvoke<kVirtual, true, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
         POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
         break;
       }
       case Instruction::INVOKE_SUPER: {
         PREAMBLE();
-        bool success = DoInvoke<kSuper, false, do_access_check>(self, shadow_frame, inst, &result_register);
+        bool success = DoInvoke<kSuper, false, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
         POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
         break;
       }
       case Instruction::INVOKE_SUPER_RANGE: {
         PREAMBLE();
-        bool success = DoInvoke<kSuper, true, do_access_check>(self, shadow_frame, inst, &result_register);
+        bool success = DoInvoke<kSuper, true, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
         POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
         break;
       }
       case Instruction::INVOKE_DIRECT: {
         PREAMBLE();
-        bool success = DoInvoke<kDirect, false, do_access_check>(self, shadow_frame, inst, &result_register);
+        bool success = DoInvoke<kDirect, false, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
         POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
         break;
       }
       case Instruction::INVOKE_DIRECT_RANGE: {
         PREAMBLE();
-        bool success = DoInvoke<kDirect, true, do_access_check>(self, shadow_frame, inst, &result_register);
+        bool success = DoInvoke<kDirect, true, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
         POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
         break;
       }
       case Instruction::INVOKE_INTERFACE: {
         PREAMBLE();
-        bool success = DoInvoke<kInterface, false, do_access_check>(self, shadow_frame, inst, &result_register);
+        bool success = DoInvoke<kInterface, false, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
         POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
         break;
       }
       case Instruction::INVOKE_INTERFACE_RANGE: {
         PREAMBLE();
-        bool success = DoInvoke<kInterface, true, do_access_check>(self, shadow_frame, inst, &result_register);
+        bool success = DoInvoke<kInterface, true, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
         POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
         break;
       }
       case Instruction::INVOKE_STATIC: {
         PREAMBLE();
-        bool success = DoInvoke<kStatic, false, do_access_check>(self, shadow_frame, inst, &result_register);
+        bool success = DoInvoke<kStatic, false, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
         POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
         break;
       }
       case Instruction::INVOKE_STATIC_RANGE: {
         PREAMBLE();
-        bool success = DoInvoke<kStatic, true, do_access_check>(self, shadow_frame, inst, &result_register);
+        bool success = DoInvoke<kStatic, true, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
         POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
         break;
       }
       case Instruction::INVOKE_VIRTUAL_QUICK: {
         PREAMBLE();
-        bool success = DoInvokeVirtualQuick<false>(self, shadow_frame, inst, &result_register);
+        bool success = DoInvokeVirtualQuick<false>(self, shadow_frame, inst, inst_data, &result_register);
         POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
         break;
       }
       case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: {
         PREAMBLE();
-        bool success = DoInvokeVirtualQuick<true>(self, shadow_frame, inst, &result_register);
+        bool success = DoInvokeVirtualQuick<true>(self, shadow_frame, inst, inst_data, &result_register);
         POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
         break;
       }
diff --git a/runtime/stack.h b/runtime/stack.h
index 2bf3340..700b7f1 100644
--- a/runtime/stack.h
+++ b/runtime/stack.h
@@ -68,8 +68,7 @@
   static ShadowFrame* Create(uint32_t num_vregs, ShadowFrame* link,
                              mirror::ArtMethod* method, uint32_t dex_pc) {
     uint8_t* memory = new uint8_t[ComputeSize(num_vregs)];
-    ShadowFrame* sf = new (memory) ShadowFrame(num_vregs, link, method, dex_pc, true);
-    return sf;
+    return Create(num_vregs, link, method, dex_pc, memory);
   }
 
   // Create ShadowFrame for interpreter using provided memory.