From 39c9cbcd9ee997ef1c88e2379a265813a6e6a0ed Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Mon, 13 May 2013 19:04:43 +0400 Subject: [PATCH] Box arguments if needed --- .../ProfilingInstrumenterExample.java | 34 +++++++++++-- .../InterceptionInstrumenter.java | 48 ++++++++++++------- 2 files changed, 62 insertions(+), 20 deletions(-) diff --git a/compiler/preloader/instrumentation/src/org/jetbrains/jet/preloading/ProfilingInstrumenterExample.java b/compiler/preloader/instrumentation/src/org/jetbrains/jet/preloading/ProfilingInstrumenterExample.java index 9444aa61012..84cd06441a2 100644 --- a/compiler/preloader/instrumentation/src/org/jetbrains/jet/preloading/ProfilingInstrumenterExample.java +++ b/compiler/preloader/instrumentation/src/org/jetbrains/jet/preloading/ProfilingInstrumenterExample.java @@ -103,16 +103,44 @@ public class ProfilingInstrumenterExample extends InterceptionInstrumenterAdapto public static Object d = new MethodCollector(); public static class MethodCollector { - private final Collection l = new LinkedHashSet(); + private final Collection collected = new LinkedHashSet(); 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 collected = new HashSet(); + + 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()); + } + } } diff --git a/compiler/preloader/instrumentation/src/org/jetbrains/jet/preloading/instrumentation/InterceptionInstrumenter.java b/compiler/preloader/instrumentation/src/org/jetbrains/jet/preloading/instrumentation/InterceptionInstrumenter.java index 1d8f287e146..a8a868b5b28 100644 --- a/compiler/preloader/instrumentation/src/org/jetbrains/jet/preloading/instrumentation/InterceptionInstrumenter.java +++ b/compiler/preloader/instrumentation/src/org/jetbrains/jet/preloading/instrumentation/InterceptionInstrumenter.java @@ -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());