Late method resolution.

Change-Id: Ic35348022391c3c11a1d4984b9add7b6ef53aa4c
diff --git a/src/class_linker.cc b/src/class_linker.cc
index e755cbd..095c949 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -1352,8 +1352,7 @@
   return oat_class;
 }
 
-// Special case to get oat code without overwriting a trampoline.
-const void* ClassLinker::GetOatCodeFor(const Method* method) {
+const OatFile::OatMethod ClassLinker::GetOatMethodFor(const Method* method) {
   CHECK(Runtime::Current()->IsCompiler() || method->GetDeclaringClass()->IsInitializing());
   // Although we overwrite the trampoline of non-static methods, we may get here via the resolution
   // method for direct methods (or virtual methods made direct).
@@ -1380,7 +1379,28 @@
   ClassHelper kh(declaring_class);
   UniquePtr<const OatFile::OatClass> oat_class(GetOatClass(kh.GetDexFile(), kh.GetDescriptor()));
   CHECK(oat_class.get() != NULL);
-  return oat_class->GetOatMethod(oat_method_index).GetCode();
+  return oat_class->GetOatMethod(oat_method_index);
+}
+
+// Special case to get oat code without overwriting a trampoline.
+const void* ClassLinker::GetOatCodeFor(const Method* method) {
+  return GetOatMethodFor(method).GetCode();
+}
+
+void ClassLinker::LinkOatCodeFor(Method* method) {
+  Class* declaring_class = method->GetDeclaringClass();
+  ClassHelper kh(declaring_class);
+  const OatFile* oat_file = FindOpenedOatFileForDexFile(kh.GetDexFile());
+  if (oat_file != NULL) {
+    // NOTE: We have to check the availability of OatFile first.  Because
+    // GetOatMethodFor(...) will try to find the OatFile and there's
+    // an assert in GetOatMethodFor(...).  Besides, due to the return
+    // type of OatClass::GetOatMethod(...), we can't return a failure value
+    // back.
+
+    // TODO: Remove this workaround.
+    GetOatMethodFor(method).LinkMethodPointers(method);
+  }
 }
 
 void ClassLinker::FixupStaticTrampolines(Class* klass) {
diff --git a/src/class_linker.h b/src/class_linker.h
index b6727d9..86b02ad 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -290,6 +290,8 @@
   // Get the oat code for a method when its class isn't yet initialized
   const void* GetOatCodeFor(const Method* method);
 
+  void LinkOatCodeFor(Method* method);
+
   // Relocate the OatFiles (ELF images)
   void RelocateExecutable();
 
@@ -299,6 +301,8 @@
  private:
   explicit ClassLinker(InternTable*);
 
+  const OatFile::OatMethod GetOatMethodFor(const Method* method);
+
   // Initialize class linker by bootstraping from dex files
   void InitFromCompiler(const std::vector<const DexFile*>& boot_class_path);
 
diff --git a/src/compiler_llvm/art_module.ll b/src/compiler_llvm/art_module.ll
index d18080f..874377e 100644
--- a/src/compiler_llvm/art_module.ll
+++ b/src/compiler_llvm/art_module.ll
@@ -141,3 +141,13 @@
 declare i32 @art_is_assignable_from_code(%JavaObject*, %JavaObject*)
 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)
+
+declare %JavaObject* @art_ensure_initialized_from_code(%JavaObject*,
+                                                       %JavaObject*)
diff --git a/src/compiler_llvm/generated/art_module.cc b/src/compiler_llvm/generated/art_module.cc
index 07fc6a3..2e46efc 100644
--- a/src/compiler_llvm/generated/art_module.cc
+++ b/src/compiler_llvm/generated/art_module.cc
@@ -46,10 +46,10 @@
 std::vector<Type*>StructTy_ShadowFrame_fields;
 PointerType* PointerTy_2 = PointerType::get(StructTy_ShadowFrame, 0);
 
-StructTy_ShadowFrame_fields.push_back(IntegerType::get(mod->getContext(), 32));
 StructTy_ShadowFrame_fields.push_back(PointerTy_2);
 StructTy_ShadowFrame_fields.push_back(PointerTy_1);
 StructTy_ShadowFrame_fields.push_back(IntegerType::get(mod->getContext(), 32));
+StructTy_ShadowFrame_fields.push_back(IntegerType::get(mod->getContext(), 32));
 if (StructTy_ShadowFrame->isOpaque()) {
 StructTy_ShadowFrame->setBody(StructTy_ShadowFrame_fields, /*isPacked=*/false);
 }
@@ -244,7 +244,7 @@
 FuncTy_25_args.push_back(PointerTy_1);
 FuncTy_25_args.push_back(PointerTy_1);
 FunctionType* FuncTy_25 = FunctionType::get(
- /*Result=*/IntegerType::get(mod->getContext(), 32),
+ /*Result=*/PointerTy_1,
  /*Params=*/FuncTy_25_args,
  /*isVarArg=*/false);
 
@@ -252,7 +252,7 @@
 FuncTy_26_args.push_back(PointerTy_1);
 FuncTy_26_args.push_back(PointerTy_1);
 FunctionType* FuncTy_26 = FunctionType::get(
- /*Result=*/Type::getVoidTy(mod->getContext()),
+ /*Result=*/IntegerType::get(mod->getContext(), 32),
  /*Params=*/FuncTy_26_args,
  /*isVarArg=*/false);
 
@@ -260,10 +260,20 @@
 FuncTy_27_args.push_back(PointerTy_1);
 FuncTy_27_args.push_back(PointerTy_1);
 FunctionType* FuncTy_27 = FunctionType::get(
- /*Result=*/PointerTy_1,
+ /*Result=*/Type::getVoidTy(mod->getContext()),
  /*Params=*/FuncTy_27_args,
  /*isVarArg=*/false);
 
+std::vector<Type*>FuncTy_28_args;
+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));
+FunctionType* FuncTy_28 = FunctionType::get(
+ /*Result=*/PointerTy_1,
+ /*Params=*/FuncTy_28_args,
+ /*isVarArg=*/false);
+
 
 // Function Declarations
 
@@ -743,7 +753,7 @@
 Function* func_art_decode_jobject_in_thread = mod->getFunction("art_decode_jobject_in_thread");
 if (!func_art_decode_jobject_in_thread) {
 func_art_decode_jobject_in_thread = Function::Create(
- /*Type=*/FuncTy_27,
+ /*Type=*/FuncTy_25,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"art_decode_jobject_in_thread", mod); // (external, no body)
 func_art_decode_jobject_in_thread->setCallingConv(CallingConv::C);
@@ -754,7 +764,7 @@
 Function* func_art_is_assignable_from_code = mod->getFunction("art_is_assignable_from_code");
 if (!func_art_is_assignable_from_code) {
 func_art_is_assignable_from_code = Function::Create(
- /*Type=*/FuncTy_25,
+ /*Type=*/FuncTy_26,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"art_is_assignable_from_code", mod); // (external, no body)
 func_art_is_assignable_from_code->setCallingConv(CallingConv::C);
@@ -765,7 +775,7 @@
 Function* func_art_check_cast_from_code = mod->getFunction("art_check_cast_from_code");
 if (!func_art_check_cast_from_code) {
 func_art_check_cast_from_code = Function::Create(
- /*Type=*/FuncTy_26,
+ /*Type=*/FuncTy_27,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"art_check_cast_from_code", mod); // (external, no body)
 func_art_check_cast_from_code->setCallingConv(CallingConv::C);
@@ -784,6 +794,39 @@
 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(
+ /*Type=*/FuncTy_28,
+ /*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_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,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_ensure_initialized_from_code", mod); // (external, no body)
+func_art_ensure_initialized_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);
+
 // Global Variable Declarations
 
 
diff --git a/src/compiler_llvm/jni_compiler.cc b/src/compiler_llvm/jni_compiler.cc
index 285caab..071c0bd 100644
--- a/src/compiler_llvm/jni_compiler.cc
+++ b/src/compiler_llvm/jni_compiler.cc
@@ -145,11 +145,20 @@
                       irb_.getInt32(Thread::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;
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 57dbf15..7c19774 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -2785,6 +2785,39 @@
     << 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));
+}
+
+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);
+}
 
 void MethodCompiler::EmitInsn_InvokeVirtualSuperSlow(uint32_t dex_pc,
                                                      DecodedInstruction &dec_insn,
@@ -2812,14 +2845,28 @@
 
   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* code_addr =
+  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_ =
       EmitLoadCodeAddr(callee_method_object_addr, callee_method_idx, false);
+
+  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);
@@ -2864,13 +2911,25 @@
     // 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* code_addr =
+    llvm::Value* method_object_addr = EmitEnsureResolved(method_object_addr_,
+                                                         EmitLoadMethodObjectAddr(),
+                                                         callee_method_idx,
+                                                         Instruction::INVOKE_VIRTUAL);
+
+    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_);
+
     // Load actual parameters
     std::vector<llvm::Value*> args;
     args.push_back(method_object_addr);
@@ -2953,14 +3012,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* code_addr =
+    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,
+                                                   callee_method_idx,
+                                                   false,
+                                                   code_addr_);
+
     // Load actual parameters
     std::vector<llvm::Value*> args;
     args.push_back(callee_method_object_addr);
@@ -3019,12 +3090,25 @@
   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* code_addr =
+  llvm::Value* callee_method_object_addr = EmitEnsureResolved(callee_method_object_addr_,
+                                                              EmitLoadMethodObjectAddr(),
+                                                              callee_method_idx,
+                                                              Instruction::INVOKE_DIRECT);
+
+  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);
+
   // Load the actual parameter
   std::vector<llvm::Value*> args;
 
@@ -3075,15 +3159,27 @@
 
   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* code_addr =
+  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_ =
     EmitLoadCodeAddr(callee_method_object_addr, callee_method_idx, false);
 
+  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);
diff --git a/src/compiler_llvm/method_compiler.h b/src/compiler_llvm/method_compiler.h
index 1ff3a9f..e5be3ba 100644
--- a/src/compiler_llvm/method_compiler.h
+++ b/src/compiler_llvm/method_compiler.h
@@ -194,6 +194,16 @@
   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* EmitEnsureResolved(llvm::Value* callee,
+                                  llvm::Value* caller,
+                                  uint32_t dex_method_idx,
+                                  Instruction::Code instr_code);
+  void EmitEnsureLink(llvm::Value*);
+
   void EmitInsn_InvokeVirtual(GEN_INSN_ARGS, bool is_range);
   void EmitInsn_InvokeSuper(GEN_INSN_ARGS, bool is_range);
   void EmitInsn_InvokeVirtualSuperSlow(uint32_t dex_pc,
diff --git a/src/compiler_llvm/runtime_support_func_list.h b/src/compiler_llvm/runtime_support_func_list.h
index 518a175..2f1fb13 100644
--- a/src/compiler_llvm/runtime_support_func_list.h
+++ b/src/compiler_llvm/runtime_support_func_list.h
@@ -57,4 +57,7 @@
   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(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 ff31825..57fd507 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -517,6 +517,94 @@
   }
 }
 
+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;
+  }
+}
+
+Method* art_ensure_resolved_from_code(Method* called,
+                                      Method* caller,
+                                      uint32_t dex_method_idx,
+                                      Instruction::Code instr_code) {
+  if (LIKELY(!called->IsResolutionMethod())) {
+    return called;
+  }
+  // Compute details about the called method (avoid GCs)
+  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);
+
+  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";
+      }
+    } 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 (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());
+  }
+
+  return called;
+}
+
+void art_ensure_link_from_code(Method* method) {
+  if (method->GetInvokeStub() == NULL && method->GetCode() == NULL) {
+    Runtime::Current()->GetClassLinker()->LinkOatCodeFor(method);
+  }
+}
+
 void* art_find_runtime_support_func(void* context, char const* name) {
   struct func_entry_t {
     char const* name;
diff --git a/src/compiler_llvm/runtime_support_llvm.h b/src/compiler_llvm/runtime_support_llvm.h
index 51d238b..1040b90 100644
--- a/src/compiler_llvm/runtime_support_llvm.h
+++ b/src/compiler_llvm/runtime_support_llvm.h
@@ -19,6 +19,9 @@
 
 namespace art {
 
+class Method;
+class Object;
+
 //----------------------------------------------------------------------------
 // Thread
 //----------------------------------------------------------------------------
@@ -59,6 +62,8 @@
 
 void* art_find_runtime_support_func(void* context, char const* name);
 
+void art_ensure_link_from_code(Method* method);
+
 }  // namespace art
 
 #endif  // ART_SRC_COMPILER_LLVM_RUNTIME_SUPPORT_LLVM_H_
diff --git a/src/compiler_llvm/upcall_compiler.cc b/src/compiler_llvm/upcall_compiler.cc
index 85bfe24..6d14a19 100644
--- a/src/compiler_llvm/upcall_compiler.cc
+++ b/src/compiler_llvm/upcall_compiler.cc
@@ -151,7 +151,15 @@
     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_ = 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* retval = irb_.CreateCall(code_addr, args);
 
diff --git a/src/object.cc b/src/object.cc
index 2cf8a6c..f2bddc3 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -40,6 +40,7 @@
 
 #if defined(ART_USE_LLVM_COMPILER)
 #include "compiler_llvm/inferred_reg_category_map.h"
+#include "compiler_llvm/runtime_support_llvm.h"
 using art::compiler_llvm::InferredRegCategoryMap;
 #endif
 
@@ -559,6 +560,7 @@
 void Method::Invoke(Thread* self, Object* receiver, JValue* args, JValue* result) const {
   // Push a transition back into managed code onto the linked list in thread.
   CHECK_EQ(Thread::kRunnable, self->GetState());
+
 #if !defined(ART_USE_LLVM_COMPILER)
   NativeToManagedRecord record;
   self->PushNativeToManagedRecord(&record);
@@ -570,6 +572,14 @@
 
   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) {