summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgaogaotiantian <gaogaotiantian@hotmail.com>2023-03-27 22:22:06 (GMT)
committerGitHub <noreply@github.com>2023-03-27 22:22:06 (GMT)
commit34eb6f727632d9a1a6998f90c9421e420c785643 (patch)
tree7baf8c3479fd74ec07156577798272f4475b8bd1
parent36067532467ec58c87ac9c140e555e1866431981 (diff)
downloadcpython-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.py7
-rw-r--r--Lib/test/test_dis.py29
-rw-r--r--Misc/NEWS.d/next/Library/2023-03-26-20-54-57.gh-issue-103046.xBlA2l.rst1
3 files changed, 36 insertions, 1 deletions
diff --git a/Lib/dis.py b/Lib/dis.py
index c3d152b..b39b283 100644
--- a/Lib/dis.py
+++ b/Lib/dis.py
@@ -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.