[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