1 #ifndef Py_INTERNAL_OBJECT_H
2 #define Py_INTERNAL_OBJECT_H
3 #ifdef __cplusplus
4 extern "C" {
5 #endif
6
7 #ifndef Py_BUILD_CORE
8 # error "this header requires Py_BUILD_CORE define"
9 #endif
10
11 #include "pycore_gc.h" // _PyObject_GC_IS_TRACKED()
12 #include "pycore_interp.h" // PyInterpreterState.gc
13 #include "pycore_pystate.h" // _PyThreadState_GET()
14
15 PyAPI_FUNC(int) _PyType_CheckConsistency(PyTypeObject *type);
16 PyAPI_FUNC(int) _PyDict_CheckConsistency(PyObject *mp, int check_content);
17
18 /* Tell the GC to track this object.
19 *
20 * NB: While the object is tracked by the collector, it must be safe to call the
21 * ob_traverse method.
22 *
23 * Internal note: interp->gc.generation0->_gc_prev doesn't have any bit flags
24 * because it's not object header. So we don't use _PyGCHead_PREV() and
25 * _PyGCHead_SET_PREV() for it to avoid unnecessary bitwise operations.
26 *
27 * The PyObject_GC_Track() function is the public version of this macro.
28 */
_PyObject_GC_TRACK_impl(const char * filename,int lineno,PyObject * op)29 static inline void _PyObject_GC_TRACK_impl(const char *filename, int lineno,
30 PyObject *op)
31 {
32 _PyObject_ASSERT_FROM(op, !_PyObject_GC_IS_TRACKED(op),
33 "object already tracked by the garbage collector",
34 filename, lineno, "_PyObject_GC_TRACK");
35
36 PyGC_Head *gc = _Py_AS_GC(op);
37 _PyObject_ASSERT_FROM(op,
38 (gc->_gc_prev & _PyGC_PREV_MASK_COLLECTING) == 0,
39 "object is in generation which is garbage collected",
40 filename, lineno, "_PyObject_GC_TRACK");
41
42 PyThreadState *tstate = _PyThreadState_GET();
43 PyGC_Head *generation0 = tstate->interp->gc.generation0;
44 PyGC_Head *last = (PyGC_Head*)(generation0->_gc_prev);
45 _PyGCHead_SET_NEXT(last, gc);
46 _PyGCHead_SET_PREV(gc, last);
47 _PyGCHead_SET_NEXT(gc, generation0);
48 generation0->_gc_prev = (uintptr_t)gc;
49 }
50
51 #define _PyObject_GC_TRACK(op) \
52 _PyObject_GC_TRACK_impl(__FILE__, __LINE__, _PyObject_CAST(op))
53
54 /* Tell the GC to stop tracking this object.
55 *
56 * Internal note: This may be called while GC. So _PyGC_PREV_MASK_COLLECTING
57 * must be cleared. But _PyGC_PREV_MASK_FINALIZED bit is kept.
58 *
59 * The object must be tracked by the GC.
60 *
61 * The PyObject_GC_UnTrack() function is the public version of this macro.
62 */
_PyObject_GC_UNTRACK_impl(const char * filename,int lineno,PyObject * op)63 static inline void _PyObject_GC_UNTRACK_impl(const char *filename, int lineno,
64 PyObject *op)
65 {
66 _PyObject_ASSERT_FROM(op, _PyObject_GC_IS_TRACKED(op),
67 "object not tracked by the garbage collector",
68 filename, lineno, "_PyObject_GC_UNTRACK");
69
70 PyGC_Head *gc = _Py_AS_GC(op);
71 PyGC_Head *prev = _PyGCHead_PREV(gc);
72 PyGC_Head *next = _PyGCHead_NEXT(gc);
73 _PyGCHead_SET_NEXT(prev, next);
74 _PyGCHead_SET_PREV(next, prev);
75 gc->_gc_next = 0;
76 gc->_gc_prev &= _PyGC_PREV_MASK_FINALIZED;
77 }
78
79 #define _PyObject_GC_UNTRACK(op) \
80 _PyObject_GC_UNTRACK_impl(__FILE__, __LINE__, _PyObject_CAST(op))
81
82 #ifdef Py_REF_DEBUG
83 extern void _PyDebug_PrintTotalRefs(void);
84 #endif
85
86 #ifdef Py_TRACE_REFS
87 extern void _Py_AddToAllObjects(PyObject *op, int force);
88 extern void _Py_PrintReferences(FILE *);
89 extern void _Py_PrintReferenceAddresses(FILE *);
90 #endif
91
92 static inline PyObject **
_PyObject_GET_WEAKREFS_LISTPTR(PyObject * op)93 _PyObject_GET_WEAKREFS_LISTPTR(PyObject *op)
94 {
95 Py_ssize_t offset = Py_TYPE(op)->tp_weaklistoffset;
96 return (PyObject **)((char *)op + offset);
97 }
98
99 // Fast inlined version of PyType_HasFeature()
100 static inline int
_PyType_HasFeature(PyTypeObject * type,unsigned long feature)101 _PyType_HasFeature(PyTypeObject *type, unsigned long feature) {
102 return ((type->tp_flags & feature) != 0);
103 }
104
105 // Fast inlined version of PyObject_IS_GC()
106 static inline int
_PyObject_IS_GC(PyObject * obj)107 _PyObject_IS_GC(PyObject *obj)
108 {
109 return (PyType_IS_GC(Py_TYPE(obj))
110 && (Py_TYPE(obj)->tp_is_gc == NULL
111 || Py_TYPE(obj)->tp_is_gc(obj)));
112 }
113
114 // Fast inlined version of PyType_IS_GC()
115 #define _PyType_IS_GC(t) _PyType_HasFeature((t), Py_TPFLAGS_HAVE_GC)
116
117 #ifdef __cplusplus
118 }
119 #endif
120 #endif /* !Py_INTERNAL_OBJECT_H */
121