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);