in asm-util/src/main/java/org/objectweb/asm/util/CheckFrameAnalyzer.java [118:218]
protected void init(final String owner, final MethodNode method) throws AnalyzerException {
insnList = method.instructions;
currentLocals = Type.getArgumentsAndReturnSizes(method.desc) >> 2;
if ((method.access & Opcodes.ACC_STATIC) != 0) {
currentLocals -= 1;
}
Frame<V>[] frames = getFrames();
Frame<V> currentFrame = frames[0];
expandFrames(owner, method, currentFrame);
for (int insnIndex = 0; insnIndex < insnList.size(); ++insnIndex) {
Frame<V> oldFrame = frames[insnIndex];
// Simulate the execution of this instruction.
AbstractInsnNode insnNode = null;
try {
insnNode = method.instructions.get(insnIndex);
int insnOpcode = insnNode.getOpcode();
int insnType = insnNode.getType();
if (insnType == AbstractInsnNode.LABEL
|| insnType == AbstractInsnNode.LINE
|| insnType == AbstractInsnNode.FRAME) {
checkFrame(insnIndex + 1, oldFrame, /* requireFrame = */ false);
} else {
currentFrame.init(oldFrame).execute(insnNode, interpreter);
if (insnNode instanceof JumpInsnNode) {
if (insnOpcode == JSR) {
throw new AnalyzerException(insnNode, "JSR instructions are unsupported");
}
JumpInsnNode jumpInsn = (JumpInsnNode) insnNode;
int targetInsnIndex = insnList.indexOf(jumpInsn.label);
checkFrame(targetInsnIndex, currentFrame, /* requireFrame = */ true);
if (insnOpcode == GOTO) {
endControlFlow(insnIndex);
} else {
checkFrame(insnIndex + 1, currentFrame, /* requireFrame = */ false);
}
} else if (insnNode instanceof LookupSwitchInsnNode) {
LookupSwitchInsnNode lookupSwitchInsn = (LookupSwitchInsnNode) insnNode;
int targetInsnIndex = insnList.indexOf(lookupSwitchInsn.dflt);
checkFrame(targetInsnIndex, currentFrame, /* requireFrame = */ true);
for (int i = 0; i < lookupSwitchInsn.labels.size(); ++i) {
LabelNode label = lookupSwitchInsn.labels.get(i);
targetInsnIndex = insnList.indexOf(label);
currentFrame.initJumpTarget(insnOpcode, label);
checkFrame(targetInsnIndex, currentFrame, /* requireFrame = */ true);
}
endControlFlow(insnIndex);
} else if (insnNode instanceof TableSwitchInsnNode) {
TableSwitchInsnNode tableSwitchInsn = (TableSwitchInsnNode) insnNode;
int targetInsnIndex = insnList.indexOf(tableSwitchInsn.dflt);
currentFrame.initJumpTarget(insnOpcode, tableSwitchInsn.dflt);
checkFrame(targetInsnIndex, currentFrame, /* requireFrame = */ true);
newControlFlowEdge(insnIndex, targetInsnIndex);
for (int i = 0; i < tableSwitchInsn.labels.size(); ++i) {
LabelNode label = tableSwitchInsn.labels.get(i);
currentFrame.initJumpTarget(insnOpcode, label);
targetInsnIndex = insnList.indexOf(label);
checkFrame(targetInsnIndex, currentFrame, /* requireFrame = */ true);
}
endControlFlow(insnIndex);
} else if (insnOpcode == RET) {
throw new AnalyzerException(insnNode, "RET instructions are unsupported");
} else if (insnOpcode != ATHROW && (insnOpcode < IRETURN || insnOpcode > RETURN)) {
checkFrame(insnIndex + 1, currentFrame, /* requireFrame = */ false);
} else {
endControlFlow(insnIndex);
}
}
List<TryCatchBlockNode> insnHandlers = getHandlers(insnIndex);
if (insnHandlers != null) {
for (TryCatchBlockNode tryCatchBlock : insnHandlers) {
Type catchType;
if (tryCatchBlock.type == null) {
catchType = Type.getObjectType("java/lang/Throwable");
} else {
catchType = Type.getObjectType(tryCatchBlock.type);
}
Frame<V> handler = newFrame(oldFrame);
handler.clearStack();
handler.push(interpreter.newExceptionValue(tryCatchBlock, handler, catchType));
checkFrame(insnList.indexOf(tryCatchBlock.handler), handler, /* requireFrame = */ true);
}
}
if (!hasNextJvmInsnOrFrame(insnIndex)) {
break;
}
} catch (AnalyzerException e) {
throw new AnalyzerException(
e.node, "Error at instruction " + insnIndex + ": " + e.getMessage(), e);
} catch (RuntimeException e) {
// DontCheck(IllegalCatch): can't be fixed, for backward compatibility.
throw new AnalyzerException(
insnNode, "Error at instruction " + insnIndex + ": " + e.getMessage(), e);
}
}
}