LCOV - code coverage report
Current view: | top level - Include/internal - pycore_object.h (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 73 | 73 | 100.0 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 19 | 19 | 100.0 %
|  |  | Branches: | 14 | 14 | 100.0 %

               Branch data     Line data    Source code
           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 <stdbool.h>
          12                 :            : #include "pycore_gc.h"            // _PyObject_GC_IS_TRACKED()
          13                 :            : #include "pycore_interp.h"        // PyInterpreterState.gc
          14                 :            : #include "pycore_pystate.h"       // _PyInterpreterState_GET()
          15                 :            : #include "pycore_runtime.h"       // _PyRuntime
          16                 :            :
          17                 :            : /* This value provides *effective* immortality, meaning the object should never
          18                 :            :     be deallocated (until runtime finalization).  See PEP 683 for more details about
          19                 :            :     immortality, as well as a proposed mechanism for proper immortality. */
          20                 :            : #define _PyObject_IMMORTAL_REFCNT 999999999
          21                 :            :
          22                 :            : #define _PyObject_IMMORTAL_INIT(type) \
          23                 :            :     { \
          24                 :            :         .ob_refcnt = _PyObject_IMMORTAL_REFCNT, \
          25                 :            :         .ob_type = (type), \
          26                 :            :     }
          27                 :            : #define _PyVarObject_IMMORTAL_INIT(type, size) \
          28                 :            :     { \
          29                 :            :         .ob_base = _PyObject_IMMORTAL_INIT(type), \
          30                 :            :         .ob_size = size, \
          31                 :            :     }
          32                 :            :
          33                 :            : PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalRefcountErrorFunc(
          34                 :            :     const char *func,
          35                 :            :     const char *message);
          36                 :            :
          37                 :            : #define _Py_FatalRefcountError(message) \
          38                 :            :     _Py_FatalRefcountErrorFunc(__func__, (message))
          39                 :            :
          40                 :            :
          41                 :            : #ifdef Py_REF_DEBUG
          42                 :            : /* The symbol is only exposed in the API for the sake of extensions
          43                 :            :    built against the pre-3.12 stable ABI. */
          44                 :            : PyAPI_DATA(Py_ssize_t) _Py_RefTotal;
          45                 :            :
          46                 :            : extern void _Py_AddRefTotal(Py_ssize_t);
          47                 :            : extern void _Py_IncRefTotal(void);
          48                 :            : extern void _Py_DecRefTotal(void);
          49                 :            : #  define _Py_DEC_REFTOTAL() _Py_RefTotal--
          50                 :            : #endif
          51                 :            :
          52                 :            : // Increment reference count by n
          53                 :       6210 : static inline void _Py_RefcntAdd(PyObject* op, Py_ssize_t n)
          54                 :            : {
          55                 :            : #ifdef Py_REF_DEBUG
          56                 :            :     _Py_AddRefTotal(n);
          57                 :            : #endif
          58                 :       6210 :     op->ob_refcnt += n;
          59                 :       6210 : }
          60                 :            : #define _Py_RefcntAdd(op, n) _Py_RefcntAdd(_PyObject_CAST(op), n)
          61                 :            :
          62                 :            : static inline void
          63                 :     459375 : _Py_DECREF_SPECIALIZED(PyObject *op, const destructor destruct)
          64                 :            : {
          65                 :            :     _Py_DECREF_STAT_INC();
          66                 :            : #ifdef Py_REF_DEBUG
          67                 :            :     _Py_DEC_REFTOTAL();
          68                 :            : #endif
          69         [ +  + ]:     459375 :     if (--op->ob_refcnt != 0) {
          70                 :            :         assert(op->ob_refcnt > 0);
          71                 :            :     }
          72                 :            :     else {
          73                 :            : #ifdef Py_TRACE_REFS
          74                 :            :         _Py_ForgetReference(op);
          75                 :            : #endif
          76                 :     459357 :         destruct(op);
          77                 :            :     }
          78                 :     459375 : }
          79                 :            :
          80                 :            : static inline void
          81                 :    3644366 : _Py_DECREF_NO_DEALLOC(PyObject *op)
          82                 :            : {
          83                 :            :     _Py_DECREF_STAT_INC();
          84                 :            : #ifdef Py_REF_DEBUG
          85                 :            :     _Py_DEC_REFTOTAL();
          86                 :            : #endif
          87                 :    3644366 :     op->ob_refcnt--;
          88                 :            : #ifdef Py_DEBUG
          89                 :            :     if (op->ob_refcnt <= 0) {
          90                 :            :         _Py_FatalRefcountError("Expected a positive remaining refcount");
          91                 :            :     }
          92                 :            : #endif
          93                 :    3644366 : }
          94                 :            :
          95                 :            : #ifdef Py_REF_DEBUG
          96                 :            : #  undef _Py_DEC_REFTOTAL
          97                 :            : #endif
          98                 :            :
          99                 :            :
         100                 :            : PyAPI_FUNC(int) _PyType_CheckConsistency(PyTypeObject *type);
         101                 :            : PyAPI_FUNC(int) _PyDict_CheckConsistency(PyObject *mp, int check_content);
         102                 :            :
         103                 :            : /* Update the Python traceback of an object. This function must be called
         104                 :            :    when a memory block is reused from a free list.
         105                 :            :
         106                 :            :    Internal function called by _Py_NewReference(). */
         107                 :            : extern int _PyTraceMalloc_NewReference(PyObject *op);
         108                 :            :
         109                 :            : // Fast inlined version of PyType_HasFeature()
         110                 :            : static inline int
         111                 :   69717451 : _PyType_HasFeature(PyTypeObject *type, unsigned long feature) {
         112                 :   69717451 :     return ((type->tp_flags & feature) != 0);
         113                 :            : }
         114                 :            :
         115                 :            : extern void _PyType_InitCache(PyInterpreterState *interp);
         116                 :            :
         117                 :            :
         118                 :            : /* Inline functions trading binary compatibility for speed:
         119                 :            :    _PyObject_Init() is the fast version of PyObject_Init(), and
         120                 :            :    _PyObject_InitVar() is the fast version of PyObject_InitVar().
         121                 :            :
         122                 :            :    These inline functions must not be called with op=NULL. */
         123                 :            : static inline void
         124                 :   25240595 : _PyObject_Init(PyObject *op, PyTypeObject *typeobj)
         125                 :            : {
         126                 :            :     assert(op != NULL);
         127                 :   25240595 :     Py_SET_TYPE(op, typeobj);
         128         [ +  + ]:   25240595 :     if (_PyType_HasFeature(typeobj, Py_TPFLAGS_HEAPTYPE)) {
         129                 :    2143043 :         Py_INCREF(typeobj);
         130                 :            :     }
         131                 :   25240595 :     _Py_NewReference(op);
         132                 :   25240595 : }
         133                 :            :
         134                 :            : static inline void
         135                 :    8769025 : _PyObject_InitVar(PyVarObject *op, PyTypeObject *typeobj, Py_ssize_t size)
         136                 :            : {
         137                 :            :     assert(op != NULL);
         138                 :    8769025 :     Py_SET_SIZE(op, size);
         139                 :    8769025 :     _PyObject_Init((PyObject *)op, typeobj);
         140                 :    8769025 : }
         141                 :            :
         142                 :            :
         143                 :            : /* Tell the GC to track this object.
         144                 :            :  *
         145                 :            :  * The object must not be tracked by the GC.
         146                 :            :  *
         147                 :            :  * NB: While the object is tracked by the collector, it must be safe to call the
         148                 :            :  * ob_traverse method.
         149                 :            :  *
         150                 :            :  * Internal note: interp->gc.generation0->_gc_prev doesn't have any bit flags
         151                 :            :  * because it's not object header.  So we don't use _PyGCHead_PREV() and
         152                 :            :  * _PyGCHead_SET_PREV() for it to avoid unnecessary bitwise operations.
         153                 :            :  *
         154                 :            :  * See also the public PyObject_GC_Track() function.
         155                 :            :  */
         156                 :   12272735 : static inline void _PyObject_GC_TRACK(
         157                 :            : // The preprocessor removes _PyObject_ASSERT_FROM() calls if NDEBUG is defined
         158                 :            : #ifndef NDEBUG
         159                 :            :     const char *filename, int lineno,
         160                 :            : #endif
         161                 :            :     PyObject *op)
         162                 :            : {
         163                 :            :     _PyObject_ASSERT_FROM(op, !_PyObject_GC_IS_TRACKED(op),
         164                 :            :                           "object already tracked by the garbage collector",
         165                 :            :                           filename, lineno, __func__);
         166                 :            :
         167                 :   12272735 :     PyGC_Head *gc = _Py_AS_GC(op);
         168                 :            :     _PyObject_ASSERT_FROM(op,
         169                 :            :                           (gc->_gc_prev & _PyGC_PREV_MASK_COLLECTING) == 0,
         170                 :            :                           "object is in generation which is garbage collected",
         171                 :            :                           filename, lineno, __func__);
         172                 :            :
         173                 :   12272735 :     PyInterpreterState *interp = _PyInterpreterState_GET();
         174                 :   12272735 :     PyGC_Head *generation0 = interp->gc.generation0;
         175                 :   12272735 :     PyGC_Head *last = (PyGC_Head*)(generation0->_gc_prev);
         176                 :   12272735 :     _PyGCHead_SET_NEXT(last, gc);
         177                 :   12272735 :     _PyGCHead_SET_PREV(gc, last);
         178                 :   12272735 :     _PyGCHead_SET_NEXT(gc, generation0);
         179                 :   12272735 :     generation0->_gc_prev = (uintptr_t)gc;
         180                 :   12272735 : }
         181                 :            :
         182                 :            : /* Tell the GC to stop tracking this object.
         183                 :            :  *
         184                 :            :  * Internal note: This may be called while GC. So _PyGC_PREV_MASK_COLLECTING
         185                 :            :  * must be cleared. But _PyGC_PREV_MASK_FINALIZED bit is kept.
         186                 :            :  *
         187                 :            :  * The object must be tracked by the GC.
         188                 :            :  *
         189                 :            :  * See also the public PyObject_GC_UnTrack() which accept an object which is
         190                 :            :  * not tracked.
         191                 :            :  */
         192                 :   12258515 : static inline void _PyObject_GC_UNTRACK(
         193                 :            : // The preprocessor removes _PyObject_ASSERT_FROM() calls if NDEBUG is defined
         194                 :            : #ifndef NDEBUG
         195                 :            :     const char *filename, int lineno,
         196                 :            : #endif
         197                 :            :     PyObject *op)
         198                 :            : {
         199                 :            :     _PyObject_ASSERT_FROM(op, _PyObject_GC_IS_TRACKED(op),
         200                 :            :                           "object not tracked by the garbage collector",
         201                 :            :                           filename, lineno, __func__);
         202                 :            :
         203                 :   12258515 :     PyGC_Head *gc = _Py_AS_GC(op);
         204                 :   12258515 :     PyGC_Head *prev = _PyGCHead_PREV(gc);
         205                 :   12258515 :     PyGC_Head *next = _PyGCHead_NEXT(gc);
         206                 :   12258515 :     _PyGCHead_SET_NEXT(prev, next);
         207                 :   12258515 :     _PyGCHead_SET_PREV(next, prev);
         208                 :   12258515 :     gc->_gc_next = 0;
         209                 :   12258515 :     gc->_gc_prev &= _PyGC_PREV_MASK_FINALIZED;
         210                 :   12258515 : }
         211                 :            :
         212                 :            : // Macros to accept any type for the parameter, and to automatically pass
         213                 :            : // the filename and the filename (if NDEBUG is not defined) where the macro
         214                 :            : // is called.
         215                 :            : #ifdef NDEBUG
         216                 :            : #  define _PyObject_GC_TRACK(op) \
         217                 :            :         _PyObject_GC_TRACK(_PyObject_CAST(op))
         218                 :            : #  define _PyObject_GC_UNTRACK(op) \
         219                 :            :         _PyObject_GC_UNTRACK(_PyObject_CAST(op))
         220                 :            : #else
         221                 :            : #  define _PyObject_GC_TRACK(op) \
         222                 :            :         _PyObject_GC_TRACK(__FILE__, __LINE__, _PyObject_CAST(op))
         223                 :            : #  define _PyObject_GC_UNTRACK(op) \
         224                 :            :         _PyObject_GC_UNTRACK(__FILE__, __LINE__, _PyObject_CAST(op))
         225                 :            : #endif
         226                 :            :
         227                 :            : #ifdef Py_REF_DEBUG
         228                 :            : extern void _PyDebug_PrintTotalRefs(void);
         229                 :            : #endif
         230                 :            :
         231                 :            : #ifdef Py_TRACE_REFS
         232                 :            : extern void _Py_AddToAllObjects(PyObject *op, int force);
         233                 :            : extern void _Py_PrintReferences(FILE *);
         234                 :            : extern void _Py_PrintReferenceAddresses(FILE *);
         235                 :            : #endif
         236                 :            :
         237                 :            :
         238                 :            : /* Return the *address* of the object's weaklist.  The address may be
         239                 :            :  * dereferenced to get the current head of the weaklist.  This is useful
         240                 :            :  * for iterating over the linked list of weakrefs, especially when the
         241                 :            :  * list is being modified externally (e.g. refs getting removed).
         242                 :            :  *
         243                 :            :  * The returned pointer should not be used to change the head of the list
         244                 :            :  * nor should it be used to add, remove, or swap any refs in the list.
         245                 :            :  * That is the sole responsibility of the code in weakrefobject.c.
         246                 :            :  */
         247                 :            : static inline PyObject **
         248                 :     689556 : _PyObject_GET_WEAKREFS_LISTPTR(PyObject *op)
         249                 :            : {
         250         [ +  + ]:     689556 :     if (PyType_Check(op) &&
         251         [ +  + ]:     136173 :             ((PyTypeObject *)op)->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
         252                 :      92819 :         static_builtin_state *state = _PyStaticType_GetState(
         253                 :            :                                                         (PyTypeObject *)op);
         254                 :      92819 :         return _PyStaticType_GET_WEAKREFS_LISTPTR(state);
         255                 :            :     }
         256                 :            :     // Essentially _PyObject_GET_WEAKREFS_LISTPTR_FROM_OFFSET():
         257                 :     596737 :     Py_ssize_t offset = Py_TYPE(op)->tp_weaklistoffset;
         258                 :     596737 :     return (PyObject **)((char *)op + offset);
         259                 :            : }
         260                 :            :
         261                 :            : /* This is a special case of _PyObject_GET_WEAKREFS_LISTPTR().
         262                 :            :  * Only the most fundamental lookup path is used.
         263                 :            :  * Consequently, static types should not be used.
         264                 :            :  *
         265                 :            :  * For static builtin types the returned pointer will always point
         266                 :            :  * to a NULL tp_weaklist.  This is fine for any deallocation cases,
         267                 :            :  * since static types are never deallocated and static builtin types
         268                 :            :  * are only finalized at the end of runtime finalization.
         269                 :            :  *
         270                 :            :  * If the weaklist for static types is actually needed then use
         271                 :            :  * _PyObject_GET_WEAKREFS_LISTPTR().
         272                 :            :  */
         273                 :            : static inline PyWeakReference **
         274                 :      37119 : _PyObject_GET_WEAKREFS_LISTPTR_FROM_OFFSET(PyObject *op)
         275                 :            : {
         276                 :            :     assert(!PyType_Check(op) ||
         277                 :            :             ((PyTypeObject *)op)->tp_flags & Py_TPFLAGS_HEAPTYPE);
         278                 :      37119 :     Py_ssize_t offset = Py_TYPE(op)->tp_weaklistoffset;
         279                 :      37119 :     return (PyWeakReference **)((char *)op + offset);
         280                 :            : }
         281                 :            :
         282                 :            :
         283                 :            : // Fast inlined version of PyObject_IS_GC()
         284                 :            : static inline int
         285                 :   18308554 : _PyObject_IS_GC(PyObject *obj)
         286                 :            : {
         287                 :   18308554 :     return (PyType_IS_GC(Py_TYPE(obj))
         288   [ +  +  +  + ]:   20774847 :             && (Py_TYPE(obj)->tp_is_gc == NULL
         289         [ +  + ]:    2466293 :                 || Py_TYPE(obj)->tp_is_gc(obj)));
         290                 :            : }
         291                 :            :
         292                 :            : // Fast inlined version of PyType_IS_GC()
         293                 :            : #define _PyType_IS_GC(t) _PyType_HasFeature((t), Py_TPFLAGS_HAVE_GC)
         294                 :            :
         295                 :            : static inline size_t
         296                 :   17975480 : _PyType_PreHeaderSize(PyTypeObject *tp)
         297                 :            : {
         298                 :   17975480 :     return _PyType_IS_GC(tp) * sizeof(PyGC_Head) +
         299                 :   17975480 :         _PyType_HasFeature(tp, Py_TPFLAGS_PREHEADER) * 2 * sizeof(PyObject *);
         300                 :            : }
         301                 :            :
         302                 :            : void _PyObject_GC_Link(PyObject *op);
         303                 :            :
         304                 :            : // Usage: assert(_Py_CheckSlotResult(obj, "__getitem__", result != NULL));
         305                 :            : extern int _Py_CheckSlotResult(
         306                 :            :     PyObject *obj,
         307                 :            :     const char *slot_name,
         308                 :            :     int success);
         309                 :            :
         310                 :            : // PyType_Ready() must be called if _PyType_IsReady() is false.
         311                 :            : // See also the Py_TPFLAGS_READY flag.
         312                 :            : #define _PyType_IsReady(type) ((type)->tp_dict != NULL)
         313                 :            :
         314                 :            : // Test if a type supports weak references
         315                 :     753866 : static inline int _PyType_SUPPORTS_WEAKREFS(PyTypeObject *type) {
         316                 :     753866 :     return (type->tp_weaklistoffset != 0);
         317                 :            : }
         318                 :            :
         319                 :            : extern PyObject* _PyType_AllocNoTrack(PyTypeObject *type, Py_ssize_t nitems);
         320                 :            :
         321                 :            : extern int _PyObject_InitializeDict(PyObject *obj);
         322                 :            : extern int _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values,
         323                 :            :                                           PyObject *name, PyObject *value);
         324                 :            : PyObject * _PyObject_GetInstanceAttribute(PyObject *obj, PyDictValues *values,
         325                 :            :                                         PyObject *name);
         326                 :            :
         327                 :            : typedef union {
         328                 :            :     PyObject *dict;
         329                 :            :     /* Use a char* to generate a warning if directly assigning a PyDictValues */
         330                 :            :     char *values;
         331                 :            : } PyDictOrValues;
         332                 :            :
         333                 :            : static inline PyDictOrValues *
         334                 :    5873932 : _PyObject_DictOrValuesPointer(PyObject *obj)
         335                 :            : {
         336                 :            :     assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
         337                 :    5873932 :     return ((PyDictOrValues *)obj)-3;
         338                 :            : }
         339                 :            :
         340                 :            : static inline int
         341                 :    5735663 : _PyDictOrValues_IsValues(PyDictOrValues dorv)
         342                 :            : {
         343                 :    5735663 :     return ((uintptr_t)dorv.values) & 1;
         344                 :            : }
         345                 :            :
         346                 :            : static inline PyDictValues *
         347                 :    3110280 : _PyDictOrValues_GetValues(PyDictOrValues dorv)
         348                 :            : {
         349                 :            :     assert(_PyDictOrValues_IsValues(dorv));
         350                 :    3110280 :     return (PyDictValues *)(dorv.values + 1);
         351                 :            : }
         352                 :            :
         353                 :            : static inline PyObject *
         354                 :    1267282 : _PyDictOrValues_GetDict(PyDictOrValues dorv)
         355                 :            : {
         356                 :            :     assert(!_PyDictOrValues_IsValues(dorv));
         357                 :    1267282 :     return dorv.dict;
         358                 :            : }
         359                 :            :
         360                 :            : static inline void
         361                 :     138267 : _PyDictOrValues_SetValues(PyDictOrValues *ptr, PyDictValues *values)
         362                 :            : {
         363                 :     138267 :     ptr->values = ((char *)values) - 1;
         364                 :     138267 : }
         365                 :            :
         366                 :            : #define MANAGED_WEAKREF_OFFSET (((Py_ssize_t)sizeof(PyObject *))*-4)
         367                 :            :
         368                 :            : extern PyObject ** _PyObject_ComputedDictPointer(PyObject *);
         369                 :            : extern void _PyObject_FreeInstanceAttributes(PyObject *obj);
         370                 :            : extern int _PyObject_IsInstanceDictEmpty(PyObject *);
         371                 :            : extern int _PyType_HasSubclasses(PyTypeObject *);
         372                 :            : extern PyObject* _PyType_GetSubclasses(PyTypeObject *);
         373                 :            : extern PyObject* _PyObject_GenericTryGetAttr(PyObject *, PyObject *);
         374                 :            :
         375                 :            : // Access macro to the members which are floating "behind" the object
         376                 :     149971 : static inline PyMemberDef* _PyHeapType_GET_MEMBERS(PyHeapTypeObject *etype) {
         377                 :     149971 :     return (PyMemberDef*)((char*)etype + Py_TYPE(etype)->tp_basicsize);
         378                 :            : }
         379                 :            :
         380                 :            : PyAPI_FUNC(PyObject *) _PyObject_LookupSpecial(PyObject *, PyObject *);
         381                 :            :
         382                 :            : /* C function call trampolines to mitigate bad function pointer casts.
         383                 :            :  *
         384                 :            :  * Typical native ABIs ignore additional arguments or fill in missing
         385                 :            :  * values with 0/NULL in function pointer cast. Compilers do not show
         386                 :            :  * warnings when a function pointer is explicitly casted to an
         387                 :            :  * incompatible type.
         388                 :            :  *
         389                 :            :  * Bad fpcasts are an issue in WebAssembly. WASM's indirect_call has strict
         390                 :            :  * function signature checks. Argument count, types, and return type must
         391                 :            :  * match.
         392                 :            :  *
         393                 :            :  * Third party code unintentionally rely on problematic fpcasts. The call
         394                 :            :  * trampoline mitigates common occurrences of bad fpcasts on Emscripten.
         395                 :            :  */
         396                 :            : #if defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE)
         397                 :            : #define _PyCFunction_TrampolineCall(meth, self, args) \
         398                 :            :     _PyCFunctionWithKeywords_TrampolineCall( \
         399                 :            :         (*(PyCFunctionWithKeywords)(void(*)(void))(meth)), (self), (args), NULL)
         400                 :            : extern PyObject* _PyCFunctionWithKeywords_TrampolineCall(
         401                 :            :     PyCFunctionWithKeywords meth, PyObject *, PyObject *, PyObject *);
         402                 :            : #else
         403                 :            : #define _PyCFunction_TrampolineCall(meth, self, args) \
         404                 :            :     (meth)((self), (args))
         405                 :            : #define _PyCFunctionWithKeywords_TrampolineCall(meth, self, args, kw) \
         406                 :            :     (meth)((self), (args), (kw))
         407                 :            : #endif // __EMSCRIPTEN__ && PY_CALL_TRAMPOLINE
         408                 :            :
         409                 :            : #ifdef __cplusplus
         410                 :            : }
         411                 :            : #endif
         412                 :            : #endif /* !Py_INTERNAL_OBJECT_H */

Generated by: LCOV version 1.14