Support @MethodName and @MethodDesc

This commit is contained in:
Andrey Breslav
2013-05-12 14:59:27 +02:00
parent 3cd1cf0807
commit b748315304
5 changed files with 105 additions and 6 deletions
@@ -145,6 +145,8 @@ public class InterceptionInstrumenter {
private static MethodData getMethodData(FieldData interceptorField, Method method) { private static MethodData getMethodData(FieldData interceptorField, Method method) {
Annotation[][] parameterAnnotations = method.getParameterAnnotations(); Annotation[][] parameterAnnotations = method.getParameterAnnotations();
int thisParameterIndex = -1; int thisParameterIndex = -1;
int methodNameParameterIndex = -1;
int methodDescParameterIndex = -1;
for (int i = 0; i < parameterAnnotations.length; i++) { for (int i = 0; i < parameterAnnotations.length; i++) {
for (Annotation annotation : parameterAnnotations[i]) { for (Annotation annotation : parameterAnnotations[i]) {
if (annotation instanceof This) { if (annotation instanceof This) {
@@ -153,6 +155,18 @@ public class InterceptionInstrumenter {
} }
thisParameterIndex = i; thisParameterIndex = i;
} }
else if (annotation instanceof MethodName) {
if (methodNameParameterIndex > -1) {
throw new IllegalArgumentException("Multiple @MethodName parameters in " + method);
}
methodNameParameterIndex = i;
}
else if (annotation instanceof MethodDesc) {
if (methodDescParameterIndex > -1) {
throw new IllegalArgumentException("Multiple @MethodDesc parameters in " + method);
}
methodDescParameterIndex = i;
}
} }
} }
return new MethodDataImpl( return new MethodDataImpl(
@@ -161,7 +175,10 @@ public class InterceptionInstrumenter {
method.getName(), method.getName(),
Type.getMethodDescriptor(method), Type.getMethodDescriptor(method),
method.getParameterTypes().length, method.getParameterTypes().length,
thisParameterIndex); thisParameterIndex,
methodNameParameterIndex,
methodDescParameterIndex
);
} }
private void addDumpTask(final Object interceptor, final Method method, final MethodInstrumenter instrumenter) { private void addDumpTask(final Object interceptor, final Method method, final MethodInstrumenter instrumenter) {
@@ -293,7 +310,7 @@ public class InterceptionInstrumenter {
if (enterDataWritten) return; if (enterDataWritten) return;
enterDataWritten = true; enterDataWritten = true;
for (MethodData methodData : enterData) { for (MethodData methodData : enterData) {
invokeMethod(access, desc, getInstructionAdapter(), methodData); invokeMethod(access, name, desc, getInstructionAdapter(), methodData);
} }
} }
@@ -309,7 +326,7 @@ public class InterceptionInstrumenter {
case ARETURN: case ARETURN:
case ATHROW: case ATHROW:
for (MethodData methodData : exitData) { for (MethodData methodData : exitData) {
invokeMethod(access, desc, getInstructionAdapter(), methodData); invokeMethod(access, name, desc, getInstructionAdapter(), methodData);
} }
break; break;
} }
@@ -348,7 +365,7 @@ public class InterceptionInstrumenter {
return cw.toByteArray(); return cw.toByteArray();
} }
private static void invokeMethod(int access, String instrumentedMethodDesc, InstructionAdapter ia, MethodData methodData) { private static void invokeMethod(int access, String instrumentedMethodName, String instrumentedMethodDesc, InstructionAdapter ia, MethodData methodData) {
FieldData field = methodData.getOwnerField(); FieldData field = methodData.getOwnerField();
ia.getstatic(field.getDeclaringClass(), field.getName(), field.getDesc()); ia.getstatic(field.getDeclaringClass(), field.getName(), field.getDesc());
ia.checkcast(field.getRuntimeType()); ia.checkcast(field.getRuntimeType());
@@ -360,7 +377,7 @@ public class InterceptionInstrumenter {
int base = isStatic ? 0 : 1; int base = isStatic ? 0 : 1;
int parametersUsed = 0; int parametersUsed = 0;
for (int i = 0; i < parameterCount; i++) { for (int i = 0; i < parameterCount; i++) {
if (methodData.getThisParameterIndex() == i) { if (i == methodData.getThisParameterIndex()) {
if (isStatic) { if (isStatic) {
// static method, 'this' is null // static method, 'this' is null
ia.aconst(null); ia.aconst(null);
@@ -370,6 +387,12 @@ public class InterceptionInstrumenter {
ia.load(0, OBJECT_TYPE); ia.load(0, OBJECT_TYPE);
} }
} }
else if (i == methodData.getMethodNameParameterIndex()) {
ia.aconst(instrumentedMethodName);
}
else if (i == methodData.getMethodDescParameterIndex()) {
ia.aconst(instrumentedMethodDesc);
}
else { else {
ia.load(base + parametersUsed, parameterTypes[parametersUsed]); ia.load(base + parametersUsed, parameterTypes[parametersUsed]);
parametersUsed++; parametersUsed++;
@@ -22,4 +22,10 @@ interface MethodData extends MemberData {
// -1 for no @This parameter // -1 for no @This parameter
int getThisParameterIndex(); int getThisParameterIndex();
// -1 for no @MethodName
int getMethodNameParameterIndex();
// -1 for no @MethodDesc
int getMethodDescParameterIndex();
} }
@@ -20,6 +20,8 @@ public class MethodDataImpl extends MemberDataImpl implements MethodData {
private final FieldData ownerField; private final FieldData ownerField;
private final int parameterCount; private final int parameterCount;
private final int thisParameterIndex; private final int thisParameterIndex;
private final int methodNameParameterIndex;
private final int methodDescParameterIndex;
MethodDataImpl( MethodDataImpl(
FieldData ownerField, FieldData ownerField,
@@ -27,12 +29,16 @@ public class MethodDataImpl extends MemberDataImpl implements MethodData {
String name, String name,
String desc, String desc,
int parameterCount, int parameterCount,
int thisParameterIndex int thisParameterIndex,
int methodNameParameterIndex,
int methodDescParameterIndex
) { ) {
super(declaringClass, name, desc); super(declaringClass, name, desc);
this.ownerField = ownerField; this.ownerField = ownerField;
this.parameterCount = parameterCount; this.parameterCount = parameterCount;
this.thisParameterIndex = thisParameterIndex; this.thisParameterIndex = thisParameterIndex;
this.methodNameParameterIndex = methodNameParameterIndex;
this.methodDescParameterIndex = methodDescParameterIndex;
} }
@Override @Override
@@ -49,4 +55,14 @@ public class MethodDataImpl extends MemberDataImpl implements MethodData {
public int getThisParameterIndex() { public int getThisParameterIndex() {
return thisParameterIndex; return thisParameterIndex;
} }
@Override
public int getMethodNameParameterIndex() {
return methodNameParameterIndex;
}
@Override
public int getMethodDescParameterIndex() {
return methodDescParameterIndex;
}
} }
@@ -0,0 +1,27 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.preloading.instrumentation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodDesc {
}
@@ -0,0 +1,27 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.preloading.instrumentation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodName {
}