Box arguments if needed
This commit is contained in:
+31
-3
@@ -103,16 +103,44 @@ public class ProfilingInstrumenterExample extends InterceptionInstrumenterAdapto
|
|||||||
public static Object d = new MethodCollector();
|
public static Object d = new MethodCollector();
|
||||||
|
|
||||||
public static class MethodCollector {
|
public static class MethodCollector {
|
||||||
private final Collection<String> l = new LinkedHashSet<String>();
|
private final Collection<String> collected = new LinkedHashSet<String>();
|
||||||
|
|
||||||
public void enter(@ClassName String className, @MethodName String name, @MethodDesc String desc) {
|
public void enter(@ClassName String className, @MethodName String name, @MethodDesc String desc) {
|
||||||
l.add(className + "." + name + desc);
|
collected.add(className + "." + name + desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dump(PrintStream out) {
|
public void dump(PrintStream out) {
|
||||||
for (String s : l) {
|
for (String s : collected) {
|
||||||
out.println(s);
|
out.println(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// What integers are passed as first arguments to any methods?
|
||||||
|
@MethodInterceptor(className = ".*",
|
||||||
|
methodName = ".*",
|
||||||
|
methodDesc = "\\(.+\\).*",
|
||||||
|
allowMultipleMatches = true)
|
||||||
|
public static Object e = new FirstArgumentCollector() {
|
||||||
|
@Override
|
||||||
|
protected boolean accept(Object arg) {
|
||||||
|
return arg instanceof Integer;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static abstract class FirstArgumentCollector {
|
||||||
|
private final Collection<Object> collected = new HashSet<Object>();
|
||||||
|
|
||||||
|
protected abstract boolean accept(Object arg);
|
||||||
|
|
||||||
|
public void enter(Object arg) {
|
||||||
|
if (accept(arg)) {
|
||||||
|
collected.add(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dump(PrintStream out) {
|
||||||
|
out.println("Arguments: " + collected.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+31
-17
@@ -466,9 +466,10 @@ public class InterceptionInstrumenter {
|
|||||||
|
|
||||||
org.jetbrains.asm4.commons.Method asmMethod = getAsmMethod(methodData);
|
org.jetbrains.asm4.commons.Method asmMethod = getAsmMethod(methodData);
|
||||||
|
|
||||||
int parameterCount = asmMethod.getArgumentTypes().length;
|
Type[] interceptingMethodParameterTypes = asmMethod.getArgumentTypes();
|
||||||
|
int parameterCount = interceptingMethodParameterTypes.length;
|
||||||
if (parameterCount > 0) {
|
if (parameterCount > 0) {
|
||||||
Type[] parameterTypes = Type.getArgumentTypes(instrumentedMethodDesc);
|
Type[] instrumentedMethodParameterTypes = Type.getArgumentTypes(instrumentedMethodDesc);
|
||||||
boolean isStatic = (instrumentedMethodAccess & ACC_STATIC) != 0;
|
boolean isStatic = (instrumentedMethodAccess & ACC_STATIC) != 0;
|
||||||
int base = isStatic ? 0 : 1;
|
int base = isStatic ? 0 : 1;
|
||||||
int instrumentedMethodParameterIndex = 0;
|
int instrumentedMethodParameterIndex = 0;
|
||||||
@@ -495,25 +496,27 @@ public class InterceptionInstrumenter {
|
|||||||
ia.aconst(instrumentedMethodDesc);
|
ia.aconst(instrumentedMethodDesc);
|
||||||
}
|
}
|
||||||
else if (i == methodData.getAllArgsParameterIndex()) {
|
else if (i == methodData.getAllArgsParameterIndex()) {
|
||||||
ia.aconst(parameterTypes.length);
|
ia.aconst(instrumentedMethodParameterTypes.length);
|
||||||
ia.newarray(OBJECT_TYPE);
|
ia.newarray(OBJECT_TYPE);
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
for (int parameterIndex = 0; parameterIndex < parameterTypes.length; parameterIndex++) {
|
for (int parameterIndex = 0; parameterIndex < instrumentedMethodParameterTypes.length; parameterIndex++) {
|
||||||
ia.dup();
|
ia.dup();
|
||||||
|
|
||||||
ia.iconst(parameterIndex);
|
ia.iconst(parameterIndex);
|
||||||
|
|
||||||
Type type = parameterTypes[parameterIndex];
|
Type type = instrumentedMethodParameterTypes[parameterIndex];
|
||||||
ia.load(base + offset, type);
|
ia.load(base + offset, type);
|
||||||
offset += type.getSize();
|
offset += type.getSize();
|
||||||
|
|
||||||
applyBoxingIfNeeded(ia, type);
|
boxOrCastIfNeeded(ia, type, OBJECT_TYPE);
|
||||||
ia.astore(OBJECT_TYPE);
|
ia.astore(OBJECT_TYPE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Type type = parameterTypes[instrumentedMethodParameterIndex];
|
Type type = instrumentedMethodParameterTypes[instrumentedMethodParameterIndex];
|
||||||
ia.load(base + instrumentedMethodParameterOffset, type);
|
ia.load(base + instrumentedMethodParameterOffset, type);
|
||||||
|
boxOrCastIfNeeded(ia, type, interceptingMethodParameterTypes[i]);
|
||||||
|
|
||||||
instrumentedMethodParameterIndex++;
|
instrumentedMethodParameterIndex++;
|
||||||
instrumentedMethodParameterOffset += type.getSize();
|
instrumentedMethodParameterOffset += type.getSize();
|
||||||
}
|
}
|
||||||
@@ -532,37 +535,48 @@ public class InterceptionInstrumenter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void applyBoxingIfNeeded(InstructionAdapter ia, Type type) {
|
private static void boxOrCastIfNeeded(InstructionAdapter ia, Type from, Type to) {
|
||||||
switch (type.getSort()) {
|
if (isPrimitive(to)) {
|
||||||
|
if (!isPrimitive(from)) {
|
||||||
|
throw new IllegalArgumentException("Cannot cast " + from + " to " + to);
|
||||||
|
}
|
||||||
|
ia.cast(from, to);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (from.getSort()) {
|
||||||
case Type.BOOLEAN:
|
case Type.BOOLEAN:
|
||||||
box(ia, type, Boolean.class);
|
box(ia, from, Boolean.class);
|
||||||
break;
|
break;
|
||||||
case Type.CHAR:
|
case Type.CHAR:
|
||||||
box(ia, type, Character.class);
|
box(ia, from, Character.class);
|
||||||
break;
|
break;
|
||||||
case Type.BYTE:
|
case Type.BYTE:
|
||||||
box(ia, type, Byte.class);
|
box(ia, from, Byte.class);
|
||||||
break;
|
break;
|
||||||
case Type.SHORT:
|
case Type.SHORT:
|
||||||
box(ia, type, Short.class);
|
box(ia, from, Short.class);
|
||||||
break;
|
break;
|
||||||
case Type.INT:
|
case Type.INT:
|
||||||
box(ia, type, Integer.class);
|
box(ia, from, Integer.class);
|
||||||
break;
|
break;
|
||||||
case Type.FLOAT:
|
case Type.FLOAT:
|
||||||
box(ia, type, Float.class);
|
box(ia, from, Float.class);
|
||||||
break;
|
break;
|
||||||
case Type.LONG:
|
case Type.LONG:
|
||||||
box(ia, type, Long.class);
|
box(ia, from, Long.class);
|
||||||
break;
|
break;
|
||||||
case Type.DOUBLE:
|
case Type.DOUBLE:
|
||||||
box(ia, type, Double.class);
|
box(ia, from, Double.class);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// Nothing to do, it's an object already
|
// Nothing to do, it's an object already
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isPrimitive(Type to) {
|
||||||
|
return to.getSort() <= Type.DOUBLE;
|
||||||
|
}
|
||||||
|
|
||||||
private static void box(InstructionAdapter ia, Type from, Class<?> boxedClass) {
|
private static void box(InstructionAdapter ia, Type from, Class<?> boxedClass) {
|
||||||
Type boxedType = Type.getType(boxedClass);
|
Type boxedType = Type.getType(boxedClass);
|
||||||
ia.invokestatic(boxedType.getInternalName(), "valueOf", "(" + from.getDescriptor() + ")" + boxedType.getDescriptor());
|
ia.invokestatic(boxedType.getInternalName(), "valueOf", "(" + from.getDescriptor() + ")" + boxedType.getDescriptor());
|
||||||
|
|||||||
Reference in New Issue
Block a user