mirror of
https://github.com/python/cpython.git
synced 2025-08-30 05:35:08 +00:00
gh-131586: Avoid refcount contention in some "special" calls (#131588)
In the free threaded build, the `_PyObject_LookupSpecial()` call can lead to reference count contention on the returned function object becuase it doesn't use stackrefs. Refactor some of the callers to use `_PyObject_MaybeCallSpecialNoArgs`, which uses stackrefs internally. This fixes the scaling bottleneck in the "lookup_special" microbenchmark in `ftscalingbench.py`. However, the are still some uses of `_PyObject_LookupSpecial()` that need to be addressed in future PRs.
This commit is contained in:
parent
3d4ac1a2c2
commit
67fbfb42bd
16 changed files with 450 additions and 374 deletions
|
@ -592,7 +592,7 @@ PyStackRef_XCLOSE(_PyStackRef ref)
|
|||
|
||||
// Note: this is a macro because MSVC (Windows) has trouble inlining it.
|
||||
|
||||
#define PyStackRef_Is(a, b) (((a).bits & (~Py_TAG_REFCNT)) == ((b).bits & (~Py_TAG_REFCNT)))
|
||||
#define PyStackRef_Is(a, b) (((a).bits & (~Py_TAG_BITS)) == ((b).bits & (~Py_TAG_BITS)))
|
||||
|
||||
#endif // !defined(Py_GIL_DISABLED) && defined(Py_STACKREF_DEBUG)
|
||||
|
||||
|
@ -640,6 +640,28 @@ PyStackRef_FunctionCheck(_PyStackRef stackref)
|
|||
return PyFunction_Check(PyStackRef_AsPyObjectBorrow(stackref));
|
||||
}
|
||||
|
||||
static inline void
|
||||
_PyThreadState_PushCStackRef(PyThreadState *tstate, _PyCStackRef *ref)
|
||||
{
|
||||
#ifdef Py_GIL_DISABLED
|
||||
_PyThreadStateImpl *tstate_impl = (_PyThreadStateImpl *)tstate;
|
||||
ref->next = tstate_impl->c_stack_refs;
|
||||
tstate_impl->c_stack_refs = ref;
|
||||
#endif
|
||||
ref->ref = PyStackRef_NULL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_PyThreadState_PopCStackRef(PyThreadState *tstate, _PyCStackRef *ref)
|
||||
{
|
||||
#ifdef Py_GIL_DISABLED
|
||||
_PyThreadStateImpl *tstate_impl = (_PyThreadStateImpl *)tstate;
|
||||
assert(tstate_impl->c_stack_refs == ref);
|
||||
tstate_impl->c_stack_refs = ref->next;
|
||||
#endif
|
||||
PyStackRef_XCLOSE(ref->ref);
|
||||
}
|
||||
|
||||
#ifdef Py_GIL_DISABLED
|
||||
|
||||
static inline int
|
||||
|
@ -656,6 +678,17 @@ _Py_TryIncrefCompareStackRef(PyObject **src, PyObject *op, _PyStackRef *out)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
_Py_TryXGetStackRef(PyObject **src, _PyStackRef *out)
|
||||
{
|
||||
PyObject *op = _Py_atomic_load_ptr_relaxed(src);
|
||||
if (op == NULL) {
|
||||
*out = PyStackRef_NULL;
|
||||
return 1;
|
||||
}
|
||||
return _Py_TryIncrefCompareStackRef(src, op, out);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Like Py_VISIT but for _PyStackRef fields
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue