Implement X86 trampoline for llvm compiler.

Change-Id: I0c6ec3a59eaebd5e28ca8e95f2711a31b79b9279
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 1edfe1a..5bd214a 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -1401,7 +1401,13 @@
     // back.
 
     // TODO: Remove this workaround.
-    GetOatMethodFor(method).LinkMethodPointers(method);
+    OatFile::OatMethod oat_method = GetOatMethodFor(method);
+    if (method->GetCode() == NULL) {
+      method->SetCode(oat_method.GetCode());
+    }
+    if (method->GetInvokeStub() == NULL) {
+      method->SetInvokeStub(oat_method.GetInvokeStub());
+    }
   }
 }
 
diff --git a/src/compiler_llvm/art_module.ll b/src/compiler_llvm/art_module.ll
index bdc4504..87be92a 100644
--- a/src/compiler_llvm/art_module.ll
+++ b/src/compiler_llvm/art_module.ll
@@ -167,11 +167,6 @@
 
 declare void @art_mark_gc_card_from_code(%JavaObject*, %JavaObject*)
 
-declare %JavaObject* @art_ensure_resolved_from_code(%JavaObject*,
-                                                    %JavaObject*,
-                                                    i32,
-                                                    i1)
-
 declare %JavaObject* @art_fix_stub_from_code(%JavaObject*)
 
 declare void @art_proxy_invoke_handler_from_code(%JavaObject*, ...)
diff --git a/src/compiler_llvm/generated/art_module.cc b/src/compiler_llvm/generated/art_module.cc
index cf92e87..c727d40 100644
--- a/src/compiler_llvm/generated/art_module.cc
+++ b/src/compiler_llvm/generated/art_module.cc
@@ -314,9 +314,6 @@
 
 std::vector<Type*>FuncTy_34_args;
 FuncTy_34_args.push_back(PointerTy_1);
-FuncTy_34_args.push_back(PointerTy_1);
-FuncTy_34_args.push_back(IntegerType::get(mod->getContext(), 32));
-FuncTy_34_args.push_back(IntegerType::get(mod->getContext(), 1));
 FunctionType* FuncTy_34 = FunctionType::get(
  /*Result=*/PointerTy_1,
  /*Params=*/FuncTy_34_args,
@@ -325,15 +322,8 @@
 std::vector<Type*>FuncTy_35_args;
 FuncTy_35_args.push_back(PointerTy_1);
 FunctionType* FuncTy_35 = FunctionType::get(
- /*Result=*/PointerTy_1,
- /*Params=*/FuncTy_35_args,
- /*isVarArg=*/false);
-
-std::vector<Type*>FuncTy_36_args;
-FuncTy_36_args.push_back(PointerTy_1);
-FunctionType* FuncTy_36 = FunctionType::get(
  /*Result=*/Type::getVoidTy(mod->getContext()),
- /*Params=*/FuncTy_36_args,
+ /*Params=*/FuncTy_35_args,
  /*isVarArg=*/true);
 
 
@@ -955,21 +945,10 @@
 AttrListPtr func_art_mark_gc_card_from_code_PAL;
 func_art_mark_gc_card_from_code->setAttributes(func_art_mark_gc_card_from_code_PAL);
 
-Function* func_art_ensure_resolved_from_code = mod->getFunction("art_ensure_resolved_from_code");
-if (!func_art_ensure_resolved_from_code) {
-func_art_ensure_resolved_from_code = Function::Create(
- /*Type=*/FuncTy_34,
- /*Linkage=*/GlobalValue::ExternalLinkage,
- /*Name=*/"art_ensure_resolved_from_code", mod); // (external, no body)
-func_art_ensure_resolved_from_code->setCallingConv(CallingConv::C);
-}
-AttrListPtr func_art_ensure_resolved_from_code_PAL;
-func_art_ensure_resolved_from_code->setAttributes(func_art_ensure_resolved_from_code_PAL);
-
 Function* func_art_fix_stub_from_code = mod->getFunction("art_fix_stub_from_code");
 if (!func_art_fix_stub_from_code) {
 func_art_fix_stub_from_code = Function::Create(
- /*Type=*/FuncTy_35,
+ /*Type=*/FuncTy_34,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"art_fix_stub_from_code", mod); // (external, no body)
 func_art_fix_stub_from_code->setCallingConv(CallingConv::C);
@@ -980,7 +959,7 @@
 Function* func_art_proxy_invoke_handler_from_code = mod->getFunction("art_proxy_invoke_handler_from_code");
 if (!func_art_proxy_invoke_handler_from_code) {
 func_art_proxy_invoke_handler_from_code = Function::Create(
- /*Type=*/FuncTy_36,
+ /*Type=*/FuncTy_35,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"art_proxy_invoke_handler_from_code", mod); // (external, no body)
 func_art_proxy_invoke_handler_from_code->setCallingConv(CallingConv::C);
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index b128693..91b57a6 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -2783,18 +2783,6 @@
     << PrettyMethod(callee_method_idx, *dex_file_);
 }
 
-llvm::Value* MethodCompiler::EmitEnsureResolved(llvm::Value* callee,
-                                                llvm::Value* caller,
-                                                uint32_t dex_method_idx,
-                                                bool is_virtual) {
-  // TODO: Remove this after we solve the trampoline related problems.
-  return  irb_.CreateCall4(irb_.GetRuntime(EnsureResolved),
-                           callee,
-                           caller,
-                           irb_.getInt32(dex_method_idx),
-                           irb_.getInt1(is_virtual));
-}
-
 llvm::Value* MethodCompiler::EmitFixStub(llvm::Value* callee_method_object_addr,
                                          uint32_t method_idx,
                                          bool is_static) {
@@ -2869,21 +2857,6 @@
                                                  dex_pc, is_fast_path);
       break;
     }
-
-    // Ensure the callee method object is resolved.
-    bool is_virtual = (dec_insn.opcode == Instruction::INVOKE_VIRTUAL) ||
-                      (dec_insn.opcode == Instruction::INVOKE_VIRTUAL_RANGE) ||
-                      (dec_insn.opcode == Instruction::INVOKE_SUPER) ||
-                      (dec_insn.opcode == Instruction::INVOKE_SUPER_RANGE);
-
-    llvm::Value* caller_method_object_addr = EmitLoadMethodObjectAddr();
-
-    callee_method_object_addr = EmitEnsureResolved(callee_method_object_addr,
-                                                   caller_method_object_addr,
-                                                   callee_method_idx,
-                                                   is_virtual);
-
-    EmitGuard_ExceptionLandingPad(dex_pc);
   }
 
 #if 0
diff --git a/src/compiler_llvm/runtime_support_func_list.h b/src/compiler_llvm/runtime_support_func_list.h
index 2f3a6fa..7a51b90 100644
--- a/src/compiler_llvm/runtime_support_func_list.h
+++ b/src/compiler_llvm/runtime_support_func_list.h
@@ -62,7 +62,6 @@
   V(IsExceptionPending, art_is_exception_pending_from_code) \
   V(FindCatchBlock, art_find_catch_block_from_code) \
   V(MarkGCCard, art_mark_gc_card_from_code) \
-  V(EnsureResolved, art_ensure_resolved_from_code) \
   V(FixStub, art_fix_stub_from_code) \
   V(ProxyInvokeHandler, art_proxy_invoke_handler_from_code) \
   V(DecodeJObjectInThread, art_decode_jobject_in_thread) \
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index ad8fded..fce0f41 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -585,83 +585,15 @@
   }
 }
 
-// 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.
+// TODO: This runtime support function is the temporary solution for the link issue.
 // 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.
+// 1. The code address is 0.                       -> Link the code by ELFLoader
+// That 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);
+  // 1. The code address is 0.                       -> Link the code by ELFLoader
+  if (UNLIKELY(code == NULL)) {
+    Runtime::Current()->GetClassLinker()->LinkOatCodeFor(called);
     return called->GetCode();
   }
 
diff --git a/src/nth_caller_visitor.h b/src/nth_caller_visitor.h
index 07b9e49..84d2b3b 100644
--- a/src/nth_caller_visitor.h
+++ b/src/nth_caller_visitor.h
@@ -24,17 +24,19 @@
 
 // Walks up the stack 'n' callers, when used with Thread::WalkStack.
 struct NthCallerVisitor : public Thread::StackVisitor {
-  NthCallerVisitor(size_t n) : n(n), count(0), caller(NULL) {}
-  bool VisitFrame(const Frame& f, uintptr_t) {
+  NthCallerVisitor(size_t n) : n(n), count(0), pc(0), caller(NULL) {}
+  bool VisitFrame(const Frame& f, uintptr_t fpc) {
     DCHECK(caller == NULL);
     if (count++ == n) {
       caller = f.GetMethod();
+      pc = fpc;
       return false;
     }
     return true;
   }
   size_t n;
   size_t count;
+  uintptr_t pc;
   Method* caller;
 };
 
diff --git a/src/oat/runtime/support_stubs.cc b/src/oat/runtime/support_stubs.cc
index fb0b5a4..ac5d6f9 100644
--- a/src/oat/runtime/support_stubs.cc
+++ b/src/oat/runtime/support_stubs.cc
@@ -14,16 +14,22 @@
  * limitations under the License.
  */
 
+#if !defined(ART_USE_LLVM_COMPILER)
 #include "callee_save_frame.h"
+#endif
 #include "dex_instruction.h"
 #include "object.h"
 #include "object_utils.h"
+#if defined(ART_USE_LLVM_COMPILER)
+#include "nth_caller_visitor.h"
+#endif
 
 // Architecture specific assembler helper to deliver exception.
 extern "C" void art_deliver_exception_from_code(void*);
 
 namespace art {
 
+#if !defined(ART_USE_LLVM_COMPILER)
 // Lazily resolve a method. Called by stub code.
 const void* UnresolvedDirectMethodTrampolineFromCode(Method* called, Method** sp, Thread* thread,
                                                      Runtime::TrampolineType type) {
@@ -206,7 +212,96 @@
   }
   return code;
 }
+#else // ART_USE_LLVM_COMPILER
+const void* UnresolvedDirectMethodTrampolineFromCode(Method* called, Method** called_addr,
+                                                     Thread* thread, Runtime::TrampolineType type) {
+  NthCallerVisitor visitor(0);
+  thread->WalkStack(&visitor);
+  Method* caller = visitor.caller;
 
+  ClassLinker* linker = Runtime::Current()->GetClassLinker();
+  bool is_static;
+  bool is_virtual;
+  uint32_t dex_method_idx;
+  if (type == Runtime::kUnknownMethod) {
+    DCHECK(called->IsRuntimeMethod());
+    // less two as return address may span into next dex instruction
+    uint32_t dex_pc = static_cast<uint32_t>(visitor.pc);
+    const DexFile::CodeItem* code = MethodHelper(caller).GetCodeItem();
+    CHECK_LT(dex_pc, code->insns_size_in_code_units_);
+    const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
+    Instruction::Code instr_code = instr->Opcode();
+    is_static = (instr_code == Instruction::INVOKE_STATIC) ||
+                (instr_code == Instruction::INVOKE_STATIC_RANGE);
+    is_virtual = (instr_code == Instruction::INVOKE_VIRTUAL) ||
+                 (instr_code == Instruction::INVOKE_VIRTUAL_RANGE) ||
+                 (instr_code == Instruction::INVOKE_SUPER) ||
+                 (instr_code == Instruction::INVOKE_SUPER_RANGE);
+    DCHECK(is_static || is_virtual || (instr_code == Instruction::INVOKE_DIRECT) ||
+           (instr_code == Instruction::INVOKE_DIRECT_RANGE));
+    DecodedInstruction dec_insn(instr);
+    dex_method_idx = dec_insn.vB;
+  } else {
+    DCHECK(!called->IsRuntimeMethod());
+    is_static = type == Runtime::kStaticMethod;
+    is_virtual = false;
+    dex_method_idx = called->GetDexMethodIndex();
+  }
+  if (type == Runtime::kUnknownMethod) {
+    called = linker->ResolveMethod(dex_method_idx, caller, !is_virtual);
+  }
+  const void* code = NULL;
+  if (LIKELY(!thread->IsExceptionPending())) {
+    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);
+      if (LIKELY(called_class->IsInitialized())) {
+        code = called->GetCode();
+        // TODO: remove this after we solve the link issue.
+        { // for lazy link.
+          if (code == NULL) {
+            code = linker->GetOatCodeFor(called);
+          }
+        }
+      } else if (called_class->IsInitializing()) {
+        if (is_static) {
+          // Class is still initializing, go to oat and grab code (trampoline must be left in place
+          // until class is initialized to stop races between threads).
+          code = linker->GetOatCodeFor(called);
+        } else {
+          // No trampoline for non-static methods.
+          code = called->GetCode();
+          // TODO: remove this after we solve the link issue.
+          { // for lazy link.
+            if (code == NULL) {
+              code = linker->GetOatCodeFor(called);
+            }
+          }
+        }
+      } else {
+        DCHECK(called_class->IsErroneous());
+      }
+    } else {
+      // Direct method has been made virtual
+      thread->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
+                                 "Expected direct method but found virtual: %s",
+                                 PrettyMethod(called, true).c_str());
+    }
+  }
+  if (LIKELY(code != NULL)) {
+    // Expect class to at least be initializing.
+    DCHECK(called->GetDeclaringClass()->IsInitializing());
+    // Don't want infinite recursion.
+    DCHECK(code != Runtime::Current()->GetResolutionStubArray(Runtime::kUnknownMethod)->GetData());
+    // Set up entry into main method
+    *called_addr = called;
+  }
+  return code;
+}
+#endif // ART_USE_LLVM_COMPILER
+
+#if !defined(ART_USE_LLVM_COMPILER)
 // Called by the AbstractMethodError. Called by stub code.
 extern void ThrowAbstractMethodErrorFromCode(Method* method, Thread* thread, Method** sp) {
   FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
@@ -214,5 +309,11 @@
                              "abstract method \"%s\"", PrettyMethod(method).c_str());
   thread->DeliverException();
 }
+#else // ART_USE_LLVM_COMPILER
+extern void ThrowAbstractMethodErrorFromCode(Method* method, Thread* thread, Method**) {
+  thread->ThrowNewExceptionF("Ljava/lang/AbstractMethodError;",
+                             "abstract method \"%s\"", PrettyMethod(method).c_str());
+}
+#endif // ART_USE_LLVM_COMPILER
 
 }  // namespace art
diff --git a/src/oat/runtime/x86/stub_x86.cc b/src/oat/runtime/x86/stub_x86.cc
index 1dea0a1..0371a1e 100644
--- a/src/oat/runtime/x86/stub_x86.cc
+++ b/src/oat/runtime/x86/stub_x86.cc
@@ -28,6 +28,7 @@
 ByteArray* X86CreateResolutionTrampoline(Runtime::TrampolineType type) {
   UniquePtr<X86Assembler> assembler(static_cast<X86Assembler*>(Assembler::Create(kX86)));
 
+#if !defined(ART_USE_LLVM_COMPILER)
   // Set up the callee save frame to conform with Runtime::CreateCalleeSaveMethod(kRefsAndArgs)
   // return address
   __ pushl(EDI);
@@ -59,6 +60,32 @@
   __ xchgl(EDI, Address(ESP,0));
   // Tail call to intended method.
   __ ret();
+#else // ART_USE_LLVM_COMPILER
+  __ pushl(EBP);
+  __ movl(EBP, ESP);          // save ESP
+  __ movl(EAX, Address(EBP,8));  // Method* called
+  __ leal(EDX, Address(EBP,8));  // Method** called_addr
+  __ pushl(Immediate(type));  // pass is_static
+  __ fs()->pushl(Address::Absolute(Thread::SelfOffset()));  // pass thread
+  __ pushl(EDX);  // pass called_addr
+  __ pushl(EAX);  // pass called
+
+  // Call to resolve method.
+  __ Call(ThreadOffset(ENTRYPOINT_OFFSET(pUnresolvedDirectMethodTrampolineFromCode)),
+          X86ManagedRegister::FromCpuRegister(ECX));
+
+  __ leave();
+
+  Label resolve_fail;  // forward declaration
+  __ cmpl(EAX, Immediate(0));
+  __ j(kEqual, &resolve_fail);
+
+  __ jmp(EAX);
+  // Tail call to intended method.
+
+  __ Bind(&resolve_fail);
+  __ ret();
+#endif // ART_USE_LLVM_COMPILER
 
   assembler->EmitSlowPaths();
   size_t cs = assembler->CodeSize();
@@ -75,6 +102,7 @@
 ByteArray* CreateAbstractMethodErrorStub() {
   UniquePtr<X86Assembler> assembler(static_cast<X86Assembler*>(Assembler::Create(kX86)));
 
+#if !defined(ART_USE_LLVM_COMPILER)
   // Set up the callee save frame to conform with Runtime::CreateCalleeSaveMethod(kSaveAll)
 
   // return address
@@ -95,18 +123,21 @@
   __ Call(ThreadOffset(ENTRYPOINT_OFFSET(pThrowAbstractMethodErrorFromCode)),
           X86ManagedRegister::FromCpuRegister(ECX));
 
-#if defined(ART_USE_LLVM_COMPILER)
-  // Return to caller who will handle pending exception.
-  // TODO: The callee save set up is unnecessary for LLVM as it uses shadow stacks.
-  __ addl(ESP, Immediate(32));
-  __ popl(EBP);
-  __ popl(ESI);
-  __ popl(EDI);
-  __ ret();
-#else
   // Call never returns.
   __ int3();
-#endif
+#else // ART_USE_LLVM_COMPILER
+  __ pushl(EBP);
+  __ movl(EBP, ESP);          // save ESP
+  __ pushl(ESP);  // pass sp (not use)
+  __ fs()->pushl(Address::Absolute(Thread::SelfOffset()));  // pass thread*
+  __ pushl(Address(EBP,8));  // pass method
+  // Call to throw AbstractMethodError.
+  __ Call(ThreadOffset(ENTRYPOINT_OFFSET(pThrowAbstractMethodErrorFromCode)),
+          X86ManagedRegister::FromCpuRegister(ECX));
+  __ leave();
+  // Return to caller who will handle pending exception.
+  __ ret();
+#endif // ART_USE_LLVM_COMPILER
 
   assembler->EmitSlowPaths();
 
diff --git a/src/object.cc b/src/object.cc
index 5413194..d91e70c 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -549,16 +549,20 @@
   self->PushNativeToManagedRecord(&record);
 #endif
 
-#if defined(ART_USE_LLVM_COMPILER)
-  art_fix_stub_from_code(const_cast<Method*>(this));
-#endif
-
   // Call the invoke stub associated with the method.
   // Pass everything as arguments.
   const Method::InvokeStub* stub = GetInvokeStub();
 
   bool have_executable_code = (GetCode() != NULL);
 
+#if defined(ART_USE_LLVM_COMPILER)
+  if (stub == NULL || !have_executable_code) {
+    Runtime::Current()->GetClassLinker()->LinkOatCodeFor(const_cast<Method*>(this));
+    stub = GetInvokeStub();
+    have_executable_code = (GetCode() != NULL);
+  }
+#endif
+
   if (Runtime::Current()->IsStarted() && have_executable_code && stub != NULL) {
     bool log = false;
     if (log) {