8000 GH-129709: Clean up tier two by brandtbucher · Pull Request #129710 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

GH-129709: Clean up tier two #129710

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

Merged
merged 5 commits into from
Feb 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Include/internal/pycore_uop_metadata.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 16 additions & 24 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -3526,6 +3526,7 @@ dummy_func(
}

op(_MAYBE_EXPAND_METHOD, (callable[1], self_or_null[1], args[oparg] -- func[1], maybe_self[1], args[oparg])) {
(void)args;
if (PyStackRef_TYPE(callable[0]) == &PyMethod_Type && PyStackRef_IsNull(self_or_null[0])) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
PyObject *self = ((PyMethodObject *)callable_o)->im_self;
Expand Down Expand Up @@ -3892,6 +3893,7 @@ dummy_func(
_CHECK_PERIODIC;

op(_CHECK_AND_ALLOCATE_OBJECT, (type_version/2, callable[1], null[1], args[oparg] -- init[1], self[1], args[oparg])) {
(void)args;
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
DEOPT_IF(!PyStackRef_IsNull(null[0]));
DEOPT_IF(!PyType_Check(callable_o));
Expand Down Expand Up @@ -4119,7 +4121,7 @@ dummy_func(
PyObject *res_o = PyLong_FromSsize_t(len_i);
assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
if (res_o == NULL) {
GOTO_ERROR(error);
ERROR_NO_POP();
}
PyStackRef_CLOSE(arg_stackref);
DEAD(args);
Expand Down Expand Up @@ -4364,6 +4366,7 @@ dummy_func(
}

op(_MAYBE_EXPAND_METHOD_KW, (callable[1], self_or_null[1], args[oparg], kwnames_in -- func[1], maybe_self[1], args[oparg], kwnames_out)) {
(void)args;
if (PyStackRef_TYPE(callable[0]) == &PyMethod_Type && PyStackRef_IsNull(self_or_null[0])) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
PyObject *self = ((PyMethodObject *)callable_o)->im_self;
Expand Down Expand Up @@ -5022,7 +5025,7 @@ dummy_func(
if (frame->lltrace >= 2) {
printf("SIDE EXIT: [UOp ");
_PyUOpPrint(&next_uop[-1]);
printf(", exit %u, temp %d, target %d -> %s]\n",
printf(", exit %lu, temp %d, target %d -> %s]\n",
exit - current_executor->exits, exit->temperature.value_and_backoff,
(int)(target - _PyFrame_GetBytecode(frame)),
_PyOpcode_OpName[target->op.code]);
Expand All @@ -5032,11 +5035,11 @@ dummy_func(
exit->temperature = initial_temperature_backoff_counter();
Py_CLEAR(exit->executor);
}
tstate->previous_executor = (PyObject *)current_executor;
if (exit->executor == NULL) {
_Py_BackoffCounter temperature = exit->temperature;
if (!backoff_counter_triggers(temperature)) {
exit->temperature = advance_backoff_counter(temperature);
tstate->previous_executor = (PyObject *)current_executor;
GOTO_TIER_ONE(target);
}
_PyExecutorObject *executor;
Expand All @@ -5049,20 +5052,13 @@ dummy_func(
int optimized = _PyOptimizer_Optimize(frame, target, &executor, chain_depth);
if (optimized <= 0) {
exit->temperature = restart_backoff_counter(temperature);
if (optimized < 0) {
GOTO_UNWIND();
}
tstate->previous_executor = (PyObject *)current_executor;
GOTO_TIER_ONE(target);
}
else {
exit->temperature = initial_temperature_backoff_counter();
GOTO_TIER_ONE(optimized < 0 ? NULL : target);
}
exit->temperature = initial_temperature_backoff_counter();
}
exit->executor = executor;
}
Py_INCREF(exit->executor);
tstate->previous_executor = (PyObject *)current_executor;
GOTO_TIER_TWO(exit->executor);
}

Expand Down Expand Up @@ -5130,7 +5126,7 @@ dummy_func(
if (frame->lltrace >= 2) {
printf("DYNAMIC EXIT: [UOp ");
_PyUOpPrint(&next_uop[-1]);
printf(", exit %u, temp %d, target %d -> %s]\n",
printf(", exit %lu, temp %d, target %d -> %s]\n",
exit - current_executor->exits, exit->temperature.value_and_backoff,
(int)(target - _PyFrame_GetBytecode(frame)),
_PyOpcode_OpName[target->op.code]);
Expand All @@ -5150,21 +5146,15 @@ dummy_func(
int optimized = _PyOptimizer_Optimize(frame, target, &executor, 0);
if (optimized <= 0) {
exit->temperature = restart_backoff_counter(exit->temperature);
if (optimized < 0) {
GOTO_UNWIND();
}
GOTO_TIER_ONE(target);
}
else {
exit->temperature = initial_temperature_backoff_counter();
GOTO_TIER_ONE(optimized < 0 ? NULL : target);
}
exit->temperature = initial_temperature_backoff_counter();
}
GOTO_TIER_TWO(executor);
}

tier2 op(_START_EXECUTOR, (executor/4 --)) {
Py_DECREF(tstate->previous_executor);
tstate->previous_executor = NULL;
Py_CLEAR(tstate->previous_executor);
#ifndef _Py_JIT
current_executor = (_PyExecutorObject*)executor;
#endif
Expand All @@ -5190,14 +5180,16 @@ dummy_func(
}

tier2 op(_DEOPT, (--)) {
EXIT_TO_TIER1();
tstate->previous_executor = (PyObject *)current_executor;
GOTO_TIER_ONE(_PyFrame_GetBytecode(frame) + CURRENT_TARGET());
}

tier2 op(_ERROR_POP_N, (target/2 --)) {
tstate->previous_executor = (PyObject *)current_executor;
assert(oparg == 0);
frame->instr_ptr = _PyFrame_GetBytecode(frame) + target;
SYNC_SP();
GOTO_UNWIND();
GOTO_TIER_ONE(NULL);
}

/* Progress is guaranteed if we DEOPT on the eval breaker, because
Expand Down
34 changes: 1 addition & 33 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -879,9 +879,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
#undef LOAD_IP
#define LOAD_IP(UNUSED) (void)0

#undef GOTO_ERROR
#define GOTO_ERROR(LABEL) goto LABEL ## _tier_two

#ifdef Py_STATS
// Disable these macros that apply to Tier 1 stats when we are in Tier 2
#undef STAT_INC
Expand Down Expand Up @@ -957,46 +954,17 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
_PyOpcode_OpName[frame->instr_ptr->op.code]);
}
#endif
assert (next_uop[-1].format == UOP_FORMAT_JUMP);
assert(next_uop[-1].format == UOP_FORMAT_JUMP);
uint16_t target = uop_get_error_target(&next_uop[-1]);
next_uop = current_executor->trace + target;
goto tier2_dispatch;

error_tier_two:
OPT_HIST(trace_uop_execution_counter, trace_run_length_hist);
assert(next_uop[-1].format == UOP_FORMAT_TARGET);
frame->return_offset = 0; // Don't leave this random
Py_DECREF(current_executor);
tstate->previous_executor = NULL;
next_instr = frame->instr_ptr;
goto error;

jump_to_jump_target:
assert(next_uop[-1].format == UOP_FORMAT_JUMP);
target = uop_get_jump_target(&next_uop[-1]);
next_uop = current_executor->trace + target;
goto tier2_dispatch;

exit_to_tier1_dynamic:
next_instr = frame->instr_ptr;
goto goto_to_tier1;
exit_to_tier1:
assert(next_uop[-1].format == UOP_FORMAT_TARGET);
next_instr = next_uop[-1].target + _PyFrame_GetBytecode(frame);
goto_to_tier1:
#ifdef Py_DEBUG
if (frame->lltrace >= 2) {
printf("DEOPT: [UOp ");
_PyUOpPrint(&next_uop[-1]);
printf(" -> %s]\n",
_PyOpcode_OpName[next_instr->op.code]);
}
#endif
OPT_HIST(trace_uop_execution_counter, trace_run_length_hist);
Py_DECREF(current_executor);
tstate->previous_executor = NULL;
DISPATCH();

#endif // _Py_JIT

#endif // _Py_TIER2
Expand Down
38 changes: 19 additions & 19 deletions Python/ceval_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,6 @@ do { \
JUMP_TO_LABEL(start_frame); \
} while (0)

// Use this instead of 'goto error' so Tier 2 can go to a different label
#define GOTO_ERROR(LABEL) JUMP_TO_LABEL(LABEL)

/* Tuple access macros */

#ifndef Py_DEBUG
Expand Down Expand Up @@ -387,17 +384,19 @@ _PyFrame_SetStackPointer(frame, stack_pointer)
#define GOTO_TIER_TWO(EXECUTOR) \
do { \
OPT_STAT_INC(traces_executed); \
jit_func jitted = (EXECUTOR)->jit_code; \
_PyExecutorObject *_executor = (EXECUTOR); \
jit_func jitted = _executor->jit_code; \
/* Keep the shim frame alive via the executor: */ \
Py_INCREF(_executor); \
next_instr = jitted(frame, stack_pointer, tstate); \
Py_DECREF(tstate->previous_executor); \
tstate->previous_executor = NULL; \
Py_DECREF(_executor); \
Py_CLEAR(tstate->previous_executor); \
frame = tstate->current_frame; \
stack_pointer = _PyFrame_GetStackPointer(frame); \
if (next_instr == NULL) { \
next_instr = frame->instr_ptr; \
stack_pointer = _PyFrame_GetStackPointer(frame); \
goto error; \
} \
stack_pointer = _PyFrame_GetStackPointer(frame); \
DISPATCH(); \
} while (0)
#else
Expand All @@ -410,24 +409,25 @@ do { \
} while (0)
#endif

#define GOTO_TIER_ONE(TARGET) \
do { \
Py_DECREF(tstate->previous_executor); \
tstate->previous_executor = NULL; \
next_instr = target; \
DISPATCH(); \
#define GOTO_TIER_ONE(TARGET) \
do { \
next_instr = (TARGET); \
OPT_HIST(trace_uop_execution_counter, trace_run_length_hist); \
Py_CLEAR(tstate->previous_executor); \
if (next_instr == NULL) { \
next_instr = frame->instr_ptr; \
goto error; \
} \
DISPATCH(); \
} while (0)

#define CURRENT_OPARG() (next_uop[-1].oparg)

#define CURRENT_OPARG() (next_uop[-1].oparg)
#define CURRENT_OPERAND0() (next_uop[-1].operand0)
#define CURRENT_OPERAND1() (next_uop[-1].operand1)
#define CURRENT_TARGET() (next_uop[-1].target)

#define JUMP_TO_JUMP_TARGET() goto jump_to_jump_target
#define JUMP_TO_ERROR() goto jump_to_error_target
#define GOTO_UNWIND() goto error_tier_two
#define EXIT_TO_TIER1() goto exit_to_tier1
#define EXIT_TO_TIER1_DYNAMIC() goto exit_to_tier1_dynamic;

/* Stackref macros */

Expand Down
Loading
Loading
0