| 
									
										
										
										
											2020-04-13 11:38:42 +02:00
										 |  |  | #ifndef Py_INTERNAL_GC_H
 | 
					
						
							|  |  |  | #define Py_INTERNAL_GC_H
 | 
					
						
							|  |  |  | #ifdef __cplusplus
 | 
					
						
							|  |  |  | extern "C" { | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef Py_BUILD_CORE
 | 
					
						
							|  |  |  | #  error "this header requires Py_BUILD_CORE define"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-10 08:04:41 +09:00
										 |  |  | #include "pycore_freelist.h"   // _PyFreeListState
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 11:38:42 +02:00
										 |  |  | /* GC information is stored BEFORE the object structure. */ | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  |     // Pointer to next object in the list.
 | 
					
						
							|  |  |  |     // 0 means the object is not tracked
 | 
					
						
							|  |  |  |     uintptr_t _gc_next; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Pointer to previous object in the list.
 | 
					
						
							|  |  |  |     // Lowest two bits are used for flags documented later.
 | 
					
						
							|  |  |  |     uintptr_t _gc_prev; | 
					
						
							|  |  |  | } PyGC_Head; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-06 14:44:48 +02:00
										 |  |  | #define _PyGC_Head_UNUSED PyGC_Head
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Get an object's GC head */ | 
					
						
							| 
									
										
										
										
											2022-05-11 13:37:18 +02:00
										 |  |  | static inline PyGC_Head* _Py_AS_GC(PyObject *op) { | 
					
						
							| 
									
										
										
										
											2023-06-06 14:44:48 +02:00
										 |  |  |     char *gc = ((char*)op) - sizeof(PyGC_Head); | 
					
						
							|  |  |  |     return (PyGC_Head*)gc; | 
					
						
							| 
									
										
										
										
											2022-05-11 13:37:18 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2023-06-06 14:44:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Get the object given the GC head */ | 
					
						
							|  |  |  | static inline PyObject* _Py_FROM_GC(PyGC_Head *gc) { | 
					
						
							|  |  |  |     char *op = ((char *)gc) + sizeof(PyGC_Head); | 
					
						
							|  |  |  |     return (PyObject *)op; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 11:38:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-08 13:03:39 -07:00
										 |  |  | /* Bit flags for ob_gc_bits (in Py_GIL_DISABLED builds)
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Setting the bits requires a relaxed store. The per-object lock must also be | 
					
						
							|  |  |  |  * held, except when the object is only visible to a single thread (e.g. during | 
					
						
							|  |  |  |  * object initialization or destruction). | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Reading the bits requires using a relaxed load, but does not require holding | 
					
						
							|  |  |  |  * the per-object lock. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2024-01-25 13:27:36 -05:00
										 |  |  | #ifdef Py_GIL_DISABLED
 | 
					
						
							| 
									
										
										
										
											2024-04-12 13:36:20 -04:00
										 |  |  | #  define _PyGC_BITS_TRACKED        (1)     // Tracked by the GC
 | 
					
						
							|  |  |  | #  define _PyGC_BITS_FINALIZED      (2)     // tp_finalize was called
 | 
					
						
							| 
									
										
										
										
											2024-01-25 13:27:36 -05:00
										 |  |  | #  define _PyGC_BITS_UNREACHABLE    (4)
 | 
					
						
							|  |  |  | #  define _PyGC_BITS_FROZEN         (8)
 | 
					
						
							| 
									
										
										
										
											2024-02-05 10:35:59 -08:00
										 |  |  | #  define _PyGC_BITS_SHARED         (16)
 | 
					
						
							| 
									
										
										
										
											2024-03-08 09:56:36 -08:00
										 |  |  | #  define _PyGC_BITS_SHARED_INLINE  (32)
 | 
					
						
							| 
									
										
										
										
											2024-04-12 13:36:20 -04:00
										 |  |  | #  define _PyGC_BITS_DEFERRED       (64)    // Use deferred reference counting
 | 
					
						
							| 
									
										
										
										
											2024-01-25 13:27:36 -05:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-08 13:03:39 -07:00
										 |  |  | #ifdef Py_GIL_DISABLED
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline void | 
					
						
							|  |  |  | _PyObject_SET_GC_BITS(PyObject *op, uint8_t new_bits) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint8_t bits = _Py_atomic_load_uint8_relaxed(&op->ob_gc_bits); | 
					
						
							|  |  |  |     _Py_atomic_store_uint8_relaxed(&op->ob_gc_bits, bits | new_bits); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline int | 
					
						
							|  |  |  | _PyObject_HAS_GC_BITS(PyObject *op, uint8_t bits) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return (_Py_atomic_load_uint8_relaxed(&op->ob_gc_bits) & bits) != 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline void | 
					
						
							|  |  |  | _PyObject_CLEAR_GC_BITS(PyObject *op, uint8_t bits_to_clear) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint8_t bits = _Py_atomic_load_uint8_relaxed(&op->ob_gc_bits); | 
					
						
							|  |  |  |     _Py_atomic_store_uint8_relaxed(&op->ob_gc_bits, bits & ~bits_to_clear); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 11:38:42 +02:00
										 |  |  | /* True if the object is currently tracked by the GC. */ | 
					
						
							| 
									
										
										
										
											2022-05-11 13:37:18 +02:00
										 |  |  | static inline int _PyObject_GC_IS_TRACKED(PyObject *op) { | 
					
						
							| 
									
										
										
										
											2024-01-25 13:27:36 -05:00
										 |  |  | #ifdef Py_GIL_DISABLED
 | 
					
						
							| 
									
										
										
										
											2024-05-08 13:03:39 -07:00
										 |  |  |     return _PyObject_HAS_GC_BITS(op, _PyGC_BITS_TRACKED); | 
					
						
							| 
									
										
										
										
											2024-01-25 13:27:36 -05:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2022-05-11 13:37:18 +02:00
										 |  |  |     PyGC_Head *gc = _Py_AS_GC(op); | 
					
						
							|  |  |  |     return (gc->_gc_next != 0); | 
					
						
							| 
									
										
										
										
											2024-01-25 13:27:36 -05:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2022-05-11 13:37:18 +02:00
										 |  |  | } | 
					
						
							|  |  |  | #define _PyObject_GC_IS_TRACKED(op) _PyObject_GC_IS_TRACKED(_Py_CAST(PyObject*, op))
 | 
					
						
							| 
									
										
										
										
											2020-04-13 11:38:42 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* True if the object may be tracked by the GC in the future, or already is.
 | 
					
						
							|  |  |  |    This can be useful to implement some optimizations. */ | 
					
						
							| 
									
										
										
										
											2022-05-11 13:37:18 +02:00
										 |  |  | static inline int _PyObject_GC_MAY_BE_TRACKED(PyObject *obj) { | 
					
						
							|  |  |  |     if (!PyObject_IS_GC(obj)) { | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (PyTuple_CheckExact(obj)) { | 
					
						
							|  |  |  |         return _PyObject_GC_IS_TRACKED(obj); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-04-13 11:38:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-05 10:35:59 -08:00
										 |  |  | #ifdef Py_GIL_DISABLED
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-08 09:56:36 -08:00
										 |  |  | /* True if memory the object references is shared between
 | 
					
						
							|  |  |  |  * multiple threads and needs special purpose when freeing | 
					
						
							|  |  |  |  * those references due to the possibility of in-flight | 
					
						
							|  |  |  |  * lock-free reads occurring.  The object is responsible | 
					
						
							|  |  |  |  * for calling _PyMem_FreeDelayed on the referenced | 
					
						
							|  |  |  |  * memory. */ | 
					
						
							| 
									
										
										
										
											2024-02-05 10:35:59 -08:00
										 |  |  | static inline int _PyObject_GC_IS_SHARED(PyObject *op) { | 
					
						
							| 
									
										
										
										
											2024-05-08 13:03:39 -07:00
										 |  |  |     return _PyObject_HAS_GC_BITS(op, _PyGC_BITS_SHARED); | 
					
						
							| 
									
										
										
										
											2024-02-05 10:35:59 -08:00
										 |  |  | } | 
					
						
							|  |  |  | #define _PyObject_GC_IS_SHARED(op) _PyObject_GC_IS_SHARED(_Py_CAST(PyObject*, op))
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline void _PyObject_GC_SET_SHARED(PyObject *op) { | 
					
						
							| 
									
										
										
										
											2024-05-08 13:03:39 -07:00
										 |  |  |     _PyObject_SET_GC_BITS(op, _PyGC_BITS_SHARED); | 
					
						
							| 
									
										
										
										
											2024-02-05 10:35:59 -08:00
										 |  |  | } | 
					
						
							|  |  |  | #define _PyObject_GC_SET_SHARED(op) _PyObject_GC_SET_SHARED(_Py_CAST(PyObject*, op))
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-08 09:56:36 -08:00
										 |  |  | /* True if the memory of the object is shared between multiple
 | 
					
						
							|  |  |  |  * threads and needs special purpose when freeing due to | 
					
						
							|  |  |  |  * the possibility of in-flight lock-free reads occurring. | 
					
						
							|  |  |  |  * Objects with this bit that are GC objects will automatically | 
					
						
							| 
									
										
										
										
											2024-04-19 14:47:42 -07:00
										 |  |  |  * delay-freed by PyObject_GC_Del. */ | 
					
						
							| 
									
										
										
										
											2024-03-08 09:56:36 -08:00
										 |  |  | static inline int _PyObject_GC_IS_SHARED_INLINE(PyObject *op) { | 
					
						
							| 
									
										
										
										
											2024-05-08 13:03:39 -07:00
										 |  |  |     return _PyObject_HAS_GC_BITS(op, _PyGC_BITS_SHARED_INLINE); | 
					
						
							| 
									
										
										
										
											2024-03-08 09:56:36 -08:00
										 |  |  | } | 
					
						
							|  |  |  | #define _PyObject_GC_IS_SHARED_INLINE(op) \
 | 
					
						
							|  |  |  |     _PyObject_GC_IS_SHARED_INLINE(_Py_CAST(PyObject*, op)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline void _PyObject_GC_SET_SHARED_INLINE(PyObject *op) { | 
					
						
							| 
									
										
										
										
											2024-05-08 13:03:39 -07:00
										 |  |  |     _PyObject_SET_GC_BITS(op, _PyGC_BITS_SHARED_INLINE); | 
					
						
							| 
									
										
										
										
											2024-03-08 09:56:36 -08:00
										 |  |  | } | 
					
						
							|  |  |  | #define _PyObject_GC_SET_SHARED_INLINE(op) \
 | 
					
						
							|  |  |  |     _PyObject_GC_SET_SHARED_INLINE(_Py_CAST(PyObject*, op)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-05 10:35:59 -08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2020-04-13 11:38:42 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Bit flags for _gc_prev */ | 
					
						
							|  |  |  | /* Bit 0 is set when tp_finalize is called */ | 
					
						
							| 
									
										
										
										
											2024-03-20 08:54:42 +00:00
										 |  |  | #define _PyGC_PREV_MASK_FINALIZED  1
 | 
					
						
							| 
									
										
										
										
											2020-04-13 11:38:42 +02:00
										 |  |  | /* Bit 1 is set when the object is in generation which is GCed currently. */ | 
					
						
							| 
									
										
										
										
											2024-03-20 08:54:42 +00:00
										 |  |  | #define _PyGC_PREV_MASK_COLLECTING 2
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-26 11:11:42 +00:00
										 |  |  | /* Bit 0 in _gc_next is the old space bit.
 | 
					
						
							|  |  |  |  * It is set as follows: | 
					
						
							|  |  |  |  * Young: gcstate->visited_space | 
					
						
							|  |  |  |  * old[0]: 0 | 
					
						
							|  |  |  |  * old[1]: 1 | 
					
						
							|  |  |  |  * permanent: 0 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * During a collection all objects handled should have the bit set to | 
					
						
							|  |  |  |  * gcstate->visited_space, as objects are moved from the young gen | 
					
						
							|  |  |  |  * and the increment into old[gcstate->visited_space]. | 
					
						
							|  |  |  |  * When object are moved from the pending space, old[gcstate->visited_space^1] | 
					
						
							|  |  |  |  * into the increment, the old space bit is flipped. | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2024-03-20 08:54:42 +00:00
										 |  |  | #define _PyGC_NEXT_MASK_OLD_SPACE_1    1
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define _PyGC_PREV_SHIFT           2
 | 
					
						
							| 
									
										
										
										
											2020-04-13 11:38:42 +02:00
										 |  |  | #define _PyGC_PREV_MASK            (((uintptr_t) -1) << _PyGC_PREV_SHIFT)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-05 15:17:16 -05:00
										 |  |  | /* set for debugging information */ | 
					
						
							|  |  |  | #define _PyGC_DEBUG_STATS             (1<<0) /* print collection statistics */
 | 
					
						
							|  |  |  | #define _PyGC_DEBUG_COLLECTABLE       (1<<1) /* print collectable objects */
 | 
					
						
							|  |  |  | #define _PyGC_DEBUG_UNCOLLECTABLE     (1<<2) /* print uncollectable objects */
 | 
					
						
							|  |  |  | #define _PyGC_DEBUG_SAVEALL           (1<<5) /* save all garbage in gc.garbage */
 | 
					
						
							|  |  |  | #define _PyGC_DEBUG_LEAK              _PyGC_DEBUG_COLLECTABLE | \
 | 
					
						
							|  |  |  |                                       _PyGC_DEBUG_UNCOLLECTABLE | \ | 
					
						
							|  |  |  |                                       _PyGC_DEBUG_SAVEALL | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef enum { | 
					
						
							|  |  |  |     // GC was triggered by heap allocation
 | 
					
						
							|  |  |  |     _Py_GC_REASON_HEAP, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // GC was called during shutdown
 | 
					
						
							|  |  |  |     _Py_GC_REASON_SHUTDOWN, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // GC was called by gc.collect() or PyGC_Collect()
 | 
					
						
							|  |  |  |     _Py_GC_REASON_MANUAL | 
					
						
							|  |  |  | } _PyGC_Reason; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 11:38:42 +02:00
										 |  |  | // Lowest bit of _gc_next is used for flags only in GC.
 | 
					
						
							|  |  |  | // But it is always 0 for normal code.
 | 
					
						
							| 
									
										
										
										
											2022-05-11 13:37:18 +02:00
										 |  |  | static inline PyGC_Head* _PyGCHead_NEXT(PyGC_Head *gc) { | 
					
						
							| 
									
										
										
										
											2024-03-20 08:54:42 +00:00
										 |  |  |     uintptr_t next = gc->_gc_next & _PyGC_PREV_MASK; | 
					
						
							| 
									
										
										
										
											2023-06-06 14:44:48 +02:00
										 |  |  |     return (PyGC_Head*)next; | 
					
						
							| 
									
										
										
										
											2022-05-11 13:37:18 +02:00
										 |  |  | } | 
					
						
							|  |  |  | static inline void _PyGCHead_SET_NEXT(PyGC_Head *gc, PyGC_Head *next) { | 
					
						
							| 
									
										
										
										
											2024-03-20 08:54:42 +00:00
										 |  |  |     uintptr_t unext = (uintptr_t)next; | 
					
						
							|  |  |  |     assert((unext & ~_PyGC_PREV_MASK) == 0); | 
					
						
							|  |  |  |     gc->_gc_next = (gc->_gc_next & ~_PyGC_PREV_MASK) | unext; | 
					
						
							| 
									
										
										
										
											2022-05-11 13:37:18 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-04-13 11:38:42 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Lowest two bits of _gc_prev is used for _PyGC_PREV_MASK_* flags.
 | 
					
						
							| 
									
										
										
										
											2022-05-11 13:37:18 +02:00
										 |  |  | static inline PyGC_Head* _PyGCHead_PREV(PyGC_Head *gc) { | 
					
						
							|  |  |  |     uintptr_t prev = (gc->_gc_prev & _PyGC_PREV_MASK); | 
					
						
							| 
									
										
										
										
											2023-06-06 14:44:48 +02:00
										 |  |  |     return (PyGC_Head*)prev; | 
					
						
							| 
									
										
										
										
											2022-05-11 13:37:18 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2024-03-20 08:54:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-11 13:37:18 +02:00
										 |  |  | static inline void _PyGCHead_SET_PREV(PyGC_Head *gc, PyGC_Head *prev) { | 
					
						
							| 
									
										
										
										
											2023-06-06 14:44:48 +02:00
										 |  |  |     uintptr_t uprev = (uintptr_t)prev; | 
					
						
							| 
									
										
										
										
											2022-05-11 13:37:18 +02:00
										 |  |  |     assert((uprev & ~_PyGC_PREV_MASK) == 0); | 
					
						
							|  |  |  |     gc->_gc_prev = ((gc->_gc_prev & ~_PyGC_PREV_MASK) | uprev); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline int _PyGC_FINALIZED(PyObject *op) { | 
					
						
							| 
									
										
										
										
											2024-01-25 13:27:36 -05:00
										 |  |  | #ifdef Py_GIL_DISABLED
 | 
					
						
							| 
									
										
										
										
											2024-05-08 13:03:39 -07:00
										 |  |  |     return _PyObject_HAS_GC_BITS(op, _PyGC_BITS_FINALIZED); | 
					
						
							| 
									
										
										
										
											2024-01-25 13:27:36 -05:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2022-05-11 13:37:18 +02:00
										 |  |  |     PyGC_Head *gc = _Py_AS_GC(op); | 
					
						
							| 
									
										
										
										
											2024-01-25 13:27:36 -05:00
										 |  |  |     return ((gc->_gc_prev & _PyGC_PREV_MASK_FINALIZED) != 0); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2022-05-11 13:37:18 +02:00
										 |  |  | } | 
					
						
							|  |  |  | static inline void _PyGC_SET_FINALIZED(PyObject *op) { | 
					
						
							| 
									
										
										
										
											2024-01-25 13:27:36 -05:00
										 |  |  | #ifdef Py_GIL_DISABLED
 | 
					
						
							| 
									
										
										
										
											2024-05-08 13:03:39 -07:00
										 |  |  |     _PyObject_SET_GC_BITS(op, _PyGC_BITS_FINALIZED); | 
					
						
							| 
									
										
										
										
											2024-01-25 13:27:36 -05:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2022-05-11 13:37:18 +02:00
										 |  |  |     PyGC_Head *gc = _Py_AS_GC(op); | 
					
						
							| 
									
										
										
										
											2024-01-25 13:27:36 -05:00
										 |  |  |     gc->_gc_prev |= _PyGC_PREV_MASK_FINALIZED; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2022-05-11 13:37:18 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2024-01-10 13:18:38 -05:00
										 |  |  | static inline void _PyGC_CLEAR_FINALIZED(PyObject *op) { | 
					
						
							| 
									
										
										
										
											2024-01-25 13:27:36 -05:00
										 |  |  | #ifdef Py_GIL_DISABLED
 | 
					
						
							| 
									
										
										
										
											2024-05-08 13:03:39 -07:00
										 |  |  |     _PyObject_CLEAR_GC_BITS(op, _PyGC_BITS_FINALIZED); | 
					
						
							| 
									
										
										
										
											2024-01-25 13:27:36 -05:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2024-01-10 13:18:38 -05:00
										 |  |  |     PyGC_Head *gc = _Py_AS_GC(op); | 
					
						
							|  |  |  |     gc->_gc_prev &= ~_PyGC_PREV_MASK_FINALIZED; | 
					
						
							| 
									
										
										
										
											2024-01-25 13:27:36 -05:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2024-01-10 13:18:38 -05:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-04-13 11:38:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-14 18:30:41 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* GC runtime state */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* If we change this, we need to change the default value in the
 | 
					
						
							|  |  |  |    signature of gc.collect. */ | 
					
						
							|  |  |  | #define NUM_GENERATIONS 3
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |    NOTE: about untracking of mutable objects. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    Certain types of container cannot participate in a reference cycle, and | 
					
						
							|  |  |  |    so do not need to be tracked by the garbage collector. Untracking these | 
					
						
							|  |  |  |    objects reduces the cost of garbage collections. However, determining | 
					
						
							|  |  |  |    which objects may be untracked is not free, and the costs must be | 
					
						
							|  |  |  |    weighed against the benefits for garbage collection. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    There are two possible strategies for when to untrack a container: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    i) When the container is created. | 
					
						
							|  |  |  |    ii) When the container is examined by the garbage collector. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    Tuples containing only immutable objects (integers, strings etc, and | 
					
						
							|  |  |  |    recursively, tuples of immutable objects) do not need to be tracked. | 
					
						
							|  |  |  |    The interpreter creates a large number of tuples, many of which will | 
					
						
							|  |  |  |    not survive until garbage collection. It is therefore not worthwhile | 
					
						
							|  |  |  |    to untrack eligible tuples at creation time. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    Instead, all tuples except the empty tuple are tracked when created. | 
					
						
							|  |  |  |    During garbage collection it is determined whether any surviving tuples | 
					
						
							|  |  |  |    can be untracked. A tuple can be untracked if all of its contents are | 
					
						
							|  |  |  |    already not tracked. Tuples are examined for untracking in all garbage | 
					
						
							|  |  |  |    collection cycles. It may take more than one cycle to untrack a tuple. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    Dictionaries containing only immutable objects also do not need to be | 
					
						
							|  |  |  |    tracked. Dictionaries are untracked when created. If a tracked item is | 
					
						
							|  |  |  |    inserted into a dictionary (either as a key or value), the dictionary | 
					
						
							|  |  |  |    becomes tracked. During a full garbage collection (all generations), | 
					
						
							|  |  |  |    the collector will untrack any dictionaries whose contents are not | 
					
						
							|  |  |  |    tracked. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    The module provides the python function is_tracked(obj), which returns | 
					
						
							|  |  |  |    the CURRENT tracking status of the object. Subsequent garbage | 
					
						
							|  |  |  |    collections may change the tracking status of the object. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    Untracking of certain containers was introduced in issue #4688, and | 
					
						
							|  |  |  |    the algorithm was refined in response to issue #14775. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct gc_generation { | 
					
						
							|  |  |  |     PyGC_Head head; | 
					
						
							|  |  |  |     int threshold; /* collection threshold */ | 
					
						
							|  |  |  |     int count; /* count of allocations or collections of younger
 | 
					
						
							|  |  |  |                   generations */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-20 08:54:42 +00:00
										 |  |  | struct gc_collection_stats { | 
					
						
							|  |  |  |     /* number of collected objects */ | 
					
						
							|  |  |  |     Py_ssize_t collected; | 
					
						
							|  |  |  |     /* total number of uncollectable objects (put into gc.garbage) */ | 
					
						
							|  |  |  |     Py_ssize_t uncollectable; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-14 18:30:41 +02:00
										 |  |  | /* Running stats per generation */ | 
					
						
							|  |  |  | struct gc_generation_stats { | 
					
						
							|  |  |  |     /* total number of collections */ | 
					
						
							|  |  |  |     Py_ssize_t collections; | 
					
						
							|  |  |  |     /* total number of collected objects */ | 
					
						
							|  |  |  |     Py_ssize_t collected; | 
					
						
							|  |  |  |     /* total number of uncollectable objects (put into gc.garbage) */ | 
					
						
							|  |  |  |     Py_ssize_t uncollectable; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct _gc_runtime_state { | 
					
						
							|  |  |  |     /* List of objects that still need to be cleaned up, singly linked
 | 
					
						
							|  |  |  |      * via their gc headers' gc_prev pointers.  */ | 
					
						
							|  |  |  |     PyObject *trash_delete_later; | 
					
						
							|  |  |  |     /* Current call-stack depth of tp_dealloc calls. */ | 
					
						
							|  |  |  |     int trash_delete_nesting; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-13 17:17:28 -07:00
										 |  |  |     /* Is automatic collection enabled? */ | 
					
						
							| 
									
										
										
										
											2020-04-14 18:30:41 +02:00
										 |  |  |     int enabled; | 
					
						
							|  |  |  |     int debug; | 
					
						
							|  |  |  |     /* linked lists of container objects */ | 
					
						
							| 
									
										
										
										
											2024-03-20 08:54:42 +00:00
										 |  |  |     struct gc_generation young; | 
					
						
							|  |  |  |     struct gc_generation old[2]; | 
					
						
							| 
									
										
										
										
											2020-04-14 18:30:41 +02:00
										 |  |  |     /* a permanent generation which won't be collected */ | 
					
						
							|  |  |  |     struct gc_generation permanent_generation; | 
					
						
							|  |  |  |     struct gc_generation_stats generation_stats[NUM_GENERATIONS]; | 
					
						
							|  |  |  |     /* true if we are currently running the collector */ | 
					
						
							|  |  |  |     int collecting; | 
					
						
							|  |  |  |     /* list of uncollectable objects */ | 
					
						
							|  |  |  |     PyObject *garbage; | 
					
						
							|  |  |  |     /* a list of callbacks to be invoked when collection is performed */ | 
					
						
							|  |  |  |     PyObject *callbacks; | 
					
						
							| 
									
										
										
										
											2024-03-20 08:54:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-22 18:43:25 +00:00
										 |  |  |     Py_ssize_t heap_size; | 
					
						
							| 
									
										
										
										
											2024-03-20 08:54:42 +00:00
										 |  |  |     Py_ssize_t work_to_do; | 
					
						
							|  |  |  |     /* Which of the old spaces is the visited space */ | 
					
						
							|  |  |  |     int visited_space; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef Py_GIL_DISABLED
 | 
					
						
							| 
									
										
										
										
											2020-04-14 18:30:41 +02:00
										 |  |  |     /* This is the number of objects that survived the last full
 | 
					
						
							|  |  |  |        collection. It approximates the number of long lived objects | 
					
						
							|  |  |  |        tracked by the GC. | 
					
						
							| 
									
										
										
										
											2024-02-07 12:38:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-14 18:30:41 +02:00
										 |  |  |        (by "full collection", we mean a collection of the oldest | 
					
						
							|  |  |  |        generation). */ | 
					
						
							|  |  |  |     Py_ssize_t long_lived_total; | 
					
						
							| 
									
										
										
										
											2024-02-07 12:38:34 +00:00
										 |  |  |     /* This is the number of objects that survived all "non-full"
 | 
					
						
							|  |  |  |        collections, and are awaiting to undergo a full collection for | 
					
						
							|  |  |  |        the first time. */ | 
					
						
							|  |  |  |     Py_ssize_t long_lived_pending; | 
					
						
							| 
									
										
										
										
											2024-04-29 14:36:02 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* gh-117783: Deferred reference counting is not fully implemented yet, so
 | 
					
						
							|  |  |  |        as a temporary measure we treat objects using deferred referenence | 
					
						
							| 
									
										
										
										
											2024-06-03 16:58:41 -04:00
										 |  |  |        counting as immortal. The value may be zero, one, or a negative number: | 
					
						
							|  |  |  |         0: immortalize deferred RC objects once the first thread is created | 
					
						
							|  |  |  |         1: immortalize all deferred RC objects immediately | 
					
						
							|  |  |  |         <0: suppressed; don't immortalize objects */ | 
					
						
							|  |  |  |     int immortalize; | 
					
						
							| 
									
										
										
										
											2024-03-20 08:54:42 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2020-04-14 18:30:41 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-16 11:22:27 -05:00
										 |  |  | #ifdef Py_GIL_DISABLED
 | 
					
						
							|  |  |  | struct _gc_thread_state { | 
					
						
							|  |  |  |     /* Thread-local allocation count. */ | 
					
						
							|  |  |  |     Py_ssize_t alloc_count; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-13 17:17:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-30 17:00:00 +01:00
										 |  |  | extern void _PyGC_InitState(struct _gc_runtime_state *); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-20 08:54:42 +00:00
										 |  |  | extern Py_ssize_t _PyGC_Collect(PyThreadState *tstate, int generation, _PyGC_Reason reason); | 
					
						
							|  |  |  | extern void _PyGC_CollectNoFail(PyThreadState *tstate); | 
					
						
							| 
									
										
										
										
											2020-04-14 18:30:41 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-05 15:17:16 -05:00
										 |  |  | /* Freeze objects tracked by the GC and ignore them in future collections. */ | 
					
						
							|  |  |  | extern void _PyGC_Freeze(PyInterpreterState *interp); | 
					
						
							|  |  |  | /* Unfreezes objects placing them in the oldest generation */ | 
					
						
							|  |  |  | extern void _PyGC_Unfreeze(PyInterpreterState *interp); | 
					
						
							|  |  |  | /* Number of frozen objects */ | 
					
						
							|  |  |  | extern Py_ssize_t _PyGC_GetFreezeCount(PyInterpreterState *interp); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-22 18:43:25 +00:00
										 |  |  | extern PyObject *_PyGC_GetObjects(PyInterpreterState *interp, int generation); | 
					
						
							| 
									
										
										
										
											2024-01-05 15:17:16 -05:00
										 |  |  | extern PyObject *_PyGC_GetReferrers(PyInterpreterState *interp, PyObject *objs); | 
					
						
							| 
									
										
										
										
											2020-04-29 02:29:20 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Functions to clear types free lists
 | 
					
						
							| 
									
										
										
										
											2024-01-10 08:04:41 +09:00
										 |  |  | extern void _PyGC_ClearAllFreeLists(PyInterpreterState *interp); | 
					
						
							| 
									
										
										
										
											2024-02-20 06:57:48 -08:00
										 |  |  | extern void _Py_ScheduleGC(PyThreadState *tstate); | 
					
						
							| 
									
										
										
										
											2022-10-08 07:57:09 -07:00
										 |  |  | extern void _Py_RunGC(PyThreadState *tstate); | 
					
						
							| 
									
										
										
										
											2020-04-29 02:29:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-29 14:36:02 -04:00
										 |  |  | #ifdef Py_GIL_DISABLED
 | 
					
						
							|  |  |  | // gh-117783: Immortalize objects that use deferred reference counting
 | 
					
						
							|  |  |  | extern void _PyGC_ImmortalizeDeferredObjects(PyInterpreterState *interp); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 11:38:42 +02:00
										 |  |  | #ifdef __cplusplus
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #endif /* !Py_INTERNAL_GC_H */
 |