/* 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) {
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;
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;
}
}
/* split */
false,
/* create */
- true);
+ true,
+ /* immedPredBlockP */
+ NULL);
}
offset = dexCatchIteratorGetEndOffset(&iterator, pCode);
/* split */
true,
/* create */
- true);
+ true,
+ /* immedPredBlockP */
+ &curBlock);
curBlock->taken = takenBlock;
dvmCompilerSetBit(takenBlock->predecessors, curBlock->id);
*/
true,
/* create */
- true);
+ true,
+ /* immedPredBlockP */
+ &curBlock);
curBlock->fallThrough = fallthroughBlock;
dvmCompilerSetBit(fallthroughBlock->predecessors, curBlock->id);
} else if (codePtr < codeEnd) {
/* split */
false,
/* create */
- true);
+ true,
+ /* immedPredBlockP */
+ NULL);
}
}
}
/* split */
true,
/* create */
- true);
+ true,
+ /* immedPredBlockP */
+ &curBlock);
SuccessorBlockInfo *successorBlockInfo =
(SuccessorBlockInfo *) dvmCompilerNew(sizeof(SuccessorBlockInfo),
false);
/* split */
false,
/* create */
- true);
+ true,
+ /* immedPredBlockP */
+ NULL);
curBlock->fallThrough = fallthroughBlock;
dvmCompilerSetBit(fallthroughBlock->predecessors, curBlock->id);
}
/* split */
false,
/* create */
- false);
+ false,
+ /* immedPredBlockP */
+ NULL);
SuccessorBlockInfo *successorBlockInfo =
(SuccessorBlockInfo *) dvmCompilerNew(sizeof(SuccessorBlockInfo),
/* split */
false,
/* create */
- true);
+ true,
+ /* immedPredBlockP */
+ NULL);
/*
* OP_THROW and OP_THROW_VERIFICATION_ERROR are unconditional
* branches.
/* split */
false,
/* create */
- true);
+ true,
+ /* immedPredBlockP */
+ NULL);
}
}
} else if (flags & kInstrCanThrow) {
/* split */
false,
/* create */
- false);
+ false,
+ /* immedPredBlockP */
+ NULL);
if (nextBlock) {
/*
* The next instruction could be the target of a previously parsed
/* split */
false,
/* create */
- false);
+ false,
+ /* immedPredBlockP */
+ NULL);
if (nextBlock) {
/*
* The next instruction could be the target of a previously parsed