https://github.com/python/cpython/commit/e998eb9a83b402f29bae06553424d1e42591cf4a
commit: e998eb9a83b402f29bae06553424d1e42591cf4a
branch: main
author: Neko Asakura <[email protected]>
committer: Fidget-Spinner <[email protected]>
date: 2026-04-16T01:08:29+08:00
summary:

gh-148604: change `ADD_OP(_POP_TOP, ...)` to `optimize_pop_top` in 
`optimizer_bytecodes.c` (GH-148619)

files:
M Lib/test/test_capi/test_opt.py
M Python/optimizer_bytecodes.c
M Python/optimizer_cases.c.h

diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py
index eb3c6458f834e8..efd00296896770 100644
--- a/Lib/test/test_capi/test_opt.py
+++ b/Lib/test/test_capi/test_opt.py
@@ -2642,6 +2642,9 @@ def testfunc(n):
         uops = get_opnames(ex)
         # When the result of type(...) is known, _CALL_TYPE_1 is decomposed.
         self.assertNotIn("_CALL_TYPE_1", uops)
+        # _CALL_TYPE_1 produces 2 _POP_TOP_NOP (callable and null)
+        # type(42) is int produces 4 _POP_TOP_NOP
+        self.assertGreaterEqual(count_ops(ex, "_POP_TOP_NOP"), 6)
 
     def test_call_type_1_result_is_const(self):
         def testfunc(n):
@@ -3453,6 +3456,10 @@ def f(n):
         self.assertEqual(res, TIER2_THRESHOLD)
         uops = get_opnames(ex)
         self.assertNotIn("_LOAD_SPECIAL", uops)
+        # __enter__/__exit__ produce 2 _POP_TOP_NOP
+        # x += 1 produces 2 _POP_TOP_NOP
+        # __exit__()'s None return produces 1 _POP_TOP_NOP
+        self.assertGreaterEqual(count_ops(ex, "_POP_TOP_NOP"), 5)
 
     def test_store_fast_refcount_elimination(self):
         def foo(x):
diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c
index 7ffd835ad120c9..d0870a87aa1386 100644
--- a/Python/optimizer_bytecodes.c
+++ b/Python/optimizer_bytecodes.c
@@ -1480,13 +1480,13 @@ dummy_func(void) {
        next = sym_new_type(ctx, &PyLong_Type);
     }
 
-    op(_CALL_TYPE_1, (unused, unused, arg -- res, a)) {
+    op(_CALL_TYPE_1, (callable, null, arg -- res, a)) {
         PyObject* type = (PyObject *)sym_get_type(arg);
         if (type) {
             res = sym_new_const(ctx, type);
             ADD_OP(_SWAP, 3, 0);
-            ADD_OP(_POP_TOP, 0, 0);
-            ADD_OP(_POP_TOP, 0, 0);
+            optimize_pop_top(ctx, this_instr, callable);
+            optimize_pop_top(ctx, this_instr, null);
             ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)type);
             ADD_OP(_SWAP, 2, 0);
         }
@@ -1509,7 +1509,7 @@ dummy_func(void) {
         a = arg;
     }
 
-    op(_CALL_ISINSTANCE, (unused, unused, instance, cls -- res)) {
+    op(_CALL_ISINSTANCE, (callable, null, instance, cls -- res)) {
         // the result is always a bool, but sometimes we can
         // narrow it down to True or False
         res = sym_new_type(ctx, &PyBool_Type);
@@ -1525,10 +1525,10 @@ dummy_func(void) {
                 out = Py_True;
             }
             sym_set_const(res, out);
-            ADD_OP(_POP_TOP, 0, 0);
-            ADD_OP(_POP_TOP, 0, 0);
-            ADD_OP(_POP_TOP_NOP, 0, 0);
-            ADD_OP(_POP_TOP, 0, 0);
+            optimize_pop_top(ctx, this_instr, cls);
+            optimize_pop_top(ctx, this_instr, instance);
+            optimize_pop_top(ctx, this_instr, null);
+            optimize_pop_top(ctx, this_instr, callable);
             ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)out);
         }
     }
@@ -1902,7 +1902,7 @@ dummy_func(void) {
                 ADD_OP(immortal ? _LOAD_CONST_INLINE_BORROW : 
_LOAD_CONST_INLINE,
                        0, (uintptr_t)descr);
                 ADD_OP(_SWAP, 3, 0);
-                ADD_OP(_POP_TOP, 0, 0);
+                optimize_pop_top(ctx, this_instr, method_and_self[0]);
                 if ((type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) {
                     PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type);
                     _Py_BloomFilter_Add(dependencies, type);
diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h
index d2caa6fc7a7882..0cce6444c4e18b 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -3614,7 +3614,7 @@
                     ADD_OP(immortal ? _LOAD_CONST_INLINE_BORROW : 
_LOAD_CONST_INLINE,
                         0, (uintptr_t)descr);
                     ADD_OP(_SWAP, 3, 0);
-                    ADD_OP(_POP_TOP, 0, 0);
+                    optimize_pop_top(ctx, this_instr, method_and_self[0]);
                     if ((type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) {
                         PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type);
                         _Py_BloomFilter_Add(dependencies, type);
@@ -4035,15 +4035,19 @@
 
         case _CALL_TYPE_1: {
             JitOptRef arg;
+            JitOptRef null;
+            JitOptRef callable;
             JitOptRef res;
             JitOptRef a;
             arg = stack_pointer[-1];
+            null = stack_pointer[-2];
+            callable = stack_pointer[-3];
             PyObject* type = (PyObject *)sym_get_type(arg);
             if (type) {
                 res = sym_new_const(ctx, type);
                 ADD_OP(_SWAP, 3, 0);
-                ADD_OP(_POP_TOP, 0, 0);
-                ADD_OP(_POP_TOP, 0, 0);
+                optimize_pop_top(ctx, this_instr, callable);
+                optimize_pop_top(ctx, this_instr, null);
                 ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)type);
                 ADD_OP(_SWAP, 2, 0);
             }
@@ -4404,9 +4408,13 @@
         case _CALL_ISINSTANCE: {
             JitOptRef cls;
             JitOptRef instance;
+            JitOptRef null;
+            JitOptRef callable;
             JitOptRef res;
             cls = stack_pointer[-1];
             instance = stack_pointer[-2];
+            null = stack_pointer[-3];
+            callable = stack_pointer[-4];
             res = sym_new_type(ctx, &PyBool_Type);
             PyTypeObject *inst_type = sym_get_type(instance);
             PyTypeObject *cls_o = (PyTypeObject *)sym_get_const(ctx, cls);
@@ -4416,10 +4424,10 @@
                     out = Py_True;
                 }
                 sym_set_const(res, out);
-                ADD_OP(_POP_TOP, 0, 0);
-                ADD_OP(_POP_TOP, 0, 0);
-                ADD_OP(_POP_TOP_NOP, 0, 0);
-                ADD_OP(_POP_TOP, 0, 0);
+                optimize_pop_top(ctx, this_instr, cls);
+                optimize_pop_top(ctx, this_instr, instance);
+                optimize_pop_top(ctx, this_instr, null);
+                optimize_pop_top(ctx, this_instr, callable);
                 ADD_OP(_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)out);
             }
             CHECK_STACK_BOUNDS(-3);

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to