X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.databoard%2Ftestcases%2Forg%2Fsimantics%2Fdataboard%2Ftests%2FtestASM.java;fp=bundles%2Forg.simantics.databoard%2Ftestcases%2Forg%2Fsimantics%2Fdataboard%2Ftests%2FtestASM.java;h=0dfc6a54d79531d87b8b876c39be9c24647fec76;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.databoard/testcases/org/simantics/databoard/tests/testASM.java b/bundles/org.simantics.databoard/testcases/org/simantics/databoard/tests/testASM.java new file mode 100644 index 000000000..0dfc6a54d --- /dev/null +++ b/bundles/org.simantics.databoard/testcases/org/simantics/databoard/tests/testASM.java @@ -0,0 +1,779 @@ +/******************************************************************************* + * Copyright (c) 2010 Association for Decentralized Information Management in + * Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.databoard.tests; + +import static org.objectweb.asm.Opcodes.AALOAD; +import static org.objectweb.asm.Opcodes.AASTORE; +import static org.objectweb.asm.Opcodes.ACC_ABSTRACT; +import static org.objectweb.asm.Opcodes.ACC_FINAL; +import static org.objectweb.asm.Opcodes.ACC_INTERFACE; +import static org.objectweb.asm.Opcodes.ACC_PUBLIC; +import static org.objectweb.asm.Opcodes.ACC_STATIC; +import static org.objectweb.asm.Opcodes.ACC_SUPER; +import static org.objectweb.asm.Opcodes.ALOAD; +import static org.objectweb.asm.Opcodes.ANEWARRAY; +import static org.objectweb.asm.Opcodes.ARETURN; +import static org.objectweb.asm.Opcodes.ARRAYLENGTH; +import static org.objectweb.asm.Opcodes.ASTORE; +import static org.objectweb.asm.Opcodes.ATHROW; +import static org.objectweb.asm.Opcodes.CHECKCAST; +import static org.objectweb.asm.Opcodes.DLOAD; +import static org.objectweb.asm.Opcodes.DRETURN; +import static org.objectweb.asm.Opcodes.DUP; +import static org.objectweb.asm.Opcodes.FLOAD; +import static org.objectweb.asm.Opcodes.FRETURN; +import static org.objectweb.asm.Opcodes.GETFIELD; +import static org.objectweb.asm.Opcodes.GETSTATIC; +import static org.objectweb.asm.Opcodes.GOTO; +import static org.objectweb.asm.Opcodes.ICONST_0; +import static org.objectweb.asm.Opcodes.IFEQ; +import static org.objectweb.asm.Opcodes.IF_ICMPLT; +import static org.objectweb.asm.Opcodes.ILOAD; +import static org.objectweb.asm.Opcodes.INSTANCEOF; +import static org.objectweb.asm.Opcodes.INVOKEINTERFACE; +import static org.objectweb.asm.Opcodes.INVOKESPECIAL; +import static org.objectweb.asm.Opcodes.INVOKESTATIC; +import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL; +import static org.objectweb.asm.Opcodes.IRETURN; +import static org.objectweb.asm.Opcodes.ISTORE; +import static org.objectweb.asm.Opcodes.LLOAD; +import static org.objectweb.asm.Opcodes.LRETURN; +import static org.objectweb.asm.Opcodes.NEW; +import static org.objectweb.asm.Opcodes.POP; +import static org.objectweb.asm.Opcodes.PUTFIELD; +import static org.objectweb.asm.Opcodes.PUTSTATIC; +import static org.objectweb.asm.Opcodes.RETURN; +import static org.objectweb.asm.Opcodes.V1_6; + +import java.lang.reflect.Constructor; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.simantics.databoard.Methods; +import org.simantics.databoard.binding.error.BindingConstructionException; +import org.simantics.databoard.method.InvokeException; +import org.simantics.databoard.method.MethodInterface; +import org.simantics.databoard.method.MethodInterface.AsyncResult; +import org.simantics.databoard.method.MethodInterface.ExecutionError; +import org.simantics.databoard.method.MethodInterface.Method; +import org.simantics.databoard.method.MethodInterfaceUtil; +import org.simantics.databoard.method.MethodNotSupportedException; +import org.simantics.databoard.method.MethodTypeBinding; +import org.simantics.databoard.method.RuntimeInvokeException; + +public class testASM { + + public interface Abu { + + Integer x(Integer i) throws testASM.MyException, testASM.RandomException, InvokeException; + double y(); + String hello(int[] args) throws testASM.MyException, InvokeException; + + } + + public interface Rajapinta { + + void m0(); + int m1(); + int m2(int arg0); + int m3(int arg0, int arg1); + Integer m10(int color, String name) throws InvokeException, ExecutionError; + int m11(int color, String name) throws InvokeException, ExecutionError; + } + + static class Toteutus implements Rajapinta { + Method _10, _11; + + public Integer m10(int color, String name) + throws InvokeException, ExecutionError + { + AsyncResult result = _10.invoke(new Object[] {color, name}); + try { + return (Integer) result.waitForResponse(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + public int m11(int color, String name) + throws InvokeException, ExecutionError + { + AsyncResult result = _11.invoke(new Object[] {color, name}); + try { + return (Integer) result.waitForResponse(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + @Override + public void m0() { + // TODO Auto-generated method stub + + } + + @Override + public int m1() { + // TODO Auto-generated method stub + return 666; + } + + @Override + public int m2(int arg0) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public int m3(int arg0, int arg1) { + // TODO Auto-generated method stub + return 0; + } + + + } + + + public static byte[] dump () throws Exception { + ClassWriter cw = new ClassWriter(0); + FieldVisitor fv; + MethodVisitor mv; + AnnotationVisitor av0; + + cw.visit(V1_6, ACC_SUPER, "org/simantics/data/Virhe", null, "java/lang/Object", null); + + cw.visitSource("testASM.java", null); + + { + mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + mv.visitCode(); + Label l0 = new Label(); + mv.visitLabel(l0); + mv.visitLineNumber(157, l0); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V"); + mv.visitInsn(RETURN); + Label l1 = new Label(); + mv.visitLabel(l1); + mv.visitLocalVariable("this", "Lorg/simantics/data/Virhe;", null, l0, l1, 0); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + cw.visitEnd(); + + return cw.toByteArray(); + } + + public static class MyException extends Exception { + String msg; + public MyException(String msg) { + this.msg = msg; + } + } + public static class RandomException extends Exception { + String msg; + public RandomException(String msg) { + this.msg = msg; + } + } + + public static void main(String[] args) throws Exception { + System.out.println(Object[][].class.getName()); + + System.out.println(Abu.class.getName()); + System.out.println(void.class.getName()); + System.out.println(int.class.getName()); + + try { + Toteutus t = new Toteutus(); + + Virhe3 server = new Virhe3(); + MethodInterface serverMi = MethodInterfaceUtil.bindInterface(Abu.class, server); + + StubClassLoader cl = new StubClassLoader(); + Class virhe = cl.loadClass("org.simantics.data.testASM$Abu_Stub"); +// Class virhe = cl.loadClass("org.simantics.data.Virhe2"); + + Constructor c = virhe.getConstructor(MethodInterface.class); + Abu client = (Abu) c.newInstance(serverMi); +// client = new Virhe2(serverMi); + + System.out.println(client); + System.out.println(client.hello(new int[] {0,5,0})); + System.out.println(client.y()); + System.out.println(client.x(5)); + } catch (testASM.MyException e) { + System.err.printf("MyException = %s", e.msg); + } + + } + +} + + +class Virhe3 implements testASM.Abu { + @Override + public Integer x(Integer i) throws testASM.MyException, testASM.RandomException, InvokeException { +// throw new testASM.MyException("XYZ"); + throw new testASM.RandomException("XYZ"); +// return 7; + } + @Override + public double y() { + return 5; + } + @Override + public String hello(int[] args) throws testASM.MyException, InvokeException { + return "World "+ Arrays.toString(args); + } + +} + +class Virhe2 implements testASM.Abu { +// static final MethodBinding x = new MethodBinding("x", DataTypes.getBinding(int.class), DataTypes.getBinding(void.class), DataTypes.getErrorBinding()); + static final Class interfaze = testASM.Abu.class; + static final MethodTypeBinding[] bindings; + + static { + java.lang.reflect.Method[] methods = interfaze.getMethods(); + Arrays.sort(methods, MethodInterfaceUtil.methodComparator); + + bindings = new MethodTypeBinding[methods.length]; + for (int i=0; i findClass(String name) throws ClassNotFoundException { + if (name.endsWith("_Stub")) { + Class interfaze = loadClass(name.substring(0, name.length()-5)); + ClassWriter cw = new ClassWriter(0); + createImpl(name, interfaze, cw); + byte[] b = cw.toByteArray(); + Class clazz = defineClass(name, b, 0, b.length); + return clazz; + } + return super.findClass(name); + } + + static String classToTypeDescriptor(Class clazz) { + if (clazz==void.class) return "V"; + if (clazz==boolean.class) return "Z"; + if (clazz==char.class) return "C"; + if (clazz==byte.class) return "B"; + if (clazz==short.class) return "S"; + if (clazz==int.class) return "I"; + if (clazz==float.class) return "F"; + if (clazz==long.class) return "J"; + if (clazz==double.class) return "D"; + if (clazz==void.class) return "V"; + if (clazz.isArray()) return clazz.getName(); + return "L"+clazz.getName().replaceAll("\\.", "/")+";"; + } + + void createImpl(String className, Class interfaze, ClassWriter cw) { + FieldVisitor fv; + MethodVisitor mv; + AnnotationVisitor av0; + + java.lang.reflect.Method[] methods = interfaze.getMethods(); + Arrays.sort(methods, MethodInterfaceUtil.methodComparator); + + String classResourceName = className.replaceAll("\\.", "/"); + String classTypeDescriptor = "L"+classResourceName+";"; + String interfaceResourceName = classResourceName.substring(0, classResourceName.length()-5); + String interfaceTypeDescriptor = "L"+interfaceResourceName+";"; + + cw.visit(V1_6, ACC_SUPER | ACC_PUBLIC, classResourceName, null, "java/lang/Object", new String[] { interfaceResourceName }); + + // Imports + Set> imports = new HashSet>(); + imports.add(AsyncResult.class); + imports.add(ExecutionError.class); + imports.add(Method.class); + imports.add(interfaze); + + for (java.lang.reflect.Method m : methods) { + for (Class clazz : m.getExceptionTypes()) { + imports.add(clazz); + } + for (Class clazz : m.getParameterTypes()) { + imports.add(clazz); + } + imports.add(m.getReturnType()); + } + + for (Class clazz : imports) { + if (clazz.isPrimitive()) continue; + String name = clazz.getName(); + if (name.startsWith("java.lang")) continue; + String resourceName = name.replaceAll("\\.", "/"); + String outerName = resourceName.contains("$") ? resourceName.substring(0, resourceName.indexOf('$')) : null; + String className_ = clazz.isArray() ? clazz.getSimpleName().substring(0, clazz.getSimpleName().length()-2) : clazz.getSimpleName(); + int access = ACC_PUBLIC + ACC_STATIC + (clazz.isInterface() ? ACC_INTERFACE + ACC_ABSTRACT : 0); +// System.out.printf("name=%s, outerName=%s, innerName=%s\n", resourceName, outerName, className_); + cw.visitInnerClass(resourceName, outerName, className_, access); + } + + // Fields + { + fv = cw.visitField(ACC_FINAL + ACC_STATIC, "interfaze", "Ljava/lang/Class;", "Ljava/lang/Class<*>;", null); + fv.visitEnd(); + } + { + fv = cw.visitField(ACC_FINAL + ACC_STATIC, "bindings", "[Lorg/simantics/databoard/method/MethodBinding;", null, null); + fv.visitEnd(); + } + { + fv = cw.visitField(0, "mi", "Lorg/simantics/data/session/MethodInterface;", null, null); + fv.visitEnd(); + } + { + fv = cw.visitField(0, "methods", "[Lorg/simantics/data/session/MethodInterface$Method;", null, null); + fv.visitEnd(); + } + + // Init class - static {} + { + mv = cw.visitMethod(ACC_STATIC, "", "()V", null, null); + mv.visitCode(); + Label l0 = new Label(); + mv.visitLabel(l0); + mv.visitLdcInsn(Type.getType(interfaceTypeDescriptor)); + mv.visitFieldInsn(PUTSTATIC, classResourceName, "interfaze", "Ljava/lang/Class;"); + Label l1 = new Label(); + mv.visitLabel(l1); + mv.visitFieldInsn(GETSTATIC, classResourceName, "interfaze", "Ljava/lang/Class;"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getMethods", "()[Ljava/lang/reflect/Method;"); + mv.visitVarInsn(ASTORE, 0); + Label l2 = new Label(); + mv.visitLabel(l2); + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(GETSTATIC, "org/simantics/data/network/MethodInterfaceUtil", "methodComparator", "Ljava/util/Comparator;"); + mv.visitMethodInsn(INVOKESTATIC, "java/util/Arrays", "sort", "([Ljava/lang/Object;Ljava/util/Comparator;)V"); + Label l3 = new Label(); + mv.visitLabel(l3); + mv.visitVarInsn(ALOAD, 0); + mv.visitInsn(ARRAYLENGTH); + mv.visitTypeInsn(ANEWARRAY, "org/simantics/databoard/method/MethodBinding"); + mv.visitFieldInsn(PUTSTATIC, classResourceName, "bindings", "[Lorg/simantics/databoard/method/MethodBinding;"); + Label l4 = new Label(); + mv.visitLabel(l4); + mv.visitInsn(ICONST_0); + mv.visitVarInsn(ISTORE, 1); + Label l5 = new Label(); + mv.visitLabel(l5); + Label l6 = new Label(); + mv.visitJumpInsn(GOTO, l6); + Label l7 = new Label(); + mv.visitLabel(l7); + mv.visitFrame(Opcodes.F_APPEND,2, new Object[] {"[Ljava/lang/reflect/Method;", Opcodes.INTEGER}, 0, null); + mv.visitFieldInsn(GETSTATIC, classResourceName, "bindings", "[Lorg/simantics/databoard/method/MethodBinding;"); + mv.visitVarInsn(ILOAD, 1); + mv.visitVarInsn(ALOAD, 0); + mv.visitVarInsn(ILOAD, 1); + mv.visitInsn(AALOAD); + mv.visitMethodInsn(INVOKESTATIC, "org/simantics/databoard/DataTypes", "getMethodBinding", "(Ljava/lang/reflect/Method;)Lorg/simantics/databoard/method/MethodBinding;"); + mv.visitInsn(AASTORE); + Label l8 = new Label(); + mv.visitLabel(l8); + mv.visitIincInsn(1, 1); + mv.visitLabel(l6); + mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); + mv.visitVarInsn(ILOAD, 1); + mv.visitFieldInsn(GETSTATIC, classResourceName, "bindings", "[Lorg/simantics/databoard/method/MethodBinding;"); + mv.visitInsn(ARRAYLENGTH); + mv.visitJumpInsn(IF_ICMPLT, l7); + Label l9 = new Label(); + mv.visitLabel(l9); + mv.visitInsn(RETURN); + Label l10 = new Label(); + mv.visitLabel(l10); + mv.visitLocalVariable("methods", "[Ljava/lang/reflect/Method;", null, l2, l10, 0); + mv.visitLocalVariable("i", "I", null, l5, l9, 1); + mv.visitMaxs(4, 2); + mv.visitEnd(); + } + + // Constructor + { + mv = cw.visitMethod(ACC_PUBLIC, "", "(Lorg/simantics/data/session/MethodInterface;)V", null, new String[] { "org/simantics/data/error/MethodNotSupportedException" }); + mv.visitCode(); + Label l0 = new Label(); + mv.visitLabel(l0); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V"); + Label l1 = new Label(); + mv.visitLabel(l1); + mv.visitVarInsn(ALOAD, 0); + mv.visitVarInsn(ALOAD, 1); + mv.visitFieldInsn(PUTFIELD, classResourceName, "mi", "Lorg/simantics/data/session/MethodInterface;"); + Label l2 = new Label(); + mv.visitLabel(l2); + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(GETSTATIC, classResourceName, "bindings", "[Lorg/simantics/databoard/method/MethodBinding;"); + mv.visitInsn(ARRAYLENGTH); + mv.visitTypeInsn(ANEWARRAY, "org/simantics/data/session/MethodInterface$Method"); + mv.visitFieldInsn(PUTFIELD, classResourceName, "methods", "[Lorg/simantics/data/session/MethodInterface$Method;"); + Label l3 = new Label(); + mv.visitLabel(l3); + mv.visitInsn(ICONST_0); + mv.visitVarInsn(ISTORE, 2); + Label l4 = new Label(); + mv.visitLabel(l4); + Label l5 = new Label(); + mv.visitJumpInsn(GOTO, l5); + Label l6 = new Label(); + mv.visitLabel(l6); + mv.visitFrame(Opcodes.F_FULL, 3, new Object[] {classResourceName, "org/simantics/data/session/MethodInterface", Opcodes.INTEGER}, 0, new Object[] {}); + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(GETFIELD, classResourceName, "methods", "[Lorg/simantics/data/session/MethodInterface$Method;"); + mv.visitVarInsn(ILOAD, 2); + mv.visitVarInsn(ALOAD, 1); + mv.visitFieldInsn(GETSTATIC, classResourceName, "bindings", "[Lorg/simantics/databoard/method/MethodBinding;"); + mv.visitVarInsn(ILOAD, 2); + mv.visitInsn(AALOAD); + mv.visitMethodInsn(INVOKEINTERFACE, "org/simantics/data/session/MethodInterface", "getMethod", "(Lorg/simantics/databoard/method/MethodBinding;)Lorg/simantics/data/session/MethodInterface$Method;"); + mv.visitInsn(AASTORE); + Label l7 = new Label(); + mv.visitLabel(l7); + mv.visitIincInsn(2, 1); + mv.visitLabel(l5); + mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); + mv.visitVarInsn(ILOAD, 2); + mv.visitFieldInsn(GETSTATIC, classResourceName, "bindings", "[Lorg/simantics/databoard/method/MethodBinding;"); + mv.visitInsn(ARRAYLENGTH); + mv.visitJumpInsn(IF_ICMPLT, l6); + Label l8 = new Label(); + mv.visitLabel(l8); + mv.visitInsn(RETURN); + Label l9 = new Label(); + mv.visitLabel(l9); + mv.visitLocalVariable("this", classTypeDescriptor, null, l0, l9, 0); + mv.visitLocalVariable("mi", "Lorg/simantics/data/session/MethodInterface;", null, l0, l9, 1); + mv.visitLocalVariable("i", "I", null, l4, l8, 2); + mv.visitMaxs(5, 3); + mv.visitEnd(); + } + + // Method + int methodNumber = 0; + for (java.lang.reflect.Method m : methods) + { + String typeDescription = ""; + Class[] params = m.getParameterTypes(); + for (int i=0; i0) typeDescription += ";"; + typeDescription += classToTypeDescriptor(params[i]); + } + typeDescription = "("+typeDescription+")"+classToTypeDescriptor(m.getReturnType()); + System.out.println(typeDescription+" "+m.getName()); + + Class[] exceptions = m.getExceptionTypes(); + String[] exceptionResourceNames = new String[exceptions.length]; + for (int i=0; i clazz = params[i]; + argRegs++; + if (clazz==long.class || clazz==float.class || clazz==Double.class) argRegs++; + } + + mv = cw.visitMethod(ACC_PUBLIC, m.getName(), typeDescription, null, exceptionResourceNames); + mv.visitCode(); + Label l0 = new Label(); + Label l1 = new Label(); + Label l2 = new Label(); + mv.visitTryCatchBlock(l0, l1, l2, "org/simantics/data/session/MethodInterface$ExecutionError"); + Label l3 = new Label(); + mv.visitTryCatchBlock(l0, l1, l3, "java/lang/InterruptedException"); + Label l4 = new Label(); + mv.visitLabel(l4); + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(GETFIELD, classResourceName, "methods", "[Lorg/simantics/data/session/MethodInterface$Method;"); + // Method m and puts into register + mv.visitLdcInsn(Integer.valueOf(methodNumber)); + mv.visitInsn(AALOAD); + mv.visitVarInsn(ASTORE, argRegs+1); + Label l5 = new Label(); + mv.visitLabel(l5); + mv.visitLdcInsn(Integer.valueOf(params.length)); + mv.visitTypeInsn(ANEWARRAY, "java/lang/Object"); + + int register = 1; // argument register + for (int i=0; i clazz = params[i]; + mv.visitInsn(DUP); + mv.visitLdcInsn(Integer.valueOf(i)); + + if (clazz==byte.class) { + mv.visitVarInsn(ILOAD, register++); + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;"); + } else if (clazz==char.class) { + mv.visitVarInsn(ILOAD, register++); + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;"); + } else if (clazz==boolean.class) { + mv.visitVarInsn(ILOAD, register++); + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;"); + } else if (clazz==byte.class) { + mv.visitVarInsn(ILOAD, register++); + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;"); + } else if (clazz==int.class) { + mv.visitVarInsn(ILOAD, register++); + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;"); + } else if (clazz==long.class) { + mv.visitVarInsn(LLOAD, register); register += 2; + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(F)Ljava/lang/Long;"); + } else if (clazz==float.class) { + mv.visitVarInsn(FLOAD, register); register += 2; + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;"); + } else if (clazz==Double.class) { + mv.visitVarInsn(DLOAD, register); register += 2; + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;"); + } else { + // Push argument to stack + mv.visitVarInsn(ALOAD, register++); + } + mv.visitInsn(AASTORE); + } + + // Store args to argRegs+2 + mv.visitVarInsn(ASTORE, argRegs+2); + Label l6 = new Label(); + mv.visitLabel(l6); + mv.visitVarInsn(ALOAD, argRegs+1 /* m */); + mv.visitVarInsn(ALOAD, argRegs+2 /*args*/); + mv.visitMethodInsn(INVOKEINTERFACE, "org/simantics/data/session/MethodInterface$Method", "invoke", "(Ljava/lang/Object;)Lorg/simantics/data/session/MethodInterface$AsyncResult;"); + mv.visitVarInsn(ASTORE, argRegs+3); + mv.visitLabel(l0); + mv.visitVarInsn(ALOAD, argRegs+3); + mv.visitMethodInsn(INVOKEINTERFACE, "org/simantics/data/session/MethodInterface$AsyncResult", "waitForResponse", "()Ljava/lang/Object;"); + // TODO Return typecase result + Class returnType = m.getReturnType(); + + if (returnType==void.class) { + mv.visitInsn(POP); + mv.visitInsn(RETURN); + } else if (returnType==int.class) { + mv.visitTypeInsn(CHECKCAST, "java/lang/Integer"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I"); + mv.visitLabel(l1); + mv.visitInsn(IRETURN); + } else if (returnType==byte.class) { + mv.visitTypeInsn(CHECKCAST, "java/lang/Byte"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "B()"); + mv.visitLabel(l1); + mv.visitInsn(IRETURN); + } else if (returnType==char.class) { + mv.visitTypeInsn(CHECKCAST, "java/lang/Character"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C"); + mv.visitLabel(l1); + mv.visitInsn(IRETURN); + } else if (returnType==boolean.class) { + mv.visitTypeInsn(CHECKCAST, "java/lang/Boolean"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z"); + mv.visitLabel(l1); + mv.visitInsn(IRETURN); + } else if (returnType==short.class) { + mv.visitTypeInsn(CHECKCAST, "java/lang/Short"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S"); + mv.visitLabel(l1); + mv.visitInsn(IRETURN); + } else if (returnType==long.class) { + mv.visitTypeInsn(CHECKCAST, "java/lang/Long"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J"); + mv.visitLabel(l1); + mv.visitInsn(LRETURN); + } else if (returnType==double.class) { + mv.visitTypeInsn(CHECKCAST, "java/lang/Double"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D"); + mv.visitLabel(l1); + mv.visitInsn(DRETURN); + } else if (returnType==float.class) { + mv.visitTypeInsn(CHECKCAST, "java/lang/Float"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F"); + mv.visitLabel(l1); + mv.visitInsn(FRETURN); + } else { + // Object + mv.visitTypeInsn(CHECKCAST, returnType.getName().replaceAll("\\.", "/")); + mv.visitLabel(l1); + mv.visitInsn(ARETURN); + } + + + // Handle exceptions + mv.visitLabel(l2); + mv.visitFrame(Opcodes.F_FULL, argRegs+4, new Object[] {classResourceName, "java/lang/Integer", "org/simantics/data/session/MethodInterface$Method", "[Ljava/lang/Object;", "org/simantics/data/session/MethodInterface$AsyncResult"}, 1, new Object[] {"org/simantics/data/session/MethodInterface$ExecutionError"}); + mv.visitVarInsn(ASTORE, argRegs+4); + Label l7 = new Label(); + mv.visitLabel(l7); + mv.visitVarInsn(ALOAD, argRegs+4); + mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/data/session/MethodInterface$ExecutionError", "getError", "()Ljava/lang/Object;"); + mv.visitVarInsn(ASTORE, argRegs+5); // argRegs+5 <- ExecutionError.cause + + Class[] exceptionClasses = m.getExceptionTypes(); + Label nextException[] = new Label[exceptionClasses.length]; + for (int i=0; i exceptionClass = exceptionClasses[i]; + String exceptionClassResourceName = exceptionClass.getName().replaceAll("\\.", "/"); + nextException[i] = new Label(); + // If instanceof MyException + Label l8 = new Label(); + mv.visitLabel(l8); + mv.visitVarInsn(ALOAD, argRegs+5); // Cause + mv.visitTypeInsn(INSTANCEOF, exceptionClassResourceName); + mv.visitJumpInsn(IFEQ, nextException[i]); // If not, go to ExecutionError + // If so, throw it + mv.visitVarInsn(ALOAD, argRegs+5); // e + mv.visitTypeInsn(CHECKCAST, exceptionClassResourceName); + mv.visitInsn(ATHROW); + mv.visitLabel(nextException[i]); + } + + // ExecutionError + mv.visitFrame(Opcodes.F_APPEND,argRegs+1, new Object[] {"org/simantics/data/session/MethodInterface$ExecutionError", "java/lang/Object"}, 0, null); + mv.visitTypeInsn(NEW, "java/lang/RuntimeException"); + mv.visitInsn(DUP); + mv.visitVarInsn(ALOAD, argRegs+4); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "", "(Ljava/lang/Throwable;)V"); + mv.visitInsn(ATHROW); + + // InteruptedException + mv.visitLabel(l3); + mv.visitFrame(Opcodes.F_FULL, argRegs+4, new Object[] {classResourceName, "java/lang/Integer", "org/simantics/data/session/MethodInterface$Method", "[Ljava/lang/Object;", "org/simantics/data/session/MethodInterface$AsyncResult"}, 1, new Object[] {"java/lang/InterruptedException"}); + mv.visitVarInsn(ASTORE, argRegs+4); + Label l10 = new Label(); + mv.visitLabel(l10); + mv.visitTypeInsn(NEW, "java/lang/RuntimeException"); + mv.visitInsn(DUP); + mv.visitVarInsn(ALOAD, argRegs+4); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "", "(Ljava/lang/Throwable;)V"); + mv.visitInsn(ATHROW); + + Label l11 = new Label(); + mv.visitLabel(l11); + mv.visitLocalVariable("this", classTypeDescriptor, null, l4, l11, 0); +// mv.visitLocalVariable("arg1", "Ljava/lang/Integer;", null, l4, l11, 1); + register = 1; + for (int i=0; i clazz = params[i]; + mv.visitLocalVariable("arg"+(i+1), classToTypeDescriptor(clazz), null, l4, l11, register); + register++; + if (clazz==long.class || clazz==float.class || clazz==Double.class) argRegs++; + } + mv.visitLocalVariable("m", "Lorg/simantics/data/session/MethodInterface$Method;", null, l5, l11, argRegs+1); + mv.visitLocalVariable("args", "[Ljava/lang/Object;", null, l6, l11, argRegs+2); + mv.visitLocalVariable("result", "Lorg/simantics/data/session/MethodInterface$AsyncResult;", null, l0, l11, argRegs+3); + mv.visitLocalVariable("e", "Lorg/simantics/data/session/MethodInterface$ExecutionError;", null, l7, l3, argRegs+4); + mv.visitLocalVariable("cause", "Ljava/lang/Object;", null, l7, l3, argRegs+5); + mv.visitLocalVariable("e", "Ljava/lang/InterruptedException;", null, l10, l11, argRegs+4); + mv.visitMaxs(argRegs+3, argRegs+6); + mv.visitEnd(); + methodNumber++; + } + + cw.visitEnd(); + } + +} +