Skip to content

Commit

Permalink
Small adjustments to finished code.
Browse files Browse the repository at this point in the history
  • Loading branch information
raphw committed Apr 3, 2016
1 parent 2af4069 commit 138b621
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 39 deletions.
163 changes: 124 additions & 39 deletions byte-buddy-dep/src/main/java/net/bytebuddy/asm/Advice.java
Expand Up @@ -210,23 +210,92 @@ public String toString() {
'}'; '}';
} }


/**
* A translator for frame found in parsed code.
*/
protected static class FrameTranslator { protected static class FrameTranslator {


/**
* Indicates that a value for visiting a frame is not defined.
*/
private static final int UNDEFINED = -1; private static final int UNDEFINED = -1;


/**
* An empty array indicating an empty frame.
*/
private static final Object[] EMPTY = new Object[0]; private static final Object[] EMPTY = new Object[0];


/**
* The instrumented method.
*/
private final MethodDescription.InDefinedShape instrumentedMethod; private final MethodDescription.InDefinedShape instrumentedMethod;


/**
* A list of intermediate types to be considered as part of the instrumented method's steady signature.
*/
private final TypeList intermediateTypes; private final TypeList intermediateTypes;


/**
* {@code true} if the translator requires a full stack map frame.
*/
private boolean requiresFull; private boolean requiresFull;


public FrameTranslator(MethodDescription.InDefinedShape instrumentedMethod, TypeList intermediateTypes) { /**
* Creates a new frame translator.
*
* @param instrumentedMethod The instrumented method.
* @param intermediateTypes A list of intermediate types to be considered as part of the instrumented method's steady signature.
*/
protected FrameTranslator(MethodDescription.InDefinedShape instrumentedMethod, TypeList intermediateTypes) {
this.instrumentedMethod = instrumentedMethod; this.instrumentedMethod = instrumentedMethod;
this.intermediateTypes = intermediateTypes; this.intermediateTypes = intermediateTypes;
} }


/**
* Translates a type into a representation of its form inside a stack map frame.
*
* @param typeDescription The type to translate.
* @return A stack entry representation of the supplied type.
*/
private static Object toFrame(TypeDescription typeDescription) {
if (typeDescription.represents(boolean.class)
|| typeDescription.represents(byte.class)
|| typeDescription.represents(short.class)
|| typeDescription.represents(char.class)
|| typeDescription.represents(int.class)) {
return Opcodes.INTEGER;
} else if (typeDescription.represents(long.class)) {
return Opcodes.LONG;
} else if (typeDescription.represents(float.class)) {
return Opcodes.FLOAT;
} else if (typeDescription.represents(double.class)) {
return Opcodes.DOUBLE;
} else {
return typeDescription.getInternalName();
}
}

/**
* Binds this frame translator to an advice method.
*
* @param methodDescription The advice method.
* @return A bound version of this frame translator.
*/
protected Bound bind(MethodDescription.InDefinedShape methodDescription) {
return bind(methodDescription, new TypeList.Empty());
}

/**
* Binds this frame translator to an advice method.
*
* @param methodDescription The advice method.
* @param intermediateTypes A list of intermediate types to be considered as part of the advice method's steady signature.
* @return A bound version of this frame translator.
*/
protected Bound bind(MethodDescription.InDefinedShape methodDescription, TypeList intermediateTypes) {
return new Bound(methodDescription, intermediateTypes);
}

protected void injectFrame(MethodVisitor methodVisitor) { protected void injectFrame(MethodVisitor methodVisitor) {
injectFrame(methodVisitor, intermediateTypes, false); injectFrame(methodVisitor, intermediateTypes, false);
} }
Expand All @@ -240,15 +309,15 @@ private void injectFrame(MethodVisitor methodVisitor, TypeList intermediateTypes
Object[] localVariable = new Object[instrumentedMethod.getParameters().size() Object[] localVariable = new Object[instrumentedMethod.getParameters().size()
+ (instrumentedMethod.isStatic() ? 0 : 1) + (instrumentedMethod.isStatic() ? 0 : 1)
+ intermediateTypes.size()]; + intermediateTypes.size()];
int variableIndex = 0; int index = 0;
if (!instrumentedMethod.isStatic()) { if (!instrumentedMethod.isStatic()) {
variableIndex += insertFrame(instrumentedMethod.getDeclaringType(), localVariable, variableIndex); localVariable[index++] = toFrame(instrumentedMethod.getDeclaringType());
} }
for (TypeDescription typeDescription : instrumentedMethod.getParameters().asTypeList().asErasures()) { for (TypeDescription typeDescription : instrumentedMethod.getParameters().asTypeList().asErasures()) {
variableIndex += insertFrame(typeDescription, localVariable, variableIndex); localVariable[index++] = toFrame(typeDescription);
} }
for (TypeDescription typeDescription : intermediateTypes) { for (TypeDescription typeDescription : intermediateTypes) {
variableIndex += insertFrame(typeDescription, localVariable, variableIndex); localVariable[index++] = toFrame(typeDescription);
} }
methodVisitor.visitFrame(Opcodes.F_FULL, methodVisitor.visitFrame(Opcodes.F_FULL,
localVariable.length, localVariable.length,
Expand All @@ -266,14 +335,16 @@ private void injectFrame(MethodVisitor methodVisitor, TypeList intermediateTypes
} }
} }


protected Bound bind(MethodDescription.InDefinedShape methodDescription) { /**
return bind(methodDescription, new TypeList.Empty()); * Translates an existing frame.
} *

* @param methodVisitor The method visitor to append the frame to.
protected Bound bind(MethodDescription.InDefinedShape methodDescription, TypeList intermediateTypes) { * @param type The type of method frame.
return new Bound(methodDescription, intermediateTypes); * @param localVariableLength The number of local variables of the original frame.
} * @param localVariable An array containing the local variable types.

* @param stackSize The size of the current operand stack.
* @param stack An array containing the types on the operand stack.
*/
protected void translateFrame(MethodVisitor methodVisitor, protected void translateFrame(MethodVisitor methodVisitor,
int type, int type,
int localVariableLength, int localVariableLength,
Expand All @@ -283,6 +354,18 @@ protected void translateFrame(MethodVisitor methodVisitor,
translateFrame(methodVisitor, instrumentedMethod, intermediateTypes, type, localVariableLength, localVariable, stackSize, stack); translateFrame(methodVisitor, instrumentedMethod, intermediateTypes, type, localVariableLength, localVariable, stackSize, stack);
} }


/**
* Translates an existing frame.
*
* @param methodVisitor The method visitor to append the frame to.
* @param methodDescription The method for which this frame was originally written.
* @param intermediateTypes The intermediate types to be considered as part of the instrumented method's signature.
* @param type The type of method frame.
* @param localVariableLength The number of local variables of the original frame.
* @param localVariable An array containing the local variable types.
* @param stackSize The size of the current operand stack.
* @param stack An array containing the types on the operand stack.
*/
private void translateFrame(MethodVisitor methodVisitor, private void translateFrame(MethodVisitor methodVisitor,
MethodDescription.InDefinedShape methodDescription, MethodDescription.InDefinedShape methodDescription,
TypeList intermediateTypes, TypeList intermediateTypes,
Expand All @@ -305,13 +388,13 @@ private void translateFrame(MethodVisitor methodVisitor,
+ intermediateTypes.size()]; + intermediateTypes.size()];
int index = 0; int index = 0;
if (!instrumentedMethod.isStatic()) { if (!instrumentedMethod.isStatic()) {
index += insertFrame(instrumentedMethod.getDeclaringType(), translated, index); localVariable[index++] = toFrame(instrumentedMethod.getDeclaringType());
} }
for (TypeDescription typeDescription : instrumentedMethod.getParameters().asTypeList().asErasures()) { for (TypeDescription typeDescription : instrumentedMethod.getParameters().asTypeList().asErasures()) {
index += insertFrame(typeDescription, translated, index); localVariable[index++] = toFrame(typeDescription);
} }
for (TypeDescription typeDescription : intermediateTypes) { for (TypeDescription typeDescription : intermediateTypes) {
index += insertFrame(typeDescription, translated, index); localVariable[index++] = toFrame(typeDescription);
} }
System.arraycopy(localVariable, System.arraycopy(localVariable,
methodDescription.getParameters().size() + (methodDescription.isStatic() ? 0 : 1), methodDescription.getParameters().size() + (methodDescription.isStatic() ? 0 : 1),
Expand All @@ -330,29 +413,6 @@ private void translateFrame(MethodVisitor methodVisitor,
methodVisitor.visitFrame(type, localVariableLength, localVariable, stackSize, stack); methodVisitor.visitFrame(type, localVariableLength, localVariable, stackSize, stack);
} }


private static int insertFrame(TypeDescription typeDescription, Object[] translated, int index) {
if (typeDescription.represents(boolean.class)
|| typeDescription.represents(byte.class)
|| typeDescription.represents(short.class)
|| typeDescription.represents(char.class)
|| typeDescription.represents(int.class)) {
translated[index] = Opcodes.INTEGER;
return 1;
} else if (typeDescription.represents(long.class)) {
translated[index] = Opcodes.LONG;
return 1;
} else if (typeDescription.represents(float.class)) {
translated[index] = Opcodes.FLOAT;
return 1;
} else if (typeDescription.represents(double.class)) {
translated[index] = Opcodes.DOUBLE;
return 1;
} else {
translated[index] = typeDescription.getInternalName();
return 1;
}
}

@Override @Override
public String toString() { public String toString() {
return "Advice.FrameAdjustment{" + return "Advice.FrameAdjustment{" +
Expand All @@ -361,17 +421,42 @@ public String toString() {
'}'; '}';
} }


/**
* A frame translator that is bound to an advice method.
*/
protected class Bound { protected class Bound {


/**
* The method description for which frames are translated.
*/
private final MethodDescription.InDefinedShape methodDescription; private final MethodDescription.InDefinedShape methodDescription;


/**
* A list of intermediate types to be considered as part of the instrumented method's steady signature.
*/
private final TypeList intermediateTypes; private final TypeList intermediateTypes;


/**
* Creates a new bound frame translator.
*
* @param methodDescription The method description for which frames are translated.
* @param intermediateTypes A list of intermediate types to be considered as part of the instrumented method's steady signature.
*/
protected Bound(MethodDescription.InDefinedShape methodDescription, TypeList intermediateTypes) { protected Bound(MethodDescription.InDefinedShape methodDescription, TypeList intermediateTypes) {
this.methodDescription = methodDescription; this.methodDescription = methodDescription;
this.intermediateTypes = intermediateTypes; this.intermediateTypes = intermediateTypes;
} }


/**
* Translates an existing frame.
*
* @param methodVisitor The method visitor to append the frame to.
* @param type The type of method frame.
* @param localVariableLength The number of local variables of the original frame.
* @param localVariable An array containing the local variable types.
* @param stackSize The size of the current operand stack.
* @param stack An array containing the types on the operand stack.
*/
protected void translateFrame(MethodVisitor methodVisitor, protected void translateFrame(MethodVisitor methodVisitor,
int type, int type,
int localVariableLength, int localVariableLength,
Expand Down
Expand Up @@ -743,6 +743,8 @@ public void testCannotInstantiateSuppressionMarker() throws Exception {
@Test @Test
public void testObjectProperties() throws Exception { public void testObjectProperties() throws Exception {
ObjectPropertyAssertion.of(Advice.class).apply(); ObjectPropertyAssertion.of(Advice.class).apply();
ObjectPropertyAssertion.of(Advice.FrameTranslator.class).applyBasic();
ObjectPropertyAssertion.of(Advice.FrameTranslator.Bound.class).applyBasic();
ObjectPropertyAssertion.of(Advice.AdviceVisitor.CodeCopier.class).applyBasic(); ObjectPropertyAssertion.of(Advice.AdviceVisitor.CodeCopier.class).applyBasic();
ObjectPropertyAssertion.of(Advice.Dispatcher.Inactive.class).apply(); ObjectPropertyAssertion.of(Advice.Dispatcher.Inactive.class).apply();
ObjectPropertyAssertion.of(Advice.Dispatcher.Active.Resolved.OffsetMapping.Target.ForReadOnlyParameter.class).apply(); ObjectPropertyAssertion.of(Advice.Dispatcher.Active.Resolved.OffsetMapping.Target.ForReadOnlyParameter.class).apply();
Expand Down

0 comments on commit 138b621

Please sign in to comment.