diff options
author | Sam Gross <colesbury@gmail.com> | 2024-09-24 13:08:18 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-24 20:08:18 +0000 |
commit | f4997bb3ac961d6aaf07ce650cd074e28ce6ccd0 (patch) | |
tree | 6c82b0fadd282e74c8f81de4a3966666fd210196 /Objects/frameobject.c | |
parent | d3c76dff444046504754a437dceebc9a9c87ef18 (diff) | |
download | cpython-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.c | 9 |
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); |