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