summaryrefslogtreecommitdiffstats
path: root/Include/internal/pycore_object.h
diff options
context:
space:
mode:
authorSam Gross <colesbury@gmail.com>2025-03-26 18:38:47 (GMT)
committerGitHub <noreply@github.com>2025-03-26 18:38:47 (GMT)
commit67fbfb42bd5dfe861d0c58d9e6c48d8eef033d24 (patch)
tree282178fa55571c055c8327dc3d77fa6a882a404b /Include/internal/pycore_object.h
parent3d4ac1a2c2b610f35a9e164878d67185e4a3546f (diff)
downloadcpython-67fbfb42bd5dfe861d0c58d9e6c48d8eef033d24.zip
cpython-67fbfb42bd5dfe861d0c58d9e6c48d8eef033d24.tar.gz
cpython-67fbfb42bd5dfe861d0c58d9e6c48d8eef033d24.tar.bz2
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.
Diffstat (limited to 'Include/internal/pycore_object.h')
-rw-r--r--Include/internal/pycore_object.h14
1 files changed, 14 insertions, 0 deletions
diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h
index 5e900f5..e5034ff 100644
--- a/Include/internal/pycore_object.h
+++ b/Include/internal/pycore_object.h
@@ -891,6 +891,12 @@ extern bool _PyObject_TryGetInstanceAttribute(PyObject *obj, PyObject *name,
extern PyObject *_PyType_LookupRefAndVersion(PyTypeObject *, PyObject *,
unsigned int *);
+// Internal API to look for a name through the MRO.
+// This stores a stack reference in out and returns the value of
+// type->tp_version or zero if name is missing. It doesn't set an exception!
+extern unsigned int
+_PyType_LookupStackRefAndVersion(PyTypeObject *type, PyObject *name, _PyStackRef *out);
+
// Cache the provided init method in the specialization cache of type if the
// provided type version matches the current version of the type.
//
@@ -946,6 +952,14 @@ extern int _PyObject_IsInstanceDictEmpty(PyObject *);
PyAPI_FUNC(PyObject*) _PyObject_LookupSpecial(PyObject *, PyObject *);
PyAPI_FUNC(PyObject*) _PyObject_LookupSpecialMethod(PyObject *self, PyObject *attr, PyObject **self_or_null);
+// Calls the method named `attr` on `self`, but does not set an exception if
+// the attribute does not exist.
+PyAPI_FUNC(PyObject *)
+_PyObject_MaybeCallSpecialNoArgs(PyObject *self, PyObject *attr);
+
+PyAPI_FUNC(PyObject *)
+_PyObject_MaybeCallSpecialOneArg(PyObject *self, PyObject *attr, PyObject *arg);
+
extern int _PyObject_IsAbstract(PyObject *);
PyAPI_FUNC(int) _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method);