mirror of https://github.com/python/cpython
GH-118093: Remove invalidated executors from side exits (GH-121885)
This commit is contained in:
parent
e9681211b9
commit
794546fd53
|
@ -260,7 +260,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {
|
|||
[_CHECK_FUNCTION] = HAS_DEOPT_FLAG,
|
||||
[_INTERNAL_INCREMENT_OPT_COUNTER] = 0,
|
||||
[_DYNAMIC_EXIT] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG,
|
||||
[_START_EXECUTOR] = HAS_DEOPT_FLAG,
|
||||
[_START_EXECUTOR] = 0,
|
||||
[_FATAL_ERROR] = 0,
|
||||
[_CHECK_VALIDITY_AND_SET_IP] = HAS_DEOPT_FLAG,
|
||||
[_DEOPT] = 0,
|
||||
|
|
|
@ -4624,6 +4624,10 @@ dummy_func(
|
|||
_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)) {
|
||||
|
@ -4743,7 +4747,7 @@ dummy_func(
|
|||
#ifndef _Py_JIT
|
||||
current_executor = (_PyExecutorObject*)executor;
|
||||
#endif
|
||||
DEOPT_IF(!((_PyExecutorObject *)executor)->vm_data.valid);
|
||||
assert(((_PyExecutorObject *)executor)->vm_data.valid);
|
||||
}
|
||||
|
||||
tier2 op(_FATAL_ERROR, (--)) {
|
||||
|
|
|
@ -4986,6 +4986,10 @@
|
|||
_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)) {
|
||||
|
@ -5156,10 +5160,7 @@
|
|||
#ifndef _Py_JIT
|
||||
current_executor = (_PyExecutorObject*)executor;
|
||||
#endif
|
||||
if (!((_PyExecutorObject *)executor)->vm_data.valid) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
assert(((_PyExecutorObject *)executor)->vm_data.valid);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -1587,42 +1587,36 @@ _Py_Executors_InvalidateDependency(PyInterpreterState *interp, void *obj, int is
|
|||
_Py_BloomFilter_Add(&obj_filter, obj);
|
||||
/* Walk the list of executors */
|
||||
/* TO DO -- Use a tree to avoid traversing as many objects */
|
||||
bool no_memory = false;
|
||||
PyObject *invalidate = PyList_New(0);
|
||||
if (invalidate == NULL) {
|
||||
PyErr_Clear();
|
||||
no_memory = true;
|
||||
goto error;
|
||||
}
|
||||
/* Clearing an executor can deallocate others, so we need to make a list of
|
||||
* executors to invalidate first */
|
||||
for (_PyExecutorObject *exec = interp->executor_list_head; exec != NULL;) {
|
||||
assert(exec->vm_data.valid);
|
||||
_PyExecutorObject *next = exec->vm_data.links.next;
|
||||
if (bloom_filter_may_contain(&exec->vm_data.bloom, &obj_filter)) {
|
||||
unlink_executor(exec);
|
||||
if (no_memory) {
|
||||
exec->vm_data.valid = 0;
|
||||
} else {
|
||||
if (PyList_Append(invalidate, (PyObject *)exec) < 0) {
|
||||
PyErr_Clear();
|
||||
no_memory = true;
|
||||
exec->vm_data.valid = 0;
|
||||
if (bloom_filter_may_contain(&exec->vm_data.bloom, &obj_filter) &&
|
||||
PyList_Append(invalidate, (PyObject *)exec))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
exec = next;
|
||||
}
|
||||
for (Py_ssize_t i = 0; i < PyList_GET_SIZE(invalidate); i++) {
|
||||
_PyExecutorObject *exec = (_PyExecutorObject *)PyList_GET_ITEM(invalidate, i);
|
||||
executor_clear(exec);
|
||||
if (is_invalidation) {
|
||||
OPT_STAT_INC(executors_invalidated);
|
||||
}
|
||||
}
|
||||
exec = next;
|
||||
}
|
||||
if (invalidate != NULL) {
|
||||
for (Py_ssize_t i = 0; i < PyList_GET_SIZE(invalidate); i++) {
|
||||
_PyExecutorObject *exec = (_PyExecutorObject *)PyList_GET_ITEM(invalidate, i);
|
||||
executor_clear(exec);
|
||||
}
|
||||
Py_DECREF(invalidate);
|
||||
}
|
||||
return;
|
||||
error:
|
||||
PyErr_Clear();
|
||||
Py_XDECREF(invalidate);
|
||||
// If we're truly out of memory, wiping out everything is a fine fallback:
|
||||
_Py_Executors_InvalidateAll(interp, is_invalidation);
|
||||
}
|
||||
|
||||
/* Invalidate all executors */
|
||||
|
|
Loading…
Reference in New Issue