[Python-Dev] Garbage collector problem
Tim Peters
tim.one@comcast.net
Fri, 28 Jun 2002 18:58:30 -0400
[Tim]
> ...
> I'm not yet sure whether the mystery is why this happens in 2.3, or
> why it doesn't happen in 2.2.1 <0.5 wink>.
Knock that down to 0.1 wink <0.3 wink>: Kevin's problem goes away in
current CVS if I change the guard in visit_decref() to
if (IS_TRACKED(op) && !IS_MOVED(op))
^^^^^^^^^^^^^^^^ added this
I've no real idea why, as 2.2.1 didn't need this to prevent "the list" from
getting continually pulled back into a younger generation.
Without this change in current CVS, it looks like, in each gen0 collection:
a. The bound method object in gen0 knocks "the list"'s gc_refs down to
-124 when visit_decref() is called by the bound method object
traverse via subtract_refs(). Therefore IS_MOVED("the list") is
no longer true.
b. move_root_reachable() then moves "the list" into the list of
reachable things, because visit_move's has-always-been-there
if (IS_TRACKED(op) && !IS_MOVED(op)) {
guard doesn't believe "the list" has already been moved. vist_move
then restores the list's gc_refs to the magic -123.
c. move_root_reachable() goes on to scan all of "the list"'s entries too.
d. "the list" itself gets moved into gen1, just because it's in the
list of reachable things.
e. The next gen0 collection starts at #a again, and does the same
stuff all over again.
Adding the new guard in visit_decref() breaks this at #a: IS_MOVED("the
list") remains true, and so #b doesn't move "the list" into the set of
reachable objects again, and so the list stays in whichever older generation
it was in, and doesn't get scanned again (until the next gen2 traversal).
The mystery to me now is why the a,b,c,d,e loop didn't happen in 2.2.1.