| 
									
										
										
										
											2018-11-21 22:27:47 +01:00
										 |  |  | #ifndef Py_INTERNAL_OBJECT_H
 | 
					
						
							|  |  |  | #define Py_INTERNAL_OBJECT_H
 | 
					
						
							|  |  |  | #ifdef __cplusplus
 | 
					
						
							|  |  |  | extern "C" { | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 23:02:26 +02:00
										 |  |  | #ifndef Py_BUILD_CORE
 | 
					
						
							|  |  |  | #  error "this header requires Py_BUILD_CORE define"
 | 
					
						
							| 
									
										
										
										
											2018-11-21 22:27:47 +01:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-19 13:21:28 +01:00
										 |  |  | #include "pycore_gc.h"            // _PyObject_GC_IS_TRACKED()
 | 
					
						
							|  |  |  | #include "pycore_interp.h"        // PyInterpreterState.gc
 | 
					
						
							|  |  |  | #include "pycore_pystate.h"       // _PyInterpreterState_GET()
 | 
					
						
							| 
									
										
										
										
											2018-11-22 01:02:54 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-12 21:51:34 +02:00
										 |  |  | PyAPI_FUNC(int) _PyType_CheckConsistency(PyTypeObject *type); | 
					
						
							|  |  |  | PyAPI_FUNC(int) _PyDict_CheckConsistency(PyObject *mp, int check_content); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-16 17:29:50 +02:00
										 |  |  | /* Update the Python traceback of an object. This function must be called
 | 
					
						
							|  |  |  |    when a memory block is reused from a free list. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    Internal function called by _Py_NewReference(). */ | 
					
						
							|  |  |  | extern int _PyTraceMalloc_NewReference(PyObject *op); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-16 01:28:07 +02:00
										 |  |  | // Fast inlined version of PyType_HasFeature()
 | 
					
						
							|  |  |  | static inline int | 
					
						
							|  |  |  | _PyType_HasFeature(PyTypeObject *type, unsigned long feature) { | 
					
						
							|  |  |  |     return ((type->tp_flags & feature) != 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-26 01:45:43 +01:00
										 |  |  | extern void _PyType_InitCache(PyInterpreterState *interp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-16 01:28:07 +02:00
										 |  |  | /* Inline functions trading binary compatibility for speed:
 | 
					
						
							|  |  |  |    _PyObject_Init() is the fast version of PyObject_Init(), and | 
					
						
							|  |  |  |    _PyObject_InitVar() is the fast version of PyObject_InitVar(). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    These inline functions must not be called with op=NULL. */ | 
					
						
							|  |  |  | static inline void | 
					
						
							|  |  |  | _PyObject_Init(PyObject *op, PyTypeObject *typeobj) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(op != NULL); | 
					
						
							|  |  |  |     Py_SET_TYPE(op, typeobj); | 
					
						
							|  |  |  |     if (_PyType_HasFeature(typeobj, Py_TPFLAGS_HEAPTYPE)) { | 
					
						
							|  |  |  |         Py_INCREF(typeobj); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     _Py_NewReference(op); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline void | 
					
						
							|  |  |  | _PyObject_InitVar(PyVarObject *op, PyTypeObject *typeobj, Py_ssize_t size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(op != NULL); | 
					
						
							|  |  |  |     Py_SET_SIZE(op, size); | 
					
						
							|  |  |  |     _PyObject_Init((PyObject *)op, typeobj); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 22:27:47 +01:00
										 |  |  | /* Tell the GC to track this object.
 | 
					
						
							| 
									
										
										
										
											2020-06-17 14:23:04 +02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * The object must not be tracked by the GC. | 
					
						
							| 
									
										
										
										
											2018-11-21 22:27:47 +01:00
										 |  |  |  * | 
					
						
							|  |  |  |  * NB: While the object is tracked by the collector, it must be safe to call the | 
					
						
							|  |  |  |  * ob_traverse method. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2019-11-20 11:48:18 +01:00
										 |  |  |  * Internal note: interp->gc.generation0->_gc_prev doesn't have any bit flags | 
					
						
							| 
									
										
										
										
											2019-06-04 03:15:09 +02:00
										 |  |  |  * because it's not object header.  So we don't use _PyGCHead_PREV() and | 
					
						
							|  |  |  |  * _PyGCHead_SET_PREV() for it to avoid unnecessary bitwise operations. | 
					
						
							| 
									
										
										
										
											2018-11-21 22:27:47 +01:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2020-06-17 14:23:04 +02:00
										 |  |  |  * See also the public PyObject_GC_Track() function. | 
					
						
							| 
									
										
										
										
											2018-11-21 22:27:47 +01:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-06-17 14:23:04 +02:00
										 |  |  | static inline void _PyObject_GC_TRACK( | 
					
						
							|  |  |  | // The preprocessor removes _PyObject_ASSERT_FROM() calls if NDEBUG is defined
 | 
					
						
							|  |  |  | #ifndef NDEBUG
 | 
					
						
							|  |  |  |     const char *filename, int lineno, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     PyObject *op) | 
					
						
							| 
									
										
										
										
											2018-11-22 01:02:54 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     _PyObject_ASSERT_FROM(op, !_PyObject_GC_IS_TRACKED(op), | 
					
						
							|  |  |  |                           "object already tracked by the garbage collector", | 
					
						
							| 
									
										
										
										
											2020-06-17 14:23:04 +02:00
										 |  |  |                           filename, lineno, __func__); | 
					
						
							| 
									
										
										
										
											2018-11-22 01:02:54 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     PyGC_Head *gc = _Py_AS_GC(op); | 
					
						
							|  |  |  |     _PyObject_ASSERT_FROM(op, | 
					
						
							|  |  |  |                           (gc->_gc_prev & _PyGC_PREV_MASK_COLLECTING) == 0, | 
					
						
							|  |  |  |                           "object is in generation which is garbage collected", | 
					
						
							| 
									
										
										
										
											2020-06-17 14:23:04 +02:00
										 |  |  |                           filename, lineno, __func__); | 
					
						
							| 
									
										
										
										
											2018-11-22 01:02:54 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-19 13:21:28 +01:00
										 |  |  |     PyInterpreterState *interp = _PyInterpreterState_GET(); | 
					
						
							|  |  |  |     PyGC_Head *generation0 = interp->gc.generation0; | 
					
						
							| 
									
										
										
										
											2019-11-20 11:48:18 +01:00
										 |  |  |     PyGC_Head *last = (PyGC_Head*)(generation0->_gc_prev); | 
					
						
							| 
									
										
										
										
											2018-11-22 01:02:54 +01:00
										 |  |  |     _PyGCHead_SET_NEXT(last, gc); | 
					
						
							|  |  |  |     _PyGCHead_SET_PREV(gc, last); | 
					
						
							| 
									
										
										
										
											2019-11-20 11:48:18 +01:00
										 |  |  |     _PyGCHead_SET_NEXT(gc, generation0); | 
					
						
							|  |  |  |     generation0->_gc_prev = (uintptr_t)gc; | 
					
						
							| 
									
										
										
										
											2018-11-22 01:02:54 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 22:27:47 +01:00
										 |  |  | /* Tell the GC to stop tracking this object.
 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-11-22 01:02:54 +01:00
										 |  |  |  * Internal note: This may be called while GC. So _PyGC_PREV_MASK_COLLECTING | 
					
						
							|  |  |  |  * must be cleared. But _PyGC_PREV_MASK_FINALIZED bit is kept. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The object must be tracked by the GC. | 
					
						
							| 
									
										
										
										
											2018-11-21 22:27:47 +01:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2020-06-17 14:23:04 +02:00
										 |  |  |  * See also the public PyObject_GC_UnTrack() which accept an object which is | 
					
						
							|  |  |  |  * not tracked. | 
					
						
							| 
									
										
										
										
											2018-11-21 22:27:47 +01:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-06-17 14:23:04 +02:00
										 |  |  | static inline void _PyObject_GC_UNTRACK( | 
					
						
							|  |  |  | // The preprocessor removes _PyObject_ASSERT_FROM() calls if NDEBUG is defined
 | 
					
						
							|  |  |  | #ifndef NDEBUG
 | 
					
						
							|  |  |  |     const char *filename, int lineno, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     PyObject *op) | 
					
						
							| 
									
										
										
										
											2018-11-22 01:02:54 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     _PyObject_ASSERT_FROM(op, _PyObject_GC_IS_TRACKED(op), | 
					
						
							|  |  |  |                           "object not tracked by the garbage collector", | 
					
						
							| 
									
										
										
										
											2020-06-17 14:23:04 +02:00
										 |  |  |                           filename, lineno, __func__); | 
					
						
							| 
									
										
										
										
											2018-11-22 01:02:54 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     PyGC_Head *gc = _Py_AS_GC(op); | 
					
						
							|  |  |  |     PyGC_Head *prev = _PyGCHead_PREV(gc); | 
					
						
							|  |  |  |     PyGC_Head *next = _PyGCHead_NEXT(gc); | 
					
						
							|  |  |  |     _PyGCHead_SET_NEXT(prev, next); | 
					
						
							|  |  |  |     _PyGCHead_SET_PREV(next, prev); | 
					
						
							|  |  |  |     gc->_gc_next = 0; | 
					
						
							|  |  |  |     gc->_gc_prev &= _PyGC_PREV_MASK_FINALIZED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-17 14:23:04 +02:00
										 |  |  | // Macros to accept any type for the parameter, and to automatically pass
 | 
					
						
							|  |  |  | // the filename and the filename (if NDEBUG is not defined) where the macro
 | 
					
						
							|  |  |  | // is called.
 | 
					
						
							|  |  |  | #ifdef NDEBUG
 | 
					
						
							|  |  |  | #  define _PyObject_GC_TRACK(op) \
 | 
					
						
							|  |  |  |         _PyObject_GC_TRACK(_PyObject_CAST(op)) | 
					
						
							|  |  |  | #  define _PyObject_GC_UNTRACK(op) \
 | 
					
						
							|  |  |  |         _PyObject_GC_UNTRACK(_PyObject_CAST(op)) | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #  define _PyObject_GC_TRACK(op) \
 | 
					
						
							|  |  |  |         _PyObject_GC_TRACK(__FILE__, __LINE__, _PyObject_CAST(op)) | 
					
						
							|  |  |  | #  define _PyObject_GC_UNTRACK(op) \
 | 
					
						
							|  |  |  |         _PyObject_GC_UNTRACK(__FILE__, __LINE__, _PyObject_CAST(op)) | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2018-11-21 22:27:47 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-03 17:28:26 +01:00
										 |  |  | #ifdef Py_REF_DEBUG
 | 
					
						
							|  |  |  | extern void _PyDebug_PrintTotalRefs(void); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef Py_TRACE_REFS
 | 
					
						
							| 
									
										
										
										
											2020-02-05 18:24:33 +01:00
										 |  |  | extern void _Py_AddToAllObjects(PyObject *op, int force); | 
					
						
							| 
									
										
										
										
											2020-02-03 17:28:26 +01:00
										 |  |  | extern void _Py_PrintReferences(FILE *); | 
					
						
							|  |  |  | extern void _Py_PrintReferenceAddresses(FILE *); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-06 14:07:02 +02:00
										 |  |  | static inline PyObject ** | 
					
						
							|  |  |  | _PyObject_GET_WEAKREFS_LISTPTR(PyObject *op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Py_ssize_t offset = Py_TYPE(op)->tp_weaklistoffset; | 
					
						
							|  |  |  |     return (PyObject **)((char *)op + offset); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-15 02:11:20 +08:00
										 |  |  | // Fast inlined version of PyObject_IS_GC()
 | 
					
						
							|  |  |  | static inline int | 
					
						
							|  |  |  | _PyObject_IS_GC(PyObject *obj) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return (PyType_IS_GC(Py_TYPE(obj)) | 
					
						
							|  |  |  |             && (Py_TYPE(obj)->tp_is_gc == NULL | 
					
						
							|  |  |  |                 || Py_TYPE(obj)->tp_is_gc(obj))); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 01:42:27 +02:00
										 |  |  | // Fast inlined version of PyType_IS_GC()
 | 
					
						
							|  |  |  | #define _PyType_IS_GC(t) _PyType_HasFeature((t), Py_TPFLAGS_HAVE_GC)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-27 17:39:16 +01:00
										 |  |  | // Usage: assert(_Py_CheckSlotResult(obj, "__getitem__", result != NULL)));
 | 
					
						
							|  |  |  | extern int _Py_CheckSlotResult( | 
					
						
							|  |  |  |     PyObject *obj, | 
					
						
							|  |  |  |     const char *slot_name, | 
					
						
							|  |  |  |     int success); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-11 23:57:09 +02:00
										 |  |  | // PyType_Ready() must be called if _PyType_IsReady() is false.
 | 
					
						
							|  |  |  | // See also the Py_TPFLAGS_READY flag.
 | 
					
						
							|  |  |  | #define _PyType_IsReady(type) ((type)->tp_dict != NULL)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-01 02:30:46 +02:00
										 |  |  | extern PyObject* _PyType_AllocNoTrack(PyTypeObject *type, Py_ssize_t nitems); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 22:27:47 +01:00
										 |  |  | #ifdef __cplusplus
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #endif /* !Py_INTERNAL_OBJECT_H */
 |