Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-11-19 09:50:50

0001 #ifndef Py_INTERNAL_STACKREF_H
0002 #define Py_INTERNAL_STACKREF_H
0003 #ifdef __cplusplus
0004 extern "C" {
0005 #endif
0006 
0007 #ifndef Py_BUILD_CORE
0008 #  error "this header requires Py_BUILD_CORE define"
0009 #endif
0010 
0011 #include <stddef.h>
0012 
0013 typedef union {
0014     uintptr_t bits;
0015 } _PyStackRef;
0016 
0017 static const _PyStackRef Py_STACKREF_NULL = { .bits = 0 };
0018 
0019 #define Py_TAG_DEFERRED (1)
0020 
0021 // Gets a PyObject * from a _PyStackRef
0022 #if defined(Py_GIL_DISABLED)
0023 static inline PyObject *
0024 PyStackRef_Get(_PyStackRef tagged)
0025 {
0026     PyObject *cleared = ((PyObject *)((tagged).bits & (~Py_TAG_DEFERRED)));
0027     return cleared;
0028 }
0029 #else
0030 #   define PyStackRef_Get(tagged) ((PyObject *)((tagged).bits))
0031 #endif
0032 
0033 // Converts a PyObject * to a PyStackRef, stealing the reference.
0034 #if defined(Py_GIL_DISABLED)
0035 static inline _PyStackRef
0036 _PyStackRef_StealRef(PyObject *obj)
0037 {
0038     // Make sure we don't take an already tagged value.
0039     assert(((uintptr_t)obj & Py_TAG_DEFERRED) == 0);
0040     return ((_PyStackRef){.bits = ((uintptr_t)(obj))});
0041 }
0042 #   define PyStackRef_StealRef(obj) _PyStackRef_StealRef(_PyObject_CAST(obj))
0043 #else
0044 #   define PyStackRef_StealRef(obj) ((_PyStackRef){.bits = ((uintptr_t)(obj))})
0045 #endif
0046 
0047 // Converts a PyObject * to a PyStackRef, with a new reference
0048 #if defined(Py_GIL_DISABLED)
0049 static inline _PyStackRef
0050 _PyStackRef_NewRefDeferred(PyObject *obj)
0051 {
0052     // Make sure we don't take an already tagged value.
0053     assert(((uintptr_t)obj & Py_TAG_DEFERRED) == 0);
0054     assert(obj != NULL);
0055     if (_PyObject_HasDeferredRefcount(obj)) {
0056         return (_PyStackRef){ .bits = (uintptr_t)obj | Py_TAG_DEFERRED };
0057     }
0058     else {
0059         return (_PyStackRef){ .bits = (uintptr_t)Py_NewRef(obj) };
0060     }
0061 }
0062 #   define PyStackRef_NewRefDeferred(obj) _PyStackRef_NewRefDeferred(_PyObject_CAST(obj))
0063 #else
0064 #   define PyStackRef_NewRefDeferred(obj) PyStackRef_NewRef(((_PyStackRef){.bits = ((uintptr_t)(obj))}))
0065 #endif
0066 
0067 #if defined(Py_GIL_DISABLED)
0068 static inline _PyStackRef
0069 _PyStackRef_XNewRefDeferred(PyObject *obj)
0070 {
0071     // Make sure we don't take an already tagged value.
0072     assert(((uintptr_t)obj & Py_TAG_DEFERRED) == 0);
0073     if (obj == NULL) {
0074         return Py_STACKREF_NULL;
0075     }
0076     return _PyStackRef_NewRefDeferred(obj);
0077 }
0078 #   define PyStackRef_XNewRefDeferred(obj) _PyStackRef_XNewRefDeferred(_PyObject_CAST(obj))
0079 #else
0080 #   define PyStackRef_XNewRefDeferred(obj) PyStackRef_XNewRef(((_PyStackRef){.bits = ((uintptr_t)(obj))}))
0081 #endif
0082 
0083 // Converts a PyStackRef back to a PyObject *.
0084 #if defined(Py_GIL_DISABLED)
0085 static inline PyObject *
0086 PyStackRef_StealObject(_PyStackRef tagged)
0087 {
0088     if ((tagged.bits & Py_TAG_DEFERRED) == Py_TAG_DEFERRED) {
0089         assert(_PyObject_HasDeferredRefcount(PyStackRef_Get(tagged)));
0090         return Py_NewRef(PyStackRef_Get(tagged));
0091     }
0092     return PyStackRef_Get(tagged);
0093 }
0094 #else
0095 #   define PyStackRef_StealObject(tagged) PyStackRef_Get(tagged)
0096 #endif
0097 
0098 static inline void
0099 _Py_untag_stack_borrowed(PyObject **dst, const _PyStackRef *src, size_t length)
0100 {
0101     for (size_t i = 0; i < length; i++) {
0102         dst[i] = PyStackRef_Get(src[i]);
0103     }
0104 }
0105 
0106 static inline void
0107 _Py_untag_stack_steal(PyObject **dst, const _PyStackRef *src, size_t length)
0108 {
0109     for (size_t i = 0; i < length; i++) {
0110         dst[i] = PyStackRef_StealObject(src[i]);
0111     }
0112 }
0113 
0114 
0115 #define PyStackRef_XSETREF(dst, src) \
0116     do { \
0117         _PyStackRef *_tmp_dst_ptr = &(dst); \
0118         _PyStackRef _tmp_old_dst = (*_tmp_dst_ptr); \
0119         *_tmp_dst_ptr = (src); \
0120         PyStackRef_XDECREF(_tmp_old_dst); \
0121     } while (0)
0122 
0123 #define PyStackRef_SETREF(dst, src) \
0124     do { \
0125         _PyStackRef *_tmp_dst_ptr = &(dst); \
0126         _PyStackRef _tmp_old_dst = (*_tmp_dst_ptr); \
0127         *_tmp_dst_ptr = (src); \
0128         PyStackRef_DECREF(_tmp_old_dst); \
0129     } while (0)
0130 
0131 #define PyStackRef_CLEAR(op) \
0132     do { \
0133         _PyStackRef *_tmp_op_ptr = &(op); \
0134         _PyStackRef _tmp_old_op = (*_tmp_op_ptr); \
0135         if (_tmp_old_op.bits != Py_STACKREF_NULL.bits) { \
0136             *_tmp_op_ptr = Py_STACKREF_NULL; \
0137             PyStackRef_DECREF(_tmp_old_op); \
0138         } \
0139     } while (0)
0140 
0141 #if defined(Py_GIL_DISABLED)
0142 static inline void
0143 PyStackRef_DECREF(_PyStackRef tagged)
0144 {
0145     if ((tagged.bits & Py_TAG_DEFERRED) == Py_TAG_DEFERRED) {
0146         return;
0147     }
0148     Py_DECREF(PyStackRef_Get(tagged));
0149 }
0150 #else
0151 #   define PyStackRef_DECREF(op) Py_DECREF(PyStackRef_Get(op))
0152 #endif
0153 
0154 #if defined(Py_GIL_DISABLED)
0155 static inline void
0156 PyStackRef_INCREF(_PyStackRef tagged)
0157 {
0158     if ((tagged.bits & Py_TAG_DEFERRED) == Py_TAG_DEFERRED) {
0159         assert(_PyObject_HasDeferredRefcount(PyStackRef_Get(tagged)));
0160         return;
0161     }
0162     Py_INCREF(PyStackRef_Get(tagged));
0163 }
0164 #else
0165 #   define PyStackRef_INCREF(op) Py_INCREF(PyStackRef_Get(op))
0166 #endif
0167 
0168 static inline void
0169 PyStackRef_XDECREF(_PyStackRef op)
0170 {
0171     if (op.bits != Py_STACKREF_NULL.bits) {
0172         PyStackRef_DECREF(op);
0173     }
0174 }
0175 
0176 static inline _PyStackRef
0177 PyStackRef_NewRef(_PyStackRef obj)
0178 {
0179     PyStackRef_INCREF(obj);
0180     return obj;
0181 }
0182 
0183 static inline _PyStackRef
0184 PyStackRef_XNewRef(_PyStackRef obj)
0185 {
0186     if (obj.bits == Py_STACKREF_NULL.bits) {
0187         return obj;
0188     }
0189     return PyStackRef_NewRef(obj);
0190 }
0191 
0192 #ifdef __cplusplus
0193 }
0194 #endif
0195 #endif /* !Py_INTERNAL_STACKREF_H */