aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Objects/frameobject.c
diff options
context:
space:
mode:
authorSam Gross <colesbury@gmail.com>2024-09-24 13:08:18 -0700
committerGitHub <noreply@github.com>2024-09-24 20:08:18 +0000
commitf4997bb3ac961d6aaf07ce650cd074e28ce6ccd0 (patch)
tree6c82b0fadd282e74c8f81de4a3966666fd210196 /Objects/frameobject.c
parentd3c76dff444046504754a437dceebc9a9c87ef18 (diff)
downloadcpython-f4997bb3ac961d6aaf07ce650cd074e28ce6ccd0.tar.gz
cpython-f4997bb3ac961d6aaf07ce650cd074e28ce6ccd0.zip
gh-123923: Defer refcounting for `f_funcobj` in `_PyInterpreterFrame` (#124026)
Use a `_PyStackRef` and defer the reference to `f_funcobj` when possible. This avoids some reference count contention in the common case of executing the same code object from multiple threads concurrently in the free-threaded build.
Diffstat (limited to 'Objects/frameobject.c')
-rw-r--r--Objects/frameobject.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index b567327f970..9f1c031dcb9 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -1634,7 +1634,7 @@ frame_dealloc(PyFrameObject *f)
/* Kill all local variables including specials, if we own them */
if (f->f_frame == frame && frame->owner == FRAME_OWNED_BY_FRAME_OBJECT) {
PyStackRef_CLEAR(frame->f_executable);
- Py_CLEAR(frame->f_funcobj);
+ PyStackRef_CLEAR(frame->f_funcobj);
Py_CLEAR(frame->f_locals);
_PyStackRef *locals = _PyFrame_GetLocalsArray(frame);
_PyStackRef *sp = frame->stackpointer;
@@ -1790,7 +1790,7 @@ static void
init_frame(_PyInterpreterFrame *frame, PyFunctionObject *func, PyObject *locals)
{
PyCodeObject *code = (PyCodeObject *)func->func_code;
- _PyFrame_Initialize(frame, (PyFunctionObject*)Py_NewRef(func),
+ _PyFrame_Initialize(frame, PyStackRef_FromPyObjectNew(func),
Py_XNewRef(locals), code, 0, NULL);
}
@@ -1861,14 +1861,15 @@ frame_init_get_vars(_PyInterpreterFrame *frame)
PyCodeObject *co = _PyFrame_GetCode(frame);
int lasti = _PyInterpreterFrame_LASTI(frame);
if (!(lasti < 0 && _PyCode_CODE(co)->op.code == COPY_FREE_VARS
- && PyFunction_Check(frame->f_funcobj)))
+ && PyStackRef_FunctionCheck(frame->f_funcobj)))
{
/* Free vars are initialized */
return;
}
/* Free vars have not been initialized -- Do that */
- PyObject *closure = ((PyFunctionObject *)frame->f_funcobj)->func_closure;
+ PyFunctionObject *func = _PyFrame_GetFunction(frame);
+ PyObject *closure = func->func_closure;
int offset = PyUnstable_Code_GetFirstFree(co);
for (int i = 0; i < co->co_nfreevars; ++i) {
PyObject *o = PyTuple_GET_ITEM(closure, i);