diff options
author | Mark Shannon <mark@hotpy.org> | 2022-04-21 15:10:37 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-04-21 15:10:37 (GMT) |
commit | 944fffee8916cb94321fa33cd3a43f4108717746 (patch) | |
tree | f88202dd13021ad5cf4b260ecf05ebab6015a5f6 /Tools | |
parent | 2a5f171759a31597032cfe52646929e6f8727243 (diff) | |
download | cpython-944fffee8916cb94321fa33cd3a43f4108717746.zip cpython-944fffee8916cb94321fa33cd3a43f4108717746.tar.gz cpython-944fffee8916cb94321fa33cd3a43f4108717746.tar.bz2 |
GH-88116: Use a compact format to represent end line and column offsets. (GH-91666)
* Stores all location info in linetable to conform to PEP 626.
* Remove column table from code objects.
* Remove end-line table from code objects.
* Document new location table format
Diffstat (limited to 'Tools')
-rwxr-xr-x | Tools/gdb/libpython.py | 76 | ||||
-rw-r--r-- | Tools/scripts/deepfreeze.py | 4 | ||||
-rw-r--r-- | Tools/scripts/umarshal.py | 2 |
3 files changed, 62 insertions, 20 deletions
diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py index 610d130..857e52f 100755 --- a/Tools/gdb/libpython.py +++ b/Tools/gdb/libpython.py @@ -634,6 +634,63 @@ class PyCFunctionObjectPtr(PyObjectPtr): else: return BuiltInMethodProxy(ml_name, pyop_m_self) +# Python implementation of location table parsing algorithm +def read(it): + return ord(next(it)) + +def read_varint(it): + b = read(it) + val = b & 63; + shift = 0; + while b & 64: + b = read(it) + shift += 6 + val |= (b&63) << shift + return val + +def read_signed_varint(it): + uval = read_varint(it) + if uval & 1: + return -(uval >> 1) + else: + return uval >> 1 + +def parse_location_table(firstlineno, linetable): + line = firstlineno + addr = 0 + it = iter(linetable) + while True: + try: + first_byte = read(it) + except StopIteration: + return + code = (first_byte >> 3) & 15 + length = (first_byte & 7) + 1 + end_addr = addr + length + if code == 15: + yield addr, end_addr, None + addr = end_addr + continue + elif code == 14: # Long form + line_delta = read_signed_varint(it) + line += line_delta + end_line = line + read_varint(it) + col = read_varint(it) + end_col = read_varint(it) + elif code == 13: # No column + line_delta = read_signed_varint(it) + line += line_delta + elif code in (10, 11, 12): # new line + line_delta = code - 10 + line += line_delta + column = read(it) + end_column = read(it) + else: + assert (0 <= code < 10) + second_byte = read(it) + column = code << 3 | (second_byte >> 4) + yield addr, end_addr, line + addr = end_addr class PyCodeObjectPtr(PyObjectPtr): """ @@ -658,18 +715,9 @@ class PyCodeObjectPtr(PyObjectPtr): if addrq < 0: return lineno addr = 0 - for addr_incr, line_incr in zip(co_linetable[::2], co_linetable[1::2]): - if addr_incr == 255: - break - addr += ord(addr_incr) - line_delta = ord(line_incr) - if line_delta == 128: - line_delta = 0 - elif line_delta > 128: - line_delta -= 256 - lineno += line_delta - if addr > addrq: - return lineno + for addr, end_addr, line in parse_location_table(lineno, co_linetable): + if addr <= addrq and end_addr > addrq: + return line assert False, "Unreachable" @@ -1082,8 +1130,8 @@ class PyFramePtr: if self.is_optimized_out(): return None try: - return self.co.addr2line(self.f_lasti*2) - except Exception: + return self.co.addr2line(self.f_lasti) + except Exception as ex: # bpo-34989: addr2line() is a complex function, it can fail in many # ways. For example, it fails with a TypeError on "FakeRepr" if # gdb fails to load debug symbols. Use a catch-all "except diff --git a/Tools/scripts/deepfreeze.py b/Tools/scripts/deepfreeze.py index 3c48bac..5ee6c2f 100644 --- a/Tools/scripts/deepfreeze.py +++ b/Tools/scripts/deepfreeze.py @@ -240,8 +240,6 @@ class Printer: co_name = self.generate(name + "_name", code.co_name) co_qualname = self.generate(name + "_qualname", code.co_qualname) co_linetable = self.generate(name + "_linetable", code.co_linetable) - co_endlinetable = self.generate(name + "_endlinetable", code.co_endlinetable) - co_columntable = self.generate(name + "_columntable", code.co_columntable) co_exceptiontable = self.generate(name + "_exceptiontable", code.co_exceptiontable) # These fields are not directly accessible localsplusnames, localspluskinds = get_localsplus(code) @@ -280,8 +278,6 @@ class Printer: self.write(f".co_name = {co_name},") self.write(f".co_qualname = {co_qualname},") self.write(f".co_linetable = {co_linetable},") - self.write(f".co_endlinetable = {co_endlinetable},") - self.write(f".co_columntable = {co_columntable},") self.write(f".co_code_adaptive = {co_code_adaptive},") name_as_code = f"(PyCodeObject *)&{name}" self.deallocs.append(f"_PyStaticCode_Dealloc({name_as_code});") diff --git a/Tools/scripts/umarshal.py b/Tools/scripts/umarshal.py index 2eaaa7c..f61570c 100644 --- a/Tools/scripts/umarshal.py +++ b/Tools/scripts/umarshal.py @@ -289,8 +289,6 @@ class Reader: retval.co_qualname = self.r_object() retval.co_firstlineno = self.r_long() retval.co_linetable = self.r_object() - retval.co_endlinetable = self.r_object() - retval.co_columntable = self.r_object() retval.co_exceptiontable = self.r_object() return retval elif type == Type.REF: |