}
private void analyse(ClassGen clazz, MethodGen method, ControlFlowGraph cfg,
InstConstraintVisitor icv, ExecutionVisitor ev) {
// build the initial frame situation for this method.
Frame vanillaFrame = new Frame(method.getMaxLocals(), method.getMaxStack());
if (!method.isStatic()) {
if (method.getName().equals(Constants.CONSTRUCTOR_NAME)) {
Frame._this = new UninitializedObjectType(new ObjectType(clazz.getClassName()));
vanillaFrame.getLocals().set(0, new UninitializedObjectType(new ObjectType(clazz.getClassName())));
} else {
Frame._this = null;
vanillaFrame.getLocals().set(0, new ObjectType(clazz.getClassName()));
}
}
// fill local variables with parameter types
Type[] argtypes = method.getArgumentTypes();
int twoslotoffset = 0;
for (int j = 0; j < argtypes.length; j++) {
if ((argtypes[j] == Type.SHORT) ||
(argtypes[j] == Type.BYTE) ||
(argtypes[j] == Type.CHAR) ||
(argtypes[j] == Type.BOOLEAN)) {
argtypes[j] = Type.INT;
}
vanillaFrame.getLocals().set(twoslotoffset + j + (method.isStatic() ? 0 : 1), argtypes[j]);
if (argtypes[j].getSize() == 2) {
twoslotoffset++;
vanillaFrame.getLocals().set(twoslotoffset + j + (method.isStatic() ? 0 : 1), Type.UNKNOWN);
}
}
icv.setMethodGen(method);
Vector ics = new Vector(); // Type: InstructionContext
Vector ecs = new Vector(); // Type: ArrayList (of InstructionContext)
InstructionContext start = cfg.contextOf(method.getInstructionList().getStart());
start.execute(vanillaFrame, new ArrayList(), icv, ev);
// new ArrayList() <=> no Instruction was executed before
// => Top-Level routine (no jsr call before)
ics.add(start);
ecs.add(new ArrayList());
while (!ics.isEmpty()) {
InstructionContext u = (InstructionContext)ics.remove(0);
ArrayList ec = (ArrayList)ecs.remove(0);
ArrayList oldchain = (ArrayList)(ec.clone());
ArrayList newchain = (ArrayList)(ec.clone());
newchain.add(u);
if ((u.getInstruction().getInstruction()) instanceof RET) {
// 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());
if (theSuccessor.execute(u.getOutFrame(oldchain), newchain, icv, ev)) {
ics.add(theSuccessor);
ecs.add(newchain.clone());
}
} 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)) {
ics.add(v);
ecs.add(newchain.clone());
}
}
}
// Exception Handlers. Add them to the queue of successors.
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.
LocalVariables newLocals = u.getOutFrame(oldchain).getLocals();
OperandStack newStack = new OperandStack(
u.getOutFrame(oldchain).getStack().maxStack(),
(exc_hds[s].getExceptionType() == null
? Type.THROWABLE
: exc_hds[s].getExceptionType()));
Frame newFrame = new Frame(newLocals, newStack);
if (v.execute(newFrame, new ArrayList(), icv, ev)) {
ics.add(v);
ecs.add(new ArrayList());
}