in bytekit-core/src/main/java/com/alibaba/bytekit/asm/location/Location.java [244:399]
public StackSaver getStackSaver() {
StackSaver stackSaver = null;
if(whenComplete) {
stackSaver = new StackSaver() {
@Override
public void store(InsnList instructions, BindingContext bindingContext) {
AbstractInsnNode insnNode = bindingContext.getLocation().getInsnNode();
MethodProcessor methodProcessor = bindingContext.getMethodProcessor();
if (insnNode instanceof MethodInsnNode) {
MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode;
String uniqueNameForMethod = AsmUtils.uniqueNameForMethod(methodInsnNode.owner, methodInsnNode.name,
methodInsnNode.desc);
Type invokeReturnType = Type.getMethodType(methodInsnNode.desc).getReturnType();
if(!invokeReturnType.equals(Type.VOID_TYPE)) {
LocalVariableNode invokeReturnVariableNode = methodProcessor.initInvokeReturnVariableNode(
uniqueNameForMethod, invokeReturnType);
AsmOpUtils.storeVar(instructions, invokeReturnType, invokeReturnVariableNode.index);
}
} else {
throw new IllegalArgumentException(
"InvokeReturnBinding location is not MethodInsnNode, insnNode: " + insnNode);
}
}
@Override
public void load(InsnList instructions, BindingContext bindingContext) {
AbstractInsnNode insnNode = bindingContext.getLocation().getInsnNode();
MethodProcessor methodProcessor = bindingContext.getMethodProcessor();
if (insnNode instanceof MethodInsnNode) {
MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode;
String uniqueNameForMethod = AsmUtils.uniqueNameForMethod(methodInsnNode.owner, methodInsnNode.name,
methodInsnNode.desc);
Type invokeReturnType = Type.getMethodType(methodInsnNode.desc).getReturnType();
if(!invokeReturnType.equals(Type.VOID_TYPE)) {
LocalVariableNode invokeReturnVariableNode = methodProcessor.initInvokeReturnVariableNode(
uniqueNameForMethod, invokeReturnType);
AsmOpUtils.loadVar(instructions, invokeReturnType, invokeReturnVariableNode.index);
}
} else {
throw new IllegalArgumentException(
"InvokeReturnBinding location is not MethodInsnNode, insnNode: " + insnNode);
}
}
@Override
public Type getType(BindingContext bindingContext) {
MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode;
return Type.getMethodType(methodInsnNode.desc).getReturnType();
}
};
}else {
stackSaver = new StackSaver() {
@Override
public void store(InsnList instructions, BindingContext bindingContext) {
// 需要从要调用的 函数的 des ,找到参数的类型,再从栈上一个个吐出来,再保存到数组里
Location location = bindingContext.getLocation();
MethodProcessor methodProcessor = bindingContext.getMethodProcessor();
if(location instanceof InvokeLocation) {
InvokeLocation invokeLocation = (InvokeLocation) location;
// 如果是非 static的,会有this指针
MethodInsnNode methodInsnNode = (MethodInsnNode)invokeLocation.getInsnNode();
Type methodType = Type.getMethodType(methodInsnNode.desc);
boolean isStatic = AsmUtils.isStatic(methodInsnNode);
Type[] argumentTypes = methodType.getArgumentTypes();
// // 如果是非static,则存放到数组的index要多 1
// AsmOpUtils.push(instructions, argumentTypes.length + (isStatic ? 0 : 1));
// AsmOpUtils.newArray(instructions, AsmOpUtils.OBJECT_TYPE);
// LocalVariableNode invokeArgsVariableNode = methodProcessor.initInvokeArgsVariableNode();
// AsmOpUtils.storeVar(instructions, AsmOpUtils.OBJECT_ARRAY_TYPE, invokeArgsVariableNode.index);
// 从invoke的参数的后面,一个个存到数组里
// for(int i = argumentTypes.length - 1; i >= 0 ; --i) {
// AsmOpUtils.loadVar(instructions, AsmOpUtils.OBJECT_ARRAY_TYPE, invokeArgsVariableNode.index);
//
// AsmOpUtils.swap(instructions, argumentTypes[i], AsmOpUtils.OBJECT_ARRAY_TYPE);
// // 如果是非static,则存放到数组的index要多 1
// AsmOpUtils.push(instructions, i + (isStatic ? 0 : 1));
// AsmOpUtils.swap(instructions, argumentTypes[i], Type.INT_TYPE);
//
// AsmOpUtils.box(instructions, argumentTypes[i]);
// AsmOpUtils.arrayStore(instructions, AsmOpUtils.OBJECT_TYPE);
//
// }
// 处理this
// if(!isStatic) {
// AsmOpUtils.loadVar(instructions, AsmOpUtils.OBJECT_ARRAY_TYPE, invokeArgsVariableNode.index);
//
// AsmOpUtils.swap(instructions, AsmOpUtils.OBJECT_TYPE, AsmOpUtils.OBJECT_ARRAY_TYPE);
// AsmOpUtils.push(instructions, 0);
// AsmOpUtils.swap(instructions, AsmOpUtils.OBJECT_TYPE, Type.INT_TYPE);
// AsmOpUtils.arrayStore(instructions, AsmOpUtils.OBJECT_TYPE);
// }
}else {
throw new IllegalArgumentException("location is not a InvokeLocation, location: " + location);
}
}
@Override
public void load(InsnList instructions, BindingContext bindingContext) {
// 从数组里取出来,一个个再放到栈上,要检查是否要unbox
Location location = bindingContext.getLocation();
MethodProcessor methodProcessor = bindingContext.getMethodProcessor();
LocalVariableNode invokeArgsVariableNode = methodProcessor.initInvokeArgsVariableNode();
if(location instanceof InvokeLocation) {
InvokeLocation invokeLocation = (InvokeLocation) location;
// 如果是非 static的,会有this指针
MethodInsnNode methodInsnNode = (MethodInsnNode)invokeLocation.getInsnNode();
Type methodType = Type.getMethodType(methodInsnNode.desc);
boolean isStatic = AsmUtils.isStatic(methodInsnNode);
Type[] argumentTypes = methodType.getArgumentTypes();
// if(!isStatic) {
// // 取出this
// AsmOpUtils.loadVar(instructions, AsmOpUtils.OBJECT_ARRAY_TYPE, invokeArgsVariableNode.index);
// AsmOpUtils.push(instructions, 0);
// AsmOpUtils.arrayLoad(instructions, AsmOpUtils.OBJECT_TYPE);
// AsmOpUtils.checkCast(instructions, Type.getObjectType(methodInsnNode.owner));
// }
//
// for(int i = 0; i < argumentTypes.length; ++i) {
// AsmOpUtils.loadVar(instructions, AsmOpUtils.OBJECT_ARRAY_TYPE, invokeArgsVariableNode.index);
// AsmOpUtils.push(instructions, i + (isStatic ? 0 : 1));
// AsmOpUtils.arrayLoad(instructions, AsmOpUtils.OBJECT_TYPE);
// // TODO 这里直接 unbox 就可以了??unbox里带有 check cast
// if(AsmOpUtils.needBox(argumentTypes[i])) {
// AsmOpUtils.unbox(instructions, argumentTypes[i]);
// }else {
// AsmOpUtils.checkCast(instructions, argumentTypes[i]);
// }
// }
}else {
throw new IllegalArgumentException("location is not a InvokeLocation, location: " + location);
}
}
@Override
public Type getType(BindingContext bindingContext) {
throw new UnsupportedOperationException("InvokeLocation saver do not support getType()");
}
};
}
return stackSaver;
}