/*
* The local descriptor is the same as the descriptor from the abstract method in the
* interface.
*/
String localDescriptor = interfaceMethod.getDescriptor();
Method localMethod = new Method(mangledName, localDescriptor);
/*
* We also use the first argument to know which type to statically dispatch to.
*/
Type implementingType = Type.getType("L"
+ implementingMethod.getArgumentTypes()[0].getInternalName() + "$;");
// Maybe create the method. This is marked final as a sanity check
MethodVisitor mv = visitMethodNoRewrite(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL
| Opcodes.ACC_SYNTHETIC, localMethod.getName(), localMethod.getDescriptor(),
null, null);
if (mv != null) {
mv.visitCode();
/*
* It just so happens that the stack and local variable sizes are the same, but they're
* kept distinct to aid in clarity should the dispatch logic change.
*/
int var = 0;
int size = 0;
for (Type t : implementingMethod.getArgumentTypes()) {
size += t.getSize();
mv.visitVarInsn(t.getOpcode(Opcodes.ILOAD), var);
var += t.getSize();
}
// Make sure there's enough room for the return value
size = Math.max(size, implementingMethod.getReturnType().getSize());
mv.visitMethodInsn(Opcodes.INVOKESTATIC, implementingType.getInternalName(),
implementingMethod.getName(), implementingMethod.getDescriptor());
mv.visitInsn(localMethod.getReturnType().getOpcode(Opcodes.IRETURN));
mv.visitMaxs(size, var);
mv.visitEnd();
}
}