Add stress-test mode for  ResolveMethodFromCode

To force call to artResolveMethodFromCode prior to each virtual or
super invoke, add (1 << kDebugExerciseResolveMethod) bit to the
compiler's debug flags.

Change-Id: If14e4bcc8073c8ac7a7a8d0d92bc49444528f77e
diff --git a/src/compiler/Compiler.h b/src/compiler/Compiler.h
index d16735c..224ea6e 100644
--- a/src/compiler/Compiler.h
+++ b/src/compiler/Compiler.h
@@ -51,6 +51,7 @@
     kDebugSlowTypePath,
     kDebugSlowestFieldPath,
     kDebugSlowestStringPath,
+    kDebugExerciseResolveMethod,
 };
 
 extern uint32_t compilerDebugFlags;
diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc
index 5855341..2eba586 100644
--- a/src/compiler/Frontend.cc
+++ b/src/compiler/Frontend.cc
@@ -41,6 +41,7 @@
      //(1 << kDebugSlowStringPath) |
      //(1 << kDebugSlowestFieldPath) |
      //(1 << kDebugSlowestStringPath) |
+     //(1 << kDebugExerciseResolveMethod) |
      0;
 
 std::string compilerMethodMatch;      // Method name match to apply above flags
diff --git a/src/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc
index 33823ca..3f8d900 100644
--- a/src/compiler/codegen/arm/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc
@@ -715,7 +715,7 @@
         case 0:  // Get the current Method* [sets r0]
             loadCurrMethodDirect(cUnit, r0);
             break;
-        case 1: // Get method->dex_cache_resolved_methods_ [usr r0, set rLR]
+        case 1: // Get method->dex_cache_resolved_methods_ [uses r0, set rLR]
             loadWordDisp(cUnit, r0,
                 Method::GetDexCacheResolvedMethodsOffset().Int32Value(), rLR);
             break;
@@ -1078,6 +1078,16 @@
 
     // Explicit register usage
     oatLockCallTemps(cUnit);
+
+    // For testing, force call to artResolveMethodFromCode & ignore result
+    if (EXERCISE_RESOLVE_METHOD) {
+        loadCurrMethodDirect(cUnit, r0);
+        loadWordDisp(cUnit, rSELF,
+                     OFFSETOF_MEMBER(Thread, pResolveMethodFromCode), rLR);
+        loadConstant(cUnit, r1, dInsn->vB);
+        callRuntimeHelper(cUnit, rLR);
+    }
+
     if (SLOW_INVOKE_PATH || baseMethod == NULL) {
         Thread* thread = Thread::Current();
         if (thread->IsExceptionPending()) {  // clear any exception left by resolve method
@@ -1138,9 +1148,18 @@
                                                  false);
     NextCallInsn nextCallInsn;
     oatFlushAllRegs(cUnit);    /* Everything to home location */
-
     // Explicit register usage
     oatLockCallTemps(cUnit);
+
+    // For testing, force call to artResolveMethodFromCode & ignore result
+    if (EXERCISE_RESOLVE_METHOD) {
+        loadCurrMethodDirect(cUnit, r0);
+        loadWordDisp(cUnit, rSELF,
+                     OFFSETOF_MEMBER(Thread, pResolveMethodFromCode), rLR);
+        loadConstant(cUnit, r1, dInsn->vB);
+        callRuntimeHelper(cUnit, rLR);
+    }
+
     if (SLOW_INVOKE_PATH || method == NULL) {
         Thread* thread = Thread::Current();
         if (thread->IsExceptionPending()) {  // clear any exception left by resolve method
diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc
index 6796f6c..0afbe41 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -30,6 +30,8 @@
     (1 << kDebugSlowestFieldPath))
 #define EXERCISE_SLOWEST_STRING_PATH (cUnit->enableDebug & \
     (1 << kDebugSlowestStringPath))
+#define EXERCISE_RESOLVE_METHOD (cUnit->enableDebug & \
+    (1 << kDebugExerciseResolveMethod))
 
 STATIC RegLocation getRetLoc(CompilationUnit* cUnit);
 
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 2ee64a1..223ea7e 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -864,6 +864,7 @@
      * throw and unwind.  The caller will restart call sequence
      * from the beginning.
      */
+    UNIMPLEMENTED(FATAL);
 }
 
 String* ResolveStringFromCode(const Method* referrer, uint32_t string_idx) {