bpo-43693: Un-revert commits 2c1e258 and b2bf2bc. (gh-26577)

These were reverted in gh-26530 (commit 17c4edc) due to refleaks.

* 2c1e258 - Compute deref offsets in compiler (gh-25152)
* b2bf2bc - Add new internal code objects fields: co_fastlocalnames and co_fastlocalkinds. (gh-26388)

This change fixes the refleaks.

https://bugs.python.org/issue43693
This commit is contained in:
Eric Snow 2021-06-07 12:22:26 -06:00 committed by GitHub
parent 001eb520b5
commit 2ab27c4af4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 6044 additions and 5710 deletions

View file

@ -273,15 +273,15 @@ def get_instructions(x, *, first_line=None):
the disassembled code object.
"""
co = _get_code_object(x)
cell_names = co.co_cellvars + co.co_freevars
linestarts = dict(findlinestarts(co))
if first_line is not None:
line_offset = first_line - co.co_firstlineno
else:
line_offset = 0
return _get_instructions_bytes(co.co_code, co.co_varnames, co.co_names,
co.co_consts, cell_names, linestarts,
line_offset)
return _get_instructions_bytes(co.co_code,
co._varname_from_oparg,
co.co_names, co.co_consts,
linestarts, line_offset)
def _get_const_info(const_index, const_list):
"""Helper to get optional details about const references
@ -295,7 +295,7 @@ def _get_const_info(const_index, const_list):
argval = const_list[const_index]
return argval, repr(argval)
def _get_name_info(name_index, name_list):
def _get_name_info(name_index, get_name, **extrainfo):
"""Helper to get optional details about named references
Returns the dereferenced name as both value and repr if the name
@ -303,8 +303,8 @@ def _get_name_info(name_index, name_list):
Otherwise returns the name index and its repr().
"""
argval = name_index
if name_list is not None:
argval = name_list[name_index]
if get_name is not None:
argval = get_name(name_index, **extrainfo)
argrepr = argval
else:
argrepr = repr(argval)
@ -336,8 +336,10 @@ def parse_exception_table(code):
except StopIteration:
return entries
def _get_instructions_bytes(code, varnames=None, names=None, constants=None,
cells=None, linestarts=None, line_offset=0, exception_entries=()):
def _get_instructions_bytes(code, varname_from_oparg=None,
names=None, constants=None,
linestarts=None, line_offset=0,
exception_entries=()):
"""Iterate over the instructions in a bytecode string.
Generates a sequence of Instruction namedtuples giving the details of each
@ -346,6 +348,7 @@ def _get_instructions_bytes(code, varnames=None, names=None, constants=None,
arguments.
"""
get_name = None if names is None else names.__getitem__
labels = set(findlabels(code))
for start, end, target, _, _ in exception_entries:
for i in range(start, end):
@ -368,20 +371,18 @@ def _get_instructions_bytes(code, varnames=None, names=None, constants=None,
if op in hasconst:
argval, argrepr = _get_const_info(arg, constants)
elif op in hasname:
argval, argrepr = _get_name_info(arg, names)
argval, argrepr = _get_name_info(arg, get_name)
elif op in hasjabs:
argval = arg*2
argrepr = "to " + repr(argval)
elif op in hasjrel:
argval = offset + 2 + arg*2
argrepr = "to " + repr(argval)
elif op in haslocal:
argval, argrepr = _get_name_info(arg, varnames)
elif op in haslocal or op in hasfree:
argval, argrepr = _get_name_info(arg, varname_from_oparg)
elif op in hascompare:
argval = cmp_op[arg]
argrepr = argval
elif op in hasfree:
argval, argrepr = _get_name_info(arg, cells)
elif op == FORMAT_VALUE:
argval, argrepr = FORMAT_VALUE_CONVERTERS[arg & 0x3]
argval = (argval, bool(arg & 0x4))
@ -398,11 +399,11 @@ def _get_instructions_bytes(code, varnames=None, names=None, constants=None,
def disassemble(co, lasti=-1, *, file=None):
"""Disassemble a code object."""
cell_names = co.co_cellvars + co.co_freevars
linestarts = dict(findlinestarts(co))
exception_entries = parse_exception_table(co)
_disassemble_bytes(co.co_code, lasti, co.co_varnames, co.co_names,
co.co_consts, cell_names, linestarts, file=file,
_disassemble_bytes(co.co_code, lasti,
co._varname_from_oparg,
co.co_names, co.co_consts, linestarts, file=file,
exception_entries=exception_entries)
def _disassemble_recursive(co, *, file=None, depth=None):
@ -416,8 +417,8 @@ def _disassemble_recursive(co, *, file=None, depth=None):
print("Disassembly of %r:" % (x,), file=file)
_disassemble_recursive(x, file=file, depth=depth)
def _disassemble_bytes(code, lasti=-1, varnames=None, names=None,
constants=None, cells=None, linestarts=None,
def _disassemble_bytes(code, lasti=-1, varname_from_oparg=None,
names=None, constants=None, linestarts=None,
*, file=None, line_offset=0, exception_entries=()):
# Omit the line number column entirely if we have no line number info
show_lineno = bool(linestarts)
@ -434,8 +435,8 @@ def _disassemble_bytes(code, lasti=-1, varnames=None, names=None,
offset_width = len(str(maxoffset))
else:
offset_width = 4
for instr in _get_instructions_bytes(code, varnames, names,
constants, cells, linestarts,
for instr in _get_instructions_bytes(code, varname_from_oparg, names,
constants, linestarts,
line_offset=line_offset, exception_entries=exception_entries):
new_source_line = (show_lineno and
instr.starts_line is not None and
@ -517,7 +518,6 @@ class Bytecode:
else:
self.first_line = first_line
self._line_offset = first_line - co.co_firstlineno
self._cell_names = co.co_cellvars + co.co_freevars
self._linestarts = dict(findlinestarts(co))
self._original_object = x
self.current_offset = current_offset
@ -525,8 +525,9 @@ class Bytecode:
def __iter__(self):
co = self.codeobj
return _get_instructions_bytes(co.co_code, co.co_varnames, co.co_names,
co.co_consts, self._cell_names,
return _get_instructions_bytes(co.co_code,
co._varname_from_oparg,
co.co_names, co.co_consts,
self._linestarts,
line_offset=self._line_offset,
exception_entries=self.exception_entries)
@ -554,9 +555,9 @@ class Bytecode:
else:
offset = -1
with io.StringIO() as output:
_disassemble_bytes(co.co_code, varnames=co.co_varnames,
_disassemble_bytes(co.co_code,
varname_from_oparg=co._varname_from_oparg,
names=co.co_names, constants=co.co_consts,
cells=self._cell_names,
linestarts=self._linestarts,
line_offset=self._line_offset,
file=output,