mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
GH-104584: Don't call executors from JUMP_BACKWARD (GH-109347)
This commit is contained in:
parent
22e65eecaa
commit
6c13e13b13
4 changed files with 23 additions and 40 deletions
|
@ -40,7 +40,7 @@ PyAPI_FUNC(_PyOptimizerObject *) PyUnstable_GetOptimizer(void);
|
||||||
|
|
||||||
PyAPI_FUNC(_PyExecutorObject *) PyUnstable_GetExecutor(PyCodeObject *code, int offset);
|
PyAPI_FUNC(_PyExecutorObject *) PyUnstable_GetExecutor(PyCodeObject *code, int offset);
|
||||||
|
|
||||||
struct _PyInterpreterFrame *
|
int
|
||||||
_PyOptimizer_BackEdge(struct _PyInterpreterFrame *frame, _Py_CODEUNIT *src, _Py_CODEUNIT *dest, PyObject **stack_pointer);
|
_PyOptimizer_BackEdge(struct _PyInterpreterFrame *frame, _Py_CODEUNIT *src, _Py_CODEUNIT *dest, PyObject **stack_pointer);
|
||||||
|
|
||||||
extern _PyOptimizerObject _PyOptimizer_Default;
|
extern _PyOptimizerObject _PyOptimizer_Default;
|
||||||
|
|
|
@ -2242,21 +2242,17 @@ dummy_func(
|
||||||
here[1].cache += (1 << OPTIMIZER_BITS_IN_COUNTER);
|
here[1].cache += (1 << OPTIMIZER_BITS_IN_COUNTER);
|
||||||
if (here[1].cache > tstate->interp->optimizer_backedge_threshold &&
|
if (here[1].cache > tstate->interp->optimizer_backedge_threshold &&
|
||||||
// Double-check that the opcode isn't instrumented or something:
|
// Double-check that the opcode isn't instrumented or something:
|
||||||
here->op.code == JUMP_BACKWARD &&
|
here->op.code == JUMP_BACKWARD)
|
||||||
// _PyOptimizer_BackEdge is going to change frame->prev_instr,
|
|
||||||
// which breaks line event calculations:
|
|
||||||
next_instr->op.code != INSTRUMENTED_LINE
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
OBJECT_STAT_INC(optimization_attempts);
|
OBJECT_STAT_INC(optimization_attempts);
|
||||||
frame = _PyOptimizer_BackEdge(frame, here, next_instr, stack_pointer);
|
int optimized = _PyOptimizer_BackEdge(frame, here, next_instr, stack_pointer);
|
||||||
if (frame == NULL) {
|
ERROR_IF(optimized < 0, error);
|
||||||
frame = tstate->current_frame;
|
if (optimized) {
|
||||||
goto resume_with_error;
|
// Rewind and enter the executor:
|
||||||
|
assert(here->op.code == ENTER_EXECUTOR);
|
||||||
|
next_instr = here;
|
||||||
}
|
}
|
||||||
assert(frame == tstate->current_frame);
|
here[1].cache &= ((1 << OPTIMIZER_BITS_IN_COUNTER) - 1);
|
||||||
here[1].cache &= ((1 << OPTIMIZER_BITS_IN_COUNTER) -1);
|
|
||||||
goto resume_frame;
|
|
||||||
}
|
}
|
||||||
#endif /* ENABLE_SPECIALIZATION */
|
#endif /* ENABLE_SPECIALIZATION */
|
||||||
}
|
}
|
||||||
|
|
20
Python/generated_cases.c.h
generated
20
Python/generated_cases.c.h
generated
|
@ -2945,21 +2945,17 @@
|
||||||
here[1].cache += (1 << OPTIMIZER_BITS_IN_COUNTER);
|
here[1].cache += (1 << OPTIMIZER_BITS_IN_COUNTER);
|
||||||
if (here[1].cache > tstate->interp->optimizer_backedge_threshold &&
|
if (here[1].cache > tstate->interp->optimizer_backedge_threshold &&
|
||||||
// Double-check that the opcode isn't instrumented or something:
|
// Double-check that the opcode isn't instrumented or something:
|
||||||
here->op.code == JUMP_BACKWARD &&
|
here->op.code == JUMP_BACKWARD)
|
||||||
// _PyOptimizer_BackEdge is going to change frame->prev_instr,
|
|
||||||
// which breaks line event calculations:
|
|
||||||
next_instr->op.code != INSTRUMENTED_LINE
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
OBJECT_STAT_INC(optimization_attempts);
|
OBJECT_STAT_INC(optimization_attempts);
|
||||||
frame = _PyOptimizer_BackEdge(frame, here, next_instr, stack_pointer);
|
int optimized = _PyOptimizer_BackEdge(frame, here, next_instr, stack_pointer);
|
||||||
if (frame == NULL) {
|
if (optimized < 0) goto error;
|
||||||
frame = tstate->current_frame;
|
if (optimized) {
|
||||||
goto resume_with_error;
|
// Rewind and enter the executor:
|
||||||
|
assert(here->op.code == ENTER_EXECUTOR);
|
||||||
|
next_instr = here;
|
||||||
}
|
}
|
||||||
assert(frame == tstate->current_frame);
|
here[1].cache &= ((1 << OPTIMIZER_BITS_IN_COUNTER) - 1);
|
||||||
here[1].cache &= ((1 << OPTIMIZER_BITS_IN_COUNTER) -1);
|
|
||||||
goto resume_frame;
|
|
||||||
}
|
}
|
||||||
#endif /* ENABLE_SPECIALIZATION */
|
#endif /* ENABLE_SPECIALIZATION */
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
|
|
|
@ -154,7 +154,7 @@ PyUnstable_SetOptimizer(_PyOptimizerObject *optimizer)
|
||||||
Py_DECREF(old);
|
Py_DECREF(old);
|
||||||
}
|
}
|
||||||
|
|
||||||
_PyInterpreterFrame *
|
int
|
||||||
_PyOptimizer_BackEdge(_PyInterpreterFrame *frame, _Py_CODEUNIT *src, _Py_CODEUNIT *dest, PyObject **stack_pointer)
|
_PyOptimizer_BackEdge(_PyInterpreterFrame *frame, _Py_CODEUNIT *src, _Py_CODEUNIT *dest, PyObject **stack_pointer)
|
||||||
{
|
{
|
||||||
assert(src->op.code == JUMP_BACKWARD);
|
assert(src->op.code == JUMP_BACKWARD);
|
||||||
|
@ -162,18 +162,14 @@ _PyOptimizer_BackEdge(_PyInterpreterFrame *frame, _Py_CODEUNIT *src, _Py_CODEUNI
|
||||||
assert(PyCode_Check(code));
|
assert(PyCode_Check(code));
|
||||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
if (!has_space_for_executor(code, src)) {
|
if (!has_space_for_executor(code, src)) {
|
||||||
goto jump_to_destination;
|
return 0;
|
||||||
}
|
}
|
||||||
_PyOptimizerObject *opt = interp->optimizer;
|
_PyOptimizerObject *opt = interp->optimizer;
|
||||||
_PyExecutorObject *executor = NULL;
|
_PyExecutorObject *executor = NULL;
|
||||||
int err = opt->optimize(opt, code, dest, &executor, (int)(stack_pointer - _PyFrame_Stackbase(frame)));
|
int err = opt->optimize(opt, code, dest, &executor, (int)(stack_pointer - _PyFrame_Stackbase(frame)));
|
||||||
if (err <= 0) {
|
if (err <= 0) {
|
||||||
assert(executor == NULL);
|
assert(executor == NULL);
|
||||||
if (err < 0) {
|
return err;
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
goto jump_to_destination;
|
|
||||||
}
|
}
|
||||||
int index = get_index_for_executor(code, src);
|
int index = get_index_for_executor(code, src);
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
|
@ -184,16 +180,11 @@ _PyOptimizer_BackEdge(_PyInterpreterFrame *frame, _Py_CODEUNIT *src, _Py_CODEUNI
|
||||||
* it might get confused by the executor disappearing,
|
* it might get confused by the executor disappearing,
|
||||||
* but there is not much we can do about that here. */
|
* but there is not much we can do about that here. */
|
||||||
Py_DECREF(executor);
|
Py_DECREF(executor);
|
||||||
goto jump_to_destination;
|
return 0;
|
||||||
}
|
}
|
||||||
insert_executor(code, src, index, executor);
|
insert_executor(code, src, index, executor);
|
||||||
assert(frame->prev_instr == src);
|
Py_DECREF(executor);
|
||||||
frame->prev_instr = dest - 1;
|
return 1;
|
||||||
return executor->execute(executor, frame, stack_pointer);
|
|
||||||
jump_to_destination:
|
|
||||||
frame->prev_instr = dest - 1;
|
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
|
||||||
return frame;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_PyExecutorObject *
|
_PyExecutorObject *
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue