/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "method_handles-inl.h"

#include "android-base/macros.h"
#include "android-base/stringprintf.h"
#include "class_root-inl.h"
#include "common_dex_operations.h"
#include "common_throws.h"
#include "interpreter/shadow_frame-inl.h"
#include "interpreter/shadow_frame.h"
#include "jvalue-inl.h"
#include "mirror/class-inl.h"
#include "mirror/emulated_stack_frame-inl.h"
#include "mirror/emulated_stack_frame.h"
#include "mirror/method_handle_impl-inl.h"
#include "mirror/method_handle_impl.h"
#include "mirror/method_type-inl.h"
#include "mirror/var_handle.h"
#include "reflection-inl.h"
#include "reflection.h"
#include "thread.h"
#include "well_known_classes.h"

namespace art {

using android::base::StringPrintf;

namespace {

#define PRIMITIVES_LIST(V) \
  V(Primitive::kPrimBoolean, Boolean, Boolean, Z) \
  V(Primitive::kPrimByte, Byte, Byte, B)          \
  V(Primitive::kPrimChar, Char, Character, C)     \
  V(Primitive::kPrimShort, Short, Short, S)       \
  V(Primitive::kPrimInt, Int, Integer, I)         \
  V(Primitive::kPrimLong, Long, Long, J)          \
  V(Primitive::kPrimFloat, Float, Float, F)       \
  V(Primitive::kPrimDouble, Double, Double, D)

// Assigns |type| to the primitive type associated with |klass|. Returns
// true iff. |klass| was a boxed type (Integer, Long etc.), false otherwise.
bool GetUnboxedPrimitiveType(ObjPtr<mirror::Class> klass, Primitive::Type* type)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  ScopedAssertNoThreadSuspension ants(__FUNCTION__);
  std::string storage;
  const char* descriptor = klass->GetDescriptor(&storage);
  static const char kJavaLangPrefix[] = "Ljava/lang/";
  static const size_t kJavaLangPrefixSize = sizeof(kJavaLangPrefix) - 1;
  if (strncmp(descriptor, kJavaLangPrefix, kJavaLangPrefixSize) != 0) {
    return false;
  }

  descriptor += kJavaLangPrefixSize;
#define LOOKUP_PRIMITIVE(primitive, _, java_name, ___) \
  if (strcmp(descriptor, #java_name ";") == 0) {       \
    *type = primitive;                                 \
    return true;                                       \
  }

  PRIMITIVES_LIST(LOOKUP_PRIMITIVE);
#undef LOOKUP_PRIMITIVE
  return false;
}

ObjPtr<mirror::Class> GetBoxedPrimitiveClass(Primitive::Type type)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  ScopedAssertNoThreadSuspension ants(__FUNCTION__);
  jmethodID m = nullptr;
  switch (type) {
#define CASE_PRIMITIVE(primitive, _, java_name, __)              \
    case primitive:                                              \
      m = WellKnownClasses::java_lang_ ## java_name ## _valueOf; \
      break;
    PRIMITIVES_LIST(CASE_PRIMITIVE);
#undef CASE_PRIMITIVE
    case Primitive::Type::kPrimNot:
    case Primitive::Type::kPrimVoid:
      return nullptr;
  }
  return jni::DecodeArtMethod(m)->GetDeclaringClass();
}

bool GetUnboxedTypeAndValue(ObjPtr<mirror::Object> o, Primitive::Type* type, JValue* value)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  ScopedAssertNoThreadSuspension ants(__FUNCTION__);
  ObjPtr<mirror::Class> klass = o->GetClass();
  ArtField* primitive_field = &klass->GetIFieldsPtr()->At(0);
#define CASE_PRIMITIVE(primitive, abbrev, _, shorthand)         \
  if (klass == GetBoxedPrimitiveClass(primitive)) {             \
    *type = primitive;                                          \
    value->Set ## shorthand(primitive_field->Get ## abbrev(o)); \
    return true;                                                \
  }
  PRIMITIVES_LIST(CASE_PRIMITIVE)
#undef CASE_PRIMITIVE
  return false;
}

inline bool IsReferenceType(Primitive::Type type) {
  return type == Primitive::kPrimNot;
}

inline bool IsPrimitiveType(Primitive::Type type) {
  return !IsReferenceType(type);
}

}  // namespace

bool IsParameterTypeConvertible(ObjPtr<mirror::Class> from, ObjPtr<mirror::Class> to)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  // This function returns true if there's any conceivable conversion
  // between |from| and |to|. It's expected this method will be used
  // to determine if a WrongMethodTypeException should be raised. The
  // decision logic follows the documentation for MethodType.asType().
  if (from == to) {
    return true;
  }

  Primitive::Type from_primitive = from->GetPrimitiveType();
  Primitive::Type to_primitive = to->GetPrimitiveType();
  DCHECK(from_primitive != Primitive::Type::kPrimVoid);
  DCHECK(to_primitive != Primitive::Type::kPrimVoid);

  // If |to| and |from| are references.
  if (IsReferenceType(from_primitive) && IsReferenceType(to_primitive)) {
    // Assignability is determined during parameter conversion when
    // invoking the associated method handle.
    return true;
  }

  // If |to| and |from| are primitives and a widening conversion exists.
  if (Primitive::IsWidenable(from_primitive, to_primitive)) {
    return true;
  }

  // If |to| is a reference and |from| is a primitive, then boxing conversion.
  if (IsReferenceType(to_primitive) && IsPrimitiveType(from_primitive)) {
    return to->IsAssignableFrom(GetBoxedPrimitiveClass(from_primitive));
  }

  // If |from| is a reference and |to| is a primitive, then unboxing conversion.
  if (IsPrimitiveType(to_primitive) && IsReferenceType(from_primitive)) {
    if (from->DescriptorEquals("Ljava/lang/Object;")) {
      // Object might be converted into a primitive during unboxing.
      return true;
    }

    if (Primitive::IsNumericType(to_primitive) && from->DescriptorEquals("Ljava/lang/Number;")) {
      // Number might be unboxed into any of the number primitive types.
      return true;
    }

    Primitive::Type unboxed_type;
    if (GetUnboxedPrimitiveType(from, &unboxed_type)) {
      if (unboxed_type == to_primitive) {
        // Straightforward unboxing conversion such as Boolean => boolean.
        return true;
      }

      // Check if widening operations for numeric primitives would work,
      // such as Byte => byte => long.
      return Primitive::IsWidenable(unboxed_type, to_primitive);
    }
  }

  return false;
}

bool IsReturnTypeConvertible(ObjPtr<mirror::Class> from, ObjPtr<mirror::Class> to)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  if (to->GetPrimitiveType() == Primitive::Type::kPrimVoid) {
    // Result will be ignored.
    return true;
  } else if (from->GetPrimitiveType() == Primitive::Type::kPrimVoid) {
    // Returned value will be 0 / null.
    return true;
  } else {
    // Otherwise apply usual parameter conversion rules.
    return IsParameterTypeConvertible(from, to);
  }
}

bool ConvertJValueCommon(
    Handle<mirror::MethodType> callsite_type,
    Handle<mirror::MethodType> callee_type,
    ObjPtr<mirror::Class> from,
    ObjPtr<mirror::Class> to,
    JValue* value) {
  // The reader maybe concerned about the safety of the heap object
  // that may be in |value|. There is only one case where allocation
  // is obviously needed and that's for boxing. However, in the case
  // of boxing |value| contains a non-reference type.

  const Primitive::Type from_type = from->GetPrimitiveType();
  const Primitive::Type to_type = to->GetPrimitiveType();

  // Put incoming value into |src_value| and set return value to 0.
  // Errors and conversions from void require the return value to be 0.
  const JValue src_value(*value);
  value->SetJ(0);

  // Conversion from void set result to zero.
  if (from_type == Primitive::kPrimVoid) {
    return true;
  }

  // This method must be called only when the types don't match.
  DCHECK(from != to);

  if (IsPrimitiveType(from_type) && IsPrimitiveType(to_type)) {
    // The source and target types are both primitives.
    if (UNLIKELY(!ConvertPrimitiveValueNoThrow(from_type, to_type, src_value, value))) {
      ThrowWrongMethodTypeException(callee_type.Get(), callsite_type.Get());
      return false;
    }
    return true;
  } else if (IsReferenceType(from_type) && IsReferenceType(to_type)) {
    // They're both reference types. If "from" is null, we can pass it
    // through unchanged. If not, we must generate a cast exception if
    // |to| is not assignable from the dynamic type of |ref|.
    //
    // Playing it safe with StackHandleScope here, not expecting any allocation
    // in mirror::Class::IsAssignable().
    StackHandleScope<2> hs(Thread::Current());
    Handle<mirror::Class> h_to(hs.NewHandle(to));
    Handle<mirror::Object> h_obj(hs.NewHandle(src_value.GetL()));
    if (UNLIKELY(!h_obj.IsNull() && !to->IsAssignableFrom(h_obj->GetClass()))) {
      ThrowClassCastException(h_to.Get(), h_obj->GetClass());
      return false;
    }
    value->SetL(h_obj.Get());
    return true;
  } else if (IsReferenceType(to_type)) {
    DCHECK(IsPrimitiveType(from_type));
    // The source type is a primitive and the target type is a reference, so we must box.
    // The target type maybe a super class of the boxed source type, for example,
    // if the source type is int, it's boxed type is java.lang.Integer, and the target
    // type could be java.lang.Number.
    Primitive::Type type;
    if (!GetUnboxedPrimitiveType(to, &type)) {
      ObjPtr<mirror::Class> boxed_from_class = GetBoxedPrimitiveClass(from_type);
      if (LIKELY(boxed_from_class->IsSubClass(to))) {
        type = from_type;
      } else {
        ThrowWrongMethodTypeException(callee_type.Get(), callsite_type.Get());
        return false;
      }
    }

    if (UNLIKELY(from_type != type)) {
      ThrowWrongMethodTypeException(callee_type.Get(), callsite_type.Get());
      return false;
    }

    if (UNLIKELY(!ConvertPrimitiveValueNoThrow(from_type, type, src_value, value))) {
      ThrowWrongMethodTypeException(callee_type.Get(), callsite_type.Get());
      return false;
    }

    // Then perform the actual boxing, and then set the reference.
    ObjPtr<mirror::Object> boxed = BoxPrimitive(type, src_value);
    value->SetL(boxed);
    return true;
  } else {
    // The source type is a reference and the target type is a primitive, so we must unbox.
    DCHECK(IsReferenceType(from_type));
    DCHECK(IsPrimitiveType(to_type));

    ObjPtr<mirror::Object> from_obj(src_value.GetL());
    if (UNLIKELY(from_obj.IsNull())) {
      ThrowNullPointerException(
          StringPrintf("Expected to unbox a '%s' primitive type but was returned null",
                       from->PrettyDescriptor().c_str()).c_str());
      return false;
    }

    Primitive::Type unboxed_type;
    JValue unboxed_value;
    if (UNLIKELY(!GetUnboxedTypeAndValue(from_obj, &unboxed_type, &unboxed_value))) {
      ThrowWrongMethodTypeException(callee_type.Get(), callsite_type.Get());
      return false;
    }

    if (UNLIKELY(!ConvertPrimitiveValueNoThrow(unboxed_type, to_type, unboxed_value, value))) {
      if (from->IsAssignableFrom(GetBoxedPrimitiveClass(to_type))) {
        // CallSite may be Number, but the Number object is
        // incompatible, e.g. Number (Integer) for a short.
        ThrowClassCastException(from, to);
      } else {
        // CallSite is incompatible, e.g. Integer for a short.
        ThrowWrongMethodTypeException(callee_type.Get(), callsite_type.Get());
      }
      return false;
    }

    return true;
  }
}

namespace {

inline void CopyArgumentsFromCallerFrame(const ShadowFrame& caller_frame,
                                         ShadowFrame* callee_frame,
                                         const InstructionOperands* const operands,
                                         const size_t first_dst_reg)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  for (size_t i = 0; i < operands->GetNumberOfOperands(); ++i) {
    size_t dst_reg = first_dst_reg + i;
    size_t src_reg = operands->GetOperand(i);
    // Uint required, so that sign extension does not make this wrong on 64-bit systems
    uint32_t src_value = caller_frame.GetVReg(src_reg);
    ObjPtr<mirror::Object> o = caller_frame.GetVRegReference<kVerifyNone>(src_reg);
    // If both register locations contains the same value, the register probably holds a reference.
    // Note: As an optimization, non-moving collectors leave a stale reference value
    // in the references array even after the original vreg was overwritten to a non-reference.
    if (src_value == reinterpret_cast<uintptr_t>(o.Ptr())) {
      callee_frame->SetVRegReference(dst_reg, o);
    } else {
      callee_frame->SetVReg(dst_reg, src_value);
    }
  }
}

inline bool ConvertAndCopyArgumentsFromCallerFrame(
    Thread* self,
    Handle<mirror::MethodType> callsite_type,
    Handle<mirror::MethodType> callee_type,
    const ShadowFrame& caller_frame,
    uint32_t first_dest_reg,
    const InstructionOperands* const operands,
    ShadowFrame* callee_frame)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  ObjPtr<mirror::ObjectArray<mirror::Class>> from_types(callsite_type->GetPTypes());
  ObjPtr<mirror::ObjectArray<mirror::Class>> to_types(callee_type->GetPTypes());

  const int32_t num_method_params = from_types->GetLength();
  if (to_types->GetLength() != num_method_params) {
    ThrowWrongMethodTypeException(callee_type.Get(), callsite_type.Get());
    return false;
  }

  ShadowFrameGetter getter(caller_frame, operands);
  ShadowFrameSetter setter(callee_frame, first_dest_reg);
  return PerformConversions<ShadowFrameGetter, ShadowFrameSetter>(self,
                                                                  callsite_type,
                                                                  callee_type,
                                                                  &getter,
                                                                  &setter,
                                                                  num_method_params);
}

inline bool IsInvoke(const mirror::MethodHandle::Kind handle_kind) {
  return handle_kind <= mirror::MethodHandle::Kind::kLastInvokeKind;
}

inline bool IsInvokeTransform(const mirror::MethodHandle::Kind handle_kind) {
  return (handle_kind == mirror::MethodHandle::Kind::kInvokeTransform
          || handle_kind == mirror::MethodHandle::Kind::kInvokeCallSiteTransform);
}

inline bool IsInvokeVarHandle(const mirror::MethodHandle::Kind handle_kind) {
  return (handle_kind == mirror::MethodHandle::Kind::kInvokeVarHandle ||
          handle_kind == mirror::MethodHandle::Kind::kInvokeVarHandleExact);
}

inline bool IsFieldAccess(mirror::MethodHandle::Kind handle_kind) {
  return (handle_kind >= mirror::MethodHandle::Kind::kFirstAccessorKind
          && handle_kind <= mirror::MethodHandle::Kind::kLastAccessorKind);
}

// 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);
  uint32_t shorty_length = 0;
  const char* shorty = method->GetShorty(&shorty_length);

  // Static methods do not include the receiver. The receiver isn't included
  // in the shorty_length though the return value is.
  size_t num_ins = method->IsStatic() ? shorty_length - 1 : shorty_length;
  for (const char* c = shorty + 1; *c != '\0'; ++c) {
    if (*c == 'J' || *c == 'D') {
      ++num_ins;
    }
  }
  return num_ins;
}

// 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 InvokedFromTransform(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));
    // NB Comparing descriptor here as it appears faster in cycle simulation than using:
    //   param == WellKnownClasses::ToClass(WellKnownClasses::dalvik_system_EmulatedStackFrame)
    // Costs are 98 vs 173 cycles per invocation.
    return param->DescriptorEquals("Ldalvik/system/EmulatedStackFrame;");
  }

  return false;
}

static inline bool MethodHandleInvokeMethod(ArtMethod* called_method,
                                            Handle<mirror::MethodType> callsite_type,
                                            Handle<mirror::MethodType> target_type,
                                            Thread* self,
                                            ShadowFrame& shadow_frame,
                                            const InstructionOperands* const operands,
                                            JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
  // Compute method information.
  CodeItemDataAccessor accessor(called_method->DexInstructionData());

  // 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(accessor.HasCodeItem())) {
    num_regs = accessor.RegistersSize();
    first_dest_reg = num_regs - accessor.InsSize();
    num_input_regs = accessor.InsSize();
    // 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.
      CopyArgumentsFromCallerFrame(shadow_frame,
                                   new_shadow_frame,
                                   operands,
                                   first_dest_reg);
    } 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 (InvokedFromTransform(callsite_type)) {
        is_caller_transformer = true;
        // The emulated stack frame is the first and only argument when we're coming
        // through from a transformer.
        size_t first_arg_register = operands->GetOperand(0);
        ObjPtr<mirror::EmulatedStackFrame> emulated_stack_frame(
            ObjPtr<mirror::EmulatedStackFrame>::DownCast(
                shadow_frame.GetVRegReference(first_arg_register)));
        if (!emulated_stack_frame->WriteToShadowFrame(self,
                                                      target_type,
                                                      first_dest_reg,
                                                      new_shadow_frame)) {
          DCHECK(self->IsExceptionPending());
          result->SetL(nullptr);
          return false;
        }
      } else {
        if (!callsite_type->IsConvertible(target_type.Get())) {
          ThrowWrongMethodTypeException(target_type.Get(), callsite_type.Get());
          return false;
        }
        if (!ConvertAndCopyArgumentsFromCallerFrame(self,
                                                    callsite_type,
                                                    target_type,
                                                    shadow_frame,
                                                    first_dest_reg,
                                                    operands,
                                                    new_shadow_frame)) {
          DCHECK(self->IsExceptionPending());
          result->SetL(nullptr);
          return false;
        }
      }
    }
  }

  PerformCall(self,
              accessor,
              shadow_frame.GetMethod(),
              first_dest_reg,
              new_shadow_frame,
              result,
              interpreter::ShouldStayInSwitchInterpreter(called_method));
  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);
    size_t first_callee_register = operands->GetOperand(0);
    Handle<mirror::EmulatedStackFrame> emulated_stack_frame(
        hs.NewHandle(ObjPtr<mirror::EmulatedStackFrame>::DownCast(
            shadow_frame.GetVRegReference(first_callee_register))));
    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;
    }

    DCHECK(self->IsExceptionPending());
    return false;
  }
  return ConvertReturnValue(callsite_type, target_type, result);
}

static inline bool MethodHandleInvokeTransform(ArtMethod* called_method,
                                               Handle<mirror::MethodType> callsite_type,
                                               Handle<mirror::MethodType> callee_type,
                                               Thread* self,
                                               ShadowFrame& shadow_frame,
                                               Handle<mirror::MethodHandle> receiver,
                                               const InstructionOperands* const operands,
                                               JValue* result)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  // 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;

  CodeItemDataAccessor accessor(called_method->DexInstructionData());
  DCHECK_EQ(kNumRegsForTransform, accessor.RegistersSize());
  DCHECK_EQ(kNumRegsForTransform, accessor.InsSize());

  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 (InvokedFromTransform(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.
    size_t first_callee_register = operands->GetOperand(0);
    sf.Assign(ObjPtr<mirror::EmulatedStackFrame>::DownCast(
        shadow_frame.GetVRegReference(first_callee_register)));
  } else {
    sf.Assign(mirror::EmulatedStackFrame::CreateFromShadowFrameAndArgs(self,
                                                                       callsite_type,
                                                                       callee_type,
                                                                       shadow_frame,
                                                                       operands));

    // Something went wrong while creating the emulated stack frame, we should
    // throw the pending exception.
    if (sf == nullptr) {
      DCHECK(self->IsExceptionPending());
      return false;
    }
  }

  new_shadow_frame->SetVRegReference(0, receiver.Get());
  new_shadow_frame->SetVRegReference(1, sf.Get());

  PerformCall(self,
              accessor,
              shadow_frame.GetMethod(),
              0 /* first destination register */,
              new_shadow_frame,
              result,
              interpreter::ShouldStayInSwitchInterpreter(called_method));
  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);
}

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;
}

ArtMethod* RefineTargetMethod(Thread* self,
                              ShadowFrame& shadow_frame,
                              const mirror::MethodHandle::Kind& handle_kind,
                              Handle<mirror::MethodType> handle_type,
                              Handle<mirror::MethodType> callsite_type,
                              const uint32_t receiver_reg,
                              ArtMethod* target_method)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  if (handle_kind == mirror::MethodHandle::Kind::kInvokeVirtual ||
      handle_kind == mirror::MethodHandle::Kind::kInvokeInterface) {
    // For virtual and interface methods ensure target_method points to
    // the actual method to invoke.
    ObjPtr<mirror::Object> receiver(shadow_frame.GetVRegReference(receiver_reg));
    if (InvokedFromTransform(callsite_type)) {
      // The current receiver is an emulated stack frame, the method's
      // receiver needs to be fetched from there as the emulated frame
      // will be unpacked into a new frame.
      receiver = ObjPtr<mirror::EmulatedStackFrame>::DownCast(receiver)->GetReceiver();
    }

    ObjPtr<mirror::Class> declaring_class(target_method->GetDeclaringClass());
    if (receiver == nullptr || receiver->GetClass() != declaring_class) {
      // Verify that _vRegC is an object reference and of the type expected by
      // the receiver.
      if (!VerifyObjectIsClass(receiver, declaring_class)) {
        DCHECK(self->IsExceptionPending());
        return nullptr;
      }
      return receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(
          target_method, kRuntimePointerSize);
    }
  } else if (handle_kind == mirror::MethodHandle::Kind::kInvokeDirect) {
    // String constructors are a special case, they are replaced with
    // StringFactory methods.
    if (target_method->IsConstructor() && target_method->GetDeclaringClass()->IsStringClass()) {
      DCHECK(handle_type->GetRType()->IsStringClass());
      return WellKnownClasses::StringInitToStringFactory(target_method);
    }
  } else if (handle_kind == mirror::MethodHandle::Kind::kInvokeSuper) {
    // 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);
    ObjPtr<mirror::Class> declaring_class = target_method->GetDeclaringClass();
    if (referrer_class == declaring_class) {
      return target_method;
    }
    if (declaring_class->IsInterface()) {
      if (target_method->IsAbstract()) {
        std::string msg =
            "Method " + target_method->PrettyMethod() + " is abstract interface method!";
        ThrowIllegalAccessException(msg.c_str());
        return nullptr;
      }
    } else {
      ObjPtr<mirror::Class> super_class = referrer_class->GetSuperClass();
      uint16_t vtable_index = target_method->GetMethodIndex();
      DCHECK(super_class != nullptr);
      DCHECK(super_class->HasVTable());
      // Note that super_class is a super of referrer_class and target_method
      // will always be declared by super_class (or one of its super classes).
      DCHECK_LT(vtable_index, super_class->GetVTableLength());
      return super_class->GetVTableEntry(vtable_index, kRuntimePointerSize);
    }
  }
  return target_method;
}

bool DoInvokePolymorphicMethod(Thread* self,
                               ShadowFrame& shadow_frame,
                               Handle<mirror::MethodHandle> method_handle,
                               Handle<mirror::MethodType> callsite_type,
                               const InstructionOperands* const operands,
                               JValue* result)
  REQUIRES_SHARED(Locks::mutator_lock_) {
  StackHandleScope<2> hs(self);
  Handle<mirror::MethodType> handle_type(hs.NewHandle(method_handle->GetMethodType()));
  const mirror::MethodHandle::Kind handle_kind = method_handle->GetHandleKind();
  DCHECK(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* target_method = method_handle->GetTargetMethod();
  uint32_t receiver_reg = (operands->GetNumberOfOperands() > 0) ? operands->GetOperand(0) : 0u;
  ArtMethod* called_method = RefineTargetMethod(self,
                                                shadow_frame,
                                                handle_kind,
                                                handle_type,
                                                callsite_type,
                                                receiver_reg,
                                                target_method);
  if (called_method == nullptr) {
    DCHECK(self->IsExceptionPending());
    return false;
  }

  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 == mirror::MethodHandle::Kind::kInvokeCallSiteTransform) ? callsite_type
        : handle_type;
    return MethodHandleInvokeTransform(called_method,
                                       callsite_type,
                                       callee_type,
                                       self,
                                       shadow_frame,
                                       /* receiver= */ method_handle,
                                       operands,
                                       result);
  } else {
    return MethodHandleInvokeMethod(called_method,
                                    callsite_type,
                                    handle_type,
                                    self,
                                    shadow_frame,
                                    operands,
                                    result);
  }
}

// Helper for getters in invoke-polymorphic.
inline static void MethodHandleFieldGet(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();
  }
}

// Helper for setters in invoke-polymorphic.
inline bool MethodHandleFieldPut(Thread* self,
                                 ShadowFrame& shadow_frame,
                                 ObjPtr<mirror::Object>& obj,
                                 ArtField* field,
                                 Primitive::Type field_type,
                                 JValue& value)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  DCHECK(!Runtime::Current()->IsActiveTransaction());
  static const bool kTransaction = false;         // Not in a transaction.
  static const bool kAssignabilityCheck = false;  // No access check.
  switch (field_type) {
    case Primitive::kPrimBoolean:
      return
          DoFieldPutCommon<Primitive::kPrimBoolean, kAssignabilityCheck, kTransaction>(
              self, shadow_frame, obj, field, value);
    case Primitive::kPrimByte:
      return DoFieldPutCommon<Primitive::kPrimByte, kAssignabilityCheck, kTransaction>(
          self, shadow_frame, obj, field, value);
    case Primitive::kPrimChar:
      return DoFieldPutCommon<Primitive::kPrimChar, kAssignabilityCheck, kTransaction>(
          self, shadow_frame, obj, field, value);
    case Primitive::kPrimShort:
      return DoFieldPutCommon<Primitive::kPrimShort, kAssignabilityCheck, kTransaction>(
          self, shadow_frame, obj, field, value);
    case Primitive::kPrimInt:
    case Primitive::kPrimFloat:
      return DoFieldPutCommon<Primitive::kPrimInt, kAssignabilityCheck, kTransaction>(
          self, shadow_frame, obj, field, value);
    case Primitive::kPrimLong:
    case Primitive::kPrimDouble:
      return DoFieldPutCommon<Primitive::kPrimLong, kAssignabilityCheck, kTransaction>(
          self, shadow_frame, obj, field, value);
    case Primitive::kPrimNot:
      return DoFieldPutCommon<Primitive::kPrimNot, kAssignabilityCheck, kTransaction>(
          self, shadow_frame, obj, field, value);
    case Primitive::kPrimVoid:
      LOG(FATAL) << "Unreachable: " << field_type;
      UNREACHABLE();
  }
}

static JValue GetValueFromShadowFrame(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;
}

bool MethodHandleFieldAccess(Thread* self,
                             ShadowFrame& shadow_frame,
                             Handle<mirror::MethodHandle> method_handle,
                             Handle<mirror::MethodType> callsite_type,
                             const InstructionOperands* const operands,
                             JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
  StackHandleScope<1> hs(self);
  const mirror::MethodHandle::Kind handle_kind = method_handle->GetHandleKind();
  ArtField* field = method_handle->GetTargetField();
  Primitive::Type field_type = field->GetTypeAsPrimitiveType();
  switch (handle_kind) {
    case mirror::MethodHandle::kInstanceGet: {
      size_t obj_reg = operands->GetOperand(0);
      ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(obj_reg);
      MethodHandleFieldGet(self, shadow_frame, obj, field, field_type, result);
      return true;
    }
    case mirror::MethodHandle::kStaticGet: {
      ObjPtr<mirror::Object> obj = GetAndInitializeDeclaringClass(self, field);
      if (obj == nullptr) {
        DCHECK(self->IsExceptionPending());
        return false;
      }
      MethodHandleFieldGet(self, shadow_frame, obj, field, field_type, result);
      return true;
    }
    case mirror::MethodHandle::kInstancePut: {
      size_t obj_reg = operands->GetOperand(0);
      size_t value_reg = operands->GetOperand(1);
      const size_t kPTypeIndex = 1;
      // Use ptypes instead of field type since we may be unboxing a reference for a primitive
      // field. The field type is incorrect for this case.
      JValue value = GetValueFromShadowFrame(
          shadow_frame,
          callsite_type->GetPTypes()->Get(kPTypeIndex)->GetPrimitiveType(),
          value_reg);
      ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(obj_reg);
      return MethodHandleFieldPut(self, shadow_frame, obj, field, field_type, value);
    }
    case mirror::MethodHandle::kStaticPut: {
      ObjPtr<mirror::Object> obj = GetAndInitializeDeclaringClass(self, field);
      if (obj == nullptr) {
        DCHECK(self->IsExceptionPending());
        return false;
      }
      size_t value_reg = operands->GetOperand(0);
      const size_t kPTypeIndex = 0;
      // Use ptypes instead of field type since we may be unboxing a reference for a primitive
      // field. The field type is incorrect for this case.
      JValue value = GetValueFromShadowFrame(
          shadow_frame,
          callsite_type->GetPTypes()->Get(kPTypeIndex)->GetPrimitiveType(),
          value_reg);
      return MethodHandleFieldPut(self, shadow_frame, obj, field, field_type, value);
    }
    default:
      LOG(FATAL) << "Unreachable: " << handle_kind;
      UNREACHABLE();
  }
}

bool DoVarHandleInvokeTranslationUnchecked(Thread* self,
                                           ShadowFrame& shadow_frame,
                                           mirror::VarHandle::AccessMode access_mode,
                                           Handle<mirror::VarHandle> vh,
                                           Handle<mirror::MethodType> vh_type,
                                           Handle<mirror::MethodType> callsite_type,
                                           const InstructionOperands* const operands,
                                           JValue* result)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  DCHECK_EQ(operands->GetNumberOfOperands(), vh_type->NumberOfVRegs());
  DCHECK_EQ(operands->GetNumberOfOperands(), callsite_type->NumberOfVRegs());
  if (!vh->IsAccessModeSupported(access_mode)) {
    ThrowUnsupportedOperationException();
    return false;
  }

  const size_t vreg_count = vh_type->NumberOfVRegs();
  ShadowFrameAllocaUniquePtr accessor_frame =
      CREATE_SHADOW_FRAME(vreg_count, nullptr, shadow_frame.GetMethod(), shadow_frame.GetDexPC());
  ShadowFrameGetter getter(shadow_frame, operands);
  static const uint32_t kFirstAccessorReg = 0;
  ShadowFrameSetter setter(accessor_frame.get(), kFirstAccessorReg);
  if (!PerformConversions(self, callsite_type, vh_type, &getter, &setter)) {
    return false;
  }
  RangeInstructionOperands accessor_operands(kFirstAccessorReg, kFirstAccessorReg + vreg_count);
  if (!vh->Access(access_mode, accessor_frame.get(), &accessor_operands, result)) {
    return false;
  }
  return ConvertReturnValue(callsite_type, vh_type, result);
}

bool DoVarHandleInvokeTranslation(Thread* self,
                                  ShadowFrame& shadow_frame,
                                  Handle<mirror::MethodHandle> method_handle,
                                  Handle<mirror::MethodType> callsite_type,
                                  const InstructionOperands* const operands,
                                  JValue* result)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  //
  // Basic checks that apply in all cases.
  //
  StackHandleScope<6> hs(self);
  Handle<mirror::ObjectArray<mirror::Class>>
      callsite_ptypes(hs.NewHandle(callsite_type->GetPTypes()));
  Handle<mirror::ObjectArray<mirror::Class>>
         mh_ptypes(hs.NewHandle(method_handle->GetMethodType()->GetPTypes()));

  // Check that the first parameter is a VarHandle
  if (callsite_ptypes->GetLength() < 1 ||
      !mh_ptypes->Get(0)->IsAssignableFrom(callsite_ptypes->Get(0)) ||
      mh_ptypes->Get(0) != GetClassRoot<mirror::VarHandle>()) {
    ThrowWrongMethodTypeException(method_handle->GetMethodType(), callsite_type.Get());
    return false;
  }

  // Get the receiver
  ObjPtr<mirror::Object> receiver = shadow_frame.GetVRegReference(operands->GetOperand(0));
  if (receiver == nullptr) {
    ThrowNullPointerException("Expected argument 1 to be a non-null VarHandle");
    return false;
  }

  // Cast to VarHandle instance
  Handle<mirror::VarHandle> vh(hs.NewHandle(ObjPtr<mirror::VarHandle>::DownCast(receiver)));
  DCHECK(GetClassRoot<mirror::VarHandle>()->IsAssignableFrom(vh->GetClass()));

  // Determine the accessor kind to dispatch
  ArtMethod* target_method = method_handle->GetTargetMethod();
  int intrinsic_index = target_method->GetIntrinsic();
  mirror::VarHandle::AccessMode access_mode =
      mirror::VarHandle::GetAccessModeByIntrinsic(static_cast<Intrinsics>(intrinsic_index));
  Handle<mirror::MethodType> vh_type =
      hs.NewHandle(vh->GetMethodTypeForAccessMode(self, access_mode));
  Handle<mirror::MethodType> mh_invoke_type = hs.NewHandle(
      mirror::MethodType::CloneWithoutLeadingParameter(self, method_handle->GetMethodType()));
  if (method_handle->GetHandleKind() == mirror::MethodHandle::Kind::kInvokeVarHandleExact) {
    if (!mh_invoke_type->IsExactMatch(vh_type.Get())) {
      ThrowWrongMethodTypeException(vh_type.Get(), mh_invoke_type.Get());
      return false;
    }
  } else {
    DCHECK_EQ(method_handle->GetHandleKind(), mirror::MethodHandle::Kind::kInvokeVarHandle);
    if (!mh_invoke_type->IsConvertible(vh_type.Get())) {
      ThrowWrongMethodTypeException(vh_type.Get(), mh_invoke_type.Get());
      return false;
    }
  }

  Handle<mirror::MethodType> callsite_type_without_varhandle =
      hs.NewHandle(mirror::MethodType::CloneWithoutLeadingParameter(self, callsite_type.Get()));
  NoReceiverInstructionOperands varhandle_operands(operands);
  return DoVarHandleInvokeTranslationUnchecked(self,
                                               shadow_frame,
                                               access_mode,
                                               vh,
                                               vh_type,
                                               callsite_type_without_varhandle,
                                               &varhandle_operands,
                                               result);
}

static inline bool MethodHandleInvokeExactInternal(
    Thread* self,
    ShadowFrame& shadow_frame,
    Handle<mirror::MethodHandle> method_handle,
    Handle<mirror::MethodType> callsite_type,
    const InstructionOperands* const operands,
    JValue* result)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  StackHandleScope<1> hs(self);
  Handle<mirror::MethodType> method_handle_type(hs.NewHandle(method_handle->GetMethodType()));
  const mirror::MethodHandle::Kind handle_kind = method_handle->GetHandleKind();

  if (!callsite_type->IsExactMatch(method_handle_type.Get())) {
    ThrowWrongMethodTypeException(method_handle_type.Get(), callsite_type.Get());
    return false;
  }

  if (IsFieldAccess(handle_kind)) {
    return MethodHandleFieldAccess(self,
                                   shadow_frame,
                                   method_handle,
                                   callsite_type,
                                   operands,
                                   result);
  }

  // Slow-path check.
  if (IsInvokeTransform(handle_kind) ||
      InvokedFromTransform(callsite_type)) {
    return DoInvokePolymorphicMethod(self,
                                     shadow_frame,
                                     method_handle,
                                     callsite_type,
                                     operands,
                                     result);
  } else if (IsInvokeVarHandle(handle_kind)) {
    return DoVarHandleInvokeTranslation(self,
                                        shadow_frame,
                                        method_handle,
                                        callsite_type,
                                        operands,
                                        result);
  }

  // On the fast-path. This is equivalent to DoCallPolymorphic without the conversion paths.
  ArtMethod* target_method = method_handle->GetTargetMethod();
  uint32_t receiver_reg = (operands->GetNumberOfOperands() > 0) ? operands->GetOperand(0) : 0u;
  ArtMethod* called_method = RefineTargetMethod(self,
                                                shadow_frame,
                                                handle_kind,
                                                method_handle_type,
                                                callsite_type,
                                                receiver_reg,
                                                target_method);
  if (called_method == nullptr) {
    DCHECK(self->IsExceptionPending());
    return false;
  }

  // Compute method information.
  CodeItemDataAccessor accessor(called_method->DexInstructionData());
  uint16_t num_regs;
  size_t num_input_regs;
  size_t first_dest_reg;
  if (LIKELY(accessor.HasCodeItem())) {
    num_regs = accessor.RegistersSize();
    first_dest_reg = num_regs - accessor.InsSize();
    num_input_regs = accessor.InsSize();
    // 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.
  const char* old_cause = self->StartAssertNoThreadSuspension("DoCallCommon");
  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();
  CopyArgumentsFromCallerFrame(shadow_frame,
                               new_shadow_frame,
                               operands,
                               first_dest_reg);
  self->EndAssertNoThreadSuspension(old_cause);

  PerformCall(self,
              accessor,
              called_method,
              first_dest_reg,
              new_shadow_frame,
              result,
              interpreter::ShouldStayInSwitchInterpreter(called_method));
  if (self->IsExceptionPending()) {
    return false;
  }
  return true;
}

template <typename T>
bool InvokeInContext(Thread* self,
                     ShadowFrame& shadow_frame,
                     Handle<mirror::MethodHandle> method_handle,
                     Handle<mirror::MethodType> callsite_type,
                     const InstructionOperands* const operands,
                     JValue* result,
                     T invoker) REQUIRES_SHARED(Locks::mutator_lock_) {
  if (!InvokedFromTransform(callsite_type) || IsInvokeTransform(method_handle->GetHandleKind())) {
    return invoker(self, shadow_frame, method_handle, callsite_type, operands, result);
  }

  // The MethodHandle invocation has occurred within a Transformer that has created an emulated
  // stack frame as context with which to invoke the MethodHandle. We need to unpack this, then
  // invoke the MethodHandle in the provided context.
  StackHandleScope<2> hs(self);
  size_t first_argument_vreg = operands->GetOperand(0);
  Handle<mirror::EmulatedStackFrame> emulated_stack_frame =
      hs.NewHandle(ObjPtr<mirror::EmulatedStackFrame>::DownCast(
          shadow_frame.GetVRegReference(first_argument_vreg)));
  Handle<mirror::MethodType> effective_callsite_type =
      hs.NewHandle(emulated_stack_frame->GetType());
  uint16_t num_vregs = effective_callsite_type->NumberOfVRegs();

  RangeInstructionOperands effective_operands(0, num_vregs);
  ArtMethod* called_method = method_handle->GetTargetMethod();  // invoke / invokeExact.
  // Create a shadow frame
  ShadowFrameAllocaUniquePtr effective_frame =
      CREATE_SHADOW_FRAME(num_vregs, &shadow_frame, called_method, shadow_frame.GetDexPC());
  if (UNLIKELY(effective_operands.GetNumberOfOperands() != 0 &&
               !emulated_stack_frame->WriteToShadowFrame(self,
                                                         effective_callsite_type,
                                                         effective_operands.GetOperand(0),
                                                         effective_frame.get()))) {
    DCHECK(self->IsExceptionPending());
    result->SetL(nullptr);
    return false;
  }

  ScopedStackedShadowFramePusher pusher(
      self, effective_frame.get(), StackedShadowFrameType::kShadowFrameUnderConstruction);

  // Invoke MethodHandle in newly created context
  bool success = invoker(self,
                         *effective_frame.get(),
                         method_handle,
                         effective_callsite_type,
                         &effective_operands,
                         result);
  if (success) {
    emulated_stack_frame->SetReturnValue(self, *result);
  }
  return success;
}

}  // namespace

bool MethodHandleInvoke(Thread* self,
                        ShadowFrame& shadow_frame,
                        Handle<mirror::MethodHandle> method_handle,
                        Handle<mirror::MethodType> callsite_type,
                        const InstructionOperands* const operands,
                        JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
  auto invoke = [](Thread* self,
                   ShadowFrame& shadow_frame,
                   Handle<mirror::MethodHandle> method_handle,
                   Handle<mirror::MethodType> callsite_type,
                   const InstructionOperands* const operands,
                   JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
    StackHandleScope<2> hs(self);
    Handle<mirror::MethodType> method_handle_type(hs.NewHandle(method_handle->GetMethodType()));

    // Non-exact invoke behaves as calling mh.asType(newType). In ART, asType() is implemented
    // as a transformer and it is expensive to call so check first if it's really necessary.
    //
    // There are two cases where the asType() transformation can be skipped:
    //
    // 1) the call site and type of the MethodHandle match, ie code is calling invoke()
    //    unnecessarily.
    //
    // 2) when the call site can be trivally converted to the MethodHandle type due to how
    //    values are represented in the ShadowFrame, ie all registers in the shadow frame are
    //    32-bit, there is no byte, short, char, etc. So a call site with arguments of these
    //    kinds can be trivially converted to one with int arguments. Similarly if the reference
    //    types are assignable between the call site and MethodHandle type, then as asType()
    //    transformation isn't really doing any work.
    if (callsite_type->IsInPlaceConvertible(method_handle_type.Get())) {
      return MethodHandleInvokeExact(
          self, shadow_frame, method_handle, method_handle_type, operands, result);
    }

    // Use asType() variant of this MethodHandle to adapt callsite to the target.
    MutableHandle<mirror::MethodHandle> atc(hs.NewHandle(method_handle->GetAsTypeCache()));
    if (atc == nullptr || !callsite_type->IsExactMatch(atc->GetMethodType())) {
      // Cached asType adapter does not exist or is for another call site. Call
      // MethodHandle::asType() to get an appropriate adapter.
      ArtMethod* as_type =
          jni::DecodeArtMethod(WellKnownClasses::java_lang_invoke_MethodHandle_asType);
      uint32_t as_type_args[] = {
          static_cast<uint32_t>(reinterpret_cast<uintptr_t>(method_handle.Get())),
          static_cast<uint32_t>(reinterpret_cast<uintptr_t>(callsite_type.Get()))};
      JValue atc_result;
      as_type->Invoke(self, as_type_args, sizeof(as_type_args), &atc_result, "LL");
      if (atc_result.GetL() == nullptr) {
        DCHECK(self->IsExceptionPending());
        return false;
      }
      ObjPtr<mirror::MethodHandle> atc_method_handle =
          down_cast<mirror::MethodHandle*>(atc_result.GetL());
      atc.Assign(atc_method_handle);
      DCHECK(!atc.IsNull());
    }
    return MethodHandleInvokeExact(self, shadow_frame, atc, callsite_type, operands, result);
  };
  return InvokeInContext(
      self, shadow_frame, method_handle, callsite_type, operands, result, invoke);
}

bool MethodHandleInvokeExact(Thread* self,
                             ShadowFrame& shadow_frame,
                             Handle<mirror::MethodHandle> method_handle,
                             Handle<mirror::MethodType> callsite_type,
                             const InstructionOperands* const operands,
                             JValue* result)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  auto invoke = [](Thread* self,
                   ShadowFrame& shadow_frame,
                   Handle<mirror::MethodHandle> method_handle,
                   Handle<mirror::MethodType> callsite_type,
                   const InstructionOperands* const operands,
                   JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
    return MethodHandleInvokeExactInternal(
        self, shadow_frame, method_handle, callsite_type, operands, result);
  };
  return InvokeInContext(
      self, shadow_frame, method_handle, callsite_type, operands, result, invoke);
}

}  // namespace art
