[Jython-checkins] jython: Implement a simple JIT for ctypes functions.

wayne.meissner jython-checkins at python.org
Sun Sep 4 03:55:25 CEST 2011


http://hg.python.org/jython/rev/e3b713cd58c9
changeset:   6236:e3b713cd58c9
user:        Wayne Meissner <wmeissner at gmail.com>
date:        Fri Jun 17 21:41:57 2011 +1000
summary:
  Implement a simple JIT for ctypes functions.

files:
  src/org/python/modules/jffi/AbstractNumericMethodGenerator.java |  359 +++
  src/org/python/modules/jffi/AsmClassBuilder.java                |  203 ++
  src/org/python/modules/jffi/CodegenUtils.java                   |  255 ++
  src/org/python/modules/jffi/DefaultInvokerFactory.java          |  102 +-
  src/org/python/modules/jffi/FastIntInvokerFactory.java          |  656 -------
  src/org/python/modules/jffi/FastIntMethodGenerator.java         |  141 +
  src/org/python/modules/jffi/FastLongMethodGenerator.java        |  129 +
  src/org/python/modules/jffi/FastNumericMethodGenerator.java     |  128 +
  src/org/python/modules/jffi/Function.java                       |   88 +-
  src/org/python/modules/jffi/JITCompiler.java                    |  100 +
  src/org/python/modules/jffi/JITHandle.java                      |   86 +
  src/org/python/modules/jffi/JITInvoker.java                     |   66 +
  src/org/python/modules/jffi/JITInvoker0.java                    |   36 +
  src/org/python/modules/jffi/JITInvoker1.java                    |   36 +
  src/org/python/modules/jffi/JITInvoker2.java                    |   36 +
  src/org/python/modules/jffi/JITInvoker3.java                    |   36 +
  src/org/python/modules/jffi/JITInvoker4.java                    |   36 +
  src/org/python/modules/jffi/JITInvoker5.java                    |   36 +
  src/org/python/modules/jffi/JITInvoker6.java                    |   40 +
  src/org/python/modules/jffi/JITMethodGenerator.java             |   11 +
  src/org/python/modules/jffi/JITRuntime.java                     |  180 +
  src/org/python/modules/jffi/JITSignature.java                   |   81 +
  src/org/python/modules/jffi/NativeDataConverter.java            |   35 +
  src/org/python/modules/jffi/NativeType.java                     |    3 +
  src/org/python/modules/jffi/SkinnyMethodAdapter.java            |  915 ++++++++++
  25 files changed, 3067 insertions(+), 727 deletions(-)


diff --git a/src/org/python/modules/jffi/AbstractNumericMethodGenerator.java b/src/org/python/modules/jffi/AbstractNumericMethodGenerator.java
new file mode 100644
--- /dev/null
+++ b/src/org/python/modules/jffi/AbstractNumericMethodGenerator.java
@@ -0,0 +1,359 @@
+package org.python.modules.jffi;
+
+import com.kenai.jffi.Platform;
+import org.objectweb.asm.Label;
+import org.python.core.PyObject;
+
+import static org.python.modules.jffi.CodegenUtils.*;
+import static org.objectweb.asm.Opcodes.ACC_FINAL;
+import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
+
+/**
+ *
+ */
+abstract class AbstractNumericMethodGenerator implements JITMethodGenerator {
+
+    public void generate(AsmClassBuilder builder, String functionName, JITSignature signature) {
+        SkinnyMethodAdapter mv = new SkinnyMethodAdapter(builder.getClassVisitor(),
+                ACC_PUBLIC | ACC_FINAL, functionName,
+                sig(PyObject.class, params(PyObject.class, signature.getParameterCount())),
+                null, null);
+
+        mv.start();
+        generate(builder, mv, signature);
+        mv.visitMaxs(10, 10);
+        mv.visitEnd();
+    }
+
+    public void generate(AsmClassBuilder builder, SkinnyMethodAdapter mv, JITSignature signature) {
+        final Class nativeIntType = getInvokerIntType();
+        int maxPointerIndex = -1;
+        Label[] fallback = new Label[signature.getParameterCount()];
+        for (int i = 0; i < signature.getParameterCount(); i++) {
+            fallback[i] = new Label();
+        }
+
+        mv.getstatic(builder.getClassName(), "jffiInvoker", ci(com.kenai.jffi.Invoker.class));
+        mv.aload(0);
+        mv.getfield(builder.getClassName(), builder.getFunctionFieldName(), ci(com.kenai.jffi.Function.class));
+        // [ stack now contains: Invoker, Function ]
+        final int firstParam = 1;
+        
+        // Perform any generic data conversions on the parameters
+        for (int i = 0; i < signature.getParameterCount(); ++i) {
+            if (signature.hasParameterConverter(i)) {
+                mv.aload(0); // this
+                mv.getfield(builder.getClassName(), builder.getParameterConverterFieldName(i), ci(NativeDataConverter.class));
+                mv.aload(firstParam + i); // PyObject
+                mv.invokevirtual(p(NativeDataConverter.class), "toNative", sig(PyObject.class, PyObject.class));
+                mv.astore(firstParam + i);
+            }
+        }
+
+        // Load and un-box parameters
+        for (int i = 0; i < signature.getParameterCount(); ++i) {
+            final NativeType parameterType = signature.getParameterType(i);
+            final int paramVar = i + firstParam;
+            mv.aload(paramVar);
+            switch (parameterType) {
+                case BOOL:
+                    unbox(mv, "boolValue");
+                    break;
+
+                case BYTE:
+                    unbox(mv, "s8Value");
+                    break;
+                
+                case UBYTE:
+                    unbox(mv, "u8Value");
+                    break;
+                
+                case SHORT:
+                    unbox(mv, "s16Value");
+                    break;
+                
+                case USHORT:
+                    unbox(mv, "u16Value");
+                    break;
+                
+                case INT:
+                    unbox(mv, "s32Value");
+                    break;
+                
+                case UINT:
+                    unbox(mv, "u32Value");
+                    break;
+                    
+                case LONG:
+                    if (Platform.getPlatform().longSize() == 32) {
+                        unbox(mv, "s32Value");
+                    } else {
+                        unbox(mv, "s64Value");
+                    }
+                    break;
+                
+                case ULONG:
+                    if (Platform.getPlatform().longSize() == 32) {
+                        unbox(mv, "u32Value");
+                    } else {
+                        unbox(mv, "u64Value");
+                    }
+                    break;
+                
+                case LONGLONG:
+                    unbox(mv, "s64Value");
+                    break;
+                
+                case ULONGLONG:
+                    unbox(mv, "u64Value");
+                    break;
+                
+                case POINTER:
+                    maxPointerIndex = i;
+                    Label direct = new Label();
+                    Label done = new Label();
+                    Label converted = new Label();
+                    
+                    // If a direct pointer is passed in, jump straight to conversion
+                    mv.instance_of(p(Pointer.class));
+                    mv.iftrue(direct);
+
+                    mv.aload(paramVar);
+                    mv.invokestatic(p(JITRuntime.class), "other2ptr", sig(PyObject.class, PyObject.class));
+                    mv.label(converted);
+                    mv.dup();
+                    mv.astore(paramVar);
+                    mv.instance_of(p(Pointer.class));
+                    mv.iffalse(fallback[i]);
+                    
+                    mv.label(direct);
+                    // The parameter is guaranteed to be a direct pointer now
+                    mv.aload(paramVar);
+                    unbox(mv, "pointerValue");
+                    mv.label(done);
+                    break;
+
+                case FLOAT:
+                    unbox(mv, "float2int");
+                    break;
+
+                case DOUBLE:
+                    unbox(mv, "double2long");
+                    break;
+
+                default:
+                    throw new UnsupportedOperationException("unsupported parameter type " + parameterType);
+            }
+        }
+
+        // stack now contains [ Invoker, Function, int/long args ]
+        mv.invokevirtual(p(com.kenai.jffi.Invoker.class),
+                getInvokerMethodName(signature),
+                getInvokerSignature(signature.getParameterCount()));
+
+
+        // box up the raw int/long result
+        boxResult(mv, signature.getResultType());
+        emitResultConversion(mv, builder, signature);;
+        mv.areturn();
+        
+        // Generate code to pop all the converted arguments off the stack 
+        // when falling back to buffer-invocation
+        if (maxPointerIndex >= 0) {
+            for (int i = maxPointerIndex; i > 0; i--) {
+                mv.label(fallback[i]);
+                if (int.class == nativeIntType) {
+                    mv.pop();
+                } else {
+                    mv.pop2();
+                }
+            }
+
+            mv.label(fallback[0]);
+            // Pop ThreadContext, Invoker and Function
+            mv.pop(); mv.pop();
+            
+            // Call the fallback invoker
+            mv.aload(0);
+            mv.getfield(builder.getClassName(), builder.getFallbackInvokerFieldName(), ci(Invoker.class));
+
+            for (int i = 0; i < signature.getParameterCount(); i++) {
+                mv.aload(firstParam + i);
+            }
+            
+            mv.invokevirtual(p(Invoker.class), "invoke",
+                    sig(PyObject.class, params(PyObject.class, signature.getParameterCount())));
+            emitResultConversion(mv, builder, signature);
+            mv.areturn();
+        }
+    }
+
+    private void emitResultConversion(SkinnyMethodAdapter mv, AsmClassBuilder builder, JITSignature signature) {
+        if (signature.hasResultConverter()) {
+            mv.aload(0); // [ result, this ]
+            mv.getfield(builder.getClassName(), builder.getResultConverterFieldName(), ci(NativeDataConverter.class));
+            mv.swap();   // [ converter, result ]
+            mv.invokevirtual(p(NativeDataConverter.class), "fromNative", sig(PyObject.class, PyObject.class));
+        }
+    }
+    
+    private void boxResult(SkinnyMethodAdapter mv, NativeType type,
+            String boxMethodName, Class primitiveType) {
+        // convert to the appropriate primitive result type
+        narrow(mv, getInvokerIntType(), primitiveType);
+        widen(mv, getInvokerIntType(), primitiveType);
+        
+        mv.invokestatic(p(JITRuntime.class), boxMethodName,
+                sig(PyObject.class, primitiveType));
+    }
+
+    private void boxResult(SkinnyMethodAdapter mv, NativeType type) {
+        switch (type) {
+            case BOOL:
+                boxResult(mv, type, "newBoolean", getInvokerIntType());
+                break;
+
+            case BYTE:
+                boxResult(mv, type, "newSigned8", byte.class);
+                break;
+
+            case UBYTE:
+                boxResult(mv, type, "newUnsigned8", byte.class);
+                break;
+
+            case SHORT:
+                boxResult(mv, type, "newSigned16", short.class);
+                break;
+
+            case USHORT:
+                boxResult(mv, type, "newUnsigned16", short.class);
+                break;
+
+            case INT:
+                boxResult(mv, type, "newSigned32", int.class);
+                break;
+
+            case UINT:
+                boxResult(mv, type, "newUnsigned32", int.class);
+                break;
+
+            case LONG:
+                if (Platform.getPlatform().longSize() == 32) {
+                    boxResult(mv, type, "newSigned32", int.class);
+                } else {
+                    boxResult(mv, type, "newSigned64", long.class);
+                }
+                break;
+
+            case ULONG:
+                if (Platform.getPlatform().longSize() == 32) {
+                    boxResult(mv, type, "newUnsigned32", int.class);
+                } else {
+                    boxResult(mv, type, "newUnsigned64", long.class);
+                }
+                break;
+
+            case LONGLONG:
+                boxResult(mv, type, "newSigned64", long.class);
+                break;
+
+            case ULONGLONG:
+                boxResult(mv, type, "newUnsigned64", long.class);
+                break;
+                
+            case FLOAT:
+                boxResult(mv, type, "newFloat32", int.class);
+                break;
+                
+            case DOUBLE:
+                boxResult(mv, type, "newFloat64", long.class);
+                break;
+
+            case VOID:
+                boxResult(mv, type, "newNil", getInvokerIntType());
+                break;
+
+            case POINTER:
+                boxResult(mv, type, "newPointer" + Platform.getPlatform().addressSize(),
+                    getInvokerIntType());
+                break;
+
+            case STRING:
+                boxResult(mv, type, "newString", getInvokerIntType());
+                break;
+
+
+            default:
+                throw new UnsupportedOperationException("native return type not supported: " + type);
+
+        }
+    }
+
+    private void unbox(SkinnyMethodAdapter mv, String method) {
+        mv.invokestatic(p(JITRuntime.class), getRuntimeMethod(method), sig(getInvokerIntType(), PyObject.class));
+    }
+
+    private String getRuntimeMethod(String method) {
+        return method + (int.class == getInvokerIntType() ? "32" : "64");
+    }
+
+    abstract String getInvokerMethodName(JITSignature signature);
+
+    abstract String getInvokerSignature(int parameterCount);
+
+    abstract Class getInvokerIntType();
+
+
+    public static boolean isPrimitiveInt(Class c) {
+        return byte.class == c || char.class == c || short.class == c || int.class == c || boolean.class == c;
+    }
+
+    public static final void widen(SkinnyMethodAdapter mv, Class from, Class to) {
+        if (long.class == to && long.class != from && isPrimitiveInt(from)) {
+            mv.i2l();
+        }
+    }
+
+    public static final void narrow(SkinnyMethodAdapter mv, Class from, Class to) {
+        if (!from.equals(to) && isPrimitiveInt(to)) {
+            if (long.class == from) {
+                mv.l2i();
+            }
+
+            if (byte.class == to) {
+                mv.i2b();
+
+            } else if (short.class == to) {
+                mv.i2s();
+
+            } else if (char.class == to) {
+                mv.i2c();
+
+            } else if (boolean.class == to) {
+                // Ensure only 0x0 and 0x1 values are used for boolean
+                mv.iconst_1();
+                mv.iand();
+            }
+        }
+    }
+    
+    protected static String[] buildSignatures(Class nativeIntClass, int maxParameters) {
+        char sigChar = int.class == nativeIntClass ? 'I' : 'J';
+        
+        String[] signatures = new String[maxParameters + 1];
+        for (int i = 0; i < signatures.length; i++) {
+            
+            StringBuilder sb = new StringBuilder();
+            
+            sb.append('(').append(ci(com.kenai.jffi.Function.class));
+            
+            for (int n = 0; n < i; n++) {
+                sb.append(sigChar);
+            }
+            
+            signatures[i] = sb.append(")").append(sigChar).toString();
+        }
+        
+        return signatures;
+    }
+}
diff --git a/src/org/python/modules/jffi/AsmClassBuilder.java b/src/org/python/modules/jffi/AsmClassBuilder.java
new file mode 100644
--- /dev/null
+++ b/src/org/python/modules/jffi/AsmClassBuilder.java
@@ -0,0 +1,203 @@
+package org.python.modules.jffi;
+
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.commons.EmptyVisitor;
+
+import java.io.PrintWriter;
+import java.lang.reflect.Constructor;
+import java.util.concurrent.atomic.AtomicLong;
+
+import static org.python.modules.jffi.CodegenUtils.*;
+import static org.objectweb.asm.Opcodes.*;
+
+/**
+ * 
+ */
+final class AsmClassBuilder {
+    public static final boolean DEBUG = false || Boolean.getBoolean("jython.ctypes.compile.dump");
+    private static final AtomicLong nextClassID = new AtomicLong(0);
+    private final JITSignature signature;
+    private final ClassWriter classWriter;
+    private final ClassVisitor classVisitor;
+    private final String className;
+    private final Class parentClass;
+    private final JITMethodGenerator generator;
+    
+    AsmClassBuilder(JITMethodGenerator generator, JITSignature signature) {
+        this.generator = generator;
+        this.signature = signature;
+        
+        switch (signature.getParameterCount()) {
+            case 0:
+                parentClass = JITInvoker0.class;
+                break;
+            case 1:
+                parentClass = JITInvoker1.class;
+                break;
+            case 2:
+                parentClass = JITInvoker2.class;
+                break;
+            case 3:
+                parentClass = JITInvoker3.class;
+                break;
+            case 4:
+                parentClass = JITInvoker4.class;
+                break;
+            case 5:
+                parentClass = JITInvoker5.class;
+                break;
+            case 6:
+                parentClass = JITInvoker6.class;
+                break;
+            default:
+                throw new UnsupportedOperationException("arity " 
+                        + signature.getParameterCount()  + " not supported");
+        }
+        
+        className = p(Invoker.class) + "$ffi$" + nextClassID.getAndIncrement();
+        
+        classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
+        classVisitor = DEBUG ? newCheckClassAdapter(classWriter) : classWriter;
+        classVisitor.visit(V1_5, ACC_PUBLIC | ACC_FINAL, className, null, 
+                p(parentClass), new String[0]);
+    }
+    
+    Class<? extends Invoker> build() {
+        // Create the constructor to set the 'library' & functions fields
+        SkinnyMethodAdapter init = new SkinnyMethodAdapter(classVisitor, ACC_PUBLIC, "<init>",
+                sig(void.class, com.kenai.jffi.Function.class, NativeDataConverter.class, 
+                    NativeDataConverter[].class, Invoker.class),
+                null, null);
+        
+        init.start();
+        // Invokes the super class constructor as super(Library)
+
+        init.aload(0);
+        
+        init.invokespecial(p(parentClass), "<init>", sig(void.class));
+        
+        // Save the function argument in a field
+        classVisitor.visitField(ACC_PRIVATE | ACC_FINAL, getFunctionFieldName(), 
+                ci(com.kenai.jffi.Function.class), null, null);
+        init.aload(0);
+        init.aload(1);
+        init.putfield(className, getFunctionFieldName(), ci(com.kenai.jffi.Function.class));
+        
+        if (signature.hasResultConverter()) {
+            // Save the result converter argument in a field
+            classVisitor.visitField(ACC_PRIVATE | ACC_FINAL, getResultConverterFieldName(),
+                    ci(NativeDataConverter.class), null, null);
+            init.aload(0);
+            init.aload(2);
+            init.putfield(className, getResultConverterFieldName(), ci(NativeDataConverter.class));
+        }
+        
+        // Now load & store the parameter converter array
+        for (int i = 0; i < signature.getParameterCount(); i++) {
+            if (signature.hasParameterConverter(i)) {
+                classVisitor.visitField(ACC_PRIVATE | ACC_FINAL, getParameterConverterFieldName(i),
+                        ci(NativeDataConverter.class), null, null);
+                init.aload(0);
+                init.aload(3);
+                init.pushInt(i);
+                init.aaload();
+                init.putfield(className, getParameterConverterFieldName(i), ci(NativeDataConverter.class));
+            }
+        }
+        
+        classVisitor.visitField(ACC_PRIVATE | ACC_FINAL, getFallbackInvokerFieldName(), 
+                ci(Invoker.class), null, null);
+        init.aload(0);
+        init.aload(4);
+        init.putfield(className, getFallbackInvokerFieldName(), ci(Invoker.class));
+        
+        init.voidreturn();
+        init.visitMaxs(10, 10);
+        init.visitEnd();
+        
+        generator.generate(this, "invoke", signature);
+
+        classVisitor.visitEnd();
+
+        try {
+            byte[] bytes = classWriter.toByteArray();
+            if (DEBUG) {
+                ClassVisitor trace = newTraceClassVisitor(new PrintWriter(System.err));
+                new ClassReader(bytes).accept(trace, 0);
+            }
+
+            JITClassLoader loader = new JITClassLoader(getClass().getClassLoader());
+            
+            return loader.defineClass(c(className), bytes);
+            
+        } catch (Throwable ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+    
+    public static ClassVisitor newCheckClassAdapter(ClassVisitor cv) {
+        try {
+            Class<? extends ClassVisitor> tmvClass = Class.forName("org.objectweb.asm.util.CheckClassAdapter").asSubclass(ClassVisitor.class);
+            Constructor<? extends ClassVisitor> c = tmvClass.getDeclaredConstructor(ClassVisitor.class);
+            return c.newInstance(cv);
+        } catch (Throwable t) {
+            return cv;
+        }
+    }
+    
+    public static final ClassVisitor newTraceClassVisitor(PrintWriter out) {
+        try {
+
+            Class<? extends ClassVisitor> tmvClass = Class.forName("org.objectweb.asm.util.TraceClassVisitor").asSubclass(ClassVisitor.class);
+            Constructor<? extends ClassVisitor> c = tmvClass.getDeclaredConstructor(PrintWriter.class);
+            return c.newInstance(out);
+        } catch (Throwable t) {
+            return new EmptyVisitor();
+        }
+    }
+
+    
+    final String getFunctionFieldName() {
+        return "function";
+    }
+    
+    final String getResultConverterFieldName() {
+        return "resultConverter";
+    }
+    
+    final String getParameterConverterFieldName(int i) {
+        return "parameterConverter" + i;
+    }
+
+    final String getFallbackInvokerFieldName() {
+        return "fallbackInvoker";
+    }
+
+    final ClassVisitor getClassVisitor() {
+        return classVisitor;
+    }
+    
+    final String getClassName() {
+        return className;
+    }
+    
+    
+    static final class JITClassLoader extends ClassLoader {
+
+        public JITClassLoader() {
+        }
+
+        public JITClassLoader(ClassLoader parent) {
+            super(parent);
+        }
+
+        public Class defineClass(String name, byte[] b) {
+            Class klass = defineClass(name, b, 0, b.length);
+            resolveClass(klass);
+            return klass;
+        }
+        
+    }
+}
diff --git a/src/org/python/modules/jffi/CodegenUtils.java b/src/org/python/modules/jffi/CodegenUtils.java
new file mode 100644
--- /dev/null
+++ b/src/org/python/modules/jffi/CodegenUtils.java
@@ -0,0 +1,255 @@
+/*
+ * CodegenUtils.java
+ *
+ * Created on January 31, 2007, 11:54 AM
+ *
+ * To change this template, choose Tools | Template Manager
+ * and open the template in the editor.
+ */
+
+package org.python.modules.jffi;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Type;
+
+import java.util.Arrays;
+import java.util.Map;
+
+/**
+ *
+ * @author headius
+ */
+public class CodegenUtils {
+    /**
+     * Creates a dotted class name from a path/package name
+     */
+    public static String c(String p) {
+        return p.replace('/', '.');
+    }
+
+    /**
+     * Creates a class path name, from a Class.
+     */
+    public static String p(Class n) {
+        return n.getName().replace('.','/');
+    }
+
+    /**
+     * Creates a class identifier of form Labc/abc;, from a Class.
+     */
+    public static String ci(Class n) {
+        if (n.isArray()) {
+            n = n.getComponentType();
+            if (n.isPrimitive()) {
+                if (n == Byte.TYPE) {
+                    return "[B";
+                } else if (n == Boolean.TYPE) {
+                    return "[Z";
+                } else if (n == Short.TYPE) {
+                    return "[S";
+                } else if (n == Character.TYPE) {
+                    return "[C";
+                } else if (n == Integer.TYPE) {
+                    return "[I";
+                } else if (n == Float.TYPE) {
+                    return "[F";
+                } else if (n == Double.TYPE) {
+                    return "[D";
+                } else if (n == Long.TYPE) {
+                    return "[J";
+                } else {
+                    throw new RuntimeException("Unrecognized type in compiler: " + n.getName());
+                }
+            } else {
+                return "[" + ci(n);
+            }
+        } else {
+            if (n.isPrimitive()) {
+                if (n == Byte.TYPE) {
+                    return "B";
+                } else if (n == Boolean.TYPE) {
+                    return "Z";
+                } else if (n == Short.TYPE) {
+                    return "S";
+                } else if (n == Character.TYPE) {
+                    return "C";
+                } else if (n == Integer.TYPE) {
+                    return "I";
+                } else if (n == Float.TYPE) {
+                    return "F";
+                } else if (n == Double.TYPE) {
+                    return "D";
+                } else if (n == Long.TYPE) {
+                    return "J";
+                } else if (n == Void.TYPE) {
+                    return "V";
+                } else {
+                    throw new RuntimeException("Unrecognized type in compiler: " + n.getName());
+                }
+            } else {
+                return "L" + p(n) + ";";
+            }
+        }
+    }
+
+    /**
+     * Creates a human-readable representation, from a Class.
+     */
+    public static String human(Class n) {
+        return n.getCanonicalName();
+    }
+    
+    public static String humanShort(Class n) {
+        return n.getSimpleName();
+    }
+    
+    /**
+     * Create a method signature from the given param types and return values
+     */
+    public static String sig(Class retval, Class... params) {
+        return sigParams(params) + ci(retval);
+    }
+    
+    public static String sig(Class[] retvalParams) {
+        Class[] justParams = new Class[retvalParams.length - 1];
+        System.arraycopy(retvalParams, 1, justParams, 0, justParams.length);
+        return sigParams(justParams) + ci(retvalParams[0]);
+    }
+
+    public static String sig(Class retval, String descriptor, Class... params) {
+        return sigParams(descriptor, params) + ci(retval);
+    }
+
+    public static String sigParams(Class... params) {
+        StringBuilder signature = new StringBuilder("(");
+        
+        for (int i = 0; i < params.length; i++) {
+            signature.append(ci(params[i]));
+        }
+        
+        signature.append(")");
+        
+        return signature.toString();
+    }
+
+    public static String sigParams(String descriptor, Class... params) {
+        StringBuilder signature = new StringBuilder("(");
+
+        signature.append(descriptor);
+        
+        for (int i = 0; i < params.length; i++) {
+            signature.append(ci(params[i]));
+        }
+
+        signature.append(")");
+
+        return signature.toString();
+    }
+    
+    public static String pretty(Class retval, Class... params) {
+        return prettyParams(params) + human(retval);
+    }
+    
+    public static String prettyParams(Class... params) {
+        StringBuilder signature = new StringBuilder("(");
+        
+        for (int i = 0; i < params.length; i++) {
+            signature.append(human(params[i]));
+            if (i < params.length - 1) signature.append(',');
+        }
+        
+        signature.append(")");
+        
+        return signature.toString();
+    }
+    
+    public static String prettyShortParams(Class... params) {
+        StringBuilder signature = new StringBuilder("(");
+        
+        for (int i = 0; i < params.length; i++) {
+            signature.append(humanShort(params[i]));
+            if (i < params.length - 1) signature.append(',');
+        }
+        
+        signature.append(")");
+        
+        return signature.toString();
+    }
+    
+    public static Class[] params(Class... classes) {
+        return classes;
+    }
+    
+    public static Class[] params(Class cls, int times) {
+        Class[] classes = new Class[times];
+        Arrays.fill(classes, cls);
+        return classes;
+    }
+    
+    public static Class[] params(Class cls1, Class clsFill, int times) {
+        Class[] classes = new Class[times + 1];
+        Arrays.fill(classes, clsFill);
+        classes[0] = cls1;
+        return classes;
+    }
+
+    public static Class[] params(Class cls1, Class cls2, Class clsFill, int times) {
+        Class[] classes = new Class[times + 2];
+        Arrays.fill(classes, clsFill);
+        classes[0] = cls1;
+        classes[1] = cls2;
+        return classes;
+    }
+    
+    public static String getAnnotatedBindingClassName(String javaMethodName, String typeName, boolean isStatic, int required, int optional, boolean multi, boolean framed) {
+        String commonClassSuffix;
+        if (multi) {
+            commonClassSuffix = (isStatic ? "$s$" : "$i$" ) + javaMethodName;
+        } else {
+            commonClassSuffix = (isStatic ? "$s$" : "$i$" ) + required + "$" + optional + "$" + javaMethodName;
+        }
+        return typeName + commonClassSuffix;
+    }
+
+    public static void visitAnnotationFields(AnnotationVisitor visitor, Map<String, Object> fields) {
+        for (Map.Entry<String, Object> fieldEntry : fields.entrySet()) {
+            Object value = fieldEntry.getValue();
+            if (value.getClass().isArray()) {
+                Object[] values = (Object[]) value;
+                AnnotationVisitor arrayV = visitor.visitArray(fieldEntry.getKey());
+                for (int i = 0; i < values.length; i++) {
+                    arrayV.visit(null, values[i]);
+                }
+                arrayV.visitEnd();
+            } else if (value.getClass().isEnum()) {
+                visitor.visitEnum(fieldEntry.getKey(), ci(value.getClass()), value.toString());
+            } else if (value instanceof Class) {
+                visitor.visit(fieldEntry.getKey(), Type.getType((Class) value));
+            } else {
+                visitor.visit(fieldEntry.getKey(), value);
+            }
+        }
+    }
+
+    public static Class getBoxType(Class type) {
+        if (type == int.class) {
+            return Integer.class;
+        } else if (type == byte.class) {
+            return Byte.class;
+        } else if (type == short.class) {
+            return Short.class;
+        } else if (type == char.class) {
+            return Character.class;
+        } else if (type == long.class) {
+            return Long.class;
+        } else if (type == float.class) {
+            return Float.class;
+        } else if (type == double.class) {
+            return Double.class;
+        } else if (type == boolean.class) {
+            return Boolean.class;
+        } else {
+            throw new RuntimeException("Not a native type: " + type);
+        }
+    }
+}
diff --git a/src/org/python/modules/jffi/DefaultInvokerFactory.java b/src/org/python/modules/jffi/DefaultInvokerFactory.java
--- a/src/org/python/modules/jffi/DefaultInvokerFactory.java
+++ b/src/org/python/modules/jffi/DefaultInvokerFactory.java
@@ -38,67 +38,83 @@
 
         return createInvoker(function, returnType, marshallers);
     }
+
+    final Invoker createInvoker(com.kenai.jffi.Function function, NativeType[] parameterTypes, NativeType returnType) {
+        ParameterMarshaller[] marshallers = new ParameterMarshaller[parameterTypes.length];
+
+        for (int i = 0; i < marshallers.length; ++i) {
+            marshallers[i] = getMarshaller(parameterTypes[i]);
+        }
+
+        return createInvoker(function, returnType, marshallers);
+    }
+
     final Invoker createInvoker(com.kenai.jffi.Function function, PyObject returnType, ParameterMarshaller[] marshallers) {
         CType cReturnType = CType.typeOf(returnType);
         if (cReturnType instanceof CType.Builtin) {
-            switch (cReturnType.getNativeType()) {
-                case VOID:
-                    return new VoidInvoker(function, marshallers);
+            return createInvoker(function, cReturnType.getNativeType(), marshallers);
+        }
 
-                case BYTE:
-                    return new Signed8Invoker(function, marshallers);
+        throw Py.RuntimeError("Unsupported return type: " + returnType);
+    }
 
-                case UBYTE:
-                    return new Unsigned8Invoker(function, marshallers);
+    final Invoker createInvoker(com.kenai.jffi.Function function, NativeType returnType, ParameterMarshaller[] marshallers) {
+        switch (returnType) {
+            case VOID:
+                return new VoidInvoker(function, marshallers);
 
-                case SHORT:
-                    return new Signed16Invoker(function, marshallers);
+            case BYTE:
+                return new Signed8Invoker(function, marshallers);
 
-                case USHORT:
-                    return new Unsigned16Invoker(function, marshallers);
+            case UBYTE:
+                return new Unsigned8Invoker(function, marshallers);
 
-                case INT:
-                    return new Signed32Invoker(function, marshallers);
+            case SHORT:
+                return new Signed16Invoker(function, marshallers);
 
-                case UINT:
-                    return new Unsigned32Invoker(function, marshallers);
+            case USHORT:
+                return new Unsigned16Invoker(function, marshallers);
 
-                case LONGLONG:
-                    return new Signed64Invoker(function, marshallers);
+            case INT:
+                return new Signed32Invoker(function, marshallers);
 
-                case ULONGLONG:
-                    return new Unsigned64Invoker(function, marshallers);
+            case UINT:
+                return new Unsigned32Invoker(function, marshallers);
 
-                case LONG:
-                    return Platform.getPlatform().longSize() == 32
-                            ? new Signed32Invoker(function, marshallers)
-                            : new Signed64Invoker(function, marshallers);
+            case LONGLONG:
+                return new Signed64Invoker(function, marshallers);
 
-                case ULONG:
-                    return Platform.getPlatform().longSize() == 32
-                            ? new Unsigned32Invoker(function, marshallers)
-                            : new Unsigned64Invoker(function, marshallers);
-                case FLOAT:
-                    return new FloatInvoker(function, marshallers);
+            case ULONGLONG:
+                return new Unsigned64Invoker(function, marshallers);
 
-                case DOUBLE:
-                    return new DoubleInvoker(function, marshallers);
+            case LONG:
+                return Platform.getPlatform().longSize() == 32
+                        ? new Signed32Invoker(function, marshallers)
+                        : new Signed64Invoker(function, marshallers);
 
-                case POINTER:
-                    return new PointerInvoker(function, marshallers);
+            case ULONG:
+                return Platform.getPlatform().longSize() == 32
+                        ? new Unsigned32Invoker(function, marshallers)
+                        : new Unsigned64Invoker(function, marshallers);
+            case FLOAT:
+                return new FloatInvoker(function, marshallers);
 
-                case STRING:
-                    return new StringInvoker(function, marshallers);
+            case DOUBLE:
+                return new DoubleInvoker(function, marshallers);
 
-                default:
-                    break;
-            }
+            case POINTER:
+                return new PointerInvoker(function, marshallers);
+
+            case STRING:
+                return new StringInvoker(function, marshallers);
+
+            default:
+                break;
         }
         throw Py.RuntimeError("Unsupported return type: " + returnType);
-        
     }
 
-    private static final ParameterMarshaller getMarshaller(NativeType type) {
+    static final ParameterMarshaller getMarshaller(NativeType type) {
         switch (type) {
 
             case BYTE:
@@ -144,7 +160,7 @@
         }
     }
 
-    private static final ParameterMarshaller getMarshaller(CType type) {
+    static final ParameterMarshaller getMarshaller(CType type) {
         if (type instanceof CType.Builtin) {
             return getMarshaller(type.getNativeType());
         } else if (type instanceof CType.Pointer) {
@@ -154,11 +170,11 @@
         }
     }
 
-    private static final ParameterMarshaller getMarshaller(PyObject type) {
+    static final ParameterMarshaller getMarshaller(PyObject type) {
         return getMarshaller(CType.typeOf(type));
     }
 
-    private static interface ParameterMarshaller {
+    static interface ParameterMarshaller {
         void marshal(HeapInvocationBuffer buffer, PyObject arg);
     }
 
diff --git a/src/org/python/modules/jffi/FastIntInvokerFactory.java b/src/org/python/modules/jffi/FastIntInvokerFactory.java
deleted file mode 100644
--- a/src/org/python/modules/jffi/FastIntInvokerFactory.java
+++ /dev/null
@@ -1,656 +0,0 @@
-
-package org.python.modules.jffi;
-
-import com.kenai.jffi.Function;
-import com.kenai.jffi.Platform;
-import org.python.core.Py;
-import org.python.core.PyObject;
-
-
-/**
- * A factory which generates {@link Invoker} instances that are optimized for
- * 32 bit integer and float parameters / result types with 3 or less parameters.
- *
- * Technical background:  Instead of trying to cram all calls down a generic call
- * path, then figuring out how to convert the parameters in the native code on
- * each call, jffi supplies arity and type specific call paths that can be
- * optimized ahead of time by the native code.
- *
- * The downside of this approach is more java code to wire up the functions and
- * call them using the arity+type specific paths, but in the case of int and float
- * parameters, it can result in more than a 100% speed boost over the generic path.
- */
-public class FastIntInvokerFactory {
-    private static final class SingletonHolder {
-        private static final FastIntInvokerFactory INSTANCE = new FastIntInvokerFactory();
-    }
-
-    private FastIntInvokerFactory() {}
-
-    public static final FastIntInvokerFactory getFactory() {
-        return SingletonHolder.INSTANCE;
-    }
-
-    /**
-     * Interface used to convert from a python object to a native integer
-     */
-    private static interface IntParameterConverter {
-        int intValue(PyObject value);
-    }
-
-    /**
-     * Interface used to convert from a native integer to a python object
-     */
-    private static interface IntResultConverter {
-        PyObject pyValue(int value);
-    }
-
-    /**
-     * Tests if a combination of result and parameter types can be called using
-     * an {@link Invoker} created by this factory.
-     *
-     * @param returnType The return type of the native function.
-     * @param parameterTypes The parameter types of the native function.
-     * @return <tt>true</tt> if the method can be handled as a fast int method.
-     */
-    final boolean isFastIntMethod(CType returnType, CType[] parameterTypes) {
-        for (int i = 0; i < parameterTypes.length; ++i) {
-            if (!isFastIntParam(parameterTypes[i])) {
-                return false;
-            }
-        }
-        return parameterTypes.length <= 3 && isFastIntResult(returnType);
-    }
-
-    /**
-     * Tests if a combination of result and parameter types can be called using
-     * an {@link Invoker} created by this factory.
-     *
-     * @param returnType The return type of the native function.
-     * @param parameterTypes The parameter types of the native function.
-     * @return <tt>true</tt> if the method can be handled as a fast int method.
-     */
-    final boolean isFastIntMethod(PyObject returnType, PyObject[] parameterTypes) {
-        for (int i = 0; i < parameterTypes.length; ++i) {
-            if (!isFastIntParam(parameterTypes[i])) {
-                return false;
-            }
-        }
-        return parameterTypes.length <= 3 && isFastIntResult(returnType);
-    }
-
-    /**
-     * Tests if the type can be returned as an integer result.
-     *
-     * @param type The result type.
-     * @return <tt>true</tt> if <tt>type</tt> can be returned as an integer.
-     */
-    final boolean isFastIntResult(CType type) {
-        if (type instanceof CType.Builtin) {
-            switch (type.getNativeType()) {
-                case VOID:
-                case BYTE:
-                case UBYTE:
-                case SHORT:
-                case USHORT:
-                case INT:
-                case UINT:
-                    return true;
-
-                case LONG:
-                case ULONG:
-                    return Platform.getPlatform().longSize() == 32;
-
-                case STRING:
-                    return Platform.getPlatform().addressSize() == 32;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Tests if the type can be returned as an integer result.
-     *
-     * @param type The result type.
-     * @return <tt>true</tt> if <tt>type</tt> can be returned as an integer.
-     */
-    final boolean isFastIntResult(PyObject type) {
-        return isFastIntResult(CType.typeOf(type));
-    }
-
-    /**
-     * Tests if the type can be passed as an integer parameter.
-     *
-     * @param type The parameter type.
-     * @return <tt>true</tt> if <tt>type</tt> can be passed as an integer.
-     */
-    final boolean isFastIntParam(CType paramType) {
-        if (paramType instanceof CType.Builtin) {
-            switch (paramType.getNativeType()) {
-                case BYTE:
-                case UBYTE:
-                case SHORT:
-                case USHORT:
-                case INT:
-                case UINT:
-                    return true;
-
-                case LONG:
-                case ULONG:
-                    return Platform.getPlatform().longSize() == 32;
-            }
-        }
-
-        return false;
-    }
-
-    /**
-     * Tests if the type can be passed as an integer parameter.
-     *
-     * @param type The parameter type.
-     * @return <tt>true</tt> if <tt>type</tt> can be passed as an integer.
-     */
-    final boolean isFastIntParam(PyObject paramType) {
-        return isFastIntParam(CType.typeOf(paramType));
-    }
-
-    /**
-     * Creates a new <tt>Invoker</tt> instance for the given function, with the
-     * given parameter types and return type.
-     *
-     * @param function The JFFI function to wrap
-     * @param parameterTypes The parameter types the function will be called with
-     * @param returnType The result type the function will return
-     * @return A new {@link Invoker} instance.
-     */
-    final Invoker createInvoker(Function function, CType[] parameterTypes, CType returnType) {
-        IntParameterConverter[] parameterConverters = new IntParameterConverter[parameterTypes.length];
-        
-        for (int i = 0; i < parameterConverters.length; ++i) {
-            parameterConverters[i] = getIntParameterConverter(parameterTypes[i]);
-        }
-        
-        return createIntInvoker(function, getIntResultConverter(returnType), parameterConverters);
-    }
-
-    /**
-     * Creates a new <tt>Invoker</tt> instance for the given function, with the
-     * given parameter types and return type.
-     *
-     * @param function The JFFI function to wrap
-     * @param parameterTypes The parameter types the function will be called with
-     * @param returnType The result type the function will return
-     * @return A new {@link Invoker} instance.
-     */
-    final Invoker createInvoker(Function function, PyObject returnType, PyObject[] parameterTypes) {
-        IntParameterConverter[] parameterConverters = new IntParameterConverter[parameterTypes.length];
-
-        for (int i = 0; i < parameterConverters.length; ++i) {
-            parameterConverters[i] = getIntParameterConverter(parameterTypes[i]);
-        }
-
-        return createIntInvoker(function, getIntResultConverter(returnType), parameterConverters);
-    }
-
-    final Invoker createIntInvoker(Function function, IntResultConverter resultConverter, IntParameterConverter[] parameterConverters) {
-        switch (parameterConverters.length) {
-            case 0:
-                return new FastIntInvokerZero(function, resultConverter, parameterConverters);
-            case 1:
-                return new FastIntInvokerOne(function, resultConverter, parameterConverters);
-            case 2:
-                return new FastIntInvokerTwo(function, resultConverter, parameterConverters);
-            case 3:
-                return new FastIntInvokerThree(function, resultConverter, parameterConverters);
-        }
-        throw Py.RuntimeError("fast int invoker does not support functions with arity=" + parameterConverters.length);
-    }
-
-
-    /**
-     * Gets a python object to integer parameter converter.
-     *
-     * @param type The python C type
-     * @return An <tt>IntParameterConverter</tt> instance.
-     */
-    final IntParameterConverter getIntParameterConverter(CType type) {
-        if (type instanceof CType.Builtin) {
-            return getIntParameterConverter(type.getNativeType());
-        }
-        throw Py.TypeError("cannot convert objects of type " + type + " to int");
-    }
-
-    /**
-     * Gets a python object to integer parameter converter.
-     *
-     * @param type The python C type
-     * @return An <tt>IntParameterConverter</tt> instance.
-     */
-    final IntParameterConverter getIntParameterConverter(PyObject type) {
-        return getIntParameterConverter(CType.typeOf(type));
-    }
-
-    /**
-     * Gets a python object to integer parameter converter.
-     *
-     * @param type The object type.
-     * @return An <tt>IntParameterConverter</tt> instance.
-     */
-    final IntParameterConverter getIntParameterConverter(NativeType type) {
-        switch (type) {
-            case BYTE:
-                return Signed8ParameterConverter.INSTANCE;
-            
-            case UBYTE:
-                return Unsigned8ParameterConverter.INSTANCE;
-            
-            case SHORT:
-                return Signed16ParameterConverter.INSTANCE;
-            
-            case USHORT:
-                return Unsigned16ParameterConverter.INSTANCE;
-            
-            case INT:
-                return Signed32ParameterConverter.INSTANCE;
-            
-            case UINT:
-                return Unsigned32ParameterConverter.INSTANCE;
-
-            case LONG:
-                if (Platform.getPlatform().longSize() == 32) {
-                    return Signed32ParameterConverter.INSTANCE;
-                }
-                break;
-
-            case ULONG:
-                if (Platform.getPlatform().longSize() == 32) {
-                    return Unsigned32ParameterConverter.INSTANCE;
-                }
-                break;
-
-            case FLOAT:
-                if (Platform.getPlatform().getCPU() == Platform.CPU.I386
-                        || Platform.getPlatform().getCPU() == Platform.CPU.X86_64) {
-                    return Float32ParameterConverter.INSTANCE;
-                }
-                break;
-            default:
-                break;
-        }
-
-        throw Py.TypeError("cannot convert objects of type " + type + " to int");
-    }
-    
-
-    /**
-     * Gets a int to python object result converter for the type.
-     *
-     * @param type The object type.
-     * @return An <tt>IntResultConverter</tt> instance.
-     */
-    final IntResultConverter getIntResultConverter(PyObject type) {
-        return getIntResultConverter(CType.typeOf(type));
-    }
-
-    /**
-     * Gets a int to python object result converter for the type.
-     *
-     * @param type The object type.
-     * @return An <tt>IntResultConverter</tt> instance.
-     */
-    final IntResultConverter getIntResultConverter(CType type) {
-        return type instanceof CType.Builtin ? getIntResultConverter(type.getNativeType()) : null;
-    }
-
-    
-    /**
-     * Gets a int to python object result converter for the type.
-     *
-     * @param type The object type.
-     * @return An <tt>IntResultConverter</tt> instance.
-     */
-    final IntResultConverter getIntResultConverter(NativeType type) {
-        switch (type) {
-            case VOID:
-                return VoidResultConverter.INSTANCE;
-            
-            case BYTE:
-                return Signed8ResultConverter.INSTANCE;
-            
-            case UBYTE:
-                return Unsigned8ResultConverter.INSTANCE;
-            
-            case SHORT:
-                return Signed16ResultConverter.INSTANCE;
-            
-            case USHORT:
-                return Unsigned16ResultConverter.INSTANCE;
-            
-            case INT:
-                return Signed32ResultConverter.INSTANCE;
-            
-            case UINT:
-                return Unsigned32ResultConverter.INSTANCE;
-
-            case LONG:
-                if (Platform.getPlatform().longSize() == 32) {
-                    return Signed32ResultConverter.INSTANCE;
-                }
-                break;
-
-            case ULONG:
-                if (Platform.getPlatform().longSize() == 32) {
-                    return Unsigned32ResultConverter.INSTANCE;
-                }
-                break;
-
-            case STRING:
-                if (Platform.getPlatform().addressSize() == 32) {
-                    return StringResultConverter.INSTANCE;
-                }
-                break;
-
-            default:
-                break;
-        }
-        throw new IllegalArgumentException("Cannot convert objects of type " + type + " from int");
-    }
-
-    /**
-     * Base class for all fast-int {@link Invoker} subclasses
-     */
-    private static abstract class BaseFastIntInvoker implements Invoker {
-        final com.kenai.jffi.Invoker jffiInvoker = com.kenai.jffi.Invoker.getInstance();
-        final Function function;
-        final IntResultConverter resultConverter;
-        final int arity;
-        final IntParameterConverter c0, c1, c2;
-
-        BaseFastIntInvoker(Function function, IntResultConverter resultConverter,
-                IntParameterConverter[] parameterConverters) {
-            this.function = function;
-            this.resultConverter = resultConverter;
-            this.arity = parameterConverters.length;
-            c0 = parameterConverters.length > 0 ? parameterConverters[0] : null;
-            c1 = parameterConverters.length > 1 ? parameterConverters[1] : null;
-            c2 = parameterConverters.length > 2 ? parameterConverters[2] : null;
-        }
-
-        final void checkArity(PyObject[] args) {
-            checkArity(args.length);
-        }
-
-        final void checkArity(int got) {
-            if (got != arity) {
-                throw Py.TypeError(String.format("__call__() takes exactly %d arguments (%d given)", arity, got));
-            }
-        }
-        public PyObject invoke(PyObject[] args) {
-            checkArity(args);
-            switch (arity) {
-                case 0:
-                    return invoke();
-                case 1:
-                    return invoke(args[0]);
-                case 2:
-                    return invoke(args[0], args[1]);
-                case 3:
-                    return invoke(args[0], args[1], args[2]);
-                default:
-                    throw Py.RuntimeError("invalid fast-int arity");
-            }
-        }
-
-        public PyObject invoke() {
-            checkArity(0);
-            return Py.None;
-        }
-
-        public PyObject invoke(PyObject arg1) {
-            checkArity(1);
-            return Py.None;
-        }
-
-        public PyObject invoke(PyObject arg1, PyObject arg2) {
-            checkArity(2);
-            return Py.None;
-        }
-
-        public PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3) {
-            checkArity(3);
-            return Py.None;
-        }
-
-    }
-
-    /**
-     * Fast-int invoker that takes no parameters.
-     */
-    private static final class FastIntInvokerZero extends BaseFastIntInvoker {
-
-        public FastIntInvokerZero(Function function, IntResultConverter resultConverter,
-                IntParameterConverter parameterConverters[]) {
-            super(function, resultConverter, parameterConverters);
-        }
-
-        @Override
-        public final PyObject invoke() {
-            return resultConverter.pyValue(jffiInvoker.invokeVrI(function));
-        }
-    }
-
-    /**
-     * Fast-int invoker that takes a single parameter
-     */
-    private static final class FastIntInvokerOne extends BaseFastIntInvoker {
-        public FastIntInvokerOne(Function function, IntResultConverter resultConverter,
-                IntParameterConverter parameterConverters[]) {
-            super(function, resultConverter, parameterConverters);
-            
-        }
-
-        @Override
-        public final PyObject invoke(PyObject arg0) {
-            return resultConverter.pyValue(jffiInvoker.invokeIrI(function,
-                    c0.intValue(arg0)));
-        }
-    }
-
-
-    /**
-     * Fast-int invoker that takes two parameters
-     */
-    private static final class FastIntInvokerTwo extends BaseFastIntInvoker {
-        
-        public FastIntInvokerTwo(Function function, IntResultConverter resultConverter,
-                IntParameterConverter parameterConverters[]) {
-            super(function, resultConverter, parameterConverters);
-        }
-
-        @Override
-        public PyObject invoke(PyObject arg0, PyObject arg1) {
-            return resultConverter.pyValue(jffiInvoker.invokeIIrI(function,
-                    c0.intValue(arg0), c1.intValue(arg1)));
-        }
-    }
-
-    /**
-     * Fast-int invoker that takes three parameters
-     */
-    private static final class FastIntInvokerThree extends BaseFastIntInvoker {
-        
-        public FastIntInvokerThree(Function function, IntResultConverter resultConverter,
-                IntParameterConverter parameterConverters[]) {
-            super(function, resultConverter, parameterConverters);
-        }
-
-        @Override
-        public PyObject invoke(PyObject arg0, PyObject arg1, PyObject arg2) {
-            return resultConverter.pyValue(jffiInvoker.invokeIIIrI(function,
-                    c0.intValue(arg0), c1.intValue(arg1), c2.intValue(arg2)));
-        }
-    }
-   
-    /**
-     * Base class for all fast-int result converters
-     */
-    static abstract class BaseResultConverter implements IntResultConverter {
-        
-    }
-
-    /**
-     * Converts a native void result into into a python None instance
-     */
-    static final class VoidResultConverter extends BaseResultConverter {
-        public static final IntResultConverter INSTANCE = new VoidResultConverter();
-        public final PyObject pyValue(int value) {
-            return Py.None;
-        }
-    }
-
-    /**
-     * Converts a native signed byte result into into a python integer instance
-     */
-    static final class Signed8ResultConverter extends BaseResultConverter {
-        public static final IntResultConverter INSTANCE = new Signed8ResultConverter();
-        public final PyObject pyValue(int value) {
-            return Util.newSigned8(value);
-        }
-    }
-
-    /**
-     * Converts a native unsigned byte result into into a python integer instance
-     */
-    static final class Unsigned8ResultConverter extends BaseResultConverter {
-        public static final IntResultConverter INSTANCE = new Unsigned8ResultConverter();
-        public final PyObject pyValue(int value) {
-            return Util.newUnsigned8(value);
-        }
-    }
-
-    /**
-     * Converts a native signed short result into into a python integer instance
-     */
-    static final class Signed16ResultConverter extends BaseResultConverter {
-        public static final IntResultConverter INSTANCE = new Signed16ResultConverter();
-        public final PyObject pyValue(int value) {
-            return Util.newSigned16(value);
-        }
-    }
-
-    /**
-     * Converts a native unsigned short result into into a python integer instance
-     */
-    static final class Unsigned16ResultConverter extends BaseResultConverter {
-        public static final IntResultConverter INSTANCE = new Unsigned16ResultConverter();
-        public final PyObject pyValue(int value) {
-            return Util.newUnsigned16(value);
-        }
-    }
-
-    /**
-     * Converts a native signed int result into into a python integer instance
-     */
-    static final class Signed32ResultConverter extends BaseResultConverter {
-        public static final IntResultConverter INSTANCE = new Signed32ResultConverter();
-        public final PyObject pyValue(int value) {
-            return Util.newSigned32(value);
-        }
-    }
-
-    /**
-     * Converts a native unsigned int result into into a python integer instance
-     */
-    static final class Unsigned32ResultConverter extends BaseResultConverter {
-        public static final IntResultConverter INSTANCE = new Unsigned32ResultConverter();
-        public final PyObject pyValue(int value) {
-            return Util.newUnsigned32(value);
-        }
-    }
-
-    /**
-     * Converts a native string address result into into a python string instance
-     */
-    static final class StringResultConverter extends BaseResultConverter {
-        public static final IntResultConverter INSTANCE = new StringResultConverter();
-        public final PyObject pyValue(int value) {
-            return Util.newString(value);
-        }
-    }
-
-    /**
-     * Base class for all integer parameter converters.
-     */
-    static abstract class BaseParameterConverter implements IntParameterConverter {
-    }
-
-    /**
-     * Converter for python signed byte to native int
-     */
-    static final class Signed8ParameterConverter extends BaseParameterConverter {
-        public static final IntParameterConverter INSTANCE = new Signed8ParameterConverter();
-        public final int intValue(PyObject obj) {
-            return Util.int8Value(obj);
-        }
-    }
-
-    /**
-     * Converter for python unsigned byte to native int
-     */
-    static final class Unsigned8ParameterConverter extends BaseParameterConverter {
-        public static final IntParameterConverter INSTANCE = new Unsigned8ParameterConverter();
-        public final int intValue(PyObject obj) {
-            return Util.uint8Value(obj);
-        }
-    }
-
-    /**
-     * Converter for python signed short to native int
-     */
-    static final class Signed16ParameterConverter extends BaseParameterConverter {
-        public static final IntParameterConverter INSTANCE = new Signed16ParameterConverter();
-        public final int intValue(PyObject obj) {
-            return Util.int16Value(obj);
-        }
-    }
-
-    /**
-     * Converter for python unsigned short to native int
-     */
-    static final class Unsigned16ParameterConverter extends BaseParameterConverter {
-        public static final IntParameterConverter INSTANCE = new Unsigned16ParameterConverter();
-        public final int intValue(PyObject obj) {
-            return Util.uint16Value(obj);
-        }
-    }
-
-    /**
-     * Converter for python signed int to native int
-     */
-    static final class Signed32ParameterConverter extends BaseParameterConverter {
-        public static final IntParameterConverter INSTANCE = new Signed32ParameterConverter();
-        public final int intValue(PyObject obj) {
-            return Util.int32Value(obj);
-        }
-    }
-
-    /**
-     * Converter for python unsigned int to native int
-     */
-    static final class Unsigned32ParameterConverter extends BaseParameterConverter {
-        public static final IntParameterConverter INSTANCE = new Unsigned32ParameterConverter();
-        public final int intValue(PyObject obj) {
-            return Util.uint32Value(obj);
-        }
-    }
-
-    /**
-     * Converter for python float to native int parameter
-     */
-    static final class Float32ParameterConverter extends BaseParameterConverter {
-        public static final IntParameterConverter INSTANCE = new Float32ParameterConverter();
-        public final int intValue(PyObject obj) {
-            return Float.floatToIntBits((float) obj.asDouble());
-        }
-    }
-}
diff --git a/src/org/python/modules/jffi/FastIntMethodGenerator.java b/src/org/python/modules/jffi/FastIntMethodGenerator.java
new file mode 100644
--- /dev/null
+++ b/src/org/python/modules/jffi/FastIntMethodGenerator.java
@@ -0,0 +1,141 @@
+package org.python.modules.jffi;
+
+
+import com.kenai.jffi.CallingConvention;
+import com.kenai.jffi.Platform;
+
+/**
+ *
+ */
+final class FastIntMethodGenerator extends AbstractNumericMethodGenerator {
+    private static final int MAX_PARAMETERS = getMaximumFastIntParameters();
+
+    private static final String[] signatures = buildSignatures(int.class, MAX_PARAMETERS);
+
+    private static final String[] methodNames = {
+        "invokeVrI", "invokeIrI", "invokeIIrI", "invokeIIIrI", "invokeIIIIrI", "invokeIIIIIrI", "invokeIIIIIIrI"
+    };
+
+    private static final String[] noErrnoMethodNames = {
+        "invokeNoErrnoVrI", "invokeNoErrnoIrI", "invokeNoErrnoIIrI", "invokeNoErrnoIIIrI"
+    };
+    
+    String getInvokerMethodName(JITSignature signature) {
+
+        final int parameterCount = signature.getParameterCount();
+
+        if (signature.isIgnoreError() && parameterCount <= MAX_PARAMETERS && parameterCount <= noErrnoMethodNames.length) {
+            return noErrnoMethodNames[signature.getParameterCount()];
+
+        } else if (parameterCount <= MAX_PARAMETERS && parameterCount <= methodNames.length) {
+            return methodNames[parameterCount];
+
+        } else {
+            throw new IllegalArgumentException("invalid fast-int parameter count: " + parameterCount);
+        }
+    }
+
+    String getInvokerSignature(int parameterCount) {
+        if (parameterCount <= MAX_PARAMETERS && parameterCount <= signatures.length) {
+            return signatures[parameterCount];
+        }
+        throw new IllegalArgumentException("invalid fast-int parameter count: " + parameterCount);
+    }
+
+    final Class getInvokerIntType() {
+        return int.class;
+    }
+
+    public boolean isSupported(JITSignature signature) {
+        final int parameterCount = signature.getParameterCount();
+
+        if (!signature.getCallingConvention().equals(CallingConvention.DEFAULT) || parameterCount > MAX_PARAMETERS) {
+            return false;
+        }
+
+        final Platform platform = Platform.getPlatform();
+
+        if (platform.getOS().equals(Platform.OS.WINDOWS)) {
+            return false;
+        }
+
+        if (!platform.getCPU().equals(Platform.CPU.I386) && !platform.getCPU().equals(Platform.CPU.X86_64)) {
+            return false;
+        }
+
+        for (int i = 0; i < parameterCount; i++) {
+            if (!isFastIntParameter(platform, signature.getParameterType(i))) {
+                return false;
+            }
+        }
+
+        return isFastIntResult(platform, signature.getResultType());
+    }
+
+
+    final static int getMaximumFastIntParameters() {
+        try {
+            com.kenai.jffi.Invoker.class.getDeclaredMethod("invokeIIIIIIrI", com.kenai.jffi.Function.class,
+                    int.class, int.class, int.class, int.class, int.class, int.class);
+            return 6;
+        } catch (NoSuchMethodException nex) {
+            try {
+                com.kenai.jffi.Invoker.class.getDeclaredMethod("invokeIIIrI", com.kenai.jffi.Function.class,
+                        int.class, int.class, int.class);
+                return 3;
+            } catch (NoSuchMethodException nex2) {
+                return -1;
+            }
+        } catch (Throwable t) {
+            return -1;
+        }
+    }
+
+
+    private static boolean isFastIntType(Platform platform, NativeType type) {
+        switch (type) {
+            case BOOL:
+            case BYTE:
+            case UBYTE:
+            case SHORT:
+            case USHORT:
+            case INT:
+            case UINT:
+                return true;
+                
+            case LONG:
+            case ULONG:
+                return platform.longSize() == 32;
+                
+            default:
+                return false;
+        }
+    }
+
+
+    static boolean isFastIntResult(Platform platform, NativeType type) {
+        switch (type) {
+            case VOID:
+                return true;
+
+            case POINTER:
+            case STRING:
+                return platform.addressSize() == 32;
+
+            default:
+                return isFastIntType(platform, type);
+        }
+    }
+
+    static boolean isFastIntParameter(Platform platform, NativeType type) {
+        switch (type) {
+            case POINTER:
+            case BUFFER_IN:
+            case BUFFER_OUT:
+            case BUFFER_INOUT:
+                return platform.addressSize() == 32;
+            default:
+                return isFastIntType(platform, type);
+        }
+    }
+}
diff --git a/src/org/python/modules/jffi/FastLongMethodGenerator.java b/src/org/python/modules/jffi/FastLongMethodGenerator.java
new file mode 100644
--- /dev/null
+++ b/src/org/python/modules/jffi/FastLongMethodGenerator.java
@@ -0,0 +1,129 @@
+package org.python.modules.jffi;
+
+
+import com.kenai.jffi.CallingConvention;
+import com.kenai.jffi.Platform;
+
+/**
+ *
+ */
+final class FastLongMethodGenerator extends AbstractNumericMethodGenerator {
+    private static final int MAX_PARAMETERS = getMaximumFastLongParameters();
+
+    private static final String[] signatures = buildSignatures(long.class, MAX_PARAMETERS);
+
+    private static final String[] methodNames = {
+        "invokeVrL", "invokeLrL", "invokeLLrL", "invokeLLLrL", "invokeLLLLrL", "invokeLLLLLrL", "invokeLLLLLLrL"
+    };
+
+    String getInvokerMethodName(JITSignature signature) {
+
+        final int parameterCount = signature.getParameterCount();
+
+        if (parameterCount <= MAX_PARAMETERS && parameterCount <= methodNames.length) {
+            return methodNames[parameterCount];
+
+        } else {
+            throw new IllegalArgumentException("invalid fast-long parameter count: " + parameterCount);
+        }
+    }
+
+    String getInvokerSignature(int parameterCount) {
+        if (parameterCount <= MAX_PARAMETERS && parameterCount <= signatures.length) {
+            return signatures[parameterCount];
+        }
+        throw new IllegalArgumentException("invalid fast-long parameter count: " + parameterCount);
+    }
+
+    final Class getInvokerIntType() {
+        return long.class;
+    }
+
+    public boolean isSupported(JITSignature signature) {
+        final int parameterCount = signature.getParameterCount();
+
+        if (!signature.getCallingConvention().equals(CallingConvention.DEFAULT) || parameterCount > MAX_PARAMETERS) {
+            return false;
+        }
+
+        final Platform platform = Platform.getPlatform();
+
+        if (platform.getOS().equals(Platform.OS.WINDOWS)) {
+            return false;
+        }
+
+        // Only supported on amd64 arches
+        if (!platform.getCPU().equals(Platform.CPU.X86_64)) {
+            return false;
+        }
+
+        for (int i = 0; i < parameterCount; i++) {
+            if (!isFastLongParameter(platform, signature.getParameterType(i))) {
+                return false;
+            }
+        }
+
+        return isFastLongResult(platform, signature.getResultType());
+    }
+
+
+    final static int getMaximumFastLongParameters() {
+        try {
+            com.kenai.jffi.Invoker.class.getDeclaredMethod("invokeLLLLLLrL", com.kenai.jffi.Function.class,
+                    long.class, long.class, long.class, long.class, long.class, long.class);
+            return 6;
+        } catch (Throwable t) {
+            return -1;
+        }
+    }
+
+
+    private static boolean isFastLongType(Platform platform, NativeType type) {
+        switch (type) {
+            case BOOL:
+            case BYTE:
+            case UBYTE:
+            case SHORT:
+            case USHORT:
+            case INT:
+            case UINT:
+            case LONG:
+            case ULONG:
+            case LONGLONG:
+            case ULONGLONG:
+            case POINTER:
+                return true;
+
+            default:
+                return false;
+        }
+    }
+
+
+    static boolean isFastLongResult(Platform platform, NativeType type) {
+        switch (type) {
+            case VOID:
+                return true;
+                
+            case POINTER:
+            case STRING:
+                return platform.addressSize() == 64;
+
+            default:
+                return isFastLongType(platform, type);
+        }
+    }
+
+    static boolean isFastLongParameter(Platform platform, NativeType type) {
+        switch (type) {
+            case POINTER:
+            case BUFFER_IN:
+            case BUFFER_OUT:
+            case BUFFER_INOUT:
+                return platform.addressSize() == 64;
+            
+            default:
+                return isFastLongType(platform, type);
+        }
+    }
+}
diff --git a/src/org/python/modules/jffi/FastNumericMethodGenerator.java b/src/org/python/modules/jffi/FastNumericMethodGenerator.java
new file mode 100644
--- /dev/null
+++ b/src/org/python/modules/jffi/FastNumericMethodGenerator.java
@@ -0,0 +1,128 @@
+package org.python.modules.jffi;
+
+
+import com.kenai.jffi.CallingConvention;
+import com.kenai.jffi.Platform;
+
+/**
+ *
+ */
+final class FastNumericMethodGenerator extends AbstractNumericMethodGenerator {
+    private static final int MAX_PARAMETERS = getMaximumFastNumericParameters();
+
+    private static final String[] signatures = buildSignatures(long.class, MAX_PARAMETERS);
+
+    private static final String[] methodNames = {
+        "invokeVrN", "invokeNrN", "invokeNNrN", "invokeNNNrN", "invokeNNNNrN", "invokeNNNNNrN", "invokeNNNNNNrN"
+    };
+
+    String getInvokerMethodName(JITSignature signature) {
+
+        final int parameterCount = signature.getParameterCount();
+
+        if (parameterCount <= MAX_PARAMETERS && parameterCount <= methodNames.length) {
+            return methodNames[parameterCount];
+
+        } else {
+            throw new IllegalArgumentException("invalid fast-long parameter count: " + parameterCount);
+        }
+    }
+
+    String getInvokerSignature(int parameterCount) {
+        if (parameterCount <= MAX_PARAMETERS && parameterCount <= signatures.length) {
+            return signatures[parameterCount];
+        }
+        throw new IllegalArgumentException("invalid fast-long parameter count: " + parameterCount);
+    }
+
+    final Class getInvokerIntType() {
+        return long.class;
+    }
+
+    public boolean isSupported(JITSignature signature) {
+        final int parameterCount = signature.getParameterCount();
+
+        if (!signature.getCallingConvention().equals(CallingConvention.DEFAULT) || parameterCount > MAX_PARAMETERS) {
+            return false;
+        }
+
+        final Platform platform = Platform.getPlatform();
+
+        if (platform.getOS().equals(Platform.OS.WINDOWS)) {
+            return false;
+        }
+
+        // Only supported on amd64 arches
+        if (!platform.getCPU().equals(Platform.CPU.I386) && !platform.getCPU().equals(Platform.CPU.X86_64)) {
+            return false;
+        }
+
+        for (int i = 0; i < parameterCount; i++) {
+            if (!isFastNumericParameter(platform, signature.getParameterType(i))) {
+                return false;
+            }
+        }
+
+        return isFastNumericResult(platform, signature.getResultType());
+    }
+
+
+    final static int getMaximumFastNumericParameters() {
+        try {
+            com.kenai.jffi.Invoker.class.getDeclaredMethod("invokeNNNNNNrN", com.kenai.jffi.Function.class,
+                    long.class, long.class, long.class, long.class, long.class, long.class);
+            return 6;
+        } catch (Throwable t) {
+            return -1;
+        }
+    }
+
+
+    private static boolean isFastNumericType(Platform platform, NativeType type) {
+        switch (type) {
+            case BOOL:
+            case BYTE:
+            case UBYTE:
+            case SHORT:
+            case USHORT:
+            case INT:
+            case UINT:
+            case LONG:
+            case ULONG:
+            case LONGLONG:
+            case ULONGLONG:
+            case FLOAT:
+            case DOUBLE:
+                return true;
+
+            default:
+                return false;
+        }
+    }
+
+
+    static boolean isFastNumericResult(Platform platform, NativeType type) {
+        switch (type) {
+            case VOID:
+            case POINTER:
+            case STRING:
+                return true;
+
+            default:
+                return isFastNumericType(platform, type);
+        }
+    }
+
+    static boolean isFastNumericParameter(Platform platform, NativeType type) {
+        switch (type) {
+            case POINTER:
+            case BUFFER_IN:
+            case BUFFER_OUT:
+            case BUFFER_INOUT:
+                return true;
+            
+            default:
+                return isFastNumericType(platform, type);
+        }
+    }
+}
diff --git a/src/org/python/modules/jffi/Function.java b/src/org/python/modules/jffi/Function.java
--- a/src/org/python/modules/jffi/Function.java
+++ b/src/org/python/modules/jffi/Function.java
@@ -1,6 +1,7 @@
 
 package org.python.modules.jffi;
 
+import com.kenai.jffi.CallingConvention;
 import org.python.core.Py;
 import org.python.core.PyList;
 import org.python.core.PyNewWrapper;
@@ -22,9 +23,12 @@
 
     private final PyStringMap dict = new PyStringMap();
 
-    private volatile PyObject restype = Py.None;
+    private volatile PyObject restype = CType.INT;
     private volatile PyObject[] argtypes = null;
-    private Invoker invoker = null;
+    private Invoker defaultInvoker;
+    private Invoker compiledInvoker;
+    private volatile JITHandle jitHandle;
+    private volatile com.kenai.jffi.Function jffiFunction;
 
     @ExposedGet
     public PyObject errcheck = Py.None;
@@ -150,38 +154,66 @@
         return !getMemory().isNull();
     }
 
-    private final Invoker getInvoker() {
+    protected final Invoker getInvoker() {
+        return compiledInvoker != null ? compiledInvoker : tryCompilation();
+    }
+
+    private synchronized Invoker tryCompilation() {
+        if (compiledInvoker != null) {
+            return compiledInvoker;
+        }
+
+        if (argtypes == null) {
+            throw Py.NotImplementedError("variadic functions not supported yet;  specify a parameter list");
+        }
+
+        CType cResultType = CType.typeOf(restype);
+        CType[] cParameterTypes = new CType[argtypes.length];
+        for (int i = 0; i < cParameterTypes.length; i++) {
+            cParameterTypes[i] = CType.typeOf(argtypes[i]);
+        }
+
+        if (jitHandle == null) {
+            jitHandle = JITCompiler.getInstance().getHandle(cResultType, cParameterTypes, CallingConvention.DEFAULT, false);
+        }
+
+        if (jffiFunction == null) {
+            com.kenai.jffi.Type jffiReturnType = Util.jffiType(cResultType);
+            com.kenai.jffi.Type[] jffiParamTypes = new com.kenai.jffi.Type[argtypes.length];
+
+            for (int i = 0; i < jffiParamTypes.length; ++i) {
+                jffiParamTypes[i] = Util.jffiType(cParameterTypes[i]);
+            }
+
+            jffiFunction = new com.kenai.jffi.Function(getMemory().getAddress(), jffiReturnType, jffiParamTypes);
+        }
+
+        if (defaultInvoker == null) {
+            Invoker invoker = DefaultInvokerFactory.getFactory().createInvoker(jffiFunction, restype, argtypes);
+            defaultInvoker = errcheck != Py.None ? new ErrCheckInvoker(invoker, errcheck) : invoker;
+        }
+
+        Invoker invoker = jitHandle.compile(jffiFunction, null, new NativeDataConverter[0]);
         if (invoker != null) {
-            return invoker;
+            return compiledInvoker = errcheck != Py.None ? new ErrCheckInvoker(invoker, errcheck) : invoker;
         }
-        return createInvoker();
+
+        //
+        // Once compilation has failed, always fallback to the default invoker
+        //
+        if (jitHandle.compilationFailed()) {
+            compiledInvoker = defaultInvoker;
+        }
+
+        return defaultInvoker;
     }
 
     private synchronized void invalidateInvoker() {
         // null out the invoker - it will be regenerated on next invocation
-        this.invoker = null;
-    }
-
-    private synchronized final Invoker createInvoker() {
-        if (argtypes == null) {
-            throw Py.NotImplementedError("variadic functions not supported yet;  specify a parameter list");
-        }
-
-        com.kenai.jffi.Type jffiReturnType = Util.jffiType(CType.typeOf(restype));
-        com.kenai.jffi.Type[] jffiParamTypes = new com.kenai.jffi.Type[argtypes.length];
-        for (int i = 0; i < jffiParamTypes.length; ++i) {
-            jffiParamTypes[i] = Util.jffiType(CType.typeOf(argtypes[i]));
-        }
-        com.kenai.jffi.Function jffiFunction = new com.kenai.jffi.Function(getMemory().getAddress(), jffiReturnType, jffiParamTypes);
-
-        Invoker i;
-        if (FastIntInvokerFactory.getFactory().isFastIntMethod(restype, argtypes)) {
-            i = FastIntInvokerFactory.getFactory().createInvoker(jffiFunction, restype, argtypes);
-        } else {
-            i = DefaultInvokerFactory.getFactory().createInvoker(jffiFunction, restype, argtypes);
-        }
-
-        return invoker = errcheck != Py.None ? new ErrCheckInvoker(i, errcheck) : i;
+        this.defaultInvoker = null;
+        this.compiledInvoker = null;
+        this.jitHandle = null;
+        this.jffiFunction = null;
     }
 
     private static final class ErrCheckInvoker implements Invoker {
diff --git a/src/org/python/modules/jffi/JITCompiler.java b/src/org/python/modules/jffi/JITCompiler.java
new file mode 100644
--- /dev/null
+++ b/src/org/python/modules/jffi/JITCompiler.java
@@ -0,0 +1,100 @@
+/*
+ *
+ */
+package org.python.modules.jffi;
+
+import com.kenai.jffi.CallingConvention;
+import org.python.core.PyObject;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ *
+ */
+class JITCompiler {
+    
+    private final Map<JITSignature, HandleRef> 
+            handles = new HashMap<JITSignature, HandleRef>();
+    private final ReferenceQueue referenceQueue = new ReferenceQueue();
+    
+    private final JITHandle failedHandle = new JITHandle(
+            new JITSignature(NativeType.VOID, new NativeType[0], false, new boolean[0], CallingConvention.DEFAULT, false),
+            true);
+
+    private static class SingletonHolder {
+        private static final JITCompiler INSTANCE = new JITCompiler();
+    }
+    
+    public static JITCompiler getInstance() {
+        return SingletonHolder.INSTANCE;
+    }
+    
+    private static final class HandleRef extends WeakReference<JITHandle> {
+        JITSignature signature;
+
+        public HandleRef(JITHandle handle, JITSignature signature, ReferenceQueue refqueue) {
+            super(handle, refqueue);
+            this.signature = signature;
+        }
+    }
+
+    private void cleanup() {
+        HandleRef ref;
+        while ((ref = (HandleRef) referenceQueue.poll()) != null) {
+            handles.remove(ref.signature);
+        }
+    }
+    
+    
+    JITHandle getHandle(PyObject resultType, PyObject[] parameterTypes, CallingConvention convention, boolean ignoreErrno) {
+        
+        boolean hasResultConverter = !(resultType instanceof CType.Builtin);
+        NativeType nativeResultType;
+
+        if (resultType instanceof CType.Builtin) {
+            nativeResultType = ((CType) resultType).getNativeType();
+        /*
+        } else if (resultType instanceof MappedType) {
+            nativeResultType = ((MappedType) resultType).getRealType().getNativeType();
+        */
+        } else {
+            return failedHandle;
+        }
+
+        NativeType[] nativeParameterTypes = new NativeType[parameterTypes.length];
+        boolean[] hasParameterConverter = new boolean[parameterTypes.length];
+        
+        for (int i = 0; i < hasParameterConverter.length; i++) {
+            CType parameterType = CType.typeOf(parameterTypes[i]);
+            if (parameterType instanceof CType.Builtin) {
+                nativeParameterTypes[i] = parameterType.getNativeType();
+        /*
+            } else if (parameterType instanceof MappedType) {
+                nativeParameterTypes[i] = ((MappedType) parameterType).getRealType().getNativeType();
+        */
+            } else {
+                return failedHandle;
+            }
+
+            hasParameterConverter[i] = !(parameterType instanceof CType.Builtin);
+        }
+        
+        JITSignature jitSignature = new JITSignature(nativeResultType, nativeParameterTypes, 
+                hasResultConverter, hasParameterConverter, convention, ignoreErrno);
+        
+        synchronized (this) {
+            cleanup();
+            HandleRef ref = handles.get(jitSignature);
+            JITHandle handle = ref != null ? ref.get() : null;
+            if (handle == null) {
+                handle = new JITHandle(jitSignature, false);
+                handles.put(jitSignature, new HandleRef(handle, jitSignature, referenceQueue));
+            }
+            
+            return handle;
+        }
+    }
+}
diff --git a/src/org/python/modules/jffi/JITHandle.java b/src/org/python/modules/jffi/JITHandle.java
new file mode 100644
--- /dev/null
+++ b/src/org/python/modules/jffi/JITHandle.java
@@ -0,0 +1,86 @@
+/*
+ *
+ */
+package org.python.modules.jffi;
+
+import java.lang.reflect.Constructor;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ *
+ */
+final class JITHandle {
+
+    private static final int THRESHOLD = Integer.getInteger("jython.ctypes.compile.threshold", 10);
+    private final JITSignature jitSignature;
+    private volatile boolean compilationFailed = false;
+    private final AtomicInteger counter = new AtomicInteger(0);
+    private volatile Class<? extends Invoker> compiledClass = null;
+
+    JITHandle(JITSignature signature, boolean compilationFailed) {
+        this.jitSignature = signature;
+        this.compilationFailed = compilationFailed;
+    }
+
+    final boolean compilationFailed() {
+        return compilationFailed;
+    }
+
+    final Invoker compile(com.kenai.jffi.Function function, NativeDataConverter resultConverter, NativeDataConverter[] parameterConverters) {
+        if (compilationFailed || counter.incrementAndGet() < THRESHOLD) {
+            return null;
+        }
+
+        synchronized (this) {
+            if (compiledClass == null) {
+                compiledClass = newInvokerClass(jitSignature);
+                if (compiledClass == null) {
+                    compilationFailed = true;
+                    return null;
+                }
+            }
+        }
+
+        try {
+            Constructor<? extends Invoker> cons = compiledClass.getDeclaredConstructor(com.kenai.jffi.Function.class,
+                    NativeDataConverter.class, NativeDataConverter[].class, Invoker.class);
+            return cons.newInstance(function, resultConverter, parameterConverters,
+                    createFallbackInvoker(function, jitSignature));
+        } catch (Throwable t) {
+            t.printStackTrace();
+            return null;
+        }
+    }
+
+    Class<? extends Invoker> newInvokerClass(JITSignature jitSignature) {
+
+        JITMethodGenerator generator = null;
+        JITMethodGenerator[] generators = {
+            new FastIntMethodGenerator(),
+            new FastLongMethodGenerator(),
+            new FastNumericMethodGenerator(),};
+
+        for (int i = 0; i < generators.length; i++) {
+            if (generators[i].isSupported(jitSignature)) {
+                generator = generators[i];
+                break;
+            }
+        }
+
+        if (generator == null) {
+            return null;
+        }
+
+        return new AsmClassBuilder(generator, jitSignature).build();
+    }
+    
+    
+    static Invoker createFallbackInvoker(com.kenai.jffi.Function function, JITSignature signature) {
+        NativeType[] parameterTypes = new NativeType[signature.getParameterCount()];
+        for (int i = 0; i < parameterTypes.length; i++) {
+            parameterTypes[i] = signature.getParameterType(i);
+        }
+
+        return DefaultInvokerFactory.getFactory().createInvoker(function, parameterTypes, signature.getResultType());
+    }
+}
diff --git a/src/org/python/modules/jffi/JITInvoker.java b/src/org/python/modules/jffi/JITInvoker.java
new file mode 100644
--- /dev/null
+++ b/src/org/python/modules/jffi/JITInvoker.java
@@ -0,0 +1,66 @@
+package org.python.modules.jffi;
+
+import com.kenai.jffi.*;
+import org.python.core.Py;
+import org.python.core.PyObject;
+
+/**
+ *
+ */
+abstract public class JITInvoker implements Invoker {
+    protected static final com.kenai.jffi.Invoker jffiInvoker = com.kenai.jffi.Invoker.getInstance();
+    private final int arity;
+
+    protected JITInvoker(int arity) {
+        this.arity = arity;
+    }
+
+    protected final PyObject invalidArity(int got) {
+        checkArity(arity, got);
+        return Py.None;
+    }
+
+    protected final void checkArity(PyObject[] args) {
+        checkArity(arity, args.length);
+    }
+
+    public static void checkArity(int arity, int got) {
+        if (got != arity) {
+            throw Py.TypeError(String.format("__call__() takes exactly %d arguments (%d given)", arity, got));
+        }
+    }
+
+
+    public PyObject invoke(PyObject[] args) {
+        checkArity(args);
+        switch (arity) {
+            case 0:
+                return invoke();
+
+            case 1:
+                return invoke(args[0]);
+
+            case 2:
+                return invoke(args[0], args[1]);
+
+            case 3:
+                return invoke(args[0], args[1], args[2]);
+
+            case 4:
+                return invoke(args[0], args[1], args[2], args[3]);
+
+            case 5:
+                return invoke(args[0], args[1], args[2], args[3], args[4]);
+
+            case 6:
+                return invoke(args[0], args[1], args[2], args[3], args[4], args[5]);
+
+            default:
+                throw Py.RuntimeError("invalid fast-int arity");
+        }
+    }
+
+    abstract public PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4);
+    abstract public PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4, PyObject arg5);
+    abstract public PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4, PyObject arg5, PyObject arg6);
+}
diff --git a/src/org/python/modules/jffi/JITInvoker0.java b/src/org/python/modules/jffi/JITInvoker0.java
new file mode 100644
--- /dev/null
+++ b/src/org/python/modules/jffi/JITInvoker0.java
@@ -0,0 +1,36 @@
+package org.python.modules.jffi;
+
+import org.python.core.PyObject;
+
+/**
+ * 
+ */
+abstract public class JITInvoker0 extends JITInvoker {
+    public JITInvoker0() {
+        super(0);
+    }
+
+    public final PyObject invoke(PyObject arg1) {
+        return invalidArity(1);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2) {
+        return invalidArity(2);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3) {
+        return invalidArity(3);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4) {
+        return invalidArity(4);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4, PyObject arg5) {
+        return invalidArity(5);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4, PyObject arg5, PyObject arg6) {
+        return invalidArity(6);
+    }
+}
diff --git a/src/org/python/modules/jffi/JITInvoker1.java b/src/org/python/modules/jffi/JITInvoker1.java
new file mode 100644
--- /dev/null
+++ b/src/org/python/modules/jffi/JITInvoker1.java
@@ -0,0 +1,36 @@
+package org.python.modules.jffi;
+
+import org.python.core.PyObject;
+
+/**
+ * 
+ */
+abstract public class JITInvoker1 extends JITInvoker {
+    public JITInvoker1() {
+        super(1);
+    }
+
+    public final PyObject invoke() {
+        return invalidArity(0);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2) {
+        return invalidArity(2);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3) {
+        return invalidArity(3);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4) {
+        return invalidArity(4);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4, PyObject arg5) {
+        return invalidArity(5);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4, PyObject arg5, PyObject arg6) {
+        return invalidArity(6);
+    }
+}
diff --git a/src/org/python/modules/jffi/JITInvoker2.java b/src/org/python/modules/jffi/JITInvoker2.java
new file mode 100644
--- /dev/null
+++ b/src/org/python/modules/jffi/JITInvoker2.java
@@ -0,0 +1,36 @@
+package org.python.modules.jffi;
+
+import org.python.core.PyObject;
+
+/**
+ * 
+ */
+abstract public class JITInvoker2 extends JITInvoker {
+    public JITInvoker2() {
+        super(2);
+    }
+
+    public final PyObject invoke() {
+        return invalidArity(0);
+    }
+
+    public final PyObject invoke(PyObject arg1) {
+        return invalidArity(1);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3) {
+        return invalidArity(3);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4) {
+        return invalidArity(4);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4, PyObject arg5) {
+        return invalidArity(5);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4, PyObject arg5, PyObject arg6) {
+        return invalidArity(6);
+    }
+}
diff --git a/src/org/python/modules/jffi/JITInvoker3.java b/src/org/python/modules/jffi/JITInvoker3.java
new file mode 100644
--- /dev/null
+++ b/src/org/python/modules/jffi/JITInvoker3.java
@@ -0,0 +1,36 @@
+package org.python.modules.jffi;
+
+import org.python.core.PyObject;
+
+/**
+ * 
+ */
+abstract public class JITInvoker3 extends JITInvoker {
+    public JITInvoker3() {
+        super(3);
+    }
+
+    public final PyObject invoke() {
+        return invalidArity(0);
+    }
+
+    public final PyObject invoke(PyObject arg1) {
+        return invalidArity(1);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2) {
+        return invalidArity(2);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4) {
+        return invalidArity(4);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4, PyObject arg5) {
+        return invalidArity(5);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4, PyObject arg5, PyObject arg6) {
+        return invalidArity(6);
+    }
+}
diff --git a/src/org/python/modules/jffi/JITInvoker4.java b/src/org/python/modules/jffi/JITInvoker4.java
new file mode 100644
--- /dev/null
+++ b/src/org/python/modules/jffi/JITInvoker4.java
@@ -0,0 +1,36 @@
+package org.python.modules.jffi;
+
+import org.python.core.PyObject;
+
+/**
+ * 
+ */
+abstract public class JITInvoker4 extends JITInvoker {
+    public JITInvoker4() {
+        super(4);
+    }
+
+    public final PyObject invoke() {
+        return invalidArity(0);
+    }
+
+    public final PyObject invoke(PyObject arg1) {
+        return invalidArity(1);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2) {
+        return invalidArity(2);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3) {
+        return invalidArity(3);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4, PyObject arg5) {
+        return invalidArity(5);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4, PyObject arg5, PyObject arg6) {
+        return invalidArity(6);
+    }
+}
diff --git a/src/org/python/modules/jffi/JITInvoker5.java b/src/org/python/modules/jffi/JITInvoker5.java
new file mode 100644
--- /dev/null
+++ b/src/org/python/modules/jffi/JITInvoker5.java
@@ -0,0 +1,36 @@
+package org.python.modules.jffi;
+
+import org.python.core.PyObject;
+
+/**
+ * 
+ */
+abstract public class JITInvoker5 extends JITInvoker {
+    public JITInvoker5() {
+        super(5);
+    }
+
+    public final PyObject invoke() {
+        return invalidArity(0);
+    }
+
+    public final PyObject invoke(PyObject arg1) {
+        return invalidArity(1);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2) {
+        return invalidArity(2);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3) {
+        return invalidArity(3);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4) {
+        return invalidArity(4);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4, PyObject arg5, PyObject arg6) {
+        return invalidArity(6);
+    }
+}
diff --git a/src/org/python/modules/jffi/JITInvoker6.java b/src/org/python/modules/jffi/JITInvoker6.java
new file mode 100644
--- /dev/null
+++ b/src/org/python/modules/jffi/JITInvoker6.java
@@ -0,0 +1,40 @@
+package org.python.modules.jffi;
+
+import org.python.core.PyObject;
+
+/**
+ * 
+ */
+abstract public class JITInvoker6 extends JITInvoker {
+    public JITInvoker6() {
+        super(6);
+    }
+
+    public final PyObject invoke() {
+        return invalidArity(0);
+    }
+
+    public final PyObject invoke(PyObject arg1) {
+        return invalidArity(1);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2) {
+        return invalidArity(2);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3) {
+        return invalidArity(3);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4) {
+        return invalidArity(4);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4, PyObject arg5) {
+        return invalidArity(5);
+    }
+
+    public final PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4, PyObject arg5, PyObject arg6) {
+        return invalidArity(6);
+    }
+}
diff --git a/src/org/python/modules/jffi/JITMethodGenerator.java b/src/org/python/modules/jffi/JITMethodGenerator.java
new file mode 100644
--- /dev/null
+++ b/src/org/python/modules/jffi/JITMethodGenerator.java
@@ -0,0 +1,11 @@
+package org.python.modules.jffi;
+
+/**
+ * 
+ */
+public interface JITMethodGenerator {
+
+    public boolean isSupported(JITSignature signature);
+
+    public void generate(AsmClassBuilder builder, String functionName, JITSignature signature);
+}
diff --git a/src/org/python/modules/jffi/JITRuntime.java b/src/org/python/modules/jffi/JITRuntime.java
new file mode 100644
--- /dev/null
+++ b/src/org/python/modules/jffi/JITRuntime.java
@@ -0,0 +1,180 @@
+package org.python.modules.jffi;
+
+import org.python.core.Py;
+import org.python.core.PyInteger;
+import org.python.core.PyLong;
+import org.python.core.PyObject;
+
+import java.math.BigInteger;
+
+/**
+ * 
+ */
+public final class JITRuntime {
+    private JITRuntime() {}
+
+    public static int pointerValue32(PyObject ptr) {
+        return (int) ((Pointer) ptr).getMemory().getAddress();
+    }
+
+    public static long pointerValue64(PyObject ptr) {
+        return ((Pointer) ptr).getMemory().getAddress();
+    }
+
+    public static int intValue(PyObject parameter) {
+        if (parameter instanceof PyInteger) {
+            return ((PyInteger) parameter).getValue();
+
+        } else if (parameter instanceof PyLong) {
+            return ((PyLong) parameter).getValue().intValue();
+
+        } else {
+            return (int) __long__value(parameter);
+        }
+    }
+    public static long longValue(PyObject parameter) {
+        if (parameter instanceof PyInteger) {
+            return ((PyInteger) parameter).getValue();
+
+        } else if (parameter instanceof PyLong) {
+            return ((PyLong) parameter).getValue().longValue();
+
+        } else {
+            return __long__value(parameter);
+        }
+    }
+
+    static final long __long__value(PyObject parameter) {
+        PyObject value = parameter.__long__();
+
+        if (value instanceof PyLong) {
+            return ((PyLong) value).getValue().longValue();
+
+        } else if (value instanceof PyInteger) {
+            return ((PyInteger) value).getValue();
+        }
+
+        throw Py.TypeError("invalid __long__() result");
+    }
+
+    public static int boolValue32(PyObject parameter) {
+        return parameter.__nonzero__() ? 1 : 0;
+    }
+
+    public static long boolValue64(PyObject parameter) {
+        return parameter.__nonzero__() ? 1L : 0L;
+    }
+
+    public static int s8Value32(PyObject parameter) {
+        return (byte) intValue(parameter);
+    }
+
+    public static long s8Value64(PyObject parameter) {
+        return (byte) intValue(parameter);
+    }
+
+    public static int u8Value32(PyObject parameter) {
+        return intValue(parameter) & 0xff;
+    }
+
+    public static long u8Value64(PyObject parameter) {
+        return ((long) intValue(parameter)) & 0xffL;
+    }
+
+    public static int s16Value32(PyObject parameter) {
+        return (short) intValue(parameter);
+    }
+
+    public static long s16Value64(PyObject parameter) {
+        return (short) intValue(parameter);
+    }
+
+    public static int u16Value32(PyObject parameter) {
+        return intValue(parameter) & 0xffff;
+    }
+
+    public static long u16Value64(PyObject parameter) {
+        return ((long) intValue(parameter)) & 0xffffL;
+    }
+
+
+    public static int s32Value32(PyObject parameter) {
+        return intValue(parameter);
+    }
+
+    public static long s32Value64(PyObject parameter) {
+        return intValue(parameter);
+    }
+
+    public static int u32Value32(PyObject parameter) {
+        return intValue(parameter);
+    }
+
+    public static long u32Value64(PyObject parameter) {
+        return ((long) intValue(parameter)) & 0xffffffffL;
+    }
+
+    public static long s64Value64(PyObject parameter) {
+        return longValue(parameter);
+    }
+
+    public static long u64Value64(PyObject parameter) {
+        return longValue(parameter);
+    }
+
+    public static int float2int32(PyObject parameter) {
+        return Float.floatToRawIntBits((float) parameter.asDouble());
+    }
+
+    public static long float2int64(PyObject parameter) {
+        return Float.floatToRawIntBits((float) parameter.asDouble());
+    }
+
+    public static long double2long64(PyObject parameter) {
+        return Double.doubleToRawLongBits(parameter.asDouble());
+    }
+    
+    
+    public static PyObject newSigned8(byte value) {
+        return Py.newInteger(value);
+    }
+
+    public static PyObject newUnsigned8(byte value) {
+        return Py.newInteger(value < 0 ? (long)((value & 0x7FL) + 0x80L) : value);
+    }
+
+    public static PyObject newSigned16(short value) {
+        return Py.newInteger(value);
+    }
+
+    public static PyObject newUnsigned16(short value) {
+        return Py.newInteger(value < 0 ? (long)((value & 0x7FFFL) + 0x8000L) : value);
+    }
+
+    public static PyObject newSigned32(int value) {
+        return Py.newInteger(value);
+    }
+
+    public static PyObject newUnsigned32(int value) {
+        return Py.newInteger(value < 0 ? (long)((value & 0x7FFFFFFFL) + 0x80000000L) : value);
+    }
+
+    public static PyObject newSigned64(long value) {
+        return Py.newInteger(value);
+    }
+
+    private static final BigInteger UINT64_BASE = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE);
+    public static PyObject newUnsigned64(long value) {
+        return value < 0
+                ? Py.newLong(BigInteger.valueOf(value & 0x7fffffffffffffffL).add(UINT64_BASE))
+                : Py.newInteger(value);
+    }
+
+    public static PyObject newFloat32(int value) {
+        return Py.newFloat(Float.intBitsToFloat(value));
+    }
+
+    public static PyObject newFloat64(long value) {
+        return Py.newFloat(Double.longBitsToDouble(value));
+    }
+}
diff --git a/src/org/python/modules/jffi/JITSignature.java b/src/org/python/modules/jffi/JITSignature.java
new file mode 100644
--- /dev/null
+++ b/src/org/python/modules/jffi/JITSignature.java
@@ -0,0 +1,81 @@
+package org.python.modules.jffi;
+
+import com.kenai.jffi.CallingConvention;
+
+import java.util.Arrays;
+
+/**
+ *
+ */
+public final class JITSignature {
+    private final NativeType resultType;
+    private final NativeType[] parameterTypes;
+    private final boolean hasResultConverter;
+    private final boolean[] hasParameterConverter;
+    private final CallingConvention convention;
+    private final boolean ignoreError;
+
+    public JITSignature(NativeType resultType, NativeType[] parameterTypes,
+                        boolean hasResultConverter, boolean[] hasParameterConverter,
+                        CallingConvention convention, boolean ignoreError) {
+        this.resultType = resultType;
+        this.parameterTypes = (NativeType[]) parameterTypes.clone();
+        this.convention = convention;
+        this.ignoreError = ignoreError;
+        this.hasResultConverter = hasResultConverter;
+        this.hasParameterConverter = (boolean[]) hasParameterConverter.clone();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == null || !o.getClass().equals(getClass())) {
+            return false;
+        }
+        JITSignature rhs = (JITSignature) o;
+        return resultType.equals(rhs.resultType) && convention.equals(rhs.convention)
+                && ignoreError == rhs.ignoreError
+                && Arrays.equals(parameterTypes, rhs.parameterTypes)
+                && hasResultConverter == rhs.hasResultConverter
+                && Arrays.equals(hasParameterConverter, rhs.hasParameterConverter);
+                
+    }
+
+    @Override
+    public int hashCode() {
+        return resultType.hashCode() 
+                ^ convention.hashCode() 
+                ^ Boolean.valueOf(ignoreError).hashCode()
+                ^ Arrays.hashCode(parameterTypes)
+                ^ Boolean.valueOf(hasResultConverter).hashCode()
+                ^ Arrays.hashCode(hasParameterConverter);
+    }
+
+    public final NativeType getResultType() {
+        return resultType;
+    }
+
+    public final NativeType getParameterType(int parameterIndex) {
+        return parameterTypes[parameterIndex];
+    }
+    
+    public final CallingConvention getCallingConvention() {
+        return convention;
+    }
+    
+    public final int getParameterCount() {
+        return parameterTypes.length;
+    }
+    
+    public final boolean hasResultConverter() {
+        return hasResultConverter;
+    }
+    
+    public final boolean hasParameterConverter(int parameterIndex) {
+        return hasParameterConverter[parameterIndex];
+    }
+
+    public boolean isIgnoreError() {
+        return ignoreError;
+    }
+    
+}
diff --git a/src/org/python/modules/jffi/NativeDataConverter.java b/src/org/python/modules/jffi/NativeDataConverter.java
new file mode 100644
--- /dev/null
+++ b/src/org/python/modules/jffi/NativeDataConverter.java
@@ -0,0 +1,35 @@
+package org.python.modules.jffi;
+
+
+import org.python.core.PyObject;
+
+/**
+ *
+ */
+abstract public class NativeDataConverter {
+    private final boolean referenceRequired;
+    private final boolean postInvokeRequired;
+
+    public NativeDataConverter() {
+        this.referenceRequired = false;
+        this.postInvokeRequired = false;
+    }
+    
+    public NativeDataConverter(boolean referenceRequired, boolean postInvokeRequired) {
+        this.referenceRequired = referenceRequired;
+        this.postInvokeRequired = postInvokeRequired;
+    }
+
+    
+    public final boolean isReferenceRequired() {
+        return referenceRequired;
+    }
+
+    public final boolean isPostInvokeRequired() {
+        return postInvokeRequired;
+    }
+    
+    abstract public PyObject fromNative(PyObject obj);
+    abstract public PyObject toNative(PyObject obj);
+    abstract public NativeType nativeType();
+}
diff --git a/src/org/python/modules/jffi/NativeType.java b/src/org/python/modules/jffi/NativeType.java
--- a/src/org/python/modules/jffi/NativeType.java
+++ b/src/org/python/modules/jffi/NativeType.java
@@ -18,6 +18,9 @@
     FLOAT,
     DOUBLE,
     POINTER,
+    BUFFER_IN,
+    BUFFER_OUT,
+    BUFFER_INOUT,
     STRING,
     ARRAY,
     STRUCT;
diff --git a/src/org/python/modules/jffi/SkinnyMethodAdapter.java b/src/org/python/modules/jffi/SkinnyMethodAdapter.java
new file mode 100644
--- /dev/null
+++ b/src/org/python/modules/jffi/SkinnyMethodAdapter.java
@@ -0,0 +1,915 @@
+/*
+ * SkinnyMethodAdapter.java
+ *
+ * Created on March 10, 2007, 2:52 AM
+ *
+ * To change this template, choose Tools | Template Manager
+ * and open the template in the editor.
+ */
+
+package org.python.modules.jffi;
+
+import org.objectweb.asm.*;
+import org.objectweb.asm.util.TraceMethodVisitor;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.util.Map;
+
+import static org.python.modules.jffi.CodegenUtils.*;
+
+/**
+ *
+ * @author headius
+ */
+public class SkinnyMethodAdapter implements MethodVisitor, Opcodes {
+    private final static boolean DEBUG = Boolean.getBoolean("jython.compile.dump");
+    private MethodVisitor method;
+    private String name;
+    private ClassVisitor cv;
+    
+    /** Creates a new instance of SkinnyMethodAdapter */
+    public SkinnyMethodAdapter(MethodVisitor method) {
+        setMethodVisitor(method);
+    }
+
+    public SkinnyMethodAdapter(ClassVisitor cv, int flags, String name, String signature, String something, String[] exceptions) {
+        setMethodVisitor(cv.visitMethod(flags, name, signature, something, exceptions));
+        this.cv = cv;
+        this.name = name;
+    }
+    
+    public SkinnyMethodAdapter() {
+    }
+    
+    public MethodVisitor getMethodVisitor() {
+        return method;
+    }
+    
+    public void setMethodVisitor(MethodVisitor mv) {
+        if (DEBUG) {
+            this.method = new TraceMethodVisitor(mv);
+        } else {
+            this.method = mv;
+        }
+    }
+
+    /**
+     * Short-hand for specifying a set of aloads
+     *
+     * @param args list of aloads you want
+     */
+    public void aloadMany(int... args) {
+        for (int arg: args) {
+            aload(arg);
+        }
+    }
+    
+    public void aload(int arg0) {
+        getMethodVisitor().visitVarInsn(ALOAD, arg0);
+    }
+    
+    public void iload(int arg0) {
+        getMethodVisitor().visitVarInsn(ILOAD, arg0);
+    }
+    
+    public void lload(int arg0) {
+        getMethodVisitor().visitVarInsn(LLOAD, arg0);
+    }
+    
+    public void fload(int arg0) {
+        getMethodVisitor().visitVarInsn(FLOAD, arg0);
+    }
+    
+    public void dload(int arg0) {
+        getMethodVisitor().visitVarInsn(DLOAD, arg0);
+    }
+    
+    public void astore(int arg0) {
+        getMethodVisitor().visitVarInsn(ASTORE, arg0);
+    }
+    
+    public void istore(int arg0) {
+        getMethodVisitor().visitVarInsn(ISTORE, arg0);
+    }
+    
+    public void lstore(int arg0) {
+        getMethodVisitor().visitVarInsn(LSTORE, arg0);
+    }
+    
+    public void fstore(int arg0) {
+        getMethodVisitor().visitVarInsn(FSTORE, arg0);
+    }
+    
+    public void dstore(int arg0) {
+        getMethodVisitor().visitVarInsn(DSTORE, arg0);
+    }
+    
+    public void ldc(Object arg0) {
+        getMethodVisitor().visitLdcInsn(arg0);
+    }
+    
+    public void bipush(int arg) {
+        getMethodVisitor().visitIntInsn(BIPUSH, arg);
+    }
+    
+    public void sipush(int arg) {
+        getMethodVisitor().visitIntInsn(SIPUSH, arg);
+    }
+        
+    public void pushInt(int value) {
+        if (value <= Byte.MAX_VALUE && value >= Byte.MIN_VALUE) {
+            switch (value) {
+            case -1:
+                iconst_m1();
+                break;
+            case 0:
+                iconst_0();
+                break;
+            case 1:
+                iconst_1();
+                break;
+            case 2:
+                iconst_2();
+                break;
+            case 3:
+                iconst_3();
+                break;
+            case 4:
+                iconst_4();
+                break;
+            case 5:
+                iconst_5();
+                break;
+            default:
+                bipush(value);
+                break;
+            }
+        } else if (value <= Short.MAX_VALUE && value >= Short.MIN_VALUE) {
+            sipush(value);
+        } else {
+            ldc(value);
+        }
+    }
+        
+    public void pushBoolean(boolean bool) {
+        if (bool) iconst_1(); else iconst_0();
+    }
+    
+    public void invokestatic(String arg1, String arg2, String arg3) {
+        getMethodVisitor().visitMethodInsn(INVOKESTATIC, arg1, arg2, arg3);
+    }
+    
+    public void invokespecial(String arg1, String arg2, String arg3) {
+        getMethodVisitor().visitMethodInsn(INVOKESPECIAL, arg1, arg2, arg3);
+    }
+    
+    public void invokevirtual(String arg1, String arg2, String arg3) {
+        getMethodVisitor().visitMethodInsn(INVOKEVIRTUAL, arg1, arg2, arg3);
+    }
+    
+    public void invokeinterface(String arg1, String arg2, String arg3) {
+        getMethodVisitor().visitMethodInsn(INVOKEINTERFACE, arg1, arg2, arg3);
+    }
+
+    public void aprintln() {
+        dup();
+        getstatic(p(System.class), "out", ci(PrintStream.class));
+        swap();
+        invokevirtual(p(PrintStream.class), "println", sig(void.class, params(Object.class)));
+    }
+
+    public void iprintln() {
+        dup();
+        getstatic(p(System.class), "out", ci(PrintStream.class));
+        swap();
+        invokevirtual(p(PrintStream.class), "println", sig(void.class, params(int.class)));
+    }
+    
+    public void areturn() {
+        getMethodVisitor().visitInsn(ARETURN);
+    }
+    
+    public void ireturn() {
+        getMethodVisitor().visitInsn(IRETURN);
+    }
+    
+    public void freturn() {
+        getMethodVisitor().visitInsn(FRETURN);
+    }
+    
+    public void lreturn() {
+        getMethodVisitor().visitInsn(LRETURN);
+    }
+    
+    public void dreturn() {
+        getMethodVisitor().visitInsn(DRETURN);
+    }
+    
+    public void newobj(String arg0) {
+        getMethodVisitor().visitTypeInsn(NEW, arg0);
+    }
+    
+    public void dup() {
+        getMethodVisitor().visitInsn(DUP);
+    }
+    
+    public void swap() {
+        getMethodVisitor().visitInsn(SWAP);
+    }
+    
+    public void swap2() {
+        dup2_x2();
+        pop2();
+    }
+    
+    public void getstatic(String arg1, String arg2, String arg3) {
+        getMethodVisitor().visitFieldInsn(GETSTATIC, arg1, arg2, arg3);
+    }
+    
+    public void putstatic(String arg1, String arg2, String arg3) {
+        getMethodVisitor().visitFieldInsn(PUTSTATIC, arg1, arg2, arg3);
+    }
+    
+    public void getfield(String arg1, String arg2, String arg3) {
+        getMethodVisitor().visitFieldInsn(GETFIELD, arg1, arg2, arg3);
+    }
+    
+    public void putfield(String arg1, String arg2, String arg3) {
+        getMethodVisitor().visitFieldInsn(PUTFIELD, arg1, arg2, arg3);
+    }
+    
+    public void voidreturn() {
+        getMethodVisitor().visitInsn(RETURN);
+    }
+    
+    public void anewarray(String arg0) {
+        getMethodVisitor().visitTypeInsn(ANEWARRAY, arg0);
+    }
+    
+    public void multianewarray(String arg0, int dims) {
+        getMethodVisitor().visitMultiANewArrayInsn(arg0, dims);
+    }
+    
+    public void newarray(int arg0) {
+        getMethodVisitor().visitIntInsn(NEWARRAY, arg0);
+    }
+    
+    public void iconst_m1() {
+        getMethodVisitor().visitInsn(ICONST_M1);
+    }
+    
+    public void iconst_0() {
+        getMethodVisitor().visitInsn(ICONST_0);
+    }
+    
+    public void iconst_1() {
+        getMethodVisitor().visitInsn(ICONST_1);
+    }
+    
+    public void iconst_2() {
+        getMethodVisitor().visitInsn(ICONST_2);
+    }
+    
+    public void iconst_3() {
+        getMethodVisitor().visitInsn(ICONST_3);
+    }
+    
+    public void iconst_4() {
+        getMethodVisitor().visitInsn(ICONST_4);
+    }
+    
+    public void iconst_5() {
+        getMethodVisitor().visitInsn(ICONST_5);
+    }
+    
+    public void lconst_0() {
+        getMethodVisitor().visitInsn(LCONST_0);
+    }
+    
+    public void aconst_null() {
+        getMethodVisitor().visitInsn(ACONST_NULL);
+    }
+    
+    public void label(Label label) {
+        getMethodVisitor().visitLabel(label);
+    }
+    
+    public void nop() {
+        getMethodVisitor().visitInsn(NOP);
+    }
+    
+    public void pop() {
+        getMethodVisitor().visitInsn(POP);
+    }
+    
+    public void pop2() {
+        getMethodVisitor().visitInsn(POP2);
+    }
+    
+    public void arrayload() {
+        getMethodVisitor().visitInsn(AALOAD);
+    }
+    
+    public void arraystore() {
+        getMethodVisitor().visitInsn(AASTORE);
+    }
+    
+    public void iarrayload() {
+        getMethodVisitor().visitInsn(IALOAD);
+    }
+    
+    public void barrayload() {
+        getMethodVisitor().visitInsn(BALOAD);
+    }
+    
+    public void barraystore() {
+        getMethodVisitor().visitInsn(BASTORE);
+    }
+    
+    public void aaload() {
+        getMethodVisitor().visitInsn(AALOAD);
+    }
+    
+    public void aastore() {
+        getMethodVisitor().visitInsn(AASTORE);
+    }
+    
+    public void iaload() {
+        getMethodVisitor().visitInsn(IALOAD);
+    }
+    
+    public void iastore() {
+        getMethodVisitor().visitInsn(IASTORE);
+    }
+    
+    public void laload() {
+        getMethodVisitor().visitInsn(LALOAD);
+    }
+    
+    public void lastore() {
+        getMethodVisitor().visitInsn(LASTORE);
+    }
+    
+    public void baload() {
+        getMethodVisitor().visitInsn(BALOAD);
+    }
+    
+    public void bastore() {
+        getMethodVisitor().visitInsn(BASTORE);
+    }
+    
+    public void saload() {
+        getMethodVisitor().visitInsn(SALOAD);
+    }
+    
+    public void sastore() {
+        getMethodVisitor().visitInsn(SASTORE);
+    }
+    
+    public void caload() {
+        getMethodVisitor().visitInsn(CALOAD);
+    }
+    
+    public void castore() {
+        getMethodVisitor().visitInsn(CASTORE);
+    }
+    
+    public void faload() {
+        getMethodVisitor().visitInsn(FALOAD);
+    }
+    
+    public void fastore() {
+        getMethodVisitor().visitInsn(FASTORE);
+    }
+    
+    public void daload() {
+        getMethodVisitor().visitInsn(DALOAD);
+    }
+    
+    public void dastore() {
+        getMethodVisitor().visitInsn(DASTORE);
+    }
+    
+    public void fcmpl() {
+        getMethodVisitor().visitInsn(FCMPL);
+    }
+    
+    public void fcmpg() {
+        getMethodVisitor().visitInsn(FCMPG);
+    }
+    
+    public void dcmpl() {
+        getMethodVisitor().visitInsn(DCMPL);
+    }
+    
+    public void dcmpg() {
+        getMethodVisitor().visitInsn(DCMPG);
+    }
+    
+    public void dup_x2() {
+        getMethodVisitor().visitInsn(DUP_X2);
+    }
+    
+    public void dup_x1() {
+        getMethodVisitor().visitInsn(DUP_X1);
+    }
+    
+    public void dup2_x2() {
+        getMethodVisitor().visitInsn(DUP2_X2);
+    }
+    
+    public void dup2_x1() {
+        getMethodVisitor().visitInsn(DUP2_X1);
+    }
+    
+    public void dup2() {
+        getMethodVisitor().visitInsn(DUP2);
+    }
+    
+    public void trycatch(Label arg0, Label arg1, Label arg2,
+                                   String arg3) {
+        getMethodVisitor().visitTryCatchBlock(arg0, arg1, arg2, arg3);
+    }
+    
+    public void trycatch(String type, Runnable body, Runnable catchBody) {
+        Label before = new Label();
+        Label after = new Label();
+        Label catchStart = new Label();
+        Label done = new Label();
+
+        trycatch(before, after, catchStart, type);
+        label(before);
+        body.run();
+        label(after);
+        go_to(done);
+        if (catchBody != null) {
+            label(catchStart);
+            catchBody.run();
+        }
+        label(done);
+    }
+    
+    public void go_to(Label arg0) {
+        getMethodVisitor().visitJumpInsn(GOTO, arg0);
+    }
+    
+    public void lookupswitch(Label arg0, int[] arg1, Label[] arg2) {
+        getMethodVisitor().visitLookupSwitchInsn(arg0, arg1, arg2);
+    }
+    
+    public void athrow() {
+        getMethodVisitor().visitInsn(ATHROW);
+    }
+    
+    public void instance_of(String arg0) {
+        getMethodVisitor().visitTypeInsn(INSTANCEOF, arg0);
+    }
+    
+    public void ifeq(Label arg0) {
+        getMethodVisitor().visitJumpInsn(IFEQ, arg0);
+    }
+
+    public void iffalse(Label arg0) {
+        ifeq(arg0);
+    }
+    
+    public void ifne(Label arg0) {
+        getMethodVisitor().visitJumpInsn(IFNE, arg0);
+    }
+
+    public void iftrue(Label arg0) {
+        ifne(arg0);
+    }
+    
+    public void if_acmpne(Label arg0) {
+        getMethodVisitor().visitJumpInsn(IF_ACMPNE, arg0);
+    }
+    
+    public void if_acmpeq(Label arg0) {
+        getMethodVisitor().visitJumpInsn(IF_ACMPEQ, arg0);
+    }
+    
+    public void if_icmple(Label arg0) {
+        getMethodVisitor().visitJumpInsn(IF_ICMPLE, arg0);
+    }
+    
+    public void if_icmpgt(Label arg0) {
+        getMethodVisitor().visitJumpInsn(IF_ICMPGT, arg0);
+    }
+    
+    public void if_icmplt(Label arg0) {
+        getMethodVisitor().visitJumpInsn(IF_ICMPLT, arg0);
+    }
+    
+    public void if_icmpne(Label arg0) {
+        getMethodVisitor().visitJumpInsn(IF_ICMPNE, arg0);
+    }
+    
+    public void if_icmpeq(Label arg0) {
+        getMethodVisitor().visitJumpInsn(IF_ICMPEQ, arg0);
+    }
+    
+    public void checkcast(String arg0) {
+        getMethodVisitor().visitTypeInsn(CHECKCAST, arg0);
+    }
+    
+    public void start() {
+        getMethodVisitor().visitCode();
+    }
+    
+    public void end() {
+        if (DEBUG) {
+            PrintWriter pw = new PrintWriter(System.out);
+            String className = "(unknown class)";
+            if (cv instanceof ClassWriter) {
+                className = new ClassReader(((ClassWriter)cv).toByteArray()).getClassName();
+            }
+            if (name != null) {
+                pw.write("*** Dumping " + className + "." + name + " ***\n");
+            } else {
+                pw.write("*** Dumping ***\n");
+            }
+            ((TraceMethodVisitor)getMethodVisitor()).print(pw);
+            pw.flush();
+        }
+        getMethodVisitor().visitMaxs(1, 1);
+        getMethodVisitor().visitEnd();
+    }
+
+    public void line(int line) {
+        Label label = new Label();
+        label(label);
+        visitLineNumber(line, label);
+    }
+
+    public void line(int line, Label label) {
+        visitLineNumber(line, label);
+    }
+    
+    public void ifnonnull(Label arg0) {
+        getMethodVisitor().visitJumpInsn(IFNONNULL, arg0);
+    }
+    
+    public void ifnull(Label arg0) {
+        getMethodVisitor().visitJumpInsn(IFNULL, arg0);
+    }
+    
+    public void iflt(Label arg0) {
+        getMethodVisitor().visitJumpInsn(IFLT, arg0);
+    }
+    
+    public void ifle(Label arg0) {
+        getMethodVisitor().visitJumpInsn(IFLE, arg0);
+    }
+    
+    public void ifgt(Label arg0) {
+        getMethodVisitor().visitJumpInsn(IFGT, arg0);
+    }
+    
+    public void ifge(Label arg0) {
+        getMethodVisitor().visitJumpInsn(IFGE, arg0);
+    }
+    
+    public void arraylength() {
+        getMethodVisitor().visitInsn(ARRAYLENGTH);
+    }
+    
+    public void ishr() {
+        getMethodVisitor().visitInsn(ISHR);
+    }
+    
+    public void ishl() {
+        getMethodVisitor().visitInsn(ISHL);
+    }
+    
+    public void iushr() {
+        getMethodVisitor().visitInsn(IUSHR);
+    }
+    
+    public void lshr() {
+        getMethodVisitor().visitInsn(LSHR);
+    }
+    
+    public void lshl() {
+        getMethodVisitor().visitInsn(LSHL);
+    }
+    
+    public void lushr() {
+        getMethodVisitor().visitInsn(LUSHR);
+    }
+    
+    public void lcmp() {
+        getMethodVisitor().visitInsn(LCMP);
+    }
+    
+    public void iand() {
+        getMethodVisitor().visitInsn(IAND);
+    }
+    
+    public void ior() {
+        getMethodVisitor().visitInsn(IOR);
+    }
+    
+    public void ixor() {
+        getMethodVisitor().visitInsn(IXOR);
+    }
+    
+    public void land() {
+        getMethodVisitor().visitInsn(LAND);
+    }
+    
+    public void lor() {
+        getMethodVisitor().visitInsn(LOR);
+    }
+    
+    public void lxor() {
+        getMethodVisitor().visitInsn(LXOR);
+    }
+    
+    public void iadd() {
+        getMethodVisitor().visitInsn(IADD);
+    }
+    
+    public void ladd() {
+        getMethodVisitor().visitInsn(LADD);
+    }
+    
+    public void fadd() {
+        getMethodVisitor().visitInsn(FADD);
+    }
+    
+    public void dadd() {
+        getMethodVisitor().visitInsn(DADD);
+    }
+    
+    public void isub() {
+        getMethodVisitor().visitInsn(ISUB);
+    }
+    
+    public void lsub() {
+        getMethodVisitor().visitInsn(LSUB);
+    }
+    
+    public void fsub() {
+        getMethodVisitor().visitInsn(FSUB);
+    }
+    
+    public void dsub() {
+        getMethodVisitor().visitInsn(DSUB);
+    }
+    
+    public void idiv() {
+        getMethodVisitor().visitInsn(IDIV);
+    }
+    
+    public void irem() {
+        getMethodVisitor().visitInsn(IREM);
+    }
+    
+    public void ineg() {
+        getMethodVisitor().visitInsn(INEG);
+    }
+    
+    public void i2d() {
+        getMethodVisitor().visitInsn(I2D);
+    }
+    
+    public void i2l() {
+        getMethodVisitor().visitInsn(I2L);
+    }
+    
+    public void i2f() {
+        getMethodVisitor().visitInsn(I2F);
+    }
+    
+    public void i2s() {
+        getMethodVisitor().visitInsn(I2S);
+    }
+    
+    public void i2c() {
+        getMethodVisitor().visitInsn(I2C);
+    }
+    
+    public void i2b() {
+        getMethodVisitor().visitInsn(I2B);
+    }
+    
+    public void ldiv() {
+        getMethodVisitor().visitInsn(LDIV);
+    }
+    
+    public void lrem() {
+        getMethodVisitor().visitInsn(LREM);
+    }
+    
+    public void lneg() {
+        getMethodVisitor().visitInsn(LNEG);
+    }
+    
+    public void l2d() {
+        getMethodVisitor().visitInsn(L2D);
+    }
+    
+    public void l2i() {
+        getMethodVisitor().visitInsn(L2I);
+    }
+    
+    public void l2f() {
+        getMethodVisitor().visitInsn(L2F);
+    }
+    
+    public void fdiv() {
+        getMethodVisitor().visitInsn(FDIV);
+    }
+    
+    public void frem() {
+        getMethodVisitor().visitInsn(FREM);
+    }
+    
+    public void fneg() {
+        getMethodVisitor().visitInsn(FNEG);
+    }
+    
+    public void f2d() {
+        getMethodVisitor().visitInsn(F2D);
+    }
+    
+    public void f2i() {
+        getMethodVisitor().visitInsn(F2D);
+    }
+    
+    public void f2l() {
+        getMethodVisitor().visitInsn(F2L);
+    }
+    
+    public void ddiv() {
+        getMethodVisitor().visitInsn(DDIV);
+    }
+    
+    public void drem() {
+        getMethodVisitor().visitInsn(DREM);
+    }
+    
+    public void dneg() {
+        getMethodVisitor().visitInsn(DNEG);
+    }
+    
+    public void d2f() {
+        getMethodVisitor().visitInsn(D2F);
+    }
+    
+    public void d2i() {
+        getMethodVisitor().visitInsn(D2I);
+    }
+    
+    public void d2l() {
+        getMethodVisitor().visitInsn(D2L);
+    }
+    
+    public void imul() {
+        getMethodVisitor().visitInsn(IMUL);
+    }
+    
+    public void lmul() {
+        getMethodVisitor().visitInsn(LMUL);
+    }
+    
+    public void fmul() {
+        getMethodVisitor().visitInsn(FMUL);
+    }
+    
+    public void dmul() {
+        getMethodVisitor().visitInsn(DMUL);
+    }
+    
+    public void iinc(int arg0, int arg1) {
+        getMethodVisitor().visitIincInsn(arg0, arg1);
+    }
+    
+    public void monitorenter() {
+        getMethodVisitor().visitInsn(MONITORENTER);
+    }
+    
+    public void monitorexit() {
+        getMethodVisitor().visitInsn(MONITOREXIT);
+    }
+    
+    public void jsr(Label branch) {
+        getMethodVisitor().visitJumpInsn(JSR, branch);
+    }
+    
+    public void ret(int arg0) {
+        getMethodVisitor().visitVarInsn(RET, arg0);
+    }
+    
+    public AnnotationVisitor visitAnnotationDefault() {
+        return getMethodVisitor().visitAnnotationDefault();
+    }
+
+    public AnnotationVisitor visitAnnotation(String arg0, boolean arg1) {
+        return getMethodVisitor().visitAnnotation(arg0, arg1);
+    }
+
+    public AnnotationVisitor visitParameterAnnotation(int arg0, String arg1,
+                                                      boolean arg2) {
+        return getMethodVisitor().visitParameterAnnotation(arg0, arg1, arg2);
+    }
+
+    public void visitAttribute(Attribute arg0) {
+        getMethodVisitor().visitAttribute(arg0);
+    }
+
+    public void visitCode() {
+        getMethodVisitor().visitCode();
+    }
+
+    public void visitInsn(int arg0) {
+        getMethodVisitor().visitInsn(arg0);
+    }
+
+    public void visitIntInsn(int arg0, int arg1) {
+        getMethodVisitor().visitIntInsn(arg0, arg1);
+    }
+
+    public void visitVarInsn(int arg0, int arg1) {
+        getMethodVisitor().visitVarInsn(arg0, arg1);
+    }
+
+    public void visitTypeInsn(int arg0, String arg1) {
+        getMethodVisitor().visitTypeInsn(arg0, arg1);
+    }
+
+    public void visitFieldInsn(int arg0, String arg1, String arg2, String arg3) {
+        getMethodVisitor().visitFieldInsn(arg0, arg1, arg2, arg3);
+    }
+
+    public void visitMethodInsn(int arg0, String arg1, String arg2, String arg3) {
+        getMethodVisitor().visitMethodInsn(arg0, arg1, arg2, arg3);
+    }
+
+    public void visitJumpInsn(int arg0, Label arg1) {
+        getMethodVisitor().visitJumpInsn(arg0, arg1);
+    }
+
+    public void visitLabel(Label arg0) {
+        getMethodVisitor().visitLabel(arg0);
+    }
+
+    public void visitLdcInsn(Object arg0) {
+        getMethodVisitor().visitLdcInsn(arg0);
+    }
+
+    public void visitIincInsn(int arg0, int arg1) {
+        getMethodVisitor().visitIincInsn(arg0, arg1);
+    }
+
+    public void visitTableSwitchInsn(int arg0, int arg1, Label arg2,
+                                     Label[] arg3) {
+        getMethodVisitor().visitTableSwitchInsn(arg0, arg1, arg2, arg3);
+    }
+
+    public void visitLookupSwitchInsn(Label arg0, int[] arg1, Label[] arg2) {
+        getMethodVisitor().visitLookupSwitchInsn(arg0, arg1, arg2);
+    }
+
+    public void visitMultiANewArrayInsn(String arg0, int arg1) {
+        getMethodVisitor().visitMultiANewArrayInsn(arg0, arg1);
+    }
+
+    public void visitTryCatchBlock(Label arg0, Label arg1, Label arg2,
+                                   String arg3) {
+        getMethodVisitor().visitTryCatchBlock(arg0, arg1, arg2, arg3);
+    }
+
+    public void visitLocalVariable(String arg0, String arg1, String arg2,
+                                   Label arg3, Label arg4, int arg5) {
+        getMethodVisitor().visitLocalVariable(arg0, arg1, arg2, arg3, arg4, arg5);
+    }
+
+    public void visitLineNumber(int arg0, Label arg1) {
+        getMethodVisitor().visitLineNumber(arg0, arg1);
+    }
+
+    public void visitMaxs(int arg0, int arg1) {
+        if (DEBUG) {
+            PrintWriter pw = new PrintWriter(System.out);
+            pw.write("*** Dumping ***\n");
+            ((TraceMethodVisitor)getMethodVisitor()).print(pw);
+            pw.flush();
+        }
+        getMethodVisitor().visitMaxs(arg0, arg1);
+    }
+
+    public void visitEnd() {
+        getMethodVisitor().visitEnd();
+    }
+    
+    public void tableswitch(int min, int max, Label defaultLabel, Label[] cases) {
+        getMethodVisitor().visitTableSwitchInsn(min, max, defaultLabel, cases);
+    }
+
+    public void visitFrame(int arg0, int arg1, Object[] arg2, int arg3, Object[] arg4) {
+        getMethodVisitor().visitFrame(arg0, arg1, arg2, arg3, arg4);
+    }
+}

-- 
Repository URL: http://hg.python.org/jython


More information about the Jython-checkins mailing list