Compiler cleanup

  o Added slow path for string resolution
  o Removed dead throw internal and runtime error
  o Restructured debug and optimization disable flags for make it easier
    for command-line option support.
  o Removed/converted #if 1/0 blocks

Change-Id: I65fc561a55437b3f74d0dfff5af87f938008d70e
diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc
index 3f7a7ae..b63c37f 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -22,9 +22,16 @@
  *
  */
 
-#define SLOW_FIELD_PATH 0
-#define SLOW_INVOKE_PATH 0
-//#define EXERCISE_SLOWEST_FIELD_PATH
+#define SLOW_FIELD_PATH (cUnit->enableDebug & (1 << kDebugSlowFieldPath))
+#define SLOW_INVOKE_PATH (cUnit->enableDebug & (1 << kDebugSlowInvokePath))
+#define SLOW_STRING_PATH (cUnit->enableDebug & (1 << kDebugSlowStringPath))
+#define SLOW_TYPE_PATH (cUnit->enableDebug & (1 << kDebugSlowTypePath))
+#define EXERCISE_SLOWEST_FIELD_PATH (cUnit->enableDebug & \
+    (1 << kDebugSlowestFieldPath))
+#define EXERCISE_SLOWEST_STRING_PATH (cUnit->enableDebug & \
+    (1 << kDebugSlowestStringPath))
+
+STATIC RegLocation getRetLoc(CompilationUnit* cUnit);
 
 std::string fieldNameFromIndex(const Method* method, uint32_t fieldIdx)
 {
@@ -427,9 +434,10 @@
      * For testing, omit the test for run-time resolution. This will
      * force all accesses to go through the runtime resolution path.
      */
-#ifndef EXERCISE_SLOWEST_FIELD_PATH
-    ArmLIR* branchOver = genCmpImmBranch(cUnit, kArmCondNe, r0, 0);
-#endif
+    ArmLIR* branchOver = NULL;
+    if (!EXERCISE_SLOWEST_FIELD_PATH) {
+        branchOver = genCmpImmBranch(cUnit, kArmCondNe, r0, 0);
+    }
     // Resolve
     loadWordDisp(cUnit, rSELF,
                  OFFSETOF_MEMBER(Thread, pFindInstanceFieldFromCode), rLR);
@@ -437,9 +445,9 @@
     callRuntimeHelper(cUnit, rLR);  // resolveTypeFromCode(idx, method)
     ArmLIR* target = newLIR0(cUnit, kArmPseudoTargetLabel);
     target->defMask = ENCODE_ALL;
-#ifndef EXERCISE_SLOWEST_FIELD_PATH
-    branchOver->generic.target = (LIR*)target;
-#endif
+    if (!EXERCISE_SLOWEST_FIELD_PATH) {
+        branchOver->generic.target = (LIR*)target;
+    }
     // Free temps (except for r0)
     oatFreeTemp(cUnit, r1);
     oatFreeTemp(cUnit, r2);
@@ -532,7 +540,7 @@
 #else
     bool isVolatile = false;
 #endif
-    if ((fieldPtr == NULL) || isVolatile) {
+    if (SLOW_FIELD_PATH || (fieldPtr == NULL) || isVolatile) {
         getFieldOffset(cUnit, mir, fieldPtr);
         // Field offset in r0
         rlObj = loadValue(cUnit, rlObj, kCoreReg);
@@ -570,7 +578,7 @@
 #else
     bool isVolatile = false;
 #endif
-    if ((fieldPtr == NULL) || isVolatile) {
+    if (SLOW_FIELD_PATH || (fieldPtr == NULL) || isVolatile) {
         getFieldOffset(cUnit, mir, fieldPtr);
         // Field offset in r0
         rlObj = loadValue(cUnit, rlObj, kCoreReg);
@@ -607,7 +615,7 @@
                  resReg);
     loadWordDisp(cUnit, resReg, Array::DataOffset().Int32Value() +
                  (sizeof(String*) * mir->dalvikInsn.vB), rlResult.lowReg);
-    if (classPtr != NULL) {
+    if (SLOW_TYPE_PATH || (classPtr == NULL)) {
         // Fast path, we're done - just store result
         storeValue(cUnit, rlDest, rlResult);
     } else {
@@ -640,19 +648,41 @@
 STATIC void genConstString(CompilationUnit* cUnit, MIR* mir,
                            RegLocation rlDest, RegLocation rlSrc)
 {
-    /* All strings should be available at compile time */
+    /* NOTE: Most strings should be available at compile time */
     const art::String* str = cUnit->method->GetDexCacheStrings()->
         Get(mir->dalvikInsn.vB);
-    DCHECK(str != NULL);
-
-    int mReg = loadCurrMethod(cUnit);
-    int resReg = oatAllocTemp(cUnit);
-    RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
-    loadWordDisp(cUnit, mReg, Method::DexCacheStringsOffset().Int32Value(),
-                 resReg);
-    loadWordDisp(cUnit, resReg, Array::DataOffset().Int32Value() +
-                 (sizeof(String*) * mir->dalvikInsn.vB), rlResult.lowReg);
-    storeValue(cUnit, rlDest, rlResult);
+    if (SLOW_STRING_PATH || (str == NULL)) {
+        oatFlushAllRegs(cUnit);
+        oatLockCallTemps(cUnit); // Using explicit registers
+        loadCurrMethodDirect(cUnit, r2);
+        loadWordDisp(cUnit, r2, Method::DexCacheStringsOffset().Int32Value(),
+                     r0);
+        // Might call out to helper, which will return resolved string in r0
+        loadWordDisp(cUnit, rSELF,
+                     OFFSETOF_MEMBER(Thread, pResolveStringFromCode), rLR);
+        loadWordDisp(cUnit, r0, Array::DataOffset().Int32Value() +
+                 (sizeof(String*) * mir->dalvikInsn.vB), r0);
+        loadConstant(cUnit, r1, mir->dalvikInsn.vB);
+        opRegImm(cUnit, kOpCmp, r0, 0);  // Is resolved?
+        genBarrier(cUnit);
+        // For testing, always force through helper
+        if (!EXERCISE_SLOWEST_STRING_PATH) {
+            genIT(cUnit, kArmCondEq, "T");
+        }
+        genRegCopy(cUnit, r0, r2);       // .eq
+        opReg(cUnit, kOpBlx, rLR);       // .eq, helper(Method*, string_idx)
+        genBarrier(cUnit);
+        storeValue(cUnit, rlDest, getRetLoc(cUnit));
+    } else {
+        int mReg = loadCurrMethod(cUnit);
+        int resReg = oatAllocTemp(cUnit);
+        RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+        loadWordDisp(cUnit, mReg, Method::DexCacheStringsOffset().Int32Value(),
+                     resReg);
+        loadWordDisp(cUnit, resReg, Array::DataOffset().Int32Value() +
+                    (sizeof(String*) * mir->dalvikInsn.vB), rlResult.lowReg);
+        storeValue(cUnit, rlDest, rlResult);
+    }
 }
 
 /*
@@ -1778,25 +1808,8 @@
                  OFFSETOF_MEMBER(Thread, pCheckSuspendFromCode), rLR);
     genRegCopy(cUnit, r0, rSELF);
     opRegImm(cUnit, kOpCmp, rSuspendCount, 0);
-    /*
-     * FIXME: for efficiency we should use an if-converted suspend
-     * test here.  However, support for IT is a bit weak at the
-     * moment, and requires knowledge of the exact number of instructions
-     * to fall in the skip shadow.  While the exception mechanism
-     * remains in flux, use a compare and branch sequence.  Once
-     * things firm up, restore the conditional skip (and perhaps
-     * fix the utility to handle variable-sized shadows).
-     */
-#if 0
     genIT(cUnit, kArmCondNe, "");
-    callUnwindableHelper(cUnit, rLR); // CheckSuspendFromCode(self)
-#else
-    ArmLIR* branch = opCondBranch(cUnit, kArmCondEq);
-    callRuntimeHelper(cUnit, rLR); // CheckSuspendFromCode(self)
-    ArmLIR* target = newLIR0(cUnit, kArmPseudoTargetLabel);
-    target->defMask = ENCODE_ALL;
-    branch->generic.target = (LIR*)target;
-#endif
+    opReg(cUnit, kOpBlx, rLR);
     oatFreeCallTemps(cUnit);
 }