/*
 * 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/stringprintf.h"

#include "common_dex_operations.h"
#include "jvalue.h"
#include "jvalue-inl.h"
#include "mirror/emulated_stack_frame.h"
#include "mirror/method_handle_impl.h"
#include "mirror/method_type.h"
#include "reflection.h"
#include "reflection-inl.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 (h_obj != nullptr && !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 (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 (!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.Ptr());
    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 == nullptr)) {
      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))) {
      ThrowClassCastException(from, to);
      return false;
    }

    return true;
  }
}

namespace {

template <bool is_range>
inline void CopyArgumentsFromCallerFrame(const ShadowFrame& caller_frame,
                                         ShadowFrame* callee_frame,
                                         const uint32_t (&args)[Instruction::kMaxVarArgRegs],
                                         uint32_t first_arg,
                                         const size_t first_dst_reg,
                                         const size_t num_regs)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  for (size_t i = 0; i < num_regs; ++i) {
    size_t dst_reg = first_dst_reg + i;
    size_t src_reg = is_range ? (first_arg + i) : args[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.Ptr());
    } else {
      callee_frame->SetVReg(dst_reg, src_value);
    }
  }
}

template <bool is_range>
inline bool ConvertAndCopyArgumentsFromCallerFrame(
    Thread* self,
    Handle<mirror::MethodType> callsite_type,
    Handle<mirror::MethodType> callee_type,
    const ShadowFrame& caller_frame,
    const uint32_t (&args)[Instruction::kMaxVarArgRegs],
    uint32_t first_arg,
    uint32_t first_dst_reg,
    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<is_range> getter(first_arg, args, caller_frame);
  ShadowFrameSetter setter(callee_frame, first_dst_reg);

  return PerformConversions<ShadowFrameGetter<is_range>, ShadowFrameSetter>(self,
                                                                            callsite_type,
                                                                            callee_type,
                                                                            &getter,
                                                                            &setter,
                                                                            num_method_params);
}

inline bool IsMethodHandleInvokeExact(const ArtMethod* const method) {
  if (method == jni::DecodeArtMethod(WellKnownClasses::java_lang_invoke_MethodHandle_invokeExact)) {
    return true;
  } else {
    DCHECK_EQ(method, jni::DecodeArtMethod(WellKnownClasses::java_lang_invoke_MethodHandle_invoke));
    return false;
  }
}

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

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,
                                     const uint32_t (&args)[Instruction::kMaxVarArgRegs],
                                     uint32_t first_arg,
                                     JValue* result)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  // 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.
      CopyArgumentsFromCallerFrame<is_range>(shadow_frame,
                                             new_shadow_frame,
                                             args,
                                             first_arg,
                                             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.
        size_t first_arg_register = (is_range) ? first_arg : args[0];
        ObjPtr<mirror::EmulatedStackFrame> emulated_stack_frame(
            reinterpret_cast<mirror::EmulatedStackFrame*>(
                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(0);
          return false;
        }
      } else {
        if (!callsite_type->IsConvertible(target_type.Get())) {
          ThrowWrongMethodTypeException(target_type.Get(), callsite_type.Get());
          return false;
        }
        if (!ConvertAndCopyArgumentsFromCallerFrame<is_range>(self,
                                                              callsite_type,
                                                              target_type,
                                                              shadow_frame,
                                                              args,
                                                              first_arg,
                                                              first_dest_reg,
                                                              new_shadow_frame)) {
          DCHECK(self->IsExceptionPending());
          result->SetL(0);
          return false;
        }
      }
    }
  }

  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);
    size_t first_callee_register = is_range ? (first_arg) : args[0];
    Handle<mirror::EmulatedStackFrame> emulated_stack_frame(
        hs.NewHandle(reinterpret_cast<mirror::EmulatedStackFrame*>(
            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);
}

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::MethodHandle> receiver,
                                   const uint32_t (&args)[Instruction::kMaxVarArgRegs],
                                   uint32_t first_arg,
                                   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;

  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.
    size_t first_callee_register = is_range ? first_arg : args[0];
    sf.Assign(reinterpret_cast<mirror::EmulatedStackFrame*>(
        shadow_frame.GetVRegReference(first_callee_register)));
  } else {
    sf.Assign(mirror::EmulatedStackFrame::CreateFromShadowFrameAndArgs<is_range>(self,
                                                                                 callsite_type,
                                                                                 callee_type,
                                                                                 shadow_frame,
                                                                                 first_arg,
                                                                                 args));

    // 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,
              code_item,
              shadow_frame.GetMethod(),
              0 /* first destination register */,
              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);
}

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 (IsCallerTransformer(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) {
    ObjPtr<mirror::Class> declaring_class = target_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 = 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);
    } else {
      return referrer_class->FindVirtualMethodForInterfaceSuper(target_method, kRuntimePointerSize);
    }
  }
  return target_method;
}

template <bool is_range>
bool DoInvokePolymorphicMethod(Thread* self,
                               ShadowFrame& shadow_frame,
                               Handle<mirror::MethodHandle> method_handle,
                               Handle<mirror::MethodType> callsite_type,
                               const uint32_t (&args)[Instruction::kMaxVarArgRegs],
                               uint32_t first_arg,
                               JValue* result)
  REQUIRES_SHARED(Locks::mutator_lock_) {
  StackHandleScope<1> 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 = is_range ? first_arg: args[0];
  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 DoCallTransform<is_range>(called_method,
                                     callsite_type,
                                     callee_type,
                                     self,
                                     shadow_frame,
                                     method_handle /* receiver */,
                                     args,
                                     first_arg,
                                     result);
  } else {
    return DoCallPolymorphic<is_range>(called_method,
                                       callsite_type,
                                       handle_type,
                                       self,
                                       shadow_frame,
                                       args,
                                       first_arg,
                                       result);
  }
}

// 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();
  }
}

// Helper for setters in invoke-polymorphic.
inline 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_) {
  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;
}

template <bool is_range, bool do_conversions>
bool DoInvokePolymorphicFieldAccess(Thread* self,
                                    ShadowFrame& shadow_frame,
                                    Handle<mirror::MethodHandle> method_handle,
                                    Handle<mirror::MethodType> callsite_type,
                                    const uint32_t (&args)[Instruction::kMaxVarArgRegs],
                                    uint32_t first_arg,
                                    JValue* result)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  StackHandleScope<1> hs(self);
  Handle<mirror::MethodType> handle_type(hs.NewHandle(method_handle->GetMethodType()));
  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 = is_range ? first_arg : args[0];
      ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(obj_reg);
      DoFieldGetForInvokePolymorphic(self, shadow_frame, obj, field, field_type, result);
      if (do_conversions && !ConvertReturnValue(callsite_type, handle_type, result)) {
        DCHECK(self->IsExceptionPending());
        return false;
      }
      return true;
    }
    case mirror::MethodHandle::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 (do_conversions && !ConvertReturnValue(callsite_type, handle_type, result)) {
        DCHECK(self->IsExceptionPending());
        return false;
      }
      return true;
    }
    case mirror::MethodHandle::kInstancePut: {
      size_t obj_reg = is_range ? first_arg : args[0];
      size_t value_reg = is_range ? (first_arg + 1) : args[1];
      JValue value = GetValueFromShadowFrame(shadow_frame, field_type, value_reg);
      if (do_conversions && !ConvertArgumentValue(callsite_type, handle_type, 1, &value)) {
        DCHECK(self->IsExceptionPending());
        return false;
      }
      ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(obj_reg);
      return DoFieldPutForInvokePolymorphic(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 = is_range ? first_arg : args[0];
      JValue value = GetValueFromShadowFrame(shadow_frame, field_type, value_reg);
      if (do_conversions && !ConvertArgumentValue(callsite_type, handle_type, 0, &value)) {
        DCHECK(self->IsExceptionPending());
        return false;
      }
      return DoFieldPutForInvokePolymorphic(self, shadow_frame, obj, field, field_type, value);
    }
    default:
      LOG(FATAL) << "Unreachable: " << handle_kind;
      UNREACHABLE();
  }
}

template <bool is_range>
static inline bool DoInvokePolymorphicNonExact(Thread* self,
                                               ShadowFrame& shadow_frame,
                                               Handle<mirror::MethodHandle> method_handle,
                                               Handle<mirror::MethodType> callsite_type,
                                               const uint32_t (&args)[Instruction::kMaxVarArgRegs],
                                               uint32_t first_arg,
                                               JValue* result)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const mirror::MethodHandle::Kind handle_kind = method_handle->GetHandleKind();
  ObjPtr<mirror::MethodType> handle_type(method_handle->GetMethodType());
  CHECK(handle_type != nullptr);

  if (IsFieldAccess(handle_kind)) {
    DCHECK(!callsite_type->IsExactMatch(handle_type.Ptr()));
    if (!callsite_type->IsConvertible(handle_type.Ptr())) {
      ThrowWrongMethodTypeException(handle_type.Ptr(), callsite_type.Get());
      return false;
    }
    const bool do_convert = true;
    return DoInvokePolymorphicFieldAccess<is_range, do_convert>(
        self,
        shadow_frame,
        method_handle,
        callsite_type,
        args,
        first_arg,
        result);
  }

  return DoInvokePolymorphicMethod<is_range>(self,
                                             shadow_frame,
                                             method_handle,
                                             callsite_type,
                                             args,
                                             first_arg,
                                             result);
}

template <bool is_range>
bool DoInvokePolymorphicExact(Thread* self,
                              ShadowFrame& shadow_frame,
                              Handle<mirror::MethodHandle> method_handle,
                              Handle<mirror::MethodType> callsite_type,
                              const uint32_t (&args)[Instruction::kMaxVarArgRegs],
                              uint32_t first_arg,
                              JValue* result)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  StackHandleScope<1> hs(self);
  const mirror::MethodHandle::Kind handle_kind = method_handle->GetHandleKind();
  Handle<mirror::MethodType> method_handle_type(hs.NewHandle(method_handle->GetMethodType()));
  if (IsFieldAccess(handle_kind)) {
    const bool do_convert = false;
    return DoInvokePolymorphicFieldAccess<is_range, do_convert>(
        self,
        shadow_frame,
        method_handle,
        callsite_type,
        args,
        first_arg,
        result);
  }

  // Slow-path check.
  if (IsInvokeTransform(handle_kind) || IsCallerTransformer(callsite_type)) {
    return DoInvokePolymorphicMethod<is_range>(self,
                                               shadow_frame,
                                               method_handle,
                                               callsite_type,
                                               args,
                                               first_arg,
                                               result);
  }

  // On the fast-path. This is equivalent to DoCallPolymoprhic without the conversion paths.
  ArtMethod* target_method = method_handle->GetTargetMethod();
  uint32_t receiver_reg = is_range ? first_arg : args[0];
  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.
  const DexFile::CodeItem* code_item = called_method->GetCodeItem();
  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.
  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<is_range>(shadow_frame,
                                         new_shadow_frame,
                                         args,
                                         first_arg,
                                         first_dest_reg,
                                         num_input_regs);
  self->EndAssertNoThreadSuspension(old_cause);

  PerformCall(self, code_item, shadow_frame.GetMethod(), first_dest_reg, new_shadow_frame, result);
  if (self->IsExceptionPending()) {
    return false;
  }
  return true;
}

}  // namespace

template <bool is_range>
bool DoInvokePolymorphic(Thread* self,
                         ArtMethod* invoke_method,
                         ShadowFrame& shadow_frame,
                         Handle<mirror::MethodHandle> method_handle,
                         Handle<mirror::MethodType> callsite_type,
                         const uint32_t (&args)[Instruction::kMaxVarArgRegs],
                         uint32_t first_arg,
                         JValue* result)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  ObjPtr<mirror::MethodType> method_handle_type = method_handle->GetMethodType();
  if (IsMethodHandleInvokeExact(invoke_method)) {
    // 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());
    if (UNLIKELY(nominal_type != nullptr)) {
      if (UNLIKELY(!callsite_type->IsExactMatch(nominal_type.Ptr()))) {
        ThrowWrongMethodTypeException(nominal_type.Ptr(), callsite_type.Get());
        return false;
      }

      if (LIKELY(!nominal_type->IsExactMatch(method_handle_type.Ptr()))) {
        // Different nominal type means we have to treat as non-exact.
        return DoInvokePolymorphicNonExact<is_range>(self,
                                                     shadow_frame,
                                                     method_handle,
                                                     callsite_type,
                                                     args,
                                                     first_arg,
                                                     result);
      }
    }

    if (!callsite_type->IsExactMatch(method_handle_type.Ptr())) {
      ThrowWrongMethodTypeException(method_handle_type.Ptr(), callsite_type.Get());
      return false;
    }
    return DoInvokePolymorphicExact<is_range>(self,
                                              shadow_frame,
                                              method_handle,
                                              callsite_type,
                                              args,
                                              first_arg,
                                              result);
  } else {
    if (UNLIKELY(callsite_type->IsExactMatch(method_handle_type.Ptr()))) {
      // A non-exact invoke that can be invoked exactly.
      return DoInvokePolymorphicExact<is_range>(self,
                                                shadow_frame,
                                                method_handle,
                                                callsite_type,
                                                args,
                                                first_arg,
                                                result);
    }
    return DoInvokePolymorphicNonExact<is_range>(self,
                                                 shadow_frame,
                                                 method_handle,
                                                 callsite_type,
                                                 args,
                                                 first_arg,
                                                 result);
  }
}

#define EXPLICIT_DO_INVOKE_POLYMORPHIC_TEMPLATE_DECL(_is_range)  \
  template REQUIRES_SHARED(Locks::mutator_lock_)                 \
  bool DoInvokePolymorphic<_is_range>(                           \
      Thread* self,                                              \
      ArtMethod* invoke_method,                                  \
      ShadowFrame& shadow_frame,                                 \
      Handle<mirror::MethodHandle> method_handle,                \
      Handle<mirror::MethodType> callsite_type,                  \
      const uint32_t (&args)[Instruction::kMaxVarArgRegs],       \
      uint32_t first_arg,                                        \
      JValue* result)

EXPLICIT_DO_INVOKE_POLYMORPHIC_TEMPLATE_DECL(true);
EXPLICIT_DO_INVOKE_POLYMORPHIC_TEMPLATE_DECL(false);
#undef EXPLICIT_DO_INVOKE_POLYMORPHIC_TEMPLATE_DECL

}  // namespace art
