Skip to content

Commit 1ad18ec

Browse files
Remove unreachable_types pass
1 parent 96f09db commit 1ad18ec

File tree

1 file changed

+21
-51
lines changed

1 file changed

+21
-51
lines changed

Python/gc.c

Lines changed: 21 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -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
*/
667667
static 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
11881184
Contracts:
11891185
@@ -1198,8 +1194,7 @@ flag is cleared (for example, by using 'clear_unreachable_mask' function or
11981194
by a call to 'move_legacy_finalizers'), the 'unreachable' list is not a normal
11991195
list and we can not use most gc_list_* functions for it. */
12001196
static 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

Comments
 (0)