codekingpro/portable-devtools
114k
1#ifndef Py_INTERNAL_GC_H2#define Py_INTERNAL_GC_H3#ifdef __cplusplus4extern "C" {5#endif6 7#ifndef Py_BUILD_CORE8# error "this header requires Py_BUILD_CORE define"9#endif10 11#include "pycore_interp_structs.h" // PyGC_Head12#include "pycore_pystate.h" // _PyInterpreterState_GET()13#include "pycore_typedefs.h" // _PyInterpreterFrame14 15 16/* Get an object's GC head */17static inline PyGC_Head* _Py_AS_GC(PyObject *op) {18 char *gc = ((char*)op) - sizeof(PyGC_Head);19 return (PyGC_Head*)gc;20}21 22/* Get the object given the GC head */23static inline PyObject* _Py_FROM_GC(PyGC_Head *gc) {24 char *op = ((char *)gc) + sizeof(PyGC_Head);25 return (PyObject *)op;26}27 28 29/* Bit flags for ob_gc_bits (in Py_GIL_DISABLED builds)30 *31 * Setting the bits requires a relaxed store. The per-object lock must also be32 * held, except when the object is only visible to a single thread (e.g. during33 * object initialization or destruction).34 *35 * Reading the bits requires using a relaxed load, but does not require holding36 * the per-object lock.37 */38#ifdef Py_GIL_DISABLED39# define _PyGC_BITS_TRACKED (1<<0) // Tracked by the GC40# define _PyGC_BITS_FINALIZED (1<<1) // tp_finalize was called41# define _PyGC_BITS_UNREACHABLE (1<<2)42# define _PyGC_BITS_FROZEN (1<<3)43# define _PyGC_BITS_SHARED (1<<4)44# define _PyGC_BITS_ALIVE (1<<5) // Reachable from a known root.45# define _PyGC_BITS_DEFERRED (1<<6) // Use deferred reference counting46#endif47 48#ifdef Py_GIL_DISABLED49 50static inline void51_PyObject_SET_GC_BITS(PyObject *op, uint8_t new_bits)52{53 uint8_t bits = _Py_atomic_load_uint8_relaxed(&op->ob_gc_bits);54 _Py_atomic_store_uint8_relaxed(&op->ob_gc_bits, bits | new_bits);55}56 57static inline int58_PyObject_HAS_GC_BITS(PyObject *op, uint8_t bits)59{60 return (_Py_atomic_load_uint8_relaxed(&op->ob_gc_bits) & bits) != 0;61}62 63static inline void64_PyObject_CLEAR_GC_BITS(PyObject *op, uint8_t bits_to_clear)65{66 uint8_t bits = _Py_atomic_load_uint8_relaxed(&op->ob_gc_bits);67 _Py_atomic_store_uint8_relaxed(&op->ob_gc_bits, bits & ~bits_to_clear);68}69 70#endif71 72/* True if the object is currently tracked by the GC. */73static inline int _PyObject_GC_IS_TRACKED(PyObject *op) {74#ifdef Py_GIL_DISABLED75 return _PyObject_HAS_GC_BITS(op, _PyGC_BITS_TRACKED);76#else77 PyGC_Head *gc = _Py_AS_GC(op);78 return (gc->_gc_next != 0);79#endif80}81#define _PyObject_GC_IS_TRACKED(op) _PyObject_GC_IS_TRACKED(_Py_CAST(PyObject*, op))82 83/* True if the object may be tracked by the GC in the future, or already is.84 This can be useful to implement some optimizations. */85static inline int _PyObject_GC_MAY_BE_TRACKED(PyObject *obj) {86 if (!PyObject_IS_GC(obj)) {87 return 0;88 }89 if (PyTuple_CheckExact(obj)) {90 return _PyObject_GC_IS_TRACKED(obj);91 }92 return 1;93}94 95#ifdef Py_GIL_DISABLED96 97/* True if memory the object references is shared between98 * multiple threads and needs special purpose when freeing99 * those references due to the possibility of in-flight100 * lock-free reads occurring. The object is responsible101 * for calling _PyMem_FreeDelayed on the referenced102 * memory. */103static inline int _PyObject_GC_IS_SHARED(PyObject *op) {104 return _PyObject_HAS_GC_BITS(op, _PyGC_BITS_SHARED);105}106#define _PyObject_GC_IS_SHARED(op) _PyObject_GC_IS_SHARED(_Py_CAST(PyObject*, op))107 108static inline void _PyObject_GC_SET_SHARED(PyObject *op) {109 _PyObject_SET_GC_BITS(op, _PyGC_BITS_SHARED);110}111#define _PyObject_GC_SET_SHARED(op) _PyObject_GC_SET_SHARED(_Py_CAST(PyObject*, op))112 113#endif114 115/* Bit flags for _gc_prev */116/* Bit 0 is set when tp_finalize is called */117#define _PyGC_PREV_MASK_FINALIZED ((uintptr_t)1)118/* Bit 1 is set when the object is in generation which is GCed currently. */119#define _PyGC_PREV_MASK_COLLECTING ((uintptr_t)2)120 121/* Bit 0 in _gc_next is the old space bit.122 * It is set as follows:123 * Young: gcstate->visited_space124 * old[0]: 0125 * old[1]: 1126 * permanent: 0127 *128 * During a collection all objects handled should have the bit set to129 * gcstate->visited_space, as objects are moved from the young gen130 * and the increment into old[gcstate->visited_space].131 * When object are moved from the pending space, old[gcstate->visited_space^1]132 * into the increment, the old space bit is flipped.133*/134#define _PyGC_NEXT_MASK_OLD_SPACE_1 1135 136#define _PyGC_PREV_SHIFT 2137#define _PyGC_PREV_MASK (((uintptr_t) -1) << _PyGC_PREV_SHIFT)138 139/* set for debugging information */140#define _PyGC_DEBUG_STATS (1<<0) /* print collection statistics */141#define _PyGC_DEBUG_COLLECTABLE (1<<1) /* print collectable objects */142#define _PyGC_DEBUG_UNCOLLECTABLE (1<<2) /* print uncollectable objects */143#define _PyGC_DEBUG_SAVEALL (1<<5) /* save all garbage in gc.garbage */144#define _PyGC_DEBUG_LEAK _PyGC_DEBUG_COLLECTABLE | \145 _PyGC_DEBUG_UNCOLLECTABLE | \146 _PyGC_DEBUG_SAVEALL147 148typedef enum {149 // GC was triggered by heap allocation150 _Py_GC_REASON_HEAP,151 152 // GC was called during shutdown153 _Py_GC_REASON_SHUTDOWN,154 155 // GC was called by gc.collect() or PyGC_Collect()156 _Py_GC_REASON_MANUAL157} _PyGC_Reason;158 159// Lowest bit of _gc_next is used for flags only in GC.160// But it is always 0 for normal code.161static inline PyGC_Head* _PyGCHead_NEXT(PyGC_Head *gc) {162 uintptr_t next = gc->_gc_next & _PyGC_PREV_MASK;163 return (PyGC_Head*)next;164}165static inline void _PyGCHead_SET_NEXT(PyGC_Head *gc, PyGC_Head *next) {166 uintptr_t unext = (uintptr_t)next;167 assert((unext & ~_PyGC_PREV_MASK) == 0);168 gc->_gc_next = (gc->_gc_next & ~_PyGC_PREV_MASK) | unext;169}170 171// Lowest two bits of _gc_prev is used for _PyGC_PREV_MASK_* flags.172static inline PyGC_Head* _PyGCHead_PREV(PyGC_Head *gc) {173 uintptr_t prev = (gc->_gc_prev & _PyGC_PREV_MASK);174 return (PyGC_Head*)prev;175}176 177static inline void _PyGCHead_SET_PREV(PyGC_Head *gc, PyGC_Head *prev) {178 uintptr_t uprev = (uintptr_t)prev;179 assert((uprev & ~_PyGC_PREV_MASK) == 0);180 gc->_gc_prev = ((gc->_gc_prev & ~_PyGC_PREV_MASK) | uprev);181}182 183static inline int _PyGC_FINALIZED(PyObject *op) {184#ifdef Py_GIL_DISABLED185 return _PyObject_HAS_GC_BITS(op, _PyGC_BITS_FINALIZED);186#else187 PyGC_Head *gc = _Py_AS_GC(op);188 return ((gc->_gc_prev & _PyGC_PREV_MASK_FINALIZED) != 0);189#endif190}191static inline void _PyGC_SET_FINALIZED(PyObject *op) {192#ifdef Py_GIL_DISABLED193 _PyObject_SET_GC_BITS(op, _PyGC_BITS_FINALIZED);194#else195 PyGC_Head *gc = _Py_AS_GC(op);196 gc->_gc_prev |= _PyGC_PREV_MASK_FINALIZED;197#endif198}199static inline void _PyGC_CLEAR_FINALIZED(PyObject *op) {200#ifdef Py_GIL_DISABLED201 _PyObject_CLEAR_GC_BITS(op, _PyGC_BITS_FINALIZED);202#else203 PyGC_Head *gc = _Py_AS_GC(op);204 gc->_gc_prev &= ~_PyGC_PREV_MASK_FINALIZED;205#endif206}207 208extern void _Py_ScheduleGC(PyThreadState *tstate);209 210#ifndef Py_GIL_DISABLED211extern void _Py_TriggerGC(struct _gc_runtime_state *gcstate);212#endif213 214 215/* Tell the GC to track this object.216 *217 * The object must not be tracked by the GC.218 *219 * NB: While the object is tracked by the collector, it must be safe to call the220 * ob_traverse method.221 *222 * Internal note: interp->gc.generation0->_gc_prev doesn't have any bit flags223 * because it's not object header. So we don't use _PyGCHead_PREV() and224 * _PyGCHead_SET_PREV() for it to avoid unnecessary bitwise operations.225 *226 * See also the public PyObject_GC_Track() function.227 */228static inline void _PyObject_GC_TRACK(229// The preprocessor removes _PyObject_ASSERT_FROM() calls if NDEBUG is defined230#ifndef NDEBUG231 const char *filename, int lineno,232#endif233 PyObject *op)234{235 _PyObject_ASSERT_FROM(op, !_PyObject_GC_IS_TRACKED(op),236 "object already tracked by the garbage collector",237 filename, lineno, __func__);238#ifdef Py_GIL_DISABLED239 _PyObject_SET_GC_BITS(op, _PyGC_BITS_TRACKED);240#else241 PyGC_Head *gc = _Py_AS_GC(op);242 _PyObject_ASSERT_FROM(op,243 (gc->_gc_prev & _PyGC_PREV_MASK_COLLECTING) == 0,244 "object is in generation which is garbage collected",245 filename, lineno, __func__);246 247 struct _gc_runtime_state *gcstate = &_PyInterpreterState_GET()->gc;248 PyGC_Head *generation0 = &gcstate->young.head;249 PyGC_Head *last = (PyGC_Head*)(generation0->_gc_prev);250 _PyGCHead_SET_NEXT(last, gc);251 _PyGCHead_SET_PREV(gc, last);252 uintptr_t not_visited = 1 ^ gcstate->visited_space;253 gc->_gc_next = ((uintptr_t)generation0) | not_visited;254 generation0->_gc_prev = (uintptr_t)gc;255 gcstate->young.count++; /* number of tracked GC objects */256 gcstate->heap_size++;257 if (gcstate->young.count > gcstate->young.threshold) {258 _Py_TriggerGC(gcstate);259 }260#endif261}262 263/* Tell the GC to stop tracking this object.264 *265 * Internal note: This may be called while GC. So _PyGC_PREV_MASK_COLLECTING266 * must be cleared. But _PyGC_PREV_MASK_FINALIZED bit is kept.267 *268 * The object must be tracked by the GC.269 *270 * See also the public PyObject_GC_UnTrack() which accept an object which is271 * not tracked.272 */273static inline void _PyObject_GC_UNTRACK(274// The preprocessor removes _PyObject_ASSERT_FROM() calls if NDEBUG is defined275#ifndef NDEBUG276 const char *filename, int lineno,277#endif278 PyObject *op)279{280 _PyObject_ASSERT_FROM(op, _PyObject_GC_IS_TRACKED(op),281 "object not tracked by the garbage collector",282 filename, lineno, __func__);283 284#ifdef Py_GIL_DISABLED285 _PyObject_CLEAR_GC_BITS(op, _PyGC_BITS_TRACKED);286#else287 PyGC_Head *gc = _Py_AS_GC(op);288 PyGC_Head *prev = _PyGCHead_PREV(gc);289 PyGC_Head *next = _PyGCHead_NEXT(gc);290 _PyGCHead_SET_NEXT(prev, next);291 _PyGCHead_SET_PREV(next, prev);292 gc->_gc_next = 0;293 gc->_gc_prev &= _PyGC_PREV_MASK_FINALIZED;294 struct _gc_runtime_state *gcstate = &_PyInterpreterState_GET()->gc;295 if (gcstate->young.count > 0) {296 gcstate->young.count--;297 }298 gcstate->heap_size--;299#endif300}301 302 303 304/*305 NOTE: about untracking of mutable objects.306 307 Certain types of container cannot participate in a reference cycle, and308 so do not need to be tracked by the garbage collector. Untracking these309 objects reduces the cost of garbage collections. However, determining310 which objects may be untracked is not free, and the costs must be311 weighed against the benefits for garbage collection.312 313 There are two possible strategies for when to untrack a container:314 315 i) When the container is created.316 ii) When the container is examined by the garbage collector.317 318 Tuples containing only immutable objects (integers, strings etc, and319 recursively, tuples of immutable objects) do not need to be tracked.320 The interpreter creates a large number of tuples, many of which will321 not survive until garbage collection. It is therefore not worthwhile322 to untrack eligible tuples at creation time.323 324 Instead, all tuples except the empty tuple are tracked when created.325 During garbage collection it is determined whether any surviving tuples326 can be untracked. A tuple can be untracked if all of its contents are327 already not tracked. Tuples are examined for untracking in all garbage328 collection cycles. It may take more than one cycle to untrack a tuple.329 330 Dictionaries containing only immutable objects also do not need to be331 tracked. Dictionaries are untracked when created. If a tracked item is332 inserted into a dictionary (either as a key or value), the dictionary333 becomes tracked. During a full garbage collection (all generations),334 the collector will untrack any dictionaries whose contents are not335 tracked.336 337 The module provides the python function is_tracked(obj), which returns338 the CURRENT tracking status of the object. Subsequent garbage339 collections may change the tracking status of the object.340 341 Untracking of certain containers was introduced in issue #4688, and342 the algorithm was refined in response to issue #14775.343*/344 345extern void _PyGC_InitState(struct _gc_runtime_state *);346 347extern Py_ssize_t _PyGC_Collect(PyThreadState *tstate, int generation, _PyGC_Reason reason);348extern void _PyGC_CollectNoFail(PyThreadState *tstate);349 350/* Freeze objects tracked by the GC and ignore them in future collections. */351extern void _PyGC_Freeze(PyInterpreterState *interp);352/* Unfreezes objects placing them in the oldest generation */353extern void _PyGC_Unfreeze(PyInterpreterState *interp);354/* Number of frozen objects */355extern Py_ssize_t _PyGC_GetFreezeCount(PyInterpreterState *interp);356 357extern PyObject *_PyGC_GetObjects(PyInterpreterState *interp, int generation);358extern PyObject *_PyGC_GetReferrers(PyInterpreterState *interp, PyObject *objs);359 360// Functions to clear types free lists361extern void _PyGC_ClearAllFreeLists(PyInterpreterState *interp);362extern void _Py_RunGC(PyThreadState *tstate);363 364union _PyStackRef;365 366// GC visit callback for tracked interpreter frames367extern int _PyGC_VisitFrameStack(_PyInterpreterFrame *frame, visitproc visit, void *arg);368extern int _PyGC_VisitStackRef(union _PyStackRef *ref, visitproc visit, void *arg);369 370#ifdef Py_GIL_DISABLED371extern void _PyGC_VisitObjectsWorldStopped(PyInterpreterState *interp,372 gcvisitobjects_t callback, void *arg);373#endif374 375#ifdef __cplusplus376}377#endif378#endif /* !Py_INTERNAL_GC_H */379 