forwarder.setAccessFlags( (meth.getModifiers() & ~(Modifier.ABSTRACT
| Modifier.NATIVE
| Modifier.SYNCHRONIZED)));
setThrows(forwarder, cp, meth);
int args = Descriptor.paramSize(desc);
Bytecode code = new Bytecode(cp, 0, args + 2);
/*
* if (methods[index * 2] == null) {
* methods[index * 2]
* = RuntimeSupport.findMethod(this, <overridden name>, <desc>);
* methods[index * 2 + 1]
* = RuntimeSupport.findMethod(this, <delegator name>, <desc>);
* or = null // the original method is abstract.
* }
* return ($r)handler.invoke(this, methods[index * 2],
* methods[index * 2 + 1], $args);
*/
int origIndex = index * 2;
int delIndex = index * 2 + 1;
int arrayVar = args + 1;
code.addGetstatic(thisClassName, HOLDER, HOLDER_TYPE);
code.addAstore(arrayVar);
code.addAload(arrayVar);
code.addIconst(origIndex);
code.addOpcode(Opcode.AALOAD);
code.addOpcode(Opcode.IFNONNULL);
int pc = code.currentPc();
code.addIndex(0);
callFindMethod(code, "findSuperMethod", arrayVar, origIndex, meth.getName(), desc);
callFindMethod(code, "findMethod", arrayVar, delIndex, delegatorName, desc);
code.write16bit(pc, code.currentPc() - pc + 1);
code.addAload(0);
code.addGetfield(thisClassName, HANDLER, HANDLER_TYPE);
code.addAload(0);
code.addAload(arrayVar);
code.addIconst(origIndex);
code.addOpcode(Opcode.AALOAD);
code.addAload(arrayVar);
code.addIconst(delIndex);
code.addOpcode(Opcode.AALOAD);
makeParameterList(code, meth.getParameterTypes());
code.addInvokeinterface(MethodHandler.class.getName(), "invoke",
"(Ljava/lang/Object;Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;",
5);
Class retType = meth.getReturnType();
addUnwrapper(code, retType);
addReturn(code, retType);
forwarder.setCodeAttribute(code.toCodeAttribute());
return forwarder;
}