co.co_names, co.co_consts,
linestarts, line_offset,
co_positions=co.co_positions(),
- show_caches=show_caches)
+ show_caches=show_caches,
+ original_code=co.co_code)
def _get_const_value(op, arg, co_consts):
"""Helper to get the value of the const in a hasconst op.
names=None, co_consts=None,
linestarts=None, line_offset=0,
exception_entries=(), co_positions=None,
- show_caches=False):
+ show_caches=False, original_code=None):
"""Iterate over the instructions in a bytecode string.
Generates a sequence of Instruction namedtuples giving the details of each
arguments.
"""
+ # Use the basic, unadaptive code for finding labels and actually walking the
+ # bytecode, since replacements like ENTER_EXECUTOR and INSTRUMENTED_* can
+ # mess that logic up pretty badly:
+ original_code = original_code or code
co_positions = co_positions or iter(())
get_name = None if names is None else names.__getitem__
- labels = set(findlabels(code))
+ labels = set(findlabels(original_code))
for start, end, target, _, _ in exception_entries:
for i in range(start, end):
labels.add(target)
starts_line = None
- for offset, start_offset, op, arg in _unpack_opargs(code):
+ for offset, start_offset, op, arg in _unpack_opargs(original_code):
if linestarts is not None:
starts_line = linestarts.get(offset, None)
if starts_line is not None:
positions = Positions(*next(co_positions, ()))
deop = _deoptop(op)
caches = _inline_cache_entries[deop]
+ op = code[offset]
if arg is not None:
# Set argval to the dereferenced value of the argument when
# available, and argrepr to the string representation of argval.
yield Instruction(_all_opname[op], op,
arg, argval, argrepr,
offset, start_offset, starts_line, is_jump_target, positions)
- caches = _inline_cache_entries[deop]
if not caches:
continue
if not show_caches:
lasti, co._varname_from_oparg,
co.co_names, co.co_consts, linestarts, file=file,
exception_entries=exception_entries,
- co_positions=co.co_positions(), show_caches=show_caches)
+ co_positions=co.co_positions(), show_caches=show_caches,
+ original_code=co.co_code)
def _disassemble_recursive(co, *, file=None, depth=None, show_caches=False, adaptive=False):
disassemble(co, file=file, show_caches=show_caches, adaptive=adaptive)
def _disassemble_bytes(code, lasti=-1, varname_from_oparg=None,
names=None, co_consts=None, linestarts=None,
*, file=None, line_offset=0, exception_entries=(),
- co_positions=None, show_caches=False):
+ co_positions=None, show_caches=False, original_code=None):
# Omit the line number column entirely if we have no line number info
show_lineno = bool(linestarts)
if show_lineno:
line_offset=line_offset,
exception_entries=exception_entries,
co_positions=co_positions,
- show_caches=show_caches):
+ show_caches=show_caches,
+ original_code=original_code):
new_source_line = (show_lineno and
instr.starts_line is not None and
instr.offset > 0)
line_offset=self._line_offset,
exception_entries=self.exception_entries,
co_positions=co.co_positions(),
- show_caches=self.show_caches)
+ show_caches=self.show_caches,
+ original_code=co.co_code)
def __repr__(self):
return "{}({!r})".format(self.__class__.__name__,
lasti=offset,
exception_entries=self.exception_entries,
co_positions=co.co_positions(),
- show_caches=self.show_caches)
+ show_caches=self.show_caches,
+ original_code=co.co_code)
return output.getvalue()