Interesting idea!   It seems the real issue is "marking and sweeping" the
vtables.  A stab at categorizing the approaches:

a)
Force vtables to be as similar to ordinary java objects as possible.  The
upside: existing GC algorithms will work unaltered.  The downside is vtables
of vtables of vtables...  This has already been discussed at length.

b)
Force vtables to live and die in a unique "vtable space".  The big
challenge seems to be building a custom GC algorithm that is simpler and
less invasive than doing a) above.  Most likely the performance of the
custom GC algorithm will never be an issue.  Vtables have some very
interesting properties that may make this doable.  The 4 (or 8) bytes at
offset "K" always point to a class structure which, in turn, always has a
pointer at offset "Z" back to the vtable.  There are way fewer vtables than
objects.  For practical reasons, it can be assumed that vtables will always
be pinned.  The number of class structs/objects is no greater than the
number of vtables.

A half-baked scheme that might be good enough:  Partition off 50 megabytes
as a hard, fixed vtables space.  Then do a word-by-word scan to pick up
candidate pointers class structs.  Then filter the candidate class struct
pointers by verifying the back pointers.  Occasionally there might be
"floating garbage" with this approach but a valid, live vtable should never
be accidentally freed.  The filtered set are the "live" vtables.  Next scan
the live vtables looking for members that were never marked by the regular
GC as mentioned  below.  When found, zero the vtable, link-list on a free
vtable space list, mark the class struct as "vtable-less".  Process the
"vtable-less" class struct, etc...

It seems as long as part of the system is built using garbage collected java
objects and part of the system is built using malloc/free C structs, the
problem of releasing connected objects/C_structs will be messy and hacky.
In a sense, this issue is really a motivation for re-writing the whole VM in
Java... hmmm...


On 10/31/06, Robin Garner <[EMAIL PROTECTED]> wrote:

Actually, just thinking about how I would implement this in JikesRVM, I
would use the reachability based algorithm, but piggyback on the
existing GC mechanisms:

- Allocate a byte (or word) in each vtable for the purpose of tracking
class reachability.
- Periodically, at a time when no GC is running (even the most
aggressive concurrent GC algorithms have these, I believe), zero this
flag across all vtables.  This is the beginning of a class-unloading
epoch.
- During each GC, when the GC is fetching the GC map for an object,
*unconditionally* write a value to the class reachability byte.  It may
make sense for this byte to be in either the first cache-line of the
vtable, or the cache line that points to the GC map - just make sure the
mark operation doesn't in general fetch an additional cache line.
- At a point in the sufficiently far future, when all reachable objects
are known to have been traced by the GC, sweep the vtables and check the
reachability of the classloaders.

The features of this approach are:

- Minimal additional work at GC time.  The additional write will cause
some additional memory traffic, but a) it's to memory that is already
guaranteed to be in L1 cache, and b) it's an unconditional independent
write, and c) multiple writes to common classes will be absorbed by the
write buffer.

- Space cost of at most 1 word per vtable.

- This works whether vtables are objects or VM structures

- If the relationship between a class and a vtable is not 1:1, this only
need affect the periodic sweep process, which should be infrequent and
small compared to a GC.

- shouldn't need a stop-the-world at any point.

I've implemented and tested the GC-relevant part of this in JikesRVM,
and the GC time overhead appears to be just under 1% in the MMTk
MarkSweep collector.

cheers,
Robin




--
Weldon Washburn
Intel Enterprise Solutions Software Division

Reply via email to