/** * Generates code to wrap Java arguments into Object[]. Non-primitive Java types are left as-is * pending conversion in the helper method. Leaves the array object on the top of the stack. */ static void generatePushWrappedArgs(ClassFileWriter cfw, Class<?>[] argTypes, int arrayLength) { // push arguments cfw.addPush(arrayLength); cfw.add(ByteCode.ANEWARRAY, "java/lang/Object"); int paramOffset = 1; for (int i = 0; i != argTypes.length; ++i) { cfw.add(ByteCode.DUP); // duplicate array reference cfw.addPush(i); paramOffset += generateWrapArg(cfw, paramOffset, argTypes[i]); cfw.add(ByteCode.AASTORE); } }
private static void generateMethod( ClassFileWriter cfw, String genName, String methodName, Class<?>[] parms, Class<?> returnType, boolean convertResult) { StringBuilder sb = new StringBuilder(); int paramsEnd = appendMethodSignature(parms, returnType, sb); String methodSignature = sb.toString(); cfw.startMethod(methodName, methodSignature, ClassFileWriter.ACC_PUBLIC); // Prepare stack to call method // push factory cfw.add(ByteCode.ALOAD_0); cfw.add(ByteCode.GETFIELD, genName, "factory", "Laurora/javascript/ContextFactory;"); // push self cfw.add(ByteCode.ALOAD_0); cfw.add(ByteCode.GETFIELD, genName, "self", "Laurora/javascript/Scriptable;"); // push function cfw.add(ByteCode.ALOAD_0); cfw.add(ByteCode.GETFIELD, genName, "delegee", "Laurora/javascript/Scriptable;"); cfw.addPush(methodName); cfw.addInvoke( ByteCode.INVOKESTATIC, "aurora/javascript/JavaAdapter", "getFunction", "(Laurora/javascript/Scriptable;" + "Ljava/lang/String;" + ")Laurora/javascript/Function;"); // push arguments generatePushWrappedArgs(cfw, parms, parms.length); // push bits to indicate which parameters should be wrapped if (parms.length > 64) { // If it will be an issue, then passing a static boolean array // can be an option, but for now using simple bitmask throw Context.reportRuntimeError0( "JavaAdapter can not subclass methods with more then" + " 64 arguments."); } long convertionMask = 0; for (int i = 0; i != parms.length; ++i) { if (!parms[i].isPrimitive()) { convertionMask |= (1 << i); } } cfw.addPush(convertionMask); // go through utility method, which creates a Context to run the // method in. cfw.addInvoke( ByteCode.INVOKESTATIC, "aurora/javascript/JavaAdapter", "callMethod", "(Laurora/javascript/ContextFactory;" + "Laurora/javascript/Scriptable;" + "Laurora/javascript/Function;" + "[Ljava/lang/Object;" + "J" + ")Ljava/lang/Object;"); generateReturnResult(cfw, returnType, convertResult); cfw.stopMethod((short) paramsEnd); }