From b4434ad3f8ce8e40df45fed78c73942f2a3cce92 Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Sun, 20 Apr 2025 18:34:02 +0800 Subject: [PATCH 1/4] Check recursion limit in _PY_FRAME_GENERAL --- Include/internal/pycore_uop_metadata.h | 2 +- Lib/test/test_opcache.py | 7 +++++++ Python/bytecodes.c | 1 + Python/executor_cases.c.h | 4 ++++ Python/generated_cases.c.h | 10 ++++++++++ 5 files changed, 23 insertions(+), 1 deletion(-) diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index 874756770c1871..147416e35b0bf5 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -221,7 +221,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_CHECK_ATTR_METHOD_LAZY_DICT] = HAS_DEOPT_FLAG, [_LOAD_ATTR_METHOD_LAZY_DICT] = HAS_ARG_FLAG, [_MAYBE_EXPAND_METHOD] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, - [_PY_FRAME_GENERAL] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_PY_FRAME_GENERAL] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_CHECK_FUNCTION_VERSION] = HAS_ARG_FLAG | HAS_EXIT_FLAG, [_CHECK_FUNCTION_VERSION_INLINE] = HAS_EXIT_FLAG, [_CHECK_METHOD_VERSION] = HAS_ARG_FLAG | HAS_EXIT_FLAG, diff --git a/Lib/test/test_opcache.py b/Lib/test/test_opcache.py index ac132465b227ad..9d5e41c3e0cdc3 100644 --- a/Lib/test/test_opcache.py +++ b/Lib/test/test_opcache.py @@ -550,6 +550,13 @@ def instantiate(): with self.assertRaises(TypeError): instantiate() + def test_recursion_check_for_general_calls(self): + def test(default=None): + return test() + + with self.assertRaises(RecursionError): + test() + def make_deferred_ref_count_obj(): """Create an object that uses deferred reference counting. diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 07df22c761fc1c..51af21fd0b4af7 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -3756,6 +3756,7 @@ dummy_func( macro(INSTRUMENTED_CALL) = unused/3 + _MAYBE_EXPAND_METHOD + _MONITOR_CALL + _DO_CALL + _CHECK_PERIODIC; op(_PY_FRAME_GENERAL, (callable, self_or_null, args[oparg] -- new_frame: _PyInterpreterFrame*)) { + DEOPT_IF(tstate->py_recursion_remaining <= 1); PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); // oparg counts all of the args, but *not* self: diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index cd265c383bd380..5b1cacba2a8b7a 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -4688,6 +4688,10 @@ args = &stack_pointer[-oparg]; self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; + if (tstate->py_recursion_remaining <= 1) { + UOP_STAT_INC(uopcode, miss); + JUMP_TO_JUMP_TARGET(); + } PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null)) { diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 911f5ae3e7c0d7..d6e3d27663a591 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -1857,6 +1857,11 @@ // _PY_FRAME_GENERAL { args = &stack_pointer[-oparg]; + if (tstate->py_recursion_remaining <= 1) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null)) { @@ -4090,6 +4095,11 @@ { args = &stack_pointer[-oparg]; self_or_null = stack_pointer[-1 - oparg]; + if (tstate->py_recursion_remaining <= 1) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null)) { From 2d88db8ed3345f6d49fb489e01bee1127af9ea16 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Sun, 20 Apr 2025 10:37:43 +0000 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2025-04-20-10-37-39.gh-issue-132744.ArrCp8.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-04-20-10-37-39.gh-issue-132744.ArrCp8.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-04-20-10-37-39.gh-issue-132744.ArrCp8.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-04-20-10-37-39.gh-issue-132744.ArrCp8.rst new file mode 100644 index 00000000000000..bcd72568c52727 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-04-20-10-37-39.gh-issue-132744.ArrCp8.rst @@ -0,0 +1 @@ +Certain calls now check for runaway recursion and respect the system recursion limit. From 0a0a49678ee1e7755cba2a4ad2c61ac0bf2f840f Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Tue, 29 Apr 2025 23:42:37 +0800 Subject: [PATCH 3/4] Address review --- Include/internal/pycore_opcode_metadata.h | 4 +-- Include/internal/pycore_uop_metadata.h | 2 +- Python/bytecodes.c | 3 ++- Python/executor_cases.c.h | 4 --- Python/generated_cases.c.h | 32 +++++++++++++++++++---- 5 files changed, 32 insertions(+), 13 deletions(-) diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index 521f7a92cf08c4..25cbe3714031ef 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -1332,7 +1332,7 @@ _PyOpcode_macro_expansion[256] = { [BUILD_TUPLE] = { .nuops = 1, .uops = { { _BUILD_TUPLE, OPARG_SIMPLE, 0 } } }, [CALL_ALLOC_AND_ENTER_INIT] = { .nuops = 4, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_AND_ALLOCATE_OBJECT, 2, 1 }, { _CREATE_INIT_FRAME, OPARG_SIMPLE, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, [CALL_BOUND_METHOD_EXACT_ARGS] = { .nuops = 9, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_CALL_BOUND_METHOD_EXACT_ARGS, OPARG_SIMPLE, 1 }, { _INIT_CALL_BOUND_METHOD_EXACT_ARGS, OPARG_SIMPLE, 1 }, { _CHECK_FUNCTION_VERSION, 2, 1 }, { _CHECK_FUNCTION_EXACT_ARGS, OPARG_SIMPLE, 3 }, { _CHECK_STACK_SPACE, OPARG_SIMPLE, 3 }, { _INIT_CALL_PY_EXACT_ARGS, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, - [CALL_BOUND_METHOD_GENERAL] = { .nuops = 6, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_METHOD_VERSION, 2, 1 }, { _EXPAND_METHOD, OPARG_SIMPLE, 3 }, { _PY_FRAME_GENERAL, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, + [CALL_BOUND_METHOD_GENERAL] = { .nuops = 7, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_METHOD_VERSION, 2, 1 }, { _EXPAND_METHOD, OPARG_SIMPLE, 3 }, { _CHECK_STACK_SPACE, OPARG_SIMPLE, 3 }, { _PY_FRAME_GENERAL, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, [CALL_BUILTIN_CLASS] = { .nuops = 2, .uops = { { _CALL_BUILTIN_CLASS, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, [CALL_BUILTIN_FAST] = { .nuops = 2, .uops = { { _CALL_BUILTIN_FAST, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, [CALL_BUILTIN_FAST_WITH_KEYWORDS] = { .nuops = 2, .uops = { { _CALL_BUILTIN_FAST_WITH_KEYWORDS, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, @@ -1351,7 +1351,7 @@ _PyOpcode_macro_expansion[256] = { [CALL_METHOD_DESCRIPTOR_O] = { .nuops = 2, .uops = { { _CALL_METHOD_DESCRIPTOR_O, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, [CALL_NON_PY_GENERAL] = { .nuops = 3, .uops = { { _CHECK_IS_NOT_PY_CALLABLE, OPARG_SIMPLE, 3 }, { _CALL_NON_PY_GENERAL, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, [CALL_PY_EXACT_ARGS] = { .nuops = 7, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_FUNCTION_VERSION, 2, 1 }, { _CHECK_FUNCTION_EXACT_ARGS, OPARG_SIMPLE, 3 }, { _CHECK_STACK_SPACE, OPARG_SIMPLE, 3 }, { _INIT_CALL_PY_EXACT_ARGS, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, - [CALL_PY_GENERAL] = { .nuops = 5, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_FUNCTION_VERSION, 2, 1 }, { _PY_FRAME_GENERAL, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, + [CALL_PY_GENERAL] = { .nuops = 6, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_FUNCTION_VERSION, 2, 1 }, { _CHECK_STACK_SPACE, OPARG_SIMPLE, 3 }, { _PY_FRAME_GENERAL, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, [CALL_STR_1] = { .nuops = 2, .uops = { { _CALL_STR_1, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, [CALL_TUPLE_1] = { .nuops = 2, .uops = { { _CALL_TUPLE_1, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, [CALL_TYPE_1] = { .nuops = 1, .uops = { { _CALL_TYPE_1, OPARG_SIMPLE, 3 } } }, diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index 147416e35b0bf5..874756770c1871 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -221,7 +221,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_CHECK_ATTR_METHOD_LAZY_DICT] = HAS_DEOPT_FLAG, [_LOAD_ATTR_METHOD_LAZY_DICT] = HAS_ARG_FLAG, [_MAYBE_EXPAND_METHOD] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, - [_PY_FRAME_GENERAL] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_PY_FRAME_GENERAL] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_CHECK_FUNCTION_VERSION] = HAS_ARG_FLAG | HAS_EXIT_FLAG, [_CHECK_FUNCTION_VERSION_INLINE] = HAS_EXIT_FLAG, [_CHECK_METHOD_VERSION] = HAS_ARG_FLAG | HAS_EXIT_FLAG, diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 51af21fd0b4af7..3b6ef165db7f24 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -3756,7 +3756,6 @@ dummy_func( macro(INSTRUMENTED_CALL) = unused/3 + _MAYBE_EXPAND_METHOD + _MONITOR_CALL + _DO_CALL + _CHECK_PERIODIC; op(_PY_FRAME_GENERAL, (callable, self_or_null, args[oparg] -- new_frame: _PyInterpreterFrame*)) { - DEOPT_IF(tstate->py_recursion_remaining <= 1); PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); // oparg counts all of the args, but *not* self: @@ -3798,6 +3797,7 @@ dummy_func( unused/1 + // Skip over the counter _CHECK_PEP_523 + _CHECK_FUNCTION_VERSION + + _CHECK_STACK_SPACE + _PY_FRAME_GENERAL + _SAVE_RETURN_OFFSET + _PUSH_FRAME; @@ -3829,6 +3829,7 @@ dummy_func( _CHECK_METHOD_VERSION + _EXPAND_METHOD + flush + // so that self is in the argument array + _CHECK_STACK_SPACE + _PY_FRAME_GENERAL + _SAVE_RETURN_OFFSET + _PUSH_FRAME; diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 5b1cacba2a8b7a..cd265c383bd380 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -4688,10 +4688,6 @@ args = &stack_pointer[-oparg]; self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; - if (tstate->py_recursion_remaining <= 1) { - UOP_STAT_INC(uopcode, miss); - JUMP_TO_JUMP_TARGET(); - } PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null)) { diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index d6e3d27663a591..08d0a80a1e6863 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -1854,14 +1854,25 @@ stack_pointer = _PyFrame_GetStackPointer(frame); } // flush - // _PY_FRAME_GENERAL + // _CHECK_STACK_SPACE { - args = &stack_pointer[-oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyFunctionObject *func = (PyFunctionObject *)callable_o; + PyCodeObject *code = (PyCodeObject *)func->func_code; + if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } if (tstate->py_recursion_remaining <= 1) { UPDATE_MISS_STATS(CALL); assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } + } + // _PY_FRAME_GENERAL + { + args = &stack_pointer[-oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null)) { @@ -4091,15 +4102,26 @@ JUMP_TO_PREDICTED(CALL); } } - // _PY_FRAME_GENERAL + // _CHECK_STACK_SPACE { - args = &stack_pointer[-oparg]; - self_or_null = stack_pointer[-1 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyFunctionObject *func = (PyFunctionObject *)callable_o; + PyCodeObject *code = (PyCodeObject *)func->func_code; + if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { + UPDATE_MISS_STATS(CALL); + assert(_PyOpcode_Deopt[opcode] == (CALL)); + JUMP_TO_PREDICTED(CALL); + } if (tstate->py_recursion_remaining <= 1) { UPDATE_MISS_STATS(CALL); assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } + } + // _PY_FRAME_GENERAL + { + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null)) { From 9a5de585ae57f05d7459ba7e898bad8eaf3bbd9d Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Tue, 29 Apr 2025 23:47:22 +0800 Subject: [PATCH 4/4] split into another uop --- Include/internal/pycore_opcode_metadata.h | 10 +- Include/internal/pycore_uop_ids.h | 317 +++++++++++----------- Include/internal/pycore_uop_metadata.h | 4 + Python/bytecodes.c | 9 +- Python/executor_cases.c.h | 4 + Python/generated_cases.c.h | 26 +- Python/optimizer_cases.c.h | 4 + 7 files changed, 191 insertions(+), 183 deletions(-) diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index 25cbe3714031ef..698d40bec3b57b 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -1298,7 +1298,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = { }; #endif -#define MAX_UOP_PER_EXPANSION 9 +#define MAX_UOP_PER_EXPANSION 10 struct opcode_macro_expansion { int nuops; struct { int16_t uop; int8_t size; int8_t offset; } uops[MAX_UOP_PER_EXPANSION]; @@ -1331,8 +1331,8 @@ _PyOpcode_macro_expansion[256] = { [BUILD_STRING] = { .nuops = 1, .uops = { { _BUILD_STRING, OPARG_SIMPLE, 0 } } }, [BUILD_TUPLE] = { .nuops = 1, .uops = { { _BUILD_TUPLE, OPARG_SIMPLE, 0 } } }, [CALL_ALLOC_AND_ENTER_INIT] = { .nuops = 4, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_AND_ALLOCATE_OBJECT, 2, 1 }, { _CREATE_INIT_FRAME, OPARG_SIMPLE, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, - [CALL_BOUND_METHOD_EXACT_ARGS] = { .nuops = 9, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_CALL_BOUND_METHOD_EXACT_ARGS, OPARG_SIMPLE, 1 }, { _INIT_CALL_BOUND_METHOD_EXACT_ARGS, OPARG_SIMPLE, 1 }, { _CHECK_FUNCTION_VERSION, 2, 1 }, { _CHECK_FUNCTION_EXACT_ARGS, OPARG_SIMPLE, 3 }, { _CHECK_STACK_SPACE, OPARG_SIMPLE, 3 }, { _INIT_CALL_PY_EXACT_ARGS, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, - [CALL_BOUND_METHOD_GENERAL] = { .nuops = 7, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_METHOD_VERSION, 2, 1 }, { _EXPAND_METHOD, OPARG_SIMPLE, 3 }, { _CHECK_STACK_SPACE, OPARG_SIMPLE, 3 }, { _PY_FRAME_GENERAL, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, + [CALL_BOUND_METHOD_EXACT_ARGS] = { .nuops = 10, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_CALL_BOUND_METHOD_EXACT_ARGS, OPARG_SIMPLE, 1 }, { _INIT_CALL_BOUND_METHOD_EXACT_ARGS, OPARG_SIMPLE, 1 }, { _CHECK_FUNCTION_VERSION, 2, 1 }, { _CHECK_FUNCTION_EXACT_ARGS, OPARG_SIMPLE, 3 }, { _CHECK_STACK_SPACE, OPARG_SIMPLE, 3 }, { _CHECK_RECURSION_REMAINING, OPARG_SIMPLE, 3 }, { _INIT_CALL_PY_EXACT_ARGS, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, + [CALL_BOUND_METHOD_GENERAL] = { .nuops = 7, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_METHOD_VERSION, 2, 1 }, { _EXPAND_METHOD, OPARG_SIMPLE, 3 }, { _CHECK_RECURSION_REMAINING, OPARG_SIMPLE, 3 }, { _PY_FRAME_GENERAL, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, [CALL_BUILTIN_CLASS] = { .nuops = 2, .uops = { { _CALL_BUILTIN_CLASS, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, [CALL_BUILTIN_FAST] = { .nuops = 2, .uops = { { _CALL_BUILTIN_FAST, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, [CALL_BUILTIN_FAST_WITH_KEYWORDS] = { .nuops = 2, .uops = { { _CALL_BUILTIN_FAST_WITH_KEYWORDS, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, @@ -1350,8 +1350,8 @@ _PyOpcode_macro_expansion[256] = { [CALL_METHOD_DESCRIPTOR_NOARGS] = { .nuops = 2, .uops = { { _CALL_METHOD_DESCRIPTOR_NOARGS, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, [CALL_METHOD_DESCRIPTOR_O] = { .nuops = 2, .uops = { { _CALL_METHOD_DESCRIPTOR_O, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, [CALL_NON_PY_GENERAL] = { .nuops = 3, .uops = { { _CHECK_IS_NOT_PY_CALLABLE, OPARG_SIMPLE, 3 }, { _CALL_NON_PY_GENERAL, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, - [CALL_PY_EXACT_ARGS] = { .nuops = 7, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_FUNCTION_VERSION, 2, 1 }, { _CHECK_FUNCTION_EXACT_ARGS, OPARG_SIMPLE, 3 }, { _CHECK_STACK_SPACE, OPARG_SIMPLE, 3 }, { _INIT_CALL_PY_EXACT_ARGS, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, - [CALL_PY_GENERAL] = { .nuops = 6, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_FUNCTION_VERSION, 2, 1 }, { _CHECK_STACK_SPACE, OPARG_SIMPLE, 3 }, { _PY_FRAME_GENERAL, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, + [CALL_PY_EXACT_ARGS] = { .nuops = 8, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_FUNCTION_VERSION, 2, 1 }, { _CHECK_FUNCTION_EXACT_ARGS, OPARG_SIMPLE, 3 }, { _CHECK_STACK_SPACE, OPARG_SIMPLE, 3 }, { _CHECK_RECURSION_REMAINING, OPARG_SIMPLE, 3 }, { _INIT_CALL_PY_EXACT_ARGS, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, + [CALL_PY_GENERAL] = { .nuops = 6, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_FUNCTION_VERSION, 2, 1 }, { _CHECK_RECURSION_REMAINING, OPARG_SIMPLE, 3 }, { _PY_FRAME_GENERAL, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } }, [CALL_STR_1] = { .nuops = 2, .uops = { { _CALL_STR_1, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, [CALL_TUPLE_1] = { .nuops = 2, .uops = { { _CALL_TUPLE_1, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC, OPARG_SIMPLE, 3 } } }, [CALL_TYPE_1] = { .nuops = 1, .uops = { { _CALL_TYPE_1, OPARG_SIMPLE, 3 } } }, diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index e9a536919da598..1f7997a2281500 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -71,86 +71,87 @@ extern "C" { #define _CHECK_PEP_523 345 #define _CHECK_PERIODIC 346 #define _CHECK_PERIODIC_IF_NOT_YIELD_FROM 347 -#define _CHECK_STACK_SPACE 348 -#define _CHECK_STACK_SPACE_OPERAND 349 -#define _CHECK_VALIDITY 350 -#define _COMPARE_OP 351 -#define _COMPARE_OP_FLOAT 352 -#define _COMPARE_OP_INT 353 -#define _COMPARE_OP_STR 354 -#define _CONTAINS_OP 355 -#define _CONTAINS_OP_DICT 356 -#define _CONTAINS_OP_SET 357 +#define _CHECK_RECURSION_REMAINING 348 +#define _CHECK_STACK_SPACE 349 +#define _CHECK_STACK_SPACE_OPERAND 350 +#define _CHECK_VALIDITY 351 +#define _COMPARE_OP 352 +#define _COMPARE_OP_FLOAT 353 +#define _COMPARE_OP_INT 354 +#define _COMPARE_OP_STR 355 +#define _CONTAINS_OP 356 +#define _CONTAINS_OP_DICT 357 +#define _CONTAINS_OP_SET 358 #define _CONVERT_VALUE CONVERT_VALUE #define _COPY COPY #define _COPY_FREE_VARS COPY_FREE_VARS -#define _CREATE_INIT_FRAME 358 +#define _CREATE_INIT_FRAME 359 #define _DELETE_ATTR DELETE_ATTR #define _DELETE_DEREF DELETE_DEREF #define _DELETE_FAST DELETE_FAST #define _DELETE_GLOBAL DELETE_GLOBAL #define _DELETE_NAME DELETE_NAME #define _DELETE_SUBSCR DELETE_SUBSCR -#define _DEOPT 359 +#define _DEOPT 360 #define _DICT_MERGE DICT_MERGE #define _DICT_UPDATE DICT_UPDATE -#define _DO_CALL 360 -#define _DO_CALL_FUNCTION_EX 361 -#define _DO_CALL_KW 362 +#define _DO_CALL 361 +#define _DO_CALL_FUNCTION_EX 362 +#define _DO_CALL_KW 363 #define _END_FOR END_FOR #define _END_SEND END_SEND -#define _ERROR_POP_N 363 +#define _ERROR_POP_N 364 #define _EXIT_INIT_CHECK EXIT_INIT_CHECK -#define _EXPAND_METHOD 364 -#define _EXPAND_METHOD_KW 365 -#define _FATAL_ERROR 366 +#define _EXPAND_METHOD 365 +#define _EXPAND_METHOD_KW 366 +#define _FATAL_ERROR 367 #define _FORMAT_SIMPLE FORMAT_SIMPLE #define _FORMAT_WITH_SPEC FORMAT_WITH_SPEC -#define _FOR_ITER 367 -#define _FOR_ITER_GEN_FRAME 368 -#define _FOR_ITER_TIER_TWO 369 +#define _FOR_ITER 368 +#define _FOR_ITER_GEN_FRAME 369 +#define _FOR_ITER_TIER_TWO 370 #define _GET_AITER GET_AITER #define _GET_ANEXT GET_ANEXT #define _GET_AWAITABLE GET_AWAITABLE #define _GET_ITER GET_ITER #define _GET_LEN GET_LEN #define _GET_YIELD_FROM_ITER GET_YIELD_FROM_ITER -#define _GUARD_BINARY_OP_EXTEND 370 -#define _GUARD_DORV_NO_DICT 371 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 372 -#define _GUARD_GLOBALS_VERSION 373 -#define _GUARD_IS_FALSE_POP 374 -#define _GUARD_IS_NONE_POP 375 -#define _GUARD_IS_NOT_NONE_POP 376 -#define _GUARD_IS_TRUE_POP 377 -#define _GUARD_KEYS_VERSION 378 -#define _GUARD_NOS_DICT 379 -#define _GUARD_NOS_FLOAT 380 -#define _GUARD_NOS_INT 381 -#define _GUARD_NOS_LIST 382 -#define _GUARD_NOS_TUPLE 383 -#define _GUARD_NOS_UNICODE 384 -#define _GUARD_NOT_EXHAUSTED_LIST 385 -#define _GUARD_NOT_EXHAUSTED_RANGE 386 -#define _GUARD_NOT_EXHAUSTED_TUPLE 387 -#define _GUARD_TOS_ANY_SET 388 -#define _GUARD_TOS_DICT 389 -#define _GUARD_TOS_FLOAT 390 -#define _GUARD_TOS_INT 391 -#define _GUARD_TOS_LIST 392 -#define _GUARD_TOS_TUPLE 393 -#define _GUARD_TOS_UNICODE 394 -#define _GUARD_TYPE_VERSION 395 -#define _GUARD_TYPE_VERSION_AND_LOCK 396 +#define _GUARD_BINARY_OP_EXTEND 371 +#define _GUARD_DORV_NO_DICT 372 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 373 +#define _GUARD_GLOBALS_VERSION 374 +#define _GUARD_IS_FALSE_POP 375 +#define _GUARD_IS_NONE_POP 376 +#define _GUARD_IS_NOT_NONE_POP 377 +#define _GUARD_IS_TRUE_POP 378 +#define _GUARD_KEYS_VERSION 379 +#define _GUARD_NOS_DICT 380 +#define _GUARD_NOS_FLOAT 381 +#define _GUARD_NOS_INT 382 +#define _GUARD_NOS_LIST 383 +#define _GUARD_NOS_TUPLE 384 +#define _GUARD_NOS_UNICODE 385 +#define _GUARD_NOT_EXHAUSTED_LIST 386 +#define _GUARD_NOT_EXHAUSTED_RANGE 387 +#define _GUARD_NOT_EXHAUSTED_TUPLE 388 +#define _GUARD_TOS_ANY_SET 389 +#define _GUARD_TOS_DICT 390 +#define _GUARD_TOS_FLOAT 391 +#define _GUARD_TOS_INT 392 +#define _GUARD_TOS_LIST 393 +#define _GUARD_TOS_TUPLE 394 +#define _GUARD_TOS_UNICODE 395 +#define _GUARD_TYPE_VERSION 396 +#define _GUARD_TYPE_VERSION_AND_LOCK 397 #define _IMPORT_FROM IMPORT_FROM #define _IMPORT_NAME IMPORT_NAME -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 397 -#define _INIT_CALL_PY_EXACT_ARGS 398 -#define _INIT_CALL_PY_EXACT_ARGS_0 399 -#define _INIT_CALL_PY_EXACT_ARGS_1 400 -#define _INIT_CALL_PY_EXACT_ARGS_2 401 -#define _INIT_CALL_PY_EXACT_ARGS_3 402 -#define _INIT_CALL_PY_EXACT_ARGS_4 403 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 398 +#define _INIT_CALL_PY_EXACT_ARGS 399 +#define _INIT_CALL_PY_EXACT_ARGS_0 400 +#define _INIT_CALL_PY_EXACT_ARGS_1 401 +#define _INIT_CALL_PY_EXACT_ARGS_2 402 +#define _INIT_CALL_PY_EXACT_ARGS_3 403 +#define _INIT_CALL_PY_EXACT_ARGS_4 404 #define _INSTRUMENTED_FOR_ITER INSTRUMENTED_FOR_ITER #define _INSTRUMENTED_INSTRUCTION INSTRUMENTED_INSTRUCTION #define _INSTRUMENTED_JUMP_FORWARD INSTRUMENTED_JUMP_FORWARD @@ -160,163 +161,163 @@ extern "C" { #define _INSTRUMENTED_POP_JUMP_IF_NONE INSTRUMENTED_POP_JUMP_IF_NONE #define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE INSTRUMENTED_POP_JUMP_IF_NOT_NONE #define _INSTRUMENTED_POP_JUMP_IF_TRUE INSTRUMENTED_POP_JUMP_IF_TRUE -#define _IS_NONE 404 +#define _IS_NONE 405 #define _IS_OP IS_OP -#define _ITER_CHECK_LIST 405 -#define _ITER_CHECK_RANGE 406 -#define _ITER_CHECK_TUPLE 407 -#define _ITER_JUMP_LIST 408 -#define _ITER_JUMP_RANGE 409 -#define _ITER_JUMP_TUPLE 410 -#define _ITER_NEXT_LIST 411 -#define _ITER_NEXT_LIST_TIER_TWO 412 -#define _ITER_NEXT_RANGE 413 -#define _ITER_NEXT_TUPLE 414 -#define _JUMP_TO_TOP 415 +#define _ITER_CHECK_LIST 406 +#define _ITER_CHECK_RANGE 407 +#define _ITER_CHECK_TUPLE 408 +#define _ITER_JUMP_LIST 409 +#define _ITER_JUMP_RANGE 410 +#define _ITER_JUMP_TUPLE 411 +#define _ITER_NEXT_LIST 412 +#define _ITER_NEXT_LIST_TIER_TWO 413 +#define _ITER_NEXT_RANGE 414 +#define _ITER_NEXT_TUPLE 415 +#define _JUMP_TO_TOP 416 #define _LIST_APPEND LIST_APPEND #define _LIST_EXTEND LIST_EXTEND -#define _LOAD_ATTR 416 -#define _LOAD_ATTR_CLASS 417 +#define _LOAD_ATTR 417 +#define _LOAD_ATTR_CLASS 418 #define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN -#define _LOAD_ATTR_INSTANCE_VALUE 418 -#define _LOAD_ATTR_METHOD_LAZY_DICT 419 -#define _LOAD_ATTR_METHOD_NO_DICT 420 -#define _LOAD_ATTR_METHOD_WITH_VALUES 421 -#define _LOAD_ATTR_MODULE 422 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 423 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 424 -#define _LOAD_ATTR_PROPERTY_FRAME 425 -#define _LOAD_ATTR_SLOT 426 -#define _LOAD_ATTR_WITH_HINT 427 +#define _LOAD_ATTR_INSTANCE_VALUE 419 +#define _LOAD_ATTR_METHOD_LAZY_DICT 420 +#define _LOAD_ATTR_METHOD_NO_DICT 421 +#define _LOAD_ATTR_METHOD_WITH_VALUES 422 +#define _LOAD_ATTR_MODULE 423 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 424 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 425 +#define _LOAD_ATTR_PROPERTY_FRAME 426 +#define _LOAD_ATTR_SLOT 427 +#define _LOAD_ATTR_WITH_HINT 428 #define _LOAD_BUILD_CLASS LOAD_BUILD_CLASS -#define _LOAD_BYTECODE 428 +#define _LOAD_BYTECODE 429 #define _LOAD_COMMON_CONSTANT LOAD_COMMON_CONSTANT #define _LOAD_CONST LOAD_CONST #define _LOAD_CONST_IMMORTAL LOAD_CONST_IMMORTAL -#define _LOAD_CONST_INLINE 429 -#define _LOAD_CONST_INLINE_BORROW 430 +#define _LOAD_CONST_INLINE 430 +#define _LOAD_CONST_INLINE_BORROW 431 #define _LOAD_CONST_MORTAL LOAD_CONST_MORTAL #define _LOAD_DEREF LOAD_DEREF -#define _LOAD_FAST 431 -#define _LOAD_FAST_0 432 -#define _LOAD_FAST_1 433 -#define _LOAD_FAST_2 434 -#define _LOAD_FAST_3 435 -#define _LOAD_FAST_4 436 -#define _LOAD_FAST_5 437 -#define _LOAD_FAST_6 438 -#define _LOAD_FAST_7 439 +#define _LOAD_FAST 432 +#define _LOAD_FAST_0 433 +#define _LOAD_FAST_1 434 +#define _LOAD_FAST_2 435 +#define _LOAD_FAST_3 436 +#define _LOAD_FAST_4 437 +#define _LOAD_FAST_5 438 +#define _LOAD_FAST_6 439 +#define _LOAD_FAST_7 440 #define _LOAD_FAST_AND_CLEAR LOAD_FAST_AND_CLEAR -#define _LOAD_FAST_BORROW 440 -#define _LOAD_FAST_BORROW_0 441 -#define _LOAD_FAST_BORROW_1 442 -#define _LOAD_FAST_BORROW_2 443 -#define _LOAD_FAST_BORROW_3 444 -#define _LOAD_FAST_BORROW_4 445 -#define _LOAD_FAST_BORROW_5 446 -#define _LOAD_FAST_BORROW_6 447 -#define _LOAD_FAST_BORROW_7 448 +#define _LOAD_FAST_BORROW 441 +#define _LOAD_FAST_BORROW_0 442 +#define _LOAD_FAST_BORROW_1 443 +#define _LOAD_FAST_BORROW_2 444 +#define _LOAD_FAST_BORROW_3 445 +#define _LOAD_FAST_BORROW_4 446 +#define _LOAD_FAST_BORROW_5 447 +#define _LOAD_FAST_BORROW_6 448 +#define _LOAD_FAST_BORROW_7 449 #define _LOAD_FAST_BORROW_LOAD_FAST_BORROW LOAD_FAST_BORROW_LOAD_FAST_BORROW #define _LOAD_FAST_CHECK LOAD_FAST_CHECK #define _LOAD_FAST_LOAD_FAST LOAD_FAST_LOAD_FAST #define _LOAD_FROM_DICT_OR_DEREF LOAD_FROM_DICT_OR_DEREF #define _LOAD_FROM_DICT_OR_GLOBALS LOAD_FROM_DICT_OR_GLOBALS -#define _LOAD_GLOBAL 449 -#define _LOAD_GLOBAL_BUILTINS 450 -#define _LOAD_GLOBAL_MODULE 451 +#define _LOAD_GLOBAL 450 +#define _LOAD_GLOBAL_BUILTINS 451 +#define _LOAD_GLOBAL_MODULE 452 #define _LOAD_LOCALS LOAD_LOCALS #define _LOAD_NAME LOAD_NAME -#define _LOAD_SMALL_INT 452 -#define _LOAD_SMALL_INT_0 453 -#define _LOAD_SMALL_INT_1 454 -#define _LOAD_SMALL_INT_2 455 -#define _LOAD_SMALL_INT_3 456 +#define _LOAD_SMALL_INT 453 +#define _LOAD_SMALL_INT_0 454 +#define _LOAD_SMALL_INT_1 455 +#define _LOAD_SMALL_INT_2 456 +#define _LOAD_SMALL_INT_3 457 #define _LOAD_SPECIAL LOAD_SPECIAL #define _LOAD_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR #define _LOAD_SUPER_ATTR_METHOD LOAD_SUPER_ATTR_METHOD -#define _MAKE_CALLARGS_A_TUPLE 457 +#define _MAKE_CALLARGS_A_TUPLE 458 #define _MAKE_CELL MAKE_CELL #define _MAKE_FUNCTION MAKE_FUNCTION -#define _MAKE_WARM 458 +#define _MAKE_WARM 459 #define _MAP_ADD MAP_ADD #define _MATCH_CLASS MATCH_CLASS #define _MATCH_KEYS MATCH_KEYS #define _MATCH_MAPPING MATCH_MAPPING #define _MATCH_SEQUENCE MATCH_SEQUENCE -#define _MAYBE_EXPAND_METHOD 459 -#define _MAYBE_EXPAND_METHOD_KW 460 -#define _MONITOR_CALL 461 -#define _MONITOR_CALL_KW 462 -#define _MONITOR_JUMP_BACKWARD 463 -#define _MONITOR_RESUME 464 +#define _MAYBE_EXPAND_METHOD 460 +#define _MAYBE_EXPAND_METHOD_KW 461 +#define _MONITOR_CALL 462 +#define _MONITOR_CALL_KW 463 +#define _MONITOR_JUMP_BACKWARD 464 +#define _MONITOR_RESUME 465 #define _NOP NOP #define _POP_EXCEPT POP_EXCEPT -#define _POP_JUMP_IF_FALSE 465 -#define _POP_JUMP_IF_TRUE 466 +#define _POP_JUMP_IF_FALSE 466 +#define _POP_JUMP_IF_TRUE 467 #define _POP_TOP POP_TOP -#define _POP_TOP_LOAD_CONST_INLINE 467 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW 468 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW 469 +#define _POP_TOP_LOAD_CONST_INLINE 468 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW 469 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW 470 #define _PUSH_EXC_INFO PUSH_EXC_INFO -#define _PUSH_FRAME 470 +#define _PUSH_FRAME 471 #define _PUSH_NULL PUSH_NULL -#define _PUSH_NULL_CONDITIONAL 471 -#define _PY_FRAME_GENERAL 472 -#define _PY_FRAME_KW 473 -#define _QUICKEN_RESUME 474 -#define _REPLACE_WITH_TRUE 475 +#define _PUSH_NULL_CONDITIONAL 472 +#define _PY_FRAME_GENERAL 473 +#define _PY_FRAME_KW 474 +#define _QUICKEN_RESUME 475 +#define _REPLACE_WITH_TRUE 476 #define _RESUME_CHECK RESUME_CHECK #define _RETURN_GENERATOR RETURN_GENERATOR #define _RETURN_VALUE RETURN_VALUE -#define _SAVE_RETURN_OFFSET 476 -#define _SEND 477 -#define _SEND_GEN_FRAME 478 +#define _SAVE_RETURN_OFFSET 477 +#define _SEND 478 +#define _SEND_GEN_FRAME 479 #define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS #define _SET_ADD SET_ADD #define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE #define _SET_UPDATE SET_UPDATE -#define _START_EXECUTOR 479 -#define _STORE_ATTR 480 -#define _STORE_ATTR_INSTANCE_VALUE 481 -#define _STORE_ATTR_SLOT 482 -#define _STORE_ATTR_WITH_HINT 483 +#define _START_EXECUTOR 480 +#define _STORE_ATTR 481 +#define _STORE_ATTR_INSTANCE_VALUE 482 +#define _STORE_ATTR_SLOT 483 +#define _STORE_ATTR_WITH_HINT 484 #define _STORE_DEREF STORE_DEREF -#define _STORE_FAST 484 -#define _STORE_FAST_0 485 -#define _STORE_FAST_1 486 -#define _STORE_FAST_2 487 -#define _STORE_FAST_3 488 -#define _STORE_FAST_4 489 -#define _STORE_FAST_5 490 -#define _STORE_FAST_6 491 -#define _STORE_FAST_7 492 +#define _STORE_FAST 485 +#define _STORE_FAST_0 486 +#define _STORE_FAST_1 487 +#define _STORE_FAST_2 488 +#define _STORE_FAST_3 489 +#define _STORE_FAST_4 490 +#define _STORE_FAST_5 491 +#define _STORE_FAST_6 492 +#define _STORE_FAST_7 493 #define _STORE_FAST_LOAD_FAST STORE_FAST_LOAD_FAST #define _STORE_FAST_STORE_FAST STORE_FAST_STORE_FAST #define _STORE_GLOBAL STORE_GLOBAL #define _STORE_NAME STORE_NAME -#define _STORE_SLICE 493 -#define _STORE_SUBSCR 494 -#define _STORE_SUBSCR_DICT 495 -#define _STORE_SUBSCR_LIST_INT 496 +#define _STORE_SLICE 494 +#define _STORE_SUBSCR 495 +#define _STORE_SUBSCR_DICT 496 +#define _STORE_SUBSCR_LIST_INT 497 #define _SWAP SWAP -#define _TIER2_RESUME_CHECK 497 -#define _TO_BOOL 498 +#define _TIER2_RESUME_CHECK 498 +#define _TO_BOOL 499 #define _TO_BOOL_BOOL TO_BOOL_BOOL #define _TO_BOOL_INT TO_BOOL_INT -#define _TO_BOOL_LIST 499 +#define _TO_BOOL_LIST 500 #define _TO_BOOL_NONE TO_BOOL_NONE -#define _TO_BOOL_STR 500 +#define _TO_BOOL_STR 501 #define _UNARY_INVERT UNARY_INVERT #define _UNARY_NEGATIVE UNARY_NEGATIVE #define _UNARY_NOT UNARY_NOT #define _UNPACK_EX UNPACK_EX -#define _UNPACK_SEQUENCE 501 -#define _UNPACK_SEQUENCE_LIST 502 -#define _UNPACK_SEQUENCE_TUPLE 503 -#define _UNPACK_SEQUENCE_TWO_TUPLE 504 +#define _UNPACK_SEQUENCE 502 +#define _UNPACK_SEQUENCE_LIST 503 +#define _UNPACK_SEQUENCE_TUPLE 504 +#define _UNPACK_SEQUENCE_TWO_TUPLE 505 #define _WITH_EXCEPT_START WITH_EXCEPT_START #define _YIELD_VALUE YIELD_VALUE -#define MAX_UOP_ID 504 +#define MAX_UOP_ID 505 #ifdef __cplusplus } diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index 874756770c1871..83fea7d9d6fff7 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -233,6 +233,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_CHECK_PEP_523] = HAS_DEOPT_FLAG, [_CHECK_FUNCTION_EXACT_ARGS] = HAS_ARG_FLAG | HAS_EXIT_FLAG, [_CHECK_STACK_SPACE] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, + [_CHECK_RECURSION_REMAINING] = HAS_DEOPT_FLAG, [_INIT_CALL_PY_EXACT_ARGS_0] = HAS_PURE_FLAG, [_INIT_CALL_PY_EXACT_ARGS_1] = HAS_PURE_FLAG, [_INIT_CALL_PY_EXACT_ARGS_2] = HAS_PURE_FLAG, @@ -368,6 +369,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = { [_CHECK_PEP_523] = "_CHECK_PEP_523", [_CHECK_PERIODIC] = "_CHECK_PERIODIC", [_CHECK_PERIODIC_IF_NOT_YIELD_FROM] = "_CHECK_PERIODIC_IF_NOT_YIELD_FROM", + [_CHECK_RECURSION_REMAINING] = "_CHECK_RECURSION_REMAINING", [_CHECK_STACK_SPACE] = "_CHECK_STACK_SPACE", [_CHECK_STACK_SPACE_OPERAND] = "_CHECK_STACK_SPACE_OPERAND", [_CHECK_VALIDITY] = "_CHECK_VALIDITY", @@ -1018,6 +1020,8 @@ int _PyUop_num_popped(int opcode, int oparg) return 0; case _CHECK_STACK_SPACE: return 0; + case _CHECK_RECURSION_REMAINING: + return 0; case _INIT_CALL_PY_EXACT_ARGS_0: return 2 + oparg; case _INIT_CALL_PY_EXACT_ARGS_1: diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 3b6ef165db7f24..08d40b8d71a2c0 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -3797,7 +3797,7 @@ dummy_func( unused/1 + // Skip over the counter _CHECK_PEP_523 + _CHECK_FUNCTION_VERSION + - _CHECK_STACK_SPACE + + _CHECK_RECURSION_REMAINING + _PY_FRAME_GENERAL + _SAVE_RETURN_OFFSET + _PUSH_FRAME; @@ -3829,7 +3829,7 @@ dummy_func( _CHECK_METHOD_VERSION + _EXPAND_METHOD + flush + // so that self is in the argument array - _CHECK_STACK_SPACE + + _CHECK_RECURSION_REMAINING + _PY_FRAME_GENERAL + _SAVE_RETURN_OFFSET + _PUSH_FRAME; @@ -3908,6 +3908,9 @@ dummy_func( PyFunctionObject *func = (PyFunctionObject *)callable_o; PyCodeObject *code = (PyCodeObject *)func->func_code; DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize)); + } + + op(_CHECK_RECURSION_REMAINING, (--)) { DEOPT_IF(tstate->py_recursion_remaining <= 1); } @@ -3949,6 +3952,7 @@ dummy_func( _CHECK_FUNCTION_VERSION + _CHECK_FUNCTION_EXACT_ARGS + _CHECK_STACK_SPACE + + _CHECK_RECURSION_REMAINING + _INIT_CALL_PY_EXACT_ARGS + _SAVE_RETURN_OFFSET + _PUSH_FRAME; @@ -3959,6 +3963,7 @@ dummy_func( _CHECK_FUNCTION_VERSION + _CHECK_FUNCTION_EXACT_ARGS + _CHECK_STACK_SPACE + + _CHECK_RECURSION_REMAINING + _INIT_CALL_PY_EXACT_ARGS + _SAVE_RETURN_OFFSET + _PUSH_FRAME; diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index cd265c383bd380..1952b71b1526b2 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -4960,6 +4960,10 @@ UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); } + break; + } + + case _CHECK_RECURSION_REMAINING: { if (tstate->py_recursion_remaining <= 1) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 08d0a80a1e6863..3cb4bd632ba4f2 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -1739,6 +1739,9 @@ assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } + } + // _CHECK_RECURSION_REMAINING + { if (tstate->py_recursion_remaining <= 1) { UPDATE_MISS_STATS(CALL); assert(_PyOpcode_Deopt[opcode] == (CALL)); @@ -1854,16 +1857,8 @@ stack_pointer = _PyFrame_GetStackPointer(frame); } // flush - // _CHECK_STACK_SPACE + // _CHECK_RECURSION_REMAINING { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - PyFunctionObject *func = (PyFunctionObject *)callable_o; - PyCodeObject *code = (PyCodeObject *)func->func_code; - if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); - } if (tstate->py_recursion_remaining <= 1) { UPDATE_MISS_STATS(CALL); assert(_PyOpcode_Deopt[opcode] == (CALL)); @@ -4016,6 +4011,9 @@ assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } + } + // _CHECK_RECURSION_REMAINING + { if (tstate->py_recursion_remaining <= 1) { UPDATE_MISS_STATS(CALL); assert(_PyOpcode_Deopt[opcode] == (CALL)); @@ -4102,16 +4100,8 @@ JUMP_TO_PREDICTED(CALL); } } - // _CHECK_STACK_SPACE + // _CHECK_RECURSION_REMAINING { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - PyFunctionObject *func = (PyFunctionObject *)callable_o; - PyCodeObject *code = (PyCodeObject *)func->func_code; - if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { - UPDATE_MISS_STATS(CALL); - assert(_PyOpcode_Deopt[opcode] == (CALL)); - JUMP_TO_PREDICTED(CALL); - } if (tstate->py_recursion_remaining <= 1) { UPDATE_MISS_STATS(CALL); assert(_PyOpcode_Deopt[opcode] == (CALL)); diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 828f0943a8db86..27ebbc9b545e7d 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -1784,6 +1784,10 @@ break; } + case _CHECK_RECURSION_REMAINING: { + break; + } + case _INIT_CALL_PY_EXACT_ARGS: { JitOptSymbol **args; JitOptSymbol *self_or_null;