summaryrefslogtreecommitdiff
path: root/Include/internal/pycore_object.h
diff options
context:
space:
mode:
authorEric Snow <ericsnowcurrently@gmail.com>2022-08-04 11:28:15 -0600
committerGitHub <noreply@github.com>2022-08-04 11:28:15 -0600
commitbdbadb905ae638b67a6c9a6767be396e18839dd6 (patch)
treeb43f9af37788bcef962f8d87fbacaca57289b0dd /Include/internal/pycore_object.h
parent60f54d94852771854cf1cb647df7cef7c1617d9e (diff)
downloadcpython-git-bdbadb905ae638b67a6c9a6767be396e18839dd6.tar.gz
gh-94673: Recover Weaklist Lookup Performance (gh-95544)
gh-95302 seems to have introduced a small performance regression. Here we make some minor changes to recover that lost performance.
Diffstat (limited to 'Include/internal/pycore_object.h')
-rw-r--r--Include/internal/pycore_object.h33
1 files changed, 33 insertions, 0 deletions
diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h
index 173d36784c..b3b0b84648 100644
--- a/Include/internal/pycore_object.h
+++ b/Include/internal/pycore_object.h
@@ -217,6 +217,16 @@ extern void _Py_PrintReferences(FILE *);
extern void _Py_PrintReferenceAddresses(FILE *);
#endif
+
+/* Return the *address* of the object's weaklist. The address may be
+ * dereferenced to get the current head of the weaklist. This is useful
+ * for iterating over the linked list of weakrefs, especially when the
+ * list is being modified externally (e.g. refs getting removed).
+ *
+ * The returned pointer should not be used to change the head of the list
+ * nor should it be used to add, remove, or swap any refs in the list.
+ * That is the sole responsibility of the code in weakrefobject.c.
+ */
static inline PyObject **
_PyObject_GET_WEAKREFS_LISTPTR(PyObject *op)
{
@@ -226,10 +236,33 @@ _PyObject_GET_WEAKREFS_LISTPTR(PyObject *op)
(PyTypeObject *)op);
return _PyStaticType_GET_WEAKREFS_LISTPTR(state);
}
+ // Essentially _PyObject_GET_WEAKREFS_LISTPTR_FROM_OFFSET():
Py_ssize_t offset = Py_TYPE(op)->tp_weaklistoffset;
return (PyObject **)((char *)op + offset);
}
+/* This is a special case of _PyObject_GET_WEAKREFS_LISTPTR().
+ * Only the most fundamental lookup path is used.
+ * Consequently, static types should not be used.
+ *
+ * For static builtin types the returned pointer will always point
+ * to a NULL tp_weaklist. This is fine for any deallocation cases,
+ * since static types are never deallocated and static builtin types
+ * are only finalized at the end of runtime finalization.
+ *
+ * If the weaklist for static types is actually needed then use
+ * _PyObject_GET_WEAKREFS_LISTPTR().
+ */
+static inline PyWeakReference **
+_PyObject_GET_WEAKREFS_LISTPTR_FROM_OFFSET(PyObject *op)
+{
+ assert(!PyType_Check(op) ||
+ ((PyTypeObject *)op)->tp_flags & Py_TPFLAGS_HEAPTYPE);
+ Py_ssize_t offset = Py_TYPE(op)->tp_weaklistoffset;
+ return (PyWeakReference **)((char *)op + offset);
+}
+
+
// Fast inlined version of PyObject_IS_GC()
static inline int
_PyObject_IS_GC(PyObject *obj)