From 6b2c10d12f76bfeb35c7172a9f68c52a21380741 Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Mon, 30 Jun 2025 00:48:52 +0900 Subject: [PATCH 1/3] gh-134584: Eliminate redundant refcounting from ``_CALL_LEN`` --- Include/internal/pycore_opcode_metadata.h | 2 +- Lib/test/test_capi/test_opt.py | 1 + Python/bytecodes.c | 13 +++++----- Python/executor_cases.c.h | 23 +++++++---------- Python/generated_cases.c.h | 31 ++++++++++++++++------- Python/optimizer_bytecodes.c | 4 ++- Python/optimizer_cases.c.h | 10 ++++++-- 7 files changed, 51 insertions(+), 33 deletions(-) diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index dd1bf2d1d2b51a..8d1d1f8a4c223c 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -1357,7 +1357,7 @@ _PyOpcode_macro_expansion[256] = { [CALL_KW_BOUND_METHOD] = { .nuops = 6, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_METHOD_VERSION_KW, 2, 1 }, { _EXPAND_METHOD_KW, OPARG_SIMPLE, 3 }, { _PY_FRAME_KW, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, [CALL_KW_NON_PY] = { .nuops = 3, .uops = { { _CHECK_IS_NOT_PY_CALLABLE_KW, OPARG_SIMPLE, 3 }, { _CALL_KW_NON_PY, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, [CALL_KW_PY] = { .nuops = 5, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_FUNCTION_VERSION_KW, 2, 1 }, { _PY_FRAME_KW, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, - [CALL_LEN] = { .nuops = 3, .uops = { { _GUARD_NOS_NULL, OPARG_SIMPLE, 3 }, { _GUARD_CALLABLE_LEN, OPARG_SIMPLE, 3 }, { _CALL_LEN, OPARG_SIMPLE, 3 } } }, + [CALL_LEN] = { .nuops = 5, .uops = { { _GUARD_NOS_NULL, OPARG_SIMPLE, 3 }, { _GUARD_CALLABLE_LEN, OPARG_SIMPLE, 3 }, { _CALL_LEN, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 } } }, [CALL_LIST_APPEND] = { .nuops = 4, .uops = { { _GUARD_CALLABLE_LIST_APPEND, OPARG_SIMPLE, 3 }, { _GUARD_NOS_NOT_NULL, OPARG_SIMPLE, 3 }, { _GUARD_NOS_LIST, OPARG_SIMPLE, 3 }, { _CALL_LIST_APPEND, OPARG_SIMPLE, 3 } } }, [CALL_METHOD_DESCRIPTOR_FAST] = { .nuops = 2, .uops = { { _CALL_METHOD_DESCRIPTOR_FAST, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { .nuops = 2, .uops = { { _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index e4c9a463855a69..e7f0a9a8ff4485 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -1967,6 +1967,7 @@ def testfunc(n): self.assertIn("_CALL_LEN", uops) self.assertNotIn("_GUARD_NOS_INT", uops) self.assertNotIn("_GUARD_TOS_INT", uops) + self.assertIn("_POP_TOP_NOP", uops) def test_call_len_known_length_small_int(self): def testfunc(n): diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 1a5a9ff13a23a5..63ac32fe28f842 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -4315,7 +4315,9 @@ dummy_func( unused/2 + _GUARD_NOS_NULL + _GUARD_CALLABLE_LEN + - _CALL_LEN; + _CALL_LEN + + POP_TOP + + POP_TOP; op(_GUARD_CALLABLE_LEN, (callable, unused, unused -- callable, unused, unused)){ PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); @@ -4323,10 +4325,10 @@ dummy_func( DEOPT_IF(callable_o != interp->callable_cache.len); } - op(_CALL_LEN, (callable, null, arg -- res)) { + op(_CALL_LEN, (callable, null, arg -- res, a, c)) { /* len(o) */ - (void)null; STAT_INC(CALL, hit); + INPUTS_DEAD(); PyObject *arg_o = PyStackRef_AsPyObjectBorrow(arg); Py_ssize_t len_i = PyObject_Length(arg_o); if (len_i < 0) { @@ -4337,10 +4339,9 @@ dummy_func( if (res_o == NULL) { ERROR_NO_POP(); } - PyStackRef_CLOSE(arg); - DEAD(null); - PyStackRef_CLOSE(callable); res = PyStackRef_FromPyObjectSteal(res_o); + a = arg; + c = callable; } op(_GUARD_CALLABLE_ISINSTANCE, (callable, unused, unused, unused -- callable, unused, unused, unused)) { diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 46fc164a5b3bc2..9ca52bea3a9163 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -5937,15 +5937,16 @@ case _CALL_LEN: { _PyStackRef arg; - _PyStackRef null; _PyStackRef callable; _PyStackRef res; + _PyStackRef a; + _PyStackRef c; arg = stack_pointer[-1]; - null = stack_pointer[-2]; callable = stack_pointer[-3]; - (void)null; STAT_INC(CALL, hit); PyObject *arg_o = PyStackRef_AsPyObjectBorrow(arg); + stack_pointer += -3; + assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); Py_ssize_t len_i = PyObject_Length(arg_o); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -5957,19 +5958,13 @@ if (res_o == NULL) { JUMP_TO_ERROR(); } - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(arg); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(callable); - stack_pointer = _PyFrame_GetStackPointer(frame); res = PyStackRef_FromPyObjectSteal(res_o); + a = arg; + c = callable; stack_pointer[0] = res; - stack_pointer += 1; + stack_pointer[1] = a; + stack_pointer[2] = c; + stack_pointer += 3; assert(WITHIN_STACK_BOUNDS()); break; } diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 8f7932f0033c6f..f8dab3960bb102 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -3408,6 +3408,9 @@ _PyStackRef callable; _PyStackRef arg; _PyStackRef res; + _PyStackRef a; + _PyStackRef c; + _PyStackRef value; /* Skip 1 cache entry */ /* Skip 2 cache entries */ // _GUARD_NOS_NULL @@ -3433,9 +3436,10 @@ // _CALL_LEN { arg = stack_pointer[-1]; - (void)null; STAT_INC(CALL, hit); PyObject *arg_o = PyStackRef_AsPyObjectBorrow(arg); + stack_pointer += -3; + assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); Py_ssize_t len_i = PyObject_Length(arg_o); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -3447,21 +3451,30 @@ if (res_o == NULL) { JUMP_TO_LABEL(error); } - stack_pointer += -1; + res = PyStackRef_FromPyObjectSteal(res_o); + a = arg; + c = callable; + } + // _POP_TOP + { + value = c; + stack_pointer[0] = res; + stack_pointer[1] = a; + stack_pointer += 2; assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(arg); + PyStackRef_XCLOSE(value); stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -2; + } + // _POP_TOP + { + value = a; + stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(callable); + PyStackRef_XCLOSE(value); stack_pointer = _PyFrame_GetStackPointer(frame); - res = PyStackRef_FromPyObjectSteal(res_o); } - stack_pointer[0] = res; - stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 3182e8b3b70144..158a8cae844351 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -1178,7 +1178,7 @@ dummy_func(void) { sym_set_const(callable, (PyObject *)&PyUnicode_Type); } - op(_CALL_LEN, (callable, null, arg -- res)) { + op(_CALL_LEN, (callable, null, arg -- res, a, c)) { res = sym_new_type(ctx, &PyLong_Type); int tuple_length = sym_tuple_length(arg); if (tuple_length >= 0) { @@ -1193,6 +1193,8 @@ dummy_func(void) { res = sym_new_const(ctx, temp); Py_DECREF(temp); } + a = arg; + c = callable; } op(_GET_LEN, (obj -- obj, len)) { diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 8d30df3aa7d429..8b90cc773c5344 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -2460,8 +2460,12 @@ case _CALL_LEN: { JitOptRef arg; + JitOptRef callable; JitOptRef res; + JitOptRef a; + JitOptRef c; arg = stack_pointer[-1]; + callable = stack_pointer[-3]; res = sym_new_type(ctx, &PyLong_Type); int tuple_length = sym_tuple_length(arg); if (tuple_length >= 0) { @@ -2480,9 +2484,11 @@ Py_DECREF(temp); stack_pointer += 2; } + a = arg; + c = callable; stack_pointer[-3] = res; - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); + stack_pointer[-2] = a; + stack_pointer[-1] = c; break; } From afd5bb001e861335972cb54b20e4c9a3ef80c4c9 Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Mon, 30 Jun 2025 01:46:57 +0900 Subject: [PATCH 2/3] more optmization --- Include/internal/pycore_uop_ids.h | 19 ++++++++------- Include/internal/pycore_uop_metadata.h | 4 ++++ Lib/test/test_capi/test_opt.py | 1 + Python/bytecodes.c | 10 ++++++++ Python/executor_cases.c.h | 33 ++++++++++++++++++++++++++ Python/optimizer_analysis.c | 1 + Python/optimizer_bytecodes.c | 8 ++++++- Python/optimizer_cases.c.h | 20 +++++++++++++++- 8 files changed, 85 insertions(+), 11 deletions(-) diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index a9432401525ebb..422963f853b55d 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -336,24 +336,25 @@ extern "C" { #define _SWAP 537 #define _SWAP_2 538 #define _SWAP_3 539 -#define _TIER2_RESUME_CHECK 540 -#define _TO_BOOL 541 +#define _SWAP_CALL_LOAD_CONST_INLINE_BORROW 540 +#define _TIER2_RESUME_CHECK 541 +#define _TO_BOOL 542 #define _TO_BOOL_BOOL TO_BOOL_BOOL #define _TO_BOOL_INT TO_BOOL_INT -#define _TO_BOOL_LIST 542 +#define _TO_BOOL_LIST 543 #define _TO_BOOL_NONE TO_BOOL_NONE -#define _TO_BOOL_STR 543 +#define _TO_BOOL_STR 544 #define _UNARY_INVERT UNARY_INVERT #define _UNARY_NEGATIVE UNARY_NEGATIVE #define _UNARY_NOT UNARY_NOT #define _UNPACK_EX UNPACK_EX -#define _UNPACK_SEQUENCE 544 -#define _UNPACK_SEQUENCE_LIST 545 -#define _UNPACK_SEQUENCE_TUPLE 546 -#define _UNPACK_SEQUENCE_TWO_TUPLE 547 +#define _UNPACK_SEQUENCE 545 +#define _UNPACK_SEQUENCE_LIST 546 +#define _UNPACK_SEQUENCE_TUPLE 547 +#define _UNPACK_SEQUENCE_TWO_TUPLE 548 #define _WITH_EXCEPT_START WITH_EXCEPT_START #define _YIELD_VALUE YIELD_VALUE -#define MAX_UOP_ID 547 +#define MAX_UOP_ID 548 #ifdef __cplusplus } diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index ff7e800aa9bb1a..75ea0a430a8d6a 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -314,6 +314,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_SET_IP] = 0, [_CHECK_STACK_SPACE_OPERAND] = HAS_DEOPT_FLAG, [_SAVE_RETURN_OFFSET] = HAS_ARG_FLAG, + [_SWAP_CALL_LOAD_CONST_INLINE_BORROW] = HAS_ESCAPES_FLAG, [_EXIT_TRACE] = HAS_ESCAPES_FLAG, [_CHECK_VALIDITY] = HAS_DEOPT_FLAG, [_LOAD_CONST_INLINE] = HAS_PURE_FLAG, @@ -648,6 +649,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = { [_SWAP] = "_SWAP", [_SWAP_2] = "_SWAP_2", [_SWAP_3] = "_SWAP_3", + [_SWAP_CALL_LOAD_CONST_INLINE_BORROW] = "_SWAP_CALL_LOAD_CONST_INLINE_BORROW", [_TIER2_RESUME_CHECK] = "_TIER2_RESUME_CHECK", [_TO_BOOL] = "_TO_BOOL", [_TO_BOOL_BOOL] = "_TO_BOOL_BOOL", @@ -1257,6 +1259,8 @@ int _PyUop_num_popped(int opcode, int oparg) return 0; case _SAVE_RETURN_OFFSET: return 0; + case _SWAP_CALL_LOAD_CONST_INLINE_BORROW: + return 3; case _EXIT_TRACE: return 0; case _CHECK_VALIDITY: diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index e7f0a9a8ff4485..ff9342786aa24c 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -1988,6 +1988,7 @@ def testfunc(n): self.assertNotIn("_POP_CALL_ONE_LOAD_CONST_INLINE_BORROW", uops) self.assertNotIn("_POP_CALL_LOAD_CONST_INLINE_BORROW", uops) self.assertNotIn("_POP_TOP_LOAD_CONST_INLINE_BORROW", uops) + self.assertIn("_SWAP_CALL_LOAD_CONST_INLINE_BORROW", uops) def test_call_len_known_length(self): def testfunc(n): diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 63ac32fe28f842..c6e2296ba378c4 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -5244,6 +5244,16 @@ dummy_func( #endif } + tier2 op(_SWAP_CALL_LOAD_CONST_INLINE_BORROW, (ptr/4, callable, null, arg -- res, a, c)) { + (void)null; // Silence compiler warnings about unused variables + DEAD(null); + PyStackRef_CLOSE(arg); + PyStackRef_CLOSE(callable); + res = PyStackRef_FromPyObjectBorrow(ptr); + a = arg; + c = callable; + } + tier2 op(_EXIT_TRACE, (exit_p/4 --)) { _PyExitData *exit = (_PyExitData *)exit_p; PyCodeObject *code = _PyFrame_GetCode(frame); diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 9ca52bea3a9163..4d2f559972923a 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -7115,6 +7115,39 @@ break; } + case _SWAP_CALL_LOAD_CONST_INLINE_BORROW: { + _PyStackRef arg; + _PyStackRef null; + _PyStackRef callable; + _PyStackRef res; + _PyStackRef a; + _PyStackRef c; + arg = stack_pointer[-1]; + null = stack_pointer[-2]; + callable = stack_pointer[-3]; + PyObject *ptr = (PyObject *)CURRENT_OPERAND0(); + (void)null; + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(arg); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(callable); + stack_pointer = _PyFrame_GetStackPointer(frame); + res = PyStackRef_FromPyObjectBorrow(ptr); + a = arg; + c = callable; + stack_pointer[0] = res; + stack_pointer[1] = a; + stack_pointer[2] = c; + stack_pointer += 3; + assert(WITHIN_STACK_BOUNDS()); + break; + } + case _EXIT_TRACE: { PyObject *exit_p = (PyObject *)CURRENT_OPERAND0(); _PyExitData *exit = (_PyExitData *)exit_p; diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index fab6fef5ccda10..8c971e74547569 100644 --- a/Python/optimizer_analysis.c +++ b/Python/optimizer_analysis.c @@ -574,6 +574,7 @@ const uint16_t op_without_push[MAX_UOP_ID + 1] = { [_POP_TOP_LOAD_CONST_INLINE_BORROW] = _POP_TOP, [_POP_TWO_LOAD_CONST_INLINE_BORROW] = _POP_TWO, [_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW] = _POP_CALL_TWO, + [_SWAP_CALL_LOAD_CONST_INLINE_BORROW] = _SWAP_CALL_LOAD_CONST_INLINE_BORROW, }; const bool op_skip[MAX_UOP_ID + 1] = { diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 158a8cae844351..bc58b928a41f75 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -516,6 +516,12 @@ dummy_func(void) { value = PyJitRef_Borrow(sym_new_const(ctx, ptr)); } + op(_SWAP_CALL_LOAD_CONST_INLINE_BORROW, (ptr/4, callable, null, arg -- res, a, c)) { + res = PyJitRef_Borrow(sym_new_const(ctx, ptr)); + a = arg; + c = callable; + } + op(_POP_TOP, (value -- )) { PyTypeObject *typ = sym_get_type(value); if (PyJitRef_IsBorrowed(value) || @@ -1187,7 +1193,7 @@ dummy_func(void) { goto error; } if (_Py_IsImmortal(temp)) { - REPLACE_OP(this_instr, _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW, + REPLACE_OP(this_instr, _SWAP_CALL_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)temp); } res = sym_new_const(ctx, temp); diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 8b90cc773c5344..54c713a0600c00 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -2474,7 +2474,7 @@ goto error; } if (_Py_IsImmortal(temp)) { - REPLACE_OP(this_instr, _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW, + REPLACE_OP(this_instr, _SWAP_CALL_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)temp); } res = sym_new_const(ctx, temp); @@ -2895,6 +2895,24 @@ break; } + case _SWAP_CALL_LOAD_CONST_INLINE_BORROW: { + JitOptRef arg; + JitOptRef callable; + JitOptRef res; + JitOptRef a; + JitOptRef c; + arg = stack_pointer[-1]; + callable = stack_pointer[-3]; + PyObject *ptr = (PyObject *)this_instr->operand0; + res = PyJitRef_Borrow(sym_new_const(ctx, ptr)); + a = arg; + c = callable; + stack_pointer[-3] = res; + stack_pointer[-2] = a; + stack_pointer[-1] = c; + break; + } + case _EXIT_TRACE: { PyObject *exit_p = (PyObject *)this_instr->operand0; (void)exit_p; From 5e217c1fcad87309bad21d0ef085dc3a9c3bb0bc Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Mon, 30 Jun 2025 01:56:55 +0900 Subject: [PATCH 3/3] Revert "more optmization" This reverts commit afd5bb001e861335972cb54b20e4c9a3ef80c4c9. --- Include/internal/pycore_uop_ids.h | 19 +++++++-------- Include/internal/pycore_uop_metadata.h | 4 ---- Lib/test/test_capi/test_opt.py | 1 - Python/bytecodes.c | 10 -------- Python/executor_cases.c.h | 33 -------------------------- Python/optimizer_analysis.c | 1 - Python/optimizer_bytecodes.c | 8 +------ Python/optimizer_cases.c.h | 20 +--------------- 8 files changed, 11 insertions(+), 85 deletions(-) diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index 422963f853b55d..a9432401525ebb 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -336,25 +336,24 @@ extern "C" { #define _SWAP 537 #define _SWAP_2 538 #define _SWAP_3 539 -#define _SWAP_CALL_LOAD_CONST_INLINE_BORROW 540 -#define _TIER2_RESUME_CHECK 541 -#define _TO_BOOL 542 +#define _TIER2_RESUME_CHECK 540 +#define _TO_BOOL 541 #define _TO_BOOL_BOOL TO_BOOL_BOOL #define _TO_BOOL_INT TO_BOOL_INT -#define _TO_BOOL_LIST 543 +#define _TO_BOOL_LIST 542 #define _TO_BOOL_NONE TO_BOOL_NONE -#define _TO_BOOL_STR 544 +#define _TO_BOOL_STR 543 #define _UNARY_INVERT UNARY_INVERT #define _UNARY_NEGATIVE UNARY_NEGATIVE #define _UNARY_NOT UNARY_NOT #define _UNPACK_EX UNPACK_EX -#define _UNPACK_SEQUENCE 545 -#define _UNPACK_SEQUENCE_LIST 546 -#define _UNPACK_SEQUENCE_TUPLE 547 -#define _UNPACK_SEQUENCE_TWO_TUPLE 548 +#define _UNPACK_SEQUENCE 544 +#define _UNPACK_SEQUENCE_LIST 545 +#define _UNPACK_SEQUENCE_TUPLE 546 +#define _UNPACK_SEQUENCE_TWO_TUPLE 547 #define _WITH_EXCEPT_START WITH_EXCEPT_START #define _YIELD_VALUE YIELD_VALUE -#define MAX_UOP_ID 548 +#define MAX_UOP_ID 547 #ifdef __cplusplus } diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index 75ea0a430a8d6a..ff7e800aa9bb1a 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -314,7 +314,6 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_SET_IP] = 0, [_CHECK_STACK_SPACE_OPERAND] = HAS_DEOPT_FLAG, [_SAVE_RETURN_OFFSET] = HAS_ARG_FLAG, - [_SWAP_CALL_LOAD_CONST_INLINE_BORROW] = HAS_ESCAPES_FLAG, [_EXIT_TRACE] = HAS_ESCAPES_FLAG, [_CHECK_VALIDITY] = HAS_DEOPT_FLAG, [_LOAD_CONST_INLINE] = HAS_PURE_FLAG, @@ -649,7 +648,6 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = { [_SWAP] = "_SWAP", [_SWAP_2] = "_SWAP_2", [_SWAP_3] = "_SWAP_3", - [_SWAP_CALL_LOAD_CONST_INLINE_BORROW] = "_SWAP_CALL_LOAD_CONST_INLINE_BORROW", [_TIER2_RESUME_CHECK] = "_TIER2_RESUME_CHECK", [_TO_BOOL] = "_TO_BOOL", [_TO_BOOL_BOOL] = "_TO_BOOL_BOOL", @@ -1259,8 +1257,6 @@ int _PyUop_num_popped(int opcode, int oparg) return 0; case _SAVE_RETURN_OFFSET: return 0; - case _SWAP_CALL_LOAD_CONST_INLINE_BORROW: - return 3; case _EXIT_TRACE: return 0; case _CHECK_VALIDITY: diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index ff9342786aa24c..e7f0a9a8ff4485 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -1988,7 +1988,6 @@ def testfunc(n): self.assertNotIn("_POP_CALL_ONE_LOAD_CONST_INLINE_BORROW", uops) self.assertNotIn("_POP_CALL_LOAD_CONST_INLINE_BORROW", uops) self.assertNotIn("_POP_TOP_LOAD_CONST_INLINE_BORROW", uops) - self.assertIn("_SWAP_CALL_LOAD_CONST_INLINE_BORROW", uops) def test_call_len_known_length(self): def testfunc(n): diff --git a/Python/bytecodes.c b/Python/bytecodes.c index c6e2296ba378c4..63ac32fe28f842 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -5244,16 +5244,6 @@ dummy_func( #endif } - tier2 op(_SWAP_CALL_LOAD_CONST_INLINE_BORROW, (ptr/4, callable, null, arg -- res, a, c)) { - (void)null; // Silence compiler warnings about unused variables - DEAD(null); - PyStackRef_CLOSE(arg); - PyStackRef_CLOSE(callable); - res = PyStackRef_FromPyObjectBorrow(ptr); - a = arg; - c = callable; - } - tier2 op(_EXIT_TRACE, (exit_p/4 --)) { _PyExitData *exit = (_PyExitData *)exit_p; PyCodeObject *code = _PyFrame_GetCode(frame); diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 4d2f559972923a..9ca52bea3a9163 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -7115,39 +7115,6 @@ break; } - case _SWAP_CALL_LOAD_CONST_INLINE_BORROW: { - _PyStackRef arg; - _PyStackRef null; - _PyStackRef callable; - _PyStackRef res; - _PyStackRef a; - _PyStackRef c; - arg = stack_pointer[-1]; - null = stack_pointer[-2]; - callable = stack_pointer[-3]; - PyObject *ptr = (PyObject *)CURRENT_OPERAND0(); - (void)null; - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(arg); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(callable); - stack_pointer = _PyFrame_GetStackPointer(frame); - res = PyStackRef_FromPyObjectBorrow(ptr); - a = arg; - c = callable; - stack_pointer[0] = res; - stack_pointer[1] = a; - stack_pointer[2] = c; - stack_pointer += 3; - assert(WITHIN_STACK_BOUNDS()); - break; - } - case _EXIT_TRACE: { PyObject *exit_p = (PyObject *)CURRENT_OPERAND0(); _PyExitData *exit = (_PyExitData *)exit_p; diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index 8c971e74547569..fab6fef5ccda10 100644 --- a/Python/optimizer_analysis.c +++ b/Python/optimizer_analysis.c @@ -574,7 +574,6 @@ const uint16_t op_without_push[MAX_UOP_ID + 1] = { [_POP_TOP_LOAD_CONST_INLINE_BORROW] = _POP_TOP, [_POP_TWO_LOAD_CONST_INLINE_BORROW] = _POP_TWO, [_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW] = _POP_CALL_TWO, - [_SWAP_CALL_LOAD_CONST_INLINE_BORROW] = _SWAP_CALL_LOAD_CONST_INLINE_BORROW, }; const bool op_skip[MAX_UOP_ID + 1] = { diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index bc58b928a41f75..158a8cae844351 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -516,12 +516,6 @@ dummy_func(void) { value = PyJitRef_Borrow(sym_new_const(ctx, ptr)); } - op(_SWAP_CALL_LOAD_CONST_INLINE_BORROW, (ptr/4, callable, null, arg -- res, a, c)) { - res = PyJitRef_Borrow(sym_new_const(ctx, ptr)); - a = arg; - c = callable; - } - op(_POP_TOP, (value -- )) { PyTypeObject *typ = sym_get_type(value); if (PyJitRef_IsBorrowed(value) || @@ -1193,7 +1187,7 @@ dummy_func(void) { goto error; } if (_Py_IsImmortal(temp)) { - REPLACE_OP(this_instr, _SWAP_CALL_LOAD_CONST_INLINE_BORROW, + REPLACE_OP(this_instr, _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)temp); } res = sym_new_const(ctx, temp); diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 54c713a0600c00..8b90cc773c5344 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -2474,7 +2474,7 @@ goto error; } if (_Py_IsImmortal(temp)) { - REPLACE_OP(this_instr, _SWAP_CALL_LOAD_CONST_INLINE_BORROW, + REPLACE_OP(this_instr, _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)temp); } res = sym_new_const(ctx, temp); @@ -2895,24 +2895,6 @@ break; } - case _SWAP_CALL_LOAD_CONST_INLINE_BORROW: { - JitOptRef arg; - JitOptRef callable; - JitOptRef res; - JitOptRef a; - JitOptRef c; - arg = stack_pointer[-1]; - callable = stack_pointer[-3]; - PyObject *ptr = (PyObject *)this_instr->operand0; - res = PyJitRef_Borrow(sym_new_const(ctx, ptr)); - a = arg; - c = callable; - stack_pointer[-3] = res; - stack_pointer[-2] = a; - stack_pointer[-1] = c; - break; - } - case _EXIT_TRACE: { PyObject *exit_p = (PyObject *)this_instr->operand0; (void)exit_p;