mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, superClass, "checkCall", "(Ljava/lang/Object;" + parameterDescription + ")Z");
Label l0 = new Label();
mv.visitJumpInsn(Opcodes.IFEQ, l0);
// valid method branch
BytecodeHelper helper = new BytecodeHelper(mv);
Class callClass = cachedMethod.getDeclaringClass().getTheClass();
boolean useInterface = callClass.isInterface();
String type = BytecodeHelper.getClassInternalName(callClass.getName());
String descriptor = BytecodeHelper.getMethodDescriptor(cachedMethod.getReturnType(), cachedMethod.getNativeParameterTypes());
// prepare call
int invokeMethodCode = Opcodes.INVOKEVIRTUAL;
if (cachedMethod.isStatic()) {
invokeMethodCode = Opcodes.INVOKESTATIC;
} else {
mv.visitVarInsn(Opcodes.ALOAD, 1);
helper.doCast(callClass);
if (useInterface) invokeMethodCode = Opcodes.INVOKEINTERFACE;
}
Method method = cachedMethod.setAccessible();
Class<?>[] parameters = method.getParameterTypes();
int size = parameters.length;
for (int i = 0; i < size; i++) {
if (useArray) {
// unpack argument from Object[]
mv.visitVarInsn(Opcodes.ALOAD, 2);
helper.pushConstant(i);
mv.visitInsn(Opcodes.AALOAD);
} else {
mv.visitVarInsn(Opcodes.ALOAD, i+2);
}
// cast argument to parameter class, inclusive unboxing
// for methods with primitive types
Class parameterType = parameters[i];
if (parameterType.isPrimitive()) {
helper.unbox(parameterType);
} else {
helper.doCast(parameterType);
}
}
// make call
mv.visitMethodInsn(invokeMethodCode, type, cachedMethod.getName(), descriptor);
// produce result
helper.box(cachedMethod.getReturnType());
if (cachedMethod.getReturnType() == void.class) {
mv.visitInsn(Opcodes.ACONST_NULL);
}
// return