From: <zy...@us...> - 2009-01-20 13:56:50
|
Revision: 5949 http://jython.svn.sourceforge.net/jython/?rev=5949&view=rev Author: zyasoft Date: 2009-01-20 13:56:46 +0000 (Tue, 20 Jan 2009) Log Message: ----------- Initial commit. Modified Paths: -------------- branches/pbcvm/src/org/python/core/PyFrame.java branches/pbcvm/src/org/python/core/PyFunction.java branches/pbcvm/src/org/python/core/PyTableCode.java Added Paths: ----------- branches/pbcvm/src/org/python/core/Opcode.java branches/pbcvm/src/org/python/core/PyBaseCode.java branches/pbcvm/src/org/python/core/PyBytecode.java Added: branches/pbcvm/src/org/python/core/Opcode.java =================================================================== --- branches/pbcvm/src/org/python/core/Opcode.java (rev 0) +++ branches/pbcvm/src/org/python/core/Opcode.java 2009-01-20 13:56:46 UTC (rev 5949) @@ -0,0 +1,172 @@ +package org.python.core; + +// derived from CPython 2.5.2 Include/opcode.h + +public class Opcode { + + public static final int POP_TOP = 1; + public static final int ROT_TWO = 2; + public static final int ROT_THREE = 3; + public static final int DUP_TOP = 4; + public static final int ROT_FOUR = 5; + public static final int NOP = 9; + public static final int UNARY_POSITIVE = 10; + public static final int UNARY_NEGATIVE = 11; + public static final int UNARY_NOT = 12; + public static final int UNARY_CONVERT = 13; + public static final int UNARY_INVERT = 15; + public static final int LIST_APPEND = 18; + public static final int BINARY_POWER = 19; + public static final int BINARY_MULTIPLY = 20; + public static final int BINARY_DIVIDE = 21; + public static final int BINARY_MODULO = 22; + public static final int BINARY_ADD = 23; + public static final int BINARY_SUBTRACT = 24; + public static final int BINARY_SUBSCR = 25; + public static final int BINARY_FLOOR_DIVIDE = 26; + public static final int BINARY_TRUE_DIVIDE = 27; + public static final int INPLACE_FLOOR_DIVIDE = 28; + public static final int INPLACE_TRUE_DIVIDE = 29; + public static final int SLICE = 30; + /* Also uses 31-33 */ + public static final int STORE_SLICE = 40; + /* Also uses 41-43 */ + public static final int DELETE_SLICE = 50; + /* Also uses 51-53 */ + public static final int INPLACE_ADD = 55; + public static final int INPLACE_SUBTRACT = 56; + public static final int INPLACE_MULTIPLY = 57; + public static final int INPLACE_DIVIDE = 58; + public static final int INPLACE_MODULO = 59; + public static final int STORE_SUBSCR = 60; + public static final int DELETE_SUBSCR = 61; + public static final int BINARY_LSHIFT = 62; + public static final int BINARY_RSHIFT = 63; + public static final int BINARY_AND = 64; + public static final int BINARY_XOR = 65; + public static final int BINARY_OR = 66; + public static final int INPLACE_POWER = 67; + public static final int GET_ITER = 68; + public static final int PRINT_EXPR = 70; + public static final int PRINT_ITEM = 71; + public static final int PRINT_NEWLINE = 72; + public static final int PRINT_ITEM_TO = 73; + public static final int PRINT_NEWLINE_TO = 74; + public static final int INPLACE_LSHIFT = 75; + public static final int INPLACE_RSHIFT = 76; + public static final int INPLACE_AND = 77; + public static final int INPLACE_XOR = 78; + public static final int INPLACE_OR = 79; + public static final int BREAK_LOOP = 80; + public static final int WITH_CLEANUP = 81; + public static final int LOAD_LOCALS = 82; + public static final int RETURN_VALUE = 83; + public static final int IMPORT_STAR = 84; + public static final int EXEC_STMT = 85; + public static final int YIELD_VALUE = 86; + public static final int POP_BLOCK = 87; + public static final int END_FINALLY = 88; + public static final int BUILD_CLASS = 89; + public static final int HAVE_ARGUMENT = 90; /* Opcodes from here have an argument: */ + + public static final int STORE_NAME = 90; /* Index in name list */ + + public static final int DELETE_NAME = 91; /* "" */ + + public static final int UNPACK_SEQUENCE = 92; /* Number of sequence items */ + + public static final int FOR_ITER = 93; + public static final int STORE_ATTR = 95; /* Index in name list */ + + public static final int DELETE_ATTR = 96; /* "" */ + + public static final int STORE_GLOBAL = 97; /* "" */ + + public static final int DELETE_GLOBAL = 98; /* "" */ + + public static final int DUP_TOPX = 99; /* number of items to duplicate */ + + public static final int LOAD_CONST = 100; /* Index in const list */ + + public static final int LOAD_NAME = 101; /* Index in name list */ + + public static final int BUILD_TUPLE = 102; /* Number of tuple items */ + + public static final int BUILD_LIST = 103; /* Number of list items */ + + public static final int BUILD_MAP = 104; /* Always zero for now */ + + public static final int LOAD_ATTR = 105; /* Index in name list */ + + public static final int COMPARE_OP = 106; /* Comparison operator */ + + public static final int IMPORT_NAME = 107; /* Index in name list */ + + public static final int IMPORT_FROM = 108; /* Index in name list */ + + public static final int JUMP_FORWARD = 110; /* Number of bytes to skip */ + + public static final int JUMP_IF_FALSE = 111; /* "" */ + + public static final int JUMP_IF_TRUE = 112; /* "" */ + + public static final int JUMP_ABSOLUTE = 113; /* Target byte offset from beginning of code */ + + public static final int LOAD_GLOBAL = 116; /* Index in name list */ + + public static final int CONTINUE_LOOP = 119; /* Start of loop (absolute) */ + + public static final int SETUP_LOOP = 120; /* Target address (absolute) */ + + public static final int SETUP_EXCEPT = 121; /* "" */ + + public static final int SETUP_FINALLY = 122; /* "" */ + + public static final int LOAD_FAST = 124; /* Local variable number */ + + public static final int STORE_FAST = 125; /* Local variable number */ + + public static final int DELETE_FAST = 126; /* Local variable number */ + + public static final int RAISE_VARARGS = 130; /* Number of raise arguments (1, 2 or 3) */ + /* CALL_FUNCTION_XXX opcodes defined below depend on this definition */ + + public static final int CALL_FUNCTION = 131; /* #args + (#kwargs<<8) */ + + public static final int MAKE_FUNCTION = 132; /* #defaults */ + + public static final int BUILD_SLICE = 133; /* Number of items */ + + public static final int MAKE_CLOSURE = 134; /* #free vars */ + + public static final int LOAD_CLOSURE = 135; /* Load free variable from closure */ + + public static final int LOAD_DEREF = 136; /* Load and dereference from closure cell */ + + public static final int STORE_DEREF = 137; /* Store into cell */ + + /* The next 3 opcodes must be contiguous and satisfy + (CALL_FUNCTION_VAR - CALL_FUNCTION) & 3 == 1 */ + public static final int CALL_FUNCTION_VAR = 140; /* #args + (#kwargs<<8) */ + + public static final int CALL_FUNCTION_KW = 141; /* #args + (#kwargs<<8) */ + + public static final int CALL_FUNCTION_VAR_KW = 142; /* #args + (#kwargs<<8) */ + + /* Support for opargs more than 16 bits long */ + public static final int EXTENDED_ARG = 143; + + // comparison opcodes (on the oparg), just put in this class too + public static final int PyCmp_LT = 0; + public static final int PyCmp_LE = 1; + public static final int PyCmp_EQ = 2; + public static final int PyCmp_NE = 3; + public static final int PyCmp_GT = 4; + public static final int PyCmp_GE = 5; + public static final int PyCmp_IN = 6; + public static final int PyCmp_NOT_IN = 7; + public static final int PyCmp_IS = 8; + public static final int PyCmp_IS_NOT = 9; + public static final int PyCmp_EXC_MATCH = 10; + +} Added: branches/pbcvm/src/org/python/core/PyBaseCode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyBaseCode.java (rev 0) +++ branches/pbcvm/src/org/python/core/PyBaseCode.java 2009-01-20 13:56:46 UTC (rev 5949) @@ -0,0 +1,314 @@ +// Copyright (c) Corporation for National Research Initiatives +package org.python.core; + +import org.python.modules._systemrestart; + +public abstract class PyBaseCode extends PyCode { + + public int co_argcount; + int nargs; + public int co_firstlineno = -1; + public String co_varnames[]; + public String co_cellvars[]; + public int jy_npurecell; // internal: jython specific + public String co_freevars[]; + public String co_filename; + public int co_flags; + public int co_nlocals; + public boolean varargs, varkwargs; + + final public static int CO_OPTIMIZED = 0x0001; + //final public static int CO_NEWLOCALS = 0x0002 + final public static int CO_VARARGS = 0x0004; + final public static int CO_VARKEYWORDS = 0x0008; + final public static int CO_GENERATOR = 0x0020; + + // these are defined in __future__.py + final public static int CO_NESTED = 0x0010; + final public static int CO_GENERATOR_ALLOWED = 0x0; + final public static int CO_FUTUREDIVISION = 0x2000; + final public static int CO_FUTURE_ABSOLUTE_IMPORT = 0x4000; + final public static int CO_WITH_STATEMENT = 0x8000; + + //XXX: I'm not positive that this is the right place for these constants. + final public static int PyCF_SOURCE_IS_UTF8 = 0x0100; + final public static int PyCF_DONT_IMPLY_DEDENT = 0x0200; + final public static int PyCF_ONLY_AST = 0x0400; + + final public static int CO_ALL_FEATURES = PyCF_DONT_IMPLY_DEDENT|PyCF_ONLY_AST| + PyCF_SOURCE_IS_UTF8|CO_NESTED| + CO_GENERATOR_ALLOWED| CO_FUTUREDIVISION| + CO_FUTURE_ABSOLUTE_IMPORT|CO_WITH_STATEMENT; + + + public boolean hasFreevars() { + return co_freevars != null && co_freevars.length > 0; + } + + public PyObject call(PyFrame frame, PyObject closure) { +// System.err.println("tablecode call: "+co_name); + ThreadState ts = Py.getThreadState(); + 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 = interpret(frame); + } 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; + } + + public PyObject call(PyObject globals, PyObject[] defaults, + PyObject closure) + { + if (co_argcount != 0 || varargs || varkwargs) + return call(Py.EmptyObjects, Py.NoKeywords, globals, defaults, + closure); + PyFrame frame = new PyFrame(this, globals); + if ((co_flags & CO_GENERATOR) != 0) { + return new PyGenerator(frame, closure); + } + return call(frame, closure); + } + + public PyObject call(PyObject arg1, PyObject globals, PyObject[] defaults, + PyObject closure) + { + if (co_argcount != 1 || varargs || varkwargs) + return call(new PyObject[] {arg1}, + Py.NoKeywords, globals, defaults, closure); + PyFrame frame = new PyFrame(this, globals); + frame.f_fastlocals[0] = arg1; + if ((co_flags & CO_GENERATOR) != 0) { + return new PyGenerator(frame, closure); + } + return call(frame, closure); + } + + public PyObject call(PyObject arg1, PyObject arg2, PyObject globals, + PyObject[] defaults, PyObject closure) + { + if (co_argcount != 2 || varargs || varkwargs) + return call(new PyObject[] {arg1, arg2}, + Py.NoKeywords, globals, defaults, closure); + PyFrame frame = new PyFrame(this, globals); + frame.f_fastlocals[0] = arg1; + frame.f_fastlocals[1] = arg2; + if ((co_flags & CO_GENERATOR) != 0) { + return new PyGenerator(frame, closure); + } + return call(frame, closure); + } + + public PyObject call(PyObject arg1, PyObject arg2, PyObject arg3, + PyObject globals, PyObject[] defaults, + PyObject closure) + { + if (co_argcount != 3 || varargs || varkwargs) + return call(new PyObject[] {arg1, arg2, arg3}, + Py.NoKeywords, globals, defaults, closure); + PyFrame frame = new PyFrame(this, globals); + frame.f_fastlocals[0] = arg1; + frame.f_fastlocals[1] = arg2; + frame.f_fastlocals[2] = arg3; + if ((co_flags & CO_GENERATOR) != 0) { + return new PyGenerator(frame, closure); + } + return call(frame, closure); + } + + public PyObject call(PyObject self, PyObject args[], + String keywords[], PyObject globals, + PyObject[] defaults, PyObject closure) + { + PyObject[] os = new PyObject[args.length+1]; + os[0] = self; + System.arraycopy(args, 0, os, 1, args.length); + return call(os, keywords, globals, defaults, closure); + } + + public PyObject call(PyObject args[], String kws[], PyObject globals, PyObject[] defs, + PyObject closure) { + PyFrame frame = new PyFrame(this, globals); + int argcount = args.length - kws.length; + int defcount = defs != null ? defs.length : 0; + PyObject[] fastlocals = frame.f_fastlocals; + + if (co_argcount > 0 || (varargs || varkwargs)) { + int i; + int n = argcount; + PyObject kwdict = null; + if (varkwargs) { + kwdict = new PyDictionary(); + i = co_argcount; + if (varargs) { + i++; + } + fastlocals[i] = kwdict; + } + if (argcount > co_argcount) { + if (!varargs) { + String msg = String.format("%.200s() takes %s %d %sargument%s (%d given)", + co_name, + defcount > 0 ? "at most" : "exactly", + co_argcount, + kws.length > 0 ? "non-keyword " : "", + co_argcount == 1 ? "" : "s", + argcount); + throw Py.TypeError(msg); + } + n = co_argcount; + } + + System.arraycopy(args, 0, fastlocals, 0, n); + + if (varargs) { + PyObject[] u = new PyObject[argcount - n]; + System.arraycopy(args, n, u, 0, argcount - n); + PyObject uTuple = new PyTuple(u); + fastlocals[co_argcount] = uTuple; + } + for (i = 0; i < kws.length; i++) { + String keyword = kws[i]; + PyObject value = args[i + argcount]; + int j; + // XXX: keywords aren't PyObjects, can't ensure strings + //if (keyword == null || keyword.getClass() != PyString.class) { + // throw Py.TypeError(String.format("%.200s() keywords must be strings", + // co_name)); + //} + for (j = 0; j < co_argcount; j++) { + if (co_varnames[j].equals(keyword)) { + break; + } + } + if (j >= co_argcount) { + if (kwdict == null) { + throw Py.TypeError(String.format("%.200s() got an unexpected keyword " + + "argument '%.400s'", + co_name, keyword)); + } + kwdict.__setitem__(keyword, value); + } else { + if (fastlocals[j] != null) { + throw Py.TypeError(String.format("%.200s() got multiple values for " + + "keyword argument '%.400s'", + co_name, keyword)); + } + fastlocals[j] = value; + } + } + if (argcount < co_argcount) { + int m = co_argcount - defcount; + for (i = argcount; i < m; i++) { + if (fastlocals[i] == null) { + String msg = + String.format("%.200s() takes %s %d %sargument%s (%d given)", + co_name, (varargs || defcount > 0) ? + "at least" : "exactly", + m, kws.length > 0 ? "non-keyword " : "", + m == 1 ? "" : "s", i); + throw Py.TypeError(msg); + } + } + if (n > m) { + i = n - m; + } else { + i = 0; + } + for (; i < defcount; i++) { + if (fastlocals[m + i] == null) { + fastlocals[m + i] = defs[i]; + } + } + } + } else if (argcount > 0) { + throw Py.TypeError(String.format("%.200s() takes no arguments (%d given)", + co_name, argcount)); + } + + if ((co_flags & CO_GENERATOR) != 0) { + return new PyGenerator(frame, closure); + } + return call(frame, closure); + } + + public String toString() { + return String.format("<code object %.100s at %s, file \"%.300s\", line %d>", + co_name, Py.idstr(this), co_filename, co_firstlineno); + } + + protected PyObject interpret(PyFrame f) { + throw new UnsupportedOperationException("interpret not supported"); + } +} Added: branches/pbcvm/src/org/python/core/PyBytecode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyBytecode.java (rev 0) +++ branches/pbcvm/src/org/python/core/PyBytecode.java 2009-01-20 13:56:46 UTC (rev 5949) @@ -0,0 +1,1129 @@ +package org.python.core; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +public class PyBytecode extends PyBaseCode { + + // for debugging + static int count = 0; // total number of opcodes run + final static int maxCount = 900; // less than my buffer on iterm + static PyObject opname; + + static synchronized PyObject getOpname() { + if (opname == null) { + opname = __builtin__.__import__("dis").__getattr__("opname"); + } + return opname; + } + // end debugging + + public final char[] co_code; // to avoid sign issues + public final PyObject[] co_consts; + public final String[] co_names; + public final int co_stacksize; // ignored, probably shouldn't be + public final PyObject[] co_lnotab; // ignored + + // follows new.code's interface + public PyBytecode(int argcount, int nlocals, int stacksize, int flags, + String codestring, PyObject[] constants, String[] names, String varnames[], + String filename, String name, int firstlineno, PyObject[] lnotab) { + this(argcount, nlocals, stacksize, flags, codestring, + constants, names, varnames, filename, name, firstlineno, lnotab, + null, null); + } + + public PyBytecode(int argcount, int nlocals, int stacksize, int flags, + String codestring, PyObject[] constants, String[] names, String varnames[], + String filename, String name, int firstlineno, PyObject[] lnotab, + String[] cellvars, String[] freevars) { + co_argcount = nargs = argcount; + co_varnames = varnames; + co_nlocals = nlocals; // maybe assert = varnames.length; + co_filename = filename; + co_firstlineno = firstlineno; + co_cellvars = cellvars; + co_freevars = freevars; + co_name = name; + +// need to look at how this is used, since it's not part of the standard new.code interface +// this.varargs = varargs; +// if (varargs) { +// co_argcount -= 1; +// co_flags |= CO_VARARGS; +// } +// this.varkwargs = varkwargs; +// if (varkwargs) { +// co_argcount -= 1; +// co_flags |= CO_VARKEYWORDS; +// } + co_flags |= flags; + + co_stacksize = stacksize; + co_consts = constants; + co_names = names; + co_code = codestring.toCharArray(); + co_lnotab = lnotab; + } + private static final String[] __members__ = { + "co_name", "co_argcount", + "co_varnames", "co_filename", "co_firstlineno", + "co_flags", "co_cellvars", "co_freevars", "co_nlocals", + "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); + } + return super.__findattr_ex__(name); + } + + enum Why { + + NOT, /* No error */ + EXCEPTION, /* Exception occurred */ + RERAISE, /* Exception re-raised by 'finally' */ + RETURN, /* 'return' statement */ + BREAK, /* 'break' statement */ + CONTINUE, /* 'continue' statement */ + YIELD /* 'yield' operator */ + + }; + + private Why do_raise() { + throw new UnsupportedOperationException("Not yet implemented"); + } + + private Why do_raise(PyObject type) { + throw new UnsupportedOperationException("Not yet implemented"); + } + + private Why do_raise(PyObject type, PyObject value) { + throw new UnsupportedOperationException("Not yet implemented"); + } + + private Why do_raise(PyObject type, PyObject value, PyObject traceback) { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + protected PyObject interpret(PyFrame f) { + final PyStack stack = new PyStack(); + int next_instr = -1; + int opcode; /* Current opcode */ + int oparg = 0; /* Current opcode argument, if any */ + Why why = Why.NOT; + PyObject retval = null; + + while (count < maxCount) { // XXX - replace with while(true) + + f.f_lasti = next_instr++; // should have no worries about needing co_lnotab, just keep this current + opcode = co_code[next_instr]; + if (opcode > Opcode.HAVE_ARGUMENT) { + next_instr += 2; + oparg = (co_code[next_instr] << 8) + co_code[next_instr - 1]; + System.err.println(count + "," + next_instr + "> opcode: " + getOpname().__getitem__(Py.newInteger(opcode)) + ", oparg: " + oparg + ", stack: " + stack.toString()); + } else { + System.err.println(count + "," + next_instr + "> opcode: " + getOpname().__getitem__(Py.newInteger(opcode)) + ", stack: " + stack.toString()); + } + count += 1; + + try { + switch (opcode) { + case Opcode.NOP: + break; + + case Opcode.LOAD_FAST: + stack.push(f.getlocal(oparg)); + break; + + case Opcode.LOAD_CONST: + stack.push(co_consts[oparg]); + break; + + case Opcode.STORE_FAST: + f.setlocal(oparg, stack.pop()); + break; + + case Opcode.POP_TOP: + stack.pop(); + break; + + case Opcode.ROT_TWO: + stack.rotN(2); + break; + + case Opcode.ROT_THREE: + stack.rotN(3); + break; + + case Opcode.ROT_FOUR: + stack.rotN(4); + break; + + case Opcode.DUP_TOP: + stack.dup(); + break; + + case Opcode.DUP_TOPX: + if (oparg == 2 || oparg == 3) { + stack.dupN(oparg); + } else { + throw Py.RuntimeError("invalid argument to DUP_TOPX" + + " (bytecode corruption?)"); + } + break; + + case Opcode.UNARY_POSITIVE: + stack.push(stack.pop().__pos__()); + break; + + case Opcode.UNARY_NEGATIVE: + stack.push(stack.pop().__neg__()); + break; + + case Opcode.UNARY_NOT: + stack.push(stack.pop().__not__()); + break; + + case Opcode.UNARY_CONVERT: + stack.push(stack.pop().__repr__()); + break; + + case Opcode.UNARY_INVERT: + stack.push(stack.pop().__invert__()); + break; + + case Opcode.BINARY_POWER: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__pow__(b)); + break; + } + + case Opcode.BINARY_MULTIPLY: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__mul__(b)); + break; + } + + case Opcode.BINARY_DIVIDE: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + + if ((co_flags & CO_FUTUREDIVISION) == 0) { + stack.push(a.__div__(b)); + } else { + stack.push(a.__truediv__(b)); + } + break; + } + + case Opcode.BINARY_TRUE_DIVIDE: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__truediv__(b)); + break; + } + + case Opcode.BINARY_FLOOR_DIVIDE: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__floordiv__(b)); + break; + } + + case Opcode.BINARY_MODULO: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__mod__(b)); + break; + } + + case Opcode.BINARY_ADD: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__add__(b)); + break; + } + + case Opcode.BINARY_SUBTRACT: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__sub__(b)); + break; + } + + case Opcode.BINARY_SUBSCR: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__getitem__(b)); + break; + } + + case Opcode.BINARY_LSHIFT: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__lshift__(b)); + break; + } + + case Opcode.BINARY_RSHIFT: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__rshift__(b)); + break; + } + + case Opcode.BINARY_AND: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__and__(b)); + break; + } + + + case Opcode.BINARY_XOR: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__xor__(b)); + break; + } + + case Opcode.BINARY_OR: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__or__(b)); + break; + } + + case Opcode.LIST_APPEND: { + PyObject b = stack.pop(); + PyList a = (PyList) (stack.pop()); + a.append(b); + break; + } + + case Opcode.INPLACE_POWER: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__ipow__(b)); + break; + } + + case Opcode.INPLACE_MULTIPLY: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__imul__(b)); + break; + } + + case Opcode.INPLACE_DIVIDE: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + if ((co_flags & CO_FUTUREDIVISION) == 0) { + stack.push(a.__idiv__(b)); + } else { + stack.push(a.__itruediv__(b)); + } + break; + } + + case Opcode.INPLACE_TRUE_DIVIDE: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__itruediv__(b)); + break; + } + + case Opcode.INPLACE_FLOOR_DIVIDE: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__ifloordiv__(b)); + break; + } + + case Opcode.INPLACE_MODULO: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__imod__(b)); + break; + } + + case Opcode.INPLACE_ADD: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__iadd__(b)); + break; + } + + case Opcode.INPLACE_SUBTRACT: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__isub__(b)); + break; + } + + case Opcode.INPLACE_LSHIFT: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__ilshift__(b)); + break; + } + + case Opcode.INPLACE_RSHIFT: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__irshift__(b)); + break; + } + + case Opcode.INPLACE_AND: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__iand__(b)); + break; + } + + case Opcode.INPLACE_XOR: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__ixor__(b)); + break; + } + + case Opcode.INPLACE_OR: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__ior__(b)); + break; + } + +// +// case SLICE+0: +// case SLICE+1: +// case SLICE+2: +// case SLICE+3: +// if ((opcode-SLICE) & 2) +// w = POP(); +// else +// w = NULL; +// if ((opcode-SLICE) & 1) +// v = POP(); +// else +// v = NULL; +// u = TOP(); +// x = apply_slice(u, v, w); +// Py_DECREF(u); +// Py_XDECREF(v); +// Py_XDECREF(w); +// SET_TOP(x); +// if (x != NULL) continue; +// break; +// +// case Opcode.STORE_SLICE+0: +// case Opcode.STORE_SLICE+1: +// case Opcode.STORE_SLICE+2: +// case Opcode.STORE_SLICE+3: +// if (((opcode - Opcode.STORE_SLICE) & 2) !=0) { +// +// } +// w = POP(); +// else +// w = NULL; +// if ((opcode-STORE_SLICE) & 1) +// v = POP(); +// else +// v = NULL; +// u = POP(); +// t = POP(); +// err = assign_slice(u, v, w, t); /* u[v:w] = t */ +// Py_DECREF(t); +// Py_DECREF(u); +// Py_XDECREF(v); +// Py_XDECREF(w); +// if (err == 0) continue; +// break; +// +// case DELETE_SLICE+0: +// case DELETE_SLICE+1: +// case DELETE_SLICE+2: +// case DELETE_SLICE+3: +// if ((opcode-DELETE_SLICE) & 2) +// w = POP(); +// else +// w = NULL; +// if ((opcode-DELETE_SLICE) & 1) +// v = POP(); +// else +// v = NULL; +// u = POP(); +// err = assign_slice(u, v, w, (PyObject *)NULL); +// /* del u[v:w] */ +// Py_DECREF(u); +// Py_XDECREF(v); +// Py_XDECREF(w); +// if (err == 0) continue; +// break; +// + case Opcode.STORE_SUBSCR: { + PyObject key = stack.pop(); + PyObject obj = stack.pop(); + PyObject value = stack.pop(); + obj.__setitem__(key, value); + break; + } + + case Opcode.DELETE_SUBSCR: { + PyObject key = stack.pop(); + PyObject obj = stack.pop(); + obj.__delitem__(key); + break; + } + + case Opcode.PRINT_EXPR: + PySystemState.displayhook(stack.pop()); + break; + + case Opcode.PRINT_ITEM_TO: + Py.printComma(stack.pop(), stack.pop()); + break; + + case Opcode.PRINT_ITEM: + Py.printComma(stack.pop()); + break; + + case Opcode.PRINT_NEWLINE_TO: + Py.printlnv(stack.pop()); + break; + + case Opcode.PRINT_NEWLINE: + Py.println(); + break; + + case Opcode.RAISE_VARARGS: + + switch (oparg) { + case 3: { + PyObject tb = stack.pop(); + PyObject value = stack.pop(); + PyObject type = stack.pop(); + why = do_raise(type, value, tb); + break; + } + case 2: { + PyObject value = stack.pop(); + PyObject type = stack.pop(); + why = do_raise(type, value); + break; + } + case 1: { + PyObject type = stack.pop(); + why = do_raise(type); + break; + } + case 0: + why = do_raise(); + break; + default: + throw Py.SystemError("bad RAISE_VARARGS oparg"); + } + break; + + case Opcode.LOAD_LOCALS: + stack.push(f.f_locals); + break; + + case Opcode.RETURN_VALUE: + retval = stack.pop(); + why = Why.RETURN; + break; + + case Opcode.YIELD_VALUE: + retval = stack.pop(); + why = Why.YIELD; + break; + + case Opcode.EXEC_STMT: { + PyObject locals = stack.pop(); + PyObject globals = stack.pop(); + PyObject code = stack.pop(); + + if ((locals == null || locals == Py.None) && + (globals == null || globals == Py.None)) { + throw Py.SystemError("globals and locals cannot be NULL"); + } + Py.exec(code, globals, locals); + + if (!(globals.__finditem__("__builtins__").__nonzero__())) { + globals.__setitem__("__builtins__", f.f_builtins); + } + break; + } + +// case POP_BLOCK: +// { +// PyTryBlock *b = PyFrame_BlockPop(f); +// while (STACK_LEVEL() > b->b_level) { +// v = POP(); +// Py_DECREF(v); +// } +// } +// continue; +// +// case END_FINALLY: +// v = POP(); +// if (PyInt_Check(v)) { +// why = (enum why_code) PyInt_AS_LONG(v); +// assert(why != WHY_YIELD); +// if (why == WHY_RETURN || +// why == WHY_CONTINUE) +// retval = POP(); +// } +// else if (PyExceptionClass_Check(v) || PyString_Check(v)) { +// w = POP(); +// u = POP(); +// PyErr_Restore(v, w, u); +// why = WHY_RERAISE; +// break; +// } +// else if (v != Py_None) { +// PyErr_SetString(PyExc_SystemError, +// "'finally' pops bad exception"); +// why = WHY_EXCEPTION; +// } +// Py_DECREF(v); +// break; +// + case Opcode.BUILD_CLASS: { + PyObject methods = stack.pop(); + PyObject bases[] = (new PyTuple(stack.pop())).getArray(); + String name = stack.pop().toString(); + stack.push(Py.makeClass(name, bases, methods)); + break; + } + + case Opcode.STORE_NAME: + f.setlocal(oparg, stack.pop()); + break; + + case Opcode.DELETE_NAME: + f.dellocal(oparg); + break; + + case Opcode.UNPACK_SEQUENCE: { + PyObject v = stack.pop(); + int i = 0; + PyObject items[] = new PyObject[oparg]; + for (PyObject item : v.asIterable()) { + items[i++] = item; + if (i > oparg) { + break; + } + } + for (i = i - 1; i >= 0; i--) { + stack.push(items[i]); + } + break; + } + + case Opcode.STORE_ATTR: { + PyObject obj = stack.pop(); + PyObject v = stack.pop(); + obj.__setattr__(co_names[oparg], v); + break; + } + + case Opcode.DELETE_ATTR: + stack.pop().__delattr__(co_names[oparg]); + break; + + case Opcode.STORE_GLOBAL: + f.setglobal(co_names[oparg], stack.pop()); + break; + + case Opcode.DELETE_GLOBAL: + f.delglobal(co_names[oparg]); + break; + + case Opcode.LOAD_NAME: + stack.push(f.getname(co_names[oparg])); + break; + + case Opcode.LOAD_GLOBAL: + stack.push(f.getglobal(co_names[oparg])); + break; + + case Opcode.DELETE_FAST: + f.dellocal(oparg); + break; + + case Opcode.LOAD_CLOSURE: + stack.push(f.getclosure(oparg)); + break; + + case Opcode.LOAD_DEREF: + stack.push(f.getderef(oparg)); + break; + + case Opcode.STORE_DEREF: + f.setderef(oparg, stack.pop()); + break; + + case Opcode.BUILD_TUPLE: + stack.push(new PyTuple(stack.popN(oparg))); + break; + + case Opcode.BUILD_LIST: + stack.push(new PyList(stack.popN(oparg))); + break; + + case Opcode.BUILD_MAP: + stack.push(new PyDictionary()); + + case Opcode.LOAD_ATTR: + stack.push(stack.pop().__getattr__(co_names[oparg])); + break; + + case Opcode.COMPARE_OP: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + + switch (oparg) { + + case Opcode.PyCmp_LT: + stack.push(a._lt(b)); + break; + case Opcode.PyCmp_LE: + stack.push(a._le(b)); + break; + case Opcode.PyCmp_EQ: + stack.push(a._eq(b)); + break; + case Opcode.PyCmp_NE: + stack.push(a._ne(b)); + break; + case Opcode.PyCmp_GT: + stack.push(a._gt(b)); + break; + case Opcode.PyCmp_GE: + stack.push(a._ge(b)); + break; + case Opcode.PyCmp_IN: + stack.push(a._in(b)); + break; + case Opcode.PyCmp_NOT_IN: + stack.push(a._notin(b)); + break; + case Opcode.PyCmp_IS: + stack.push(a._is(b)); + break; + case Opcode.PyCmp_IS_NOT: + stack.push(a._isnot(b)); + break; + case Opcode.PyCmp_EXC_MATCH: + stack.push(Py.newBoolean(Py.matchException(new PyException(a), b))); + break; + + } + break; + } + + case Opcode.IMPORT_NAME: { + PyObject __import__ = f.f_builtins.__finditem__("__import__"); + if (__import__ == null) { + throw Py.ImportError("__import__ not found"); + } + PyString name = Py.newString(co_names[oparg]); + PyObject fromlist = stack.pop(); + PyObject level = stack.pop(); + + if (level.asInt() != -1) { + stack.push(__import__.__call__(new PyObject[]{name, f.f_globals, f.f_locals, fromlist, level})); + } else { + stack.push(__import__.__call__(new PyObject[]{name, f.f_globals, f.f_locals, fromlist})); + } + break; + } + + case Opcode.IMPORT_STAR: { + String module = stack.pop().toString(); + imp.importAll(module, f); + break; + } + + case Opcode.IMPORT_FROM: + String name = co_names[oparg]; + try { + stack.push(stack.pop().__getattr__(name)); + + } catch (PyException pye) { + if (Py.matchException(pye, Py.AttributeError)) { + throw Py.ImportError(String.format("cannot import name %.230s", name)); + } else { + throw pye; + } + } + break; + + case Opcode.JUMP_FORWARD: + next_instr += oparg; + break; + + case Opcode.JUMP_IF_FALSE: + if (!stack.top().__nonzero__()) { + next_instr += oparg; + } + break; + + case Opcode.JUMP_IF_TRUE: + if (stack.top().__nonzero__()) { + next_instr += oparg; + } + break; + + case Opcode.JUMP_ABSOLUTE: + next_instr = oparg; + break; + + case Opcode.GET_ITER: { + PyObject it = stack.top().__iter__(); + if (it != null) { + stack.set_top(it); + } + break; + } + + case Opcode.FOR_ITER: { + PyObject it = stack.pop(); + try { + PyObject x = it.__iternext__(); + if (x != null) { + stack.push(x); + } + } catch (PyException pye) { + if (!Py.matchException(pye, Py.StopIteration)) { + throw pye; + } + } + next_instr += oparg; + break; + } + + case Opcode.BREAK_LOOP: + why = Why.BREAK; + break; + + case Opcode.CONTINUE_LOOP: + retval = Py.newInteger(oparg); + if (retval.__nonzero__()) { + why = Why.CONTINUE; + } + break; +// +// case SETUP_LOOP: +// case SETUP_EXCEPT: +// case SETUP_FINALLY: +// /* NOTE: If you add any new block-setup opcodes that are not try/except/finally +// handlers, you may need to update the PyGen_NeedsFinalizing() function. */ +// +// PyFrame_BlockSetup(f, opcode, INSTR_OFFSET() + oparg, +// STACK_LEVEL()); +// continue; +// +// case WITH_CLEANUP: +// { +// /* TOP is the context.__exit__ bound method. +// Below that are 1-3 values indicating how/why +// we entered the finally clause: +// - SECOND = None +// - (SECOND, THIRD) = (WHY_{RETURN,CONTINUE}), retval +// - SECOND = WHY_*; no retval below it +// - (SECOND, THIRD, FOURTH) = exc_info() +// In the last case, we must call +// TOP(SECOND, THIRD, FOURTH) +// otherwise we must call +// TOP(None, None, None) +// +// In addition, if the stack represents an exception, +// *and* the function call returns a 'true' value, we +// "zap" this information, to prevent END_FINALLY from +// re-raising the exception. (But non-local gotos +// should still be resumed.) +// */ +// +// x = TOP(); +// u = SECOND(); +// if (PyInt_Check(u) || u == Py_None) { +// u = v = w = Py_None; +// } +// else { +// v = THIRD(); +// w = FOURTH(); +// } +// /* XXX Not the fastest way to call it... */ +// x = PyObject_CallFunctionObjArgs(x, u, v, w, NULL); +// if (x == NULL) +// break; /* Go to error exit */ +// if (u != Py_None && PyObject_IsTrue(x)) { +// /* There was an exception and a true return */ +// Py_DECREF(x); +// x = TOP(); /* Again */ +// STACKADJ(-3); +// Py_INCREF(Py_None); +// SET_TOP(Py_None); +// Py_DECREF(x); +// Py_DECREF(u); +// Py_DECREF(v); +// Py_DECREF(w); +// } else { +// /* Let END_FINALLY do its thing */ +// Py_DECREF(x); +// x = POP(); +// Py_DECREF(x); +// } +// break; +// } +// + case Opcode.CALL_FUNCTION: { + int na = oparg & 0xff; + int nk = (oparg >> 8) & 0xff; + int n = na + 2 * nk; + + PyObject args[] = stack.popN(na); + PyObject callable = stack.pop(); + System.err.println("__call__:" + callable + "," + Arrays.toString(args)); + stack.push(callable.__call__(args)); + break; + } + +// +// case CALL_FUNCTION_VAR: +// case CALL_FUNCTION_KW: +// case CALL_FUNCTION_VAR_KW: +// { +// int na = oparg & 0xff; +// int nk = (oparg>>8) & 0xff; +// int flags = (opcode - CALL_FUNCTION) & 3; +// int n = na + 2 * nk; +// PyObject **pfunc, *func, **sp; +// PCALL(PCALL_ALL); +// if (flags & CALL_FLAG_VAR) +// n++; +// if (flags & CALL_FLAG_KW) +// n++; +// pfunc = stack_pointer - n - 1; +// func = *pfunc; +// +// if (PyMethod_Check(func) +// && PyMethod_GET_SELF(func) != NULL) { +// PyObject *self = PyMethod_GET_SELF(func); +// Py_INCREF(self); +// func = PyMethod_GET_FUNCTION(func); +// Py_INCREF(func); +// Py_DECREF(*pfunc); +// *pfunc = self; +// na++; +// n++; +// } else +// Py_INCREF(func); +// sp = stack_pointer; +// READ_TIMESTAMP(intr0); +// x = ext_do_call(func, &sp, flags, na, nk); +// READ_TIMESTAMP(intr1); +// stack_pointer = sp; +// Py_DECREF(func); +// +// while (stack_pointer > pfunc) { +// w = POP(); +// Py_DECREF(w); +// } +// PUSH(x); +// if (x != NULL) +// continue; +// break; +// } +// + case Opcode.MAKE_FUNCTION: { + PyCode code = (PyCode) stack.pop(); + PyObject[] defaults = stack.popN(oparg); + PyFunction func = new PyFunction(f.f_globals, defaults, code); + stack.push(func); + break; + } + + case Opcode.MAKE_CLOSURE: { + PyCode code = (PyCode) stack.pop(); + PyObject[] closure_cells = new PyTuple(stack.pop()).getArray(); + PyObject[] defaults = stack.popN(oparg); + PyFunction func = new PyFunction(f.f_globals, defaults, code, closure_cells); + stack.push(func); + break; + } + +// case BUILD_SLICE: +// if (oparg == 3) +// w = POP(); +// else +// w = NULL; +// v = POP(); +// u = TOP(); +// x = PySlice_New(u, v, w); +// Py_DECREF(u); +// Py_DECREF(v); +// Py_XDECREF(w); +// SET_TOP(x); +// if (x != NULL) continue; +// break; +// + case Opcode.EXTENDED_ARG: + opcode = co_code[next_instr++]; + next_instr += 2; + oparg = oparg << 16 | ((co_code[next_instr - 1] << 8) + (co_code[next_instr - 2])); + break; + + default: + Py.print(Py.getSystemState().stderr, + Py.newString( + String.format("XXX lineno: %d, opcode: %d\n", + f.f_lasti, opcode))); + throw Py.SystemError("unknown opcode"); + + + } // end switch + } // end try + catch (Throwable t) { + // wrap so we can consume with our try block handling + PyException pye = Py.JavaError(t); + // XXX - but since that hasn't been written, for now just rethrow in wrapped form + throw pye; + } + + + // process why, blocks + switch (why) { + case RETURN: + return retval; + default: + break; + } + } // end while + return Py.None; // should never get here, just for debugging + } + + // XXX - perhaps add support for max stack size (presumably from co_stacksize) + // and capacity hints + class PyStack { + + final List<PyObject> stack; + + PyStack() { + stack = new ArrayList<PyObject>(); + } + + PyObject top() { + return stack.get(stack.size() - 1); + } + + PyObject pop() { + return stack.remove(stack.size() - 1); + } + + void push(PyObject v) { + stack.add(v); + } + + void set_top(PyObject v) { + stack.set(stack.size() - 1, v); + } + + void dup() { + stack.add(top()); + } + + void dupN(int n) { + PyObject v = top(); + for (int i = 0; i < n; i++) { + stack.add(v); + } + } + + PyObject[] popN(int n) { + int end = stack.size(); // exclusive + PyObject ret[] = new PyObject[n]; + List<PyObject> lastN = stack.subList(end - n, end); + lastN.toArray(ret); + lastN.clear(); + return ret; + } + + void rotN(int n) { + int end = stack.size(); + List<PyObject> lastN = stack.subList(end - n, end); + Collections.rotate(lastN, n); + } + + @Override + public String toString() { + return stack.toString(); + } + } +} + + Modified: branches/pbcvm/src/org/python/core/PyFrame.java =================================================================== --- branches/pbcvm/src/org/python/core/PyFrame.java 2009-01-20 13:47:20 UTC (rev 5948) +++ branches/pbcvm/src/org/python/core/PyFrame.java 2009-01-20 13:56:46 UTC (rev 5949) @@ -8,7 +8,7 @@ { public PyFrame f_... [truncated message content] |
From: <zy...@us...> - 2009-01-26 01:19:16
|
Revision: 5980 http://jython.svn.sourceforge.net/jython/?rev=5980&view=rev Author: zyasoft Date: 2009-01-26 01:19:12 +0000 (Mon, 26 Jan 2009) Log Message: ----------- Properly handles *args, **kwargs for the receiver function. func_code can now be set to a PyBytecode (or other extender of PyBaseCode). Turned off debugging by default for PyBytecode objects. Modified Paths: -------------- branches/pbcvm/src/org/python/core/PyBytecode.java branches/pbcvm/src/org/python/core/PyFunction.java Modified: branches/pbcvm/src/org/python/core/PyBytecode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyBytecode.java 2009-01-26 00:33:21 UTC (rev 5979) +++ branches/pbcvm/src/org/python/core/PyBytecode.java 2009-01-26 01:19:12 UTC (rev 5980) @@ -18,7 +18,9 @@ return opname; } + private boolean debug = false; public PyObject _debug(int maxCount) { + debug = maxCount > 0; this.maxCount = maxCount; return Py.None; } @@ -66,6 +68,8 @@ // co_argcount -= 1; // co_flags |= CO_VARKEYWORDS; // } + varargs = (flags & CO_VARARGS) != 0; + varkwargs = (flags & CO_VARKEYWORDS) != 0; co_flags |= flags; co_stacksize = stacksize; @@ -206,12 +210,14 @@ } private void print_debug(int count, int next_instr, int opcode, int oparg, PyStack stack, PyFrame f) { - System.err.println(co_name + ":" + - count + "," + f.f_lasti + "> opcode: " + - getOpname().__getitem__(Py.newInteger(opcode)) + - (opcode > Opcode.HAVE_ARGUMENT ? ", oparg: " + oparg : "") + - ", stack: " + stack.toString() + - ", blocks: " + stringify_blocks(f)); + if (debug) { + System.err.println(co_name + ":" + + count + "," + f.f_lasti + "> opcode: " + + getOpname().__getitem__(Py.newInteger(opcode)) + + (opcode > Opcode.HAVE_ARGUMENT ? ", oparg: " + oparg : "") + + ", stack: " + stack.toString() + + ", blocks: " + stringify_blocks(f)); + } } private static PyTryBlock popBlock(PyFrame f) { @@ -248,7 +254,9 @@ // 1. consider detaching the setting/getting of frame fields to improve performance, instead do this // in a shadow version of the frame that we copy back to on entry/exit and downcalls - System.err.println("Entry with " + f.f_lasti + " into " + co_code.length); + if (debug) { + System.err.println("Entry with " + f.f_lasti + " into " + co_code.length); + } if (f.f_lasti >= co_code.length) { throw Py.SystemError(""); } @@ -266,7 +274,7 @@ f.f_savedlocals = null; } - while (count < maxCount) { // XXX - replace with while(true) + while (!debug || (count < maxCount)) { // XXX - replace with while(true) try { @@ -290,7 +298,6 @@ next_instr += 1; f.f_lasti = next_instr; // should have no worries about needing co_lnotab, just keep this current - switch (opcode) { case Opcode.NOP: break; @@ -910,7 +917,7 @@ break; case Opcode.JUMP_ABSOLUTE: - next_instr = oparg; // XXX - continue to a label is probably much better + next_instr = oparg; break; case Opcode.GET_ITER: { @@ -1048,7 +1055,7 @@ case Opcode.EXTENDED_ARG: opcode = co_code[next_instr++]; next_instr += 2; - oparg = oparg << 16 | ((co_code[next_instr - 1] << 8) + (co_code[next_instr - 2])); + oparg = oparg << 16 | ((co_code[next_instr] << 8) + co_code[next_instr - 1]); break; default: @@ -1058,7 +1065,6 @@ f.f_lasti, opcode))); throw Py.SystemError("unknown opcode"); - } // end switch } // end try catch (Throwable t) { @@ -1133,9 +1139,11 @@ f.f_lasti = next_instr; // need to update on function entry, etc - System.err.println(count + "," + f.f_lasti + "> Returning from " + why + ": " + retval + - ", stack: " + stack.toString() + - ", blocks: " + stringify_blocks(f)); + if (debug) { + System.err.println(count + "," + f.f_lasti + "> Returning from " + why + ": " + retval + + ", stack: " + stack.toString() + + ", blocks: " + stringify_blocks(f)); + } if (why == why.EXCEPTION) { throw ts.exception; Modified: branches/pbcvm/src/org/python/core/PyFunction.java =================================================================== --- branches/pbcvm/src/org/python/core/PyFunction.java 2009-01-26 00:33:21 UTC (rev 5979) +++ branches/pbcvm/src/org/python/core/PyFunction.java 2009-01-26 01:19:12 UTC (rev 5980) @@ -195,10 +195,10 @@ @ExposedSet(name = "func_code") public void setFuncCode(PyCode code) { - if (func_code == null || !(code instanceof PyTableCode)) { + if (func_code == null || !(code instanceof PyBaseCode)) { throw Py.TypeError("func_code must be set to a code object"); } - PyTableCode tcode = (PyTableCode)code; + PyBaseCode tcode = (PyBaseCode)code; int nfree = tcode.co_freevars == null ? 0 : tcode.co_freevars.length; int nclosure = func_closure != null ? func_closure.__len__() : 0; if (nclosure != nfree) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2009-02-07 06:29:41
|
Revision: 6019 http://jython.svn.sourceforge.net/jython/?rev=6019&view=rev Author: zyasoft Date: 2009-02-07 06:29:37 +0000 (Sat, 07 Feb 2009) Log Message: ----------- Fixed IMPORT_STAR for nested modules. sys.exc_info now returns Py.None for the traceback (this fixes an issue in PBC where null is being used as both a sentinel value by __getitem__ AND an actual value for exception handling). Modified Paths: -------------- branches/pbcvm/src/org/python/core/PyBytecode.java branches/pbcvm/src/org/python/core/PySystemState.java branches/pbcvm/src/org/python/core/imp.java Modified: branches/pbcvm/src/org/python/core/PyBytecode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyBytecode.java 2009-02-07 04:04:54 UTC (rev 6018) +++ branches/pbcvm/src/org/python/core/PyBytecode.java 2009-02-07 06:29:37 UTC (rev 6019) @@ -9,7 +9,7 @@ // for debugging private int count = 0; // total number of opcodes run - private int maxCount = 10000; // less than my buffer on iterm + private int maxCount = -1; // less than my buffer on iterm private static PyObject opname; public static boolean defaultDebug = false; @@ -263,7 +263,7 @@ f.f_savedlocals = null; } - while (!debug || (count < maxCount)) { // XXX - replace with while(true) + while (!debug || (maxCount == -1 || count < maxCount)) { // XXX - replace with while(true) try { @@ -870,7 +870,7 @@ } case Opcode.IMPORT_STAR: { - String module = stack.pop().toString(); + PyObject module = stack.pop(); imp.importAll(module, f); break; } @@ -1109,9 +1109,11 @@ if (b.b_type == Opcode.SETUP_EXCEPT) { exc.normalize(); } - stack.push(new PyStackException(exc)); - stack.dup(); // x3 to conform with CPython's calling convention, which - stack.dup(); // stores the type, val, tb separately on the stack + stack.push(exc.traceback); + stack.push(exc.value); + stack.push(new PyStackException(exc)); // instead of stack.push(exc.type);, like CPython +// stack.dup(); // x3 to conform with CPython's calling convention, which +// stack.dup(); // stores the type, val, tb separately on the stack } else { if (why == Why.RETURN || why == Why.CONTINUE) { stack.push(retval); Modified: branches/pbcvm/src/org/python/core/PySystemState.java =================================================================== --- branches/pbcvm/src/org/python/core/PySystemState.java 2009-02-07 04:04:54 UTC (rev 6018) +++ branches/pbcvm/src/org/python/core/PySystemState.java 2009-02-07 06:29:37 UTC (rev 6019) @@ -1027,7 +1027,8 @@ PyException exc = Py.getThreadState().exception; if(exc == null) return new PyTuple(Py.None, Py.None, Py.None); - return new PyTuple(exc.type, exc.value, exc.traceback); + PyObject tb = exc.traceback; + return new PyTuple(exc.type, exc.value, tb == null ? Py.None : tb); } public static void exc_clear() { Modified: branches/pbcvm/src/org/python/core/imp.java =================================================================== --- branches/pbcvm/src/org/python/core/imp.java 2009-02-07 04:04:54 UTC (rev 6018) +++ branches/pbcvm/src/org/python/core/imp.java 2009-02-07 06:29:37 UTC (rev 6019) @@ -827,22 +827,15 @@ return submods; } - private static PyTuple all = null; + private final static PyTuple all = new PyTuple(Py.newString('*')); - private synchronized static PyTuple getStarArg() { - if (all == null) { - all = new PyTuple(Py.newString('*')); - } - return all; - } - /** * Called from jython generated code when a statement like "from spam.eggs * import *" is executed. */ public static void importAll(String mod, PyFrame frame) { PyObject module = __builtin__.__import__(mod, frame.f_globals, frame - .getLocals(), getStarArg()); + .getLocals(), all); PyObject names; boolean filter = true; if (module instanceof PyJavaPackage) { @@ -860,6 +853,27 @@ loadNames(names, module, frame.getLocals(), filter); } + public static void importAll(PyObject module, PyFrame frame) { + PyObject names; + boolean filter = true; + if (module instanceof PyJavaPackage) { + names = ((PyJavaPackage) module).fillDir(); + } else { + PyObject __all__ = module.__findattr__("__all__"); + if (__all__ != null) { + names = __all__; + filter = false; + } else { + names = module.__dir__(); + } + } + + loadNames(names, module, frame.getLocals(), filter); + } + + + + /** * From a module, load the attributes found in <code>names</code> into * locals. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2009-02-07 17:47:22
|
Revision: 6020 http://jython.svn.sourceforge.net/jython/?rev=6020&view=rev Author: zyasoft Date: 2009-02-07 17:47:19 +0000 (Sat, 07 Feb 2009) Log Message: ----------- Fixes nested scope treatment of free variables. Modified Paths: -------------- branches/pbcvm/src/org/python/core/PyBytecode.java branches/pbcvm/src/org/python/core/PySystemState.java Modified: branches/pbcvm/src/org/python/core/PyBytecode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyBytecode.java 2009-02-07 06:29:37 UTC (rev 6019) +++ branches/pbcvm/src/org/python/core/PyBytecode.java 2009-02-07 17:47:19 UTC (rev 6020) @@ -2,20 +2,27 @@ import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.List; public class PyBytecode extends PyBaseCode { // for debugging - private int count = 0; // total number of opcodes run - private int maxCount = -1; // less than my buffer on iterm - private static PyObject opname; + private int count = 0; // total number of opcodes run so far in this code obj + private int maxCount = -1; // if -1, no cap on number of opcodes than can be run public static boolean defaultDebug = false; + private static PyObject dis; - private static synchronized PyObject getOpname() { + private static synchronized PyObject get_dis() { + if (dis == null) { + dis = __builtin__.__import__("dis"); + } + return dis; + } + private static PyObject opname; + + private static synchronized PyObject get_opname() { if (opname == null) { - opname = __builtin__.__import__("dis").__getattr__("opname"); + opname = get_dis().__getattr__("opname"); } return opname; } @@ -37,7 +44,7 @@ public final PyObject[] co_consts; public final String[] co_names; public final int co_stacksize; // XXX - use to convert PyStack to use PyObject[] instead of ArrayList<PyObject> - public final PyObject[] co_lnotab; // ignored + public final String co_lnotab; // ignored for now private final static int CALL_FLAG_VAR = 1; private final static int CALL_FLAG_KW = 2; @@ -73,7 +80,7 @@ co_consts = constants; co_names = names; co_code = codestring.toCharArray(); - co_lnotab = null; // ignore + co_lnotab = lnotab; // ignore } private static final String[] __members__ = { "co_name", "co_argcount", @@ -201,7 +208,7 @@ if (debug) { System.err.println(co_name + ":" + count + "," + f.f_lasti + "> opcode: " + - getOpname().__getitem__(Py.newInteger(opcode)) + + get_opname().__getitem__(Py.newInteger(opcode)) + (opcode >= Opcode.HAVE_ARGUMENT ? ", oparg: " + oparg : "") + ", stack: " + stack.toString() + ", blocks: " + stringify_blocks(f)); @@ -245,9 +252,18 @@ if (debug) { System.err.println(co_name + ":" + f.f_lasti + "/" + co_code.length + ", cells:" + Arrays.toString(co_cellvars) + ", free:" + Arrays.toString(co_freevars)); + int i = 0; + for (String cellvar : co_cellvars) { + System.err.println(cellvar + " = " + f.f_env[i++]); + } + for (String freevar : co_freevars) { + System.err.println(freevar + " = " + f.f_env[i++]); + } + get_dis().invoke("disassemble", this); + } if (f.f_lasti >= co_code.length) { - throw Py.SystemError(""); + throw Py.SystemError(""); // XXX - chose an appropriate error!!! } next_instr = f.f_lasti; @@ -763,22 +779,53 @@ break; case Opcode.LOAD_CLOSURE: { - if (debug) { - System.err.println("LOAD_CLOSURE: " + Arrays.toString(f.f_env)); - } +//// if (debug) { +//// System.err.println("LOAD_CLOSURE: " + Arrays.toString(f.f_env)); +//// } +// PyCell cell = (PyCell) (f.getclosure(oparg)); +// if (cell.ob_ref == null) { +// cell.ob_ref = f.getlocal(oparg); +// } +////// cell.ob_ref = f.getname(co_freevars[oparg]); +// stack.push(cell); +// stack.push(f.getclosure(oparg)); + + PyCell cell = (PyCell) (f.getclosure(oparg)); if (cell.ob_ref == null) { - cell.ob_ref = f.getlocal(oparg); +// if (oparg < co_nlocals) { +// cell.ob_ref = f.getlocal(oparg); +// } else { +// String name = co_cellvars[oparg]; + +// cell.ob_ref = f.getname(name); +// } + + String name = co_cellvars[oparg]; +// System.err.println("Loading closure: " + name); + // XXX - consider some efficient lookup mechanism, like a hash + if (f.f_fastlocals != null) { + int i = 0; + boolean matched = false; + for (String match : co_varnames) { + if (match.equals(name)) { + matched = true; + break; + } + i++; + } + if (matched) { + cell.ob_ref = f.f_fastlocals[i]; + } + } else { + cell.ob_ref = f.f_locals.__finditem__(name); + } } -// cell.ob_ref = f.getname(co_freevars[oparg]); stack.push(cell); break; } case Opcode.LOAD_DEREF: { - if (debug) { - System.err.println("LOAD_DEREF: " + Arrays.toString(f.f_env)); - } stack.push(f.getderef(oparg)); break; } @@ -1354,7 +1401,7 @@ @Override public String toString() { - return "<" + getOpname().__getitem__(Py.newInteger(b_type)) + "," + + return "<" + get_opname().__getitem__(Py.newInteger(b_type)) + "," + b_handler + "," + b_level + ">"; } } Modified: branches/pbcvm/src/org/python/core/PySystemState.java =================================================================== --- branches/pbcvm/src/org/python/core/PySystemState.java 2009-02-07 06:29:37 UTC (rev 6019) +++ branches/pbcvm/src/org/python/core/PySystemState.java 2009-02-07 17:47:19 UTC (rev 6020) @@ -1028,7 +1028,10 @@ if(exc == null) return new PyTuple(Py.None, Py.None, Py.None); PyObject tb = exc.traceback; - return new PyTuple(exc.type, exc.value, tb == null ? Py.None : tb); + PyObject value = exc.value; + return new PyTuple(exc.type, + value == null ? Py.None : value, + tb == null ? Py.None : tb); } public static void exc_clear() { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2009-02-18 00:06:59
|
Revision: 6038 http://jython.svn.sourceforge.net/jython/?rev=6038&view=rev Author: zyasoft Date: 2009-02-18 00:06:55 +0000 (Wed, 18 Feb 2009) Log Message: ----------- Added support for code.getlineno (using co_lnotab), co_code, co_consts, co_lnotab. co_code and co_lnotab now use byte[] for a more compact representation and then manage accessing as if it were an unsigned representation. This enables a good chunk of the peak.util.assembler unit tests to pass; the remainder seem to have a dictionary traversal dependency. Modified Paths: -------------- branches/pbcvm/src/org/python/core/PyBaseCode.java branches/pbcvm/src/org/python/core/PyBytecode.java branches/pbcvm/src/org/python/core/PyFrame.java Modified: branches/pbcvm/src/org/python/core/PyBaseCode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyBaseCode.java 2009-02-17 02:38:09 UTC (rev 6037) +++ branches/pbcvm/src/org/python/core/PyBaseCode.java 2009-02-18 00:06:55 UTC (rev 6038) @@ -311,4 +311,8 @@ protected PyObject interpret(PyFrame f) { throw new UnsupportedOperationException("interpret not supported"); } + + protected int getline(PyFrame f) { + return f.f_lineno; + } } Modified: branches/pbcvm/src/org/python/core/PyBytecode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyBytecode.java 2009-02-17 02:38:09 UTC (rev 6037) +++ branches/pbcvm/src/org/python/core/PyBytecode.java 2009-02-18 00:06:55 UTC (rev 6038) @@ -40,11 +40,11 @@ // end debugging public final static int CO_MAXBLOCKS = 20; // same as in CPython - public final char[] co_code; // widened to char to avoid signed byte issues + public final byte[] co_code; // widened to char to avoid signed byte issues public final PyObject[] co_consts; public final String[] co_names; public final int co_stacksize; // XXX - use to convert PyStack to use PyObject[] instead of ArrayList<PyObject> - public final String co_lnotab; + public final byte[] co_lnotab; private final static int CALL_FLAG_VAR = 1; private final static int CALL_FLAG_KW = 2; @@ -57,6 +57,8 @@ null, null); } + + // XXX - intern names HERE instead of in marshal public PyBytecode(int argcount, int nlocals, int stacksize, int flags, String codestring, PyObject[] constants, String[] names, String varnames[], String filename, String name, int firstlineno, String lnotab, @@ -79,9 +81,10 @@ co_stacksize = stacksize; co_consts = constants; co_names = names; - co_code = codestring.toCharArray(); - co_lnotab = lnotab; // ignore + co_code = getBytes(codestring); + co_lnotab = getBytes(lnotab); } + private static final String[] __members__ = { "co_name", "co_argcount", "co_varnames", "co_filename", "co_firstlineno", @@ -89,6 +92,7 @@ "co_code", "co_consts", "co_names", "co_lnotab", "co_stacksize" }; + @Override public PyObject __dir__() { PyString members[] = new PyString[__members__.length]; for (int i = 0; i < __members__.length; i++) { @@ -144,6 +148,15 @@ if (name == "co_name") { return new PyString(co_name); } + if (name == "co_code") { + return new PyString(getString(co_code)); + } + if (name == "co_lnotab") { + return new PyString(getString(co_lnotab)); + } + if (name == "co_consts") { + return new PyTuple(co_consts); + } return super.__findattr_ex__(name); } @@ -184,7 +197,7 @@ @Override public String toString() { - return exception.toString(); + return String.format("PyStackException<%s,%s,%.100s>", exception.type, exception.value, exception.traceback); } } @@ -207,9 +220,9 @@ private void print_debug(int count, int next_instr, int opcode, int oparg, PyStack stack, PyFrame f) { if (debug) { System.err.println(co_name + ":" + - count + "," + f.f_lasti + "> opcode: " + + count + "," + f.f_lasti + "> " + get_opname().__getitem__(Py.newInteger(opcode)) + - (opcode >= Opcode.HAVE_ARGUMENT ? ", oparg: " + oparg : "") + + (opcode >= Opcode.HAVE_ARGUMENT ? " " + oparg : "") + ", stack: " + stack.toString() + ", blocks: " + stringify_blocks(f)); } @@ -292,10 +305,10 @@ stack.push((PyObject) generatorInput); } - opcode = co_code[next_instr]; + opcode = getUnsigned(co_code, next_instr); if (opcode >= Opcode.HAVE_ARGUMENT) { next_instr += 2; - oparg = (co_code[next_instr] << 8) + co_code[next_instr - 1]; + oparg = (getUnsigned(co_code, next_instr) << 8) + getUnsigned(co_code, next_instr - 1); } print_debug(count, next_instr, opcode, oparg, stack, f); @@ -734,10 +747,10 @@ f.dellocal(co_names[oparg]); break; - case Opcode.UNPACK_SEQUENCE: + case Opcode.UNPACK_SEQUENCE: unpack_iterable(oparg, stack); break; - + case Opcode.STORE_ATTR: { PyObject obj = stack.pop(); PyObject v = stack.pop(); @@ -1112,9 +1125,9 @@ } case Opcode.EXTENDED_ARG: - opcode = co_code[next_instr++]; + opcode = getUnsigned(co_code, next_instr++); next_instr += 2; - oparg = oparg << 16 | ((co_code[next_instr] << 8) + co_code[next_instr - 1]); + oparg = oparg << 16 | ((getUnsigned(co_code, next_instr) << 8) + getUnsigned(co_code, next_instr - 1)); break; default: @@ -1172,19 +1185,18 @@ } stack.push(exc.traceback); stack.push(exc.value); - stack.push(new PyStackException(exc)); // instead of stack.push(exc.type);, like CPython + stack.push(new PyStackException(exc)); // instead of stack.push(exc.type), like CPython } else { if (why == Why.RETURN || why == Why.CONTINUE) { stack.push(retval); } - // FIGURE OUT THE FLOW HERE, in test_optparse2 stack.push(new PyStackWhy(why)); } why = Why.NOT; next_instr = b.b_handler; break; } - } // unwindstack + } // unwind block stack if (why != Why.NOT) { break; @@ -1413,8 +1425,38 @@ @Override public String toString() { - return stack.toString(); + StringBuilder buffer = new StringBuilder(); + int size = stack.size(); + int N = size > 4 ? 4 : size; + buffer.append("["); + for (int i = 0; i < N; i++) { + if (i > 0) { + buffer.append(", "); + } + PyObject item = stack.get(size - (i + 1)); + buffer.append(upto(item.__repr__().toString())); + } + if (N < size) { + buffer.append(String.format(", %d more...", size - N)); + } + buffer.append("]"); + return buffer.toString(); } + + private String upto(String x) { + return upto(x, 100); + } + + private String upto(String x, int n) { + x = x.replace('\n', '|'); + if (x.length() > n) { + StringBuilder item = new StringBuilder(x.substring(0, n)); + item.append("..."); + return item.toString(); + } else { + return x; + } + } } private class PyTryBlock extends PyObject { // purely to sit on top of the existing PyFrame in f_exits!!! @@ -1438,6 +1480,52 @@ b_handler + "," + b_level + ">"; } } + + @Override + protected int getline(PyFrame f) { + int addrq = f.f_lasti; + int size = co_lnotab.length / 2; + int p = 0; + int line = co_firstlineno; + int addr = 0; + while (--size >= 0) { + addr += getUnsigned(co_lnotab, p++); + if (addr > addrq) { + break; + } + line += getUnsigned(co_lnotab, p++); + } + return line; + } + + // Utility functions to enable storage of unsigned bytes in co_code, co_lnotab byte[] arrays + private static char getUnsigned(byte[] x, int i) { + byte b = x[i]; + if (b < 0) { + return (char)(b + 256); + } + else { + return (char)b; + } + } + + private static String getString(byte[] x) { + StringBuilder buffer = new StringBuilder(x.length); + for (int i = 0; i < x.length; i++) { + buffer.append(getUnsigned(x, i)); + } + return buffer.toString(); + } + + private static byte[] getBytes(String s) { + int len = s.length(); + byte[] x = new byte[len]; + for (int i = 0; i < len; i++) { + x[i] = (byte)(s.charAt(i) & 0xFF); + } + return x; + } + } Modified: branches/pbcvm/src/org/python/core/PyFrame.java =================================================================== --- branches/pbcvm/src/org/python/core/PyFrame.java 2009-02-17 02:38:09 UTC (rev 6037) +++ branches/pbcvm/src/org/python/core/PyFrame.java 2009-02-18 00:06:55 UTC (rev 6038) @@ -244,7 +244,7 @@ } public int getline() { - return f_lineno; + return f_code.getline(this); } public PyObject getlocal(int index) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2009-02-22 14:40:53
|
Revision: 6041 http://jython.svn.sourceforge.net/jython/?rev=6041&view=rev Author: zyasoft Date: 2009-02-22 14:40:49 +0000 (Sun, 22 Feb 2009) Log Message: ----------- Inlined PyTableCode#interpret into #call(PyFrame,PyClosure) (which restores this method to what it was before the PBC-VM work). This change restores the performance as tested by test/pystone.py. Modified Paths: -------------- branches/pbcvm/src/org/python/core/PyBaseCode.java branches/pbcvm/src/org/python/core/PyTableCode.java Modified: branches/pbcvm/src/org/python/core/PyBaseCode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyBaseCode.java 2009-02-19 20:16:18 UTC (rev 6040) +++ branches/pbcvm/src/org/python/core/PyBaseCode.java 2009-02-22 14:40:49 UTC (rev 6041) @@ -308,9 +308,7 @@ co_name, Py.idstr(this), co_filename, co_firstlineno); } - protected PyObject interpret(PyFrame f) { - throw new UnsupportedOperationException("interpret not supported"); - } + protected abstract PyObject interpret(PyFrame f); protected int getline(PyFrame f) { return f.f_lineno; Modified: branches/pbcvm/src/org/python/core/PyTableCode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyTableCode.java 2009-02-19 20:16:18 UTC (rev 6040) +++ branches/pbcvm/src/org/python/core/PyTableCode.java 2009-02-22 14:40:49 UTC (rev 6041) @@ -6,6 +6,8 @@ * is stored as a PyFunctionTable instance and an integer index. */ +import org.python.modules._systemrestart; + public class PyTableCode extends PyBaseCode { @@ -116,7 +118,92 @@ return super.__findattr_ex__(name); } - protected PyObject interpret(PyFrame frame) { - return funcs.call_function(func_id, frame); + @Override + public PyObject call(PyFrame frame, PyObject closure) { +// System.err.println("tablecode call: "+co_name); + ThreadState ts = Py.getThreadState(); + 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); + } 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) { + throw new UnsupportedOperationException("Inlined interpret to improve call performance (may want to reconsider in the future)."); + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2009-02-24 04:25:17
|
Revision: 6042 http://jython.svn.sourceforge.net/jython/?rev=6042&view=rev Author: zyasoft Date: 2009-02-24 04:25:13 +0000 (Tue, 24 Feb 2009) Log Message: ----------- LineCache implementation to support efficient setline edge detection, as necessary for tracing. No longer looks up the ThreadState twice, in the caller of PyBytecode#interpret and interpret itself, so this should provide for some optimization. Modified Paths: -------------- branches/pbcvm/src/org/python/core/PyBaseCode.java branches/pbcvm/src/org/python/core/PyBytecode.java branches/pbcvm/src/org/python/core/PyTableCode.java Modified: branches/pbcvm/src/org/python/core/PyBaseCode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyBaseCode.java 2009-02-22 14:40:49 UTC (rev 6041) +++ branches/pbcvm/src/org/python/core/PyBaseCode.java 2009-02-24 04:25:13 UTC (rev 6042) @@ -86,7 +86,7 @@ PyObject ret; try { - ret = interpret(frame); + ret = interpret(frame, ts); } catch (Throwable t) { // Convert exceptions that occured in Java code to PyExceptions PyException pye = Py.JavaError(t); @@ -308,7 +308,7 @@ co_name, Py.idstr(this), co_filename, co_firstlineno); } - protected abstract PyObject interpret(PyFrame f); + protected abstract PyObject interpret(PyFrame f, ThreadState ts); protected int getline(PyFrame f) { return f.f_lineno; Modified: branches/pbcvm/src/org/python/core/PyBytecode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyBytecode.java 2009-02-22 14:40:49 UTC (rev 6041) +++ branches/pbcvm/src/org/python/core/PyBytecode.java 2009-02-24 04:25:13 UTC (rev 6042) @@ -84,7 +84,6 @@ co_code = getBytes(codestring); co_lnotab = getBytes(lnotab); } - private static final String[] __members__ = { "co_name", "co_argcount", "co_varnames", "co_filename", "co_firstlineno", @@ -217,9 +216,9 @@ return buf.toString(); } - private void print_debug(int count, int next_instr, int opcode, int oparg, PyStack stack, PyFrame f) { + private void print_debug(int count, int next_instr, int line, int opcode, int oparg, PyStack stack, PyFrame f) { if (debug) { - System.err.println(co_name + ":" + + System.err.println(co_name + " " + line + ":" + count + "," + f.f_lasti + "> " + get_opname().__getitem__(Py.newInteger(opcode)) + (opcode >= Opcode.HAVE_ARGUMENT ? " " + oparg : "") + @@ -249,14 +248,16 @@ } @Override - protected PyObject interpret(PyFrame f) { + protected PyObject interpret(PyFrame f, ThreadState ts) { final PyStack stack = new PyStack(); int next_instr = -1; int opcode; /* Current opcode */ int oparg = 0; /* Current opcode argument, if any */ Why why = Why.NOT; PyObject retval = null; - ThreadState ts = Py.getThreadState(); // XXX - change interpret to pass through from PyFrame since our ts will never change + LineCache lineCache = null; + int last_line = -1; + int line = 0; // XXX - optimization opportunities // 1. consider detaching the setting/getting of frame fields to improve performance, instead do this @@ -294,6 +295,19 @@ while (!debug || (maxCount == -1 || count < maxCount)) { // XXX - replace with while(true) + if (f.tracefunc != null || debug) { + if (lineCache == null) { + lineCache = new LineCache(); + if (debug) { + System.err.println("LineCache: " + lineCache.toString()); + } + } + line = lineCache.getline(next_instr); // XXX - should also return the range this is valid to avoid an unnecessary bisect + if (line != last_line) { + f.setline(line); + } + } + try { if (checkGeneratorInput) { @@ -310,11 +324,11 @@ next_instr += 2; oparg = (getUnsigned(co_code, next_instr) << 8) + getUnsigned(co_code, next_instr - 1); } - print_debug(count, next_instr, opcode, oparg, stack, f); + print_debug(count, next_instr, line, opcode, oparg, stack, f); count += 1; next_instr += 1; - f.f_lasti = next_instr; // should have no worries about needing co_lnotab, just keep this current + f.f_lasti = next_instr; switch (opcode) { case Opcode.NOP: @@ -1498,15 +1512,78 @@ return line; } + private class LineCache { + + private class Pair { + + private final int addr; + private final int line; + + private Pair(int a, int b) { + this.addr = a; + this.line = b; + } + + public String toString() { + return "(" + addr + "," + line + ")"; + } + } + List<Integer> addr_breakpoints = new ArrayList<Integer>(); + List<Integer> lines = new ArrayList<Integer>(); // length should be one more than addr_breakpoints + + private LineCache() { // based on dis.findlinestarts + + int size = co_lnotab.length / 2; + int p = 0; + int lastline = -1; + int line = co_firstlineno; + int addr = 0; + while (--size >= 0) { + int byte_incr = getUnsigned(co_lnotab, p++); + int line_incr = getUnsigned(co_lnotab, p++); + if (byte_incr > 0) { + if (line != lastline) { + addr_breakpoints.add(addr); + lines.add(line); + lastline = line; + } + addr += byte_incr; + } + line += line_incr; + } + if (line != lastline) { + lines.add(line); + } + } + + private int getline(int addrq) { // bisect_right to the lineno + + int lo = 0; + int hi = addr_breakpoints.size(); + while (lo < hi) { + int mid = (lo + hi) / 2; + if (addrq < addr_breakpoints.get(mid)) { + hi = mid; + } else { + lo = mid + 1; + } + } + return lines.get(lo); + } + + public String toString() { + return addr_breakpoints.toString() + ";" + lines.toString(); + } + } + // Utility functions to enable storage of unsigned bytes in co_code, co_lnotab byte[] arrays private static char getUnsigned(byte[] x, int i) { byte b = x[i]; if (b < 0) { - return (char)(b + 256); + return (char) (b + 256); + } else { + return (char) b; } - else { - return (char)b; - } } private static String getString(byte[] x) { @@ -1521,11 +1598,10 @@ int len = s.length(); byte[] x = new byte[len]; for (int i = 0; i < len; i++) { - x[i] = (byte)(s.charAt(i) & 0xFF); + x[i] = (byte) (s.charAt(i) & 0xFF); } return x; } - } Modified: branches/pbcvm/src/org/python/core/PyTableCode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyTableCode.java 2009-02-22 14:40:49 UTC (rev 6041) +++ branches/pbcvm/src/org/python/core/PyTableCode.java 2009-02-24 04:25:13 UTC (rev 6042) @@ -203,7 +203,7 @@ } @Override - protected PyObject interpret(PyFrame f) { + protected PyObject interpret(PyFrame f, ThreadState ts) { throw new UnsupportedOperationException("Inlined interpret to improve call performance (may want to reconsider in the future)."); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |