]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-103046: Display current line correctly for `dis.disco()` with CACHE entries (...
authorgaogaotiantian <gaogaotiantian@hotmail.com>
Mon, 27 Mar 2023 22:22:06 +0000 (15:22 -0700)
committerGitHub <noreply@github.com>
Mon, 27 Mar 2023 22:22:06 +0000 (23:22 +0100)
Lib/dis.py
Lib/test/test_dis.py
Misc/NEWS.d/next/Library/2023-03-26-20-54-57.gh-issue-103046.xBlA2l.rst [new file with mode: 0644]

index c3d152b4de046946f41a538ee9a9e6d975797fd5..b39b2835330135e451f20806cadc649ab662bada 100644 (file)
@@ -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:
index ed66b362b0808096ffe51bc43f4f09bf1dd8034f..7cad8d1bfe13ae7352d2ad8e769a9b8cf74a7ab8 100644 (file)
@@ -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 (file)
index 0000000..f9bd0a1
--- /dev/null
@@ -0,0 +1 @@
+Display current line label correctly in :mod:`dis` when ``show_caches`` is False and ``lasti`` points to a CACHE entry.