[_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,
_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)) {
#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, (--)) {
_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)) {
#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;
}
_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 (is_invalidation) {
- OPT_STAT_INC(executors_invalidated);
- }
+ if (bloom_filter_may_contain(&exec->vm_data.bloom, &obj_filter) &&
+ PyList_Append(invalidate, (PyObject *)exec))
+ {
+ goto error;
}
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);
+ 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);
}
- Py_DECREF(invalidate);
}
+ 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 */