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,