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
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
0034 #if defined(Py_GIL_DISABLED)
0035 static inline _PyStackRef
0036 _PyStackRef_StealRef(PyObject *obj)
0037 {
0038
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
0048 #if defined(Py_GIL_DISABLED)
0049 static inline _PyStackRef
0050 _PyStackRef_NewRefDeferred(PyObject *obj)
0051 {
0052
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
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
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