Support @ClassName

This commit is contained in:
Andrey Breslav
2013-05-13 18:41:03 +04:00
parent 3d40d11c98
commit ab48f3411a
5 changed files with 53 additions and 5 deletions
@@ -45,6 +45,7 @@ Whatever the type of the field, if it has methods named by the convention define
If any of the methods above, except for ```dump.*```, have parameters, they are treated as follows: If any of the methods above, except for ```dump.*```, have parameters, they are treated as follows:
* *no annotation* - this parameter receives the respective parameter of the instrumented method * *no annotation* - this parameter receives the respective parameter of the instrumented method
* ```@This``` - this parameter receives the ```this``` of the instrumented method, or ```null``` if there's no ```this``` * ```@This``` - this parameter receives the ```this``` of the instrumented method, or ```null``` if there's no ```this```
* ```@ClassName``` - this parameter receives the name of the class containing the instrumented method, must be a ```String```
* ```@MethodName``` - this parameter receives the name of the instrumented method, must be a ```String``` * ```@MethodName``` - this parameter receives the name of the instrumented method, must be a ```String```
* ```@MethodDesc``` - this parameter receives the JVM descriptor of the instrumented method, like ```(ILjava/lang/Object;)V```, must be a ```String``` * ```@MethodDesc``` - this parameter receives the JVM descriptor of the instrumented method, like ```(ILjava/lang/Object;)V```, must be a ```String```
* ```@AllArgs``` - this parameter receives an array of all arguments of the instrumented method, must be of type ```Object[]``` * ```@AllArgs``` - this parameter receives an array of all arguments of the instrumented method, must be of type ```Object[]```
@@ -17,6 +17,7 @@
package org.jetbrains.jet.preloading; package org.jetbrains.jet.preloading;
import org.jetbrains.jet.preloading.instrumentation.InterceptionInstrumenterAdaptor; import org.jetbrains.jet.preloading.instrumentation.InterceptionInstrumenterAdaptor;
import org.jetbrains.jet.preloading.instrumentation.annotations.ClassName;
import org.jetbrains.jet.preloading.instrumentation.annotations.MethodDesc; import org.jetbrains.jet.preloading.instrumentation.annotations.MethodDesc;
import org.jetbrains.jet.preloading.instrumentation.annotations.MethodInterceptor; import org.jetbrains.jet.preloading.instrumentation.annotations.MethodInterceptor;
import org.jetbrains.jet.preloading.instrumentation.annotations.MethodName; import org.jetbrains.jet.preloading.instrumentation.annotations.MethodName;
@@ -104,8 +105,8 @@ public class ProfilingInstrumenterExample extends InterceptionInstrumenterAdapto
public static class MethodCollector { public static class MethodCollector {
private final Collection<String> l = new LinkedHashSet<String>(); private final Collection<String> l = new LinkedHashSet<String>();
public void enter(@MethodName String name, @MethodDesc String desc) {//long l, Object arg) { public void enter(@ClassName String className, @MethodName String name, @MethodDesc String desc) {
l.add(name + desc); l.add(className + "." + name + desc);
} }
public void dump(PrintStream out) { public void dump(PrintStream out) {
@@ -166,6 +166,7 @@ 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 classNameParameterIndex = -1;
int methodNameParameterIndex = -1; int methodNameParameterIndex = -1;
int methodDescParameterIndex = -1; int methodDescParameterIndex = -1;
int allArgsParameterIndex = -1; int allArgsParameterIndex = -1;
@@ -177,6 +178,12 @@ public class InterceptionInstrumenter {
} }
thisParameterIndex = i; thisParameterIndex = i;
} }
else if (annotation instanceof ClassName) {
if (classNameParameterIndex > -1) {
throw new IllegalArgumentException("Multiple @ClassName parameters in " + method);
}
classNameParameterIndex = i;
}
else if (annotation instanceof MethodName) { else if (annotation instanceof MethodName) {
if (methodNameParameterIndex > -1) { if (methodNameParameterIndex > -1) {
throw new IllegalArgumentException("Multiple @MethodName parameters in " + method); throw new IllegalArgumentException("Multiple @MethodName parameters in " + method);
@@ -203,6 +210,7 @@ public class InterceptionInstrumenter {
method.getName(), method.getName(),
Type.getMethodDescriptor(method), Type.getMethodDescriptor(method),
thisParameterIndex, thisParameterIndex,
classNameParameterIndex,
methodNameParameterIndex, methodNameParameterIndex,
methodDescParameterIndex, methodDescParameterIndex,
allArgsParameterIndex); allArgsParameterIndex);
@@ -338,7 +346,7 @@ public class InterceptionInstrumenter {
for (MethodData methodData : enterData) { for (MethodData methodData : enterData) {
// At the very beginning of a constructor, i.e. before any super() call, 'this' is not available // At the very beginning of a constructor, i.e. before any super() call, 'this' is not available
// It's too hard to detect a place right after the super() call, so we just put null instead of 'this' in such cases // It's too hard to detect a place right after the super() call, so we just put null instead of 'this' in such cases
invokeMethod(access, name, desc, getInstructionAdapter(), methodData, isConstructor); invokeMethod(access, cr.getClassName(), name, desc, getInstructionAdapter(), methodData, isConstructor);
} }
super.visitCode(); super.visitCode();
} }
@@ -353,13 +361,13 @@ public class InterceptionInstrumenter {
case DRETURN: case DRETURN:
case ARETURN: case ARETURN:
for (MethodData methodData : normalReturnData) { for (MethodData methodData : normalReturnData) {
invokeMethod(access, name, desc, getInstructionAdapter(), methodData, false); invokeMethod(access, cr.getClassName(), name, desc, getInstructionAdapter(), methodData, false);
} }
break; break;
case ATHROW: case ATHROW:
for (MethodData methodData : exceptionData) { for (MethodData methodData : exceptionData) {
// A constructor may throw before calling super(), 'this' is not available in this case // A constructor may throw before calling super(), 'this' is not available in this case
invokeMethod(access, name, desc, getInstructionAdapter(), methodData, isConstructor); invokeMethod(access, cr.getClassName(), name, desc, getInstructionAdapter(), methodData, isConstructor);
} }
break; break;
} }
@@ -445,6 +453,7 @@ public class InterceptionInstrumenter {
private static void invokeMethod( private static void invokeMethod(
int instrumentedMethodAccess, int instrumentedMethodAccess,
String instrumentedClassName,
String instrumentedMethodName, String instrumentedMethodName,
String instrumentedMethodDesc, String instrumentedMethodDesc,
InstructionAdapter ia, InstructionAdapter ia,
@@ -475,6 +484,9 @@ public class InterceptionInstrumenter {
ia.load(0, OBJECT_TYPE); ia.load(0, OBJECT_TYPE);
} }
} }
else if (i == methodData.getClassNameParameterIndex()) {
ia.aconst(instrumentedClassName);
}
else if (i == methodData.getMethodNameParameterIndex()) { else if (i == methodData.getMethodNameParameterIndex()) {
ia.aconst(instrumentedMethodName); ia.aconst(instrumentedMethodName);
} }
@@ -19,6 +19,7 @@ package org.jetbrains.jet.preloading.instrumentation;
public class MethodData extends MemberData { public class MethodData extends MemberData {
private final FieldData ownerField; private final FieldData ownerField;
private final int thisParameterIndex; private final int thisParameterIndex;
private final int classNameParameterIndex;
private final int methodNameParameterIndex; private final int methodNameParameterIndex;
private final int methodDescParameterIndex; private final int methodDescParameterIndex;
private final int allArgsParameterIndex; private final int allArgsParameterIndex;
@@ -29,6 +30,7 @@ public class MethodData extends MemberData {
String name, String name,
String desc, String desc,
int thisParameterIndex, int thisParameterIndex,
int classNameParameterIndex,
int methodNameParameterIndex, int methodNameParameterIndex,
int methodDescParameterIndex, int methodDescParameterIndex,
int allArgsParameterIndex int allArgsParameterIndex
@@ -36,6 +38,7 @@ public class MethodData extends MemberData {
super(declaringClass, name, desc); super(declaringClass, name, desc);
this.ownerField = ownerField; this.ownerField = ownerField;
this.thisParameterIndex = thisParameterIndex; this.thisParameterIndex = thisParameterIndex;
this.classNameParameterIndex = classNameParameterIndex;
this.methodNameParameterIndex = methodNameParameterIndex; this.methodNameParameterIndex = methodNameParameterIndex;
this.methodDescParameterIndex = methodDescParameterIndex; this.methodDescParameterIndex = methodDescParameterIndex;
this.allArgsParameterIndex = allArgsParameterIndex; this.allArgsParameterIndex = allArgsParameterIndex;
@@ -49,6 +52,10 @@ public class MethodData extends MemberData {
return thisParameterIndex; return thisParameterIndex;
} }
public int getClassNameParameterIndex() {
return classNameParameterIndex;
}
public int getMethodNameParameterIndex() { public int getMethodNameParameterIndex() {
return methodNameParameterIndex; return methodNameParameterIndex;
} }
@@ -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.annotations;
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 ClassName {
}