@@ -139,6 +139,9 @@ gc_list_is_empty(PyGC_Head *list)
139139 return (list -> gc .gc_next == list );
140140}
141141
142+ #if 0
143+ /* This became unused after gc_list_move() was introduced. */
144+ /* Append `node` to `list`. */
142145static void
143146gc_list_append (PyGC_Head * node , PyGC_Head * list )
144147{
@@ -147,7 +150,9 @@ gc_list_append(PyGC_Head *node, PyGC_Head *list)
147150 node -> gc .gc_prev -> gc .gc_next = node ;
148151 list -> gc .gc_prev = node ;
149152}
153+ #endif
150154
155+ /* Remove `node` from the gc list it's currently in. */
151156static void
152157gc_list_remove (PyGC_Head * node )
153158{
@@ -156,11 +161,29 @@ gc_list_remove(PyGC_Head *node)
156161 node -> gc .gc_next = NULL ; /* object is not currently tracked */
157162}
158163
159- /* append a list onto another list, from becomes an empty list */
164+ /* Move `node` from the gc list it's currently in (which is not explicitly
165+ * named here) to the end of `list`. This is semantically the same as
166+ * gc_list_remove(node) followed by gc_list_append(node, list).
167+ */
168+ static void
169+ gc_list_move (PyGC_Head * node , PyGC_Head * list )
170+ {
171+ PyGC_Head * current_prev = node -> gc .gc_prev ;
172+ PyGC_Head * current_next = node -> gc .gc_next ;
173+ PyGC_Head * new_prev = list -> gc .gc_prev ;
174+ current_prev -> gc .gc_next = current_next ;
175+ current_next -> gc .gc_prev = current_prev ;
176+ node -> gc .gc_next = list ;
177+ node -> gc .gc_prev = new_prev ;
178+ new_prev -> gc .gc_next = list -> gc .gc_prev = node ;
179+ }
180+
181+ /* append list `from` onto list `to`; `from` becomes an empty list */
160182static void
161183gc_list_merge (PyGC_Head * from , PyGC_Head * to )
162184{
163185 PyGC_Head * tail ;
186+ assert (from != to );
164187 if (!gc_list_is_empty (from )) {
165188 tail = to -> gc .gc_prev ;
166189 tail -> gc .gc_next = from -> gc .gc_next ;
@@ -295,8 +318,7 @@ visit_reachable(PyObject *op, PyGC_Head *reachable)
295318 * and move_unreachable will eventually get to it
296319 * again.
297320 */
298- gc_list_remove (gc );
299- gc_list_append (gc , reachable );
321+ gc_list_move (gc , reachable );
300322 gc -> gc .gc_refs = 1 ;
301323 }
302324 /* Else there's nothing to do.
@@ -368,8 +390,7 @@ move_unreachable(PyGC_Head *young, PyGC_Head *unreachable)
368390 * young if that's so, and we'll see it again.
369391 */
370392 next = gc -> gc .gc_next ;
371- gc_list_remove (gc );
372- gc_list_append (gc , unreachable );
393+ gc_list_move (gc , unreachable );
373394 gc -> gc .gc_refs = GC_TENTATIVELY_UNREACHABLE ;
374395 }
375396 gc = next ;
@@ -416,8 +437,7 @@ move_finalizers(PyGC_Head *unreachable, PyGC_Head *finalizers)
416437 next = gc -> gc .gc_next ;
417438
418439 if (has_finalizer (op )) {
419- gc_list_remove (gc );
420- gc_list_append (gc , finalizers );
440+ gc_list_move (gc , finalizers );
421441 gc -> gc .gc_refs = GC_REACHABLE ;
422442 }
423443 }
@@ -430,8 +450,7 @@ visit_move(PyObject *op, PyGC_Head *tolist)
430450 if (PyObject_IS_GC (op )) {
431451 if (IS_TENTATIVELY_UNREACHABLE (op )) {
432452 PyGC_Head * gc = AS_GC (op );
433- gc_list_remove (gc );
434- gc_list_append (gc , tolist );
453+ gc_list_move (gc , tolist );
435454 gc -> gc .gc_refs = GC_REACHABLE ;
436455 }
437456 }
@@ -559,8 +578,7 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old)
559578 assert (wrasgc != next ); /* wrasgc is reachable, but
560579 next isn't, so they can't
561580 be the same */
562- gc_list_remove (wrasgc );
563- gc_list_append (wrasgc , & wrcb_to_call );
581+ gc_list_move (wrasgc , & wrcb_to_call );
564582 }
565583 }
566584
@@ -600,8 +618,7 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old)
600618 Py_DECREF (op );
601619 if (wrcb_to_call .gc .gc_next == gc ) {
602620 /* object is still alive -- move it */
603- gc_list_remove (gc );
604- gc_list_append (gc , old );
621+ gc_list_move (gc , old );
605622 }
606623 else
607624 ++ num_freed ;
@@ -694,8 +711,7 @@ delete_garbage(PyGC_Head *collectable, PyGC_Head *old)
694711 }
695712 if (collectable -> gc .gc_next == gc ) {
696713 /* object is still alive, move it, it may die later */
697- gc_list_remove (gc );
698- gc_list_append (gc , old );
714+ gc_list_move (gc , old );
699715 gc -> gc .gc_refs = GC_REACHABLE ;
700716 }
701717 }
0 commit comments