.getMethod("boolean hasNext()");
for (Iterator methods = theClass.getMethods().iterator(); methods
.hasNext();) {
SootMethod method = (SootMethod) methods.next();
JimpleBody body = (JimpleBody) method.retrieveActiveBody();
BlockGraph graph = new CompleteBlockGraph(body);
for (Iterator blocks = graph.iterator(); blocks.hasNext();) {
Block block = (Block) blocks.next();
// System.out.println("body = " + block);
// filter out anything that doesn't look like a loop body.
if ((block.getPreds().size() != 1)
|| (block.getSuccs().size() != 1)) {
continue;
}
// filter out anything that isn't attached to something
// that looks like a conditional jump.
Block whileCond = (Block) block.getSuccs().get(0);
// System.out.println("cond = " + whileCond);
if ((whileCond != block.getPreds().get(0))
|| (whileCond.getPreds().size() != 2)
|| (whileCond.getSuccs().size() != 2)) {
continue;
}
// filter out anything that doesn't start with a call
// to hasNext().
if (!(whileCond.getHead() instanceof DefinitionStmt)) {
continue;
}
DefinitionStmt stmt = (DefinitionStmt) whileCond.getHead();
if (!(stmt.getRightOp() instanceof InterfaceInvokeExpr)) {
continue;
}
InterfaceInvokeExpr expr = (InterfaceInvokeExpr) stmt
.getRightOp();
if (expr.getMethod() != iteratorHasNextMethod) {
continue;
}
// At this point we know we have a while (hasNext()) loop.
// Now go check for iterator is defined... it should be just
// above
Local iteratorLocal = (Local) expr.getBase();
Block whilePredecessor = (Block) whileCond.getPreds().get(0);
if (whilePredecessor == block) {
whilePredecessor = (Block) whileCond.getPreds().get(1);
}
// System.out.println("whilePredecessor = " + whilePredecessor);
Unit unit = whilePredecessor.getTail();
boolean found = false;
// walk backwards until we find a definition of the iterator.
while ((unit != whilePredecessor.getHead()) && !found) {
if (unit instanceof DefinitionStmt
&& ((DefinitionStmt) unit).getLeftOp().equals(
iteratorLocal)) {
found = true;
} else {
unit = whilePredecessor.getPredOf(unit);
}
}
// System.out.println("iterator def = " + unit);
DefinitionStmt iteratorDefinition = ((DefinitionStmt) unit);
if (!(iteratorDefinition.getRightOp() instanceof InterfaceInvokeExpr)
|| !((InterfaceInvokeExpr) iteratorDefinition
.getRightOp()).getMethod().getName().equals(
"iterator")) {
continue;
}
Local collectionLocal = (Local) ((InterfaceInvokeExpr) iteratorDefinition
.getRightOp()).getBase();
// System.out.println("collection Local = " + collectionLocal);
found = false;
// Walk backward again until we reach the definition
// of the collection.
while ((unit != whilePredecessor.getHead()) && !found) {
if (unit instanceof DefinitionStmt
&& ((DefinitionStmt) unit).getLeftOp().equals(
collectionLocal)) {
found = true;
} else {
unit = whilePredecessor.getPredOf(unit);
}
}
// System.out.println("collection def = " + unit);
// System.out.println("field = " + field);
DefinitionStmt collectionDefinition = ((DefinitionStmt) unit);
if (!(collectionDefinition.getRightOp() instanceof FieldRef)
|| (((FieldRef) collectionDefinition.getRightOp())
.getField() != field)) {
continue;
}
// FINALLY we know we've found something we can unroll... :)
// System.out.println("is unrollable...");
// There should be a jump from the predecessor to the
// condition. Redirect this jump to the body.
whileCond.getHead().redirectJumpsToThisTo(block.getHead());
Local thisLocal = body.getThisLocal();
Chain units = body.getUnits();
List blockStmtList = new LinkedList();
// pull the statements that we are inlining out of the block
// so that we can copy them. Note that this also removes
// them from the method body.
Unit insertPoint = (Unit) units.getSuccOf(block.getTail());
for (Iterator blockStmts = block.iterator(); blockStmts
.hasNext();) {
Stmt original = (Stmt) blockStmts.next();
blockStmtList.add(original);
blockStmts.remove();
}
// Remove the jump that should be the final statement.
blockStmtList.remove(blockStmtList
.get(blockStmtList.size() - 1));
// Loop through and unroll the loop body once for
// every element of the field list.
for (Iterator fields = fieldList.iterator(); fields.hasNext();) {
SootField insertField = (SootField) fields.next();
for (Iterator blockStmts = blockStmtList.iterator(); blockStmts
.hasNext();) {
// clone each statement
Stmt original = (Stmt) blockStmts.next();
Stmt clone = (Stmt) original.clone();
// If the statement is a call to the next() method,
// then inline it with the next value of the iterator.
for (Iterator boxes = clone.getUseBoxes().iterator(); boxes
.hasNext();) {
ValueBox box = (ValueBox) boxes.next();
Value value = box.getValue();
if (value instanceof InvokeExpr) {
InvokeExpr r = (InvokeExpr) value;
if (r.getMethod() == iteratorNextMethod) {
box.setValue(Jimple.v()
.newInstanceFieldRef(thisLocal,
insertField.makeRef()));
}
}
}
units.insertBefore(clone, insertPoint);
}
}
// remove the conditional
for (Iterator blockStmts = whileCond.iterator(); blockStmts
.hasNext();) {
/*Stmt original = (Stmt)*/blockStmts.next();
blockStmts.remove();
}
body.getUnits().remove(iteratorDefinition);
// Find while loops.
// This code modified from WhileMatcher.
/*