summaryrefslogtreecommitdiffstats
path: root/Tools
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2022-04-21 15:10:37 (GMT)
committerGitHub <noreply@github.com>2022-04-21 15:10:37 (GMT)
commit944fffee8916cb94321fa33cd3a43f4108717746 (patch)
treef88202dd13021ad5cf4b260ecf05ebab6015a5f6 /Tools
parent2a5f171759a31597032cfe52646929e6f8727243 (diff)
downloadcpython-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-xTools/gdb/libpython.py76
-rw-r--r--Tools/scripts/deepfreeze.py4
-rw-r--r--Tools/scripts/umarshal.py2
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: