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. |