diff options
author | gaogaotiantian <gaogaotiantian@hotmail.com> | 2023-03-27 22:22:06 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-27 22:22:06 (GMT) |
commit | 34eb6f727632d9a1a6998f90c9421e420c785643 (patch) | |
tree | 7baf8c3479fd74ec07156577798272f4475b8bd1 | |
parent | 36067532467ec58c87ac9c140e555e1866431981 (diff) | |
download | cpython-34eb6f727632d9a1a6998f90c9421e420c785643.zip cpython-34eb6f727632d9a1a6998f90c9421e420c785643.tar.gz cpython-34eb6f727632d9a1a6998f90c9421e420c785643.tar.bz2 |
gh-103046: Display current line correctly for `dis.disco()` with CACHE entries (#103047)
-rw-r--r-- | Lib/dis.py | 7 | ||||
-rw-r--r-- | Lib/test/test_dis.py | 29 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2023-03-26-20-54-57.gh-issue-103046.xBlA2l.rst | 1 |
3 files changed, 36 insertions, 1 deletions
@@ -581,7 +581,12 @@ def _disassemble_bytes(code, lasti=-1, varname_from_oparg=None, instr.offset > 0) if new_source_line: print(file=file) - is_current_instr = instr.offset == lasti + if show_caches: + is_current_instr = instr.offset == lasti + else: + # Each CACHE takes 2 bytes + is_current_instr = instr.offset <= lasti \ + <= instr.offset + 2 * _inline_cache_entries[_deoptop(instr.opcode)] print(instr._disassemble(lineno_width, is_current_instr, offset_width), file=file) if exception_entries: diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index ed66b36..7cad8d1 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -1198,6 +1198,35 @@ class DisTests(DisTestBase): self.assertEqual(caches.count(""), empty_caches) self.assertEqual(len(caches), total_caches) + @cpython_only + def test_show_currinstr_with_cache(self): + """ + Make sure that with lasti pointing to CACHE, it still shows the current + line correctly + """ + def f(): + print(a) + # The code above should generate a LOAD_GLOBAL which has CACHE instr after + # However, this might change in the future. So we explicitly try to find + # a CACHE entry in the instructions. If we can't do that, fail the test + + for inst in dis.get_instructions(f, show_caches=True): + if inst.opname == "CACHE": + op_offset = inst.offset - 2 + cache_offset = inst.offset + break + else: + self.fail("Can't find a CACHE entry in the function provided to do the test") + + assem_op = self.get_disassembly(f.__code__, lasti=op_offset, wrapper=False) + assem_cache = self.get_disassembly(f.__code__, lasti=cache_offset, wrapper=False) + + # Make sure --> exists and points to the correct offset + self.assertRegex(assem_op, fr"-->\s+{op_offset}") + # Make sure when lasti points to cache, it shows the same disassembly + self.assertEqual(assem_op, assem_cache) + + class DisWithFileTests(DisTests): # Run the tests again, using the file arg instead of print diff --git a/Misc/NEWS.d/next/Library/2023-03-26-20-54-57.gh-issue-103046.xBlA2l.rst b/Misc/NEWS.d/next/Library/2023-03-26-20-54-57.gh-issue-103046.xBlA2l.rst new file mode 100644 index 0000000..f9bd0a1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-03-26-20-54-57.gh-issue-103046.xBlA2l.rst @@ -0,0 +1 @@ +Display current line label correctly in :mod:`dis` when ``show_caches`` is False and ``lasti`` points to a CACHE entry. |