]> granicus.if.org Git - python/commitdiff
Instead of emitting SET_LINENO instructions, generate a line number
authorGuido van Rossum <guido@python.org>
Fri, 24 Jan 1997 03:43:35 +0000 (03:43 +0000)
committerGuido van Rossum <guido@python.org>
Fri, 24 Jan 1997 03:43:35 +0000 (03:43 +0000)
table which is incorporated in the code object.  This way, the runtime
overhead to keep track of line numbers is only incurred when an
exception has to be reported.

Python/compile.c

index 6d3a479f49c84f0cbda5a74ee55f1a6fb9bf2a22..e06f345358ea6c681fab71f8b0a2d5f526019bba 100644 (file)
@@ -76,6 +76,8 @@ static struct memberlist code_memberlist[] = {
        {"co_varnames", T_OBJECT,       OFF(co_varnames),       READONLY},
        {"co_filename", T_OBJECT,       OFF(co_filename),       READONLY},
        {"co_name",     T_OBJECT,       OFF(co_name),           READONLY},
+       {"co_firstlineno", T_INT,       OFF(co_firstlineno),    READONLY},
+       {"co_lnotab",   T_OBJECT,       OFF(co_lnotab),         READONLY},
        {NULL}  /* Sentinel */
 };
 
@@ -180,7 +182,8 @@ typeobject Codetype = {
 
 codeobject *
 newcodeobject(argcount, nlocals, stacksize, flags,
-             code, consts, names, varnames, filename, name)
+             code, consts, names, varnames, filename, name,
+             firstlineno, lnotab)
        int argcount;
        int nlocals;
        int stacksize;
@@ -191,6 +194,8 @@ newcodeobject(argcount, nlocals, stacksize, flags,
        object *varnames;
        object *filename;
        object *name;
+       int firstlineno;
+       object *lnotab;
 {
        codeobject *co;
        int i;
@@ -201,7 +206,8 @@ newcodeobject(argcount, nlocals, stacksize, flags,
            names == NULL || !is_tupleobject(names) ||
            varnames == NULL || !is_tupleobject(varnames) ||
            name == NULL || !is_stringobject(name) ||
-           filename == NULL || !is_stringobject(filename)) {
+           filename == NULL || !is_stringobject(filename) ||
+               lnotab == NULL || !is_stringobject(lnotab)) {
                err_badcall();
                return NULL;
        }
@@ -252,6 +258,9 @@ newcodeobject(argcount, nlocals, stacksize, flags,
                co->co_filename = filename;
                INCREF(name);
                co->co_name = name;
+               co->co_firstlineno = firstlineno;
+               INCREF(lnotab);
+               co->co_lnotab = lnotab;
        }
        return co;
 }
@@ -282,6 +291,9 @@ struct compiling {
        int c_lineno;           /* Current line number */
        int c_stacklevel;       /* Current stack level */
        int c_maxstacklevel;    /* Maximum stack level */
+       int c_firstlineno;
+       object *c_lnotab;       /* Table mapping address to line number */
+       int c_last_addr, c_last_line, c_lnotab_next;
 #ifdef PRIVATE_NAME_MANGLING
        char *c_private;        /* for private name mangling */
 #endif
@@ -387,6 +399,8 @@ com_init(c, filename)
                goto fail_00;
        if ((c->c_varnames = newlistobject(0)) == NULL)
                goto fail_000;
+       if ((c->c_lnotab = newsizedstringobject((char *)NULL, 1000)) == NULL)
+               goto fail_0000;
        c->c_nlocals = 0;
        c->c_argcount = 0;
        c->c_flags = 0;
@@ -402,8 +416,14 @@ com_init(c, filename)
        c->c_lineno = 0;
        c->c_stacklevel = 0;
        c->c_maxstacklevel = 0;
+       c->c_firstlineno = 0;
+       c->c_last_addr = 0;
+       c->c_last_line = 0;
+       c-> c_lnotab_next = 0;
        return 1;
        
+  fail_0000:
+       DECREF(c->c_lnotab);
   fail_000:
        DECREF(c->c_locals);
   fail_00:
@@ -428,6 +448,7 @@ com_free(c)
        XDECREF(c->c_globals);
        XDECREF(c->c_locals);
        XDECREF(c->c_varnames);
+       XDECREF(c->c_lnotab);
 }
 
 static void
@@ -462,6 +483,8 @@ com_done(c)
 {
        if (c->c_code != NULL)
                resizestring(&c->c_code, c->c_nexti);
+       if (c->c_lnotab != NULL)
+               resizestring(&c->c_lnotab, c->c_lnotab_next);
 }
 
 static void
@@ -499,6 +522,57 @@ com_addint(c, x)
        com_addbyte(c, x >> 8); /* XXX x should be positive */
 }
 
+static void
+com_add_lnotab(c, addr, line)
+       struct compiling *c;
+       int addr;
+       int line;
+{
+       int size;
+       char *p;
+       if (c->c_lnotab == NULL)
+               return;
+       size = getstringsize(c->c_lnotab);
+       if (c->c_lnotab_next+2 > size) {
+               if (resizestring(&c->c_lnotab, size + 1000) < 0) {
+                       c->c_errors++;
+                       return;
+               }
+       }
+       p = getstringvalue(c->c_lnotab) + c->c_lnotab_next;
+       *p++ = addr;
+       *p++ = line;
+       c->c_lnotab_next += 2;
+}
+
+static void
+com_set_lineno(c, lineno)
+       struct compiling *c;
+       int lineno;
+{
+       c->c_lineno = lineno;
+       if (c->c_firstlineno == 0) {
+               c->c_firstlineno = c->c_last_line = lineno;
+       }
+       else {
+               int incr_addr = c->c_nexti - c->c_last_addr;
+               int incr_line = lineno - c->c_last_line;
+               while (incr_addr > 0 || incr_line > 0) {
+                       int trunc_addr = incr_addr;
+                       int trunc_line = incr_line;
+                       if (trunc_addr > 255)
+                               trunc_addr = 255;
+                       if (trunc_line > 255)
+                               trunc_line = 255;
+                       com_add_lnotab(c, trunc_addr, trunc_line);
+                       incr_addr -= trunc_addr;
+                       incr_line -= trunc_line;
+               }
+               c->c_last_addr = c->c_nexti;
+               c->c_last_line = lineno;
+       }
+}
+
 static void
 com_addoparg(c, op, arg)
        struct compiling *c;
@@ -506,9 +580,11 @@ com_addoparg(c, op, arg)
        int arg;
 {
        if (op == SET_LINENO)
-               c->c_lineno = arg;
-       com_addbyte(c, op);
-       com_addint(c, arg);
+               com_set_lineno(c, arg);
+       else {
+               com_addbyte(c, op);
+               com_addint(c, arg);
+       }
 }
 
 static void
@@ -3212,7 +3288,9 @@ jcompile(n, filename, base)
                                           names,
                                           varnames,
                                           filename,
-                                          name);
+                                          name,
+                                          sc.c_firstlineno,
+                                          sc.c_lnotab);
                XDECREF(consts);
                XDECREF(names);
                XDECREF(varnames);
@@ -3222,3 +3300,21 @@ jcompile(n, filename, base)
        com_free(&sc);
        return co;
 }
+
+int
+PyCode_Addr2Line(co, addrq)
+       PyCodeObject *co;
+       int addrq;
+{
+       int size = PyString_Size(co->co_lnotab) / 2;
+       char *p = PyString_AsString(co->co_lnotab);
+       int line = co->co_firstlineno;
+       int addr = 0;
+       while (--size >= 0) {
+               addr += *p++;
+               if (addr > addrq)
+                       break;
+               line += *p++;
+       }
+       return line;
+}