/*
 * Copyright (C) 2012 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 "class_linker.h"
#include "nth_caller_visitor.h"
#include "object.h"
#include "object_utils.h"
#include "reflection.h"
#include "runtime_support.h"
#include "runtime_support_llvm.h"
#include "ScopedLocalRef.h"
#include "shadow_frame.h"
#include "thread.h"
#include "thread_list.h"
#include "verifier/method_verifier.h"

#include <algorithm>
#include <cstdarg>
#include <stdint.h>

#include "asm_support.h"

namespace art {

//----------------------------------------------------------------------------
// Thread
//----------------------------------------------------------------------------

// This is used by other runtime support functions, NOT FROM CODE. The REAL GetCurrentThread is
// implemented by IRBuilder. (So, ARM can't return R9 in this function.)
// TODO: Maybe remove these which are implemented by IRBuilder after refactor runtime support.
Thread* art_get_current_thread_from_code() {
#if defined(__i386__)
  Thread* ptr;
  asm volatile("movl %%fs:(%1), %0"
      : "=r"(ptr)  // output
      : "r"(THREAD_SELF_OFFSET)  // input
      :);  // clobber
  return ptr;
#else
  return Thread::Current();
#endif
}

void art_set_current_thread_from_code(void* thread_object_addr) {
  LOG(FATAL) << "Implemented by IRBuilder.";
}

void art_lock_object_from_code(Object* obj) {
  Thread* thread = art_get_current_thread_from_code();
  DCHECK(obj != NULL);        // Assumed to have been checked before entry
  obj->MonitorEnter(thread);  // May block
  DCHECK(thread->HoldsLock(obj));
  // Only possible exception is NPE and is handled before entry
  DCHECK(!thread->IsExceptionPending());
}

void art_unlock_object_from_code(Object* obj) {
  Thread* thread = art_get_current_thread_from_code();
  DCHECK(obj != NULL);  // Assumed to have been checked before entry
  // MonitorExit may throw exception
  obj->MonitorExit(thread);
}

void art_test_suspend_from_code() {
  Thread* thread = art_get_current_thread_from_code();
  Runtime::Current()->GetThreadList()->FullSuspendCheck(thread);
}

void art_push_shadow_frame_from_code(void* new_shadow_frame) {
  LOG(FATAL) << "Implemented by IRBuilder.";
}

void art_pop_shadow_frame_from_code() {
  LOG(FATAL) << "Implemented by IRBuilder.";
}

void art_mark_gc_card_from_code(void *, void*) {
  LOG(FATAL) << "Implemented by IRBuilder.";
}

//----------------------------------------------------------------------------
// Exception
//----------------------------------------------------------------------------

bool art_is_exception_pending_from_code() {
  LOG(FATAL) << "Implemented by IRBuilder.";
  return false;
}

void art_throw_div_zero_from_code() {
  Thread* thread = art_get_current_thread_from_code();
  thread->ThrowNewException("Ljava/lang/ArithmeticException;",
                            "divide by zero");
}

void art_throw_array_bounds_from_code(int32_t length, int32_t index) {
  Thread* thread = art_get_current_thread_from_code();
  thread->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
                             "length=%d; index=%d", length, index);
}

void art_throw_no_such_method_from_code(int32_t method_idx) {
  Thread* thread = art_get_current_thread_from_code();
  // We need the calling method as context for the method_idx
  Frame frame = thread->GetTopOfStack();
  frame.Next();
  Method* method = frame.GetMethod();
  thread->ThrowNewException("Ljava/lang/NoSuchMethodError;",
                            MethodNameFromIndex(method,
                                                method_idx,
                                                verifier::VERIFY_ERROR_REF_METHOD,
                                                false).c_str());
}

void art_throw_null_pointer_exception_from_code(uint32_t dex_pc) {
  Thread* thread = art_get_current_thread_from_code();
  NthCallerVisitor visitor(0);
  thread->WalkStack(&visitor);
  Method* throw_method = visitor.caller;
  ThrowNullPointerExceptionFromDexPC(thread, throw_method, dex_pc);
}

void art_throw_stack_overflow_from_code() {
  Thread* thread = art_get_current_thread_from_code();
  if (Runtime::Current()->IsMethodTracingActive()) {
    TraceMethodUnwindFromCode(thread);
  }
  thread->SetStackEndForStackOverflow();  // Allow space on the stack for constructor to execute
  thread->ThrowNewExceptionF("Ljava/lang/StackOverflowError;",
      "stack size %zdkb; default stack size: %zdkb",
      thread->GetStackSize() / KB,
      Runtime::Current()->GetDefaultStackSize() / KB);
  thread->ResetDefaultStackEnd();  // Return to default stack size
}

void art_throw_exception_from_code(Object* exception) {
  Thread* thread = art_get_current_thread_from_code();
  if (exception == NULL) {
    thread->ThrowNewException("Ljava/lang/NullPointerException;", "throw with null exception");
  } else {
    thread->SetException(static_cast<Throwable*>(exception));
  }
}

void art_throw_verification_error_from_code(Method* current_method,
                                            int32_t kind,
                                            int32_t ref) {
  ThrowVerificationError(art_get_current_thread_from_code(), current_method, kind, ref);
}

int32_t art_find_catch_block_from_code(Method* current_method, int32_t dex_pc) {
  Thread* thread = art_get_current_thread_from_code();
  Class* exception_type = thread->GetException()->GetClass();
  MethodHelper mh(current_method);
  const DexFile::CodeItem* code_item = mh.GetCodeItem();
  int iter_index = 0;
  // Iterate over the catch handlers associated with dex_pc
  for (CatchHandlerIterator it(*code_item, dex_pc); it.HasNext(); it.Next()) {
    uint16_t iter_type_idx = it.GetHandlerTypeIndex();
    // Catch all case
    if (iter_type_idx == DexFile::kDexNoIndex16) {
      return iter_index;
    }
    // Does this catch exception type apply?
    Class* iter_exception_type = mh.GetDexCacheResolvedType(iter_type_idx);
    if (iter_exception_type == NULL) {
      // The verifier should take care of resolving all exception classes early
      LOG(WARNING) << "Unresolved exception class when finding catch block: "
          << mh.GetTypeDescriptorFromTypeIdx(iter_type_idx);
    } else if (iter_exception_type->IsAssignableFrom(exception_type)) {
      return iter_index;
    }
    ++iter_index;
  }
  // Handler not found
  return -1;
}


//----------------------------------------------------------------------------
// Object Space
//----------------------------------------------------------------------------

Object* art_alloc_object_from_code(uint32_t type_idx, Method* referrer) {
  return AllocObjectFromCode(type_idx, referrer, art_get_current_thread_from_code(), false);
}

Object* art_alloc_object_from_code_with_access_check(uint32_t type_idx, Method* referrer) {
  return AllocObjectFromCode(type_idx, referrer, art_get_current_thread_from_code(), true);
}

Object* art_alloc_array_from_code(uint32_t type_idx, Method* referrer, uint32_t length) {
  return AllocArrayFromCode(type_idx, referrer, length, art_get_current_thread_from_code(), false);
}

Object* art_alloc_array_from_code_with_access_check(uint32_t type_idx,
                                                    Method* referrer,
                                                    uint32_t length) {
  return AllocArrayFromCode(type_idx, referrer, length, art_get_current_thread_from_code(), true);
}

Object* art_check_and_alloc_array_from_code(uint32_t type_idx,
                                            Method* referrer,
                                            uint32_t length) {
  return CheckAndAllocArrayFromCode(type_idx, referrer, length, art_get_current_thread_from_code(), false);
}

Object* art_check_and_alloc_array_from_code_with_access_check(uint32_t type_idx,
                                                              Method* referrer,
                                                              uint32_t length) {
  return CheckAndAllocArrayFromCode(type_idx, referrer, length, art_get_current_thread_from_code(), true);
}

static Method* FindMethodHelper(uint32_t method_idx, Object* this_object, Method* caller_method,
                                bool access_check, InvokeType type) {
  Method* method = FindMethodFast(method_idx, this_object, caller_method, access_check, type);
  if (UNLIKELY(method == NULL)) {
    method = FindMethodFromCode(method_idx, this_object, caller_method,
                                art_get_current_thread_from_code(), access_check, type);
    if (UNLIKELY(method == NULL)) {
      CHECK(art_get_current_thread_from_code()->IsExceptionPending());
      return 0;  // failure
    }
  }
  DCHECK(!art_get_current_thread_from_code()->IsExceptionPending());
  return method;
}

Object* art_find_static_method_from_code_with_access_check(uint32_t method_idx,
                                                           Object* this_object,
                                                           Method* referrer) {
  return FindMethodHelper(method_idx, this_object, referrer, true, kStatic);
}

Object* art_find_direct_method_from_code_with_access_check(uint32_t method_idx,
                                                           Object* this_object,
                                                           Method* referrer) {
  return FindMethodHelper(method_idx, this_object, referrer, true, kDirect);
}

Object* art_find_virtual_method_from_code_with_access_check(uint32_t method_idx,
                                                            Object* this_object,
                                                            Method* referrer) {
  return FindMethodHelper(method_idx, this_object, referrer, true, kVirtual);
}

Object* art_find_super_method_from_code_with_access_check(uint32_t method_idx,
                                                          Object* this_object,
                                                          Method* referrer) {
  return FindMethodHelper(method_idx, this_object, referrer, true, kSuper);
}

Object*
art_find_interface_method_from_code_with_access_check(uint32_t method_idx,
                                                      Object* this_object,
                                                      Method* referrer) {
  return FindMethodHelper(method_idx, this_object, referrer, true, kInterface);
}

Object* art_find_interface_method_from_code(uint32_t method_idx,
                                            Object* this_object,
                                            Method* referrer) {
  return FindMethodHelper(method_idx, this_object, referrer, false, kInterface);
}

Object* art_initialize_static_storage_from_code(uint32_t type_idx, Method* referrer) {
  return ResolveVerifyAndClinit(type_idx, referrer, art_get_current_thread_from_code(), true, false);
}

Object* art_initialize_type_from_code(uint32_t type_idx, Method* referrer) {
  return ResolveVerifyAndClinit(type_idx, referrer, art_get_current_thread_from_code(), false, false);
}

Object* art_initialize_type_and_verify_access_from_code(uint32_t type_idx, Method* referrer) {
  // Called when caller isn't guaranteed to have access to a type and the dex cache may be
  // unpopulated
  return ResolveVerifyAndClinit(type_idx, referrer, art_get_current_thread_from_code(), false, true);
}

Object* art_resolve_string_from_code(Method* referrer, uint32_t string_idx) {
  return ResolveStringFromCode(referrer, string_idx);
}

int32_t art_set32_static_from_code(uint32_t field_idx, Method* referrer, int32_t new_value) {
  Field* field = FindFieldFast(field_idx, referrer, true, true, sizeof(uint32_t));
  if (LIKELY(field != NULL)) {
    field->Set32(NULL, new_value);
    return 0;
  }
  field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
                            true, true, true, sizeof(uint32_t));
  if (LIKELY(field != NULL)) {
    field->Set32(NULL, new_value);
    return 0;
  }
  return -1;
}

int32_t art_set64_static_from_code(uint32_t field_idx, Method* referrer, int64_t new_value) {
  Field* field = FindFieldFast(field_idx, referrer, true, true, sizeof(uint64_t));
  if (LIKELY(field != NULL)) {
    field->Set64(NULL, new_value);
    return 0;
  }
  field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
                            true, true, true, sizeof(uint64_t));
  if (LIKELY(field != NULL)) {
    field->Set64(NULL, new_value);
    return 0;
  }
  return -1;
}

int32_t art_set_obj_static_from_code(uint32_t field_idx, Method* referrer, Object* new_value) {
  Field* field = FindFieldFast(field_idx, referrer, false, true, sizeof(Object*));
  if (LIKELY(field != NULL)) {
    field->SetObj(NULL, new_value);
    return 0;
  }
  field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
                            true, false, true, sizeof(Object*));
  if (LIKELY(field != NULL)) {
    field->SetObj(NULL, new_value);
    return 0;
  }
  return -1;
}

int32_t art_get32_static_from_code(uint32_t field_idx, Method* referrer) {
  Field* field = FindFieldFast(field_idx, referrer, true, false, sizeof(uint32_t));
  if (LIKELY(field != NULL)) {
    return field->Get32(NULL);
  }
  field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
                            true, true, false, sizeof(uint32_t));
  if (LIKELY(field != NULL)) {
    return field->Get32(NULL);
  }
  return 0;
}

int64_t art_get64_static_from_code(uint32_t field_idx, Method* referrer) {
  Field* field = FindFieldFast(field_idx, referrer, true, false, sizeof(uint64_t));
  if (LIKELY(field != NULL)) {
    return field->Get64(NULL);
  }
  field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
                            true, true, false, sizeof(uint64_t));
  if (LIKELY(field != NULL)) {
    return field->Get64(NULL);
  }
  return 0;
}

Object* art_get_obj_static_from_code(uint32_t field_idx, Method* referrer) {
  Field* field = FindFieldFast(field_idx, referrer, false, false, sizeof(Object*));
  if (LIKELY(field != NULL)) {
    return field->GetObj(NULL);
  }
  field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
                            true, false, false, sizeof(Object*));
  if (LIKELY(field != NULL)) {
    return field->GetObj(NULL);
  }
  return 0;
}

int32_t art_set32_instance_from_code(uint32_t field_idx, Method* referrer,
                                     Object* obj, uint32_t new_value) {
  Field* field = FindFieldFast(field_idx, referrer, true, true, sizeof(uint32_t));
  if (LIKELY(field != NULL)) {
    field->Set32(obj, new_value);
    return 0;
  }
  field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
                            false, true, true, sizeof(uint32_t));
  if (LIKELY(field != NULL)) {
    field->Set32(obj, new_value);
    return 0;
  }
  return -1;
}

int32_t art_set64_instance_from_code(uint32_t field_idx, Method* referrer,
                                     Object* obj, int64_t new_value) {
  Field* field = FindFieldFast(field_idx, referrer, true, true, sizeof(uint64_t));
  if (LIKELY(field != NULL)) {
    field->Set64(obj, new_value);
    return 0;
  }
  field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
                            false, true, true, sizeof(uint64_t));
  if (LIKELY(field != NULL)) {
    field->Set64(obj, new_value);
    return 0;
  }
  return -1;
}

int32_t art_set_obj_instance_from_code(uint32_t field_idx, Method* referrer,
                                       Object* obj, Object* new_value) {
  Field* field = FindFieldFast(field_idx, referrer, false, true, sizeof(Object*));
  if (LIKELY(field != NULL)) {
    field->SetObj(obj, new_value);
    return 0;
  }
  field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
                            false, false, true, sizeof(Object*));
  if (LIKELY(field != NULL)) {
    field->SetObj(obj, new_value);
    return 0;
  }
  return -1;
}

int32_t art_get32_instance_from_code(uint32_t field_idx, Method* referrer, Object* obj) {
  Field* field = FindFieldFast(field_idx, referrer, true, false, sizeof(uint32_t));
  if (LIKELY(field != NULL)) {
    return field->Get32(obj);
  }
  field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
                            false, true, false, sizeof(uint32_t));
  if (LIKELY(field != NULL)) {
    return field->Get32(obj);
  }
  return 0;
}

int64_t art_get64_instance_from_code(uint32_t field_idx, Method* referrer, Object* obj) {
  Field* field = FindFieldFast(field_idx, referrer, true, false, sizeof(uint64_t));
  if (LIKELY(field != NULL)) {
    return field->Get64(obj);
  }
  field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
                            false, true, false, sizeof(uint64_t));
  if (LIKELY(field != NULL)) {
    return field->Get64(obj);
  }
  return 0;
}

Object* art_get_obj_instance_from_code(uint32_t field_idx, Method* referrer, Object* obj) {
  Field* field = FindFieldFast(field_idx, referrer, false, false, sizeof(Object*));
  if (LIKELY(field != NULL)) {
    return field->GetObj(obj);
  }
  field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
                            false, false, false, sizeof(Object*));
  if (LIKELY(field != NULL)) {
    return field->GetObj(obj);
  }
  return 0;
}

Object* art_decode_jobject_in_thread(Thread* thread, jobject obj) {
  if (thread->IsExceptionPending()) {
    return NULL;
  }
  return thread->DecodeJObject(obj);
}

//----------------------------------------------------------------------------
// Type checking, in the nature of casting
//----------------------------------------------------------------------------

int32_t art_is_assignable_from_code(const Class* dest_type, const Class* src_type) {
  DCHECK(dest_type != NULL);
  DCHECK(src_type != NULL);
  return dest_type->IsAssignableFrom(src_type) ? 1 : 0;
}

void art_check_cast_from_code(const Class* dest_type, const Class* src_type) {
  DCHECK(dest_type->IsClass()) << PrettyClass(dest_type);
  DCHECK(src_type->IsClass()) << PrettyClass(src_type);
  if (UNLIKELY(!dest_type->IsAssignableFrom(src_type))) {
    Thread* thread = art_get_current_thread_from_code();
    thread->ThrowNewExceptionF("Ljava/lang/ClassCastException;",
                               "%s cannot be cast to %s",
                               PrettyDescriptor(dest_type).c_str(),
                               PrettyDescriptor(src_type).c_str());
  }
}

void art_check_put_array_element_from_code(const Object* element, const Object* array) {
  if (element == NULL) {
    return;
  }
  DCHECK(array != NULL);
  Class* array_class = array->GetClass();
  DCHECK(array_class != NULL);
  Class* component_type = array_class->GetComponentType();
  Class* element_class = element->GetClass();
  if (UNLIKELY(!component_type->IsAssignableFrom(element_class))) {
    Thread* thread = art_get_current_thread_from_code();
    thread->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
                               "%s cannot be stored in an array of type %s",
                               PrettyDescriptor(element_class).c_str(),
                               PrettyDescriptor(array_class).c_str());
  }
  return;
}

//----------------------------------------------------------------------------
// Runtime Support Function Lookup Callback
//----------------------------------------------------------------------------

class CStringComparator {
 public:
  bool operator()(const char* lhs, const char* rhs) const {
    return (strcmp(lhs, rhs) < 0);
  }
};

#define EXTERNAL_LINKAGE(NAME) \
extern "C" void NAME(...);

#include "compiler_runtime_func_list.h"
COMPILER_RUNTIME_FUNC_LIST(EXTERNAL_LINKAGE)
#undef COMPILER_RUNTIME_FUNC_LIST
#undef EXTERNAL_LINKAGE

static void* art_find_compiler_runtime_func(char const* name) {
// TODO: If target support some math func, use the target's version. (e.g. D2I -> __aeabi_d2iz)
  static const char* const names[] = {
#define DEFINE_ENTRY(NAME) #NAME ,
#include "compiler_runtime_func_list.h"
    COMPILER_RUNTIME_FUNC_LIST(DEFINE_ENTRY)
#undef COMPILER_RUNTIME_FUNC_LIST
#undef DEFINE_ENTRY
  };

  static void* const funcs[] = {
#define DEFINE_ENTRY(NAME) reinterpret_cast<void*>(NAME) ,
#include "compiler_runtime_func_list.h"
    COMPILER_RUNTIME_FUNC_LIST(DEFINE_ENTRY)
#undef COMPILER_RUNTIME_FUNC_LIST
#undef DEFINE_ENTRY
  };

  static const size_t num_entries = sizeof(names) / sizeof(const char* const);

  const char* const* const names_begin = names;
  const char* const* const names_end = names + num_entries;

  const char* const* name_lbound_ptr =
      std::lower_bound(names_begin, names_end, name, CStringComparator());

  if (name_lbound_ptr < names_end && strcmp(*name_lbound_ptr, name) == 0) {
    return funcs[name_lbound_ptr - names_begin];
  } else {
    return NULL;
  }
}

// TODO: This runtime support function is the temporary solution for the stubs. Because now the
// stubs and runtime support functions in the LLVM part and the non-LLVM part is different.
// After deal these problems, we should remove this function, and will save a function call before
// every method invocation.
Method* art_ensure_resolved_from_code(Method* called,
                                      Method* caller,
                                      uint32_t dex_method_idx,
                                      bool is_virtual) {
  if (LIKELY(!called->IsResolutionMethod())) {
    return called;
  }

  // If the called method is ResolutionMethod.  -> ResolutionTrampoline(kUnknownMethod)
  //                                               Resolve method.
  ClassLinker* linker = Runtime::Current()->GetClassLinker();
  called = linker->ResolveMethod(dex_method_idx, caller, !is_virtual);
  if (UNLIKELY(art_get_current_thread_from_code()->IsExceptionPending())) {
    return NULL;
  }
  if (LIKELY(called->IsDirect() == !is_virtual)) {
    // Ensure that the called method's class is initialized.
    Class* called_class = called->GetDeclaringClass();
    linker->EnsureInitialized(called_class, true, true);
    return called;
  } else {
    Thread* thread = art_get_current_thread_from_code();
    // Direct method has been made virtual
    thread->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
                               "Expected direct method but found virtual: %s",
                               PrettyMethod(called, true).c_str());
    return NULL;
  }
}


// TODO: This runtime support function is the temporary solution for the stubs. Because now the
// stubs and runtime support functions in the LLVM part and the non-LLVM part is different.
// After deal these problems, we should remove this function, and will save a function call before
// every method invocation.
// It calls to this function before invoking any function, and this function will check:
// 1. The code address is ResolutionStub.          -> ResolutionTrampoline(kStaticMethod)
//                                                    Initialize class.
// 2. The code address is AbstractMethodErrorStub. -> AbstractMethodErrorStub
// 3. The code address is 0.                       -> Link the code by ELFLoader
// The item 3 will solved by in-place linking at image loading.
const void* art_fix_stub_from_code(Method* called) {
  DCHECK(!called->IsResolutionMethod()) << PrettyMethod(called);
  Runtime* runtime = Runtime::Current();
  const void* code = called->GetCode();

  // 1. The code address is ResolutionStub.          -> ResolutionTrampoline(kStaticMethod)
  if (UNLIKELY(code == runtime->GetResolutionStubArray(Runtime::kStaticMethod)->GetData())) {
    ClassLinker* linker = runtime->GetClassLinker();
    Class* called_class = called->GetDeclaringClass();
    linker->EnsureInitialized(called_class, true, true);
    if (LIKELY(called_class->IsInitialized())) {
      return called->GetCode();
    } else if (called_class->IsInitializing()) {
      return linker->GetOatCodeFor(called);
    } else {
      DCHECK(art_get_current_thread_from_code()->IsExceptionPending());
      DCHECK(called_class->IsErroneous());
      return NULL;
    }
  }

  // 2. The code address is AbstractMethodErrorStub. -> AbstractMethodErrorStub
  if (UNLIKELY(code == runtime->GetAbstractMethodErrorStubArray()->GetData())) {
    art_get_current_thread_from_code()->ThrowNewExceptionF("Ljava/lang/AbstractMethodError;",
                                                           "abstract method \"%s\"",
                                                           PrettyMethod(called).c_str());
    return NULL;
  }

  // 3. The code address is 0.                       -> Link the code by ELFLoader
  if (UNLIKELY(called->GetInvokeStub() == NULL || code == NULL)) {
    runtime->GetClassLinker()->LinkOatCodeFor(called);
    return called->GetCode();
  }

  return code;
}

// Handler for invocation on proxy methods. We create a boxed argument array. And we invoke
// the invocation handler which is a field within the proxy object receiver.
void art_proxy_invoke_handler_from_code(Method* proxy_method, ...) {
  va_list ap;
  va_start(ap, proxy_method);

  Object* receiver = va_arg(ap, Object*);
  Thread* thread = art_get_current_thread_from_code();
  MethodHelper proxy_mh(proxy_method);
  const size_t num_params = proxy_mh.NumArgs();

  // Start new JNI local reference state
  JNIEnvExt* env = thread->GetJniEnv();
  ScopedJniEnvLocalRefState env_state(env);

  // Create local ref. copies of the receiver
  jobject rcvr_jobj = AddLocalReference<jobject>(env, receiver);

  // Convert proxy method into expected interface method
  Method* interface_method = proxy_method->FindOverriddenMethod();
  DCHECK(interface_method != NULL);
  DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method);

  // Set up arguments array and place in local IRT during boxing (which may allocate/GC)
  jvalue args_jobj[3];
  args_jobj[0].l = rcvr_jobj;
  args_jobj[1].l = AddLocalReference<jobject>(env, interface_method);
  // Args array, if no arguments then NULL (don't include receiver in argument count)
  args_jobj[2].l = NULL;
  ObjectArray<Object>* args = NULL;
  if ((num_params - 1) > 0) {
    args = Runtime::Current()->GetClassLinker()->AllocObjectArray<Object>(num_params - 1);
    if (args == NULL) {
      CHECK(thread->IsExceptionPending());
      return;
    }
    args_jobj[2].l = AddLocalReference<jobjectArray>(env, args);
  }

  // Get parameter types.
  const char* shorty = proxy_mh.GetShorty();
  ObjectArray<Class>* param_types = proxy_mh.GetParameterTypes();
  if (param_types == NULL) {
    CHECK(thread->IsExceptionPending());
    return;
  }

  // Box arguments.
  for (size_t i = 0; i < (num_params - 1);++i) {
    JValue val;
    switch (shorty[i+1]) {
      case 'Z':
        val.SetZ(va_arg(ap, jint));
        break;
      case 'B':
        val.SetB(va_arg(ap, jint));
        break;
      case 'C':
        val.SetC(va_arg(ap, jint));
        break;
      case 'S':
        val.SetS(va_arg(ap, jint));
        break;
      case 'I':
        val.SetI(va_arg(ap, jint));
        break;
      case 'F':
        val.SetI(va_arg(ap, jint)); // TODO: is this right?
        break;
      case 'L':
        val.SetL(va_arg(ap, Object*));
        break;
      case 'D':
      case 'J':
        val.SetJ(va_arg(ap, jlong)); // TODO: is this right for double?
        break;
    }
    Class* param_type = param_types->Get(i);
    if (param_type->IsPrimitive()) {
      BoxPrimitive(param_type->GetPrimitiveType(), val);
      if (thread->IsExceptionPending()) {
        return;
      }
    }
    args->Set(i, val.GetL());
  }

  // Get the InvocationHandler method and the field that holds it within the Proxy object
  static jmethodID inv_hand_invoke_mid = NULL;
  static jfieldID proxy_inv_hand_fid = NULL;
  if (proxy_inv_hand_fid == NULL) {
    ScopedLocalRef<jclass> proxy(env, env->FindClass("java/lang/reflect/Proxy"));
    proxy_inv_hand_fid = env->GetFieldID(proxy.get(), "h", "Ljava/lang/reflect/InvocationHandler;");
    ScopedLocalRef<jclass> inv_hand_class(env, env->FindClass("java/lang/reflect/InvocationHandler"));
    inv_hand_invoke_mid = env->GetMethodID(inv_hand_class.get(), "invoke",
        "(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;");
  }

  DCHECK(env->IsInstanceOf(rcvr_jobj, env->FindClass("java/lang/reflect/Proxy")));

  jobject inv_hand = env->GetObjectField(rcvr_jobj, proxy_inv_hand_fid);
  // Call InvocationHandler.invoke
  jobject result = env->CallObjectMethodA(inv_hand, inv_hand_invoke_mid, args_jobj);

  // Place result in stack args
  if (!thread->IsExceptionPending()) {
    if (shorty[0] == 'V') {
      return;
    }
    Object* result_ref = thread->DecodeJObject(result);
    JValue* result_unboxed = va_arg(ap, JValue*);
    if (result_ref == NULL) {
      result_unboxed->SetL(NULL);
    } else {
      bool unboxed_okay = UnboxPrimitive(result_ref, proxy_mh.GetReturnType(), *result_unboxed, "result");
      if (!unboxed_okay) {
        thread->ClearException();
        thread->ThrowNewExceptionF("Ljava/lang/ClassCastException;",
                                 "Couldn't convert result of type %s to %s",
                                 PrettyTypeOf(result_ref).c_str(),
                                 PrettyDescriptor(proxy_mh.GetReturnType()).c_str());
        return;
      }
    }
  } else {
    // In the case of checked exceptions that aren't declared, the exception must be wrapped by
    // a UndeclaredThrowableException.
    Throwable* exception = thread->GetException();
    thread->ClearException();
    if (!exception->IsCheckedException()) {
      thread->SetException(exception);
    } else {
      SynthesizedProxyClass* proxy_class =
          down_cast<SynthesizedProxyClass*>(proxy_method->GetDeclaringClass());
      int throws_index = -1;
      size_t num_virt_methods = proxy_class->NumVirtualMethods();
      for (size_t i = 0; i < num_virt_methods; i++) {
        if (proxy_class->GetVirtualMethod(i) == proxy_method) {
          throws_index = i;
          break;
        }
      }
      CHECK_NE(throws_index, -1);
      ObjectArray<Class>* declared_exceptions = proxy_class->GetThrows()->Get(throws_index);
      Class* exception_class = exception->GetClass();
      bool declares_exception = false;
      for (int i = 0; i < declared_exceptions->GetLength() && !declares_exception; i++) {
        Class* declared_exception = declared_exceptions->Get(i);
        declares_exception = declared_exception->IsAssignableFrom(exception_class);
      }
      if (declares_exception) {
        thread->SetException(exception);
      } else {
        ThrowNewUndeclaredThrowableException(thread, env, exception);
      }
    }
  }

  va_end(ap);
}

void* art_find_runtime_support_func(void* context, char const* name) {
  struct func_entry_t {
    char const* name;
    size_t name_len;
    void* addr;
  };

  static struct func_entry_t const tab[] = {
#define DEFINE_ENTRY(ID, NAME) \
    { #NAME, sizeof(#NAME) - 1, reinterpret_cast<void*>(NAME) },

#include "runtime_support_func_list.h"
    RUNTIME_SUPPORT_FUNC_LIST(DEFINE_ENTRY)
#undef RUNTIME_SUPPORT_FUNC_LIST
#undef DEFINE_ENTRY
  };

  static size_t const tab_size = sizeof(tab) / sizeof(struct func_entry_t);

  // Search the compiler runtime (such as __divdi3)
  void* result = art_find_compiler_runtime_func(name);
  if (result != NULL) {
    return result;
  }

  // Note: Since our table is small, we are using trivial O(n) searching
  // function.  For bigger table, it will be better to use binary
  // search or hash function.
  size_t i;
  size_t name_len = strlen(name);
  for (i = 0; i < tab_size; ++i) {
    if (name_len == tab[i].name_len && strcmp(name, tab[i].name) == 0) {
      return tab[i].addr;
    }
  }

  LOG(FATAL) << "Error: Can't find symbol " << name;
  return 0;
}

}  // namespace art
