From da4d4ec1851714bb56a5e8d0c1cd5bf9842b4cee Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Thu, 3 Feb 2022 18:36:28 +0000 Subject: [PATCH] Pass reference to func, as well as args, when pushing frame. (GH-31100) --- Include/internal/pycore_frame.h | 6 ++---- Objects/frameobject.c | 2 ++ Python/ceval.c | 10 +++++----- Python/frame.c | 2 ++ Python/pystate.c | 20 -------------------- 5 files changed, 11 insertions(+), 29 deletions(-) diff --git a/Include/internal/pycore_frame.h b/Include/internal/pycore_frame.h index 85b9cf0f77b..1ad156290a5 100644 --- a/Include/internal/pycore_frame.h +++ b/Include/internal/pycore_frame.h @@ -87,12 +87,12 @@ static inline void _PyFrame_StackPush(InterpreterFrame *f, PyObject *value) { void _PyFrame_Copy(InterpreterFrame *src, InterpreterFrame *dest); +/* Consumes reference to func */ static inline void _PyFrame_InitializeSpecials( InterpreterFrame *frame, PyFunctionObject *func, PyObject *locals, int nlocalsplus) { - Py_INCREF(func); frame->f_func = func; frame->f_code = (PyCodeObject *)Py_NewRef(func->func_code); frame->f_builtins = func->func_builtins; @@ -166,9 +166,6 @@ _PyFrame_FastToLocalsWithError(InterpreterFrame *frame); void _PyFrame_LocalsToFast(InterpreterFrame *frame, int clear); -InterpreterFrame *_PyThreadState_PushFrame( - PyThreadState *tstate, PyFunctionObject *func, PyObject *locals); - extern InterpreterFrame * _PyThreadState_BumpFramePointerSlow(PyThreadState *tstate, size_t size); @@ -189,6 +186,7 @@ _PyThreadState_BumpFramePointer(PyThreadState *tstate, size_t size) void _PyThreadState_PopFrame(PyThreadState *tstate, InterpreterFrame *frame); +/* Consume reference to func */ InterpreterFrame * _PyFrame_Push(PyThreadState *tstate, PyFunctionObject *func); diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 15da1325d14..78f3894111b 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -784,6 +784,8 @@ _Py_IDENTIFIER(__builtins__); static void init_frame(InterpreterFrame *frame, PyFunctionObject *func, PyObject *locals) { + /* _PyFrame_InitializeSpecials consumes reference to func */ + Py_INCREF(func); PyCodeObject *code = (PyCodeObject *)func->func_code; _PyFrame_InitializeSpecials(frame, func, locals, code->co_nlocalsplus); for (Py_ssize_t i = 0; i < code->co_nlocalsplus; i++) { diff --git a/Python/ceval.c b/Python/ceval.c index 3c52c5824b4..3197fe8eebb 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2243,6 +2243,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr goto error; } CALL_STAT_INC(frames_pushed); + Py_INCREF(getitem); _PyFrame_InitializeSpecials(new_frame, getitem, NULL, code->co_nlocalsplus); STACK_SHRINK(2); @@ -4590,7 +4591,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr STACK_SHRINK(call_shape.postcall_shrink); // The frame has stolen all the arguments from the stack, // so there is no need to clean them up. - Py_DECREF(function); if (new_frame == NULL) { goto error; } @@ -4675,7 +4675,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr new_frame->localsplus[i] = NULL; } STACK_SHRINK(call_shape.postcall_shrink); - Py_DECREF(func); _PyFrame_SetStackPointer(frame, stack_pointer); new_frame->previous = frame; frame = cframe.current_frame = new_frame; @@ -4712,7 +4711,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr new_frame->localsplus[i] = NULL; } STACK_SHRINK(call_shape.postcall_shrink); - Py_DECREF(func); _PyFrame_SetStackPointer(frame, stack_pointer); new_frame->previous = frame; frame = cframe.current_frame = new_frame; @@ -6077,7 +6075,7 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject *func, return -1; } -/* Consumes all the references to the args */ +/* Consumes references to func and all the args */ static InterpreterFrame * _PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func, PyObject *locals, PyObject* const* args, @@ -6131,7 +6129,9 @@ _PyEval_Vector(PyThreadState *tstate, PyFunctionObject *func, PyObject* const* args, size_t argcount, PyObject *kwnames) { - /* _PyEvalFramePushAndInit consumes all the references to its arguments */ + /* _PyEvalFramePushAndInit consumes the references + * to func and all its arguments */ + Py_INCREF(func); for (size_t i = 0; i < argcount; i++) { Py_INCREF(args[i]); } diff --git a/Python/frame.c b/Python/frame.c index ca7c5f9c94e..76697cfa083 100644 --- a/Python/frame.c +++ b/Python/frame.c @@ -109,6 +109,7 @@ _PyFrame_Clear(InterpreterFrame *frame) Py_DECREF(frame->f_code); } +/* Consumes reference to func */ InterpreterFrame * _PyFrame_Push(PyThreadState *tstate, PyFunctionObject *func) { @@ -117,6 +118,7 @@ _PyFrame_Push(PyThreadState *tstate, PyFunctionObject *func) CALL_STAT_INC(frames_pushed); InterpreterFrame *new_frame = _PyThreadState_BumpFramePointer(tstate, size); if (new_frame == NULL) { + Py_DECREF(func); return NULL; } _PyFrame_InitializeSpecials(new_frame, func, NULL, code->co_nlocalsplus); diff --git a/Python/pystate.c b/Python/pystate.c index 77467944e2a..a85460c1510 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -2212,26 +2212,6 @@ _PyThreadState_BumpFramePointerSlow(PyThreadState *tstate, size_t size) return (InterpreterFrame *)base; } - -InterpreterFrame * -_PyThreadState_PushFrame(PyThreadState *tstate, PyFunctionObject *func, PyObject *locals) -{ - PyCodeObject *code = (PyCodeObject *)func->func_code; - int nlocalsplus = code->co_nlocalsplus; - size_t size = nlocalsplus + code->co_stacksize + - FRAME_SPECIALS_SIZE; - CALL_STAT_INC(frames_pushed); - InterpreterFrame *frame = _PyThreadState_BumpFramePointer(tstate, size); - if (frame == NULL) { - return NULL; - } - _PyFrame_InitializeSpecials(frame, func, locals, nlocalsplus); - for (int i=0; i < nlocalsplus; i++) { - frame->localsplus[i] = NULL; - } - return frame; -} - void _PyThreadState_PopFrame(PyThreadState *tstate, InterpreterFrame * frame) {