]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-112720: make it easier to subclass and modify dis.ArgResolver's jump arg resolutio...
authorIrit Katriel <1055913+iritkatriel@users.noreply.github.com>
Fri, 16 Feb 2024 19:25:19 +0000 (19:25 +0000)
committerGitHub <noreply@github.com>
Fri, 16 Feb 2024 19:25:19 +0000 (19:25 +0000)
Lib/dis.py
Lib/test/test_dis.py
Misc/NEWS.d/next/Library/2024-02-16-16-40-10.gh-issue-112720.io6_Ac.rst [new file with mode: 0644]

index f05ea1a24f45a716711d5e9c23734f7a7d8f9954..d146bcbb5097efd60cb6b6f0e27c121cbef760fa 100644 (file)
@@ -505,6 +505,20 @@ class ArgResolver:
         self.varname_from_oparg = varname_from_oparg
         self.labels_map = labels_map or {}
 
+    def offset_from_jump_arg(self, op, arg, offset):
+        deop = _deoptop(op)
+        if deop in hasjabs:
+            return arg * 2
+        elif deop in hasjrel:
+            signed_arg = -arg if _is_backward_jump(deop) else arg
+            argval = offset + 2 + signed_arg*2
+            caches = _get_cache_size(_all_opname[deop])
+            argval += 2 * caches
+            if deop == ENTER_EXECUTOR:
+                argval += 2
+            return argval
+        return None
+
     def get_label_for_offset(self, offset):
         return self.labels_map.get(offset, None)
 
@@ -536,17 +550,11 @@ class ArgResolver:
                         argrepr = f"{argrepr} + NULL|self"
                 else:
                     argval, argrepr = _get_name_info(arg, get_name)
-            elif deop in hasjabs:
-                argval = arg*2
-                argrepr = f"to L{self.labels_map[argval]}"
-            elif deop in hasjrel:
-                signed_arg = -arg if _is_backward_jump(deop) else arg
-                argval = offset + 2 + signed_arg*2
-                caches = _get_cache_size(_all_opname[deop])
-                argval += 2 * caches
-                if deop == ENTER_EXECUTOR:
-                    argval += 2
-                argrepr = f"to L{self.labels_map[argval]}"
+            elif deop in hasjump or deop in hasexc:
+                argval = self.offset_from_jump_arg(op, arg, offset)
+                lbl = self.get_label_for_offset(argval)
+                assert lbl is not None
+                argrepr = f"to L{lbl}"
             elif deop in (LOAD_FAST_LOAD_FAST, STORE_FAST_LOAD_FAST, STORE_FAST_STORE_FAST):
                 arg1 = arg >> 4
                 arg2 = arg & 15
index a5917da346dded5c292298afae5778e604b46809..a93cb509b651c517f32f8107df3692e847c90d65 100644 (file)
@@ -1986,6 +1986,22 @@ class InstructionTests(InstructionTestCase):
         self.assertEqual(f(opcode.opmap["BINARY_OP"], 3, *args), (3, '<<'))
         self.assertEqual(f(opcode.opmap["CALL_INTRINSIC_1"], 2, *args), (2, 'INTRINSIC_IMPORT_STAR'))
 
+    def test_custom_arg_resolver(self):
+        class MyArgResolver(dis.ArgResolver):
+            def offset_from_jump_arg(self, op, arg, offset):
+                return arg + 1
+
+            def get_label_for_offset(self, offset):
+                return 2 * offset
+
+        def f(opcode, oparg, offset, *init_args):
+            arg_resolver = MyArgResolver(*init_args)
+            return arg_resolver.get_argval_argrepr(opcode, oparg, offset)
+        offset = 42
+        self.assertEqual(f(opcode.opmap["JUMP_BACKWARD"], 1, offset), (2, 'to L4'))
+        self.assertEqual(f(opcode.opmap["SETUP_FINALLY"], 2, offset), (3, 'to L6'))
+
+
     def get_instructions(self, code):
         return dis._get_instructions_bytes(code)
 
diff --git a/Misc/NEWS.d/next/Library/2024-02-16-16-40-10.gh-issue-112720.io6_Ac.rst b/Misc/NEWS.d/next/Library/2024-02-16-16-40-10.gh-issue-112720.io6_Ac.rst
new file mode 100644 (file)
index 0000000..32916ed
--- /dev/null
@@ -0,0 +1,2 @@
+Refactor :class:`dis.ArgResolver` to make it possible to subclass and change
+the way jump args are interpreted.