From: <fwi...@us...> - 2009-09-25 03:08:57
|
Revision: 6810 http://jython.svn.sourceforge.net/jython/?rev=6810&view=rev Author: fwierzbicki Date: 2009-09-25 03:08:49 +0000 (Fri, 25 Sep 2009) Log Message: ----------- Replace tableswitch in modules with MethodHandles. Modified Paths: -------------- branches/indy/build.xml branches/indy/src/org/python/compiler/ClassConstants.java branches/indy/src/org/python/compiler/Code.java branches/indy/src/org/python/compiler/Module.java branches/indy/src/org/python/core/Py.java branches/indy/src/org/python/core/imp.java Added Paths: ----------- branches/indy/src/org/python/core/IndyCode.java branches/indy/src/org/python/core/IndyFunctionTable.java branches/indy/src/org/python/util/CodegenUtils.java Modified: branches/indy/build.xml =================================================================== --- branches/indy/build.xml 2009-09-24 01:34:49 UTC (rev 6809) +++ branches/indy/build.xml 2009-09-25 03:08:49 UTC (rev 6810) @@ -171,11 +171,11 @@ <property name="dist.dir" value="${work.dir}/dist" /> <property name="apidoc.dir" value="${dist.dir}/Doc/javadoc" /> <property name="junit.reports" value="${dist.dir}/testreports" /> + <!-- <property name="javac.Xlint" value="-Xlint -Xlint:-serial -Xlint:-unchecked -Xlint:-cast -Xbootclasspath/p:${extlibs.dir}/jsr292-mock.jar"/> - <!-- + --> <property name="javac.Xlint" value="-Xlint -Xlint:-serial -XDinvokedynamic -Xlint:-unchecked -Xlint:-cast"/> - --> <!-- classpaths --> <path id="main.classpath"> <pathelement path="${extlibs.dir}/libreadline-java-0.8.jar" /> Modified: branches/indy/src/org/python/compiler/ClassConstants.java =================================================================== --- branches/indy/src/org/python/compiler/ClassConstants.java 2009-09-24 01:34:49 UTC (rev 6809) +++ branches/indy/src/org/python/compiler/ClassConstants.java 2009-09-25 03:08:49 UTC (rev 6810) @@ -15,7 +15,7 @@ final static String $pyFloat = "Lorg/python/core/PyFloat;"; final static String $pyComplex = "Lorg/python/core/PyComplex;"; final static String $pyRunnable = "Lorg/python/core/PyRunnable;"; - final static String $pyFuncTbl = "Lorg/python/core/PyFunctionTable;"; + final static String $pyFuncTbl = "Lorg/python/core/IndyFunctionTable;"; final static String $pyProxy = "Lorg/python/core/PyProxy;"; final static String $obj = "Ljava/lang/Object;"; Modified: branches/indy/src/org/python/compiler/Code.java =================================================================== --- branches/indy/src/org/python/compiler/Code.java 2009-09-24 01:34:49 UTC (rev 6809) +++ branches/indy/src/org/python/compiler/Code.java 2009-09-25 03:08:49 UTC (rev 6810) @@ -480,7 +480,11 @@ public void invokevirtual(String owner, String name, String type) { mv.visitMethodInsn(INVOKEVIRTUAL, owner, name, type); } - + + public void invokedynamic(String owner, String name, String type) { + mv.visitMethodInsn(INVOKEDYNAMIC, owner, name, type); + } + public void ireturn() { mv.visitInsn(IRETURN); } Modified: branches/indy/src/org/python/compiler/Module.java =================================================================== --- branches/indy/src/org/python/compiler/Module.java 2009-09-24 01:34:49 UTC (rev 6809) +++ branches/indy/src/org/python/compiler/Module.java 2009-09-25 03:08:49 UTC (rev 6810) @@ -16,6 +16,7 @@ import org.python.core.CodeFlag; import org.python.core.CodeLoader; import org.python.core.CompilerFlags; +import org.python.core.invokedynamic.InvokeDynamicSupport; import org.python.core.Py; import org.python.core.PyException; import org.python.core.PyRunnableBootstrap; @@ -24,6 +25,7 @@ import org.python.antlr.PythonTree; import org.python.antlr.ast.Suite; import org.python.antlr.base.mod; +import static org.python.util.CodegenUtils.*; class PyIntegerConstant extends Constant implements ClassConstants, Opcodes { @@ -268,8 +270,23 @@ c.getstatic(module.classfile.name, "self", "L"+module.classfile.name+";"); - c.iconst(id); + //REPLACING WITH METH HANDLE + //c.iconst(id); +c.visitMethodInsn(INVOKESTATIC, "java/dyn/MethodHandles", "lookup", "()Ljava/dyn/MethodHandles$Lookup;"); +c.visitLdcInsn(Type.getType("L"+module.classfile.name+";")); +c.visitLdcInsn(fname); +c.visitLdcInsn(Type.getType("Lorg/python/core/PyObject;")); +c.visitLdcInsn(Type.getType("Lorg/python/core/PyFrame;")); +c.visitInsn(ICONST_1); +c.visitTypeInsn(ANEWARRAY, "java/lang/Class"); +c.visitInsn(DUP); +c.visitInsn(ICONST_0); +c.visitLdcInsn(Type.getType("Lorg/python/core/ThreadState;")); +c.visitInsn(AASTORE); +c.visitMethodInsn(INVOKESTATIC, "java/dyn/MethodType", "make", "(Ljava/lang/Class;Ljava/lang/Class;[Ljava/lang/Class;)Ljava/dyn/MethodType;"); +c.visitMethodInsn(INVOKEVIRTUAL, "java/dyn/MethodHandles$Lookup", "findVirtual", "(Ljava/lang/Class;Ljava/lang/String;Ljava/dyn/MethodType;)Ljava/dyn/MethodHandle;"); + if (cellvars != null) { int strArray = CodeCompiler.makeStrings(c, cellvars); c.aload(strArray); @@ -287,7 +304,7 @@ c.iconst(moreflags); - c.invokestatic("org/python/core/Py", "newCode", "(I" + $strArr + $str + $str + "IZZ" + $pyFuncTbl + "I" + $strArr + $strArr + "II)" + $pyCode); + c.invokestatic("org/python/core/Py", "newCode", "(I" + $strArr + $str + $str + "IZZ" + $pyFuncTbl + "Ljava/dyn/MethodHandle;" + $strArr + $strArr + "II)" + $pyCode); c.putstatic(module.classfile.name, name, $pyCode); } } @@ -310,7 +327,7 @@ public Module(String name, String filename, boolean linenumbers, long mtime) { this.linenumbers = linenumbers; this.mtime = mtime; - classfile = new ClassFile(name, "org/python/core/PyFunctionTable", + classfile = new ClassFile(name, "org/python/core/IndyFunctionTable", ACC_SYNCHRONIZED | ACC_PUBLIC, mtime); constants = new Hashtable<Constant,Constant>(); sfilename = filename; @@ -523,7 +540,11 @@ public void addInit() throws IOException { Code c = classfile.addMethod("<init>", "(Ljava/lang/String;)V", ACC_PUBLIC); c.aload(0); - c.invokespecial("org/python/core/PyFunctionTable", "<init>", "()V"); + c.invokespecial("org/python/core/IndyFunctionTable", "<init>", "()V"); + + //HERE + //c.invokestatic(p(InvokeDynamicSupport.class), "registerBootstrap", sig(void.class, Class.class)); + addConstants(c); } @@ -584,30 +605,22 @@ public void addFunctions() throws IOException { Code code = classfile.addMethod( "call_function", - "(I" + $pyFrame + $threadState + ")" + $pyObj, + "(Ljava/dyn/MethodHandle;" + $pyFrame + $threadState + ")" + $pyObj, ACC_PUBLIC); + code.aload(1); // handle code.aload(0); // this code.aload(2); // frame code.aload(3); // thread state + /* Label def = new Label(); Label[] labels = new Label[codes.size()]; int i; for(i=0; i<labels.length; i++) labels[i] = new Label(); - //Get index for function to call - code.iload(1); - code.tableswitch(0, labels.length - 1, def, labels); - for(i=0; i<labels.length; i++) { - code.label(labels[i]); - code.invokevirtual(classfile.name, (codes.get(i)).fname, "(" + $pyFrame + $threadState + ")" + $pyObj); - code.areturn(); - } - code.label(def); - - //Should probably throw internal exception here - code.aconst_null(); + */ + code.invokevirtual("java/dyn/MethodHandle", "invoke", "(Ljava/lang/Object;" + $pyFrame + $threadState + ")" + $pyObj); code.areturn(); } Added: branches/indy/src/org/python/core/IndyCode.java =================================================================== --- branches/indy/src/org/python/core/IndyCode.java (rev 0) +++ branches/indy/src/org/python/core/IndyCode.java 2009-09-25 03:08:49 UTC (rev 6810) @@ -0,0 +1,212 @@ +// Copyright (c) Corporation for National Research Initiatives +package org.python.core; + +/** + * An implementation of PyCode where the actual executable content + * is stored as a PyFunctionTable instance and an integer index. + */ + +import org.python.modules._systemrestart; +import java.dyn.MethodHandle; + +public class IndyCode extends PyBaseCode +{ + + IndyFunctionTable funcs; + MethodHandle func_id; + public String co_code = ""; // only used by inspect + + public IndyCode(int argcount, String varnames[], + String filename, String name, + int firstlineno, + boolean varargs, boolean varkwargs, + IndyFunctionTable funcs, MethodHandle func_id) + { + this(argcount, varnames, filename, name, firstlineno, varargs, + varkwargs, funcs, func_id, null, null, 0, 0); + } + + public IndyCode(int argcount, String varnames[], + String filename, String name, + int firstlineno, + boolean varargs, boolean varkwargs, + IndyFunctionTable funcs, MethodHandle func_id, + String[] cellvars, String[] freevars, int npurecell, + int moreflags) // may change + { + co_argcount = nargs = argcount; + co_varnames = varnames; + co_nlocals = varnames.length; + co_filename = filename; + co_firstlineno = firstlineno; + co_cellvars = cellvars; + co_freevars = freevars; + this.jy_npurecell = npurecell; + this.varargs = varargs; + co_name = name; + if (varargs) { + co_argcount -= 1; + co_flags.setFlag(CodeFlag.CO_VARARGS); + } + this.varkwargs = varkwargs; + if (varkwargs) { + co_argcount -= 1; + co_flags.setFlag(CodeFlag.CO_VARKEYWORDS); + } + co_flags = new CompilerFlags(co_flags.toBits() | moreflags); + this.funcs = funcs; + this.func_id = func_id; + } + + private static final String[] __members__ = { + "co_name", "co_argcount", + "co_varnames", "co_filename", "co_firstlineno", + "co_flags","co_cellvars","co_freevars","co_nlocals" + // not supported: co_code, co_consts, co_names, + // co_lnotab, co_stacksize + }; + + public PyObject __dir__() { + PyString members[] = new PyString[__members__.length]; + for (int i = 0; i < __members__.length; i++) + members[i] = new PyString(__members__[i]); + return new PyList(members); + } + + private void throwReadonly(String name) { + for (int i = 0; i < __members__.length; i++) + if (__members__[i] == name) + throw Py.TypeError("readonly attribute"); + throw Py.AttributeError(name); + } + + public void __setattr__(String name, PyObject value) { + // no writable attributes + throwReadonly(name); + } + + public void __delattr__(String name) { + throwReadonly(name); + } + + private static PyTuple toPyStringTuple(String[] ar) { + if (ar == null) return Py.EmptyTuple; + int sz = ar.length; + PyString[] pystr = new PyString[sz]; + for (int i = 0; i < sz; i++) { + pystr[i] = new PyString(ar[i]); + } + return new PyTuple(pystr); + } + + public PyObject __findattr_ex__(String name) { + // have to craft co_varnames specially + if (name == "co_varnames") { + return toPyStringTuple(co_varnames); + } + if (name == "co_cellvars") { + return toPyStringTuple(co_cellvars); + } + if (name == "co_freevars") { + return toPyStringTuple(co_freevars); + } + if (name == "co_filename") { + return new PyString(co_filename); + } + if (name == "co_name") { + return new PyString(co_name); + } + if (name == "co_flags") { + return Py.newInteger(co_flags.toBits()); + } + return super.__findattr_ex__(name); + } + + @Override + public PyObject call(ThreadState ts, PyFrame frame, PyObject closure) { +// System.err.println("tablecode call: "+co_name); + if (ts.systemState == null) { + ts.systemState = Py.defaultSystemState; + } + //System.err.println("got ts: "+ts+", "+ts.systemState); + + // Cache previously defined exception + PyException previous_exception = ts.exception; + + // Push frame + frame.f_back = ts.frame; + if (frame.f_builtins == null) { + if (frame.f_back != null) { + frame.f_builtins = frame.f_back.f_builtins; + } else { + //System.err.println("ts: "+ts); + //System.err.println("ss: "+ts.systemState); + frame.f_builtins = PySystemState.builtins; + } + } + // nested scopes: setup env with closure + // this should only be done once, so let the frame take care of it + frame.setupEnv((PyTuple)closure); + + ts.frame = frame; + + // Handle trace function for debugging + if (ts.tracefunc != null) { + frame.f_lineno = co_firstlineno; + frame.tracefunc = ts.tracefunc.traceCall(frame); + } + + // Handle trace function for profiling + if (ts.profilefunc != null) { + ts.profilefunc.traceCall(frame); + } + + PyObject ret; + try { + ret = funcs.call_function(func_id, frame, ts); + } catch (Throwable t) { + // Convert exceptions that occured in Java code to PyExceptions + PyException pye = Py.JavaError(t); + pye.tracebackHere(frame); + + frame.f_lasti = -1; + + if (frame.tracefunc != null) { + frame.tracefunc.traceException(frame, pye); + } + if (ts.profilefunc != null) { + ts.profilefunc.traceException(frame, pye); + } + + // Rethrow the exception to the next stack frame + ts.exception = previous_exception; + ts.frame = ts.frame.f_back; + throw pye; + } + + if (frame.tracefunc != null) { + frame.tracefunc.traceReturn(frame, ret); + } + // Handle trace function for profiling + if (ts.profilefunc != null) { + ts.profilefunc.traceReturn(frame, ret); + } + + // Restore previously defined exception + ts.exception = previous_exception; + + ts.frame = ts.frame.f_back; + + // Check for interruption, which is used for restarting the interpreter + // on Jython + if (Thread.currentThread().isInterrupted()) { + throw new PyException(_systemrestart.SystemRestart); + } + return ret; + } + + @Override + protected PyObject interpret(PyFrame f, ThreadState ts) { + throw new UnsupportedOperationException("Inlined interpret to improve call performance (may want to reconsider in the future)."); + } +} Property changes on: branches/indy/src/org/python/core/IndyCode.java ___________________________________________________________________ Added: svn:eol-style + native Added: branches/indy/src/org/python/core/IndyFunctionTable.java =================================================================== --- branches/indy/src/org/python/core/IndyFunctionTable.java (rev 0) +++ branches/indy/src/org/python/core/IndyFunctionTable.java 2009-09-25 03:08:49 UTC (rev 6810) @@ -0,0 +1,15 @@ +// Copyright (c) Corporation for National Research Initiatives +package org.python.core; + +import java.dyn.MethodHandle; +/** + * An entry point for class that implements several function calls. + * <P> + * Used together with the PyTableCode class. + * + * @see PyTableCode + */ + +public abstract class IndyFunctionTable { + abstract public PyObject call_function(MethodHandle mh, PyFrame frame, ThreadState ts); +} Property changes on: branches/indy/src/org/python/core/IndyFunctionTable.java ___________________________________________________________________ Added: svn:eol-style + native Modified: branches/indy/src/org/python/core/Py.java =================================================================== --- branches/indy/src/org/python/core/Py.java 2009-09-24 01:34:49 UTC (rev 6809) +++ branches/indy/src/org/python/core/Py.java 2009-09-25 03:08:49 UTC (rev 6810) @@ -1,6 +1,7 @@ // Copyright (c) Corporation for National Research Initiatives package org.python.core; +import java.dyn.MethodHandle; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; @@ -630,10 +631,10 @@ public static PyCode newCode(int argcount, String varnames[], String filename, String name, boolean args, boolean keywords, - PyFunctionTable funcs, int func_id, + IndyFunctionTable funcs, MethodHandle func_id, String[] cellvars, String[] freevars, int npurecell, int moreflags) { - return new PyTableCode(argcount, varnames, + return new IndyCode(argcount, varnames, filename, name, 0, args, keywords, funcs, func_id, cellvars, freevars, npurecell, moreflags); @@ -643,10 +644,10 @@ String filename, String name, int firstlineno, boolean args, boolean keywords, - PyFunctionTable funcs, int func_id, + IndyFunctionTable funcs, MethodHandle func_id, String[] cellvars, String[] freevars, int npurecell, int moreflags) { - return new PyTableCode(argcount, varnames, + return new IndyCode(argcount, varnames, filename, name, firstlineno, args, keywords, funcs, func_id, cellvars, freevars, npurecell, moreflags); @@ -656,8 +657,8 @@ public static PyCode newCode(int argcount, String varnames[], String filename, String name, boolean args, boolean keywords, - PyFunctionTable funcs, int func_id) { - return new PyTableCode(argcount, varnames, + IndyFunctionTable funcs, MethodHandle func_id) { + return new IndyCode(argcount, varnames, filename, name, 0, args, keywords, funcs, func_id); } @@ -666,8 +667,8 @@ String filename, String name, int firstlineno, boolean args, boolean keywords, - PyFunctionTable funcs, int func_id) { - return new PyTableCode(argcount, varnames, + IndyFunctionTable funcs, MethodHandle func_id) { + return new IndyCode(argcount, varnames, filename, name, firstlineno, args, keywords, funcs, func_id); } @@ -1194,9 +1195,9 @@ globals = ts.frame.f_globals; } - PyTableCode tc = null; - if (code instanceof PyTableCode) { - tc = (PyTableCode) code; + IndyCode tc = null; + if (code instanceof IndyCode) { + tc = (IndyCode) code; } f = new PyFrame(tc, locals, globals, Modified: branches/indy/src/org/python/core/imp.java =================================================================== --- branches/indy/src/org/python/core/imp.java 2009-09-24 01:34:49 UTC (rev 6809) +++ branches/indy/src/org/python/core/imp.java 2009-09-25 03:08:49 UTC (rev 6810) @@ -308,9 +308,9 @@ public static PyObject createFromCode(String name, PyCode c, String moduleLocation) { PyModule module = addModule(name); - PyTableCode code = null; - if (c instanceof PyTableCode) { - code = (PyTableCode) c; + IndyCode code = null; + if (c instanceof IndyCode) { + code = (IndyCode) c; } if (moduleLocation != null) { Added: branches/indy/src/org/python/util/CodegenUtils.java =================================================================== --- branches/indy/src/org/python/util/CodegenUtils.java (rev 0) +++ branches/indy/src/org/python/util/CodegenUtils.java 2009-09-25 03:08:49 UTC (rev 6810) @@ -0,0 +1,137 @@ +/* + * Initial code taken from Charlie Nutter's org.jruby.util.CodegenUtils. + */ + +package org.python.util; + +import java.util.Arrays; + +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) + ";"; + } + } + } + + /** + * 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 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 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; + } + +} Property changes on: branches/indy/src/org/python/util/CodegenUtils.java ___________________________________________________________________ Added: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |