@@ -260,46 +260,6 @@ _PyExecutor_Free(_PyExecutorObject *self)
260260 PyObject_GC_Del (self );
261261}
262262
263- void
264- _Py_ClearExecutorDeletionList (PyThreadState * tstate )
265- {
266- _PyThreadStateImpl * ts = (_PyThreadStateImpl * )tstate ;
267- _PyExecutorObject * * prev_to_next_ptr = & ts -> jit_executor_state .executor_deletion_list_head ;
268- _PyExecutorObject * exec = * prev_to_next_ptr ;
269- // Mark the currently executing executor.
270- if (tstate -> current_executor != NULL ) {
271- ((_PyExecutorObject * )tstate -> current_executor )-> vm_data .linked = 1 ;
272- }
273- while (exec != NULL ) {
274- if (exec -> vm_data .linked ) {
275- // This executor is currently executing
276- exec -> vm_data .linked = 0 ;
277- prev_to_next_ptr = & exec -> vm_data .links .next ;
278- }
279- else {
280- * prev_to_next_ptr = exec -> vm_data .links .next ;
281- assert (exec != _PyExecutor_GetColdDynamicExecutor ());
282- assert (exec != _PyExecutor_GetColdExecutor ());
283- _PyExecutor_Free (exec );
284- }
285- exec = * prev_to_next_ptr ;
286- }
287- ts -> jit_executor_state .executor_deletion_list_remaining_capacity = EXECUTOR_DELETE_LIST_MAX ;
288- }
289-
290- static void
291- add_to_pending_deletion_list (_PyExecutorObject * self )
292- {
293- _PyThreadStateImpl * _tstate = (_PyThreadStateImpl * )_PyThreadState_GET ();
294- self -> vm_data .links .next = _tstate -> jit_executor_state .executor_deletion_list_head ;
295- _tstate -> jit_executor_state .executor_deletion_list_head = self ;
296- if (_tstate -> jit_executor_state .executor_deletion_list_remaining_capacity > 0 ) {
297- _tstate -> jit_executor_state .executor_deletion_list_remaining_capacity -- ;
298- }
299- else {
300- _Py_ClearExecutorDeletionList (& _tstate -> base );
301- }
302- }
303263
304264static void
305265uop_dealloc (PyObject * op ) {
@@ -309,7 +269,7 @@ uop_dealloc(PyObject *op) {
309269 unlink_executor (self );
310270 // Once unlinked it becomes impossible to invalidate an executor, so do it here.
311271 self -> vm_data .valid = 0 ;
312- add_to_pending_deletion_list (self );
272+ PyObject_GC_Del (self );
313273}
314274
315275const char *
@@ -1672,10 +1632,6 @@ executor_clear(PyObject *op)
16721632 assert (FT_ATOMIC_LOAD_UINT8_RELAXED (executor -> vm_data .valid ) == 0 );
16731633 unlink_executor (executor );
16741634
1675- /* It is possible for an executor to form a reference
1676- * cycle with itself, so decref'ing a side exit could
1677- * free the executor unless we hold a strong reference to it
1678- */
16791635 _PyExecutorObject * cold = _PyExecutor_GetColdExecutor ();
16801636 for (uint32_t i = 0 ; i < executor -> exit_count ; i ++ ) {
16811637 executor -> exits [i ].temperature = initial_unreachable_backoff_counter ();
@@ -1720,7 +1676,8 @@ invalidate_sub_executors(_PyThreadStateImpl *tstate, _PyExecutorObject *executor
17201676 invalidate_sub_executors (tstate , next );
17211677 }
17221678 }
1723- executor_clear ((PyObject * )executor );
1679+ // Let it be cleared up by cold executor invalidation later.
1680+ executor -> vm_data .warm = 0 ;
17241681}
17251682
17261683/* Invalidate all executors that depend on `obj`
@@ -1737,6 +1694,7 @@ _Py_Executors_InvalidateDependencyLockHeld(PyInterpreterState *interp, void *obj
17371694 /* Walk the list of executors */
17381695 /* Clearing an executor can deallocate others, so we need to make a list of
17391696 * executors to invalidate first */
1697+ assert (PyMutex_IsLocked (& (interp -> runtime )-> interpreters .mutex ));
17401698 _Py_FOR_EACH_TSTATE_UNLOCKED (interp , p ) {
17411699 jit_tracer_invalidate_dependency (p , obj );
17421700 for (_PyExecutorObject * exec = ((_PyThreadStateImpl * )p )-> jit_executor_state .executor_list_head ; exec != NULL ;) {
@@ -1755,9 +1713,9 @@ _Py_Executors_InvalidateDependencyLockHeld(PyInterpreterState *interp, void *obj
17551713void
17561714_Py_Executors_InvalidateDependency (PyInterpreterState * interp , void * obj , int is_invalidation )
17571715{
1758- HEAD_LOCK (& _PyRuntime );
1716+ HEAD_LOCK (interp -> runtime );
17591717 _Py_Executors_InvalidateDependencyLockHeld (interp , obj , is_invalidation );
1760- HEAD_UNLOCK (& _PyRuntime );
1718+ HEAD_UNLOCK (interp -> runtime );
17611719}
17621720
17631721// To avoid deadlocks due to stop the world, we just invalidate the executors but leave them to be freed
@@ -1772,6 +1730,8 @@ _Py_Executors_InvalidateAllLockHeld(PyInterpreterState *interp, int is_invalidat
17721730 for (_PyExecutorObject * exec = ((_PyThreadStateImpl * )p )-> jit_executor_state .executor_list_head ; exec != NULL ;) {
17731731 assert (exec -> tstate == p );
17741732 FT_ATOMIC_STORE_UINT8 (exec -> vm_data .valid , 0 );
1733+ // Let it be cleared up by cold executor invalidation later.
1734+ exec -> vm_data .warm = 0 ;
17751735 if (is_invalidation ) {
17761736 OPT_STAT_INC (executors_invalidated );
17771737 }
@@ -1854,8 +1814,7 @@ _Py_Executors_InvalidateColdGC(PyInterpreterState *interp)
18541814 return ;
18551815 }
18561816 _PyEval_StopTheWorld (interp );
1857- HEAD_LOCK (interp -> runtime );
1858- _Py_FOR_EACH_TSTATE_UNLOCKED (interp , p )
1817+ _Py_FOR_EACH_TSTATE_BEGIN (interp , p )
18591818 {
18601819 PyObject * more_invalidate = _Py_Executors_CollectCold (p );
18611820 if (more_invalidate == NULL ) {
@@ -1867,7 +1826,7 @@ _Py_Executors_InvalidateColdGC(PyInterpreterState *interp)
18671826 goto error ;
18681827 }
18691828 }
1870- HEAD_UNLOCK (interp -> runtime );
1829+ _Py_FOR_EACH_TSTATE_END (interp );
18711830 _PyEval_StartTheWorld (interp );
18721831 // We can only clear the list after unlocking the runtime.
18731832 // Otherwise, it may deadlock.
0 commit comments