@@ -665,13 +665,11 @@ visit_reachable(PyObject *op, void *arg)
665665 * So we can not gc_list_* functions for unreachable until we remove the flag.
666666 */
667667static void
668- move_unreachable (PyGC_Head * young , PyGC_Head * unreachable , PyGC_Head * unreachable_types )
668+ move_unreachable (PyGC_Head * young , PyGC_Head * unreachable )
669669{
670670 // previous elem in the young list, used for restore gc_prev.
671671 PyGC_Head * prev = young ;
672672 PyGC_Head * gc = GC_NEXT (young );
673- PyGC_Head * to ;
674- PyObject * op ;
675673
676674 /* Invariants: all objects "to the left" of us in young are reachable
677675 * (directly or indirectly) from outside the young list as it was at entry.
@@ -722,26 +720,18 @@ move_unreachable(PyGC_Head *young, PyGC_Head *unreachable, PyGC_Head *unreachabl
722720 // No need to gc->next->prev = prev because it is single linked.
723721 prev -> _gc_next = gc -> _gc_next ;
724722
725- op = FROM_GC (gc );
726- if (unreachable_types != NULL && PyType_Check (op )) {
727- to = unreachable_types ;
728- }
729- else {
730- to = unreachable ;
731- }
732-
733723 // We can't use gc_list_append() here because we use
734724 // NEXT_MASK_UNREACHABLE here.
735- PyGC_Head * last = GC_PREV (to );
725+ PyGC_Head * last = GC_PREV (unreachable );
736726 // NOTE: Since all objects in unreachable set has
737727 // NEXT_MASK_UNREACHABLE flag, we set it unconditionally.
738728 // But this may pollute the unreachable list head's 'next' pointer
739729 // too. That's semantically senseless but expedient here - the
740730 // damage is repaired when this function ends.
741731 last -> _gc_next = flags | (uintptr_t )gc ;
742732 _PyGCHead_SET_PREV (gc , last );
743- gc -> _gc_next = flags | (uintptr_t )to ;
744- to -> _gc_prev = (uintptr_t )gc ;
733+ gc -> _gc_next = flags | (uintptr_t )unreachable ;
734+ unreachable -> _gc_prev = (uintptr_t )gc ;
745735 }
746736 gc = _PyGCHead_NEXT (prev );
747737 }
@@ -750,9 +740,6 @@ move_unreachable(PyGC_Head *young, PyGC_Head *unreachable, PyGC_Head *unreachabl
750740 young -> _gc_next &= _PyGC_PREV_MASK ;
751741 // don't let the pollution of the list head's next pointer leak
752742 unreachable -> _gc_next &= _PyGC_PREV_MASK ;
753- if (unreachable_types != NULL ) {
754- unreachable_types -> _gc_next &= _PyGC_PREV_MASK ;
755- }
756743}
757744
758745/* In theory, all tuples should be younger than the
@@ -920,7 +907,12 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old)
920907 * will run and potentially cause a crash. See bpo-38006 for
921908 * one example.
922909 */
923- _PyWeakref_ClearRef ((PyWeakReference * )op );
910+ if (!((PyWeakReference * )op )-> is_subclass ) {
911+ _PyWeakref_ClearRef ((PyWeakReference * )op );
912+ }
913+ else {
914+ continue ;
915+ }
924916 }
925917
926918 if (! _PyType_SUPPORTS_WEAKREFS (Py_TYPE (op ))) {
@@ -938,9 +930,15 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old)
938930 * all the weakrefs, and move the weakrefs with callbacks
939931 * that must be called into wrcb_to_call.
940932 */
941- for (wr = * wrlist ; wr != NULL ; wr = * wrlist ) {
933+ PyWeakReference * wr_next = * wrlist ;
934+ for (wr = wr_next ; wr != NULL ; wr = wr_next ) {
942935 PyGC_Head * wrasgc ; /* AS_GC(wr) */
943936
937+ wr_next = wr -> wr_next ;
938+ if (wr -> is_subclass == 1 ) {
939+ continue ;
940+ }
941+
944942 /* _PyWeakref_ClearRef clears the weakref but leaves
945943 * the callback pointer intact. Obscure: it also
946944 * changes *wrlist.
@@ -1182,8 +1180,6 @@ delete_garbage(PyThreadState *tstate, GCState *gcstate,
11821180 them to the "unreachable" list. This step also needs to move back to "base" all
11831181 objects that were initially marked as unreachable but are referred transitively
11841182 by the reachable objects (the ones with strictly positive reference count).
1185- 4. Split unreachable objects and unreachable types to prevent clearing types
1186- before instances.
11871183
11881184Contracts:
11891185
@@ -1198,8 +1194,7 @@ flag is cleared (for example, by using 'clear_unreachable_mask' function or
11981194by a call to 'move_legacy_finalizers'), the 'unreachable' list is not a normal
11991195list and we can not use most gc_list_* functions for it. */
12001196static inline void
1201- deduce_unreachable (PyGC_Head * base , PyGC_Head * unreachable ,
1202- PyGC_Head * unreachable_types ) {
1197+ deduce_unreachable (PyGC_Head * base , PyGC_Head * unreachable ) {
12031198 validate_list (base , collecting_clear_unreachable_clear );
12041199 /* Using ob_refcnt and gc_refs, calculate which objects in the
12051200 * container set are reachable from outside the set (i.e., have a
@@ -1250,12 +1245,9 @@ deduce_unreachable(PyGC_Head *base, PyGC_Head *unreachable,
12501245 * the type's cache will not be properly invalidated from
12511246 * within the __del__ method.
12521247 */
1253- move_unreachable (base , unreachable , unreachable_types ); // gc_prev is pointer again
1248+ move_unreachable (base , unreachable ); // gc_prev is pointer again
12541249 validate_list (base , collecting_clear_unreachable_clear );
12551250 validate_list (unreachable , collecting_set_unreachable_set );
1256- if (unreachable_types != NULL ) {
1257- validate_list (unreachable_types , collecting_set_unreachable_set );
1258- }
12591251}
12601252
12611253/* Handle objects that may have resurrected after a call to 'finalize_garbage', moving
@@ -1283,7 +1275,7 @@ handle_resurrected_objects(PyGC_Head *unreachable, PyGC_Head* still_unreachable,
12831275 // have the PREV_MARK_COLLECTING set, but the objects are going to be
12841276 // removed so we can skip the expense of clearing the flag.
12851277 PyGC_Head * resurrected = unreachable ;
1286- deduce_unreachable (resurrected , still_unreachable , NULL );
1278+ deduce_unreachable (resurrected , still_unreachable );
12871279 clear_unreachable_mask (still_unreachable );
12881280
12891281 // Move the resurrected objects to the old generation for future collection.
@@ -1723,16 +1715,14 @@ gc_collect_region(PyThreadState *tstate,
17231715{
17241716 PyGC_Head unreachable ; /* non-problematic unreachable trash */
17251717 PyGC_Head finalizers ; /* objects with, & reachable from, __del__ */
1726- PyGC_Head unreachable_types ; /* unreachable types */
17271718 PyGC_Head * gc ; /* initialize to prevent a compiler warning */
17281719 GCState * gcstate = & tstate -> interp -> gc ;
17291720
17301721 assert (gcstate -> garbage != NULL );
17311722 assert (!_PyErr_Occurred (tstate ));
17321723
17331724 gc_list_init (& unreachable );
1734- gc_list_init (& unreachable_types );
1735- deduce_unreachable (from , & unreachable , & unreachable_types );
1725+ deduce_unreachable (from , & unreachable );
17361726 validate_consistent_old_space (from );
17371727 untrack_tuples (from );
17381728 validate_consistent_old_space (to );
@@ -1749,24 +1739,18 @@ gc_collect_region(PyThreadState *tstate,
17491739 // NEXT_MASK_UNREACHABLE is cleared here.
17501740 // After move_legacy_finalizers(), unreachable is normal list.
17511741 move_legacy_finalizers (& unreachable , & finalizers );
1752- move_legacy_finalizers (& unreachable_types , & finalizers );
17531742 /* finalizers contains the unreachable objects with a legacy finalizer;
17541743 * unreachable objects reachable *from* those are also uncollectable,
17551744 * and we move those into the finalizers list too.
17561745 */
17571746 move_legacy_finalizer_reachable (& finalizers );
17581747 validate_list (& finalizers , collecting_clear_unreachable_clear );
17591748 validate_list (& unreachable , collecting_set_unreachable_clear );
1760- validate_list (& unreachable_types , collecting_set_unreachable_clear );
17611749 /* Print debugging information. */
17621750 if (gcstate -> debug & _PyGC_DEBUG_COLLECTABLE ) {
17631751 for (gc = GC_NEXT (& unreachable ); gc != & unreachable ; gc = GC_NEXT (gc )) {
17641752 debug_cycle ("collectable" , FROM_GC (gc ));
17651753 }
1766- gc = GC_NEXT (& unreachable_types );
1767- for (; gc != & unreachable_types ; gc = GC_NEXT (gc )) {
1768- debug_cycle ("collectable" , FROM_GC (gc ));
1769- }
17701754 }
17711755
17721756 /* Clear weakrefs and invoke callbacks as necessary. */
@@ -1778,20 +1762,6 @@ gc_collect_region(PyThreadState *tstate,
17781762 /* Call tp_finalize on objects which have one. */
17791763 finalize_garbage (tstate , & unreachable );
17801764
1781- /* Clear weakrefs to types and invoke callbacks as necessary. */
1782- stats -> collected += handle_weakrefs (& unreachable_types , to );
1783- gc_list_validate_space (to , gcstate -> visited_space );
1784- validate_list (to , collecting_clear_unreachable_clear );
1785- validate_list (& unreachable_types , collecting_set_unreachable_clear );
1786-
1787- /* Call tp_finalize on types. */
1788- finalize_garbage (tstate , & unreachable_types );
1789-
1790- /* Merge types back to unreachable to properly process resurected
1791- * objects and so on.
1792- */
1793- gc_list_merge (& unreachable_types , & unreachable );
1794-
17951765 /* Handle any objects that may have resurrected after the call
17961766 * to 'finalize_garbage' and continue the collection with the
17971767 * objects that are still unreachable */
0 commit comments