|
|
|
@ -205,7 +205,7 @@ public abstract class Location {
|
|
|
|
|
/**
|
|
|
|
|
* location identifying a method invocation trigger point
|
|
|
|
|
*/
|
|
|
|
|
public static class InvokeLocation extends Location {
|
|
|
|
|
public static class InvokeLocation extends Location implements MethodInsnNodeWare {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* count identifying which invocation should be taken as the trigger point. if
|
|
|
|
@ -216,7 +216,7 @@ public abstract class Location {
|
|
|
|
|
public InvokeLocation(MethodInsnNode insnNode, int count, boolean whenComplete) {
|
|
|
|
|
super(insnNode, whenComplete);
|
|
|
|
|
this.count = count;
|
|
|
|
|
this.stackNeedSave = true;
|
|
|
|
|
this.stackNeedSave = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@ -313,34 +313,43 @@ public abstract class Location {
|
|
|
|
|
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的参数的后面,一个个存到数组里
|
|
|
|
|
//保存到 var里,再从var取出放到数组里
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
LocalVariableNode methodInvokeArgVar = methodProcessor.addInterceptorLocalVariable("__" + i, argumentTypes[i].getDescriptor());
|
|
|
|
|
AsmOpUtils.storeVar(instructions, argumentTypes[i], methodInvokeArgVar.index);
|
|
|
|
|
}
|
|
|
|
|
// 处理this
|
|
|
|
|
if(!isStatic) {
|
|
|
|
|
AsmOpUtils.loadVar(instructions, AsmOpUtils.OBJECT_ARRAY_TYPE, invokeArgsVariableNode.index);
|
|
|
|
|
// 保存this到 var
|
|
|
|
|
LocalVariableNode methodInvokeThis = methodProcessor.addInterceptorLocalVariable("__invokemethodthis", AsmOpUtils.OBJECT_TYPE.getDescriptor());
|
|
|
|
|
AsmOpUtils.storeVar(instructions, AsmOpUtils.OBJECT_TYPE, methodInvokeThis.index);
|
|
|
|
|
|
|
|
|
|
// // 如果是非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);
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
// 从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);
|
|
|
|
@ -363,26 +372,37 @@ public abstract class Location {
|
|
|
|
|
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));
|
|
|
|
|
}
|
|
|
|
|
// 从var里取回this
|
|
|
|
|
LocalVariableNode methodInvokeThis = methodProcessor.findLocalVariableLabel("__invokemethodthis");
|
|
|
|
|
AsmOpUtils.loadVar(instructions, AsmOpUtils.OBJECT_TYPE, methodInvokeThis.index);
|
|
|
|
|
AsmOpUtils.checkCast(instructions, Type.getObjectType(methodInsnNode.owner));
|
|
|
|
|
|
|
|
|
|
// 从 var里取出原来的数据,放回栈上
|
|
|
|
|
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]);
|
|
|
|
|
}
|
|
|
|
|
LocalVariableNode methodInvokeArgVar = methodProcessor.findLocalVariableLabel("__" + i);
|
|
|
|
|
AsmOpUtils.loadVar(instructions, argumentTypes[i], methodInvokeArgVar.index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
}
|
|
|
|
@ -399,6 +419,11 @@ public abstract class Location {
|
|
|
|
|
return stackSaver;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public MethodInsnNode methodInsnNode() {
|
|
|
|
|
return (MethodInsnNode) insnNode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -606,8 +631,7 @@ public abstract class Location {
|
|
|
|
|
/**
|
|
|
|
|
* location identifying a method exceptional exit trigger point
|
|
|
|
|
*/
|
|
|
|
|
public static class ExceptionExitLocation extends Location {
|
|
|
|
|
|
|
|
|
|
public static class ExceptionExitLocation extends Location{
|
|
|
|
|
public ExceptionExitLocation(AbstractInsnNode insnNode) {
|
|
|
|
|
super(insnNode, true);
|
|
|
|
|
stackNeedSave = true;
|
|
|
|
@ -643,4 +667,50 @@ public abstract class Location {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* location identifying a method exceptional exit trigger point
|
|
|
|
|
*/
|
|
|
|
|
public static class InvokeExceptionExitLocation extends Location implements MethodInsnNodeWare {
|
|
|
|
|
private MethodInsnNode methodInsnNode;
|
|
|
|
|
|
|
|
|
|
public InvokeExceptionExitLocation(MethodInsnNode methodInsnNode, AbstractInsnNode insnNode) {
|
|
|
|
|
super(insnNode, true);
|
|
|
|
|
stackNeedSave = true;
|
|
|
|
|
this.methodInsnNode = methodInsnNode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public LocationType getLocationType() {
|
|
|
|
|
return LocationType.INVOKE_EXCEPTION_EXIT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public StackSaver getStackSaver() {
|
|
|
|
|
StackSaver stackSaver = new StackSaver() {
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void store(InsnList instructions, BindingContext bindingContext) {
|
|
|
|
|
LocalVariableNode throwVariableNode = bindingContext.getMethodProcessor().initThrowVariableNode();
|
|
|
|
|
AsmOpUtils.storeVar(instructions, Type.getType(Throwable.class), throwVariableNode.index);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void load(InsnList instructions, BindingContext bindingContext) {
|
|
|
|
|
LocalVariableNode throwVariableNode = bindingContext.getMethodProcessor().initThrowVariableNode();
|
|
|
|
|
AsmOpUtils.loadVar(instructions, Type.getType(Throwable.class), throwVariableNode.index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Type getType(BindingContext bindingContext) {
|
|
|
|
|
return Type.getType(Throwable.class);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
return stackSaver;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public MethodInsnNode methodInsnNode() {
|
|
|
|
|
return methodInsnNode;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|