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:
* *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```
* ```@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```
* ```@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[]```
@@ -17,6 +17,7 @@
package org.jetbrains.jet.preloading;
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.MethodInterceptor;
import org.jetbrains.jet.preloading.instrumentation.annotations.MethodName;
@@ -104,8 +105,8 @@ public class ProfilingInstrumenterExample extends InterceptionInstrumenterAdapto
public static class MethodCollector {
private final Collection<String> l = new LinkedHashSet<String>();
public void enter(@MethodName String name, @MethodDesc String desc) {//long l, Object arg) {
l.add(name + desc);
public void enter(@ClassName String className, @MethodName String name, @MethodDesc String desc) {
l.add(className + "." + name + desc);
}
public void dump(PrintStream out) {
@@ -166,6 +166,7 @@ public class InterceptionInstrumenter {
private static MethodData getMethodData(FieldData interceptorField, Method method) {
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
int thisParameterIndex = -1;
int classNameParameterIndex = -1;
int methodNameParameterIndex = -1;
int methodDescParameterIndex = -1;
int allArgsParameterIndex = -1;
@@ -177,6 +178,12 @@ public class InterceptionInstrumenter {
}
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) {
if (methodNameParameterIndex > -1) {
throw new IllegalArgumentException("Multiple @MethodName parameters in " + method);
@@ -203,6 +210,7 @@ public class InterceptionInstrumenter {
method.getName(),
Type.getMethodDescriptor(method),
thisParameterIndex,
classNameParameterIndex,
methodNameParameterIndex,
methodDescParameterIndex,
allArgsParameterIndex);
@@ -338,7 +346,7 @@ public class InterceptionInstrumenter {
for (MethodData methodData : enterData) {
// 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
invokeMethod(access, name, desc, getInstructionAdapter(), methodData, isConstructor);
invokeMethod(access, cr.getClassName(), name, desc, getInstructionAdapter(), methodData, isConstructor);
}
super.visitCode();
}
@@ -353,13 +361,13 @@ public class InterceptionInstrumenter {
case DRETURN:
case ARETURN:
for (MethodData methodData : normalReturnData) {
invokeMethod(access, name, desc, getInstructionAdapter(), methodData, false);
invokeMethod(access, cr.getClassName(), name, desc, getInstructionAdapter(), methodData, false);
}
break;
case ATHROW:
for (MethodData methodData : exceptionData) {
// 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;
}
@@ -445,6 +453,7 @@ public class InterceptionInstrumenter {
private static void invokeMethod(
int instrumentedMethodAccess,
String instrumentedClassName,
String instrumentedMethodName,
String instrumentedMethodDesc,
InstructionAdapter ia,
@@ -475,6 +484,9 @@ public class InterceptionInstrumenter {
ia.load(0, OBJECT_TYPE);
}
}
else if (i == methodData.getClassNameParameterIndex()) {
ia.aconst(instrumentedClassName);
}
else if (i == methodData.getMethodNameParameterIndex()) {
ia.aconst(instrumentedMethodName);
}
@@ -19,6 +19,7 @@ package org.jetbrains.jet.preloading.instrumentation;
public class MethodData extends MemberData {
private final FieldData ownerField;
private final int thisParameterIndex;
private final int classNameParameterIndex;
private final int methodNameParameterIndex;
private final int methodDescParameterIndex;
private final int allArgsParameterIndex;
@@ -29,6 +30,7 @@ public class MethodData extends MemberData {
String name,
String desc,
int thisParameterIndex,
int classNameParameterIndex,
int methodNameParameterIndex,
int methodDescParameterIndex,
int allArgsParameterIndex
@@ -36,6 +38,7 @@ public class MethodData extends MemberData {
super(declaringClass, name, desc);
this.ownerField = ownerField;
this.thisParameterIndex = thisParameterIndex;
this.classNameParameterIndex = classNameParameterIndex;
this.methodNameParameterIndex = methodNameParameterIndex;
this.methodDescParameterIndex = methodDescParameterIndex;
this.allArgsParameterIndex = allArgsParameterIndex;
@@ -49,6 +52,10 @@ public class MethodData extends MemberData {
return thisParameterIndex;
}
public int getClassNameParameterIndex() {
return classNameParameterIndex;
}
public int getMethodNameParameterIndex() {
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 {
}