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/Optimizer.h b/src/compiler/codegen/Optimizer.h
index c946e93..307d401 100644
--- a/src/compiler/codegen/Optimizer.h
+++ b/src/compiler/codegen/Optimizer.h
@@ -22,16 +22,6 @@
 #define STACK_ALIGN_WORDS 4
 #define STACK_ALIGNMENT (STACK_ALIGN_WORDS * 4)
 
-/* Supress optimization if corresponding bit set */
-enum optControlVector {
-    kLoadStoreElimination = 0,
-    kLoadHoisting,
-    kSuppressLoads,
-    kNullCheckElimination,
-    kPromoteRegs,
-    kTrackLiveTemps,
-};
-
 /* Forward declarations */
 struct CompilationUnit;
 struct LIR;
diff --git a/src/compiler/codegen/arm/ArmLIR.h b/src/compiler/codegen/arm/ArmLIR.h
index 99b22e7..daa1396 100644
--- a/src/compiler/codegen/arm/ArmLIR.h
+++ b/src/compiler/codegen/arm/ArmLIR.h
@@ -357,8 +357,6 @@
     kArmThrowArrayBounds,
     kArmThrowVerificationError,
     kArmThrowNegArraySize,
-    kArmThrowInternalError,
-    kArmThrowRuntimeException,
     kArmThrowNoSuchMethod,
     kArmThrowStackOverflow,
 } ArmThrowKind;
diff --git a/src/compiler/codegen/arm/ArmRallocUtil.cc b/src/compiler/codegen/arm/ArmRallocUtil.cc
index 9a7c642..94852e3 100644
--- a/src/compiler/codegen/arm/ArmRallocUtil.cc
+++ b/src/compiler/codegen/arm/ArmRallocUtil.cc
@@ -178,11 +178,6 @@
     qsort(coreRegs, numRegs, sizeof(RefCounts), sortCounts);
     qsort(fpRegs, numRegs, sizeof(RefCounts), sortCounts);
 
-    if (cUnit->printMeVerbose) {
-        dumpCounts(coreRegs, numRegs, "coreRegs");
-        dumpCounts(fpRegs, numRegs, "fpRegs");
-    }
-
     if (!(cUnit->disableOpt & (1 << kPromoteRegs))) {
         // Promote fpRegs
         for (int i = 0; (fpRegs[i].count > 0) && (i < numRegs); i++) {
diff --git a/src/compiler/codegen/arm/Assemble.cc b/src/compiler/codegen/arm/Assemble.cc
index c42b4b8..bbd97b4 100644
--- a/src/compiler/codegen/arm/Assemble.cc
+++ b/src/compiler/codegen/arm/Assemble.cc
@@ -20,12 +20,6 @@
 #include "Codegen.h"
 #include <sys/mman.h>           /* for protection change */
 
-//#define TESTMODE
-#ifdef TESTMODE
-#include <cutils/ashmem.h>      /* for oat testing */
-#include <unistd.h>
-#endif
-
 #define MAX_ASSEMBLER_RETRIES 50
 
 /*
diff --git a/src/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc
index 6be9f76..922e25b 100644
--- a/src/compiler/codegen/arm/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#define DISPLAY_MISSING_TARGETS 1
+#define DISPLAY_MISSING_TARGETS (cUnit->enableDebug & \
+    (1 << kDebugDisplayMissingTargets))
 
 STATIC const RegLocation badLoc = {kLocDalvikFrame, 0, 0, INVALID_REG,
                                    INVALID_REG, INVALID_SREG, 0,
@@ -922,7 +923,6 @@
     return callState;
 }
 
-#ifdef DISPLAY_MISSING_TARGETS
 // Debugging routine - if null target, branch to DebugMe
 STATIC void genShowTarget(CompilationUnit* cUnit)
 {
@@ -933,7 +933,6 @@
     target->defMask = -1;
     branchOver->generic.target = (LIR*)target;
 }
-#endif
 
 STATIC void genInvokeStaticDirect(CompilationUnit* cUnit, MIR* mir,
                                   bool direct, bool range)
@@ -959,9 +958,9 @@
     while (callState >= 0) {
         callState = nextCallInsn(cUnit, mir, dInsn, callState, NULL);
     }
-#ifdef DISPLAY_MISSING_TARGETS
-    genShowTarget(cUnit);
-#endif
+    if (DISPLAY_MISSING_TARGETS) {
+        genShowTarget(cUnit);
+    }
     opReg(cUnit, kOpBlx, rLR);
     oatClobberCalleeSave(cUnit);
 }
@@ -992,9 +991,9 @@
     while (callState >= 0) {
         callState = nextInterfaceCallInsn(cUnit, mir, dInsn, callState, NULL);
     }
-#ifdef DISPLAY_MISSING_TARGETS
-    genShowTarget(cUnit);
-#endif
+    if (DISPLAY_MISSING_TARGETS) {
+        genShowTarget(cUnit);
+    }
     opReg(cUnit, kOpBlx, rLR);
     oatClobberCalleeSave(cUnit);
 }
@@ -1045,9 +1044,9 @@
     while (callState >= 0) {
         callState = nextCallInsn(cUnit, mir, dInsn, callState, rollback);
     }
-#ifdef DISPLAY_MISSING_TARGETS
-    genShowTarget(cUnit);
-#endif
+    if (DISPLAY_MISSING_TARGETS) {
+        genShowTarget(cUnit);
+    }
     opReg(cUnit, kOpBlx, rLR);
     oatClobberCalleeSave(cUnit);
 }
@@ -1085,9 +1084,9 @@
     while (callState >= 0) {
         callState = nextCallInsn(cUnit, mir, dInsn, callState, rollback);
     }
-#ifdef DISPLAY_MISSING_TARGETS
-    genShowTarget(cUnit);
-#endif
+    if (DISPLAY_MISSING_TARGETS) {
+        genShowTarget(cUnit);
+    }
     opReg(cUnit, kOpBlx, rLR);
     oatClobberCalleeSave(cUnit);
 }
@@ -2108,16 +2107,6 @@
                 funcOffset =
                     OFFSETOF_MEMBER(Thread, pThrowNegArraySizeFromCode);
                 break;
-            case kArmThrowInternalError:
-                genRegCopy(cUnit, r0, v1);
-                funcOffset =
-                    OFFSETOF_MEMBER(Thread, pThrowInternalErrorFromCode);
-                break;
-            case kArmThrowRuntimeException:
-                genRegCopy(cUnit, r0, v1);
-                funcOffset =
-                    OFFSETOF_MEMBER(Thread, pThrowRuntimeExceptionFromCode);
-                break;
             case kArmThrowNoSuchMethod:
                 genRegCopy(cUnit, r0, v1);
                 funcOffset =
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);
 }