Merge "Bug fix for control-flow construction involving nested loops."
diff --git a/tests/083-jit-regressions/expected.txt b/tests/083-jit-regressions/expected.txt
index 1f30d21..4b9ad5b 100644
--- a/tests/083-jit-regressions/expected.txt
+++ b/tests/083-jit-regressions/expected.txt
@@ -1,3 +1,4 @@
b2296099 passes
b2302318 passes
b2487514 passes
+b5884080 passes
diff --git a/tests/083-jit-regressions/info.txt b/tests/083-jit-regressions/info.txt
index b791aba..00c24ee 100644
--- a/tests/083-jit-regressions/info.txt
+++ b/tests/083-jit-regressions/info.txt
@@ -8,3 +8,4 @@
2296099 JIT shift bug
2302318 Crash during spin-on-suspend testing
2487514 Missed exception in PriorityBlockingQueueTest.testToArray1_BadArg
+5884080 ICS JIT regression in nested loop formation
diff --git a/tests/083-jit-regressions/src/Main.java b/tests/083-jit-regressions/src/Main.java
index 1f1dee3..3b596db 100644
--- a/tests/083-jit-regressions/src/Main.java
+++ b/tests/083-jit-regressions/src/Main.java
@@ -24,6 +24,7 @@
b2296099Test();
b2302318Test();
b2487514Test();
+ b5884080Test();
}
static void b2296099Test() throws Exception {
@@ -105,6 +106,26 @@
" (expecting 1000)");
}
}
+
+ static void b5884080Test() {
+ int vA = 1;
+
+ int l = 0;
+ do
+ {
+ int k = 0;
+ do
+ vA += 1;
+ while(++k < 100);
+ } while(++l < 1000);
+ if (vA == 100001) {
+ System.out.println("b5884080 passes");
+ }
+ else {
+ System.out.println("b5884080 fails: vA is " + vA +
+ " (expecting 100001)");
+ }
+ }
}
class SpinThread extends Thread {
diff --git a/vm/compiler/Frontend.cpp b/vm/compiler/Frontend.cpp
index a36eedb..e0226e9 100644
--- a/vm/compiler/Frontend.cpp
+++ b/vm/compiler/Frontend.cpp
@@ -511,7 +511,8 @@
/* Split an existing block from the specified code offset into two */
static BasicBlock *splitBlock(CompilationUnit *cUnit,
unsigned int codeOffset,
- BasicBlock *origBlock)
+ BasicBlock *origBlock,
+ BasicBlock **immedPredBlockP)
{
MIR *insn = origBlock->firstMIRInsn;
while (insn) {
@@ -573,16 +574,29 @@
insn->prev->next = NULL;
insn->prev = NULL;
+
+ /*
+ * Update the immediate predecessor block pointer so that outgoing edges
+ * can be applied to the proper block.
+ */
+ if (immedPredBlockP) {
+ assert(*immedPredBlockP == origBlock);
+ *immedPredBlockP = bottomBlock;
+ }
return bottomBlock;
}
/*
* Given a code offset, find out the block that starts with it. If the offset
- * is in the middle of an existing block, split it into two.
+ * is in the middle of an existing block, split it into two. If immedPredBlockP
+ * is non-null and is the block being split, update *immedPredBlockP to point
+ * to the bottom block so that outgoing edges can be setup properly (by the
+ * caller).
*/
static BasicBlock *findBlock(CompilationUnit *cUnit,
unsigned int codeOffset,
- bool split, bool create)
+ bool split, bool create,
+ BasicBlock **immedPredBlockP)
{
GrowableList *blockList = &cUnit->blockList;
BasicBlock *bb;
@@ -596,7 +610,9 @@
if ((split == true) && (codeOffset > bb->startOffset) &&
(bb->lastMIRInsn != NULL) &&
(codeOffset <= bb->lastMIRInsn->offset)) {
- BasicBlock *newBB = splitBlock(cUnit, codeOffset, bb);
+ BasicBlock *newBB = splitBlock(cUnit, codeOffset, bb,
+ bb == *immedPredBlockP ?
+ immedPredBlockP : NULL);
return newBB;
}
}
@@ -873,7 +889,9 @@
/* split */
false,
/* create */
- true);
+ true,
+ /* immedPredBlockP */
+ NULL);
}
offset = dexCatchIteratorGetEndOffset(&iterator, pCode);
@@ -917,7 +935,9 @@
/* split */
true,
/* create */
- true);
+ true,
+ /* immedPredBlockP */
+ &curBlock);
curBlock->taken = takenBlock;
dvmCompilerSetBit(takenBlock->predecessors, curBlock->id);
@@ -939,7 +959,9 @@
*/
true,
/* create */
- true);
+ true,
+ /* immedPredBlockP */
+ &curBlock);
curBlock->fallThrough = fallthroughBlock;
dvmCompilerSetBit(fallthroughBlock->predecessors, curBlock->id);
} else if (codePtr < codeEnd) {
@@ -949,7 +971,9 @@
/* split */
false,
/* create */
- true);
+ true,
+ /* immedPredBlockP */
+ NULL);
}
}
}
@@ -1013,7 +1037,9 @@
/* split */
true,
/* create */
- true);
+ true,
+ /* immedPredBlockP */
+ &curBlock);
SuccessorBlockInfo *successorBlockInfo =
(SuccessorBlockInfo *) dvmCompilerNew(sizeof(SuccessorBlockInfo),
false);
@@ -1031,7 +1057,9 @@
/* split */
false,
/* create */
- true);
+ true,
+ /* immedPredBlockP */
+ NULL);
curBlock->fallThrough = fallthroughBlock;
dvmCompilerSetBit(fallthroughBlock->predecessors, curBlock->id);
}
@@ -1074,7 +1102,9 @@
/* split */
false,
/* create */
- false);
+ false,
+ /* immedPredBlockP */
+ NULL);
SuccessorBlockInfo *successorBlockInfo =
(SuccessorBlockInfo *) dvmCompilerNew(sizeof(SuccessorBlockInfo),
@@ -1108,7 +1138,9 @@
/* split */
false,
/* create */
- true);
+ true,
+ /* immedPredBlockP */
+ NULL);
/*
* OP_THROW and OP_THROW_VERIFICATION_ERROR are unconditional
* branches.
@@ -1226,7 +1258,9 @@
/* split */
false,
/* create */
- true);
+ true,
+ /* immedPredBlockP */
+ NULL);
}
}
} else if (flags & kInstrCanThrow) {
@@ -1240,7 +1274,9 @@
/* split */
false,
/* create */
- false);
+ false,
+ /* immedPredBlockP */
+ NULL);
if (nextBlock) {
/*
* The next instruction could be the target of a previously parsed
@@ -1380,7 +1416,9 @@
/* split */
false,
/* create */
- false);
+ false,
+ /* immedPredBlockP */
+ NULL);
if (nextBlock) {
/*
* The next instruction could be the target of a previously parsed
diff --git a/vm/mterp/common/asm-constants.h b/vm/mterp/common/asm-constants.h
index bbc043c..e1a4df6 100644
--- a/vm/mterp/common/asm-constants.h
+++ b/vm/mterp/common/asm-constants.h
@@ -193,7 +193,7 @@
MTERP_OFFSET(offThread_jniLocal_topCookie, \
Thread, jniLocalRefTable.segmentState.all, 168)
#if defined(WITH_SELF_VERIFICATION)
-MTERP_OFFSET(offThread_shadowSpace, Thread, shadowSpace, 192)
+MTERP_OFFSET(offThread_shadowSpace, Thread, shadowSpace, 188)
#endif
#else
MTERP_OFFSET(offThread_jniLocal_topCookie, \