mirror of
https://github.com/python/cpython.git
synced 2025-08-22 17:55:18 +00:00
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
This commit is contained in:
parent
2a5f171759
commit
944fffee89
20 changed files with 859 additions and 539 deletions
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue