Extend the Tutorial plan to create a "copy-MS" collector, which allocates into a copying nursery and at collection time, copies nursery survivors into a mark-sweep space. This plan does not require a write barrier (it is not strictly generational, as it will collect the whole heap each time the heap is full). Later we will extended it with a write barrier, allowing the nursery to be collected in isolation. Such a collector would be a generational mark-sweep collector, similar to GenMS.
Add a Copying Nursery
- In
TutorialConstraints
, make the following changes:Override the
movesObjects()
method to returntrue
, reflecting that we are now building a copying collector:@Override public boolean movesObjects() { return true; }
- Remove the restriction on default alloc bytes (since default allocation will now go to a bump-pointed space). To do this, remove the override of
maxNonLOSDefaultAllocBytes()
. Add a restriction on the maximum size that may be copied into the (default) non-LOS mature space:
@Override public int maxNonLOSCopyBytes() { return SegregatedFreeListSpace.MAX_FREELIST_OBJECT_BYTES;}
- In
Tutorial
, add a nursery space:Create a new space,
nurserySpace
, of typeCopySpace
. The new space will initially be a from-space, so providefalse
as the third argument. Initialize the space with a contiguous virtual memory region consuming 0.15 of the heap by passing "0.15
" and "true
" as arguments to the constructor ofVMRequest
(more on this later). Create and initialize a new integer constant to hold the descriptor for this new space:public static final CopySpace nurserySpace = new CopySpace("nursery", DEFAULT_POLL_FREQUENCY, false, VMRequest.create(0.15f, true)); public static final int NURSERY = nurserySpace.getDescriptor();
- Add the necessary import statements
- Add
nurserySpace
to thePREPARE
andRELEASE
phases ofcollectionPhase()
, prior to the existing calls tomsTrace
. Passtrue
tonurserySpace.prepare()
indicating that the nursery is a from-space during collection. - Fix accounting so that
Tutorial
accounts for space consumed bynurserySpace
:- Add
nurserySpace
to the equation ingetPagesUsed()
,
- Add
- Since initial allocation will be into a copying space, we need to account for copy reserve:
- Change
getPagesRequired()
, replacingmsSpace.requiredPages()
with(nurserySpace.requiredPages() * 2)
- Add a method to override
getCollectionReserve()
which returnsnurserySpace.reservedPages() + super.getCollectionReserve()
, - Add a method to override
getPagesAvail()
, returningsuper.getPagesAvail()/2
,
- Change
Add nursery allocation
In TutorialMutator
, replace the free-list allocator (MarkSweepLocal
) with add a nursery allocator. Add an instance of CopyLocal
, calling it nursery
. The constructor argument should be Tutorial.nurserySpace
:
- change
alloc()
to usenursery.alloc()
rather thanms.alloc()
. - remove the call to
msSpace.postAlloc()
frompostAlloc()
since there is no special post-allocation work necessary for the new copy space. The call tosuper.postAlloc()
should remain conditional onallocator != Tutorial.ALLOC_DEFAULT
. - change the check within
getAllocatorFromSpace()
to check againstTutorial.nurserySpace
and to returnnursery
. - adjust
collectionPhase
- replace call to
ms.prepare()
withnursery.reset()
- remove call to
ms.release()
since there are no actions necessary for the nursery allocator upon release.
- replace call to
Add copying to the collector
In TutorialCollector
add the capacity for the collector to allocate (copy), since our new hybrid collector will perform copying.
Add local allocators for both large object space and the mature space:
private final LargeObjectLocal los = new LargeObjectLocal(Plan.loSpace); private final MarkSweepLocal mature = new MarkSweepLocal(Tutorial.msSpace);
Add an
allocCopy()
method that conditionally allocates to the LOS or mature space:@Override public final Address allocCopy(ObjectReference original, int bytes, int align, int offset, int allocator) { if (allocator == Plan.ALLOC_LOS) return los.alloc(bytes, align, offset); else return mature.alloc(bytes, align, offset); }
Add a
postCopy()
method that conditionally calls LOS or mature space post-copy actions:@Override public final void postCopy(ObjectReference object, ObjectReference typeRef, int bytes, int allocator) { if (allocator == Plan.ALLOC_LOS) Plan.loSpace.initializeHeader(object, false); else Tutorial.msSpace.postCopy(object, true); }
Make necessary changes to TutorialTraceLocal
- Add
nurserySpace
clauses toisLive()
andtraceObject()
:Add the following to
isLive()
:if (Space.isInSpace(Tutorial.NURSERY, object)) return Tutorial.nurserySpace.isLive(object);
Add the following to
traceObject()
:if (Space.isInSpace(Tutorial.NURSERY, object)) return Tutorial.nurserySpace.traceObject(this, object, Tutorial.ALLOC_DEFAULT);
Add a new
precopyObject()
method, which is necessary for all copying collectors:@Override public ObjectReference precopyObject(ObjectReference object) { if (object.isNull()) return object; else if (Space.isInSpace(Tutorial.NURSERY, object)) return Tutorial.nurserySpace.traceObject(this, object, Tutorial.ALLOC_DEFAULT); else return object; }
Add a new
willNotMoveInCurrentCollection()
method, which identifies those objects which do not move (necessary for copying collectors):@Override public boolean willNotMoveInCurrentCollection(ObjectReference object) { return !Space.isInSpace(Tutorial.NURSERY, object); }
With these changes, Tutorial should now work. You should be able to again build a BaseBaseTutorial image and test it against any benchmark. Again, if you use -X:gc:verbose=3
you can see the movement of data among the spaces at each garbage collection.
![]() | Checkpoint This zip file captures all of the above steps with respect to Jikes RVM 3.0.1. You can use the archive to verify you've completed the above steps correctly. |