@@ -171,6 +171,48 @@ _PyDebug_PrintTotalRefs(void) {
171171#define REFCHAIN (interp ) interp->object_state.refchain
172172#define REFCHAIN_VALUE ((void*)(uintptr_t)1)
173173
174+ static inline int
175+ has_own_refchain (PyInterpreterState * interp )
176+ {
177+ if (interp -> feature_flags & Py_RTFLAGS_USE_MAIN_OBMALLOC ) {
178+ return (_Py_IsMainInterpreter (interp )
179+ || _PyInterpreterState_Main () == NULL );
180+ }
181+ return 1 ;
182+ }
183+
184+ static int
185+ refchain_init (PyInterpreterState * interp )
186+ {
187+ if (!has_own_refchain (interp )) {
188+ // Legacy subinterpreters share a refchain with the main interpreter.
189+ REFCHAIN (interp ) = REFCHAIN (_PyInterpreterState_Main ());
190+ return 0 ;
191+ }
192+ _Py_hashtable_allocator_t alloc = {
193+ // Don't use default PyMem_Malloc() and PyMem_Free() which
194+ // require the caller to hold the GIL.
195+ .malloc = PyMem_RawMalloc ,
196+ .free = PyMem_RawFree ,
197+ };
198+ REFCHAIN (interp ) = _Py_hashtable_new_full (
199+ _Py_hashtable_hash_ptr , _Py_hashtable_compare_direct ,
200+ NULL , NULL , & alloc );
201+ if (REFCHAIN (interp ) == NULL ) {
202+ return -1 ;
203+ }
204+ return 0 ;
205+ }
206+
207+ static void
208+ refchain_fini (PyInterpreterState * interp )
209+ {
210+ if (has_own_refchain (interp ) && REFCHAIN (interp ) != NULL ) {
211+ _Py_hashtable_destroy (REFCHAIN (interp ));
212+ }
213+ REFCHAIN (interp ) = NULL ;
214+ }
215+
174216bool
175217_PyRefchain_IsTraced (PyInterpreterState * interp , PyObject * obj )
176218{
@@ -2191,16 +2233,7 @@ PyStatus
21912233_PyObject_InitState (PyInterpreterState * interp )
21922234{
21932235#ifdef Py_TRACE_REFS
2194- _Py_hashtable_allocator_t alloc = {
2195- // Don't use default PyMem_Malloc() and PyMem_Free() which
2196- // require the caller to hold the GIL.
2197- .malloc = PyMem_RawMalloc ,
2198- .free = PyMem_RawFree ,
2199- };
2200- REFCHAIN (interp ) = _Py_hashtable_new_full (
2201- _Py_hashtable_hash_ptr , _Py_hashtable_compare_direct ,
2202- NULL , NULL , & alloc );
2203- if (REFCHAIN (interp ) == NULL ) {
2236+ if (refchain_init (interp ) < 0 ) {
22042237 return _PyStatus_NO_MEMORY ();
22052238 }
22062239#endif
@@ -2211,8 +2244,7 @@ void
22112244_PyObject_FiniState (PyInterpreterState * interp )
22122245{
22132246#ifdef Py_TRACE_REFS
2214- _Py_hashtable_destroy (REFCHAIN (interp ));
2215- REFCHAIN (interp ) = NULL ;
2247+ refchain_fini (interp );
22162248#endif
22172249}
22182250
@@ -2501,42 +2533,6 @@ _Py_ResurrectReference(PyObject *op)
25012533
25022534
25032535#ifdef Py_TRACE_REFS
2504- /* Make sure the ref is associated with the right interpreter.
2505- * This only needs special attention for heap-allocated objects
2506- * that have been immortalized, and only when the object might
2507- * outlive the interpreter where it was created. That means the
2508- * object was necessarily created using a global allocator
2509- * (i.e. from the main interpreter). Thus in that specific case
2510- * we move the object over to the main interpreter's refchain.
2511- *
2512- * This was added for the sake of the immortal interned strings,
2513- * where legacy subinterpreters share the main interpreter's
2514- * interned dict (and allocator), and therefore the strings can
2515- * outlive the subinterpreter.
2516- *
2517- * It may make sense to fold this into _Py_SetImmortalUntracked(),
2518- * but that requires further investigation. In the meantime, it is
2519- * up to the caller to know if this is needed. There should be
2520- * very few cases.
2521- */
2522- void
2523- _Py_NormalizeImmortalReference (PyObject * op )
2524- {
2525- assert (_Py_IsImmortal (op ));
2526- PyInterpreterState * interp = _PyInterpreterState_GET ();
2527- if (!_PyRefchain_IsTraced (interp , op )) {
2528- return ;
2529- }
2530- PyInterpreterState * main_interp = _PyInterpreterState_Main ();
2531- if (interp != main_interp
2532- && interp -> feature_flags & Py_RTFLAGS_USE_MAIN_OBMALLOC )
2533- {
2534- assert (!_PyRefchain_IsTraced (main_interp , op ));
2535- _PyRefchain_Remove (interp , op );
2536- _PyRefchain_Trace (main_interp , op );
2537- }
2538- }
2539-
25402536void
25412537_Py_ForgetReference (PyObject * op )
25422538{
0 commit comments