Implement proxy stub for compiler_llvm.

Change-Id: Id8ba59c62795d885a18b3cc634e7ef370a2d2f97
diff --git a/build/Android.libart-compiler-llvm.mk b/build/Android.libart-compiler-llvm.mk
index 3cbff80..f27e83e 100644
--- a/build/Android.libart-compiler-llvm.mk
+++ b/build/Android.libart-compiler-llvm.mk
@@ -30,8 +30,8 @@
 	src/compiler_llvm/runtime_support_builder_arm.cc \
 	src/compiler_llvm/runtime_support_builder_x86.cc \
 	src/compiler_llvm/runtime_support_llvm.cc \
-	src/compiler_llvm/tbaa_info.cc \
-	src/compiler_llvm/upcall_compiler.cc
+	src/compiler_llvm/stub_compiler.cc \
+	src/compiler_llvm/tbaa_info.cc
 
 # $(1): target or host
 # $(2): ndebug or debug
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 43f1b42..000e2a5 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -1344,6 +1344,9 @@
     }
     if (method->GetInvokeStub() == NULL) {
       method->SetInvokeStub(oat_method.GetInvokeStub());
+#if defined(ART_USE_LLVM_COMPILER)
+      method->SetProxyStub(oat_method.GetProxyStub());
+#endif
     }
   }
 }
@@ -2297,8 +2300,7 @@
 #if !defined(ART_USE_LLVM_COMPILER)
   method->SetCode(reinterpret_cast<void*>(art_proxy_invoke_handler));
 #else
-  method->SetCode(reinterpret_cast<const void*>(
-      static_cast<uintptr_t>(compiler_llvm::special_stub::kProxyStub)));
+  method->SetCode(prototype->GetProxyStub());
 #endif
 
   return method;
diff --git a/src/common_test.h b/src/common_test.h
index 3b31bd4..b03d4d6 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -210,6 +210,7 @@
                                 static_cast<uint16_t>(-1u),
                                 static_cast<uint16_t>(-1u),
                                 static_cast<uint16_t>(-1u),
+                                static_cast<uint16_t>(-1u),
                                 static_cast<uint16_t>(-1u)
 #endif
                                 );
diff --git a/src/compiled_method.cc b/src/compiled_method.cc
index 89b5496..07f331c 100644
--- a/src/compiled_method.cc
+++ b/src/compiled_method.cc
@@ -180,8 +180,8 @@
 }
 
 #if defined(ART_USE_LLVM_COMPILER)
-CompiledInvokeStub::CompiledInvokeStub(uint16_t elf_idx, uint16_t elf_func_idx)
-    : elf_idx_(elf_idx), elf_func_idx_(elf_func_idx) {
+CompiledInvokeStub::CompiledInvokeStub(uint16_t elf_idx)
+    : elf_idx_(elf_idx) {
 }
 #endif
 
diff --git a/src/compiled_method.h b/src/compiled_method.h
index 96dfa00..f436214 100644
--- a/src/compiled_method.h
+++ b/src/compiled_method.h
@@ -21,6 +21,7 @@
 
 #include "instruction_set.h"
 #include "utils.h"
+#include "UniquePtr.h"
 
 namespace llvm {
   class Function;
@@ -120,20 +121,33 @@
  public:
   explicit CompiledInvokeStub(std::vector<uint8_t>& code);
 #if defined(ART_USE_LLVM_COMPILER)
-  explicit CompiledInvokeStub(uint16_t elf_idx, uint16_t elf_func_idx);
+  explicit CompiledInvokeStub(uint16_t elf_idx);
 #endif
   ~CompiledInvokeStub();
 
   const std::vector<uint8_t>& GetCode() const;
 
-  uint16_t GetElfIndex() const {
+  uint16_t GetStubElfIndex() const {
     DCHECK(IsExecutableInElf());
     return elf_idx_;
   }
 
-  uint16_t GetElfFuncIndex() const {
+  uint16_t GetInvokeStubElfFuncIndex() const {
     DCHECK(IsExecutableInElf());
-    return elf_func_idx_;
+    return invoke_stub_elf_func_idx_;
+  }
+
+  uint16_t GetProxyStubElfFuncIndex() const {
+    DCHECK(IsExecutableInElf());
+    return proxy_stub_elf_func_idx_;
+  }
+
+  void SetInvokeStub(uint16_t invoke_stub_elf_func_idx) {
+    invoke_stub_elf_func_idx_ = invoke_stub_elf_func_idx;
+  }
+
+  void SetProxyStub(uint16_t proxy_stub_elf_func_idx) {
+    proxy_stub_elf_func_idx_ = proxy_stub_elf_func_idx;
   }
 
   bool IsExecutableInElf() const {
@@ -143,7 +157,8 @@
  private:
   std::vector<uint8_t> code_;
   uint16_t elf_idx_;
-  uint16_t elf_func_idx_;
+  uint16_t invoke_stub_elf_func_idx_;
+  uint16_t proxy_stub_elf_func_idx_;
 };
 
 }  // namespace art
diff --git a/src/compiler_llvm/compiler_llvm.cc b/src/compiler_llvm/compiler_llvm.cc
index 6d30912..95e9803 100644
--- a/src/compiler_llvm/compiler_llvm.cc
+++ b/src/compiler_llvm/compiler_llvm.cc
@@ -30,7 +30,7 @@
 #include "oat_compilation_unit.h"
 #include "oat_file.h"
 #include "stl_util.h"
-#include "upcall_compiler.h"
+#include "stub_compiler.h"
 
 #include <llvm/LinkAllPasses.h>
 #include <llvm/LinkAllVMCore.h>
@@ -225,8 +225,8 @@
 
 const Method::InvokeStub* CompilerLLVM::
 GetMethodInvokeStubAddr(const CompiledInvokeStub* cm) const {
-  return elf_loader_->GetMethodInvokeStubAddr(cm->GetElfIndex(),
-                                              cm->GetElfFuncIndex());
+  return elf_loader_->GetMethodInvokeStubAddr(cm->GetStubElfIndex(),
+                                              cm->GetInvokeStubElfFuncIndex());
 }
 
 
@@ -279,10 +279,15 @@
 
   MutexLock GUARD_CUNIT(curr_cunit_->cunit_lock_);
 
-  UniquePtr<UpcallCompiler> upcall_compiler(
-    new UpcallCompiler(curr_cunit_, *compiler_));
+  UniquePtr<StubCompiler> stub_compiler(
+    new StubCompiler(curr_cunit_, *compiler_));
 
-  return upcall_compiler->CreateStub(is_static, shorty);
+  CompiledInvokeStub* compiled_stub = new CompiledInvokeStub(curr_cunit_->GetElfIndex());
+
+  compiled_stub->SetInvokeStub(stub_compiler->CreateInvokeStub(is_static, shorty));
+  compiled_stub->SetProxyStub(stub_compiler->CreateProxyStub(is_static, shorty));
+
+  return compiled_stub;
 }
 
 } // namespace compiler_llvm
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 620ba39..cd79dcb 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -72,7 +72,7 @@
     basic_blocks_(code_item_->insns_size_in_code_units_),
     basic_block_landing_pads_(code_item_->tries_size_, NULL),
     basic_block_unwind_(NULL), basic_block_unreachable_(NULL),
-    shadow_frame_(NULL), jvalue_temp_(NULL), old_shadow_frame_(NULL),
+    shadow_frame_(NULL), old_shadow_frame_(NULL),
     already_pushed_shadow_frame_(NULL), shadow_frame_size_(0),
     elf_func_idx_(cunit_->AcquireUniqueElfFuncIndex()) {
 }
@@ -168,7 +168,6 @@
 #endif
 
   irb_.SetInsertPoint(basic_block_alloca_);
-  jvalue_temp_ = irb_.CreateAlloca(irb_.getJValueTy());
 
   // Create Shadow Frame
   if (method_info_.need_shadow_frame) {
@@ -2880,10 +2879,7 @@
   llvm::BasicBlock* block_stub = CreateBasicBlockWithDexPC(dex_pc, "stub");
   llvm::BasicBlock* block_continue = CreateBasicBlockWithDexPC(dex_pc, "cont");
 
-  llvm::Value* code_addr_int = irb_.CreatePtrToInt(code_addr, irb_.getPtrEquivIntTy());
-  llvm::Value* max_stub_int = irb_.getPtrEquivInt(special_stub::kMaxSpecialStub);
-  llvm::Value* is_stub = irb_.CreateICmpULT(code_addr_int, max_stub_int);
-  irb_.CreateCondBr(is_stub, block_stub, block_normal, kUnlikely);
+  irb_.CreateCondBr(irb_.CreateIsNull(code_addr), block_stub, block_normal, kUnlikely);
 
 
   irb_.SetInsertPoint(block_normal);
@@ -2898,42 +2894,15 @@
 
 
   irb_.SetInsertPoint(block_stub);
-  {
-    { // lazy link
-      // TODO: Remove this after we solve the link problem.
-      llvm::BasicBlock* block_proxy_stub = CreateBasicBlockWithDexPC(dex_pc, "proxy");
-      llvm::BasicBlock* block_link = CreateBasicBlockWithDexPC(dex_pc, "link");
+  { // lazy link
+    // TODO: Remove this after we solve the link problem.
+    code_addr = EmitFixStub(callee_method_object_addr, callee_method_idx, is_static);
 
-      irb_.CreateCondBr(irb_.CreateIsNull(code_addr), block_link, block_proxy_stub, kUnlikely);
+    EmitGuard_ExceptionLandingPad(dex_pc, false);
 
-
-      irb_.SetInsertPoint(block_link);
-      code_addr = EmitFixStub(callee_method_object_addr, callee_method_idx, is_static);
-
-      EmitGuard_ExceptionLandingPad(dex_pc, false);
-
-      llvm::Value* retval = irb_.CreateCall(code_addr, args);
-      if (ret_shorty != 'V') {
-        EmitStoreDalvikRetValReg(ret_shorty, kAccurate, retval);
-      }
-      irb_.CreateBr(block_continue);
-
-
-      irb_.SetInsertPoint(block_proxy_stub);
-    }
-    { // proxy stub
-      if (ret_shorty != 'V') {
-        args.push_back(jvalue_temp_);
-      }
-      // TODO: Remove this after we solve the proxy trampoline calling convention problem.
-      irb_.CreateCall(irb_.GetRuntime(ProxyInvokeHandler), args);
-      if (ret_shorty != 'V') {
-        llvm::Type* accurate_ret_type = irb_.getJType(ret_shorty, kAccurate);
-        llvm::Value* result_addr =
-            irb_.CreateBitCast(jvalue_temp_, accurate_ret_type->getPointerTo());
-        llvm::Value* retval = irb_.CreateLoad(result_addr, kTBAAStackTemp);
-        EmitStoreDalvikRetValReg(ret_shorty, kAccurate, retval);
-      }
+    llvm::Value* retval = irb_.CreateCall(code_addr, args);
+    if (ret_shorty != 'V') {
+      EmitStoreDalvikRetValReg(ret_shorty, kAccurate, retval);
     }
   }
   irb_.CreateBr(block_continue);
diff --git a/src/compiler_llvm/method_compiler.h b/src/compiler_llvm/method_compiler.h
index 44ab863..1907823 100644
--- a/src/compiler_llvm/method_compiler.h
+++ b/src/compiler_llvm/method_compiler.h
@@ -473,7 +473,6 @@
   llvm::BasicBlock* basic_block_unreachable_;
 
   llvm::AllocaInst* shadow_frame_;
-  llvm::AllocaInst* jvalue_temp_;
   llvm::Value* old_shadow_frame_;
 
   llvm::Value* already_pushed_shadow_frame_;
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index 578f84e..59124ce 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -654,7 +654,7 @@
   va_start(ap, proxy_method);
 
   Object* receiver = va_arg(ap, Object*);
-  Thread* thread = art_get_current_thread_from_code();
+  Thread* thread = va_arg(ap, Thread*);
   MethodHelper proxy_mh(proxy_method);
   const size_t num_params = proxy_mh.NumArgs();
 
diff --git a/src/compiler_llvm/runtime_support_llvm.h b/src/compiler_llvm/runtime_support_llvm.h
index bca9528..3e8d96d 100644
--- a/src/compiler_llvm/runtime_support_llvm.h
+++ b/src/compiler_llvm/runtime_support_llvm.h
@@ -19,16 +19,6 @@
 
 namespace art {
 
-namespace compiler_llvm {
-namespace special_stub {
-  enum SpecialStub {
-    kProxyStub = 16,
-    kMaxSpecialStub
-  };
-}
-}  // namespace compiler_llvm
-
-
 class Method;
 class Object;
 
diff --git a/src/compiler_llvm/upcall_compiler.cc b/src/compiler_llvm/stub_compiler.cc
similarity index 67%
rename from src/compiler_llvm/upcall_compiler.cc
rename to src/compiler_llvm/stub_compiler.cc
index 0f3a92e..2cf5141 100644
--- a/src/compiler_llvm/upcall_compiler.cc
+++ b/src/compiler_llvm/stub_compiler.cc
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "upcall_compiler.h"
+#include "stub_compiler.h"
 
 #include "compilation_unit.h"
 #include "compiled_method.h"
@@ -40,21 +40,21 @@
 using namespace runtime_support;
 
 
-UpcallCompiler::UpcallCompiler(CompilationUnit* cunit, Compiler& compiler)
+StubCompiler::StubCompiler(CompilationUnit* cunit, Compiler& compiler)
 : cunit_(cunit), compiler_(&compiler), module_(cunit_->GetModule()),
-  context_(cunit_->GetLLVMContext()), irb_(*cunit_->GetIRBuilder()),
-  elf_func_idx_(cunit_->AcquireUniqueElfFuncIndex()) {
+  context_(cunit_->GetLLVMContext()), irb_(*cunit_->GetIRBuilder()) {
 }
 
 
-CompiledInvokeStub* UpcallCompiler::CreateStub(bool is_static,
-                                               char const* shorty) {
+uint16_t StubCompiler::CreateInvokeStub(bool is_static,
+                                        char const* shorty) {
+  uint16_t elf_func_idx = cunit_->AcquireUniqueElfFuncIndex();
 
   CHECK_NE(shorty, static_cast<char const*>(NULL));
   size_t shorty_size = strlen(shorty);
 
   // Function name
-  std::string func_name(ElfFuncName(elf_func_idx_));
+  std::string func_name(ElfFuncName(elf_func_idx));
 
   // Get argument types
   llvm::Type* arg_types[] = {
@@ -189,7 +189,80 @@
   // store ret_addr, and ret_void.  Beside, we guess that we have to use
   // 50 bytes to represent one LLVM instruction.
 
-  return new CompiledInvokeStub(cunit_->GetElfIndex(), elf_func_idx_);
+  return elf_func_idx;
+}
+
+uint16_t StubCompiler::CreateProxyStub(bool is_static,
+                                       char const* shorty) {
+  // Static method dosen't need proxy stub.
+  if (is_static) {
+    return NULL;
+  }
+
+  CHECK_NE(shorty, static_cast<char const*>(NULL));
+  size_t shorty_size = strlen(shorty);
+
+  uint16_t elf_func_idx = cunit_->AcquireUniqueElfFuncIndex();
+
+  // Function name
+  std::string func_name(ElfFuncName(elf_func_idx));
+
+  // Accurate function type
+  llvm::Type* accurate_ret_type = irb_.getJType(shorty[0], kAccurate);
+  std::vector<llvm::Type*> accurate_arg_types;
+  accurate_arg_types.push_back(irb_.getJObjectTy()); // method
+  accurate_arg_types.push_back(irb_.getJObjectTy()); // this
+  for (size_t i = 1; i < shorty_size; ++i) {
+    accurate_arg_types.push_back(irb_.getJType(shorty[i], kAccurate));
+  }
+  llvm::FunctionType* accurate_func_type =
+    llvm::FunctionType::get(accurate_ret_type, accurate_arg_types, false);
+
+  // Create function
+  llvm::Function* func =
+    llvm::Function::Create(accurate_func_type, llvm::Function::ExternalLinkage,
+                           func_name, module_);
+
+  // Create basic block for the body of this function
+  llvm::BasicBlock* block_body =
+    llvm::BasicBlock::Create(*context_, "proxy", func);
+  irb_.SetInsertPoint(block_body);
+
+  // JValue for proxy return
+  llvm::AllocaInst* jvalue_temp = irb_.CreateAlloca(irb_.getJValueTy());
+
+  // Load actual arguments
+  llvm::Function::arg_iterator arg_iter = func->arg_begin();
+  std::vector<llvm::Value*> args;
+  args.push_back(arg_iter++); // method
+  args.push_back(arg_iter++); // this
+  args.push_back(irb_.Runtime().EmitGetCurrentThread()); // thread
+  for (size_t i = 1; i < shorty_size; ++i) {
+    args.push_back(arg_iter++);
+  }
+  if (shorty[0] != 'V') {
+    args.push_back(jvalue_temp);
+  }
+
+  // Call ProxyInvokeHandler
+  // TODO: Partial inline ProxyInvokeHandler, don't use VarArg.
+  irb_.CreateCall(irb_.GetRuntime(ProxyInvokeHandler), args);
+  if (shorty[0] != 'V') {
+    llvm::Value* result_addr =
+        irb_.CreateBitCast(jvalue_temp, accurate_ret_type->getPointerTo());
+    llvm::Value* retval = irb_.CreateLoad(result_addr, kTBAAStackTemp);
+    irb_.CreateRet(retval);
+  } else {
+    irb_.CreateRetVoid();
+  }
+
+  // Verify the generated function
+  VERIFY_LLVM_FUNCTION(*func);
+
+  // Add the memory usage approximation of the compilation unit
+  cunit_->AddMemUsageApproximation((shorty_size + 2) * 50);
+
+  return elf_func_idx;
 }
 
 
diff --git a/src/compiler_llvm/upcall_compiler.h b/src/compiler_llvm/stub_compiler.h
similarity index 73%
rename from src/compiler_llvm/upcall_compiler.h
rename to src/compiler_llvm/stub_compiler.h
index 9cb49b0..4b49ec4 100644
--- a/src/compiler_llvm/upcall_compiler.h
+++ b/src/compiler_llvm/stub_compiler.h
@@ -14,13 +14,14 @@
  * limitations under the License.
  */
 
-#ifndef ART_SRC_COMPILER_LLVM_UPCALL_COMPILER_H_
-#define ART_SRC_COMPILER_LLVM_UPCALL_COMPILER_H_
+#ifndef ART_SRC_COMPILER_LLVM_STUB_COMPILER_H_
+#define ART_SRC_COMPILER_LLVM_STUB_COMPILER_H_
 
 #include <stdint.h>
 
 namespace art {
   class CompiledInvokeStub;
+  class CompiledProxyStub;
   class Compiler;
 }
 
@@ -36,11 +37,12 @@
 class CompilerLLVM;
 class IRBuilder;
 
-class UpcallCompiler {
+class StubCompiler {
  public:
-  UpcallCompiler(CompilationUnit* cunit, Compiler& compiler);
+  StubCompiler(CompilationUnit* cunit, Compiler& compiler);
 
-  CompiledInvokeStub* CreateStub(bool is_static, char const* shorty);
+  uint16_t CreateInvokeStub(bool is_static, char const* shorty);
+  uint16_t CreateProxyStub(bool is_static, char const* shorty);
 
  private:
   CompilationUnit* cunit_;
@@ -48,7 +50,6 @@
   llvm::Module* module_;
   llvm::LLVMContext* context_;
   IRBuilder& irb_;
-  uint16_t elf_func_idx_;
 };
 
 
@@ -56,4 +57,4 @@
 } // namespace art
 
 
-#endif // ART_SRC_COMPILER_LLVM_UPCALL_COMPILER_H_
+#endif // ART_SRC_COMPILER_LLVM_STUB_COMPILER_H_
diff --git a/src/oat.cc b/src/oat.cc
index bf05f71..d5aaf64 100644
--- a/src/oat.cc
+++ b/src/oat.cc
@@ -176,7 +176,8 @@
                                  , uint16_t code_elf_idx,
                                    uint16_t code_elf_func_idx,
                                    uint16_t invoke_stub_elf_idx,
-                                   uint16_t invoke_stub_elf_func_idx
+                                   uint16_t invoke_stub_elf_func_idx,
+                                   uint16_t proxy_stub_elf_func_idx
 #endif
                                    )
   : code_offset_(code_offset),
@@ -191,7 +192,8 @@
   , code_elf_idx_(code_elf_idx),
     code_elf_func_idx_(code_elf_func_idx),
     invoke_stub_elf_idx_(invoke_stub_elf_idx),
-    invoke_stub_elf_func_idx_(invoke_stub_elf_func_idx)
+    invoke_stub_elf_func_idx_(invoke_stub_elf_func_idx),
+    proxy_stub_elf_func_idx_(proxy_stub_elf_func_idx)
 #endif
 {}
 
diff --git a/src/oat.h b/src/oat.h
index 4fadcc5..c2617cf 100644
--- a/src/oat.h
+++ b/src/oat.h
@@ -86,7 +86,8 @@
                  , uint16_t code_elf_idx,
                    uint16_t code_elf_func_idx,
                    uint16_t invoke_stub_elf_idx,
-                   uint16_t invoke_stub_elf_func_idx
+                   uint16_t invoke_stub_elf_func_idx,
+                   uint16_t proxy_stub_elf_func_idx
 #endif
                    );
   ~OatMethodOffsets();
@@ -105,6 +106,7 @@
   uint16_t code_elf_func_idx_;
   uint16_t invoke_stub_elf_idx_;
   uint16_t invoke_stub_elf_func_idx_;
+  uint16_t proxy_stub_elf_func_idx_;
 #endif
 };
 
diff --git a/src/oat_file.cc b/src/oat_file.cc
index 7196222..32e3b69 100644
--- a/src/oat_file.cc
+++ b/src/oat_file.cc
@@ -314,7 +314,8 @@
       oat_method_offsets.code_elf_idx_,
       oat_method_offsets.code_elf_func_idx_,
       oat_method_offsets.invoke_stub_elf_idx_,
-      oat_method_offsets.invoke_stub_elf_func_idx_
+      oat_method_offsets.invoke_stub_elf_func_idx_,
+      oat_method_offsets.proxy_stub_elf_func_idx_
 #endif
       );
 }
@@ -333,7 +334,8 @@
                               const uint16_t code_elf_idx,
                               const uint16_t code_elf_func_idx,
                               const uint16_t invoke_stub_elf_idx,
-                              const uint16_t invoke_stub_elf_func_idx
+                              const uint16_t invoke_stub_elf_func_idx,
+                              const uint16_t proxy_stub_elf_func_idx
 #endif
                               )
   : begin_(base),
@@ -350,7 +352,8 @@
     code_elf_idx_(code_elf_idx),
     code_elf_func_idx_(code_elf_func_idx),
     invoke_stub_elf_idx_(invoke_stub_elf_idx),
-    invoke_stub_elf_func_idx_(invoke_stub_elf_func_idx)
+    invoke_stub_elf_func_idx_(invoke_stub_elf_func_idx),
+    proxy_stub_elf_func_idx_(proxy_stub_elf_func_idx)
 #endif
 {
 #ifndef NDEBUG
@@ -444,6 +447,18 @@
   }
 }
 
+#if defined(ART_USE_LLVM_COMPILER)
+const void* OatFile::OatMethod::GetProxyStub() const {
+  CHECK(elf_loader_ != NULL);
+  const void* stub = NULL;
+  if (proxy_stub_elf_func_idx_ != static_cast<uint16_t>(-1)) {
+    stub = elf_loader_->GetMethodCodeAddr(invoke_stub_elf_idx_,
+                                          proxy_stub_elf_func_idx_);
+  }
+  return stub;
+}
+#endif
+
 void OatFile::OatMethod::LinkMethodPointers(Method* method) const {
   CHECK(method != NULL);
   method->SetCode(GetCode());
@@ -454,6 +469,9 @@
   method->SetVmapTable(GetVmapTable());
   method->SetGcMap(GetGcMap());  // Note, used by native methods in work around JNI mode.
   method->SetInvokeStub(GetInvokeStub());
+#if defined(ART_USE_LLVM_COMPILER)
+  method->SetProxyStub(GetProxyStub());
+#endif
 }
 
 void OatFile::OatMethod::LinkMethodOffsets(Method* method) const {
diff --git a/src/oat_file.h b/src/oat_file.h
index 0b1ebac..e958c4d 100644
--- a/src/oat_file.h
+++ b/src/oat_file.h
@@ -150,6 +150,10 @@
     const Method::InvokeStub* GetInvokeStub() const;
     uint32_t GetInvokeStubSize() const;
 
+#if defined(ART_USE_LLVM_COMPILER)
+    const void* GetProxyStub() const;
+#endif
+
     ~OatMethod();
 
     // Create an OatMethod with offsets relative to the given base address
@@ -167,7 +171,8 @@
               const uint16_t code_elf_idx,
               const uint16_t code_elf_func_idx,
               const uint16_t invoke_stub_elf_idx,
-              const uint16_t invoke_stub_elf_func_idx
+              const uint16_t invoke_stub_elf_func_idx,
+              const uint16_t proxy_stub_elf_func_idx
 #endif
               );
 
@@ -198,6 +203,7 @@
     uint16_t code_elf_func_idx_;
     uint16_t invoke_stub_elf_idx_;
     uint16_t invoke_stub_elf_func_idx_;
+    uint16_t proxy_stub_elf_func_idx_;
 #endif
 
     friend class OatClass;
diff --git a/src/oat_writer.cc b/src/oat_writer.cc
index ffdb0c8..f5c0816 100644
--- a/src/oat_writer.cc
+++ b/src/oat_writer.cc
@@ -273,6 +273,7 @@
 #if defined(ART_USE_LLVM_COMPILER)
   uint16_t invoke_stub_elf_idx = static_cast<uint16_t>(-1u);
   uint16_t invoke_stub_elf_func_idx = static_cast<uint16_t>(-1u);
+  uint16_t proxy_stub_elf_func_idx = static_cast<uint16_t>(-1u);
 #endif
 
   CompiledMethod* compiled_method =
@@ -365,10 +366,18 @@
   const CompiledInvokeStub* compiled_invoke_stub = compiler_->FindInvokeStub(is_static, shorty);
   if (compiled_invoke_stub != NULL) {
     if (compiled_invoke_stub->IsExecutableInElf()) {
+<<<<<<< HEAD
 #if defined(ART_USE_LLVM_COMPILER)
       invoke_stub_elf_idx = compiled_invoke_stub->GetElfIndex();
       invoke_stub_elf_func_idx = compiled_invoke_stub->GetElfFuncIndex();
 #endif
+=======
+      invoke_stub_elf_idx = compiled_invoke_stub->GetStubElfIndex();
+      invoke_stub_elf_func_idx = compiled_invoke_stub->GetInvokeStubElfFuncIndex();
+      if (!is_static) {
+        proxy_stub_elf_func_idx = compiled_invoke_stub->GetProxyStubElfFuncIndex();
+      }
+>>>>>>> f3b0b35... Implement proxy stub for compiler_llvm.
     } else {
       offset = CompiledMethod::AlignCode(offset, compiler_->GetInstructionSet());
       DCHECK_ALIGNED(offset, kArmAlignment);
@@ -403,7 +412,8 @@
                        , code_elf_idx,
                          code_elf_func_idx,
                          invoke_stub_elf_idx,
-                         invoke_stub_elf_func_idx
+                         invoke_stub_elf_func_idx,
+                         proxy_stub_elf_func_idx
 #endif
                          );
 
diff --git a/src/object.h b/src/object.h
index f5970f6..e787933 100644
--- a/src/object.h
+++ b/src/object.h
@@ -861,6 +861,22 @@
     return OFFSET_OF_OBJECT_MEMBER(Method, invoke_stub_);
   }
 
+#if defined(ART_USE_LLVM_COMPILER)
+  // Proxy stub entry point
+  const void* GetProxyStub() const {
+    // NOTE: LLVM doesn't use vmap table, so we reuse it for proxy stub.
+    const void* result = GetFieldPtr<const void*>(
+        OFFSET_OF_OBJECT_MEMBER(Method, vmap_table_), false);
+    // TODO: DCHECK(result != NULL);  should be ahead of time compiled
+    return result;
+  }
+
+  void SetProxyStub(const void* proxy_stub) {
+    SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(Method, vmap_table_),
+                             proxy_stub, false);
+  }
+#endif
+
   static MemberOffset GetMethodIndexOffset() {
     return OFFSET_OF_OBJECT_MEMBER(Method, method_index_);
   }