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 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) {
|
||||
l.add(className + "." + name + desc);
|
||||
collected.add(className + "." + name + desc);
|
||||
}
|
||||
|
||||
public void dump(PrintStream out) {
|
||||
for (String s : l) {
|
||||
for (String s : collected) {
|
||||
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);
|
||||
|
||||
int parameterCount = asmMethod.getArgumentTypes().length;
|
||||
Type[] interceptingMethodParameterTypes = asmMethod.getArgumentTypes();
|
||||
int parameterCount = interceptingMethodParameterTypes.length;
|
||||
if (parameterCount > 0) {
|
||||
Type[] parameterTypes = Type.getArgumentTypes(instrumentedMethodDesc);
|
||||
Type[] instrumentedMethodParameterTypes = Type.getArgumentTypes(instrumentedMethodDesc);
|
||||
boolean isStatic = (instrumentedMethodAccess & ACC_STATIC) != 0;
|
||||
int base = isStatic ? 0 : 1;
|
||||
int instrumentedMethodParameterIndex = 0;
|
||||
@@ -495,25 +496,27 @@ public class InterceptionInstrumenter {
|
||||
ia.aconst(instrumentedMethodDesc);
|
||||
}
|
||||
else if (i == methodData.getAllArgsParameterIndex()) {
|
||||
ia.aconst(parameterTypes.length);
|
||||
ia.aconst(instrumentedMethodParameterTypes.length);
|
||||
ia.newarray(OBJECT_TYPE);
|
||||
int offset = 0;
|
||||
for (int parameterIndex = 0; parameterIndex < parameterTypes.length; parameterIndex++) {
|
||||
for (int parameterIndex = 0; parameterIndex < instrumentedMethodParameterTypes.length; parameterIndex++) {
|
||||
ia.dup();
|
||||
|
||||
ia.iconst(parameterIndex);
|
||||
|
||||
Type type = parameterTypes[parameterIndex];
|
||||
Type type = instrumentedMethodParameterTypes[parameterIndex];
|
||||
ia.load(base + offset, type);
|
||||
offset += type.getSize();
|
||||
|
||||
applyBoxingIfNeeded(ia, type);
|
||||
boxOrCastIfNeeded(ia, type, OBJECT_TYPE);
|
||||
ia.astore(OBJECT_TYPE);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Type type = parameterTypes[instrumentedMethodParameterIndex];
|
||||
Type type = instrumentedMethodParameterTypes[instrumentedMethodParameterIndex];
|
||||
ia.load(base + instrumentedMethodParameterOffset, type);
|
||||
boxOrCastIfNeeded(ia, type, interceptingMethodParameterTypes[i]);
|
||||
|
||||
instrumentedMethodParameterIndex++;
|
||||
instrumentedMethodParameterOffset += type.getSize();
|
||||
}
|
||||
@@ -532,37 +535,48 @@ public class InterceptionInstrumenter {
|
||||
}
|
||||
}
|
||||
|
||||
private static void applyBoxingIfNeeded(InstructionAdapter ia, Type type) {
|
||||
switch (type.getSort()) {
|
||||
private static void boxOrCastIfNeeded(InstructionAdapter ia, Type from, Type to) {
|
||||
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:
|
||||
box(ia, type, Boolean.class);
|
||||
box(ia, from, Boolean.class);
|
||||
break;
|
||||
case Type.CHAR:
|
||||
box(ia, type, Character.class);
|
||||
box(ia, from, Character.class);
|
||||
break;
|
||||
case Type.BYTE:
|
||||
box(ia, type, Byte.class);
|
||||
box(ia, from, Byte.class);
|
||||
break;
|
||||
case Type.SHORT:
|
||||
box(ia, type, Short.class);
|
||||
box(ia, from, Short.class);
|
||||
break;
|
||||
case Type.INT:
|
||||
box(ia, type, Integer.class);
|
||||
box(ia, from, Integer.class);
|
||||
break;
|
||||
case Type.FLOAT:
|
||||
box(ia, type, Float.class);
|
||||
box(ia, from, Float.class);
|
||||
break;
|
||||
case Type.LONG:
|
||||
box(ia, type, Long.class);
|
||||
box(ia, from, Long.class);
|
||||
break;
|
||||
case Type.DOUBLE:
|
||||
box(ia, type, Double.class);
|
||||
box(ia, from, Double.class);
|
||||
break;
|
||||
default:
|
||||
// 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) {
|
||||
Type boxedType = Type.getType(boxedClass);
|
||||
ia.invokestatic(boxedType.getInternalName(), "valueOf", "(" + from.getDescriptor() + ")" + boxedType.getDescriptor());
|
||||
|
||||
Reference in New Issue
Block a user