Skip to content

GH-132532: Add new DSL macros to better declare semantics of exits at ends of instructions/uops. #137098

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

markshannon
Copy link
Member

@markshannon markshannon commented Jul 25, 2025

This PR changes adds the ability to de-opt at the end an instruction.
Exits from tier 2 jump to the next instruction in tier 1.
In the case of deopting due to the eval breaker being set, _Py_HandlePending is called before resuming tier 1.

I am taking this approach instead of checking the eval breaker before each call, as this does not cause any observable behavior change. For comparison see https://github.com/python/cpython/compare/main...faster-cpython:cpython:check-periodic-before-call?expand=1, noting the necessary changes to tests and threading module.

Although this approach adds a bit more complexity to the optimizer, it doesn't need any changes to the library or tests.

Copy link
Member

@brandtbucher brandtbucher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems correct. My only issue is with all of the new names... naming is hard.

I feel like the chosen names are a bit hard to parse and reason about, and suggested some alternatives. But they're just suggestions, nothing blocking.

Comment on lines +165 to +170
_Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY();
QSBR_QUIESCENT_STATE(tstate);
if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) {
int err = _Py_HandlePending(tstate);
ERROR_IF(err != 0);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic is now repeated 3 times, and two of them are in identical opcode implementations. Maybe it should be broken out into a static inline helper function?

@@ -5189,32 +5198,28 @@ dummy_func(
op (_GUARD_IS_TRUE_POP, (flag -- )) {
int is_true = PyStackRef_IsTrue(flag);
DEAD(flag);
SYNC_SP();
EXIT_IF(!is_true);
EXIT_IF_AFTER(!is_true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The wording makes this a bit hard to parse: "exit if after not is true"? Maybe use "at end" for consistency with _CHECK_PERIODIC_AT_END, if they mean the same thing? AT_END_EXIT_IF, maybe?

@@ -5380,6 +5385,11 @@ dummy_func(
GOTO_TIER_ONE(_PyFrame_GetBytecode(frame) + CURRENT_TARGET());
}

tier2 op(_PERIODIC, (--)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get that this is "check periodic without the check", but maybe we could find a better name here? _HANDLE_PENDING_AND_DEOPT?

@@ -5391,11 +5401,11 @@ dummy_func(
* ENTER_EXECUTOR will not re-enter tier 2 with the eval breaker set. */
tier2 op(_TIER2_RESUME_CHECK, (--)) {
#if defined(__EMSCRIPTEN__)
DEOPT_IF(_Py_emscripten_signal_clock == 0);
PERIODIC_IF(_Py_emscripten_signal_clock == 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here... Maybe HANDLE_PENDING_AND_DEOPT_IF?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants