Generate code for loops formed with the new builder

Adapt the existing counted loop analysis and range/null check
elimination code to work with the new loop building heuristics.
Cleaned up the old ad-hoc loop builder.

Suspend polling is enabled by default for loops. The backward chaining
cell will be used in self-verification and profiling mode.

If the loop includes accesses to resolved fields/classes, abort code
generation for now and revert to the basic acyclic trace. Added
tests/090-loop-formation to make sure the JIT won't choke on such
instructions.

Change-Id: Idbc57df0a745be3b692f68c1acb6d4861c537f75
diff --git a/vm/compiler/codegen/arm/CodegenDriver.c b/vm/compiler/codegen/arm/CodegenDriver.c
index 8d8619b..f020e9c 100644
--- a/vm/compiler/codegen/arm/CodegenDriver.c
+++ b/vm/compiler/codegen/arm/CodegenDriver.c
@@ -1356,6 +1356,12 @@
     int flagsToCheck = kInstrCanBranch | kInstrCanSwitch | kInstrCanReturn |
                        kInstrCanThrow;
 
+    // Single stepping is considered loop mode breaker
+    if (cUnit->jitMode == kJitLoop) {
+        cUnit->quitLoopMode = true;
+        return;
+    }
+
     //If already optimized out, just ignore
     if (mir->dalvikInsn.opcode == OP_NOP)
         return;
@@ -1448,7 +1454,8 @@
     /* backward branch? */
     bool backwardBranch = (bb->taken->startOffset <= mir->offset);
 
-    if (backwardBranch && gDvmJit.genSuspendPoll) {
+    if (backwardBranch &&
+        (gDvmJit.genSuspendPoll || cUnit->jitMode == kJitLoop)) {
         genSuspendPoll(cUnit, mir);
     }
 
@@ -1579,6 +1586,7 @@
               (cUnit->method->clazz->pDvmDex->pResStrings[mir->dalvikInsn.vB]);
 
             if (strPtr == NULL) {
+                BAIL_LOOP_COMPILATION();
                 LOGE("Unexpected null string");
                 dvmAbort();
             }
@@ -1595,6 +1603,7 @@
               (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
 
             if (classPtr == NULL) {
+                BAIL_LOOP_COMPILATION();
                 LOGE("Unexpected null class");
                 dvmAbort();
             }
@@ -1631,6 +1640,7 @@
             Opcode opcode = mir->dalvikInsn.opcode;
 
             if (fieldPtr == NULL) {
+                BAIL_LOOP_COMPILATION();
                 LOGE("Unexpected null static field");
                 dvmAbort();
             }
@@ -1664,6 +1674,7 @@
               (method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
 
             if (fieldPtr == NULL) {
+                BAIL_LOOP_COMPILATION();
                 LOGE("Unexpected null static field");
                 dvmAbort();
             }
@@ -1707,6 +1718,12 @@
               (method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
             Opcode opcode = mir->dalvikInsn.opcode;
 
+            if (fieldPtr == NULL) {
+                BAIL_LOOP_COMPILATION();
+                LOGE("Unexpected null static field");
+                dvmAbort();
+            }
+
             isVolatile = (opcode == OP_SPUT_VOLATILE) ||
                          (opcode == OP_SPUT_VOLATILE_JUMBO) ||
                          (opcode == OP_SPUT_OBJECT_VOLATILE) ||
@@ -1718,11 +1735,6 @@
                            (opcode == OP_SPUT_OBJECT_VOLATILE) ||
                            (opcode == OP_SPUT_OBJECT_VOLATILE_JUMBO);
 
-            if (fieldPtr == NULL) {
-                LOGE("Unexpected null static field");
-                dvmAbort();
-            }
-
             rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
             rlSrc = loadValue(cUnit, rlSrc, kAnyReg);
             loadConstant(cUnit, tReg,  (int) fieldPtr);
@@ -1755,6 +1767,7 @@
               (method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
 
             if (fieldPtr == NULL) {
+                BAIL_LOOP_COMPILATION();
                 LOGE("Unexpected null static field");
                 dvmAbort();
             }
@@ -1778,6 +1791,7 @@
               (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
 
             if (classPtr == NULL) {
+                BAIL_LOOP_COMPILATION();
                 LOGE("Unexpected null class");
                 dvmAbort();
             }
@@ -1829,9 +1843,10 @@
              * so that we can tell if it happens frequently.
              */
             if (classPtr == NULL) {
-                 LOGVV("null clazz in OP_CHECK_CAST, single-stepping");
-                 genInterpSingleStep(cUnit, mir);
-                 return false;
+                BAIL_LOOP_COMPILATION();
+                LOGVV("null clazz in OP_CHECK_CAST, single-stepping");
+                genInterpSingleStep(cUnit, mir);
+                return false;
             }
             dvmCompilerFlushAllRegs(cUnit);   /* Everything to home location */
             loadConstant(cUnit, r1, (int) classPtr );
@@ -2093,7 +2108,8 @@
     /* backward branch? */
     bool backwardBranch = (bb->taken->startOffset <= mir->offset);
 
-    if (backwardBranch && gDvmJit.genSuspendPoll) {
+    if (backwardBranch &&
+        (gDvmJit.genSuspendPoll || cUnit->jitMode == kJitLoop)) {
         genSuspendPoll(cUnit, mir);
     }
 
@@ -2426,6 +2442,7 @@
                 method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vC];
 
             if (fieldPtr == NULL) {
+                BAIL_LOOP_COMPILATION();
                 LOGE("Unexpected null instance field");
                 dvmAbort();
             }
@@ -2448,6 +2465,7 @@
               (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vC]);
 
             if (classPtr == NULL) {
+                BAIL_LOOP_COMPILATION();
                 LOGE("Unexpected null class");
                 dvmAbort();
             }
@@ -2499,6 +2517,7 @@
              * so that we can tell if it happens frequently.
              */
             if (classPtr == NULL) {
+                BAIL_LOOP_COMPILATION();
                 LOGD("null clazz in OP_INSTANCE_OF, single-stepping");
                 genInterpSingleStep(cUnit, mir);
                 break;
@@ -2627,7 +2646,8 @@
     /* backward branch? */
     bool backwardBranch = (bb->taken->startOffset <= mir->offset);
 
-    if (backwardBranch && gDvmJit.genSuspendPoll) {
+    if (backwardBranch &&
+        (gDvmJit.genSuspendPoll || cUnit->jitMode == kJitLoop)) {
         genSuspendPoll(cUnit, mir);
     }
 
@@ -4238,7 +4258,7 @@
             dvmCompilerAppendLIR(cUnit, (LIR *) &labelList[i]);
         }
 
-        if (bb->blockType == kTraceEntryBlock) {
+        if (bb->blockType == kEntryBlock) {
             labelList[i].opcode = kArmPseudoEntryBlock;
             if (bb->firstMIRInsn == NULL) {
                 continue;
@@ -4246,10 +4266,11 @@
               setupLoopEntryBlock(cUnit, bb,
                                   &labelList[bb->fallThrough->id]);
             }
-        } else if (bb->blockType == kTraceExitBlock) {
+        } else if (bb->blockType == kExitBlock) {
             labelList[i].opcode = kArmPseudoExitBlock;
             goto gen_fallthrough;
         } else if (bb->blockType == kDalvikByteCode) {
+            if (bb->hidden == true) continue;
             labelList[i].opcode = kArmPseudoNormalBlockLabel;
             /* Reset the register state */
             dvmCompilerResetRegPool(cUnit);
@@ -4297,8 +4318,8 @@
                     /* Make sure exception handling block is next */
                     labelList[i].opcode =
                         kArmPseudoPCReconstructionBlockLabel;
-                    assert (i == cUnit->numBlocks - 2);
-                    handlePCReconstruction(cUnit, &labelList[i+1]);
+                    handlePCReconstruction(cUnit,
+                                           &labelList[cUnit->puntBlock->id]);
                     break;
                 case kExceptionHandling:
                     labelList[i].opcode = kArmPseudoEHBlockLabel;
@@ -4510,7 +4531,7 @@
             }
         }
 
-        if (bb->blockType == kTraceEntryBlock) {
+        if (bb->blockType == kEntryBlock) {
             dvmCompilerAppendLIR(cUnit,
                                  (LIR *) cUnit->loopAnalysis->branchToBody);
             dvmCompilerAppendLIR(cUnit,