Refactor the temporary solution of the stubs.

Also, fix test 032 and 088.

Change-Id: I84049356b29ca6d9a5c852c926190de76b285780
diff --git a/src/compiler_llvm/art_module.ll b/src/compiler_llvm/art_module.ll
index 434aa7b..74616d1 100644
--- a/src/compiler_llvm/art_module.ll
+++ b/src/compiler_llvm/art_module.ll
@@ -142,12 +142,9 @@
 declare void @art_check_cast_from_code(%JavaObject*, %JavaObject*)
 declare void @art_check_put_array_element_from_code(%JavaObject*, %JavaObject*)
 
-declare void @art_ensure_link_from_code(%JavaObject*)
-
 declare %JavaObject* @art_ensure_resolved_from_code(%JavaObject*,
                                                     %JavaObject*,
                                                     i32,
-                                                    i32)
+                                                    i1)
 
-declare %JavaObject* @art_ensure_initialized_from_code(%JavaObject*,
-                                                       %JavaObject*)
+declare %JavaObject* @art_fix_stub_from_code(%JavaObject*)
diff --git a/src/compiler_llvm/generated/art_module.cc b/src/compiler_llvm/generated/art_module.cc
index 52048eb..6676e02 100644
--- a/src/compiler_llvm/generated/art_module.cc
+++ b/src/compiler_llvm/generated/art_module.cc
@@ -268,12 +268,19 @@
 FuncTy_28_args.push_back(PointerTy_1);
 FuncTy_28_args.push_back(PointerTy_1);
 FuncTy_28_args.push_back(IntegerType::get(mod->getContext(), 32));
-FuncTy_28_args.push_back(IntegerType::get(mod->getContext(), 32));
+FuncTy_28_args.push_back(IntegerType::get(mod->getContext(), 1));
 FunctionType* FuncTy_28 = FunctionType::get(
  /*Result=*/PointerTy_1,
  /*Params=*/FuncTy_28_args,
  /*isVarArg=*/false);
 
+std::vector<Type*>FuncTy_29_args;
+FuncTy_29_args.push_back(PointerTy_1);
+FunctionType* FuncTy_29 = FunctionType::get(
+ /*Result=*/PointerTy_1,
+ /*Params=*/FuncTy_29_args,
+ /*isVarArg=*/false);
+
 
 // Function Declarations
 
@@ -794,17 +801,6 @@
 AttrListPtr func_art_check_put_array_element_from_code_PAL;
 func_art_check_put_array_element_from_code->setAttributes(func_art_check_put_array_element_from_code_PAL);
 
-Function* func_art_ensure_link_from_code = mod->getFunction("art_ensure_link_from_code");
-if (!func_art_ensure_link_from_code) {
-func_art_ensure_link_from_code = Function::Create(
- /*Type=*/FuncTy_4,
- /*Linkage=*/GlobalValue::ExternalLinkage,
- /*Name=*/"art_ensure_link_from_code", mod); // (external, no body)
-func_art_ensure_link_from_code->setCallingConv(CallingConv::C);
-}
-AttrListPtr func_art_ensure_link_from_code_PAL;
-func_art_ensure_link_from_code->setAttributes(func_art_ensure_link_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(
@@ -816,16 +812,16 @@
 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_ensure_initialized_from_code = mod->getFunction("art_ensure_initialized_from_code");
-if (!func_art_ensure_initialized_from_code) {
-func_art_ensure_initialized_from_code = Function::Create(
- /*Type=*/FuncTy_25,
+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_29,
  /*Linkage=*/GlobalValue::ExternalLinkage,
- /*Name=*/"art_ensure_initialized_from_code", mod); // (external, no body)
-func_art_ensure_initialized_from_code->setCallingConv(CallingConv::C);
+ /*Name=*/"art_fix_stub_from_code", mod); // (external, no body)
+func_art_fix_stub_from_code->setCallingConv(CallingConv::C);
 }
-AttrListPtr func_art_ensure_initialized_from_code_PAL;
-func_art_ensure_initialized_from_code->setAttributes(func_art_ensure_initialized_from_code_PAL);
+AttrListPtr func_art_fix_stub_from_code_PAL;
+func_art_fix_stub_from_code->setAttributes(func_art_fix_stub_from_code_PAL);
 
 // Global Variable Declarations
 
diff --git a/src/compiler_llvm/jni_compiler.cc b/src/compiler_llvm/jni_compiler.cc
index e0a5704..492ad25 100644
--- a/src/compiler_llvm/jni_compiler.cc
+++ b/src/compiler_llvm/jni_compiler.cc
@@ -39,6 +39,7 @@
 namespace art {
 namespace compiler_llvm {
 
+using namespace runtime_support;
 
 JniCompiler::JniCompiler(CompilationUnit* cunit,
                          Compiler const& compiler,
@@ -106,8 +107,7 @@
   }
 
   // Get thread object
-  llvm::Value* thread_object_addr =
-    irb_.CreateCall(irb_.GetRuntime(runtime_support::GetCurrentThread));
+  llvm::Value* thread_object_addr = irb_.CreateCall(irb_.GetRuntime(GetCurrentThread));
 
   // Shadow stack
   llvm::StructType* shadow_frame_type = irb_.getShadowFrameTy(sirt_size);
@@ -132,7 +132,7 @@
 
   // Push the shadow frame
   llvm::Value* shadow_frame_upcast = irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
-  irb_.CreateCall(irb_.GetRuntime(runtime_support::PushShadowFrame), shadow_frame_upcast);
+  irb_.CreateCall(irb_.GetRuntime(PushShadowFrame), shadow_frame_upcast);
 
   // Get JNIEnv
   llvm::Value* jni_env_object_addr = LoadFromObjectOffset(thread_object_addr,
@@ -145,20 +145,10 @@
                       irb_.getInt32(kNative));
 
   // Get callee code_addr
-  llvm::Value* code_addr_ =
+  llvm::Value* code_addr =
       LoadFromObjectOffset(method_object_addr,
                            Method::NativeMethodOffset().Int32Value(),
                            GetFunctionType(method_idx_, is_static, true)->getPointerTo());
-  llvm::Value* code_addr;
-  llvm::FunctionType* method_type = GetFunctionType(method_idx_, is_static, true);
-
-  // TODO: Inline check
-  llvm::Value* runtime_func = irb_.GetRuntime(runtime_support::EnsureInitialized);
-  llvm::Value* result = irb_.CreateCall2(runtime_func,
-                                         method_object_addr,
-                                         irb_.CreatePointerCast(code_addr_,
-                                                                irb_.getJObjectTy()));
-  code_addr = irb_.CreatePointerCast(result, method_type->getPointerTo());
 
   // Load actual parameters
   std::vector<llvm::Value*> args;
@@ -204,11 +194,10 @@
   // Acquire lock for synchronized methods.
   if (is_synchronized) {
     // Acquire lock
-    irb_.CreateCall(irb_.GetRuntime(runtime_support::LockObject), this_object_or_class_object);
+    irb_.CreateCall(irb_.GetRuntime(LockObject), this_object_or_class_object);
 
     // Check exception pending
-    llvm::Value* exception_pending =
-        irb_.CreateCall(irb_.GetRuntime(runtime_support::IsExceptionPending));
+    llvm::Value* exception_pending = irb_.CreateCall(irb_.GetRuntime(IsExceptionPending));
 
     // Create two basic block for branch
     llvm::BasicBlock* block_cont = llvm::BasicBlock::Create(*context_, "B.cont", func_);
@@ -222,7 +211,7 @@
     irb_.SetInsertPoint(block_exception_);
     // TODO: Set thread state?
     // Pop the shadow frame
-    irb_.CreateCall(irb_.GetRuntime(runtime_support::PopShadowFrame));
+    irb_.CreateCall(irb_.GetRuntime(PopShadowFrame));
     // Unwind
     if (return_shorty != 'V') {
       irb_.CreateRet(irb_.getJZero(return_shorty));
@@ -256,7 +245,7 @@
 
   // Release lock for synchronized methods.
   if (is_synchronized) {
-    irb_.CreateCall(irb_.GetRuntime(runtime_support::UnlockObject), this_object_or_class_object);
+    irb_.CreateCall(irb_.GetRuntime(UnlockObject), this_object_or_class_object);
   }
 
   // Set thread state to kRunnable
@@ -266,7 +255,7 @@
 
   if (return_shorty == 'L') {
     // If the return value is reference, it may point to SIRT, we should decode it.
-    retval = irb_.CreateCall2(irb_.GetRuntime(runtime_support::DecodeJObjectInThread),
+    retval = irb_.CreateCall2(irb_.GetRuntime(DecodeJObjectInThread),
                               thread_object_addr,
                               retval);
   }
@@ -286,7 +275,7 @@
                       saved_local_ref_cookie);
 
   // Pop the shadow frame
-  irb_.CreateCall(irb_.GetRuntime(runtime_support::PopShadowFrame));
+  irb_.CreateCall(irb_.GetRuntime(PopShadowFrame));
 
   // Return!
   if (return_shorty != 'V') {
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 615e600..5485ba6 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -2782,38 +2782,27 @@
     << PrettyMethod(callee_method_idx, *dex_file_);
 }
 
-llvm::Value* MethodCompiler::EmitEnsureInitialized(llvm::Value* callee_method_object_addr,
-                                                   uint32_t method_idx,
-                                                   bool is_static,
-                                                   llvm::Value* code_addr) {
-  llvm::FunctionType* method_type = GetFunctionType(method_idx, is_static);
-
-  // TODO: Inline check
-  llvm::Value* runtime_func = irb_.GetRuntime(EnsureInitialized);
-  llvm::Value* result = irb_.CreateCall2(runtime_func,
-                                         callee_method_object_addr,
-                                         irb_.CreatePointerCast(code_addr,
-                                                                irb_.getJObjectTy()));
-  return irb_.CreatePointerCast(result, method_type->getPointerTo());
-}
-
 llvm::Value* MethodCompiler::EmitEnsureResolved(llvm::Value* callee,
                                                 llvm::Value* caller,
                                                 uint32_t dex_method_idx,
-                                                Instruction::Code instr_code) {
-  // TODO: Inline check
-  llvm::Value* runtime_func = irb_.GetRuntime(EnsureResolved);
-  return irb_.CreateCall4(runtime_func,
-                          callee,
-                          caller,
-                          irb_.getInt32(dex_method_idx),
-                          irb_.getInt32(instr_code));
+                                                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));
 }
 
-void MethodCompiler::EmitEnsureLink(llvm::Value* method_object_addr) {
-  // TODO: Inline check
-  llvm::Value* runtime_func = irb_.GetRuntime(EnsureLink);
-  irb_.CreateCall(runtime_func, method_object_addr);
+llvm::Value* MethodCompiler::EmitFixStub(llvm::Value* callee_method_object_addr,
+                                         uint32_t method_idx,
+                                         bool is_static) {
+  // TODO: Remove this after we solve the link and trampoline related problems.
+  llvm::Value* code_addr =  irb_.CreateCall(irb_.GetRuntime(FixStub), callee_method_object_addr);
+
+  llvm::FunctionType* method_type = GetFunctionType(method_idx, is_static);
+
+  return irb_.CreatePointerCast(code_addr, method_type->getPointerTo());
 }
 
 void MethodCompiler::EmitInsn_InvokeVirtualSuperSlow(uint32_t dex_pc,
@@ -2842,28 +2831,23 @@
 
   EmitUpdateLineNumFromDexPC(dex_pc);
 
-  llvm::Value* callee_method_object_addr_ =
+  llvm::Value* callee_method_object_addr =
       irb_.CreateCall3(runtime_func,
                        callee_method_idx_value, this_addr, method_object_addr);
 
   EmitGuard_ExceptionLandingPad(dex_pc);
 
-  llvm::Value* callee_method_object_addr = EmitEnsureResolved(callee_method_object_addr_,
-                                                              method_object_addr,
-                                                              callee_method_idx,
-                                                              (is_virtual ?
-                                                               Instruction::INVOKE_VIRTUAL :
-                                                               Instruction::INVOKE_SUPER));
-
-  EmitEnsureLink(callee_method_object_addr);
-
-  llvm::Value* code_addr_ =
+#if 0
+  llvm::Value* code_addr =
       EmitLoadCodeAddr(callee_method_object_addr, callee_method_idx, false);
+#else
+  // TODO: Remove this after we solve the link and trampoline related problems.
+  llvm::Value* code_addr = EmitFixStub(callee_method_object_addr,
+                                       callee_method_idx,
+                                       false);
+  EmitGuard_ExceptionLandingPad(dex_pc);
+#endif
 
-  llvm::Value* code_addr = EmitEnsureInitialized(callee_method_object_addr,
-                                                 callee_method_idx,
-                                                 false,
-                                                 code_addr_);
   // Load the actual parameter
   std::vector<llvm::Value*> args;
   args.push_back(callee_method_object_addr);
@@ -2908,25 +2892,26 @@
     // Load callee method code address (branch destination)
     llvm::Value* vtable_addr = EmitLoadVTableAddr(class_object_addr);
 
-    llvm::Value* method_object_addr_ =
+    llvm::Value* method_object_addr =
       EmitLoadMethodObjectAddrFromVTable(vtable_addr,
                                          callee_method->GetMethodIndex());
 
-    llvm::Value* method_object_addr = EmitEnsureResolved(method_object_addr_,
-                                                         EmitLoadMethodObjectAddr(),
-                                                         callee_method_idx,
-                                                         Instruction::INVOKE_VIRTUAL);
+#if 0
+    llvm::Value* code_addr =
+        EmitLoadCodeAddr(method_object_addr, callee_method_idx, false);
+#else
+    // TODO: Remove this after we solve the link and trampoline related problems.
+    method_object_addr = EmitEnsureResolved(method_object_addr,
+                                            EmitLoadMethodObjectAddr(),
+                                            callee_method_idx,
+                                            true);
+    EmitGuard_ExceptionLandingPad(dex_pc);
 
-    EmitEnsureLink(method_object_addr);
-
-    llvm::Value* code_addr_ =
-      EmitLoadCodeAddr(method_object_addr, callee_method_idx, false);
-
-    llvm::Value* code_addr = EmitEnsureInitialized(method_object_addr,
-                                                   callee_method_idx,
-                                                   false,
-                                                   code_addr_);
-
+    llvm::Value* code_addr = EmitFixStub(method_object_addr,
+                                         callee_method_idx,
+                                         false);
+    EmitGuard_ExceptionLandingPad(dex_pc);
+#endif
     // Load actual parameters
     std::vector<llvm::Value*> args;
     args.push_back(method_object_addr);
@@ -3009,25 +2994,26 @@
     // Load method object from virtual table
     llvm::Value* vtable_addr = EmitLoadVTableAddr(super_class_addr);
 
-    llvm::Value* callee_method_object_addr_ =
+    llvm::Value* callee_method_object_addr =
       EmitLoadMethodObjectAddrFromVTable(vtable_addr,
                                          callee_method->GetMethodIndex());
 
-    llvm::Value* callee_method_object_addr = EmitEnsureResolved(callee_method_object_addr_,
-                                                                method_object_addr,
-                                                                callee_method_idx,
-                                                                Instruction::INVOKE_SUPER);
-
-    EmitEnsureLink(callee_method_object_addr);
-
-    llvm::Value* code_addr_ =
-      EmitLoadCodeAddr(callee_method_object_addr,
-                       callee_method_idx, false);
-
-    llvm::Value* code_addr = EmitEnsureInitialized(callee_method_object_addr,
+#if 0
+    llvm::Value* code_addr =
+        EmitLoadCodeAddr(callee_method_object_addr, callee_method_idx, false);
+#else
+    // TODO: Remove this after we solve the link and trampoline related problems.
+    callee_method_object_addr = EmitEnsureResolved(callee_method_object_addr,
+                                                   method_object_addr,
                                                    callee_method_idx,
-                                                   false,
-                                                   code_addr_);
+                                                   true);
+    EmitGuard_ExceptionLandingPad(dex_pc);
+
+    llvm::Value* code_addr = EmitFixStub(callee_method_object_addr,
+                                         callee_method_idx,
+                                         false);
+    EmitGuard_ExceptionLandingPad(dex_pc);
+#endif
 
     // Load actual parameters
     std::vector<llvm::Value*> args;
@@ -3087,24 +3073,26 @@
   llvm::Value* callee_method_object_field_addr =
     EmitLoadDexCacheResolvedMethodFieldAddr(callee_method_idx);
 
-  llvm::Value* callee_method_object_addr_ =
+  llvm::Value* callee_method_object_addr =
     irb_.CreateLoad(callee_method_object_field_addr);
 
-  llvm::Value* callee_method_object_addr = EmitEnsureResolved(callee_method_object_addr_,
-                                                              EmitLoadMethodObjectAddr(),
-                                                              callee_method_idx,
-                                                              Instruction::INVOKE_DIRECT);
+#if 0
+    llvm::Value* code_addr =
+        EmitLoadCodeAddr(callee_method_object_addr, callee_method_idx, is_static);
+#else
+    // TODO: Remove this after we solve the link and trampoline related problems.
+    callee_method_object_addr = EmitEnsureResolved(callee_method_object_addr,
+                                                   EmitLoadMethodObjectAddr(),
+                                                   callee_method_idx,
+                                                   false);
+    EmitGuard_ExceptionLandingPad(dex_pc);
 
-  EmitEnsureLink(callee_method_object_addr);
-
-  llvm::Value* code_addr_ =
-    EmitLoadCodeAddr(callee_method_object_addr, callee_method_idx, is_static);
-
-  llvm::Value* code_addr = EmitEnsureInitialized(callee_method_object_addr,
-                                                 callee_method_idx,
-                                                 is_static,
-                                                 code_addr_);
-  EmitGuard_ExceptionLandingPad(dex_pc);
+    llvm::Value* code_addr = EmitFixStub(callee_method_object_addr,
+                                         callee_method_idx,
+                                         is_static);
+    EmitGuard_ExceptionLandingPad(dex_pc);
+    // FixStub may resolve method, so we need to reload method.
+#endif
 
   // Load the actual parameter
   std::vector<llvm::Value*> args;
@@ -3156,26 +3144,22 @@
 
   EmitUpdateLineNumFromDexPC(dex_pc);
 
-  llvm::Value* callee_method_object_addr_ =
+  llvm::Value* callee_method_object_addr =
     irb_.CreateCall3(runtime_func,
                      callee_method_idx_value, this_addr, method_object_addr);
 
   EmitGuard_ExceptionLandingPad(dex_pc);
 
-  llvm::Value* callee_method_object_addr = EmitEnsureResolved(callee_method_object_addr_,
-                                                              method_object_addr,
-                                                              callee_method_idx,
-                                                              Instruction::INVOKE_INTERFACE);
-
-  EmitEnsureLink(callee_method_object_addr);
-
-  llvm::Value* code_addr_ =
+#if 0
+  llvm::Value* code_addr =
     EmitLoadCodeAddr(callee_method_object_addr, callee_method_idx, false);
-
-  llvm::Value* code_addr = EmitEnsureInitialized(callee_method_object_addr,
-                                                 callee_method_idx,
-                                                 false,
-                                                 code_addr_);
+#else
+  // TODO: Remove this after we solve the link and trampoline related problems.
+  llvm::Value* code_addr = EmitFixStub(callee_method_object_addr,
+                                       callee_method_idx,
+                                       false);
+  EmitGuard_ExceptionLandingPad(dex_pc);
+#endif
 
   // Load the actual parameter
   std::vector<llvm::Value*> args;
diff --git a/src/compiler_llvm/method_compiler.h b/src/compiler_llvm/method_compiler.h
index e5be3ba..48d4467 100644
--- a/src/compiler_llvm/method_compiler.h
+++ b/src/compiler_llvm/method_compiler.h
@@ -194,15 +194,13 @@
   void EmitInsn_SPut(GEN_INSN_ARGS, JType field_jty);
 
   // INVOKE instructions
-  llvm::Value* EmitEnsureInitialized(llvm::Value* callee_method_object_addr,
-                                     uint32_t method_idx,
-                                     bool is_static,
-                                     llvm::Value* code_addr);
+  llvm::Value* EmitFixStub(llvm::Value* callee_method_object_addr,
+                           uint32_t method_idx,
+                           bool is_static);
   llvm::Value* EmitEnsureResolved(llvm::Value* callee,
                                   llvm::Value* caller,
                                   uint32_t dex_method_idx,
-                                  Instruction::Code instr_code);
-  void EmitEnsureLink(llvm::Value*);
+                                  bool is_virtual);
 
   void EmitInsn_InvokeVirtual(GEN_INSN_ARGS, bool is_range);
   void EmitInsn_InvokeSuper(GEN_INSN_ARGS, bool is_range);
diff --git a/src/compiler_llvm/runtime_support_func_list.h b/src/compiler_llvm/runtime_support_func_list.h
index 2f1fb13..56755fa 100644
--- a/src/compiler_llvm/runtime_support_func_list.h
+++ b/src/compiler_llvm/runtime_support_func_list.h
@@ -57,7 +57,6 @@
   V(InitializeStaticStorage, art_initialize_static_storage_from_code) \
   V(IsExceptionPending, art_is_exception_pending_from_code) \
   V(FindCatchBlock, art_find_catch_block_from_code) \
-  V(EnsureInitialized, art_ensure_initialized_from_code) \
-  V(EnsureLink, art_ensure_link_from_code) \
   V(EnsureResolved, art_ensure_resolved_from_code) \
+  V(FixStub, art_fix_stub_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 e7e2d86..79d06df 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -521,92 +521,87 @@
   }
 }
 
-const void* art_ensure_initialized_from_code(Method* called,
-                                             void* code) {
-  if (LIKELY(code != Runtime::Current()->GetResolutionStubArray(Runtime::kStaticMethod)->GetData())) {
-    return code;
-  }
-  ClassLinker* linker = Runtime::Current()->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(called_class->IsErroneous());
-    return code;
-  }
-}
-
+// 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,
-                                      Instruction::Code instr_code) {
+                                      bool is_virtual) {
   if (LIKELY(!called->IsResolutionMethod())) {
     return called;
   }
-  // Compute details about the called method (avoid GCs)
+
+  // If the called method is ResolutionMethod.  -> ResolutionTrampoline(kUnknownMethod)
+  //                                               Resolve method.
   ClassLinker* linker = Runtime::Current()->GetClassLinker();
-  bool is_static = (instr_code == Instruction::INVOKE_STATIC) ||
-                   (instr_code == Instruction::INVOKE_STATIC_RANGE);
-
-  bool 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));
-
   called = linker->ResolveMethod(dex_method_idx, caller, !is_virtual);
+  if (UNLIKELY(Thread::Current()->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 {
+    // Direct method has been made virtual
+    Thread::Current()->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
+                                          "Expected direct method but found virtual: %s",
+                                          PrettyMethod(called, true).c_str());
+    return NULL;
+  }
+}
 
-  const void* code = NULL;
-  Thread* thread = art_get_current_thread_from_code();
-  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();
-      } 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);
-          LOG(FATAL) << "Is static";
-        } else {
-          // No trampoline for non-static methods.
-          code = called->GetCode();
-        }
-      } else {
-        DCHECK(called_class->IsErroneous());
-        LOG(FATAL) << "Is erroneous";
-      }
+
+// 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) {
+  if (UNLIKELY(called->IsResolutionMethod())) {
+    LOG(FATAL) << "is ResolutionMethod!!";
+  }
+  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 {
-      // Direct method has been made virtual
-      thread->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
-                                 "Expected direct method but found virtual: %s",
-                                 PrettyMethod(called, true).c_str());
+      DCHECK(Thread::Current()->IsExceptionPending());
+      DCHECK(called_class->IsErroneous());
+      return NULL;
     }
   }
 
-  if (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());
+  // 2. The code address is AbstractMethodErrorStub. -> AbstractMethodErrorStub
+  if (UNLIKELY(code == runtime->GetAbstractMethodErrorStubArray()->GetData())) {
+    Thread::Current()->ThrowNewExceptionF("Ljava/lang/AbstractMethodError;",
+                                          "abstract method \"%s\"", PrettyMethod(called).c_str());
+    return NULL;
   }
 
-  return called;
-}
-
-void art_ensure_link_from_code(Method* method) {
-  if (method->GetInvokeStub() == NULL || method->GetCode() == NULL) {
-    Runtime::Current()->GetClassLinker()->LinkOatCodeFor(method);
+  // 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;
 }
 
 void* art_find_runtime_support_func(void* context, char const* name) {
diff --git a/src/compiler_llvm/runtime_support_llvm.h b/src/compiler_llvm/runtime_support_llvm.h
index 1dbd71d..ab5c804 100644
--- a/src/compiler_llvm/runtime_support_llvm.h
+++ b/src/compiler_llvm/runtime_support_llvm.h
@@ -62,7 +62,7 @@
 
 void* art_find_runtime_support_func(void* context, char const* name);
 
-void art_ensure_link_from_code(Method* method);
+const void* art_fix_stub_from_code(Method* called);
 
 }  // namespace art
 
diff --git a/src/compiler_llvm/upcall_compiler.cc b/src/compiler_llvm/upcall_compiler.cc
index 6d14a19..691d7e5 100644
--- a/src/compiler_llvm/upcall_compiler.cc
+++ b/src/compiler_llvm/upcall_compiler.cc
@@ -144,6 +144,8 @@
   }
 
   // Invoke managed method now!
+  // TODO: If we solve the trampoline related problems, we can just get the code address and call.
+#if 0
   llvm::Value* code_field_offset_value =
     irb_.getPtrEquivInt(Method::GetCodeOffset().Int32Value());
 
@@ -151,15 +153,20 @@
     irb_.CreatePtrDisp(method_object_addr, code_field_offset_value,
                        accurate_func_type->getPointerTo()->getPointerTo());
 
-  llvm::Value* code_addr_ = irb_.CreateLoad(code_field_addr);
-  llvm::Value* code_addr;
-  // TODO: Inline check
-  llvm::Value* runtime_func = irb_.GetRuntime(runtime_support::EnsureInitialized);
-  llvm::Value* result = irb_.CreateCall2(runtime_func,
-                                         method_object_addr,
-                                         irb_.CreatePointerCast(code_addr_,
-                                                                irb_.getJObjectTy()));
-  code_addr = irb_.CreatePointerCast(result, accurate_func_type->getPointerTo());
+  llvm::Value* code_addr = irb_.CreateLoad(code_field_addr);
+#else
+  llvm::Value* result = irb_.CreateCall(irb_.GetRuntime(FixStub), method_object_addr);
+  llvm::Value* code_addr = irb_.CreatePointerCast(result, accurate_func_type->getPointerTo());
+
+  // Exception unwind.
+  llvm::Value* exception_pending = irb_.CreateCall(irb_.GetRuntime(IsExceptionPending));
+  llvm::BasicBlock* block_unwind = llvm::BasicBlock::Create(*context_, "exception_unwind", func);
+  llvm::BasicBlock* block_cont = llvm::BasicBlock::Create(*context_, "cont", func);
+  irb_.CreateCondBr(exception_pending, block_unwind, block_cont);
+  irb_.SetInsertPoint(block_unwind);
+  irb_.CreateRetVoid();
+  irb_.SetInsertPoint(block_cont);
+#endif
 
   llvm::Value* retval = irb_.CreateCall(code_addr, args);
 
diff --git a/src/object.cc b/src/object.cc
index 7fdff31..0bcf5c7 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -566,20 +566,16 @@
   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) {
-    art_ensure_link_from_code(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) {