remover.perform();
}
}
private static void processExceptionHandler(MethodNode mth, BlockNode block) {
ExcHandlerAttr handlerAttr = block.get(AType.EXC_HANDLER);
if (handlerAttr == null) {
return;
}
ExceptionHandler excHandler = handlerAttr.getHandler();
boolean noExitNode = true; // check if handler has exit edge to block not from this handler
boolean reThrow = false;
for (BlockNode excBlock : excHandler.getBlocks()) {
if (noExitNode) {
noExitNode = excHandler.getBlocks().containsAll(excBlock.getCleanSuccessors());
}
List<InsnNode> insns = excBlock.getInstructions();
int size = insns.size();
if (excHandler.isCatchAll()
&& size > 0
&& insns.get(size - 1).getType() == InsnType.THROW) {
reThrow = true;
InstructionRemover.remove(mth, excBlock, size - 1);
// move not removed instructions to 'finally' block
if (!insns.isEmpty()) {
// TODO: support instructions from several blocks
// tryBlock.setFinalBlockFromInsns(mth, insns);
// TODO: because of incomplete realization don't extract final block,
// just remove unnecessary instructions
insns.clear();
}
}
}
List<InsnNode> blockInsns = block.getInstructions();
if (!blockInsns.isEmpty()) {
InsnNode insn = blockInsns.get(0);
if (insn.getType() == InsnType.MOVE_EXCEPTION) {
// result arg used both in this insn and exception handler,
RegisterArg resArg = insn.getResult();
ArgType type = excHandler.isCatchAll() ? ArgType.THROWABLE : excHandler.getCatchType().getType();
String name = excHandler.isCatchAll() ? "th" : "e";
if (resArg.getName() == null) {
resArg.setName(name);
}
SSAVar sVar = insn.getResult().getSVar();
if (sVar.getUseCount() == 0) {
excHandler.setArg(new NamedArg(name, type));
InstructionRemover.remove(mth, block, 0);
} else if (sVar.isUsedInPhi()) {
// exception var moved to external variable => replace with 'move' insn
InsnNode moveInsn = new InsnNode(InsnType.MOVE, 1);
moveInsn.setResult(insn.getResult());
NamedArg namedArg = new NamedArg(name, type);
moveInsn.addArg(namedArg);
excHandler.setArg(namedArg);
replaceInsn(block, 0, moveInsn);
}
}
}
int totalSize = 0;
for (BlockNode excBlock : excHandler.getBlocks()) {
totalSize += excBlock.getInstructions().size();
}
if (totalSize == 0 && noExitNode && reThrow) {
handlerAttr.getTryBlock().removeHandler(mth, excHandler);
}
}