Add unimplemented artResolveMethodFromCode

Change-Id: I1ba804c56413477451abff82939e27579494e1f9
diff --git a/src/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc
index 3f8d900..08a53bd 100644
--- a/src/compiler/codegen/arm/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc
@@ -545,6 +545,7 @@
             loadWordDisp(cUnit, rSELF,
                          OFFSETOF_MEMBER(Thread, pResolveMethodFromCode), rLR);
             loadConstant(cUnit, r1, dInsn->vB);
+            loadConstant(cUnit, r2, false);
             callRuntimeHelper(cUnit, rLR);
             genUnconditionalBranch(cUnit, rollback);
             // Resume normal slow path
@@ -729,6 +730,7 @@
             loadWordDisp(cUnit, rSELF,
                          OFFSETOF_MEMBER(Thread, pResolveMethodFromCode), rLR);
             loadConstant(cUnit, r1, dInsn->vB);
+            loadConstant(cUnit, r2, true);
             callRuntimeHelper(cUnit, rLR);
             genUnconditionalBranch(cUnit, rollback);
             // Resume normal slow path
@@ -1085,6 +1087,7 @@
         loadWordDisp(cUnit, rSELF,
                      OFFSETOF_MEMBER(Thread, pResolveMethodFromCode), rLR);
         loadConstant(cUnit, r1, dInsn->vB);
+        loadConstant(cUnit, r2, true);
         callRuntimeHelper(cUnit, rLR);
     }
 
@@ -1157,6 +1160,7 @@
         loadWordDisp(cUnit, rSELF,
                      OFFSETOF_MEMBER(Thread, pResolveMethodFromCode), rLR);
         loadConstant(cUnit, r1, dInsn->vB);
+        loadConstant(cUnit, r2, false);
         callRuntimeHelper(cUnit, rLR);
     }
 
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 223ea7e..1a6d2e6 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -854,17 +854,22 @@
   return InitializeStaticStorageAndVerifyAccess(type_idx, referrer, self);
 }
 
-// TODO: placeholder.  Helper function to resolve virtual method
-void ResolveMethodFromCode(Method* method, uint32_t method_idx) {
+// Helper function to resolve virtual method
+extern "C" Method* artResolveMethodFromCode(Method* referrer,
+                                            uint32_t method_idx,
+                                            bool is_direct,
+                                            Thread* self,
+                                            Method** sp) {
     /*
      * Slow-path handler on invoke virtual method path in which
-     * base method is unresolved at compile-time.  Doesn't need to
-     * return anything - just either ensure that
-     * method->dex_cache_resolved_methods_(method_idx) != NULL or
-     * throw and unwind.  The caller will restart call sequence
-     * from the beginning.
+     * base method is unresolved at compile-time.  Caller will
+     * unwind if can't resolve.
      */
-    UNIMPLEMENTED(FATAL);
+    FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+    Method* method = class_linker->ResolveMethod(method_idx, referrer, is_direct);
+    referrer->GetDexCacheResolvedMethods()->Set(method_idx, method);
+    return method;
 }
 
 String* ResolveStringFromCode(const Method* referrer, uint32_t string_idx) {
diff --git a/src/runtime_support.h b/src/runtime_support.h
index 2ebfc22..876abd7 100644
--- a/src/runtime_support.h
+++ b/src/runtime_support.h
@@ -25,7 +25,6 @@
 extern Class* InitializeTypeFromCode(uint32_t type_idx, Method* method);
 uint32_t IsAssignableFromCode(const Class* klass, const Class* ref_class);
 void ObjectInitFromCode(Object* o);
-extern void ResolveMethodFromCode(Method* method, uint32_t method_idx);
 extern void LockObjectFromCode(Thread* thread, Object* obj);
 uint32_t artTraceMethodUnwindFromCode(Thread* self);
 extern int64_t D2L(double d);
@@ -73,6 +72,7 @@
   extern "C" void art_trace_entry_from_code(void*);
   extern "C" void art_trace_exit_from_code();
   extern "C" void* art_resolve_string_from_code(void*, uint32_t);
+  extern "C" void* art_resolve_method_from_code(void* referrer, uint32_t method_idx, bool is_direct);
 
   /* Conversions */
   extern "C" float __aeabi_i2f(int op1);             // OP_INT_TO_FLOAT
diff --git a/src/runtime_support_arm.S b/src/runtime_support_arm.S
index 38337a3..c73588e 100644
--- a/src/runtime_support_arm.S
+++ b/src/runtime_support_arm.S
@@ -421,6 +421,22 @@
     bxeq   lr                            @ return on success
     DELIVER_PENDING_EXCEPTION
 
+   .global art_resolve_method_from_code
+    .extern artResolveMethodFromCode
+    /*
+     * Entry from managed code to resolve a method.
+     */
+art_resolve_method_from_code:
+    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  @ save callee saves in case of GC
+    mov    r3, r9                     @ pass Thread::Current
+    str    sp, [sp, #0]               @ pass SP
+    @ artResolveMethodFromCode(Method* referrer, uint32_t method_idx, bool is_direct, Thread*, SP)
+    bl     artResolveMethodFromCode
+    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
+    cmp    r0, #0                     @ success if result is non-null
+    bxne   lr                         @ return on success
+    DELIVER_PENDING_EXCEPTION
+
     .global art_resolve_string_from_code
     .extern artResolveStringFromCode
     /*
diff --git a/src/thread.cc b/src/thread.cc
index 4adf1e0..b065533 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -127,6 +127,7 @@
   pThrowStackOverflowFromCode = art_throw_stack_overflow_from_code;
   pThrowVerificationErrorFromCode = art_throw_verification_error_from_code;
   pUnlockObjectFromCode = art_unlock_object_from_code;
+  pResolveMethodFromCode = art_resolve_method_from_code;
 #endif
   pF2l = F2L;
   pD2l = D2L;
@@ -137,7 +138,6 @@
   pDeliverException = art_deliver_exception_from_code;
   pFindNativeMethod = FindNativeMethod;
   pInstanceofNonTrivialFromCode = IsAssignableFromCode;
-  pResolveMethodFromCode = ResolveMethodFromCode;
   pThrowAbstractMethodErrorFromCode = ThrowAbstractMethodErrorFromCode;
   pUnresolvedDirectMethodTrampolineFromCode = UnresolvedDirectMethodTrampolineFromCode;
 }
diff --git a/src/thread.h b/src/thread.h
index c5fb914..aee784d 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -143,7 +143,7 @@
   void* (*pInitializeTypeAndVerifyAccessFromCode)(uint32_t, void*);
   void (*pLockObjectFromCode)(void*);
   void (*pObjectInit)(void*);
-  void (*pResolveMethodFromCode)(Method*, uint32_t);
+  void* (*pResolveMethodFromCode)(void*, uint32_t, bool);
   void* (*pResolveStringFromCode)(void*, uint32_t);
   int (*pSet32Static)(uint32_t, void*, int32_t);
   int (*pSet64Static)(uint32_t, void*, int64_t);