advisedMethodNode.tryCatchBlocks.clear();
if (advisedMethodNode.localVariables != null)
advisedMethodNode.localVariables.clear();
InstructionBuilder builder = newBuilder(description, advisedMethodNode);
builder.newInstance(invocationClassName).dupe(0);
// Now load up the parameters to the constructor
builder.loadThis();
builder.loadThis().getField(className, getInstanceContextFieldName(), constructorTypes[1]);
builder.loadThis().getField(className, fieldName, constructorTypes[2]);
// Load up the actual method parameters
builder.loadArguments();
builder.invokeConstructor(invocationClassName, constructorTypes);
// That leaves an instance of the invocation class on the stack. If the method is void
// and throws no checked exceptions, then the variable actually isn't used. This code
// should be refactored a bit once there are tests for those cases.
builder.startVariable("invocation", invocationClassName, new InstructionBuilderCallback()
{
public void doBuild(InstructionBuilder builder)
{
builder.dupe(0).storeVariable("invocation");
builder.invoke(AbstractMethodInvocation.class, MethodInvocation.class, "proceed");
if (description.checkedExceptionTypes.length > 0)
{
builder.invoke(MethodInvocation.class, boolean.class, "didThrowCheckedException");
builder.ifZero(null, new InstructionBuilderCallback()
{
public void doBuild(InstructionBuilder builder)
{
builder.loadVariable("invocation").loadTypeConstant(Exception.class);
builder.invokeVirtual(invocationClassName, Throwable.class.getName(),
"getCheckedException", Class.class.getName());
builder.throwException();
}
});
}
if (!isVoid)
builder.loadVariable("invocation").getField(invocationClassName, RETURN_VALUE,
description.returnType);
builder.returnResult();
}
});
}