Skip to content

Commit

Permalink
pythonGH-108866: Guarantee forward progress in executors. (pythonGH-1…
Browse files Browse the repository at this point in the history
  • Loading branch information
markshannon authored Dec 12, 2023
1 parent 9898e61 commit 9560238
Show file tree
Hide file tree
Showing 7 changed files with 19 additions and 21 deletions.
2 changes: 1 addition & 1 deletion Include/cpython/optimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ typedef struct {
typedef struct _PyExecutorObject {
PyObject_VAR_HEAD
/* WARNING: execute consumes a reference to self. This is necessary to allow executors to tail call into each other. */
struct _PyInterpreterFrame *(*execute)(struct _PyExecutorObject *self, struct _PyInterpreterFrame *frame, PyObject **stack_pointer);
_Py_CODEUNIT *(*execute)(struct _PyExecutorObject *self, struct _PyInterpreterFrame *frame, PyObject **stack_pointer);
_PyVMData vm_data; /* Used by the VM, but opaque to the optimizer */
/* Data needed by the executor goes here, but is opaque to the VM */
} _PyExecutorObject;
Expand Down
2 changes: 1 addition & 1 deletion Include/internal/pycore_opcode_metadata.h

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

2 changes: 1 addition & 1 deletion Include/internal/pycore_uops.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ typedef struct {
_PyUOpInstruction trace[1];
} _PyUOpExecutorObject;

_PyInterpreterFrame *_PyUOpExecute(
_Py_CODEUNIT *_PyUOpExecute(
_PyExecutorObject *executor,
_PyInterpreterFrame *frame,
PyObject **stack_pointer);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Change the API and contract of ``_PyExecutorObject`` to return the
next_instr pointer, instead of the frame, and to always execute at least one
instruction.
11 changes: 4 additions & 7 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -2352,20 +2352,17 @@ dummy_func(

PyCodeObject *code = _PyFrame_GetCode(frame);
_PyExecutorObject *executor = (_PyExecutorObject *)code->co_executors->executors[oparg&255];
int original_oparg = executor->vm_data.oparg | (oparg & 0xfffff00);
JUMPBY(1-original_oparg);
frame->instr_ptr = next_instr;
Py_INCREF(executor);
if (executor->execute == _PyUOpExecute) {
current_executor = (_PyUOpExecutorObject *)executor;
GOTO_TIER_TWO();
}
frame = executor->execute(executor, frame, stack_pointer);
if (frame == NULL) {
frame = tstate->current_frame;
next_instr = executor->execute(executor, frame, stack_pointer);
frame = tstate->current_frame;
if (next_instr == NULL) {
goto resume_with_error;
}
goto enter_tier_one;
stack_pointer = _PyFrame_GetStackPointer(frame);
}

replaced op(_POP_JUMP_IF_FALSE, (unused/1, cond -- )) {
Expand Down
12 changes: 5 additions & 7 deletions Python/generated_cases.c.h

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

8 changes: 4 additions & 4 deletions Python/optimizer.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ _PyOptimizer_BackEdge(_PyInterpreterFrame *frame, _Py_CODEUNIT *src, _Py_CODEUNI
}
_PyOptimizerObject *opt = interp->optimizer;
_PyExecutorObject *executor = NULL;
/* Start optimizing at the destination to guarantee forward progress */
int err = opt->optimize(opt, code, dest, &executor, (int)(stack_pointer - _PyFrame_Stackbase(frame)));
if (err <= 0) {
assert(executor == NULL);
Expand Down Expand Up @@ -247,14 +248,13 @@ PyTypeObject _PyCounterExecutor_Type = {
.tp_methods = executor_methods,
};

static _PyInterpreterFrame *
static _Py_CODEUNIT *
counter_execute(_PyExecutorObject *self, _PyInterpreterFrame *frame, PyObject **stack_pointer)
{
((_PyCounterExecutorObject *)self)->optimizer->count++;
_PyFrame_SetStackPointer(frame, stack_pointer);
frame->instr_ptr = ((_PyCounterExecutorObject *)self)->next_instr;
Py_DECREF(self);
return frame;
return ((_PyCounterExecutorObject *)self)->next_instr;
}

static int
Expand Down Expand Up @@ -891,7 +891,7 @@ uop_optimize(
/* Dummy execute() function for UOp Executor.
* The actual implementation is inlined in ceval.c,
* in _PyEval_EvalFrameDefault(). */
_PyInterpreterFrame *
_Py_CODEUNIT *
_PyUOpExecute(_PyExecutorObject *executor, _PyInterpreterFrame *frame, PyObject **stack_pointer)
{
Py_FatalError("Tier 2 is now inlined into Tier 1");
Expand Down

0 comments on commit 9560238

Please sign in to comment.