CodeIterator iterator = context.behavior.getMethodInfo().getCodeAttribute().iterator();
iterator.move(from);
Stack currentStack = stack.copy();
while(iterator.hasNext()) {
int index = iterator.next();
Op op = Opcodes.OPCODES.get(iterator.byteAt(index)).init(context, index);
trace.append("\n").append(index).append(":").append(op.getName()).append(" --> ");
Frame frame = frames[index];
frame.isAccessible = true;
frame.stackBefore = currentStack.copy();
frame.decodedOp = op.decode(context, index);
if(frame.decodedOp instanceof DecodedBranchOp)
trace.append(" [jump to ").append(((DecodedBranchOp)frame.decodedOp).getJump()).append("] ");
if(frame.decodedOp instanceof DecodedMethodInvocationOp)
trace.append(" [params = ").append(StackElementLength.add(((DecodedMethodInvocationOp)frame.decodedOp).getPops())).append(" -> ").append(Arrays.toString(((DecodedMethodInvocationOp)frame.decodedOp).getParameterTypes())).append("] ");
frame.decodedOp.simulate(currentStack);
frame.stackAfter = currentStack.copy();
trace.append(frame.stackAfter);
if( !(op instanceof ExitOpcode || (op instanceof BranchOpCode && !((BranchOpCode)op).isConditional()) || op instanceof SwitchOpcode) )
trace.append(". Next is ").append(iterator.lookAhead());
if(LOGGER.isTraceEnabled())
LOGGER.trace(trace);
if(op instanceof ExitOpcode)
return;
if(op instanceof BranchOpCode) {
BranchOpCode branchOpCode = op.as(BranchOpCode.class);
int jump = branchOpCode.decode(context, index).getJump();
analyze(jump, frame.stackAfter);
if(!branchOpCode.isConditional())
return;
}
if(op instanceof SwitchOpcode) {
SwitchOpcode switchOpcode = op.as(SwitchOpcode.class);
DecodedSwitchOpcode decodedSwitchOpcode = switchOpcode.decode(context, index);
for(int offset : decodedSwitchOpcode.offsets)
analyze(offset, frame.stackAfter);
analyze(decodedSwitchOpcode.defaultOffset, frame.stackAfter);
return;