@@ -217,6 +217,16 @@ extern void _Py_PrintReferences(FILE *);
217217extern void _Py_PrintReferenceAddresses (FILE * );
218218#endif
219219
220+
221+ /* Return the *address* of the object's weaklist. The address may be
222+ * dereferenced to get the current head of the weaklist. This is useful
223+ * for iterating over the linked list of weakrefs, especially when the
224+ * list is being modified externally (e.g. refs getting removed).
225+ *
226+ * The returned pointer should not be used to change the head of the list
227+ * nor should it be used to add, remove, or swap any refs in the list.
228+ * That is the sole responsibility of the code in weakrefobject.c.
229+ */
220230static inline PyObject * *
221231_PyObject_GET_WEAKREFS_LISTPTR (PyObject * op )
222232{
@@ -226,10 +236,33 @@ _PyObject_GET_WEAKREFS_LISTPTR(PyObject *op)
226236 (PyTypeObject * )op );
227237 return _PyStaticType_GET_WEAKREFS_LISTPTR (state );
228238 }
239+ // Essentially _PyObject_GET_WEAKREFS_LISTPTR_FROM_OFFSET():
229240 Py_ssize_t offset = Py_TYPE (op )-> tp_weaklistoffset ;
230241 return (PyObject * * )((char * )op + offset );
231242}
232243
244+ /* This is a special case of _PyObject_GET_WEAKREFS_LISTPTR().
245+ * Only the most fundamental lookup path is used.
246+ * Consequently, static types should not be used.
247+ *
248+ * For static builtin types the returned pointer will always point
249+ * to a NULL tp_weaklist. This is fine for any deallocation cases,
250+ * since static types are never deallocated and static builtin types
251+ * are only finalized at the end of runtime finalization.
252+ *
253+ * If the weaklist for static types is actually needed then use
254+ * _PyObject_GET_WEAKREFS_LISTPTR().
255+ */
256+ static inline PyWeakReference * *
257+ _PyObject_GET_WEAKREFS_LISTPTR_FROM_OFFSET (PyObject * op )
258+ {
259+ assert (!PyType_Check (op ) ||
260+ ((PyTypeObject * )op )-> tp_flags & Py_TPFLAGS_HEAPTYPE );
261+ Py_ssize_t offset = Py_TYPE (op )-> tp_weaklistoffset ;
262+ return (PyWeakReference * * )((char * )op + offset );
263+ }
264+
265+
233266// Fast inlined version of PyObject_IS_GC()
234267static inline int
235268_PyObject_IS_GC (PyObject * obj )
0 commit comments