@@ -169,6 +169,48 @@ _PyDebug_PrintTotalRefs(void) {
169169#define REFCHAIN (interp ) interp->object_state.refchain
170170#define REFCHAIN_VALUE ((void*)(uintptr_t)1)
171171
172+ static inline int
173+ has_own_refchain (PyInterpreterState * interp )
174+ {
175+ if (interp -> feature_flags & Py_RTFLAGS_USE_MAIN_OBMALLOC ) {
176+ return (_Py_IsMainInterpreter (interp )
177+ || _PyInterpreterState_Main () == NULL );
178+ }
179+ return 1 ;
180+ }
181+
182+ static int
183+ refchain_init (PyInterpreterState * interp )
184+ {
185+ if (!has_own_refchain (interp )) {
186+ // Legacy subinterpreters share a refchain with the main interpreter.
187+ REFCHAIN (interp ) = REFCHAIN (_PyInterpreterState_Main ());
188+ return 0 ;
189+ }
190+ _Py_hashtable_allocator_t alloc = {
191+ // Don't use default PyMem_Malloc() and PyMem_Free() which
192+ // require the caller to hold the GIL.
193+ .malloc = PyMem_RawMalloc ,
194+ .free = PyMem_RawFree ,
195+ };
196+ REFCHAIN (interp ) = _Py_hashtable_new_full (
197+ _Py_hashtable_hash_ptr , _Py_hashtable_compare_direct ,
198+ NULL , NULL , & alloc );
199+ if (REFCHAIN (interp ) == NULL ) {
200+ return -1 ;
201+ }
202+ return 0 ;
203+ }
204+
205+ static void
206+ refchain_fini (PyInterpreterState * interp )
207+ {
208+ if (has_own_refchain (interp ) && REFCHAIN (interp ) != NULL ) {
209+ _Py_hashtable_destroy (REFCHAIN (interp ));
210+ }
211+ REFCHAIN (interp ) = NULL ;
212+ }
213+
172214bool
173215_PyRefchain_IsTraced (PyInterpreterState * interp , PyObject * obj )
174216{
@@ -2171,16 +2213,7 @@ PyStatus
21712213_PyObject_InitState (PyInterpreterState * interp )
21722214{
21732215#ifdef Py_TRACE_REFS
2174- _Py_hashtable_allocator_t alloc = {
2175- // Don't use default PyMem_Malloc() and PyMem_Free() which
2176- // require the caller to hold the GIL.
2177- .malloc = PyMem_RawMalloc ,
2178- .free = PyMem_RawFree ,
2179- };
2180- REFCHAIN (interp ) = _Py_hashtable_new_full (
2181- _Py_hashtable_hash_ptr , _Py_hashtable_compare_direct ,
2182- NULL , NULL , & alloc );
2183- if (REFCHAIN (interp ) == NULL ) {
2216+ if (refchain_init (interp ) < 0 ) {
21842217 return _PyStatus_NO_MEMORY ();
21852218 }
21862219#endif
@@ -2191,8 +2224,7 @@ void
21912224_PyObject_FiniState (PyInterpreterState * interp )
21922225{
21932226#ifdef Py_TRACE_REFS
2194- _Py_hashtable_destroy (REFCHAIN (interp ));
2195- REFCHAIN (interp ) = NULL ;
2227+ refchain_fini (interp );
21962228#endif
21972229}
21982230
@@ -2481,42 +2513,6 @@ _Py_ResurrectReference(PyObject *op)
24812513
24822514
24832515#ifdef Py_TRACE_REFS
2484- /* Make sure the ref is associated with the right interpreter.
2485- * This only needs special attention for heap-allocated objects
2486- * that have been immortalized, and only when the object might
2487- * outlive the interpreter where it was created. That means the
2488- * object was necessarily created using a global allocator
2489- * (i.e. from the main interpreter). Thus in that specific case
2490- * we move the object over to the main interpreter's refchain.
2491- *
2492- * This was added for the sake of the immortal interned strings,
2493- * where legacy subinterpreters share the main interpreter's
2494- * interned dict (and allocator), and therefore the strings can
2495- * outlive the subinterpreter.
2496- *
2497- * It may make sense to fold this into _Py_SetImmortalUntracked(),
2498- * but that requires further investigation. In the meantime, it is
2499- * up to the caller to know if this is needed. There should be
2500- * very few cases.
2501- */
2502- void
2503- _Py_NormalizeImmortalReference (PyObject * op )
2504- {
2505- assert (_Py_IsImmortal (op ));
2506- PyInterpreterState * interp = _PyInterpreterState_GET ();
2507- if (!_PyRefchain_IsTraced (interp , op )) {
2508- return ;
2509- }
2510- PyInterpreterState * main_interp = _PyInterpreterState_Main ();
2511- if (interp != main_interp
2512- && interp -> feature_flags & Py_RTFLAGS_USE_MAIN_OBMALLOC )
2513- {
2514- assert (!_PyRefchain_IsTraced (main_interp , op ));
2515- _PyRefchain_Remove (interp , op );
2516- _PyRefchain_Trace (main_interp , op );
2517- }
2518- }
2519-
25202516void
25212517_Py_ForgetReference (PyObject * op )
25222518{
0 commit comments