@@ -217,6 +217,16 @@ extern void _Py_PrintReferences(FILE *);
217
217
extern void _Py_PrintReferenceAddresses (FILE * );
218
218
#endif
219
219
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
+ */
220
230
static inline PyObject * *
221
231
_PyObject_GET_WEAKREFS_LISTPTR (PyObject * op )
222
232
{
@@ -226,10 +236,33 @@ _PyObject_GET_WEAKREFS_LISTPTR(PyObject *op)
226
236
(PyTypeObject * )op );
227
237
return _PyStaticType_GET_WEAKREFS_LISTPTR (state );
228
238
}
239
+ // Essentially _PyObject_GET_WEAKREFS_LISTPTR_FROM_OFFSET():
229
240
Py_ssize_t offset = Py_TYPE (op )-> tp_weaklistoffset ;
230
241
return (PyObject * * )((char * )op + offset );
231
242
}
232
243
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
+
233
266
// Fast inlined version of PyObject_IS_GC()
234
267
static inline int
235
268
_PyObject_IS_GC (PyObject * obj )
0 commit comments