// handle before rejoining the rest of the program.
#define MAX_CHAIN_DEPTH 4
+// The maximum number of side exits arising from unpredictable control-flow.
+#define MAX_DYNAMIC_CHAIN_DEPTH 6
+
/* Symbols */
/* See explanation in optimizer_symbols.c */
#ifndef _Py_JIT
assert(current_executor == (_PyExecutorObject*)executor);
#endif
- assert(tstate->jit_exit != NULL || tstate->jit_exit->executor == current_executor);
tstate->current_executor = (PyObject *)executor;
if (!current_executor->vm_data.valid) {
assert(tstate->jit_exit->executor == current_executor);
if (target->op.code == ENTER_EXECUTOR) {
PyCodeObject *code = _PyFrame_GetCode(frame);
executor = code->co_executors->executors[target->op.arg];
- if (executor->trace[2].opcode == _GUARD_EXECUTOR_IP && executor->vm_data.valid) {
+ if (executor->trace[0].opcode == _START_DYNAMIC_EXECUTOR && executor->vm_data.valid) {
Py_INCREF(executor);
assert(tstate->jit_exit == exit);
exit->executor = executor;
#ifndef _Py_JIT
assert(current_executor == (_PyExecutorObject*)executor);
#endif
- assert(tstate->jit_exit != NULL || tstate->jit_exit->executor == current_executor);
tstate->current_executor = (PyObject *)executor;
if (!current_executor->vm_data.valid) {
assert(tstate->jit_exit->executor == current_executor);
if (target->op.code == ENTER_EXECUTOR) {
PyCodeObject *code = _PyFrame_GetCode(frame);
executor = code->co_executors->executors[target->op.arg];
- if (executor->trace[2].opcode == _GUARD_EXECUTOR_IP && executor->vm_data.valid) {
+ if (executor->trace[0].opcode == _START_DYNAMIC_EXECUTOR && executor->vm_data.valid) {
Py_INCREF(executor);
assert(tstate->jit_exit == exit);
exit->executor = executor;
// make progress in order to avoid infinite loops or excessively-long
// side-exit chains. We can only insert the executor into the bytecode if
// this is true, since a deopt won't infinitely re-enter the executor:
- chain_depth %= MAX_CHAIN_DEPTH;
+ if (tstate->interp->jit_state.code_buffer[0].opcode == _START_DYNAMIC_EXECUTOR) {
+ chain_depth %= MAX_DYNAMIC_CHAIN_DEPTH;
+ }
+ else {
+ chain_depth %= MAX_CHAIN_DEPTH;
+ }
bool progress_needed = chain_depth == 0;
PyCodeObject *code = (PyCodeObject *)tstate->interp->jit_state.initial_code;
_Py_CODEUNIT *start = tstate->interp->jit_state.insert_exec_instr;
if (oparg > 0xFFFF) {
return 0;
}
- // Dynamic exits with progress is wonky.
- if (is_dynamic_target && chain_depth >= MAX_CHAIN_DEPTH) {
- return 0;
- }
+
PyCodeObject *code = _PyFrame_GetCode(frame);
#ifdef Py_DEBUG
char *python_lltrace = Py_GETENV("PYTHON_LLTRACE");