Instead of emitting SET_LINENO instructions, generate a line number

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.
This commit is contained in:
Guido van Rossum 1997-01-24 03:43:35 +00:00
parent 767579854c
commit da4eb5c3b5
1 changed files with 102 additions and 6 deletions

View File

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