public void addMethod(Method method, int access) throws Exception { boolean isAbstract = false; if (Modifier.isAbstract(access)) { access = access & ~Modifier.ABSTRACT; isAbstract = true; } Class<?>[] parameters = method.getParameterTypes(); Class<?> ret = method.getReturnType(); String sig = makeSig(ret, parameters); String name = method.getName(); names.add(name); Code code = classfile.addMethod(name, sig, access); code.aload(0); code.ldc(name); if (!isAbstract) { int tmp = code.getLocal("org/python/core/PyObject"); code.invokestatic( "org/python/compiler/ProxyMaker", "findPython", makeSig($pyObj, $pyProxy, $str)); code.astore(tmp); code.aload(tmp); Label callPython = new Label(); code.ifnonnull(callPython); String superClass = mapClass(method.getDeclaringClass()); callSuper(code, name, superClass, parameters, ret, sig); code.label(callPython); code.aload(tmp); callMethod(code, name, parameters, ret, method.getExceptionTypes()); addSuperMethod("super__" + name, name, superClass, parameters, ret, sig, access); } else { code.invokestatic( "org/python/compiler/ProxyMaker", "findPython", makeSig($pyObj, $pyProxy, $str)); code.dup(); Label returnNull = new Label(); code.ifnull(returnNull); callMethod(code, name, parameters, ret, method.getExceptionTypes()); code.label(returnNull); code.pop(); doNullReturn(code, ret); } }
public void callMethod( Code code, String name, Class<?>[] parameters, Class<?> ret, Class<?>[] exceptions) throws Exception { Label start = null; Label end = null; String jcallName = "_jcall"; int instLocal = 0; if (exceptions.length > 0) { start = new Label(); end = new Label(); jcallName = "_jcallexc"; instLocal = code.getLocal("org/python/core/PyObject"); code.astore(instLocal); code.label(start); code.aload(instLocal); } getArgs(code, parameters); switch (getType(ret)) { case tCharacter: doJavaCall(code, "char", "C", jcallName); break; case tBoolean: doJavaCall(code, "boolean", "Z", jcallName); break; case tByte: case tShort: case tInteger: doJavaCall(code, "int", "I", jcallName); break; case tLong: doJavaCall(code, "long", "J", jcallName); break; case tFloat: doJavaCall(code, "float", "F", jcallName); break; case tDouble: doJavaCall(code, "double", "D", jcallName); break; case tVoid: doJavaCall(code, "void", "V", jcallName); break; default: code.invokevirtual("org/python/core/PyObject", jcallName, makeSig($pyObj, $objArr)); code.ldc(ret.getName()); code.invokestatic("java/lang/Class", "forName", makeSig($clss, $str)); code.invokestatic("org/python/core/Py", "tojava", makeSig($obj, $pyObj, $clss)); // I guess I need this checkcast to keep the verifier happy code.checkcast(mapClass(ret)); break; } if (end != null) { code.label(end); } doReturn(code, ret); if (exceptions.length > 0) { boolean throwableFound = false; Label handlerStart = null; for (Class<?> exception : exceptions) { handlerStart = new Label(); code.label(handlerStart); int excLocal = code.getLocal("java/lang/Throwable"); code.astore(excLocal); code.aload(excLocal); code.athrow(); code.visitTryCatchBlock(start, end, handlerStart, mapClass(exception)); doNullReturn(code, ret); code.freeLocal(excLocal); if (exception == Throwable.class) throwableFound = true; } if (!throwableFound) { // The final catch (Throwable) handlerStart = new Label(); code.label(handlerStart); int excLocal = code.getLocal("java/lang/Throwable"); code.astore(excLocal); code.aload(instLocal); code.aload(excLocal); code.invokevirtual("org/python/core/PyObject", "_jthrow", makeSig("V", $throwable)); code.visitTryCatchBlock(start, end, handlerStart, "java/lang/Throwable"); code.freeLocal(excLocal); doNullReturn(code, ret); } code.freeLocal(instLocal); } }