Feature or enhancement
The _PyInterpreterFrame struct contains a strong reference to:
f_executable - the currently executing code object
f_funcobj - the function object
f_locals - the locals object (often NULL)
frame_obj - the frame object (often NULL)
We should use deferred references (in the free-threaded build) for f_executable and f_funcobj because they are a common source of reference count contention. The pointed to objects (code and function) already support deferred reference counting, but the references in the frame are not deferred.
I think we don't need to bother with changing f_locals for now. I don't think it's used frequently enough to be a bottleneck, but we can revisit it later if necessary.
The frame_obj are typically unique -- not shared across threads -- so we don't need to bother with deferred reference counting for frame_obj.
Complications and hazards
_PyInterpreterFrame are also embedded in generators/coroutines and PyFrameObject, which are heap objects. We need to be careful that _PyStackRef fields are visible to the GC in order to be kept alive. Once an object is untracked, the _PyStackRef fields may no longer be valid: it's safe to call PyStackRef_CLOSE/CLEAR but not otherwise access or dereference those fields because the GC may have already collected them.
Linked PRs
Feature or enhancement
The
_PyInterpreterFramestruct contains a strong reference to:f_executable- the currently executing code objectf_funcobj- the function objectf_locals- the locals object (often NULL)frame_obj- the frame object (often NULL)We should use deferred references (in the free-threaded build) for
f_executableandf_funcobjbecause they are a common source of reference count contention. The pointed to objects (code and function) already support deferred reference counting, but the references in the frame are not deferred.I think we don't need to bother with changing
f_localsfor now. I don't think it's used frequently enough to be a bottleneck, but we can revisit it later if necessary.The
frame_objare typically unique -- not shared across threads -- so we don't need to bother with deferred reference counting forframe_obj.Complications and hazards
_PyInterpreterFrameare also embedded in generators/coroutines andPyFrameObject, which are heap objects. We need to be careful that_PyStackReffields are visible to the GC in order to be kept alive. Once an object is untracked, the_PyStackReffields may no longer be valid: it's safe to callPyStackRef_CLOSE/CLEARbut not otherwise access or dereference those fields because the GC may have already collected them.Linked PRs
f_executablein_PyInterpreterFrame#123924f_funcobjin_PyInterpreterFrame#124026