summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIrit Katriel <1055913+iritkatriel@users.noreply.github.com>2023-12-03 12:12:49 (GMT)
committerGitHub <noreply@github.com>2023-12-03 12:12:49 (GMT)
commit162d3d428a836850ba29c58bbf37c931843d9e37 (patch)
tree7c876204b40b009f3c087b402b7f867ffd840038
parent4ed46d224401243399b41c7ceef4532bd249da27 (diff)
downloadcpython-162d3d428a836850ba29c58bbf37c931843d9e37.zip
cpython-162d3d428a836850ba29c58bbf37c931843d9e37.tar.gz
cpython-162d3d428a836850ba29c58bbf37c931843d9e37.tar.bz2
gh-112620: Fix dis error on show_cache with labels (#112621)
-rw-r--r--Lib/dis.py17
-rw-r--r--Lib/test/test_dis.py12
2 files changed, 23 insertions, 6 deletions
diff --git a/Lib/dis.py b/Lib/dis.py
index e08e9a9..8d3885d 100644
--- a/Lib/dis.py
+++ b/Lib/dis.py
@@ -412,7 +412,6 @@ class Instruction(_Instruction):
co_consts=None, varname_from_oparg=None, names=None,
labels_map=None, exceptions_map=None):
- label_width = 4 + len(str(len(labels_map)))
argval, argrepr = cls._get_argval_argrepr(
op, arg, offset,
co_consts, names, varname_from_oparg, labels_map)
@@ -420,7 +419,7 @@ class Instruction(_Instruction):
instr = Instruction(_all_opname[op], op, arg, argval, argrepr,
offset, start_offset, starts_line, line_number,
label, positions)
- instr.label_width = label_width
+ instr.label_width = 4 + len(str(len(labels_map)))
instr.exc_handler = exceptions_map.get(offset, None)
return instr
@@ -468,12 +467,14 @@ class Instruction(_Instruction):
"""True if other code jumps to here, otherwise False"""
return self.label is not None
- def _disassemble(self, lineno_width=3, mark_as_current=False, offset_width=0):
+ def _disassemble(self, lineno_width=3, mark_as_current=False, offset_width=0,
+ label_width=0):
"""Format instruction details for inclusion in disassembly output.
*lineno_width* sets the width of the line number field (0 omits it)
*mark_as_current* inserts a '-->' marker arrow as part of the line
*offset_width* sets the width of the instruction offset field
+ *label_width* sets the width of the label field
"""
fields = []
# Column: Source code line number
@@ -488,9 +489,9 @@ class Instruction(_Instruction):
# Column: Label
if self.label is not None:
lbl = f"L{self.label}:"
- fields.append(f"{lbl:>{self.label_width}}")
+ fields.append(f"{lbl:>{label_width}}")
else:
- fields.append(' ' * self.label_width)
+ fields.append(' ' * label_width)
# Column: Instruction offset from start of code sequence
if offset_width > 0:
fields.append(f"{repr(self.offset):>{offset_width}} ")
@@ -648,6 +649,7 @@ def _get_instructions_bytes(code, varname_from_oparg=None,
return labels_map
labels_map = make_labels_map(original_code, exception_entries)
+ label_width = 4 + len(str(len(labels_map)))
exceptions_map = {}
for start, end, target, _, _ in exception_entries:
@@ -756,6 +758,7 @@ def _disassemble_bytes(code, lasti=-1, varname_from_oparg=None,
else:
offset_width = 0
+ label_width = -1
for instr in _get_instructions_bytes(code, varname_from_oparg, names,
co_consts, linestarts,
line_offset=line_offset,
@@ -774,7 +777,9 @@ def _disassemble_bytes(code, lasti=-1, varname_from_oparg=None,
# Each CACHE takes 2 bytes
is_current_instr = instr.offset <= lasti \
<= instr.offset + 2 * _get_cache_size(_all_opname[_deoptop(instr.opcode)])
- print(instr._disassemble(lineno_width, is_current_instr, offset_width),
+ label_width = getattr(instr, 'label_width', label_width)
+ assert label_width >= 0
+ print(instr._disassemble(lineno_width, is_current_instr, offset_width, label_width),
file=file)
if exception_entries:
print("ExceptionTable:", file=file)
diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py
index 805cd4e..349790e 100644
--- a/Lib/test/test_dis.py
+++ b/Lib/test/test_dis.py
@@ -1896,6 +1896,18 @@ class InstructionTests(InstructionTestCase):
positions=None)
self.assertEqual(instruction.arg, instruction.oparg)
+ def test_show_caches_with_label(self):
+ def f(x, y, z):
+ if x:
+ res = y
+ else:
+ res = z
+ return res
+
+ output = io.StringIO()
+ dis.dis(f.__code__, file=output, show_caches=True)
+ self.assertIn("L1:", output.getvalue())
+
def test_baseopname_and_baseopcode(self):
# Standard instructions
for name, code in dis.opmap.items():