[MLton] cvs commit: improved GC structure

Stephen Weeks MLton@mlton.org
Thu, 8 Apr 2004 15:11:17 -0700


One thing that caught my eye while reading this commit is that the
ensureBytesFree argument to GC_switchToThread is not used in the fast
branch of GC_switchToThread.  Shouldn't we do 

		s->currentThread->bytesNeeded = ensureBytesFree;

there as well?

>    - folded Thread_switchTo into GC_threadSwitchTo.

I was wondering if we could eliminate Thread_switchTo entirely and
change the calls to Thread_switchTo in ssa-to-rssa into calls to
GC_switchToThread?

>    - I did not attempt to fold the growth of the current stack into
>       forward; it's not clear to me how to do it properly -- note that
>       it only applies when doing a major copying GC.  If we need to do a
>       major mark compact GC, then we really need to copy the stack after
>       the compaction.

Yeah, that occurred to me as well.  It still might be worth doing the
stack growth in forward during a copying GC, and only do it afterward
if the major GC was mark compact.  I think this could be done by
changing the stackTopOk test before growStack to test
mutatorStackInvariant instead.

I thought more about the comment in forward

	We cannot do any growing here because we may run out of to
	space.

and concluded that it is indeed vestigal.  It comes from a time before
we had the mark-compact gc.  When we only had stop-and-copy major gc,
we would sometimes be unable to mmap a tospace that was as large as
from space.  In that case, we would let the GC proceed, but had to
test before copying each object that it would not extend outside of
tospace.  We didn't want to grow the stack in that case, because it
might push us over the edge.

Now that we have mark-compact gc, we only run the major copying gc
when we can allocate a tospace that is big enough.  So, we know that
the stack growth will succeed (assuming we asked for enough space in
the bytesRequested passed to majorGC).

>    - I modified the stack shrinking policy:
...
>       + for heap stacks, if stack->used <= stack->reserved / 4,
>          then shrink to stack->reserved / 2,
>          else if stack->used <= stack->reserved / 2,
>          then shink to stack->used.
>         This allows stacks to shrink down to the minimal size, if they
>         live through multiple GCs.

The idea makes sense, but I don't understand how the code does this.
What if stack->used = 3/4 stack->reserved?  Don't we want to shrink
that down to minimal size too? 

Since major GCs are infrequent, why not instantly shrink all paused
stacks to minimal size?  Or maybe shrink them by a factor of two each
time, until they drop below mutatorStackInvariant, at which point drop
them to minimal size?