@@ -53,36 +53,53 @@ extern "C" {
5353
5454#if  !defined(Py_GIL_DISABLED ) &&  defined(Py_STACKREF_DEBUG )
5555
56- #define  Py_TAG_BITS  0
56+ #define  Py_INT_TAG  3
57+ #define  Py_TAG_INVALID  2
58+ #define  Py_TAG_REFCNT  1
59+ #define  Py_TAG_BITS  3
5760
5861PyAPI_FUNC (PyObject  * ) _Py_stackref_get_object (_PyStackRef  ref );
5962PyAPI_FUNC (PyObject  * ) _Py_stackref_close (_PyStackRef  ref , const  char  * filename , int  linenumber );
60- PyAPI_FUNC (_PyStackRef ) _Py_stackref_create (PyObject  * obj , const  char  * filename , int  linenumber );
63+ PyAPI_FUNC (_PyStackRef ) _Py_stackref_create (PyObject  * obj , uint16_t   flags ,  const  char  * filename , int  linenumber );
6164PyAPI_FUNC (void ) _Py_stackref_record_borrow (_PyStackRef  ref , const  char  * filename , int  linenumber );
6265extern  void  _Py_stackref_associate (PyInterpreterState  * interp , PyObject  * obj , _PyStackRef  ref );
6366
6467static  const  _PyStackRef  PyStackRef_NULL  =  { .index  =  0  };
65- static  const  _PyStackRef  PyStackRef_ERROR  =  { .index  =  2  };
68+ static  const  _PyStackRef  PyStackRef_ERROR  =  { .index  =  4  };
6669
67- // Use the first 3 even numbers for None, True and False. 
68- // Odd numbers are reserved for (tagged) integers 
69- #define  PyStackRef_None  ((_PyStackRef){ .index = 4 } )
70- #define  PyStackRef_False  ((_PyStackRef){ .index = 6 })
71- #define  PyStackRef_True  ((_PyStackRef){ .index = 8 })
70+ #define  PyStackRef_None  ((_PyStackRef){ .index = 8 } )
71+ #define  PyStackRef_False  ((_PyStackRef){ .index = 12 })
72+ #define  PyStackRef_True  ((_PyStackRef){ .index = 16 })
7273
73- #define  INITIAL_STACKREF_INDEX  10 
74+ #define  INITIAL_STACKREF_INDEX  20 
7475
7576static  inline  _PyStackRef 
7677PyStackRef_Wrap (void  * ptr )
7778{
7879    assert (ptr  !=  NULL );
80+ #ifdef  Py_DEBUG 
81+     assert (((uint64_t )ptr  &  Py_TAG_BITS ) ==  0 );
82+     return  (_PyStackRef ){ .index  =  ((uint64_t )ptr ) | Py_TAG_INVALID  };
83+ #else 
7984    return  (_PyStackRef ){ .index  =  (uint64_t )ptr  };
85+ #endif 
8086}
8187
8288static  inline  void  * 
8389PyStackRef_Unwrap (_PyStackRef  ref )
8490{
91+ #ifdef  Py_DEBUG 
92+     assert  ((ref .index  &  Py_TAG_BITS ) ==  Py_TAG_INVALID );
93+     return  (void  * )(ref .index  &  ~Py_TAG_BITS );
94+ #else 
8595    return  (void  * )(ref .index );
96+ #endif 
97+ }
98+ 
99+ static  inline  int 
100+ PyStackRef_RefcountOnObject (_PyStackRef  ref )
101+ {
102+     return  (ref .index  &  Py_TAG_REFCNT ) ==  0 ;
86103}
87104
88105static  inline  int 
@@ -94,7 +111,7 @@ PyStackRef_IsNull(_PyStackRef ref)
94111static  inline  bool 
95112PyStackRef_IsError (_PyStackRef  ref )
96113{
97-     return  ref .index  ==  2 ;
114+     return  ref .index  ==  4 ;
98115}
99116
100117static  inline  bool 
@@ -125,7 +142,7 @@ PyStackRef_IsNone(_PyStackRef ref)
125142static  inline  bool 
126143PyStackRef_IsTaggedInt (_PyStackRef  ref )
127144{
128-     return  (ref .index  &  1 ) ==  1 ;
145+     return  (ref .index  &  Py_TAG_BITS ) ==  Py_INT_TAG ;
129146}
130147
131148static  inline  PyObject  * 
@@ -136,51 +153,68 @@ _PyStackRef_AsPyObjectBorrow(_PyStackRef ref, const char *filename, int linenumb
136153    _Py_stackref_record_borrow (ref , filename , linenumber );
137154    return  _Py_stackref_get_object (ref );
138155}
139- 
140156#define  PyStackRef_AsPyObjectBorrow (REF ) _PyStackRef_AsPyObjectBorrow((REF), __FILE__, __LINE__)
141157
142158static  inline  PyObject  * 
143159_PyStackRef_AsPyObjectSteal (_PyStackRef  ref , const  char  * filename , int  linenumber )
144160{
145-     return  _Py_stackref_close (ref , filename , linenumber );
161+     PyObject  * obj  =  _Py_stackref_close (ref , filename , linenumber );
162+     if  (PyStackRef_RefcountOnObject (ref )) {
163+         return  obj ;
164+     }
165+     return  Py_NewRef (obj );
146166}
147167#define  PyStackRef_AsPyObjectSteal (REF ) _PyStackRef_AsPyObjectSteal((REF), __FILE__, __LINE__)
148168
149169static  inline  _PyStackRef 
150170_PyStackRef_FromPyObjectNew (PyObject  * obj , const  char  * filename , int  linenumber )
151171{
152-     Py_INCREF (obj );
153-     return  _Py_stackref_create (obj , filename , linenumber );
172+     assert (obj  !=  NULL );
173+     uint16_t  flags  =  0 ;
174+     if  (!_Py_IsImmortal (obj )) {
175+         _Py_INCREF_MORTAL (obj );
176+     } else  {
177+         flags  =  Py_TAG_REFCNT ;
178+     }
179+     return  _Py_stackref_create (obj , flags , filename , linenumber );
154180}
155181#define  PyStackRef_FromPyObjectNew (obj ) _PyStackRef_FromPyObjectNew(_PyObject_CAST(obj), __FILE__, __LINE__)
156182
157183static  inline  _PyStackRef 
158184_PyStackRef_FromPyObjectSteal (PyObject  * obj , const  char  * filename , int  linenumber )
159185{
160-     return  _Py_stackref_create (obj , filename , linenumber );
186+     assert (obj  !=  NULL );
187+     uint16_t  flags  =  0 ;
188+     if  (_Py_IsImmortal (obj )) {
189+         flags  =  Py_TAG_REFCNT ;
190+     }
191+     return  _Py_stackref_create (obj , flags , filename , linenumber );
161192}
162193#define  PyStackRef_FromPyObjectSteal (obj ) _PyStackRef_FromPyObjectSteal(_PyObject_CAST(obj), __FILE__, __LINE__)
163194
164195static  inline  _PyStackRef 
165196_PyStackRef_FromPyObjectBorrow (PyObject  * obj , const  char  * filename , int  linenumber )
166197{
167-     Py_INCREF (obj );
168-     return  _Py_stackref_create (obj , filename , linenumber );
198+     return  _Py_stackref_create (obj , Py_TAG_REFCNT , filename , linenumber );
169199}
170200#define  PyStackRef_FromPyObjectBorrow (obj ) _PyStackRef_FromPyObjectBorrow(_PyObject_CAST(obj), __FILE__, __LINE__)
171201
172202static  inline  void 
173203_PyStackRef_CLOSE (_PyStackRef  ref , const  char  * filename , int  linenumber )
174204{
205+     assert (!PyStackRef_IsError (ref ));
206+     assert (!PyStackRef_IsNull (ref ));
175207    if  (PyStackRef_IsTaggedInt (ref )) {
176208        return ;
177209    }
178210    PyObject  * obj  =  _Py_stackref_close (ref , filename , linenumber );
179-     Py_DECREF (obj );
211+     assert (Py_REFCNT (obj ) >  0 );
212+     if  (PyStackRef_RefcountOnObject (ref )) {
213+         Py_DECREF (obj );
214+     }
180215}
181216#define  PyStackRef_CLOSE (REF ) _PyStackRef_CLOSE((REF), __FILE__, __LINE__)
182217
183- 
184218static  inline  void 
185219_PyStackRef_XCLOSE (_PyStackRef  ref , const  char  * filename , int  linenumber )
186220{
@@ -196,31 +230,46 @@ static inline _PyStackRef
196230_PyStackRef_DUP (_PyStackRef  ref , const  char  * filename , int  linenumber )
197231{
198232    assert (!PyStackRef_IsError (ref ));
233+     assert (!PyStackRef_IsNull (ref ));
199234    if  (PyStackRef_IsTaggedInt (ref )) {
200235        return  ref ;
201236    }
202-     else  {
203-         PyObject  * obj  =  _Py_stackref_get_object (ref );
237+     PyObject  * obj  =  _Py_stackref_get_object (ref );
238+     uint16_t  flags  =  0 ;
239+     if  (PyStackRef_RefcountOnObject (ref )) {
204240        Py_INCREF (obj );
205-         return  _Py_stackref_create (obj , filename , linenumber );
241+     } else  {
242+         flags  =  Py_TAG_REFCNT ;
206243    }
244+     return  _Py_stackref_create (obj , flags , filename , linenumber );
207245}
208246#define  PyStackRef_DUP (REF ) _PyStackRef_DUP(REF, __FILE__, __LINE__)
209247
210- extern  void  _PyStackRef_CLOSE_SPECIALIZED (_PyStackRef  ref , destructor  destruct , const  char  * filename , int  linenumber );
211- #define  PyStackRef_CLOSE_SPECIALIZED (REF , DESTRUCT ) _PyStackRef_CLOSE_SPECIALIZED(REF, DESTRUCT, __FILE__, __LINE__)
212- 
213- static  inline  _PyStackRef 
214- PyStackRef_MakeHeapSafe (_PyStackRef  ref )
248+ static  inline  void 
249+ _PyStackRef_CLOSE_SPECIALIZED (_PyStackRef  ref , destructor  destruct , const  char  * filename , int  linenumber )
215250{
216-     return  ref ;
251+     assert (!PyStackRef_IsError (ref ));
252+     assert (!PyStackRef_IsNull (ref ));
253+     assert (!PyStackRef_IsTaggedInt (ref ));
254+     PyObject  * obj  =  _Py_stackref_close (ref , filename , linenumber );
255+     if  (PyStackRef_RefcountOnObject (ref )) {
256+         _Py_DECREF_SPECIALIZED (obj , destruct );
257+     }
217258}
259+ #define  PyStackRef_CLOSE_SPECIALIZED (REF , DESTRUCT ) _PyStackRef_CLOSE_SPECIALIZED(REF, DESTRUCT, __FILE__, __LINE__)
218260
219261static  inline  _PyStackRef 
220- PyStackRef_Borrow (_PyStackRef  ref )
262+ _PyStackRef_Borrow (_PyStackRef  ref ,  const   char   * filename ,  int   linenumber )
221263{
222-     return  PyStackRef_DUP (ref );
264+     assert (!PyStackRef_IsError (ref ));
265+     assert (!PyStackRef_IsNull (ref ));
266+     if  (PyStackRef_IsTaggedInt (ref )) {
267+         return  ref ;
268+     }
269+     PyObject  * obj  =  _Py_stackref_get_object (ref );
270+     return  _Py_stackref_create (obj , Py_TAG_REFCNT , filename , linenumber );
223271}
272+ #define  PyStackRef_Borrow (REF ) _PyStackRef_Borrow((REF), __FILE__, __LINE__)
224273
225274#define  PyStackRef_CLEAR (REF ) \
226275    do { \
@@ -234,27 +283,44 @@ static inline _PyStackRef
234283_PyStackRef_FromPyObjectStealMortal (PyObject  * obj , const  char  * filename , int  linenumber )
235284{
236285    assert (!_Py_IsImmortal (obj ));
237-     return  _Py_stackref_create (obj , filename , linenumber );
286+     return  _Py_stackref_create (obj , 0 ,  filename , linenumber );
238287}
239288#define  PyStackRef_FromPyObjectStealMortal (obj ) _PyStackRef_FromPyObjectStealMortal(_PyObject_CAST(obj), __FILE__, __LINE__)
240289
241290static  inline  bool 
242291PyStackRef_IsHeapSafe (_PyStackRef  ref )
243292{
244-     return  true;
293+     if  ((ref .index  &  Py_TAG_BITS ) !=  Py_TAG_REFCNT  ||  PyStackRef_IsNull (ref )) {
294+         // Tagged ints and ERROR are included. 
295+         return  true;
296+     }
297+ 
298+     PyObject  * obj  =  _Py_stackref_get_object (ref );
299+     return  _Py_IsImmortal (obj );
245300}
246301
302+ static  inline  _PyStackRef 
303+ _PyStackRef_MakeHeapSafe (_PyStackRef  ref , const  char  * filename , int  linenumber )
304+ {
305+     if  (PyStackRef_IsHeapSafe (ref )) {
306+         return  ref ;
307+     }
308+ 
309+     PyObject  * obj  =  _Py_stackref_close (ref , filename , linenumber );
310+     Py_INCREF (obj );
311+     return  _Py_stackref_create (obj , 0 , filename , linenumber );
312+ }
313+ #define  PyStackRef_MakeHeapSafe (REF ) _PyStackRef_MakeHeapSafe(REF, __FILE__, __LINE__)
314+ 
247315static  inline  _PyStackRef 
248316_PyStackRef_FromPyObjectNewMortal (PyObject  * obj , const  char  * filename , int  linenumber )
249317{
250318    assert (!_Py_IsStaticImmortal (obj ));
251-     Py_INCREF (obj );
252-     return  _Py_stackref_create (obj , filename , linenumber );
319+     Py_XINCREF (obj );
320+     return  _Py_stackref_create (obj , 0 ,  filename , linenumber );
253321}
254322#define  PyStackRef_FromPyObjectNewMortal (obj ) _PyStackRef_FromPyObjectNewMortal(_PyObject_CAST(obj), __FILE__, __LINE__)
255323
256- #define  PyStackRef_RefcountOnObject (REF ) 1
257- 
258324extern  int  PyStackRef_Is (_PyStackRef  a , _PyStackRef  b );
259325
260326extern  bool  PyStackRef_IsTaggedInt (_PyStackRef  ref );
@@ -287,6 +353,7 @@ PyStackRef_Wrap(void *ptr)
287353{
288354    assert (ptr  !=  NULL );
289355#ifdef  Py_DEBUG 
356+     assert (((uintptr_t )ptr  &  Py_TAG_BITS ) ==  0 );
290357    return  (_PyStackRef ){ .bits  =  ((uintptr_t )ptr ) | Py_TAG_INVALID  };
291358#else 
292359    return  (_PyStackRef ){ .bits  =  (uintptr_t )ptr  };
0 commit comments