@@ -2930,6 +2930,39 @@ Py_ReprLeave(PyObject *obj)
29302930
29312931/* Trashcan support. */ 
29322932
2933+ /* We need to store a pointer in the refcount field of 
2934+  * an object. It is important that we never store 0 (NULL). 
2935+ * It is also important to not make the object appear immortal, 
2936+ * or it might be untracked by the cycle GC. */ 
2937+ uintptr_t 
2938+ pointer_to_safe_refcount (void  * ptr )
2939+ {
2940+     uintptr_t  full  =  (uintptr_t )ptr ;
2941+     assert ((full  &  3 ) ==  0 );
2942+ #if  defined(Py_GIL_DISABLED )
2943+     return  full  +  1 ;
2944+ #else 
2945+     uint32_t  refcnt  =  (uint32_t )full ;
2946+     if  (refcnt  >= (uint32_t )_Py_IMMORTAL_MINIMUM_REFCNT ) {
2947+         full  =  full  -  ((uintptr_t )_Py_IMMORTAL_MINIMUM_REFCNT ) +  1 ;
2948+     }
2949+     return  full  +  2 ;
2950+ #endif 
2951+ }
2952+ 
2953+ void  * 
2954+ safe_refcount_to_pointer (uintptr_t  refcnt )
2955+ {
2956+ #if  defined(Py_GIL_DISABLED )
2957+     return  (void  * )(refcnt  -  1 );
2958+ #else 
2959+     if  (refcnt  &  1 ) {
2960+         refcnt  +=  _Py_IMMORTAL_MINIMUM_REFCNT  -  1 ;
2961+     }
2962+     return  (void  * )(refcnt  -  2 );
2963+ #endif 
2964+ }
2965+ 
29332966/* Add op to the gcstate->trash_delete_later list.  Called when the current 
29342967 * call-stack depth gets large.  op must be a currently untracked gc'ed 
29352968 * object, with refcount 0.  Py_DECREF must already have been called on it. 
@@ -2941,11 +2974,10 @@ _PyTrash_thread_deposit_object(PyThreadState *tstate, PyObject *op)
29412974#ifdef  Py_GIL_DISABLED 
29422975    op -> ob_tid  =  (uintptr_t )tstate -> delete_later ;
29432976#else 
2944-     /* Store the delete_later pointer in the refcnt field. 
2945-      * As this object may still be tracked by the GC, 
2946-      * it is important that we never store 0 (NULL). */ 
2947-     uintptr_t  refcnt  =  (uintptr_t )tstate -> delete_later ;
2948-     * ((uintptr_t * )op ) =  refcnt + 1 ;
2977+     /* Store the delete_later pointer in the refcnt field. */ 
2978+     uintptr_t  refcnt  =  pointer_to_safe_refcount (tstate -> delete_later );
2979+     * ((uintptr_t * )op ) =  refcnt ;
2980+     assert (!_Py_IsImmortal (op ));
29492981#endif 
29502982    tstate -> delete_later  =  op ;
29512983}
@@ -2967,7 +2999,7 @@ _PyTrash_thread_destroy_chain(PyThreadState *tstate)
29672999        /* Get the delete_later pointer from the refcnt field. 
29683000         * See _PyTrash_thread_deposit_object(). */ 
29693001        uintptr_t  refcnt  =  * ((uintptr_t * )op );
2970-         tstate -> delete_later  =  ( PyObject   * )( refcnt   -   1 );
3002+         tstate -> delete_later  =  safe_refcount_to_pointer ( refcnt );
29713003        op -> ob_refcnt  =  0 ;
29723004#endif 
29733005
0 commit comments