comparison Python/compile.c @ 18065:889db6d55506 legacy-trunk

SF bug 430991: wrong co_lnotab Armin Rigo pointed out that the way the line-# table got built didn't work for lines generating more than 255 bytes of bytecode. Fixed as he suggested, plus corresponding changes to pyassem.py, plus added some long overdue docs about this subtle table to compile.c. Bugfix candidate (line numbers may be off in tracebacks under -O).
author Tim Peters <tim.peters@gmail.com>
date Sat, 09 Jun 2001 09:26:21 +0000
parents 437482fe55e6
children 7bc473b2c654
comparison
equal deleted inserted replaced
18064:ac5489a2548d 18065:889db6d55506
332 332
333 The two passes communicate via symtable_load_symbols() and via 333 The two passes communicate via symtable_load_symbols() and via
334 is_local() and is_global(). The former initializes several slots 334 is_local() and is_global(). The former initializes several slots
335 in the compiling struct: c_varnames, c_locals, c_nlocals, 335 in the compiling struct: c_varnames, c_locals, c_nlocals,
336 c_argcount, c_globals, and c_flags. 336 c_argcount, c_globals, and c_flags.
337 */
338
339 /* All about c_lnotab.
340
341 c_lnotab is an array of unsigned bytes disguised as a Python string. In -O
342 mode, SET_LINENO opcodes aren't generated, and bytecode offsets are mapped
343 to source code line #s (when needed for tracebacks) via c_lnotab instead.
344 The array is conceptually a list of
345 (bytecode offset increment, line number increment)
346 pairs. The details are important and delicate, best illustrated by example:
347
348 byte code offset source code line number
349 0 1
350 6 2
351 50 7
352 350 307
353 361 308
354
355 The first trick is that these numbers aren't stored, only the increments
356 from one row to the next (this doesn't really work, but it's a start):
357
358 0, 1, 6, 1, 44, 5, 300, 300, 11, 1
359
360 The second trick is that an unsigned byte can't hold negative values, or
361 values larger than 255, so (a) there's a deep assumption that byte code
362 offsets and their corresponding line #s both increase monotonically, and (b)
363 if at least one column jumps by more than 255 from one row to the next, more
364 than one pair is written to the table. In case #b, there's no way to know
365 from looking at the table later how many were written. That's the delicate
366 part. A user of c_lnotab desiring to find the source line number
367 corresponding to a bytecode address A should do something like this
368
369 lineno = addr = 0
370 for addr_incr, line_incr in c_lnotab:
371 addr += addr_incr
372 if addr > A:
373 return lineno
374 lineno += line_incr
375
376 In order for this to work, when the addr field increments by more than 255,
377 the line # increment in each pair generated must be 0 until the remaining addr
378 increment is < 256. So, in the example above, com_set_lineno should not (as
379 was actually done until 2.2) expand 300, 300 to 255, 255, 45, 45, but to
380 255, 0, 45, 255, 0, 45.
337 */ 381 */
338 382
339 struct compiling { 383 struct compiling {
340 PyObject *c_code; /* string */ 384 PyObject *c_code; /* string */
341 PyObject *c_consts; /* list of objects */ 385 PyObject *c_consts; /* list of objects */
690 c->c_firstlineno = c->c_last_line = lineno; 734 c->c_firstlineno = c->c_last_line = lineno;
691 } 735 }
692 else { 736 else {
693 int incr_addr = c->c_nexti - c->c_last_addr; 737 int incr_addr = c->c_nexti - c->c_last_addr;
694 int incr_line = lineno - c->c_last_line; 738 int incr_line = lineno - c->c_last_line;
695 while (incr_addr > 0 || incr_line > 0) { 739 while (incr_addr > 255) {
696 int trunc_addr = incr_addr; 740 com_add_lnotab(c, 255, 0);
697 int trunc_line = incr_line; 741 incr_addr -= 255;
698 if (trunc_addr > 255) 742 }
699 trunc_addr = 255; 743 while (incr_line > 255) {
700 if (trunc_line > 255) 744 com_add_lnotab(c, incr_addr, 255);
701 trunc_line = 255; 745 incr_line -=255;
702 com_add_lnotab(c, trunc_addr, trunc_line); 746 incr_addr = 0;
703 incr_addr -= trunc_addr; 747 }
704 incr_line -= trunc_line; 748 if (incr_addr > 0 || incr_line > 0)
705 } 749 com_add_lnotab(c, incr_addr, incr_line);
706 c->c_last_addr = c->c_nexti; 750 c->c_last_addr = c->c_nexti;
707 c->c_last_line = lineno; 751 c->c_last_line = lineno;
708 } 752 }
709 } 753 }
710 754