// => Top-Level routine (no jsr call before)
icq.add(start, new ArrayList<InstructionContext>());
// LOOP!
while (!icq.isEmpty()) {
InstructionContext u;
ArrayList<InstructionContext> ec;
if (!DEBUG) {
int r = random.nextInt(icq.size());
u = icq.getIC(r);
ec = icq.getEC(r);
icq.remove(r);
} else {
u = icq.getIC(0);
ec = icq.getEC(0);
icq.remove(0);
}
ArrayList<InstructionContext> oldchain = new ArrayList<InstructionContext>(ec);
ArrayList<InstructionContext> newchain = new ArrayList<InstructionContext>(ec);
newchain.add(u);
if (u.getInstruction().getInstruction() instanceof RET) {
// System.err.println(u);
// We can only follow _one_ successor, the one after the
// JSR that was recently executed.
RET ret = (RET) u.getInstruction().getInstruction();
ReturnaddressType t = (ReturnaddressType) u.getOutFrame(oldchain)
.getLocals()
.get(ret.getIndex());
InstructionContext theSuccessor = cfg.contextOf(t.getTarget());
// Sanity check
InstructionContext lastJSR = null;
int skip_jsr = 0;
for (int ss = oldchain.size() - 1; ss >= 0; ss--) {
if (skip_jsr < 0) {
throw new AssertionViolatedException("More RET than JSR in execution chain?!");
}
// System.err.println("+"+oldchain.get(ss));
if (oldchain.get(ss).getInstruction()
.getInstruction() instanceof JsrInstruction)
{
if (skip_jsr == 0) {
lastJSR = oldchain.get(ss);
break;
} else {
skip_jsr--;
}
}
if (oldchain.get(ss).getInstruction()
.getInstruction() instanceof RET)
{
skip_jsr++;
}
}
if (lastJSR == null) {
throw new AssertionViolatedException("RET without a JSR before in ExecutionChain?! EC: '"
+ oldchain + "'.");
}
JsrInstruction jsr = (JsrInstruction) lastJSR.getInstruction()
.getInstruction();
if (theSuccessor != cfg.contextOf(jsr.physicalSuccessor())) {
throw new AssertionViolatedException("RET '"
+ u.getInstruction()
+ "' info inconsistent: jump back to '"
+ theSuccessor + "' or '"
+ cfg.contextOf(jsr.physicalSuccessor()) + "'?");
}
if (theSuccessor.execute(u.getOutFrame(oldchain),
newchain,
icv,
ev))
{
icq.add(theSuccessor, new ArrayList<InstructionContext>(newchain));
}
} else {// "not a ret"
// Normal successors. Add them to the queue of successors.
InstructionContext[] succs = u.getSuccessors();
for (int s = 0; s < succs.length; s++) {
InstructionContext v = succs[s];
if (v.execute(u.getOutFrame(oldchain), newchain, icv, ev)) {
icq.add(v, new ArrayList<InstructionContext>(newchain));
}
}
}// end "not a ret"
// Exception Handlers. Add them to the queue of successors.
// [subroutines are never protected; mandated by JustIce]
ExceptionHandler[] exc_hds = u.getExceptionHandlers();
for (int s = 0; s < exc_hds.length; s++) {
InstructionContext v = cfg.contextOf(exc_hds[s].getHandlerStart());
// TODO: the "oldchain" and "newchain" is used to determine the
// subroutine
// we're in (by searching for the last JSR) by the
// InstructionContext
// implementation. Therefore, we should not use this chain
// mechanism
// when dealing with exception handlers.
// Example: a JSR with an exception handler as its successor
// does not
// mean we're in a subroutine if we go to the exception handler.
// We should address this problem later; by now we simply "cut"
// the chain
// by using an empty chain for the exception handlers.
// if (v.execute(new Frame(u.getOutFrame(oldchain).getLocals(),
// new OperandStack (u.getOutFrame().getStack().maxStack(),
// (exc_hds[s].getExceptionType()==null? Type.THROWABLE :
// exc_hds[s].getExceptionType())) ), newchain), icv, ev){
// icq.add(v, (ArrayList) newchain.clone());
if (v.execute(new Frame(u.getOutFrame(oldchain).getLocals(),
new OperandStack(u.getOutFrame(oldchain)
.getStack()
.maxStack(),
(exc_hds[s].getExceptionType() == null
? Type.THROWABLE