summaryrefslogtreecommitdiffstats
path: root/Python/ceval.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/ceval.c')
-rw-r--r--Python/ceval.c70
1 files changed, 1 insertions, 69 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 6ce1a6a..9bcb83f 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -763,68 +763,6 @@ resume_frame:
DISPATCH();
-handle_eval_breaker:
-
- /* Do periodic things, like check for signals and async I/0.
- * We need to do reasonably frequently, but not too frequently.
- * All loops should include a check of the eval breaker.
- * We also check on return from any builtin function.
- *
- * ## More Details ###
- *
- * The eval loop (this function) normally executes the instructions
- * of a code object sequentially. However, the runtime supports a
- * number of out-of-band execution scenarios that may pause that
- * sequential execution long enough to do that out-of-band work
- * in the current thread using the current PyThreadState.
- *
- * The scenarios include:
- *
- * - cyclic garbage collection
- * - GIL drop requests
- * - "async" exceptions
- * - "pending calls" (some only in the main thread)
- * - signal handling (only in the main thread)
- *
- * When the need for one of the above is detected, the eval loop
- * pauses long enough to handle the detected case. Then, if doing
- * so didn't trigger an exception, the eval loop resumes executing
- * the sequential instructions.
- *
- * To make this work, the eval loop periodically checks if any
- * of the above needs to happen. The individual checks can be
- * expensive if computed each time, so a while back we switched
- * to using pre-computed, per-interpreter variables for the checks,
- * and later consolidated that to a single "eval breaker" variable
- * (now a PyInterpreterState field).
- *
- * For the longest time, the eval breaker check would happen
- * frequently, every 5 or so times through the loop, regardless
- * of what instruction ran last or what would run next. Then, in
- * early 2021 (gh-18334, commit 4958f5d), we switched to checking
- * the eval breaker less frequently, by hard-coding the check to
- * specific places in the eval loop (e.g. certain instructions).
- * The intent then was to check after returning from calls
- * and on the back edges of loops.
- *
- * In addition to being more efficient, that approach keeps
- * the eval loop from running arbitrary code between instructions
- * that don't handle that well. (See gh-74174.)
- *
- * Currently, the eval breaker check happens here at the
- * "handle_eval_breaker" label. Some instructions come here
- * explicitly (goto) and some indirectly. Notably, the check
- * happens on back edges in the control flow graph, which
- * pretty much applies to all loops and most calls.
- * (See bytecodes.c for exact information.)
- *
- * One consequence of this approach is that it might not be obvious
- * how to force any specific thread to pick up the eval breaker,
- * or for any specific thread to not pick it up. Mostly this
- * involves judicious uses of locks and careful ordering of code,
- * while avoiding code that might trigger the eval breaker
- * until so desired.
- */
if (_Py_HandlePending(tstate) != 0) {
goto error;
}
@@ -2796,13 +2734,7 @@ _PyUopExecute(_PyExecutorObject *executor, _PyInterpreterFrame *frame, PyObject
PyThreadState *tstate = _PyThreadState_GET();
_PyUOpExecutorObject *self = (_PyUOpExecutorObject *)executor;
- // Equivalent to CHECK_EVAL_BREAKER()
- _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY();
- if (_Py_atomic_load_relaxed_int32(&tstate->interp->ceval.eval_breaker)) {
- if (_Py_HandlePending(tstate) != 0) {
- goto error;
- }
- }
+ CHECK_EVAL_BREAKER();
OBJECT_STAT_INC(optimization_traces_executed);
_Py_CODEUNIT *ip_offset = (_Py_CODEUNIT *)_PyFrame_GetCode(frame)->co_code_adaptive;