diff options
author | Mark Shannon <mark@hotpy.org> | 2023-09-07 13:39:03 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-07 13:39:03 (GMT) |
commit | 0858328ca2457ae95715eb93e347d5c0547bec6f (patch) | |
tree | 35c18050d74c747699f30e9862fd4a63fb14eaa7 /Python | |
parent | d485551c9d1792ff3539eef1d6374bd4c01dcd5d (diff) | |
download | cpython-0858328ca2457ae95715eb93e347d5c0547bec6f.zip cpython-0858328ca2457ae95715eb93e347d5c0547bec6f.tar.gz cpython-0858328ca2457ae95715eb93e347d5c0547bec6f.tar.bz2 |
GH-108614: Add `RESUME_CHECK` instruction (GH-108630)
Diffstat (limited to 'Python')
-rw-r--r-- | Python/abstract_interp_cases.c.h | 2 | ||||
-rw-r--r-- | Python/bytecodes.c | 29 | ||||
-rw-r--r-- | Python/ceval_macros.h | 2 | ||||
-rw-r--r-- | Python/emscripten_signal.c | 8 | ||||
-rw-r--r-- | Python/executor_cases.c.h | 25 | ||||
-rw-r--r-- | Python/generated_cases.c.h | 28 | ||||
-rw-r--r-- | Python/opcode_targets.h | 4 |
7 files changed, 58 insertions, 40 deletions
diff --git a/Python/abstract_interp_cases.c.h b/Python/abstract_interp_cases.c.h index 07e8a71..11fbf44 100644 --- a/Python/abstract_interp_cases.c.h +++ b/Python/abstract_interp_cases.c.h @@ -7,7 +7,7 @@ break; } - case RESUME: { + case RESUME_CHECK: { break; } diff --git a/Python/bytecodes.c b/Python/bytecodes.c index fae1da3..8820b52 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -132,24 +132,37 @@ dummy_func( inst(NOP, (--)) { } + family(RESUME, 0) = { + RESUME_CHECK, + }; + inst(RESUME, (--)) { + TIER_ONE_ONLY assert(frame == tstate->current_frame); - /* Possibly combine this with eval breaker */ if (_PyFrame_GetCode(frame)->_co_instrumentation_version != tstate->interp->monitoring_version) { int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp); ERROR_IF(err, error); - #if TIER_ONE next_instr--; - #endif - #if TIER_TWO - goto deoptimize; - #endif } - else if (oparg < 2) { - CHECK_EVAL_BREAKER(); + else { + if (oparg < 2) { + CHECK_EVAL_BREAKER(); + } + next_instr[-1].op.code = RESUME_CHECK; } } + inst(RESUME_CHECK, (--)) { +#if defined(__EMSCRIPTEN__) + DEOPT_IF(emscripten_signal_clock == 0, RESUME); + emscripten_signal_clock -= Py_EMSCRIPTEN_SIGNAL_HANDLING; +#endif + /* Possibly combine these two checks */ + DEOPT_IF(_PyFrame_GetCode(frame)->_co_instrumentation_version + != tstate->interp->monitoring_version, RESUME); + DEOPT_IF(_Py_atomic_load_relaxed_int32(&tstate->interp->ceval.eval_breaker), RESUME); + } + inst(INSTRUMENTED_RESUME, (--)) { /* Possible performance enhancement: * We need to check the eval breaker anyway, can we diff --git a/Python/ceval_macros.h b/Python/ceval_macros.h index 81fbb79..f5d9155 100644 --- a/Python/ceval_macros.h +++ b/Python/ceval_macros.h @@ -374,6 +374,8 @@ static inline void _Py_LeaveRecursiveCallPy(PyThreadState *tstate) { tstate->py_recursion_remaining++; } +/* Marker to specify tier 1 only instructions */ +#define TIER_ONE_ONLY /* Implementation of "macros" that modify the instruction pointer, * stack pointer, or frame pointer. diff --git a/Python/emscripten_signal.c b/Python/emscripten_signal.c index d617ddf..1a19638 100644 --- a/Python/emscripten_signal.c +++ b/Python/emscripten_signal.c @@ -38,19 +38,17 @@ _Py_CheckEmscriptenSignals(void) } } - #define PY_EMSCRIPTEN_SIGNAL_INTERVAL 50 static int emscripten_signal_clock = PY_EMSCRIPTEN_SIGNAL_INTERVAL; void _Py_CheckEmscriptenSignalsPeriodically(void) { - if (!Py_EMSCRIPTEN_SIGNAL_HANDLING) { - return; - } - emscripten_signal_clock--; if (emscripten_signal_clock == 0) { emscripten_signal_clock = PY_EMSCRIPTEN_SIGNAL_INTERVAL; _Py_CheckEmscriptenSignals(); } + else if (Py_EMSCRIPTEN_SIGNAL_HANDLING) { + emscripten_signal_clock--; + } } diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 0d5606f..f4c526a 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -7,22 +7,15 @@ break; } - case RESUME: { - assert(frame == tstate->current_frame); - /* Possibly combine this with eval breaker */ - if (_PyFrame_GetCode(frame)->_co_instrumentation_version != tstate->interp->monitoring_version) { - int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp); - if (err) goto error; - #if TIER_ONE - next_instr--; - #endif - #if TIER_TWO - goto deoptimize; - #endif - } - else if (oparg < 2) { - CHECK_EVAL_BREAKER(); - } + case RESUME_CHECK: { +#if defined(__EMSCRIPTEN__) + DEOPT_IF(emscripten_signal_clock == 0, RESUME); + emscripten_signal_clock -= Py_EMSCRIPTEN_SIGNAL_HANDLING; +#endif + /* Possibly combine these two checks */ + DEOPT_IF(_PyFrame_GetCode(frame)->_co_instrumentation_version + != tstate->interp->monitoring_version, RESUME); + DEOPT_IF(_Py_atomic_load_relaxed_int32(&tstate->interp->ceval.eval_breaker), RESUME); break; } diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 34cea84..84f83db 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -8,24 +8,36 @@ } TARGET(RESUME) { + PREDICTED(RESUME); + static_assert(0 == 0, "incorrect cache size"); + TIER_ONE_ONLY assert(frame == tstate->current_frame); - /* Possibly combine this with eval breaker */ if (_PyFrame_GetCode(frame)->_co_instrumentation_version != tstate->interp->monitoring_version) { int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp); if (err) goto error; - #if TIER_ONE next_instr--; - #endif - #if TIER_TWO - goto deoptimize; - #endif } - else if (oparg < 2) { - CHECK_EVAL_BREAKER(); + else { + if (oparg < 2) { + CHECK_EVAL_BREAKER(); + } + next_instr[-1].op.code = RESUME_CHECK; } DISPATCH(); } + TARGET(RESUME_CHECK) { +#if defined(__EMSCRIPTEN__) + DEOPT_IF(emscripten_signal_clock == 0, RESUME); + emscripten_signal_clock -= Py_EMSCRIPTEN_SIGNAL_HANDLING; +#endif + /* Possibly combine these two checks */ + DEOPT_IF(_PyFrame_GetCode(frame)->_co_instrumentation_version + != tstate->interp->monitoring_version, RESUME); + DEOPT_IF(_Py_atomic_load_relaxed_int32(&tstate->interp->ceval.eval_breaker), RESUME); + DISPATCH(); + } + TARGET(INSTRUMENTED_RESUME) { /* Possible performance enhancement: * We need to check the eval breaker anyway, can we diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 305eb0b..413bb88 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -46,6 +46,7 @@ static void *opcode_targets[256] = { &&TARGET_POP_TOP, &&TARGET_PUSH_EXC_INFO, &&TARGET_PUSH_NULL, + &&TARGET_RESUME_CHECK, &&TARGET_RETURN_GENERATOR, &&TARGET_RETURN_VALUE, &&TARGET_SETUP_ANNOTATIONS, @@ -164,8 +165,8 @@ static void *opcode_targets[256] = { &&TARGET_POP_JUMP_IF_NOT_NONE, &&TARGET_POP_JUMP_IF_TRUE, &&TARGET_RAISE_VARARGS, - &&TARGET_RERAISE, &&TARGET_RESUME, + &&TARGET_RERAISE, &&TARGET_RETURN_CONST, &&TARGET_SEND, &&TARGET_SEND_GEN, @@ -235,7 +236,6 @@ static void *opcode_targets[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, - &&_unknown_opcode, &&TARGET_INSTRUMENTED_RESUME, &&TARGET_INSTRUMENTED_END_FOR, &&TARGET_INSTRUMENTED_END_SEND, |