@@ -452,184 +452,6 @@ PyStackRef_IncrementTaggedIntNoOverflow(_PyStackRef ref)
452452 return (_PyStackRef ){ .bits = ref .bits + (1 << Py_TAGGED_SHIFT ) };
453453}
454454
455- #define PyStackRef_IsDeferredOrTaggedInt (ref ) (((ref).bits & Py_TAG_REFCNT) != 0)
456-
457- #ifdef Py_GIL_DISABLED
458-
459- #define Py_TAG_DEFERRED Py_TAG_REFCNT
460-
461- #define Py_TAG_PTR ((uintptr_t)0)
462-
463-
464- static const _PyStackRef PyStackRef_NULL = { .bits = Py_TAG_DEFERRED };
465-
466- #define PyStackRef_IsNull (stackref ) ((stackref).bits == PyStackRef_NULL.bits)
467- #define PyStackRef_True ((_PyStackRef){.bits = ((uintptr_t)&_Py_TrueStruct) | Py_TAG_DEFERRED })
468- #define PyStackRef_False ((_PyStackRef){.bits = ((uintptr_t)&_Py_FalseStruct) | Py_TAG_DEFERRED })
469- #define PyStackRef_None ((_PyStackRef){.bits = ((uintptr_t)&_Py_NoneStruct) | Py_TAG_DEFERRED })
470-
471- // Checks that mask out the deferred bit in the free threading build.
472- #define PyStackRef_IsNone (ref ) (PyStackRef_AsPyObjectBorrow(ref) == Py_None)
473- #define PyStackRef_IsTrue (ref ) (PyStackRef_AsPyObjectBorrow(ref) == Py_True)
474- #define PyStackRef_IsFalse (ref ) (PyStackRef_AsPyObjectBorrow(ref) == Py_False)
475-
476- #define PyStackRef_IsNullOrInt (stackref ) (PyStackRef_IsNull(stackref) || PyStackRef_IsTaggedInt(stackref))
477-
478- static inline PyObject *
479- PyStackRef_AsPyObjectBorrow (_PyStackRef stackref )
480- {
481- assert (!PyStackRef_IsTaggedInt (stackref ));
482- PyObject * cleared = ((PyObject * )((stackref ).bits & (~Py_TAG_BITS )));
483- return cleared ;
484- }
485-
486- #define PyStackRef_IsDeferred (ref ) (((ref).bits & Py_TAG_BITS) == Py_TAG_DEFERRED)
487-
488- static inline PyObject *
489- PyStackRef_AsPyObjectSteal (_PyStackRef stackref )
490- {
491- assert (!PyStackRef_IsNull (stackref ));
492- if (PyStackRef_IsDeferred (stackref )) {
493- return Py_NewRef (PyStackRef_AsPyObjectBorrow (stackref ));
494- }
495- return PyStackRef_AsPyObjectBorrow (stackref );
496- }
497-
498- static inline _PyStackRef
499- _PyStackRef_FromPyObjectSteal (PyObject * obj )
500- {
501- assert (obj != NULL );
502- // Make sure we don't take an already tagged value.
503- assert (((uintptr_t )obj & Py_TAG_BITS ) == 0 );
504- return (_PyStackRef ){ .bits = (uintptr_t )obj };
505- }
506- # define PyStackRef_FromPyObjectSteal (obj ) _PyStackRef_FromPyObjectSteal(_PyObject_CAST(obj))
507-
508- static inline bool
509- PyStackRef_IsHeapSafe (_PyStackRef stackref )
510- {
511- if (PyStackRef_IsDeferred (stackref )) {
512- PyObject * obj = PyStackRef_AsPyObjectBorrow (stackref );
513- return obj == NULL || _Py_IsImmortal (obj ) || _PyObject_HasDeferredRefcount (obj );
514- }
515- return true;
516- }
517-
518- static inline _PyStackRef
519- PyStackRef_MakeHeapSafe (_PyStackRef stackref )
520- {
521- if (PyStackRef_IsHeapSafe (stackref )) {
522- return stackref ;
523- }
524- PyObject * obj = PyStackRef_AsPyObjectBorrow (stackref );
525- return (_PyStackRef ){ .bits = (uintptr_t )(Py_NewRef (obj )) | Py_TAG_PTR };
526- }
527-
528- static inline _PyStackRef
529- PyStackRef_FromPyObjectStealMortal (PyObject * obj )
530- {
531- assert (obj != NULL );
532- assert (!_Py_IsImmortal (obj ));
533- // Make sure we don't take an already tagged value.
534- assert (((uintptr_t )obj & Py_TAG_BITS ) == 0 );
535- return (_PyStackRef ){ .bits = (uintptr_t )obj };
536- }
537-
538- static inline _PyStackRef
539- PyStackRef_FromPyObjectNew (PyObject * obj )
540- {
541- // Make sure we don't take an already tagged value.
542- assert (((uintptr_t )obj & Py_TAG_BITS ) == 0 );
543- assert (obj != NULL );
544- if (_PyObject_HasDeferredRefcount (obj )) {
545- return (_PyStackRef ){ .bits = (uintptr_t )obj | Py_TAG_DEFERRED };
546- }
547- else {
548- return (_PyStackRef ){ .bits = (uintptr_t )(Py_NewRef (obj )) | Py_TAG_PTR };
549- }
550- }
551- #define PyStackRef_FromPyObjectNew (obj ) PyStackRef_FromPyObjectNew(_PyObject_CAST(obj))
552-
553- static inline _PyStackRef
554- PyStackRef_FromPyObjectBorrow (PyObject * obj )
555- {
556- // Make sure we don't take an already tagged value.
557- assert (((uintptr_t )obj & Py_TAG_BITS ) == 0 );
558- assert (obj != NULL );
559- return (_PyStackRef ){ .bits = (uintptr_t )obj | Py_TAG_DEFERRED };
560- }
561- #define PyStackRef_FromPyObjectBorrow (obj ) PyStackRef_FromPyObjectBorrow(_PyObject_CAST(obj))
562-
563- #define PyStackRef_CLOSE (REF ) \
564- do { \
565- _PyStackRef _close_tmp = (REF); \
566- assert(!PyStackRef_IsNull(_close_tmp)); \
567- if (!PyStackRef_IsDeferredOrTaggedInt(_close_tmp)) { \
568- Py_DECREF(PyStackRef_AsPyObjectBorrow(_close_tmp)); \
569- } \
570- } while (0)
571-
572- static inline void
573- PyStackRef_CLOSE_SPECIALIZED (_PyStackRef ref , destructor destruct )
574- {
575- (void )destruct ;
576- PyStackRef_CLOSE (ref );
577- }
578-
579- static inline int
580- PyStackRef_RefcountOnObject (_PyStackRef ref )
581- {
582- return (ref .bits & Py_TAG_REFCNT ) == 0 ;
583- }
584-
585- static inline _PyStackRef
586- PyStackRef_DUP (_PyStackRef stackref )
587- {
588- assert (!PyStackRef_IsNull (stackref ));
589- if (PyStackRef_IsDeferredOrTaggedInt (stackref )) {
590- return stackref ;
591- }
592- Py_INCREF (PyStackRef_AsPyObjectBorrow (stackref ));
593- return stackref ;
594- }
595-
596- static inline _PyStackRef
597- PyStackRef_Borrow (_PyStackRef stackref )
598- {
599- return (_PyStackRef ){ .bits = stackref .bits | Py_TAG_DEFERRED };
600- }
601-
602- // Convert a possibly deferred reference to a strong reference.
603- static inline _PyStackRef
604- PyStackRef_AsStrongReference (_PyStackRef stackref )
605- {
606- return PyStackRef_FromPyObjectSteal (PyStackRef_AsPyObjectSteal (stackref ));
607- }
608-
609- #define PyStackRef_XCLOSE (stackref ) \
610- do { \
611- _PyStackRef _tmp = (stackref); \
612- if (!PyStackRef_IsNull(_tmp)) { \
613- PyStackRef_CLOSE(_tmp); \
614- } \
615- } while (0);
616-
617- #define PyStackRef_CLEAR (op ) \
618- do { \
619- _PyStackRef *_tmp_op_ptr = &(op); \
620- _PyStackRef _tmp_old_op = (*_tmp_op_ptr); \
621- if (!PyStackRef_IsNull(_tmp_old_op)) { \
622- *_tmp_op_ptr = PyStackRef_NULL; \
623- PyStackRef_CLOSE(_tmp_old_op); \
624- } \
625- } while (0)
626-
627- #define PyStackRef_FromPyObjectNewMortal PyStackRef_FromPyObjectNew
628-
629- #else // Py_GIL_DISABLED
630-
631- // With GIL
632-
633455/* References to immortal objects always have their tag bit set to Py_TAG_REFCNT
634456 * as they can (must) have their reclamation deferred */
635457
@@ -648,13 +470,24 @@ static const _PyStackRef PyStackRef_NULL = { .bits = PyStackRef_NULL_BITS };
648470#define PyStackRef_False ((_PyStackRef){.bits = ((uintptr_t)&_Py_FalseStruct) | Py_TAG_REFCNT })
649471#define PyStackRef_None ((_PyStackRef){.bits = ((uintptr_t)&_Py_NoneStruct) | Py_TAG_REFCNT })
650472
473+ #ifdef Py_GIL_DISABLED
474+ // Checks that mask out the deferred bit in the free threading build.
475+ #define PyStackRef_IsNone (REF ) (((REF).bits & ~Py_TAG_REFCNT) == (uintptr_t)&_Py_NoneStruct)
476+ #define PyStackRef_IsTrue (REF ) (((REF).bits & ~Py_TAG_REFCNT) == (uintptr_t)&_Py_TrueStruct)
477+ #define PyStackRef_IsFalse (REF ) (((REF).bits & ~Py_TAG_REFCNT) == (uintptr_t)&_Py_FalseStruct)
478+ #else
651479#define PyStackRef_IsTrue (REF ) ((REF).bits == (((uintptr_t)&_Py_TrueStruct) | Py_TAG_REFCNT))
652480#define PyStackRef_IsFalse (REF ) ((REF).bits == (((uintptr_t)&_Py_FalseStruct) | Py_TAG_REFCNT))
653481#define PyStackRef_IsNone (REF ) ((REF).bits == (((uintptr_t)&_Py_NoneStruct) | Py_TAG_REFCNT))
482+ #endif
654483
655- #ifdef Py_DEBUG
484+ #define PyStackRef_IsNullOrInt (stackref ) (PyStackRef_IsNull(stackref) || PyStackRef_IsTaggedInt(stackref))
485+
486+ #if defined(Py_DEBUG ) && !defined(Py_GIL_DISABLED )
656487
657- static inline void PyStackRef_CheckValid (_PyStackRef ref ) {
488+ static inline void
489+ PyStackRef_CheckValid (_PyStackRef ref )
490+ {
658491 assert (ref .bits != 0 );
659492 int tag = ref .bits & Py_TAG_BITS ;
660493 PyObject * obj = BITS_TO_PTR_MASKED (ref );
@@ -705,6 +538,8 @@ PyStackRef_Borrow(_PyStackRef ref)
705538static inline PyObject *
706539PyStackRef_AsPyObjectSteal (_PyStackRef ref )
707540{
541+ assert (!PyStackRef_IsNull (ref ));
542+ assert (!PyStackRef_IsTaggedInt (ref ));
708543 if (PyStackRef_RefcountOnObject (ref )) {
709544 return BITS_TO_PTR (ref );
710545 }
@@ -717,22 +552,26 @@ static inline _PyStackRef
717552PyStackRef_FromPyObjectSteal (PyObject * obj )
718553{
719554 assert (obj != NULL );
720- #if SIZEOF_VOID_P > 4
721- unsigned int tag = obj -> ob_flags & Py_TAG_REFCNT ;
555+ #ifdef Py_GIL_DISABLED
556+ return ( _PyStackRef ){ . bits = ( uintptr_t ) obj } ;
722557#else
558+ # if SIZEOF_VOID_P > 4
559+ unsigned int tag = obj -> ob_flags & Py_TAG_REFCNT ;
560+ # else
723561 unsigned int tag = _Py_IsImmortal (obj ) ? Py_TAG_REFCNT : 0 ;
724- #endif
562+ # endif
725563 _PyStackRef ref = ((_PyStackRef ){.bits = ((uintptr_t )(obj )) | tag });
726564 PyStackRef_CheckValid (ref );
727565 return ref ;
566+ #endif
728567}
729568
730569static inline _PyStackRef
731570PyStackRef_FromPyObjectStealMortal (PyObject * obj )
732571{
733572 assert (obj != NULL );
734573 assert (!_Py_IsImmortal (obj ));
735- _PyStackRef ref = (( _PyStackRef ){.bits = (( uintptr_t )( obj )) }) ;
574+ _PyStackRef ref = (_PyStackRef ){ .bits = (uintptr_t )obj } ;
736575 PyStackRef_CheckValid (ref );
737576 return ref ;
738577}
@@ -741,9 +580,15 @@ static inline _PyStackRef
741580_PyStackRef_FromPyObjectNew (PyObject * obj )
742581{
743582 assert (obj != NULL );
583+ #ifdef Py_GIL_DISABLED
584+ if (_PyObject_HasDeferredRefcount (obj )) {
585+ return (_PyStackRef ){ .bits = (uintptr_t )obj | Py_TAG_REFCNT };
586+ }
587+ #else
744588 if (_Py_IsImmortal (obj )) {
745- return (_PyStackRef ){ .bits = (( uintptr_t )obj ) | Py_TAG_REFCNT };
589+ return (_PyStackRef ){ .bits = (uintptr_t )obj | Py_TAG_REFCNT };
746590 }
591+ #endif
747592 _Py_INCREF_MORTAL (obj );
748593 _PyStackRef ref = (_PyStackRef ){ .bits = (uintptr_t )obj };
749594 PyStackRef_CheckValid (ref );
@@ -766,6 +611,7 @@ _PyStackRef_FromPyObjectNewMortal(PyObject *obj)
766611static inline _PyStackRef
767612PyStackRef_FromPyObjectBorrow (PyObject * obj )
768613{
614+ assert (obj != NULL );
769615 return (_PyStackRef ){ .bits = (uintptr_t )obj | Py_TAG_REFCNT };
770616}
771617
@@ -788,7 +634,15 @@ PyStackRef_DUP(_PyStackRef ref)
788634static inline bool
789635PyStackRef_IsHeapSafe (_PyStackRef ref )
790636{
791- return (ref .bits & Py_TAG_BITS ) != Py_TAG_REFCNT || ref .bits == PyStackRef_NULL_BITS || _Py_IsImmortal (BITS_TO_PTR_MASKED (ref ));
637+ #ifdef Py_GIL_DISABLED
638+ if ((ref .bits & Py_TAG_BITS ) != Py_TAG_REFCNT ) {
639+ return true;
640+ }
641+ PyObject * obj = BITS_TO_PTR_MASKED (ref );
642+ return obj == NULL || _PyObject_HasDeferredRefcount (obj );
643+ #else
644+ return (ref .bits & Py_TAG_BITS ) != Py_TAG_REFCNT || ref .bits == PyStackRef_NULL_BITS || _Py_IsImmortal (BITS_TO_PTR_MASKED (ref ));
645+ #endif
792646}
793647
794648static inline _PyStackRef
@@ -804,6 +658,13 @@ PyStackRef_MakeHeapSafe(_PyStackRef ref)
804658 return ref ;
805659}
806660
661+ // Convert a possibly deferred reference to a strong reference.
662+ static inline _PyStackRef
663+ PyStackRef_AsStrongReference (_PyStackRef stackref )
664+ {
665+ return PyStackRef_FromPyObjectSteal (PyStackRef_AsPyObjectSteal (stackref ));
666+ }
667+
807668#ifdef _WIN32
808669#define PyStackRef_CLOSE (REF ) \
809670do { \
@@ -821,12 +682,6 @@ PyStackRef_CLOSE(_PyStackRef ref)
821682}
822683#endif
823684
824- static inline bool
825- PyStackRef_IsNullOrInt (_PyStackRef ref )
826- {
827- return PyStackRef_IsNull (ref ) || PyStackRef_IsTaggedInt (ref );
828- }
829-
830685static inline void
831686PyStackRef_CLOSE_SPECIALIZED (_PyStackRef ref , destructor destruct )
832687{
@@ -859,8 +714,6 @@ PyStackRef_XCLOSE(_PyStackRef ref)
859714 } while (0)
860715
861716
862- #endif // Py_GIL_DISABLED
863-
864717// Note: this is a macro because MSVC (Windows) has trouble inlining it.
865718
866719#define PyStackRef_Is (a , b ) (((a).bits & (~Py_TAG_REFCNT)) == ((b).bits & (~Py_TAG_REFCNT)))
@@ -945,7 +798,7 @@ static inline int
945798_Py_TryIncrefCompareStackRef (PyObject * * src , PyObject * op , _PyStackRef * out )
946799{
947800 if (_PyObject_HasDeferredRefcount (op )) {
948- * out = (_PyStackRef ){ .bits = (uintptr_t )op | Py_TAG_DEFERRED };
801+ * out = (_PyStackRef ){ .bits = (uintptr_t )op | Py_TAG_REFCNT };
949802 return 1 ;
950803 }
951804 if (_Py_TryIncrefCompare (src , op )) {
0 commit comments