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 f95973fb2c6..e1aa33deca3 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 @@ -36,6 +36,7 @@ public class InterceptionInstrumenter { private static final Pattern ANYTHING = Pattern.compile(".*"); private static final Type OBJECT_TYPE = Type.getType(Object.class); + //private final boolean dumpInstrumentedMethods = true; private final boolean dumpInstrumentedMethods = false; private final Map classPatterns = new LinkedHashMap(); @@ -181,7 +182,6 @@ public class InterceptionInstrumenter { Type.getInternalName(method.getDeclaringClass()), method.getName(), Type.getMethodDescriptor(method), - method.getParameterTypes().length, thisParameterIndex, methodNameParameterIndex, methodDescParameterIndex, @@ -279,18 +279,22 @@ public class InterceptionInstrumenter { final List exitData = new ArrayList(); final List enterData = new ArrayList(); - int maxParamCount = 0; + org.jetbrains.asm4.commons.Method methodBeingInstrumented = new org.jetbrains.asm4.commons.Method(name, desc); + + int maxStackDepth = 0; for (MethodInstrumenter instrumenter : applicableInstrumenters) { for (MethodData methodData : instrumenter.getEnterData()) { - if (maxParamCount < stackDepth(methodData)) { - maxParamCount = stackDepth(methodData); + int depth = stackDepth(methodData, methodBeingInstrumented); + if (maxStackDepth < depth) { + maxStackDepth = depth; } enterData.add(methodData); } for (MethodData methodData : instrumenter.getExitData()) { - if (maxParamCount < stackDepth(methodData)) { - maxParamCount = stackDepth(methodData); + int depth = stackDepth(methodData, methodBeingInstrumented); + if (maxStackDepth < depth) { + maxStackDepth = depth; } exitData.add(methodData); } @@ -304,7 +308,7 @@ public class InterceptionInstrumenter { final boolean isConstructor = "".equals(name); - final int finalMaxParamCount = maxParamCount; + final int finalMaxStackDepth = maxStackDepth; return new MethodVisitorWithUniversalHandler(ASM4, mv) { private InstructionAdapter ia = null; @@ -319,8 +323,7 @@ public class InterceptionInstrumenter { @Override public void visitMaxs(int maxStack, int maxLocals) { - int maxInstrumentedStack = finalMaxParamCount + 1; // +1 for returned value on the stack - super.visitMaxs(Math.max(maxStack, maxInstrumentedStack), maxLocals); + super.visitMaxs(Math.max(maxStack, finalMaxStackDepth), maxLocals); } @Override @@ -362,10 +365,16 @@ public class InterceptionInstrumenter { }; } - private int stackDepth(MethodData methodData) { - // array + index + value - int allArgsStackDepth = methodData.getAllArgsParameterIndex() >= 0 ? 3 : 0; - return methodData.getParameterCount() + 1 /*receiver*/ + allArgsStackDepth; + private int stackDepth(MethodData methodData, org.jetbrains.asm4.commons.Method methodBeingInstrumented) { + org.jetbrains.asm4.commons.Method method = getAsmMethod(methodData); + // array * 2 (dup) + index + value (may be long/double) + int allArgsStackDepth = methodData.getAllArgsParameterIndex() >= 0 ? 5 : 0; + // receiver + return value must be kept on the stack OR exception, so we have to reserve at least 1 + int totalSize = 1 + Math.max(methodBeingInstrumented.getReturnType().getSize(), 1); + for (Type type : method.getArgumentTypes()) { + totalSize += type.getSize(); + } + return totalSize + allArgsStackDepth + method.getReturnType().getSize(); } private void checkMultipleMatches(MethodInstrumenter instrumenter, String name, String desc) { @@ -398,6 +407,10 @@ public class InterceptionInstrumenter { return cw.toByteArray(); } + private static org.jetbrains.asm4.commons.Method getAsmMethod(MethodData methodData) { + return new org.jetbrains.asm4.commons.Method(methodData.getName(), methodData.getDesc()); + } + private static void invokeMethod( int access, String instrumentedMethodName, @@ -410,7 +423,9 @@ public class InterceptionInstrumenter { ia.getstatic(field.getDeclaringClass(), field.getName(), field.getDesc()); ia.checkcast(field.getRuntimeType()); - int parameterCount = methodData.getParameterCount(); + org.jetbrains.asm4.commons.Method asmMethod = getAsmMethod(methodData); + + int parameterCount = asmMethod.getArgumentTypes().length; if (parameterCount > 0) { Type[] parameterTypes = Type.getArgumentTypes(instrumentedMethodDesc); boolean isStatic = (access & ACC_STATIC) != 0; @@ -457,6 +472,15 @@ public class InterceptionInstrumenter { } } ia.invokevirtual(methodData.getDeclaringClass(), methodData.getName(), methodData.getDesc()); + Type type = asmMethod.getReturnType(); + if (type.getSort() != Type.VOID) { + if (type.getSize() == 1) { + ia.pop(); + } + else { + ia.pop2(); + } + } } private static void applyBoxingIfNeeded(InstructionAdapter ia, Type type) { diff --git a/compiler/preloader/instrumentation/src/org/jetbrains/jet/preloading/instrumentation/MethodData.java b/compiler/preloader/instrumentation/src/org/jetbrains/jet/preloading/instrumentation/MethodData.java index 5cb50fc5d01..4be00c227cf 100644 --- a/compiler/preloader/instrumentation/src/org/jetbrains/jet/preloading/instrumentation/MethodData.java +++ b/compiler/preloader/instrumentation/src/org/jetbrains/jet/preloading/instrumentation/MethodData.java @@ -18,7 +18,6 @@ package org.jetbrains.jet.preloading.instrumentation; interface MethodData extends MemberData { FieldData getOwnerField(); - int getParameterCount(); // -1 for no @This parameter int getThisParameterIndex(); diff --git a/compiler/preloader/instrumentation/src/org/jetbrains/jet/preloading/instrumentation/MethodDataImpl.java b/compiler/preloader/instrumentation/src/org/jetbrains/jet/preloading/instrumentation/MethodDataImpl.java index ee4cb491df2..0f738409885 100644 --- a/compiler/preloader/instrumentation/src/org/jetbrains/jet/preloading/instrumentation/MethodDataImpl.java +++ b/compiler/preloader/instrumentation/src/org/jetbrains/jet/preloading/instrumentation/MethodDataImpl.java @@ -18,7 +18,6 @@ package org.jetbrains.jet.preloading.instrumentation; public class MethodDataImpl extends MemberDataImpl implements MethodData { private final FieldData ownerField; - private final int parameterCount; private final int thisParameterIndex; private final int methodNameParameterIndex; private final int methodDescParameterIndex; @@ -29,7 +28,6 @@ public class MethodDataImpl extends MemberDataImpl implements MethodData { String declaringClass, String name, String desc, - int parameterCount, int thisParameterIndex, int methodNameParameterIndex, int methodDescParameterIndex, @@ -37,7 +35,6 @@ public class MethodDataImpl extends MemberDataImpl implements MethodData { ) { super(declaringClass, name, desc); this.ownerField = ownerField; - this.parameterCount = parameterCount; this.thisParameterIndex = thisParameterIndex; this.methodNameParameterIndex = methodNameParameterIndex; this.methodDescParameterIndex = methodDescParameterIndex; @@ -49,11 +46,6 @@ public class MethodDataImpl extends MemberDataImpl implements MethodData { return ownerField; } - @Override - public int getParameterCount() { - return parameterCount; - } - @Override public int getThisParameterIndex() { return thisParameterIndex;