@@ -232,18 +232,22 @@ extern intptr_t PyStackRef_UntagInt(_PyStackRef ref);
232232
233233extern _PyStackRef PyStackRef_TagInt (intptr_t i );
234234
235+ /* Increments a tagged int, but does not check for overflow */
236+ extern _PyStackRef PyStackRef_IncrementTaggedIntNoOverflow (_PyStackRef ref );
237+
235238extern bool
236239PyStackRef_IsNullOrInt (_PyStackRef ref );
237240
238241#else
239242
240243#define Py_INT_TAG 3
241244#define Py_TAG_REFCNT 1
245+ #define Py_TAG_BITS 3
242246
243247static inline bool
244248PyStackRef_IsTaggedInt (_PyStackRef i )
245249{
246- return (i .bits & Py_INT_TAG ) == Py_INT_TAG ;
250+ return (i .bits & Py_TAG_BITS ) == Py_INT_TAG ;
247251}
248252
249253static inline _PyStackRef
@@ -262,12 +266,21 @@ PyStackRef_UntagInt(_PyStackRef i)
262266}
263267
264268
269+ static inline _PyStackRef
270+ PyStackRef_IncrementTaggedIntNoOverflow (_PyStackRef ref )
271+ {
272+ assert ((ref .bits & Py_TAG_BITS ) == Py_INT_TAG ); // Is tagged int
273+ assert ((ref .bits & (~Py_TAG_BITS )) != (INT_MAX & (~Py_TAG_BITS ))); // Isn't about to overflow
274+ return (_PyStackRef ){ .bits = ref .bits + 4 };
275+ }
276+
277+ #define PyStackRef_IsDeferredOrTaggedInt (ref ) (((ref).bits & Py_TAG_REFCNT) != 0)
278+
265279#ifdef Py_GIL_DISABLED
266280
267281#define Py_TAG_DEFERRED Py_TAG_REFCNT
268282
269283#define Py_TAG_PTR ((uintptr_t)0)
270- #define Py_TAG_BITS ((uintptr_t)1)
271284
272285
273286static const _PyStackRef PyStackRef_NULL = { .bits = Py_TAG_DEFERRED };
@@ -379,7 +392,7 @@ PyStackRef_FromPyObjectBorrow(PyObject *obj)
379392 do { \
380393 _PyStackRef _close_tmp = (REF); \
381394 assert(!PyStackRef_IsNull(_close_tmp)); \
382- if (!PyStackRef_IsDeferred (_close_tmp)) { \
395+ if (!PyStackRef_IsDeferredOrTaggedInt (_close_tmp)) { \
383396 Py_DECREF(PyStackRef_AsPyObjectBorrow(_close_tmp)); \
384397 } \
385398 } while (0)
@@ -395,7 +408,7 @@ static inline _PyStackRef
395408PyStackRef_DUP (_PyStackRef stackref )
396409{
397410 assert (!PyStackRef_IsNull (stackref ));
398- if (PyStackRef_IsDeferred (stackref )) {
411+ if (PyStackRef_IsDeferredOrTaggedInt (stackref )) {
399412 return stackref ;
400413 }
401414 Py_INCREF (PyStackRef_AsPyObjectBorrow (stackref ));
@@ -442,7 +455,6 @@ PyStackRef_AsStrongReference(_PyStackRef stackref)
442455/* References to immortal objects always have their tag bit set to Py_TAG_REFCNT
443456 * as they can (must) have their reclamation deferred */
444457
445- #define Py_TAG_BITS 3
446458#if _Py_IMMORTAL_FLAGS != Py_TAG_REFCNT
447459# error "_Py_IMMORTAL_FLAGS != Py_TAG_REFCNT"
448460#endif
@@ -678,50 +690,44 @@ PyStackRef_XCLOSE(_PyStackRef ref)
678690
679691#endif // !defined(Py_GIL_DISABLED) && defined(Py_STACKREF_DEBUG)
680692
681- #define PyStackRef_TYPE (stackref ) Py_TYPE(PyStackRef_AsPyObjectBorrow(stackref))
693+ static inline PyTypeObject *
694+ PyStackRef_TYPE (_PyStackRef stackref ) {
695+ if (PyStackRef_IsTaggedInt (stackref )) {
696+ return & PyLong_Type ;
697+ }
698+ return Py_TYPE (PyStackRef_AsPyObjectBorrow (stackref ));
699+ }
682700
683701// Converts a PyStackRef back to a PyObject *, converting the
684702// stackref to a new reference.
685703#define PyStackRef_AsPyObjectNew (stackref ) Py_NewRef(PyStackRef_AsPyObjectBorrow(stackref))
686704
687705// StackRef type checks
688706
689- static inline bool
690- PyStackRef_GenCheck (_PyStackRef stackref )
691- {
692- return PyGen_Check (PyStackRef_AsPyObjectBorrow (stackref ));
693- }
707+ #define STACKREF_CHECK_FUNC (T ) \
708+ static inline bool \
709+ PyStackRef_ ## T ## Check(_PyStackRef stackref) { \
710+ if (PyStackRef_IsTaggedInt(stackref)) { \
711+ return false; \
712+ } \
713+ return Py ## T ## _Check(PyStackRef_AsPyObjectBorrow(stackref)); \
714+ }
694715
695- static inline bool
696- PyStackRef_BoolCheck ( _PyStackRef stackref )
697- {
698- return PyBool_Check ( PyStackRef_AsPyObjectBorrow ( stackref ));
699- }
716+ STACKREF_CHECK_FUNC ( Gen )
717+ STACKREF_CHECK_FUNC ( Bool )
718+ STACKREF_CHECK_FUNC ( ExceptionInstance )
719+ STACKREF_CHECK_FUNC ( Code )
720+ STACKREF_CHECK_FUNC ( Function )
700721
701722static inline bool
702723PyStackRef_LongCheck (_PyStackRef stackref )
703724{
725+ if (PyStackRef_IsTaggedInt (stackref )) {
726+ return true;
727+ }
704728 return PyLong_Check (PyStackRef_AsPyObjectBorrow (stackref ));
705729}
706730
707- static inline bool
708- PyStackRef_ExceptionInstanceCheck (_PyStackRef stackref )
709- {
710- return PyExceptionInstance_Check (PyStackRef_AsPyObjectBorrow (stackref ));
711- }
712-
713- static inline bool
714- PyStackRef_CodeCheck (_PyStackRef stackref )
715- {
716- return PyCode_Check (PyStackRef_AsPyObjectBorrow (stackref ));
717- }
718-
719- static inline bool
720- PyStackRef_FunctionCheck (_PyStackRef stackref )
721- {
722- return PyFunction_Check (PyStackRef_AsPyObjectBorrow (stackref ));
723- }
724-
725731static inline void
726732_PyThreadState_PushCStackRef (PyThreadState * tstate , _PyCStackRef * ref )
727733{
0 commit comments