mirror of
https://github.com/python/cpython.git
synced 2025-08-22 09:45:06 +00:00
gh-106581: Project through calls (#108067)
This finishes the work begun in gh-107760. When, while projecting a superblock, we encounter a call to a short, simple function, the superblock will now enter the function using `_PUSH_FRAME`, continue through it, and leave it using `_POP_FRAME`, and then continue through the original code. Multiple frame pushes and pops are even possible. It is also possible to stop appending to the superblock in the middle of a called function, when running out of space or encountering an unsupported bytecode.
This commit is contained in:
parent
292a22bdc2
commit
61c7249759
16 changed files with 409 additions and 109 deletions
|
@ -222,8 +222,6 @@ _PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func,
|
|||
static _PyInterpreterFrame *
|
||||
_PyEvalFramePushAndInit_Ex(PyThreadState *tstate, PyFunctionObject *func,
|
||||
PyObject *locals, Py_ssize_t nargs, PyObject *callargs, PyObject *kwargs);
|
||||
static void
|
||||
_PyEvalFrameClearAndPop(PyThreadState *tstate, _PyInterpreterFrame *frame);
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
|
@ -603,10 +601,6 @@ int _Py_CheckRecursiveCallPy(
|
|||
}
|
||||
|
||||
|
||||
static inline void _Py_LeaveRecursiveCallPy(PyThreadState *tstate) {
|
||||
tstate->py_recursion_remaining++;
|
||||
}
|
||||
|
||||
static const _Py_CODEUNIT _Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS[] = {
|
||||
/* Put a NOP at the start, so that the IP points into
|
||||
* the code, rather than before it */
|
||||
|
@ -731,7 +725,7 @@ resume_frame:
|
|||
// When tracing executed uops, also trace bytecode
|
||||
char *uop_debug = Py_GETENV("PYTHONUOPSDEBUG");
|
||||
if (uop_debug != NULL && *uop_debug >= '0') {
|
||||
lltrace = (*uop_debug - '0') >= 4; // TODO: Parse an int and all that
|
||||
lltrace = (*uop_debug - '0') >= 5; // TODO: Parse an int and all that
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -918,7 +912,7 @@ exit_unwind:
|
|||
// GH-99729: We need to unlink the frame *before* clearing it:
|
||||
_PyInterpreterFrame *dying = frame;
|
||||
frame = tstate->current_frame = dying->previous;
|
||||
_PyEvalFrameClearAndPop(tstate, dying);
|
||||
_PyEval_FrameClearAndPop(tstate, dying);
|
||||
frame->return_offset = 0;
|
||||
if (frame == &entry_frame) {
|
||||
/* Restore previous frame and exit */
|
||||
|
@ -1487,8 +1481,8 @@ clear_gen_frame(PyThreadState *tstate, _PyInterpreterFrame * frame)
|
|||
frame->previous = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_PyEvalFrameClearAndPop(PyThreadState *tstate, _PyInterpreterFrame * frame)
|
||||
void
|
||||
_PyEval_FrameClearAndPop(PyThreadState *tstate, _PyInterpreterFrame * frame)
|
||||
{
|
||||
if (frame->owner == FRAME_OWNED_BY_THREAD) {
|
||||
clear_thread_frame(tstate, frame);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue