in bytekit-core/src/main/java/com/alibaba/bytekit/asm/MethodProcessor.java [668:761]
public void inline(String owner, MethodNode toInlineMethodNode, boolean removeLineNumber) {
ListIterator<AbstractInsnNode> originMethodIter = this.methodNode.instructions.iterator();
while(originMethodIter.hasNext()) {
AbstractInsnNode originMethodInsnNode = originMethodIter.next();
if (originMethodInsnNode instanceof MethodInsnNode) {
MethodInsnNode methodInsnNode = (MethodInsnNode) originMethodInsnNode;
if (methodInsnNode.owner.equals(owner) && methodInsnNode.name.equals(toInlineMethodNode.name)
&& methodInsnNode.desc.equals(toInlineMethodNode.desc)) {
// 要copy一份,否则inline多次会出问题
MethodNode tmpToInlineMethodNode = AsmUtils.copy(toInlineMethodNode);
if (removeLineNumber) {
tmpToInlineMethodNode = AsmUtils.removeLineNumbers(tmpToInlineMethodNode);
}
LabelNode end = new LabelNode();
this.methodNode.instructions.insert(methodInsnNode, end);
InsnList instructions = new InsnList();
// 要先记录好当前的 maxLocals ,然后再依次把 栈上的 args保存起来 ,后面调整 VarInsnNode index里,要加上当前的 maxLocals
// save args to local vars
int currentMaxLocals = this.nextLocals;
int off = (tmpToInlineMethodNode.access & Opcodes.ACC_STATIC) != 0 ? 0 : 1;
Type[] args = Type.getArgumentTypes(tmpToInlineMethodNode.desc);
int argsOff = off;
for(int i = 0; i < args.length; ++i) {
argsOff += args[i].getSize();
}
// 记录新的 maxLocals
this.nextLocals += argsOff;
methodNode.maxLocals = this.nextLocals;
for(int i = args.length - 1; i >= 0; --i) {
argsOff -= args[i].getSize();
// this.visitVarInsn(args[i].getOpcode(Opcodes.ISTORE), argsOff);
AsmOpUtils.storeVar(instructions, args[i], currentMaxLocals + argsOff);
}
// this
if (off > 0) {
// this.visitVarInsn(Opcodes.ASTORE, 0);
AsmOpUtils.storeVar(instructions, OBJECT_TYPE, currentMaxLocals);
}
ListIterator<AbstractInsnNode> inlineIterator = tmpToInlineMethodNode.instructions.iterator();
while(inlineIterator.hasNext()) {
AbstractInsnNode abstractInsnNode = inlineIterator.next();
if(abstractInsnNode instanceof FrameNode) {
continue;
}
//修改inline代码中的使用到局部变量的指令的var操作数(变量slot)
if(abstractInsnNode instanceof VarInsnNode) {
VarInsnNode varInsnNode = (VarInsnNode) abstractInsnNode;
varInsnNode.var += currentMaxLocals;
} else if (abstractInsnNode instanceof IincInsnNode) {
IincInsnNode iincInsnNode = (IincInsnNode) abstractInsnNode;
iincInsnNode.var += currentMaxLocals;
}
int opcode = abstractInsnNode.getOpcode();
if (opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) {
// super.visitJumpInsn(Opcodes.GOTO, end);
// instructions.add(new JumpInsnNode(Opcodes.GOTO, end));
inlineIterator.remove();
instructions.add(new JumpInsnNode(Opcodes.GOTO, end));
continue;
}
inlineIterator.remove();
instructions.add(abstractInsnNode);
}
// 插入inline之后的代码,再删除掉原来的 MethodInsnNode
this.methodNode.instructions.insertBefore(methodInsnNode, instructions);
originMethodIter.remove();
// try catch 块加上,然后排序
if(this.methodNode.tryCatchBlocks != null && tmpToInlineMethodNode.tryCatchBlocks != null) {
this.methodNode.tryCatchBlocks.addAll(tmpToInlineMethodNode.tryCatchBlocks);
}
this.sortTryCatchBlock();
}
}
}
}