Skip to content

Commit

Permalink
Added possibility to read return types as boxed values or read argume…
Browse files Browse the repository at this point in the history
…nts as argument arrays.
  • Loading branch information
raphw committed Apr 8, 2016
1 parent ca72163 commit 90ba814
Showing 1 changed file with 104 additions and 17 deletions.
121 changes: 104 additions & 17 deletions byte-buddy-dep/src/main/java/net/bytebuddy/asm/Advice.java
Expand Up @@ -2310,8 +2310,6 @@ public String toString() {

class ForBoxedParameter implements Target {

private static final String VALUE_OF = "valueOf";

private final int offset;

private final BoxingDispatcher boxingDispatcher;
Expand All @@ -2329,12 +2327,7 @@ protected static Target of(int offset, TypeDefinition type) {
public void resolveAccess(MethodVisitor methodVisitor, int opcode) {
switch (opcode) {
case Opcodes.ALOAD:
methodVisitor.visitVarInsn(boxingDispatcher.getOpcode(), offset);
methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
boxingDispatcher.getOwner(),
VALUE_OF,
boxingDispatcher.getDescriptor(),
false);
boxingDispatcher.loadBoxed(methodVisitor, offset);
break;
case Opcodes.ILOAD:
case Opcodes.LLOAD:
Expand Down Expand Up @@ -2367,15 +2360,17 @@ protected enum BoxingDispatcher {
FLOAT(Opcodes.ILOAD, Float.class, float.class),
DOUBLE(Opcodes.ILOAD, Double.class, double.class);

private static final String VALUE_OF = "valueOf";

private final int opcode;

private final String target;
private final String owner;

private final String descriptor;

BoxingDispatcher(int opcode, Class<?> wrapperType, Class<?> primitiveType) {
this.opcode = opcode;
target = Type.getInternalName(wrapperType);
owner = Type.getInternalName(wrapperType);
descriptor = Type.getMethodDescriptor(Type.getType(wrapperType), Type.getType(primitiveType));
}

Expand All @@ -2401,18 +2396,51 @@ protected static BoxingDispatcher of(TypeDefinition typeDefinition) {
}
}

protected int getOpcode() {
return opcode;
protected void loadBoxed(MethodVisitor methodVisitor, int offset) {
methodVisitor.visitVarInsn(opcode, offset);
methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, owner, VALUE_OF, descriptor, false);
}
}
}

protected String getOwner() {
return target;
}
class ForBoxedArguments implements Target {

protected String getDescriptor() {
return descriptor;
private final List<ParameterDescription.InDefinedShape> parameters;

protected ForBoxedArguments(List<ParameterDescription.InDefinedShape> parameters) {
this.parameters = parameters;
}

@Override
public void resolveAccess(MethodVisitor methodVisitor, int opcode) {
switch (opcode) {
case Opcodes.ALOAD:
methodVisitor.visitLdcInsn(parameters.size());
methodVisitor.visitTypeInsn(Opcodes.ANEWARRAY, TypeDescription.OBJECT.getInternalName());
for (ParameterDescription parameter : parameters) {
ForBoxedParameter.BoxingDispatcher.of(parameter.getType()).loadBoxed(methodVisitor, parameter.getOffset());
methodVisitor.visitInsn(Opcodes.AASTORE);
}
break;
case Opcodes.ILOAD:
case Opcodes.LLOAD:
case Opcodes.FLOAD:
case Opcodes.DLOAD:
case Opcodes.ISTORE:
case Opcodes.FSTORE:
case Opcodes.ASTORE:
case Opcodes.LSTORE:
case Opcodes.DSTORE:
throw new IllegalStateException(); // TODO
default:
throw new IllegalStateException("Unexpected opcode: " + opcode);
}
}

@Override
public void resolveIncrement(MethodVisitor methodVisitor, int increment) {
throw new IllegalStateException(); // TODO
}
}

enum ForNullConstant implements Target {
Expand Down Expand Up @@ -3407,6 +3435,50 @@ public OffsetMapping make(ParameterDescription.InDefinedShape parameterDescripti
}
}

enum ForBoxedArguments implements OffsetMapping, Factory {

INSTANCE;

@Override
public Target resolve(MethodDescription.InDefinedShape instrumentedMethod, Context context) {
return new Target.ForBoxedArguments(instrumentedMethod.getParameters());
}

@Override
public OffsetMapping make(ParameterDescription.InDefinedShape parameterDescription) {
if (parameterDescription.getDeclaredAnnotations().isAnnotationPresent(BoxedArguments.class)) {
if (!parameterDescription.getType().represents(Object[].class)) {
throw new IllegalStateException(); // TODO
}
return this;
} else {
return UNDEFINED;
}
}
}

enum ForOriginType implements OffsetMapping, Factory {

INSTANCE;

@Override
public Target resolve(MethodDescription.InDefinedShape instrumentedMethod, Context context) {
return new Target.ForConstantPoolValue(Type.getType(instrumentedMethod.getDeclaringType().getDescriptor()));
}

@Override
public OffsetMapping make(ParameterDescription.InDefinedShape parameterDescription) {
if (parameterDescription.getDeclaredAnnotations().isAnnotationPresent(OriginType.class)) {
if (!parameterDescription.getType().represents(Class.class)) {
throw new IllegalStateException(); // TODO
}
return this;
} else {
return UNDEFINED;
}
}
}

/**
* An offset mapping for accessing a {@link Throwable} of the instrumented method.
*/
Expand Down Expand Up @@ -3529,9 +3601,11 @@ protected static class ForMethodEnter extends Active.Resolved implements Dispatc
protected ForMethodEnter(MethodDescription.InDefinedShape adviceMethod) {
super(adviceMethod,
OffsetMapping.ForParameter.Factory.INSTANCE,
OffsetMapping.ForBoxedArguments.INSTANCE,
OffsetMapping.ForThisReference.Factory.INSTANCE,
OffsetMapping.ForField.Factory.INSTANCE,
OffsetMapping.ForOrigin.Factory.INSTANCE,
OffsetMapping.ForOriginType.INSTANCE,
OffsetMapping.ForIgnored.INSTANCE,
new OffsetMapping.Illegal(Thrown.class, Enter.class, Return.class));
}
Expand Down Expand Up @@ -3599,9 +3673,11 @@ protected abstract static class ForMethodExit extends Active.Resolved implements
protected ForMethodExit(MethodDescription.InDefinedShape adviceMethod, TypeDescription enterType) {
super(adviceMethod,
OffsetMapping.ForParameter.Factory.INSTANCE,
OffsetMapping.ForBoxedArguments.INSTANCE,
OffsetMapping.ForThisReference.Factory.INSTANCE,
OffsetMapping.ForField.Factory.INSTANCE,
OffsetMapping.ForOrigin.Factory.INSTANCE,
OffsetMapping.ForOriginType.INSTANCE,
OffsetMapping.ForIgnored.INSTANCE,
new OffsetMapping.ForEnterValue.Factory(enterType),
OffsetMapping.ForReturnValue.Factory.INSTANCE,
Expand Down Expand Up @@ -4378,6 +4454,10 @@ public String toString() {
String value() default DEFAULT;
}

public @interface OriginType {

}

/**
* Indicates that the annotated parameter should always return a default value (i.e. {@code 0} for numeric values, {@code false}
* for {@code boolean} types and {@code null} for reference types).
Expand Down Expand Up @@ -4445,6 +4525,13 @@ public String toString() {

}

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface BoxedArguments {

}

/**
* Indicates that the annotated parameter should be mapped to the return value of the instrumented method. For this to be valid,
* the parameter must be of type {@link Throwable}. If the instrumented method terminates regularly, {@code null} is assigned to
Expand Down

0 comments on commit 90ba814

Please sign in to comment.