ART: Make method handle runtime code callable from compiler.

Most of this change is moving the existing method handles code, but it
also introduces a new header file, common_dex_operations.h, that has
some operations taken from interpreter_common.{h,cc} that are also used
by method handles (perform call, set field, get field).

Bug: 30550796
Test: m test-art-host
Change-Id: I2235e13770a5562950f2767f65a25ca273479150
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index a09e71b..ca26207 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -32,7 +32,6 @@
 #include "reflection.h"
 #include "reflection-inl.h"
 #include "stack.h"
-#include "unstarted_runtime.h"
 #include "verifier/method_verifier.h"
 #include "well_known_classes.h"
 
@@ -43,60 +42,6 @@
   ThrowNullPointerExceptionFromDexPC();
 }
 
-template<Primitive::Type field_type>
-static ALWAYS_INLINE void DoFieldGetCommon(Thread* self,
-                                           const ShadowFrame& shadow_frame,
-                                           ObjPtr<mirror::Object>& obj,
-                                           ArtField* field,
-                                           JValue* result)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  field->GetDeclaringClass()->AssertInitializedOrInitializingInThread(self);
-
-  // Report this field access to instrumentation if needed.
-  instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
-  if (UNLIKELY(instrumentation->HasFieldReadListeners())) {
-    StackHandleScope<1> hs(self);
-    // Wrap in handle wrapper in case the listener does thread suspension.
-    HandleWrapperObjPtr<mirror::Object> h(hs.NewHandleWrapper(&obj));
-    ObjPtr<mirror::Object> this_object;
-    if (!field->IsStatic()) {
-      this_object = obj;
-    }
-    instrumentation->FieldReadEvent(self,
-                                    this_object.Ptr(),
-                                    shadow_frame.GetMethod(),
-                                    shadow_frame.GetDexPC(),
-                                    field);
-  }
-
-  switch (field_type) {
-    case Primitive::kPrimBoolean:
-      result->SetZ(field->GetBoolean(obj));
-      break;
-    case Primitive::kPrimByte:
-      result->SetB(field->GetByte(obj));
-      break;
-    case Primitive::kPrimChar:
-      result->SetC(field->GetChar(obj));
-      break;
-    case Primitive::kPrimShort:
-      result->SetS(field->GetShort(obj));
-      break;
-    case Primitive::kPrimInt:
-      result->SetI(field->GetInt(obj));
-      break;
-    case Primitive::kPrimLong:
-      result->SetJ(field->GetLong(obj));
-      break;
-    case Primitive::kPrimNot:
-      result->SetL(field->GetObject(obj));
-      break;
-    default:
-      LOG(FATAL) << "Unreachable: " << field_type;
-      UNREACHABLE();
-  }
-}
-
 template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check>
 bool DoFieldGet(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst,
                 uint16_t inst_data) {
@@ -184,48 +129,6 @@
 #undef EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL
 #undef EXPLICIT_DO_FIELD_GET_TEMPLATE_DECL
 
-// Helper for getters in invoke-polymorphic.
-inline static void DoFieldGetForInvokePolymorphic(Thread* self,
-                                                  const ShadowFrame& shadow_frame,
-                                                  ObjPtr<mirror::Object>& obj,
-                                                  ArtField* field,
-                                                  Primitive::Type field_type,
-                                                  JValue* result)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  switch (field_type) {
-    case Primitive::kPrimBoolean:
-      DoFieldGetCommon<Primitive::kPrimBoolean>(self, shadow_frame, obj, field, result);
-      break;
-    case Primitive::kPrimByte:
-      DoFieldGetCommon<Primitive::kPrimByte>(self, shadow_frame, obj, field, result);
-      break;
-    case Primitive::kPrimChar:
-      DoFieldGetCommon<Primitive::kPrimChar>(self, shadow_frame, obj, field, result);
-      break;
-    case Primitive::kPrimShort:
-      DoFieldGetCommon<Primitive::kPrimShort>(self, shadow_frame, obj, field, result);
-      break;
-    case Primitive::kPrimInt:
-      DoFieldGetCommon<Primitive::kPrimInt>(self, shadow_frame, obj, field, result);
-      break;
-    case Primitive::kPrimLong:
-      DoFieldGetCommon<Primitive::kPrimLong>(self, shadow_frame, obj, field, result);
-      break;
-    case Primitive::kPrimFloat:
-      DoFieldGetCommon<Primitive::kPrimInt>(self, shadow_frame, obj, field, result);
-      break;
-    case Primitive::kPrimDouble:
-      DoFieldGetCommon<Primitive::kPrimLong>(self, shadow_frame, obj, field, result);
-      break;
-    case Primitive::kPrimNot:
-      DoFieldGetCommon<Primitive::kPrimNot>(self, shadow_frame, obj, field, result);
-      break;
-    case Primitive::kPrimVoid:
-      LOG(FATAL) << "Unreachable: " << field_type;
-      UNREACHABLE();
-  }
-}
-
 // Handles iget-quick, iget-wide-quick and iget-object-quick instructions.
 // Returns true on success, otherwise throws an exception and returns false.
 template<Primitive::Type field_type>
@@ -300,42 +203,6 @@
 EXPLICIT_DO_IGET_QUICK_TEMPLATE_DECL(Primitive::kPrimNot);      // iget-object-quick.
 #undef EXPLICIT_DO_IGET_QUICK_TEMPLATE_DECL
 
-static JValue GetFieldValue(const ShadowFrame& shadow_frame,
-                            Primitive::Type field_type,
-                            uint32_t vreg)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  JValue field_value;
-  switch (field_type) {
-    case Primitive::kPrimBoolean:
-      field_value.SetZ(static_cast<uint8_t>(shadow_frame.GetVReg(vreg)));
-      break;
-    case Primitive::kPrimByte:
-      field_value.SetB(static_cast<int8_t>(shadow_frame.GetVReg(vreg)));
-      break;
-    case Primitive::kPrimChar:
-      field_value.SetC(static_cast<uint16_t>(shadow_frame.GetVReg(vreg)));
-      break;
-    case Primitive::kPrimShort:
-      field_value.SetS(static_cast<int16_t>(shadow_frame.GetVReg(vreg)));
-      break;
-    case Primitive::kPrimInt:
-    case Primitive::kPrimFloat:
-      field_value.SetI(shadow_frame.GetVReg(vreg));
-      break;
-    case Primitive::kPrimLong:
-    case Primitive::kPrimDouble:
-      field_value.SetJ(shadow_frame.GetVRegLong(vreg));
-      break;
-    case Primitive::kPrimNot:
-      field_value.SetL(shadow_frame.GetVRegReference(vreg));
-      break;
-    case Primitive::kPrimVoid:
-      LOG(FATAL) << "Unreachable: " << field_type;
-      UNREACHABLE();
-  }
-  return field_value;
-}
-
 template<Primitive::Type field_type>
 static JValue GetFieldValue(const ShadowFrame& shadow_frame, uint32_t vreg)
     REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -369,82 +236,6 @@
   return field_value;
 }
 
-template<Primitive::Type field_type, bool do_assignability_check, bool transaction_active>
-static inline bool DoFieldPutCommon(Thread* self,
-                                    const ShadowFrame& shadow_frame,
-                                    ObjPtr<mirror::Object>& obj,
-                                    ArtField* f,
-                                    const JValue& value)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  f->GetDeclaringClass()->AssertInitializedOrInitializingInThread(self);
-
-  // Report this field access to instrumentation if needed. Since we only have the offset of
-  // the field from the base of the object, we need to look for it first.
-  instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
-  if (UNLIKELY(instrumentation->HasFieldWriteListeners())) {
-    StackHandleScope<1> hs(self);
-    // Wrap in handle wrapper in case the listener does thread suspension.
-    HandleWrapperObjPtr<mirror::Object> h(hs.NewHandleWrapper(&obj));
-    ObjPtr<mirror::Object> this_object = f->IsStatic() ? nullptr : obj;
-    instrumentation->FieldWriteEvent(self, this_object.Ptr(),
-                                     shadow_frame.GetMethod(),
-                                     shadow_frame.GetDexPC(),
-                                     f,
-                                     value);
-  }
-
-  switch (field_type) {
-    case Primitive::kPrimBoolean:
-      f->SetBoolean<transaction_active>(obj, value.GetZ());
-      break;
-    case Primitive::kPrimByte:
-      f->SetByte<transaction_active>(obj, value.GetB());
-      break;
-    case Primitive::kPrimChar:
-      f->SetChar<transaction_active>(obj, value.GetC());
-      break;
-    case Primitive::kPrimShort:
-      f->SetShort<transaction_active>(obj, value.GetS());
-      break;
-    case Primitive::kPrimInt:
-      f->SetInt<transaction_active>(obj, value.GetI());
-      break;
-    case Primitive::kPrimLong:
-      f->SetLong<transaction_active>(obj, value.GetJ());
-      break;
-    case Primitive::kPrimNot: {
-      ObjPtr<mirror::Object> reg = value.GetL();
-      if (do_assignability_check && reg != nullptr) {
-        // FieldHelper::GetType can resolve classes, use a handle wrapper which will restore the
-        // object in the destructor.
-        ObjPtr<mirror::Class> field_class;
-        {
-          StackHandleScope<2> hs(self);
-          HandleWrapperObjPtr<mirror::Object> h_reg(hs.NewHandleWrapper(&reg));
-          HandleWrapperObjPtr<mirror::Object> h_obj(hs.NewHandleWrapper(&obj));
-          field_class = f->GetType<true>();
-        }
-        if (!reg->VerifierInstanceOf(field_class.Ptr())) {
-          // This should never happen.
-          std::string temp1, temp2, temp3;
-          self->ThrowNewExceptionF("Ljava/lang/InternalError;",
-                                   "Put '%s' that is not instance of field '%s' in '%s'",
-                                   reg->GetClass()->GetDescriptor(&temp1),
-                                   field_class->GetDescriptor(&temp2),
-                                   f->GetDeclaringClass()->GetDescriptor(&temp3));
-          return false;
-        }
-      }
-      f->SetObj<transaction_active>(obj, reg);
-      break;
-    }
-    default:
-      LOG(FATAL) << "Unreachable: " << field_type;
-      UNREACHABLE();
-  }
-  return true;
-}
-
 template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check,
          bool transaction_active>
 bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame, const Instruction* inst,
@@ -511,46 +302,6 @@
 #undef EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL
 #undef EXPLICIT_DO_FIELD_PUT_TEMPLATE_DECL
 
-// Helper for setters in invoke-polymorphic.
-bool DoFieldPutForInvokePolymorphic(Thread* self,
-                                    ShadowFrame& shadow_frame,
-                                    ObjPtr<mirror::Object>& obj,
-                                    ArtField* field,
-                                    Primitive::Type field_type,
-                                    const JValue& value)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  static const bool kDoCheckAssignability = false;
-  static const bool kTransaction = false;
-  switch (field_type) {
-    case Primitive::kPrimBoolean:
-      return DoFieldPutCommon<Primitive::kPrimBoolean, kDoCheckAssignability, kTransaction>(
-          self, shadow_frame, obj, field, value);
-    case Primitive::kPrimByte:
-      return DoFieldPutCommon<Primitive::kPrimByte, kDoCheckAssignability, kTransaction>(
-          self, shadow_frame, obj, field, value);
-    case Primitive::kPrimChar:
-      return DoFieldPutCommon<Primitive::kPrimChar, kDoCheckAssignability, kTransaction>(
-          self, shadow_frame, obj, field, value);
-    case Primitive::kPrimShort:
-      return DoFieldPutCommon<Primitive::kPrimShort, kDoCheckAssignability, kTransaction>(
-          self, shadow_frame, obj, field, value);
-    case Primitive::kPrimInt:
-    case Primitive::kPrimFloat:
-      return DoFieldPutCommon<Primitive::kPrimInt, kDoCheckAssignability, kTransaction>(
-          self, shadow_frame, obj, field, value);
-    case Primitive::kPrimLong:
-    case Primitive::kPrimDouble:
-      return DoFieldPutCommon<Primitive::kPrimLong, kDoCheckAssignability, kTransaction>(
-          self, shadow_frame, obj, field, value);
-    case Primitive::kPrimNot:
-      return DoFieldPutCommon<Primitive::kPrimNot, kDoCheckAssignability, kTransaction>(
-          self, shadow_frame, obj, field, value);
-    case Primitive::kPrimVoid:
-      LOG(FATAL) << "Unreachable: " << field_type;
-      UNREACHABLE();
-  }
-}
-
 template<Primitive::Type field_type, bool transaction_active>
 bool DoIPutQuick(const ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data) {
   ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
@@ -697,36 +448,6 @@
                                        uint32_t vregC) REQUIRES_SHARED(Locks::mutator_lock_);
 
 template <bool is_range>
-static ALWAYS_INLINE bool DoCallPolymorphic(ArtMethod* called_method,
-                                            Handle<mirror::MethodType> callsite_type,
-                                            Handle<mirror::MethodType> target_type,
-                                            Thread* self,
-                                            ShadowFrame& shadow_frame,
-                                            JValue* result,
-                                            uint32_t (&arg)[Instruction::kMaxVarArgRegs],
-                                            uint32_t vregC,
-                                            const MethodHandleKind handle_kind)
-  REQUIRES_SHARED(Locks::mutator_lock_);
-
-template <bool is_range>
-static ALWAYS_INLINE bool DoCallTransform(ArtMethod* called_method,
-                                          Handle<mirror::MethodType> callsite_type,
-                                          Handle<mirror::MethodType> callee_type,
-                                          Thread* self,
-                                          ShadowFrame& shadow_frame,
-                                          Handle<mirror::MethodHandleImpl> receiver,
-                                          JValue* result,
-                                          uint32_t (&arg)[Instruction::kMaxVarArgRegs],
-                                          uint32_t vregC) REQUIRES_SHARED(Locks::mutator_lock_);
-
-ALWAYS_INLINE void PerformCall(Thread* self,
-                               const DexFile::CodeItem* code_item,
-                               ArtMethod* caller_method,
-                               const size_t first_dest_reg,
-                               ShadowFrame* callee_frame,
-                               JValue* result) REQUIRES_SHARED(Locks::mutator_lock_);
-
-template <bool is_range>
 ALWAYS_INLINE void CopyRegisters(ShadowFrame& caller_frame,
                                  ShadowFrame* callee_frame,
                                  const uint32_t (&arg)[Instruction::kMaxVarArgRegs],
@@ -798,55 +519,12 @@
   }
 }
 
-inline static bool IsInvokeExact(const DexFile& dex_file, int invoke_method_idx) {
-  // This check uses string comparison as it needs less code and data
-  // to do than fetching the associated ArtMethod from the DexCache
-  // and checking against ArtMethods in the well known classes. The
-  // verifier needs to perform a more rigorous check.
-  const char* method_name = dex_file.GetMethodName(dex_file.GetMethodId(invoke_method_idx));
-  bool is_invoke_exact = (0 == strcmp(method_name, "invokeExact"));
-  DCHECK(is_invoke_exact || (0 == strcmp(method_name, "invoke")));
-  return is_invoke_exact;
-}
-
-inline static ObjPtr<mirror::Class> GetAndInitializeDeclaringClass(Thread* self, ArtField* field)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  // Method handle invocations on static fields should ensure class is
-  // initialized. This usually happens when an instance is constructed
-  // or class members referenced, but this is not guaranteed when
-  // looking up method handles.
-  ObjPtr<mirror::Class> klass = field->GetDeclaringClass();
-  if (UNLIKELY(!klass->IsInitialized())) {
-    StackHandleScope<1> hs(self);
-    HandleWrapperObjPtr<mirror::Class> h(hs.NewHandleWrapper(&klass));
-    if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(self, h, true, true)) {
-      DCHECK(self->IsExceptionPending());
-      return nullptr;
-    }
-  }
-  return klass;
-}
-
-// Returns true iff. the callsite type for a polymorphic invoke is transformer
-// like, i.e that it has a single input argument whose type is
-// dalvik.system.EmulatedStackFrame.
-static inline bool IsCallerTransformer(Handle<mirror::MethodType> callsite_type)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  ObjPtr<mirror::ObjectArray<mirror::Class>> param_types(callsite_type->GetPTypes());
-  if (param_types->GetLength() == 1) {
-    ObjPtr<mirror::Class> param(param_types->GetWithoutChecks(0));
-    return param == WellKnownClasses::ToClass(WellKnownClasses::dalvik_system_EmulatedStackFrame);
-  }
-
-  return false;
-}
-
 template<bool is_range, bool do_access_check>
-inline bool DoInvokePolymorphic(Thread* self,
-                                ShadowFrame& shadow_frame,
-                                const Instruction* inst,
-                                uint16_t inst_data,
-                                JValue* result)
+bool DoInvokePolymorphic(Thread* self,
+                         ShadowFrame& shadow_frame,
+                         const Instruction* inst,
+                         uint16_t inst_data,
+                         JValue* result)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   // Invoke-polymorphic instructions always take a receiver. i.e, they are never static.
   const uint32_t vRegC = (is_range) ? inst->VRegC_4rcc() : inst->VRegC_45cc();
@@ -857,15 +535,10 @@
   // and provides sane return result in error cases.
   result->SetJ(0);
 
-  // Determine if this invocation is MethodHandle.invoke() or
-  // MethodHandle.invokeExact().
-  bool is_invoke_exact = IsInvokeExact(shadow_frame.GetMethod()->GetDeclaringClass()->GetDexFile(),
-                                       invoke_method_idx);
-
   // The invoke_method_idx here is the name of the signature polymorphic method that
   // was symbolically invoked in bytecode (say MethodHandle.invoke or MethodHandle.invokeExact)
   // and not the method that we'll dispatch to in the end.
-  StackHandleScope<6> hs(self);
+  StackHandleScope<5> hs(self);
   Handle<mirror::MethodHandleImpl> method_handle(hs.NewHandle(
       ObjPtr<mirror::MethodHandleImpl>::DownCast(
           MakeObjPtr(shadow_frame.GetVRegReference(vRegC)))));
@@ -877,7 +550,7 @@
   }
 
   // The vRegH value gives the index of the proto_id associated with this
-  // signature polymorphic callsite.
+  // signature polymorphic call site.
   const uint32_t callsite_proto_id = (is_range) ? inst->VRegH_4rcc() : inst->VRegH_45cc();
 
   // Call through to the classlinker and ask it to resolve the static type associated
@@ -896,224 +569,43 @@
     return false;
   }
 
-  const MethodHandleKind handle_kind = method_handle->GetHandleKind();
-  Handle<mirror::MethodType> handle_type(hs.NewHandle(method_handle->GetMethodType()));
-  CHECK(handle_type.Get() != nullptr);
-  {
-    // We need to check the nominal type of the handle in addition to the
-    // real type. The "nominal" type is present when MethodHandle.asType is
-    // called any handle, and results in the declared type of the handle
-    // changing.
-    ObjPtr<mirror::MethodType> nominal_type(method_handle->GetNominalType());
-    ObjPtr<mirror::MethodType> check_type(nullptr);
-    if (LIKELY(nominal_type.Ptr() == nullptr)) {
-      check_type.Assign(handle_type.Get());
-    } else {
-      check_type.Assign(nominal_type.Ptr());
-    }
+  ArtMethod* invoke_method =
+      class_linker->ResolveMethod<ClassLinker::kForceICCECheck>(self,
+                                                                invoke_method_idx,
+                                                                shadow_frame.GetMethod(),
+                                                                kVirtual);
 
-    if (is_invoke_exact) {
-      if (UNLIKELY(!callsite_type->IsExactMatch(check_type.Ptr()))) {
-        ThrowWrongMethodTypeException(check_type.Ptr(), callsite_type.Get());
-        return false;
-      }
-    } else if (!IsInvokeTransform(handle_kind)) {
-      if (UNLIKELY(!IsCallerTransformer(callsite_type) &&
-                   !callsite_type->IsConvertible(check_type.Ptr()))) {
-        ThrowWrongMethodTypeException(check_type.Ptr(), callsite_type.Get());
-        return false;
-      }
-    }
-  }
-
-  uint32_t arg[Instruction::kMaxVarArgRegs] = {};
-  uint32_t first_src_reg = 0;
+  // There is a common dispatch method for method handles that takes
+  // arguments either from a range or an array of arguments depending
+  // on whether the DEX instruction is invoke-polymorphic/range or
+  // invoke-polymorphic. The array here is for the latter.
+  uint32_t args[Instruction::kMaxVarArgRegs] = {};
   if (is_range) {
-    first_src_reg = (inst->VRegC_4rcc() + 1);
+    // VRegC is the register holding the method handle. Arguments passed
+    // to the method handle's target do not include the method handle.
+    uint32_t first_arg = inst->VRegC_4rcc() + 1;
+    return DoInvokePolymorphic<is_range, do_access_check>(self,
+                                                          invoke_method,
+                                                          shadow_frame,
+                                                          method_handle,
+                                                          callsite_type,
+                                                          args /* unused */,
+                                                          first_arg,
+                                                          result);
   } else {
-    inst->GetVarArgs(arg, inst_data);
-    arg[0] = arg[1];
-    arg[1] = arg[2];
-    arg[2] = arg[3];
-    arg[3] = arg[4];
-    arg[4] = 0;
-    first_src_reg = arg[0];
-  }
-
-  if (IsInvoke(handle_kind)) {
-    // Get the method we're actually invoking along with the kind of
-    // invoke that is desired. We don't need to perform access checks at this
-    // point because they would have been performed on our behalf at the point
-    // of creation of the method handle.
-    ArtMethod* called_method = method_handle->GetTargetMethod();
-    CHECK(called_method != nullptr);
-
-    if (handle_kind == kInvokeVirtual || handle_kind == kInvokeInterface) {
-      // TODO: Unfortunately, we have to postpone dynamic receiver based checks
-      // because the receiver might be cast or might come from an emulated stack
-      // frame, which means that it is unknown at this point. We perform these
-      // checks inside DoCallPolymorphic right before we do the actual invoke.
-    } else if (handle_kind == kInvokeDirect) {
-      // String constructors are a special case, they are replaced with StringFactory
-      // methods.
-      if (called_method->IsConstructor() && called_method->GetDeclaringClass()->IsStringClass()) {
-        DCHECK(handle_type->GetRType()->IsStringClass());
-        called_method = WellKnownClasses::StringInitToStringFactory(called_method);
-      }
-    } else if (handle_kind == kInvokeSuper) {
-      ObjPtr<mirror::Class> declaring_class = called_method->GetDeclaringClass();
-
-      // Note that we're not dynamically dispatching on the type of the receiver
-      // here. We use the static type of the "receiver" object that we've
-      // recorded in the method handle's type, which will be the same as the
-      // special caller that was specified at the point of lookup.
-      ObjPtr<mirror::Class> referrer_class = handle_type->GetPTypes()->Get(0);
-      if (!declaring_class->IsInterface()) {
-        ObjPtr<mirror::Class> super_class = referrer_class->GetSuperClass();
-        uint16_t vtable_index = called_method->GetMethodIndex();
-        DCHECK(super_class != nullptr);
-        DCHECK(super_class->HasVTable());
-        // Note that super_class is a super of referrer_class and called_method
-        // will always be declared by super_class (or one of its super classes).
-        DCHECK_LT(vtable_index, super_class->GetVTableLength());
-        called_method = super_class->GetVTableEntry(vtable_index, kRuntimePointerSize);
-      } else {
-        called_method = referrer_class->FindVirtualMethodForInterfaceSuper(
-            called_method, kRuntimePointerSize);
-      }
-
-      CHECK(called_method != nullptr);
-    }
-
-    if (IsInvokeTransform(handle_kind)) {
-      // There are two cases here - method handles representing regular
-      // transforms and those representing call site transforms. Method
-      // handles for call site transforms adapt their MethodType to match
-      // the call site. For these, the |callee_type| is the same as the
-      // |callsite_type|. The VarargsCollector is such a tranform, its
-      // method type depends on the call site, ie. x(a) or x(a, b), or
-      // x(a, b, c). The VarargsCollector invokes a variable arity method
-      // with the arity arguments in an array.
-      Handle<mirror::MethodType> callee_type =
-          (handle_kind == kInvokeCallSiteTransform) ? callsite_type : handle_type;
-      return DoCallTransform<is_range>(called_method,
-                                       callsite_type,
-                                       callee_type,
-                                       self,
-                                       shadow_frame,
-                                       method_handle /* receiver */,
-                                       result,
-                                       arg,
-                                       first_src_reg);
-    } else {
-      return DoCallPolymorphic<is_range>(called_method,
-                                         callsite_type,
-                                         handle_type,
-                                         self,
-                                         shadow_frame,
-                                         result,
-                                         arg,
-                                         first_src_reg,
-                                         handle_kind);
-    }
-  } else {
-    DCHECK(!is_range);
-    ArtField* field = method_handle->GetTargetField();
-    Primitive::Type field_type = field->GetTypeAsPrimitiveType();
-
-    switch (handle_kind) {
-      case kInstanceGet: {
-        ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(first_src_reg);
-        DoFieldGetForInvokePolymorphic(self, shadow_frame, obj, field, field_type, result);
-        if (!ConvertReturnValue(callsite_type, handle_type, result)) {
-          DCHECK(self->IsExceptionPending());
-          return false;
-        }
-        return true;
-      }
-      case kStaticGet: {
-        ObjPtr<mirror::Object> obj = GetAndInitializeDeclaringClass(self, field);
-        if (obj == nullptr) {
-          DCHECK(self->IsExceptionPending());
-          return false;
-        }
-        DoFieldGetForInvokePolymorphic(self, shadow_frame, obj, field, field_type, result);
-        if (!ConvertReturnValue(callsite_type, handle_type, result)) {
-          DCHECK(self->IsExceptionPending());
-          return false;
-        }
-        return true;
-      }
-      case kInstancePut: {
-        JValue value = GetFieldValue(shadow_frame, field_type, arg[1]);
-        if (!ConvertArgumentValue(callsite_type, handle_type, 1, &value)) {
-          DCHECK(self->IsExceptionPending());
-          return false;
-        }
-        ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(first_src_reg);
-        return DoFieldPutForInvokePolymorphic(self, shadow_frame, obj, field, field_type, value);
-      }
-      case kStaticPut: {
-        JValue value = GetFieldValue(shadow_frame, field_type, arg[0]);
-        if (!ConvertArgumentValue(callsite_type, handle_type, 0, &value)) {
-          DCHECK(self->IsExceptionPending());
-          return false;
-        }
-        ObjPtr<mirror::Object> obj = field->GetDeclaringClass();
-        return DoFieldPutForInvokePolymorphic(self, shadow_frame, obj, field, field_type, value);
-      }
-      default:
-        LOG(FATAL) << "Unreachable: " << handle_kind;
-        UNREACHABLE();
-    }
-  }
-}
-
-// Calculate the number of ins for a proxy or native method, where we
-// can't just look at the code item.
-static inline size_t GetInsForProxyOrNativeMethod(ArtMethod* method)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  DCHECK(method->IsNative() || method->IsProxyMethod());
-
-  method = method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
-  size_t num_ins = 0;
-  // Separate accounting for the receiver, which isn't a part of the
-  // shorty.
-  if (!method->IsStatic()) {
-    ++num_ins;
-  }
-
-  uint32_t shorty_len = 0;
-  const char* shorty = method->GetShorty(&shorty_len);
-  for (size_t i = 1; i < shorty_len; ++i) {
-    const char c = shorty[i];
-    ++num_ins;
-    if (c == 'J' || c == 'D') {
-      ++num_ins;
-    }
-  }
-
-  return num_ins;
-}
-
-inline void PerformCall(Thread* self,
-                        const DexFile::CodeItem* code_item,
-                        ArtMethod* caller_method,
-                        const size_t first_dest_reg,
-                        ShadowFrame* callee_frame,
-                        JValue* result) {
-  if (LIKELY(Runtime::Current()->IsStarted())) {
-    ArtMethod* target = callee_frame->GetMethod();
-    if (ClassLinker::ShouldUseInterpreterEntrypoint(
-        target,
-        target->GetEntryPointFromQuickCompiledCode())) {
-      ArtInterpreterToInterpreterBridge(self, code_item, callee_frame, result);
-    } else {
-      ArtInterpreterToCompiledCodeBridge(
-          self, caller_method, code_item, callee_frame, result);
-    }
-  } else {
-    UnstartedRuntime::Invoke(self, code_item, callee_frame, result, first_dest_reg);
+    // Get the register arguments for the invoke.
+    inst->GetVarArgs(args, inst_data);
+    // Drop the first register which is the method handle performing the invoke.
+    memcpy(args, args + 1, sizeof(args[0]) * (Instruction::kMaxVarArgRegs - 1));
+    args[Instruction::kMaxVarArgRegs - 1] = 0;
+    return DoInvokePolymorphic<is_range, do_access_check>(self,
+                                                          invoke_method,
+                                                          shadow_frame,
+                                                          method_handle,
+                                                          callsite_type,
+                                                          args,
+                                                          args[0],
+                                                          result);
   }
 }
 
@@ -1139,217 +631,6 @@
   }
 }
 
-template <bool is_range>
-static inline bool DoCallPolymorphic(ArtMethod* called_method,
-                                     Handle<mirror::MethodType> callsite_type,
-                                     Handle<mirror::MethodType> target_type,
-                                     Thread* self,
-                                     ShadowFrame& shadow_frame,
-                                     JValue* result,
-                                     uint32_t (&arg)[Instruction::kMaxVarArgRegs],
-                                     uint32_t first_src_reg,
-                                     const MethodHandleKind handle_kind) {
-  // Compute method information.
-  const DexFile::CodeItem* code_item = called_method->GetCodeItem();
-
-  // Number of registers for the callee's call frame. Note that for non-exact
-  // invokes, we always derive this information from the callee method. We
-  // cannot guarantee during verification that the number of registers encoded
-  // in the invoke is equal to the number of ins for the callee. This is because
-  // some transformations (such as boxing a long -> Long or wideining an
-  // int -> long will change that number.
-  uint16_t num_regs;
-  size_t num_input_regs;
-  size_t first_dest_reg;
-  if (LIKELY(code_item != nullptr)) {
-    num_regs = code_item->registers_size_;
-    first_dest_reg = num_regs - code_item->ins_size_;
-    num_input_regs = code_item->ins_size_;
-    // Parameter registers go at the end of the shadow frame.
-    DCHECK_NE(first_dest_reg, (size_t)-1);
-  } else {
-    // No local regs for proxy and native methods.
-    DCHECK(called_method->IsNative() || called_method->IsProxyMethod());
-    num_regs = num_input_regs = GetInsForProxyOrNativeMethod(called_method);
-    first_dest_reg = 0;
-  }
-
-  // Allocate shadow frame on the stack.
-  ShadowFrameAllocaUniquePtr shadow_frame_unique_ptr =
-      CREATE_SHADOW_FRAME(num_regs, &shadow_frame, called_method, /* dex pc */ 0);
-  ShadowFrame* new_shadow_frame = shadow_frame_unique_ptr.get();
-
-  // Whether this polymorphic invoke was issued by a transformer method.
-  bool is_caller_transformer = false;
-  // Thread might be suspended during PerformArgumentConversions due to the
-  // allocations performed during boxing.
-  {
-    ScopedStackedShadowFramePusher pusher(
-        self, new_shadow_frame, StackedShadowFrameType::kShadowFrameUnderConstruction);
-    if (callsite_type->IsExactMatch(target_type.Get())) {
-      // This is an exact invoke, we can take the fast path of just copying all
-      // registers without performing any argument conversions.
-      CopyRegisters<is_range>(shadow_frame,
-                              new_shadow_frame,
-                              arg,
-                              first_src_reg,
-                              first_dest_reg,
-                              num_input_regs);
-    } else {
-      // This includes the case where we're entering this invoke-polymorphic
-      // from a transformer method. In that case, the callsite_type will contain
-      // a single argument of type dalvik.system.EmulatedStackFrame. In that
-      // case, we'll have to unmarshal the EmulatedStackFrame into the
-      // new_shadow_frame and perform argument conversions on it.
-      if (IsCallerTransformer(callsite_type)) {
-        is_caller_transformer = true;
-        // The emulated stack frame is the first and only argument when we're coming
-        // through from a transformer.
-        ObjPtr<mirror::EmulatedStackFrame> emulated_stack_frame(
-            reinterpret_cast<mirror::EmulatedStackFrame*>(
-                shadow_frame.GetVRegReference(first_src_reg)));
-        if (!emulated_stack_frame->WriteToShadowFrame(self,
-                                                      target_type,
-                                                      first_dest_reg,
-                                                      new_shadow_frame)) {
-          DCHECK(self->IsExceptionPending());
-          result->SetL(0);
-          return false;
-        }
-      } else if (!ConvertAndCopyArgumentsFromCallerFrame<is_range>(self,
-                                                                   callsite_type,
-                                                                   target_type,
-                                                                   shadow_frame,
-                                                                   first_src_reg,
-                                                                   first_dest_reg,
-                                                                   arg,
-                                                                   new_shadow_frame)) {
-        DCHECK(self->IsExceptionPending());
-        result->SetL(0);
-        return false;
-      }
-    }
-  }
-
-  // See TODO in DoInvokePolymorphic : We need to perform this dynamic, receiver
-  // based dispatch right before we perform the actual call, because the
-  // receiver isn't known very early.
-  if (handle_kind == kInvokeVirtual || handle_kind == kInvokeInterface) {
-    ObjPtr<mirror::Object> receiver(new_shadow_frame->GetVRegReference(first_dest_reg));
-    ObjPtr<mirror::Class> declaring_class(called_method->GetDeclaringClass());
-    // Verify that _vRegC is an object reference and of the type expected by
-    // the receiver.
-    if (!VerifyObjectIsClass(receiver, declaring_class)) {
-      DCHECK(self->IsExceptionPending());
-      return false;
-    }
-
-    called_method = receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(
-        called_method, kRuntimePointerSize);
-  }
-
-  PerformCall(self, code_item, shadow_frame.GetMethod(), first_dest_reg, new_shadow_frame, result);
-  if (self->IsExceptionPending()) {
-    return false;
-  }
-
-  // If the caller of this signature polymorphic method was a transformer,
-  // we need to copy the result back out to the emulated stack frame.
-  if (is_caller_transformer) {
-    StackHandleScope<2> hs(self);
-    Handle<mirror::EmulatedStackFrame> emulated_stack_frame(
-        hs.NewHandle(reinterpret_cast<mirror::EmulatedStackFrame*>(
-            shadow_frame.GetVRegReference(first_src_reg))));
-    Handle<mirror::MethodType> emulated_stack_type(hs.NewHandle(emulated_stack_frame->GetType()));
-    JValue local_result;
-    local_result.SetJ(result->GetJ());
-
-    if (ConvertReturnValue(emulated_stack_type, target_type, &local_result)) {
-      emulated_stack_frame->SetReturnValue(self, local_result);
-      return true;
-    } else {
-      DCHECK(self->IsExceptionPending());
-      return false;
-    }
-  } else {
-    return ConvertReturnValue(callsite_type, target_type, result);
-  }
-}
-
-template <bool is_range>
-static inline bool DoCallTransform(ArtMethod* called_method,
-                                   Handle<mirror::MethodType> callsite_type,
-                                   Handle<mirror::MethodType> callee_type,
-                                   Thread* self,
-                                   ShadowFrame& shadow_frame,
-                                   Handle<mirror::MethodHandleImpl> receiver,
-                                   JValue* result,
-                                   uint32_t (&arg)[Instruction::kMaxVarArgRegs],
-                                   uint32_t first_src_reg) {
-  // This can be fixed to two, because the method we're calling here
-  // (MethodHandle.transformInternal) doesn't have any locals and the signature
-  // is known :
-  //
-  // private MethodHandle.transformInternal(EmulatedStackFrame sf);
-  //
-  // This means we need only two vregs :
-  // - One for the receiver object.
-  // - One for the only method argument (an EmulatedStackFrame).
-  static constexpr size_t kNumRegsForTransform = 2;
-
-  const DexFile::CodeItem* code_item = called_method->GetCodeItem();
-  DCHECK(code_item != nullptr);
-  DCHECK_EQ(kNumRegsForTransform, code_item->registers_size_);
-  DCHECK_EQ(kNumRegsForTransform, code_item->ins_size_);
-
-  ShadowFrameAllocaUniquePtr shadow_frame_unique_ptr =
-      CREATE_SHADOW_FRAME(kNumRegsForTransform, &shadow_frame, called_method, /* dex pc */ 0);
-  ShadowFrame* new_shadow_frame = shadow_frame_unique_ptr.get();
-
-  StackHandleScope<1> hs(self);
-  MutableHandle<mirror::EmulatedStackFrame> sf(hs.NewHandle<mirror::EmulatedStackFrame>(nullptr));
-  if (IsCallerTransformer(callsite_type)) {
-    // If we're entering this transformer from another transformer, we can pass
-    // through the handle directly to the callee, instead of having to
-    // instantiate a new stack frame based on the shadow frame.
-    sf.Assign(reinterpret_cast<mirror::EmulatedStackFrame*>(
-        shadow_frame.GetVRegReference(first_src_reg)));
-  } else {
-    sf.Assign(mirror::EmulatedStackFrame::CreateFromShadowFrameAndArgs<is_range>(
-        self,
-        callsite_type,
-        callee_type,
-        shadow_frame,
-        first_src_reg,
-        arg));
-
-    // Something went wrong while creating the emulated stack frame, we should
-    // throw the pending exception.
-    if (sf.Get() == nullptr) {
-      DCHECK(self->IsExceptionPending());
-      return false;
-    }
-  }
-
-  new_shadow_frame->SetVRegReference(0, receiver.Get());
-  new_shadow_frame->SetVRegReference(1, sf.Get());
-
-  PerformCall(self,
-              code_item,
-              shadow_frame.GetMethod(),
-              0 /* first dest reg */,
-              new_shadow_frame,
-              result);
-  if (self->IsExceptionPending()) {
-    return false;
-  }
-
-  // If the called transformer method we called has returned a value, then we
-  // need to copy it back to |result|.
-  sf->GetReturnValue(self, result);
-  return ConvertReturnValue(callsite_type, callee_type, result);
-}
-
 template <bool is_range,
           bool do_assignability_check>
 static inline bool DoCallCommon(ArtMethod* called_method,