From a9d68f383b3a8fe97f8fe25eec2e31493f4408a3 Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Thu, 5 Sep 2024 10:56:07 -0700 Subject: [PATCH 1/2] [3.13] GH-123545: Remove duplicate Py_DECREF when handling _PyOptimizer_Optimize errors (GH-123546) (cherry picked from commit 1fbc118c5d3916e920a57cda3cb6d9a0292de26e) Co-authored-by: Savannah Ostrowski --- ...-09-01-00-02-05.gh-issue-123545.8nQNbL.rst | 1 + Python/bytecodes.c | 52 ++++++++++++++++-- Python/executor_cases.c.h | 53 ++++++++++++++++++- 3 files changed, 100 insertions(+), 6 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2024-09-01-00-02-05.gh-issue-123545.8nQNbL.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-09-01-00-02-05.gh-issue-123545.8nQNbL.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-09-01-00-02-05.gh-issue-123545.8nQNbL.rst new file mode 100644 index 00000000000000..4da4151416d13c --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2024-09-01-00-02-05.gh-issue-123545.8nQNbL.rst @@ -0,0 +1 @@ +Fix a double decref in rare cases on experimental JIT builds. diff --git a/Python/bytecodes.c b/Python/bytecodes.c index d9533110af20ed..7cd0cfa840b4eb 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -4224,8 +4224,54 @@ dummy_func( #endif } - tier2 op(_EXIT_TRACE, (--)) { - EXIT_TO_TRACE(); + tier2 op(_EXIT_TRACE, (exit_p/4 --)) { + _PyExitData *exit = (_PyExitData *)exit_p; + PyCodeObject *code = _PyFrame_GetCode(frame); + _Py_CODEUNIT *target = _PyCode_CODE(code) + exit->target; + #if defined(Py_DEBUG) && !defined(_Py_JIT) + OPT_HIST(trace_uop_execution_counter, trace_run_length_hist); + if (lltrace >= 2) { + printf("SIDE EXIT: [UOp "); + _PyUOpPrint(&next_uop[-1]); + printf(", exit %u, temp %d, target %d -> %s]\n", + exit - current_executor->exits, exit->temperature.as_counter, + (int)(target - _PyCode_CODE(code)), + _PyOpcode_OpName[target->op.code]); + } + #endif + if (exit->executor && !exit->executor->vm_data.valid) { + exit->temperature = initial_temperature_backoff_counter(); + Py_CLEAR(exit->executor); + } + if (exit->executor == NULL) { + _Py_BackoffCounter temperature = exit->temperature; + if (!backoff_counter_triggers(temperature)) { + exit->temperature = advance_backoff_counter(temperature); + tstate->previous_executor = (PyObject *)current_executor; + GOTO_TIER_ONE(target); + } + _PyExecutorObject *executor; + if (target->op.code == ENTER_EXECUTOR) { + executor = code->co_executors->executors[target->op.arg]; + Py_INCREF(executor); + } + else { + int chain_depth = current_executor->vm_data.chain_depth + 1; + int optimized = _PyOptimizer_Optimize(frame, target, stack_pointer, &executor, chain_depth); + if (optimized <= 0) { + exit->temperature = restart_backoff_counter(temperature); + if (optimized < 0) { + GOTO_UNWIND(); + } + tstate->previous_executor = (PyObject *)current_executor; + GOTO_TIER_ONE(target); + } + } + exit->executor = executor; + } + Py_INCREF(exit->executor); + tstate->previous_executor = (PyObject *)current_executor; + GOTO_TIER_TWO(exit->executor); } tier2 op(_CHECK_VALIDITY, (--)) { @@ -4322,8 +4368,6 @@ dummy_func( if (optimized <= 0) { exit->temperature = restart_backoff_counter(exit->temperature); if (optimized < 0) { - Py_DECREF(current_executor); - tstate->previous_executor = Py_None; GOTO_UNWIND(); } GOTO_TIER_ONE(target); diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 799f3b7f69239a..ead0afb5c32b4e 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -4250,7 +4250,58 @@ } case _EXIT_TRACE: { +<<<<<<< HEAD EXIT_TO_TRACE(); +======= + PyObject *exit_p = (PyObject *)CURRENT_OPERAND(); + _PyExitData *exit = (_PyExitData *)exit_p; + PyCodeObject *code = _PyFrame_GetCode(frame); + _Py_CODEUNIT *target = _PyCode_CODE(code) + exit->target; + #if defined(Py_DEBUG) && !defined(_Py_JIT) + OPT_HIST(trace_uop_execution_counter, trace_run_length_hist); + if (lltrace >= 2) { + printf("SIDE EXIT: [UOp "); + _PyUOpPrint(&next_uop[-1]); + printf(", exit %u, temp %d, target %d -> %s]\n", + exit - current_executor->exits, exit->temperature.as_counter, + (int)(target - _PyCode_CODE(code)), + _PyOpcode_OpName[target->op.code]); + } + #endif + if (exit->executor && !exit->executor->vm_data.valid) { + exit->temperature = initial_temperature_backoff_counter(); + Py_CLEAR(exit->executor); + } + if (exit->executor == NULL) { + _Py_BackoffCounter temperature = exit->temperature; + if (!backoff_counter_triggers(temperature)) { + exit->temperature = advance_backoff_counter(temperature); + tstate->previous_executor = (PyObject *)current_executor; + GOTO_TIER_ONE(target); + } + _PyExecutorObject *executor; + if (target->op.code == ENTER_EXECUTOR) { + executor = code->co_executors->executors[target->op.arg]; + Py_INCREF(executor); + } + else { + int chain_depth = current_executor->vm_data.chain_depth + 1; + int optimized = _PyOptimizer_Optimize(frame, target, stack_pointer, &executor, chain_depth); + if (optimized <= 0) { + exit->temperature = restart_backoff_counter(temperature); + if (optimized < 0) { + GOTO_UNWIND(); + } + tstate->previous_executor = (PyObject *)current_executor; + GOTO_TIER_ONE(target); + } + } + exit->executor = executor; + } + Py_INCREF(exit->executor); + tstate->previous_executor = (PyObject *)current_executor; + GOTO_TIER_TWO(exit->executor); +>>>>>>> 1fbc118c5d (GH-123545: Remove duplicate Py_DECREF when handling _PyOptimizer_Optimize errors (GH-123546)) break; } @@ -4390,8 +4441,6 @@ if (optimized <= 0) { exit->temperature = restart_backoff_counter(exit->temperature); if (optimized < 0) { - Py_DECREF(current_executor); - tstate->previous_executor = Py_None; GOTO_UNWIND(); } GOTO_TIER_ONE(target); From 39acce1f5b62612f80431081d5bfc7cb05afe6a7 Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Thu, 5 Sep 2024 19:31:19 -0700 Subject: [PATCH 2/2] undo --- Python/bytecodes.c | 50 ++------------------------------------ Python/executor_cases.c.h | 51 --------------------------------------- 2 files changed, 2 insertions(+), 99 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 7cd0cfa840b4eb..1e6185d3c9e489 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -4224,54 +4224,8 @@ dummy_func( #endif } - tier2 op(_EXIT_TRACE, (exit_p/4 --)) { - _PyExitData *exit = (_PyExitData *)exit_p; - PyCodeObject *code = _PyFrame_GetCode(frame); - _Py_CODEUNIT *target = _PyCode_CODE(code) + exit->target; - #if defined(Py_DEBUG) && !defined(_Py_JIT) - OPT_HIST(trace_uop_execution_counter, trace_run_length_hist); - if (lltrace >= 2) { - printf("SIDE EXIT: [UOp "); - _PyUOpPrint(&next_uop[-1]); - printf(", exit %u, temp %d, target %d -> %s]\n", - exit - current_executor->exits, exit->temperature.as_counter, - (int)(target - _PyCode_CODE(code)), - _PyOpcode_OpName[target->op.code]); - } - #endif - if (exit->executor && !exit->executor->vm_data.valid) { - exit->temperature = initial_temperature_backoff_counter(); - Py_CLEAR(exit->executor); - } - if (exit->executor == NULL) { - _Py_BackoffCounter temperature = exit->temperature; - if (!backoff_counter_triggers(temperature)) { - exit->temperature = advance_backoff_counter(temperature); - tstate->previous_executor = (PyObject *)current_executor; - GOTO_TIER_ONE(target); - } - _PyExecutorObject *executor; - if (target->op.code == ENTER_EXECUTOR) { - executor = code->co_executors->executors[target->op.arg]; - Py_INCREF(executor); - } - else { - int chain_depth = current_executor->vm_data.chain_depth + 1; - int optimized = _PyOptimizer_Optimize(frame, target, stack_pointer, &executor, chain_depth); - if (optimized <= 0) { - exit->temperature = restart_backoff_counter(temperature); - if (optimized < 0) { - GOTO_UNWIND(); - } - tstate->previous_executor = (PyObject *)current_executor; - GOTO_TIER_ONE(target); - } - } - exit->executor = executor; - } - Py_INCREF(exit->executor); - tstate->previous_executor = (PyObject *)current_executor; - GOTO_TIER_TWO(exit->executor); + tier2 op(_EXIT_TRACE, (--)) { + EXIT_TO_TRACE(); } tier2 op(_CHECK_VALIDITY, (--)) { diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index ead0afb5c32b4e..df7c19a80e40c5 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -4250,58 +4250,7 @@ } case _EXIT_TRACE: { -<<<<<<< HEAD EXIT_TO_TRACE(); -======= - PyObject *exit_p = (PyObject *)CURRENT_OPERAND(); - _PyExitData *exit = (_PyExitData *)exit_p; - PyCodeObject *code = _PyFrame_GetCode(frame); - _Py_CODEUNIT *target = _PyCode_CODE(code) + exit->target; - #if defined(Py_DEBUG) && !defined(_Py_JIT) - OPT_HIST(trace_uop_execution_counter, trace_run_length_hist); - if (lltrace >= 2) { - printf("SIDE EXIT: [UOp "); - _PyUOpPrint(&next_uop[-1]); - printf(", exit %u, temp %d, target %d -> %s]\n", - exit - current_executor->exits, exit->temperature.as_counter, - (int)(target - _PyCode_CODE(code)), - _PyOpcode_OpName[target->op.code]); - } - #endif - if (exit->executor && !exit->executor->vm_data.valid) { - exit->temperature = initial_temperature_backoff_counter(); - Py_CLEAR(exit->executor); - } - if (exit->executor == NULL) { - _Py_BackoffCounter temperature = exit->temperature; - if (!backoff_counter_triggers(temperature)) { - exit->temperature = advance_backoff_counter(temperature); - tstate->previous_executor = (PyObject *)current_executor; - GOTO_TIER_ONE(target); - } - _PyExecutorObject *executor; - if (target->op.code == ENTER_EXECUTOR) { - executor = code->co_executors->executors[target->op.arg]; - Py_INCREF(executor); - } - else { - int chain_depth = current_executor->vm_data.chain_depth + 1; - int optimized = _PyOptimizer_Optimize(frame, target, stack_pointer, &executor, chain_depth); - if (optimized <= 0) { - exit->temperature = restart_backoff_counter(temperature); - if (optimized < 0) { - GOTO_UNWIND(); - } - tstate->previous_executor = (PyObject *)current_executor; - GOTO_TIER_ONE(target); - } - } - exit->executor = executor; - } - Py_INCREF(exit->executor); - tstate->previous_executor = (PyObject *)current_executor; - GOTO_TIER_TWO(exit->executor); ->>>>>>> 1fbc118c5d (GH-123545: Remove duplicate Py_DECREF when handling _PyOptimizer_Optimize errors (GH-123546)) break; }