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) {
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
int thisParameterIndex = -1;
int methodNameParameterIndex = -1;
int methodDescParameterIndex = -1;
for (int i = 0; i < parameterAnnotations.length; i++) {
for (Annotation annotation : parameterAnnotations[i]) {
if (annotation instanceof This) {
@@ -153,6 +155,18 @@ public class InterceptionInstrumenter {
}
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(
@@ -161,7 +175,10 @@ public class InterceptionInstrumenter {
method.getName(),
Type.getMethodDescriptor(method),
method.getParameterTypes().length,
thisParameterIndex);
thisParameterIndex,
methodNameParameterIndex,
methodDescParameterIndex
);
}
private void addDumpTask(final Object interceptor, final Method method, final MethodInstrumenter instrumenter) {
@@ -293,7 +310,7 @@ public class InterceptionInstrumenter {
if (enterDataWritten) return;
enterDataWritten = true;
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 ATHROW:
for (MethodData methodData : exitData) {
invokeMethod(access, desc, getInstructionAdapter(), methodData);
invokeMethod(access, name, desc, getInstructionAdapter(), methodData);
}
break;
}
@@ -348,7 +365,7 @@ public class InterceptionInstrumenter {
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();
ia.getstatic(field.getDeclaringClass(), field.getName(), field.getDesc());
ia.checkcast(field.getRuntimeType());
@@ -360,7 +377,7 @@ public class InterceptionInstrumenter {
int base = isStatic ? 0 : 1;
int parametersUsed = 0;
for (int i = 0; i < parameterCount; i++) {
if (methodData.getThisParameterIndex() == i) {
if (i == methodData.getThisParameterIndex()) {
if (isStatic) {
// static method, 'this' is null
ia.aconst(null);
@@ -370,6 +387,12 @@ public class InterceptionInstrumenter {
ia.load(0, OBJECT_TYPE);
}
}
else if (i == methodData.getMethodNameParameterIndex()) {
ia.aconst(instrumentedMethodName);
}
else if (i == methodData.getMethodDescParameterIndex()) {
ia.aconst(instrumentedMethodDesc);
}
else {
ia.load(base + parametersUsed, parameterTypes[parametersUsed]);
parametersUsed++;
@@ -22,4 +22,10 @@ interface MethodData extends MemberData {
// -1 for no @This parameter
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 int parameterCount;
private final int thisParameterIndex;
private final int methodNameParameterIndex;
private final int methodDescParameterIndex;
MethodDataImpl(
FieldData ownerField,
@@ -27,12 +29,16 @@ public class MethodDataImpl extends MemberDataImpl implements MethodData {
String name,
String desc,
int parameterCount,
int thisParameterIndex
int thisParameterIndex,
int methodNameParameterIndex,
int methodDescParameterIndex
) {
super(declaringClass, name, desc);
this.ownerField = ownerField;
this.parameterCount = parameterCount;
this.thisParameterIndex = thisParameterIndex;
this.methodNameParameterIndex = methodNameParameterIndex;
this.methodDescParameterIndex = methodDescParameterIndex;
}
@Override
@@ -49,4 +55,14 @@ public class MethodDataImpl extends MemberDataImpl implements MethodData {
public int getThisParameterIndex() {
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 {
}