Class returnType = method.getReturnType();
Class[] paramTypes = method.getParameterTypes();
ClassVisitor cv = new ClassWriter(ClassWriter.COMPUTE_MAXS);
cv.visit(ACC_PUBLIC | ACC_FINAL | ACC_SUPER, V1_5, name, null, p(Handle.class), null);
SkinnyMethodAdapter m;
String signature;
boolean needsArgsVersion = true;
switch (paramTypes.length) {
case 0:
signature = sig(Object.class, Object.class);
break;
case 1:
signature = sig(Object.class, Object.class, Object.class);
break;
case 2:
signature = sig(Object.class, Object.class, Object.class, Object.class);
break;
case 3:
signature = sig(Object.class, Object.class, Object.class, Object.class, Object.class);
break;
// case 4:
// signature = sig(Object.class, Object.class, Object.class, Object.class, Object.class);
// break;
// case 5:
// signature = sig(Object.class, Object.class, Object.class, Object.class, Object.class, Object.class);
// break;
default:
needsArgsVersion = false;
signature = sig(Object.class, Object.class, Object[].class);
break;
}
m = new SkinnyMethodAdapter(cv, ACC_PUBLIC | ACC_FINAL | ACC_SYNTHETIC, "invoke", signature, null, null);
m.start();
// load receiver
if (!Modifier.isStatic(method.getModifiers())) {
m.aload(1); // receiver
if (method.getDeclaringClass() != Object.class) {
m.checkcast(p(method.getDeclaringClass()));
}
}
// load arguments
switch (paramTypes.length) {
case 0:
case 1:
case 2:
case 3:
// case 4:
// case 5:
for (int i = 0; i < paramTypes.length; i++) {
loadUnboxedArgument(m, i + 2, paramTypes[i]);
}
break;
default:
for (int i = 0; i < paramTypes.length; i++) {
m.aload(2); // Object[] args
m.pushInt(i);
m.aaload();
Class paramClass = paramTypes[i];
if (paramClass.isPrimitive()) {
Class boxType = getBoxType(paramClass);
m.checkcast(p(boxType));
m.invokevirtual(p(boxType), paramClass.toString() + "Value", sig(paramClass));
} else if (paramClass != Object.class) {
m.checkcast(p(paramClass));
}
}
break;
}
if (Modifier.isStatic(method.getModifiers())) {
m.invokestatic(p(method.getDeclaringClass()), method.getName(), sig(returnType, paramTypes));
} else if (Modifier.isInterface(method.getDeclaringClass().getModifiers())) {
m.invokeinterface(p(method.getDeclaringClass()), method.getName(), sig(returnType, paramTypes));
} else {
m.invokevirtual(p(method.getDeclaringClass()), method.getName(), sig(returnType, paramTypes));
}
if (returnType == void.class) {
m.aconst_null();
} else if (returnType.isPrimitive()) {
Class boxType = getBoxType(returnType);
m.invokestatic(p(boxType), "valueOf", sig(boxType, returnType));
}
m.areturn();
m.end();
if (needsArgsVersion) {
m = new SkinnyMethodAdapter(cv, ACC_PUBLIC | ACC_FINAL | ACC_SYNTHETIC, "invoke", sig(Object.class, Object.class, Object[].class), null, null);
m.start();
// load handle
m.aload(0);
// load receiver
m.aload(1);
// load arguments
for (int i = 0; i < paramTypes.length; i++) {
m.aload(2); // args array
m.ldc(i);
m.aaload(); // i'th argument
}
// invoke specific arity version
m.invokevirtual(name, "invoke", sig(Object.class, params(Object.class, Object.class, paramTypes.length)));
// return result
m.areturn();
m.end();
}
// constructor
m = new SkinnyMethodAdapter(cv, ACC_PUBLIC, "<init>", sig(void.class), null, null);
m.start();
m.aload(0);
m.invokespecial(p(Handle.class), "<init>", sig(void.class));
m.voidreturn();
m.end();
cv.visitEnd();
byte[] bytes = ((ClassWriter)cv).toByteArray();