https://github.com/python/cpython/commit/20aeb3a4631beebd255781ba4932b53011edb011
commit: 20aeb3a4631beebd255781ba4932b53011edb011
branch: main
author: Mark Shannon <[email protected]>
committer: Fidget-Spinner <[email protected]>
date: 2025-12-23T17:19:34Z
summary:
GH-143026: Fix assertion error in executor management. (GH-143104)
files:
M Include/internal/pycore_object.h
M Include/internal/pycore_optimizer.h
M Lib/test/test_capi/test_opt.py
M Python/optimizer.c
M Tools/cases_generator/analyzer.py
diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h
index 6b91e4334b169e..d14cee6af66103 100644
--- a/Include/internal/pycore_object.h
+++ b/Include/internal/pycore_object.h
@@ -252,25 +252,6 @@ _Py_DECREF_SPECIALIZED(PyObject *op, const destructor
destruct)
}
}
-static inline void
-_Py_DECREF_NO_DEALLOC(PyObject *op)
-{
- if (_Py_IsImmortal(op)) {
- _Py_DECREF_IMMORTAL_STAT_INC();
- return;
- }
- _Py_DECREF_STAT_INC();
-#ifdef Py_REF_DEBUG
- _Py_DEC_REFTOTAL(PyInterpreterState_Get());
-#endif
- op->ob_refcnt--;
-#ifdef Py_DEBUG
- if (op->ob_refcnt <= 0) {
- _Py_FatalRefcountError("Expected a positive remaining refcount");
- }
-#endif
-}
-
#else
// TODO: implement Py_DECREF specializations for Py_GIL_DISABLED build
static inline void
@@ -279,12 +260,6 @@ _Py_DECREF_SPECIALIZED(PyObject *op, const destructor
destruct)
Py_DECREF(op);
}
-static inline void
-_Py_DECREF_NO_DEALLOC(PyObject *op)
-{
- Py_DECREF(op);
-}
-
static inline int
_Py_REF_IS_MERGED(Py_ssize_t ob_ref_shared)
{
diff --git a/Include/internal/pycore_optimizer.h
b/Include/internal/pycore_optimizer.h
index 3ee62f1728321d..6a0fc1a59e7965 100644
--- a/Include/internal/pycore_optimizer.h
+++ b/Include/internal/pycore_optimizer.h
@@ -27,6 +27,7 @@ typedef struct {
uint8_t valid;
uint8_t chain_depth; // Must be big enough for MAX_CHAIN_DEPTH - 1.
bool warm;
+ uint8_t pending_deletion;
int32_t index; // Index of ENTER_EXECUTOR (if code isn't NULL,
below).
_PyBloomFilter bloom;
_PyExecutorLinkListNode links;
diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py
index 3d2b61d355a309..16288a447e20fe 100644
--- a/Lib/test/test_capi/test_opt.py
+++ b/Lib/test/test_capi/test_opt.py
@@ -3114,6 +3114,26 @@ def testfunc(n):
self.assertNotIn("_POP_TOP_INT", uops)
self.assertIn("_POP_TOP_NOP", uops)
+ def test_143026(self):
+ # https://github.com/python/cpython/issues/143026
+
+ result = script_helper.run_python_until_end('-c', textwrap.dedent("""
+ import gc
+ thresholds = gc.get_threshold()
+ try:
+ gc.set_threshold(1)
+
+ def f1():
+ for i in range(5000):
+ globals()[''] = i
+
+ f1()
+ finally:
+ gc.set_threshold(*thresholds)
+ """), PYTHON_JIT="1")
+ self.assertEqual(result[0].rc, 0, result)
+
+
def global_identity(x):
return x
diff --git a/Python/optimizer.c b/Python/optimizer.c
index 869889bf2598d8..0f8ddb4ba558d3 100644
--- a/Python/optimizer.c
+++ b/Python/optimizer.c
@@ -310,7 +310,7 @@ _Py_ClearExecutorDeletionList(PyInterpreterState *interp)
while (ts) {
_PyExecutorObject *current = (_PyExecutorObject *)ts->current_executor;
if (current != NULL) {
- _Py_DECREF_NO_DEALLOC((PyObject *)current);
+ Py_DECREF((PyObject *)current);
}
ts = ts->next;
}
@@ -320,6 +320,10 @@ _Py_ClearExecutorDeletionList(PyInterpreterState *interp)
static void
add_to_pending_deletion_list(_PyExecutorObject *self)
{
+ if (self->vm_data.pending_deletion) {
+ return;
+ }
+ self->vm_data.pending_deletion = 1;
PyInterpreterState *interp = PyInterpreterState_Get();
self->vm_data.links.previous = NULL;
self->vm_data.links.next = interp->executor_deletion_list_head;
@@ -627,7 +631,7 @@ _PyJit_translate_single_bytecode_to_trace(
uint32_t target = 0;
target = Py_IsNone((PyObject *)old_code)
- ? (int)(target_instr - _Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS_PTR)
+ ? (uint32_t)(target_instr -
_Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS_PTR)
: INSTR_IP(target_instr, old_code);
// Rewind EXTENDED_ARG so that we see the whole thing.
@@ -1666,6 +1670,7 @@ void
_Py_ExecutorInit(_PyExecutorObject *executor, const _PyBloomFilter
*dependency_set)
{
executor->vm_data.valid = true;
+ executor->vm_data.pending_deletion = 0;
for (int i = 0; i < _Py_BLOOM_FILTER_WORDS; i++) {
executor->vm_data.bloom.bits[i] = dependency_set->bits[i];
}
diff --git a/Tools/cases_generator/analyzer.py
b/Tools/cases_generator/analyzer.py
index 659befe312afaf..2001fb7c37931a 100644
--- a/Tools/cases_generator/analyzer.py
+++ b/Tools/cases_generator/analyzer.py
@@ -673,7 +673,6 @@ def has_error_without_pop(op: parser.CodeDef) -> bool:
"_PyUnicode_Equal",
"_PyUnicode_JoinArray",
"_Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY",
- "_Py_DECREF_NO_DEALLOC",
"_Py_ID",
"_Py_IsImmortal",
"_Py_IsOwnedByCurrentThread",
_______________________________________________
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]