[vmkit-commits] [vmkit] r75904 [1/2] - in /vmkit/trunk/mmtk: ./ java/ java/src/ java/src/org/ java/src/org/j3/ java/src/org/j3/config/ java/src/org/j3/mmtk/ java/src/org/j3/options/ java/src/org/j3/runtime/ java/src/org/jikesrvm/ java/src/org/mmtk/ java/src/org/mmtk/plan/ java/src/org/mmtk/plan/copyms/ java/src/org/mmtk/plan/generational/ java/src/org/mmtk/plan/generational/copying/ java/src/org/mmtk/plan/generational/immix/ java/src/org/mmtk/plan/generational/marksweep/ java/src/org/mmtk/plan/immix/ java/src/org/mmtk/p...

Nicolas Geoffray nicolas.geoffray at lip6.fr
Thu Jul 16 04:26:41 PDT 2009


Author: geoffray
Date: Thu Jul 16 06:26:34 2009
New Revision: 75904

URL: http://llvm.org/viewvc/llvm-project?rev=75904&view=rev
Log:
Import MMTk and the VMKit interface for MMTk.


Added:
    vmkit/trunk/mmtk/
    vmkit/trunk/mmtk/java/
    vmkit/trunk/mmtk/java/build.xml
    vmkit/trunk/mmtk/java/src/
    vmkit/trunk/mmtk/java/src/org/
    vmkit/trunk/mmtk/java/src/org/j3/
    vmkit/trunk/mmtk/java/src/org/j3/config/
    vmkit/trunk/mmtk/java/src/org/j3/config/Selected.java
    vmkit/trunk/mmtk/java/src/org/j3/mmtk/
    vmkit/trunk/mmtk/java/src/org/j3/mmtk/ActivePlan.java
    vmkit/trunk/mmtk/java/src/org/j3/mmtk/Assert.java
    vmkit/trunk/mmtk/java/src/org/j3/mmtk/Barriers.java
    vmkit/trunk/mmtk/java/src/org/j3/mmtk/BuildTimeConfig.java
    vmkit/trunk/mmtk/java/src/org/j3/mmtk/Collection.java
    vmkit/trunk/mmtk/java/src/org/j3/mmtk/Debug.java
    vmkit/trunk/mmtk/java/src/org/j3/mmtk/Factory.java
    vmkit/trunk/mmtk/java/src/org/j3/mmtk/FinalizableProcessor.java
    vmkit/trunk/mmtk/java/src/org/j3/mmtk/Lock.java
    vmkit/trunk/mmtk/java/src/org/j3/mmtk/MMTk_Events.java
    vmkit/trunk/mmtk/java/src/org/j3/mmtk/Memory.java
    vmkit/trunk/mmtk/java/src/org/j3/mmtk/ObjectModel.java
    vmkit/trunk/mmtk/java/src/org/j3/mmtk/ReferenceProcessor.java
    vmkit/trunk/mmtk/java/src/org/j3/mmtk/Scanning.java
    vmkit/trunk/mmtk/java/src/org/j3/mmtk/Statistics.java
    vmkit/trunk/mmtk/java/src/org/j3/mmtk/Strings.java
    vmkit/trunk/mmtk/java/src/org/j3/mmtk/SynchronizedCounter.java
    vmkit/trunk/mmtk/java/src/org/j3/mmtk/TraceInterface.java
    vmkit/trunk/mmtk/java/src/org/j3/options/
    vmkit/trunk/mmtk/java/src/org/j3/options/OptionSet.java
    vmkit/trunk/mmtk/java/src/org/j3/runtime/
    vmkit/trunk/mmtk/java/src/org/j3/runtime/VM.java
    vmkit/trunk/mmtk/java/src/org/jikesrvm/
    vmkit/trunk/mmtk/java/src/org/jikesrvm/Magic.java
    vmkit/trunk/mmtk/java/src/org/jikesrvm/SizeConstants.java
    vmkit/trunk/mmtk/java/src/org/mmtk/
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/CollectorContext.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/ComplexPhase.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/GCspyPlan.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/MutatorContext.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/Phase.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/Plan.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/PlanConstraints.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/Simple.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleCollector.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleConstraints.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleMutator.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimplePhase.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorld.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldCollector.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldConstraints.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldMutator.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/Trace.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/TraceLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/TraceWriteBuffer.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/TransitiveClosure.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMS.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSCollector.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSConstraints.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSMutator.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSTraceLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/Gen.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenCollector.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenConstraints.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenMatureTraceLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenMutator.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenNurseryTraceLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopy.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyCollector.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyConstraints.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyMatureTraceLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyMutator.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmix.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixCollector.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixConstraints.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMatureDefragTraceLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMatureTraceLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMutator.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMS.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSCollector.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSConstraints.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSMatureTraceLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSMutator.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/Immix.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixCollector.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixConstraints.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixDefragTraceLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixMutator.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixTraceLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MC.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCCollector.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCConstraints.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCForwardTraceLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCMarkTraceLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCMutator.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MS.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSCollector.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSConstraints.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSMutator.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSTraceLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGC.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCCollector.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCConstraints.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCMutator.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCTraceLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/Poisoned.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedCollector.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedConstraints.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedMutator.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBase.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseCollector.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseConstraints.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseMutator.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCDecBuffer.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCHeader.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCZero.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTDecMarked.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTDecMarkedAndZero.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTFreeLargeObjectSweeper.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTScanLargeObjectSweeper.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTSweepImmortalScanner.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTSweeper.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTTraceLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RC.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCCollector.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCConstraints.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCFindRootSetTraceLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCModifiedProcessor.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCMutator.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRC.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCCollector.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCConstraints.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCFindRootSetTraceLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCModifiedProcessor.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCMutator.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SS.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSCollector.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSConstraints.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSMutator.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSTraceLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspy.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyCollector.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyConstraints.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyMutator.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyTraceLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTrace.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceCollector.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceConstraints.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceMutator.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceTraceLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmix.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixCollector.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixConstraints.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixMutator.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixNurseryTraceLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMS.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSCollector.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSConstraints.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSMutator.java
    vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSNurseryTraceLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/BaseLargeObjectSpace.java
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/CopyLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/CopySpace.java
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitFreeListLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitFreeListSpace.java
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitLargeObjectSpace.java
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/ImmortalLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/ImmortalSpace.java
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/LargeObjectLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/LargeObjectSpace.java
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkCompactLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkCompactSpace.java
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkSweepLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkSweepSpace.java
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/RawPageSpace.java
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/SegregatedFreeListSpace.java
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/Space.java
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Block.java
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Chunk.java
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ChunkList.java
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/CollectorLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Defrag.java
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ImmixConstants.java
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ImmixSpace.java
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Line.java
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/MutatorLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ObjectHeader.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/BaseGenericFreeList.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/CallSite.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/Constants.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/Conversions.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/CycleDetector.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/DoublyLinkedList.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/GenericFreeList.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/Log.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/Memory.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/SimpleHashtable.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/Synchronize.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/TraceGenerator.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/TracingConstants.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/Treadmill.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/Allocator.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/BlockAllocator.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/BumpPointer.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/DumpLinearScan.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/EmbeddedMetaData.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/ImmixAllocator.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/LargeObjectAllocator.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/LinearScan.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/SegregatedFreeList.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/SegregatedFreeListLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressDeque.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressPairDeque.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressTripleDeque.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/Deque.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalDeque.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalQueue.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalSSB.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/ObjectReferenceBuffer.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/ObjectReferenceDeque.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SharedDeque.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortSharedDeque.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODAddressStack.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODObjectReferenceStack.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODSharedDeque.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/TraceBuffer.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/WriteBuffer.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/Color.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/GCspy.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/LinearScan.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/StreamConstants.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/Subspace.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/AbstractDriver.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/GenImmortalSpaceDriver.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/GenLOSDriver.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/ImmortalSpaceDriver.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/LinearSpaceDriver.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/TreadmillDriver.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/FreeListPageResource.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/HeapGrowthManager.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/Map.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/Mmapper.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/MonotonePageResource.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/PageResource.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/SpaceDescriptor.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/VMRequest.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/BoundedNursery.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/ConcurrentTrigger.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleFilterThreshold.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleMetaDataLimit.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleTriggerThreshold.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DebugAddress.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragFreeHeadroom.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragFreeHeadroomFraction.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragHeadroom.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragHeadroomFraction.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragLineReuseRatio.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragSimpleSpillThreshold.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragStress.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DummyEnum.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EagerCompleteSweep.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EagerMmapSpaces.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EchoOptions.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FixedNursery.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FragmentationStats.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FullHeapSystemGC.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCTimeCap.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyPort.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyTileSize.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyWait.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GenCycleDetection.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/HarnessAll.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/IgnoreSystemGC.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/LineReuseRatio.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/MarkSweepMarkBits.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/MetaDataLimit.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NoFinalizer.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NoReferenceTypes.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NurserySize.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/Options.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/PerfMetric.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/PrintPhaseStats.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/ProtectOnRelease.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/SanityCheck.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/StressFactor.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/TraceRate.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VariableSizeHeap.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/Verbose.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VerboseFragmentationStats.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VerboseTiming.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/XmlStats.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityChecker.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityCheckerLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityDataTable.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityLinearScan.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityRootTraceLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityTraceLocal.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/BooleanCounter.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Counter.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/EventCounter.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/LongCounter.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/PerfCounter.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/SizeCounter.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Stats.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Timer.java
    vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Xml.java
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/ActivePlan.java
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/Assert.java
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/Barriers.java
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/BuildTimeConfig.java
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/Collection.java
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/Config.java
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/Debug.java
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/Factory.java
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/FinalizableProcessor.java
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/Lock.java
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/MMTk_Events.java
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/Memory.java
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/ObjectModel.java
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/ReferenceProcessor.java
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/Scanning.java
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/Statistics.java
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/Strings.java
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/SynchronizedCounter.java
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/TraceInterface.java
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/VM.java
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ByteStream.java
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/IntStream.java
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ServerInterpreter.java
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ServerSpace.java
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ShortStream.java
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/Stream.java
    vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/Util.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/
    vmkit/trunk/mmtk/java/src/org/vmmagic/Intrinsic.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/Pragma.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/Unboxed.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/BaselineNoRegisters.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/BaselineSaveLSRegisters.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/DynamicBridge.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Entrypoint.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Inline.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Interruptible.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/LogicallyUninterruptible.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NativeBridge.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoBoundsCheck.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoEscapes.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoInline.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoNullCheck.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoOptCompile.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NonMoving.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NonMovingAllocation.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Preemptible.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Pure.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RawStorage.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RuntimeFinal.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RuntimePure.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SaveVolatile.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SpecializedMethodInvoke.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SynchronizedObject.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SysCallNative.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Uninterruptible.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/UninterruptibleNoWarn.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Unpreemptible.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/UnpreemptibleNoWarn.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Untraced.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/
    vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/Address.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/AddressArray.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/Extent.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/ExtentArray.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/ObjectReference.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/ObjectReferenceArray.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/Offset.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/OffsetArray.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/Word.java
    vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/WordArray.java
    vmkit/trunk/mmtk/java/src/org/vmutil/
    vmkit/trunk/mmtk/java/src/org/vmutil/options/
    vmkit/trunk/mmtk/java/src/org/vmutil/options/AddressOption.java
    vmkit/trunk/mmtk/java/src/org/vmutil/options/BooleanOption.java
    vmkit/trunk/mmtk/java/src/org/vmutil/options/EnumOption.java
    vmkit/trunk/mmtk/java/src/org/vmutil/options/FloatOption.java
    vmkit/trunk/mmtk/java/src/org/vmutil/options/IntOption.java
    vmkit/trunk/mmtk/java/src/org/vmutil/options/MicrosecondsOption.java
    vmkit/trunk/mmtk/java/src/org/vmutil/options/Option.java
    vmkit/trunk/mmtk/java/src/org/vmutil/options/OptionSet.java
    vmkit/trunk/mmtk/java/src/org/vmutil/options/PagesOption.java
    vmkit/trunk/mmtk/java/src/org/vmutil/options/StringOption.java
    vmkit/trunk/mmtk/magic/
    vmkit/trunk/mmtk/magic/LowerJavaRT.cpp
    vmkit/trunk/mmtk/magic/LowerMagic.cpp
    vmkit/trunk/mmtk/magic/Makefile
    vmkit/trunk/mmtk/mmtk-j3/
    vmkit/trunk/mmtk/mmtk-j3/ActivePlan.cpp
    vmkit/trunk/mmtk/mmtk-j3/Assert.cpp
    vmkit/trunk/mmtk/mmtk-j3/Collection.cpp
    vmkit/trunk/mmtk/mmtk-j3/FinalizableProcessor.cpp
    vmkit/trunk/mmtk/mmtk-j3/Lock.cpp
    vmkit/trunk/mmtk/mmtk-j3/Makefile
    vmkit/trunk/mmtk/mmtk-j3/Memory.cpp
    vmkit/trunk/mmtk/mmtk-j3/ObjectModel.cpp
    vmkit/trunk/mmtk/mmtk-j3/ReferenceProcessor.cpp
    vmkit/trunk/mmtk/mmtk-j3/Scanning.cpp
    vmkit/trunk/mmtk/mmtk-j3/Selected.cpp
    vmkit/trunk/mmtk/mmtk-j3/Statistics.cpp
    vmkit/trunk/mmtk/mmtk-j3/Strings.cpp
    vmkit/trunk/mmtk/mmtk-j3/SynchronizedCounter.cpp
    vmkit/trunk/mmtk/mmtk-j3/TraceInterface.cpp
    vmkit/trunk/mmtk/mmtk-j3/VM.cpp

Added: vmkit/trunk/mmtk/java/build.xml
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/build.xml?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/build.xml (added)
+++ vmkit/trunk/mmtk/java/build.xml Thu Jul 16 06:26:34 2009
@@ -0,0 +1,9 @@
+<project name="MMTK-VMKit" default="main" basedir=".">
+  <target name="main">
+    <mkdir dir="classes"/>
+    <javac srcdir="src" destdir="classes" source="1.5"/>
+    <jar jarfile="mmtk-vmkit.jar">
+      <fileset dir="classes"/>
+    </jar>
+  </target>
+</project>

Added: vmkit/trunk/mmtk/java/src/org/j3/config/Selected.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/config/Selected.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/j3/config/Selected.java (added)
+++ vmkit/trunk/mmtk/java/src/org/j3/config/Selected.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,58 @@
+//===------------------------- Selected.java ------------------------------===//
+//
+//                            The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+package org.j3.config;
+
+import org.mmtk.utility.Log;
+
+import org.vmmagic.pragma.*;
+
+public class Selected {
+  public static final String name = "org.mmtk.plan.marksweep.MS";
+  @Uninterruptible
+  public static final class Plan extends org.mmtk.plan.marksweep.MS
+  {
+    private static final Plan plan = new Plan();
+
+    @Inline
+    public static Plan get() { return plan; }
+  }
+
+  @Uninterruptible
+  public static final class Constraints extends org.mmtk.plan.marksweep.MSConstraints
+  {
+    private static final Constraints constraints = new Constraints();
+
+    @Inline
+    public static Constraints get() { return constraints; }
+  }
+
+  @Uninterruptible
+  public static class Collector extends org.mmtk.plan.marksweep.MSCollector
+  {
+    private static final Collector bootstrapCollector = new Collector();
+    
+    public static void staticCollect() {
+      bootstrapCollector.collect();
+    }
+
+    public Collector() {}
+    @Inline
+    public native static Collector get();
+  }
+
+  @Uninterruptible
+  public static class Mutator extends org.mmtk.plan.marksweep.MSMutator
+  {
+    private static final Mutator bootstrapThread = new Mutator();
+
+    @Inline
+    public static native Mutator get();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/ActivePlan.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/ActivePlan.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/j3/mmtk/ActivePlan.java (added)
+++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/ActivePlan.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,70 @@
+//===---------------- ActivePlan.java - Plan for J3 -----------------------===//
+//
+//                            The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+package org.j3.mmtk;
+
+
+import org.mmtk.plan.Plan;
+import org.mmtk.plan.CollectorContext;
+import org.mmtk.plan.MutatorContext;
+import org.mmtk.plan.PlanConstraints;
+import org.mmtk.utility.Log;
+
+import org.j3.config.Selected;
+
+import org.vmmagic.pragma.*;
+
+public final class ActivePlan extends org.mmtk.vm.ActivePlan {
+
+  /** @return The active Plan instance. */
+  @Inline
+  public Plan global() {
+    return Selected.Plan.get();
+  }
+
+  /** @return The active PlanConstraints instance. */
+  @Inline
+  public PlanConstraints constraints() {
+    return Selected.Constraints.get();
+  }
+
+  /** @return The number of registered CollectorContext instances. */
+  @Inline
+  public native int collectorCount();
+
+  /** @return The active CollectorContext instance. */
+  @Inline
+  public CollectorContext collector() {
+    return Selected.Collector.get();
+  }
+
+  /** @return The active MutatorContext instance. */
+  @Inline
+  public MutatorContext mutator() {
+    return Selected.Mutator.get();
+  }
+
+  /** @return The log for the active thread */
+  public Log log() {
+    return Selected.Mutator.get().getLog();
+  }
+
+  /** Reset the mutator iterator */
+  public native void resetMutatorIterator();
+
+  /**
+   * Return the next <code>MutatorContext</code> in a
+   * synchronized iteration of all mutators.
+   *
+   * @return The next <code>MutatorContext</code> in a
+   *  synchronized iteration of all mutators, or
+   *  <code>null</code> when all mutators have been done.
+   */
+  public native MutatorContext getNextMutator();
+}

Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/Assert.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/Assert.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/j3/mmtk/Assert.java (added)
+++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/Assert.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,92 @@
+//===--------------------------- Assert.java ------------------------------===//
+//
+//                            The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+package org.j3.mmtk;
+
+import org.mmtk.policy.Space;
+import org.vmmagic.pragma.*;
+import org.j3.runtime.VM;
+
+ at Uninterruptible
+public final class Assert extends org.mmtk.vm.Assert {
+  
+  /**
+   * <code>true</code> if assertions should be verified
+   */
+  protected final boolean getVerifyAssertionsConstant() {
+    return VM.VerifyAssertions;
+  }
+
+  /**
+   * This method should be called whenever an error is encountered.
+   *
+   * @param str A string describing the error condition.
+   */
+  public final void error(String str) {
+    Space.printUsagePages();
+    Space.printUsageMB();
+    fail(str);
+  }
+
+  /**
+   * Logs a message and traceback, then exits.
+   *
+   * @param message the string to log
+   */
+  public final void fail(String message) {
+    VM.sysFail(message);
+  }
+
+  @Uninterruptible
+  public final void exit(int rc) {
+    VM.sysExit(rc);
+  }
+
+  /**
+   * Checks that the given condition is true.  If it is not, this
+   * method does a traceback and exits. All calls to this method
+   * must be guarded by <code>VM.VERIFY_ASSERTIONS</code>.
+   *
+   * @param cond the condition to be checked
+   */
+  @Inline(value=Inline.When.AllArgumentsAreConstant)
+  public final void _assert(boolean cond) {
+    if (!org.mmtk.vm.VM.VERIFY_ASSERTIONS)
+      VM.sysFail("All assertions must be guarded by VM.VERIFY_ASSERTIONS: please check the failing assertion");
+    VM._assert(cond);
+  }
+
+  /**
+   * Checks that the given condition is true.  If it is not, this
+   * method prints a message, does a traceback and exits. All calls
+   * to this method must be guarded by <code>VM.VERIFY_ASSERTIONS</code>.
+   *
+   * @param cond the condition to be checked
+   * @param message the message to print
+   */
+  @Inline(value=Inline.When.ArgumentsAreConstant, arguments={1})
+  public final void _assert(boolean cond, String message) {
+    if (!org.mmtk.vm.VM.VERIFY_ASSERTIONS)
+      VM.sysFail("All assertions must be guarded by VM.VERIFY_ASSERTIONS: please check the failing assertion");
+    if (!cond) VM.sysWriteln(message);
+    VM._assert(cond);
+  }
+
+  public native final void dumpStack();
+
+  /**
+   * Checks if the virtual machine is running.  This value changes, so
+   * the call-through to the VM must be a method. 
+   *
+   * @return <code>true</code> if the virtual machine is running
+   */
+  public final boolean runningVM() { return VM.runningVM; }
+
+}

Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/Barriers.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/Barriers.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/j3/mmtk/Barriers.java (added)
+++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/Barriers.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,212 @@
+//===--------------- Barriers.java - Barriers for J3 ----------------------===//
+//
+//                            The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+package org.j3.mmtk;
+
+import org.jikesrvm.Magic;
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+public final class Barriers extends org.mmtk.vm.Barriers {
+  /**
+   * Perform the actual write of the write barrier.
+   *
+   * @param ref The object that has the reference field
+   * @param slot The slot that holds the reference
+   * @param target The value that the slot will be updated to
+   * @param metaDataA The offset from the ref
+   * @param metaDataB The index of the FieldReference
+   * @param mode The context in which the write is occuring
+   */
+  @Inline
+  public final void performWriteInBarrier(ObjectReference ref, Address slot,
+                                           ObjectReference target, Word metaDataA,
+                                           Word metaDataB, int mode) {
+    Object obj = ref.toObject();
+    Offset offset = metaDataA.toOffset();
+    int location = metaDataB.toInt();
+    Magic.setObjectAtOffset(obj, offset, target.toObject(), location);
+  }
+
+  /**
+   * Perform the actual write of the write barrier, writing the value as a raw word.
+   *
+   * @param ref The object that has the reference field
+   * @param slot The slot that holds the reference
+   * @param rawTarget The value that the slot will be updated to
+   * @param metaDataA The offset from the ref
+   * @param metaDataB The index of the FieldReference
+   * @param mode The context in which the write is occuring
+   */
+  @Inline
+  public final void performRawWriteInBarrier(ObjectReference ref, Address slot,
+                                             Word rawTarget, Word metaDataA,
+                                             Word metaDataB, int mode) {
+    Object obj = ref.toObject();
+    Offset offset = metaDataA.toOffset();
+    int location = metaDataB.toInt();
+    Magic.setWordAtOffset(obj, offset, rawTarget, location);
+  }
+
+  /**
+   * Perform the actual read of the read barrier.
+   *
+   * @param ref The object that has the reference field
+   * @param slot The slot that holds the reference
+   * @param metaDataA The offset from the ref
+   * @param metaDataB The index of the FieldReference
+   * @param mode The context in which the write is occuring
+   * @return the read value
+   */
+  @Inline
+  public final ObjectReference performReadInBarrier(ObjectReference ref, Address slot,
+                                                    Word metaDataA, Word metaDataB, int mode) {
+    Object obj = ref.toObject();
+    Offset offset = metaDataA.toOffset();
+    int location = metaDataB.toInt();
+    return ObjectReference.fromObject(Magic.getObjectAtOffset(obj, offset, location));
+  }
+
+  /**
+   * Perform the actual read of the read barrier, returning the value as a raw word.
+   *
+   * @param ref The object that has the reference field
+   * @param slot The slot that holds the reference
+   * @param metaDataA The offset from the ref
+   * @param metaDataB The index of the FieldReference
+   * @param mode The context in which the write is occuring
+   * @return the read value
+   */
+  @Inline
+  public final Word performRawReadInBarrier(ObjectReference ref, Address slot,
+                                            Word metaDataA, Word metaDataB, int mode) {
+    Object obj = ref.toObject();
+    Offset offset = metaDataA.toOffset();
+    int location = metaDataB.toInt();
+    return Magic.getWordAtOffset(obj, offset, location);
+  }
+
+  /**
+   * Atomically write a reference field of an object or array and return
+   * the old value of the reference field.
+   *
+   * @param ref The object that has the reference field
+   * @param slot The slot that holds the reference
+   * @param target The value that the slot will be updated to
+   * @param metaDataA The offset from the ref
+   * @param metaDataB Unused
+   * @param mode The context in which the write is occuring
+   * @return The value that was replaced by the write.
+   */
+  @Inline
+  public final ObjectReference performWriteInBarrierAtomic(
+                                           ObjectReference ref, Address slot,
+                                           ObjectReference target, Word metaDataA,
+                                           Word metaDataB, int mode) {
+    Object obj = ref.toObject();
+    Object newObject = target.toObject();
+    Offset offset = metaDataA.toOffset();
+    Object oldObject;
+    do {
+      oldObject = Magic.prepareObject(obj, offset);
+    } while (!Magic.attemptObject(obj, offset, oldObject, newObject));
+    return ObjectReference.fromObject(oldObject);
+  }
+
+
+  /**
+   * Atomically write a raw reference field of an object or array and return
+   * the old value of the reference field.
+   *
+   * @param ref The object that has the reference field
+   * @param slot The slot that holds the reference
+   * @param rawTarget The value that the slot will be updated to
+   * @param metaDataA The offset from the ref
+   * @param metaDataB Unused
+   * @param mode The context in which the write is occuring
+   * @return The value that was replaced by the write.
+   */
+  @Inline
+  public final Word performRawWriteInBarrierAtomic(
+                                           ObjectReference ref, Address slot,
+                                           Word rawTarget, Word metaDataA,
+                                           Word metaDataB, int mode) {
+    Object obj = ref.toObject();
+    Offset offset = metaDataA.toOffset();
+    Word oldValue;
+    do {
+      oldValue = Magic.prepareWord(obj, offset);
+    } while (!Magic.attemptWord(obj, offset, oldValue, rawTarget));
+    return oldValue;
+  }
+
+  /**
+   * Attempt an atomic compare and exchange in a write barrier sequence.
+   *
+   * @param ref The object that has the reference field
+   * @param slot The slot that holds the reference
+   * @param old The old reference to be swapped out
+   * @param target The value that the slot will be updated to
+   * @param metaDataA The offset from the ref
+   * @param metaDataB Unused
+   * @param mode The context in which the write is occuring
+   * @return True if the compare and swap was successful
+   */
+  @Inline
+  public final boolean tryCompareAndSwapWriteInBarrier(ObjectReference ref, Address slot,
+                                                       ObjectReference old, ObjectReference target,
+                                                       Word metaDataA, Word metaDataB, int mode) {
+    Object oldValue;
+    Offset offset = metaDataA.toOffset();
+    do {
+      oldValue = Magic.prepareObject(ref, offset);
+      if (oldValue != old) return false;
+    } while (!Magic.attemptObject(ref, offset, oldValue, target));
+    return true;
+  }
+
+
+  /**
+   * Attempt an atomic compare and exchange in a write barrier sequence.
+   *
+   * @param ref The object that has the reference field
+   * @param slot The slot that holds the reference
+   * @param rawOld The old reference to be swapped out
+   * @param rawTarget The value that the slot will be updated to
+   * @param metaDataA The offset from the ref
+   * @param metaDataB Unused
+   * @param mode The context in which the write is occuring
+   * @return True if the compare and swap was successful
+   */
+  @Inline
+  public final boolean tryRawCompareAndSwapWriteInBarrier(ObjectReference ref, Address slot,
+                                                          Word rawOld, Word rawTarget, Word metaDataA,
+                                                          Word metaDataB, int mode) {
+    Offset offset = metaDataA.toOffset();
+    do {
+      Word currentValue = Magic.prepareWord(ref, offset);
+      if (currentValue != rawOld) return false;
+    } while (!Magic.attemptObject(ref, offset, rawOld, rawTarget));
+    return true;
+  }
+
+  /**
+   * Sets an element of an object array without invoking any write
+   * barrier.  This method is called by the Map class to ensure
+   * potentially-allocation-triggering write barriers do not occur in
+   * allocation slow path code.
+   *
+   * @param dst the destination array
+   * @param index the index of the element to set
+   * @param value the new value for the element
+   */
+  public final void setArrayNoBarrier(Object [] dst, int index, Object value) {
+    dst[index] = value;
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/BuildTimeConfig.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/BuildTimeConfig.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/j3/mmtk/BuildTimeConfig.java (added)
+++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/BuildTimeConfig.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,128 @@
+//===---------------------- BuildTimeConfig.java --------------------------===//
+//
+//                            The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+package org.j3.mmtk;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Properties;
+
+import org.j3.runtime.VM;
+import org.j3.config.Selected;
+
+/**
+ * Read build-time configuration information for MMTk from a Java properties
+ * file.  Properties read through this mechanism should be read at build time
+ * and saved in static final fields.
+ *
+ * This is a wrapper for a java.util.Properties object.
+ */
+public final class BuildTimeConfig extends org.mmtk.vm.BuildTimeConfig {
+
+  /**
+   * The underlying properties object
+   */
+  private Properties props;
+
+  public BuildTimeConfig(String property_file_property, String default_property_file) {
+    props = getProperties(property_file_property,default_property_file);
+  }
+
+  public BuildTimeConfig(String property_file_property) {
+    props = getProperties(property_file_property,null);
+  }
+
+  /**
+   * @param property_file_property The name of the property that sets
+   * the location of the properties file
+   * @param default_property_file The default properties file.
+   *
+   */
+  private Properties getProperties(String property_file_property, String default_property_file) {
+    Properties props = new Properties();
+    return props;
+    /*String propFileName;
+    if (default_property_file == null) {
+      propFileName = System.getProperty(property_file_property);
+      if (propFileName == null) {
+        System.err.println(property_file_property+" must specify a properties file");
+        VM.sysExit(1);
+      }
+    } else {
+      propFileName = System.getProperty(property_file_property, default_property_file);
+    }
+    File propFile = new File(propFileName);
+
+    try {
+      BufferedInputStream propFileStream = new BufferedInputStream(new FileInputStream(propFile));
+      props.load(propFileStream);
+      propFileStream.close();
+    } catch (FileNotFoundException e) {
+      if (!propFileName.equals(default_property_file)) {
+        System.err.println(propFileName+" not found.");
+        VM.sysExit(1);
+      }
+    } catch (IOException e) {
+      e.printStackTrace();
+      VM.sysExit(1);
+    }
+    return props;*/
+  }
+
+  @Override
+  public String getPlanName() {
+    return Selected.name;
+  }
+
+  @Override
+  public boolean getBooleanProperty(String name, boolean dflt) {
+    String value = props.getProperty(name,Boolean.toString(dflt));
+    return Boolean.valueOf(value);
+  }
+
+  @Override
+  public boolean getBooleanProperty(String name) {
+    String value = props.getProperty(name);
+    if (value == null)
+      throw new RuntimeException("Undefined property "+name);
+    return Boolean.valueOf(value);
+  }
+
+  @Override
+  public int getIntProperty(String name, int dflt) {
+    String value = props.getProperty(name,Integer.toString(dflt));
+    return Integer.valueOf(value);
+  }
+
+  @Override
+  public int getIntProperty(String name) {
+    String value = props.getProperty(name);
+    if (value == null)
+      throw new RuntimeException("Undefined property "+name);
+    return Integer.valueOf(value);
+  }
+
+  @Override
+  public String getStringProperty(String name, String dflt) {
+    return props.getProperty(name,dflt);
+  }
+
+  @Override
+  public String getStringProperty(String name) {
+    String value = props.getProperty(name);
+    if (value == null)
+      throw new RuntimeException("Undefined property "+name);
+    return value;
+  }
+
+
+}

Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/Collection.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/Collection.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/j3/mmtk/Collection.java (added)
+++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/Collection.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,120 @@
+//===------------------------- Collection.java ----------------------------===//
+//
+//                            The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+package org.j3.mmtk;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.plan.CollectorContext;
+import org.mmtk.plan.MutatorContext;
+import org.mmtk.utility.options.Options;
+
+import org.vmmagic.pragma.Inline;
+import org.vmmagic.pragma.Interruptible;
+import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.pragma.UninterruptibleNoWarn;
+import org.vmmagic.pragma.Unpreemptible;
+import org.vmmagic.unboxed.Address;
+
+ at Uninterruptible
+public final class Collection extends org.mmtk.vm.Collection {
+
+  /**
+   * Triggers a collection.
+   *
+   * @param why the reason why a collection was triggered.  0 to
+   * <code>TRIGGER_REASONS - 1</code>.
+   */
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
+  public native final void triggerCollection(int why);
+
+  /**
+   * Joins a collection.
+   */
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
+  public native final void joinCollection();
+
+  /**
+   * The maximum number collection attempts across threads.
+   */
+  public native int maximumCollectionAttempt();
+
+  /**
+   * Report that the the physical allocation has succeeded.
+   */
+  public native void reportAllocationSuccess();
+
+  /**
+   * Report that a physical allocation has failed.
+   */
+  public native void reportPhysicalAllocationFailed();
+
+  /**
+   * Does the VM consider this an emergency allocation, where the normal
+   * heap size rules can be ignored.
+   */
+  public native boolean isEmergencyAllocation();
+
+  /**
+   * Trigger an asynchronous collection, checking for memory
+   * exhaustion first.
+   */
+  @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
+  public native final void triggerAsyncCollection(int why);
+
+  /**
+   * Determine whether a collection cycle has fully completed (this is
+   * used to ensure a GC is not in the process of completing, to
+   * avoid, for example, an async GC being triggered on the switch
+   * from GC to mutator thread before all GC threads have switched.
+   *
+   * @return True if GC is not in progress.
+   */
+  @Uninterruptible
+  public native final boolean noThreadsInGC();
+
+  /**
+   * Prepare a mutator for a collection.
+   *
+   * @param m the mutator to prepare
+   */
+  public native final void prepareMutator(MutatorContext m);
+
+  /**
+   * Prepare a collector for a collection.
+   *
+   * @param c the collector to prepare
+   */
+  public native final void prepareCollector(CollectorContext c);
+
+  /**
+   * Rendezvous with all other processors, returning the rank
+   * (that is, the order this processor arrived at the barrier).
+   */
+  public native final int rendezvous(int where);
+
+  // REVIEW: what are the semantics of this method in a concurrent collector?
+  /** @return The number of active collector threads */
+  public native final int activeGCThreads();
+
+  /**
+   * @return The ordinal ID of the running collector thread w.r.t.
+   * the set of active collector threads (zero based)
+   */
+  public native final int activeGCThreadOrdinal();
+
+  /**
+   * Request each mutator flush remembered sets. This method
+   * will trigger the flush and then yield until all processors have
+   * flushed.
+   */
+  @UninterruptibleNoWarn("This method is really unpreemptible, since it involves blocking")
+  public native void requestMutatorFlush();
+
+}
+

Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/Debug.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/Debug.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/j3/mmtk/Debug.java (added)
+++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/Debug.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,28 @@
+//===--------------------------- Debug.java -------------------------------===//
+//
+//                            The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+package org.j3.mmtk;
+
+import org.vmmagic.pragma.Uninterruptible;
+
+/**
+ * Debugger support for the MMTk harness
+ */
+ at Uninterruptible
+public final class Debug extends org.mmtk.vm.Debug {
+
+  /**
+   * Enable/disable MMTk debugger support
+   */
+  @Override
+  public boolean isEnabled() {
+    return false;
+  }
+
+}

Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/Factory.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/Factory.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/j3/mmtk/Factory.java (added)
+++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/Factory.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,501 @@
+//===-------------------------- Factory.java ------------------------------===//
+//
+//                            The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+package org.j3.mmtk;
+
+import org.vmutil.options.OptionSet;
+import org.mmtk.utility.gcspy.Color;
+import org.mmtk.utility.gcspy.drivers.AbstractDriver;
+import org.mmtk.vm.ReferenceProcessor.Semantics;
+
+import org.j3.runtime.VM;
+
+/**
+ * This is a VM-specific class which defines factory methods for
+ * VM-specific types which must be instantiated within MMTk.
+ *
+ * @see org.mmtk.vm.Factory
+ */
+public final class Factory extends org.mmtk.vm.Factory {
+
+  private static final String DEFAULT_MMTK_PROPERTIES = ".mmtk.properties";
+  private static final String CONFIG_FILE_PROPERTY = "mmtk.properties";
+
+  /**
+   * Create or retrieve the OptionSet used for MMTk options.
+   *
+   * @return A concrete VM-specific OptionSet instance
+   */
+  public OptionSet getOptionSet() {
+    return org.j3.options.OptionSet.gc;
+  }
+
+  /**
+   * Create a new ActivePlan instance using the appropriate VM-specific
+   * concrete ActivePlan sub-class.
+   *
+   * @see ActivePlan
+   * @return A concrete VM-specific ActivePlan instance.
+   */
+  public org.mmtk.vm.ActivePlan newActivePlan() {
+    try {
+      return new ActivePlan();
+    } catch (Exception e) {
+      VM.sysFail("Failed to allocate new ActivePlan!");
+      return null; // never get here
+    }
+  }
+
+  /**
+   * Create a new Assert instance using the appropriate VM-specific
+   * concrete Assert sub-class.
+   *
+   * @see Assert
+   * @return A concrete VM-specific Assert instance.
+   */
+  public org.mmtk.vm.Assert newAssert() {
+    try {
+      return new Assert();
+    } catch (Exception e) {
+      VM.sysFail("Failed to allocate new Assert!");
+      return null; // never get here
+    }
+  }
+
+  /**
+   * Create a new Barriers instance using the appropriate VM-specific
+   * concrete Barriers sub-class.
+   *
+   * @see Barriers
+   * @return A concrete VM-specific Barriers instance.
+   */
+  public org.mmtk.vm.Barriers newBarriers() {
+    try {
+      return new Barriers();
+    } catch (Exception e) {
+      VM.sysFail("Failed to allocate new Barriers!");
+      return null; // never get here
+    }
+  }
+
+  /**
+   * Create a new Collection instance using the appropriate VM-specific
+   * concrete Collection sub-class.
+   *
+   * @see Collection
+   * @return A concrete VM-specific Collection instance.
+   */
+  public org.mmtk.vm.Collection newCollection() {
+    try {
+      return new Collection();
+    } catch (Exception e) {
+      VM.sysFail("Failed to allocate new Collection!");
+      return null; // never get here
+    }
+  }
+
+  /**
+   * Create a new BuildTimeConfig instance using the appropriate VM-specific
+   * concrete BuildTimeConfig sub-class.
+   *
+   * @see Collection
+   * @return A concrete VM-specific Collection instance.
+   */
+  public org.mmtk.vm.BuildTimeConfig newBuildTimeConfig() {
+    try {
+      return new BuildTimeConfig(CONFIG_FILE_PROPERTY, DEFAULT_MMTK_PROPERTIES);
+    } catch (Exception e) {
+      VM.sysFail("Failed to allocate new BuildTimeConfiguration!");
+      return null; // never get here
+    }
+  }
+
+  /**
+   * Create a new Lock instance using the appropriate VM-specific
+   * concrete Lock sub-class.
+   *
+   * @see Lock
+   *
+   * @param name The string to be associated with this lock instance
+   * @return A concrete VM-specific Lock instance.
+   */
+  public org.mmtk.vm.Lock newLock(String name) {
+    try {
+      return new Lock(name);
+    } catch (Exception e) {
+      VM.sysFail("Failed to allocate new Lock!");
+      return null; // never get here
+    }
+  }
+
+  /**
+   * Create a new Memory instance using the appropriate VM-specific
+   * concrete Memory sub-class.
+   *
+   * @see Memory
+   * @return A concrete VM-specific Memory instance.
+   */
+  public org.mmtk.vm.Memory newMemory() {
+    try {
+      return new Memory();
+    } catch (Exception e) {
+      VM.sysFail("Failed to allocate new Memory!");
+      return null; // never get here
+    }
+  }
+
+  /**
+   * Create a new ObjectModel instance using the appropriate VM-specific
+   * concrete ObjectModel sub-class.
+   *
+   * @see ObjectModel
+   * @return A concrete VM-specific ObjectModel instance.
+   */
+  public org.mmtk.vm.ObjectModel newObjectModel() {
+    try {
+      return new ObjectModel();
+    } catch (Exception e) {
+      VM.sysFail("Failed to allocate new ObjectModel!");
+      return null; // never get here
+    }
+  }
+
+  /**
+   * Create a new ReferenceProcessor instance using the appropriate VM-specific
+   * concrete ReferenceProcessor sub-class.
+   *
+   * @see ReferenceProcessor
+   * @return A concrete VM-specific ReferenceProcessor instance.
+   */
+  public org.mmtk.vm.ReferenceProcessor newReferenceProcessor(Semantics semantics) {
+    try {
+      return ReferenceProcessor.get(semantics);
+    } catch (Exception e) {
+      VM.sysFail("Failed to allocate new ReferenceProcessor!");
+      return null; // never get here
+    }
+  }
+
+  /**
+   * Create a new FinalizableProcessor instance using the appropriate VM-specific
+   * concrete FinalizableProcessor sub-class.
+   *
+   * @see ReferenceProcessor
+   * @return A concrete VM-specific FinalizableProcessor instance.
+   */
+  public org.mmtk.vm.FinalizableProcessor newFinalizableProcessor() {
+    try {
+      return FinalizableProcessor.getProcessor();
+    } catch (Exception e) {
+      VM.sysFail("Failed to allocate new FinalizableProcessor!");
+      return null; // never get here
+    }
+  }
+
+  /**
+   * Create a new Scanning instance using the appropriate VM-specific
+   * concrete Scanning sub-class.
+   *
+   * @see Scanning
+   * @return A concrete VM-specific Scanning instance.
+   */
+  public org.mmtk.vm.Scanning newScanning() {
+    try {
+      return new Scanning();
+    } catch (Exception e) {
+      VM.sysFail("Failed to allocate new Scanning!");
+      return null; // never get here
+    }
+  }
+
+  /**
+   * Create a new Statistics instance using the appropriate VM-specific
+   * concrete Statistics sub-class.
+   *
+   * @see Statistics
+   * @return A concrete VM-specific Statistics instance.
+   */
+  public org.mmtk.vm.Statistics newStatistics() {
+    try {
+      return new Statistics();
+    } catch (Exception e) {
+      VM.sysFail("Failed to allocate new Statistics!");
+      return null; // never get here
+    }
+  }
+
+  /**
+   * Create a new Strings instance using the appropriate VM-specific
+   * concrete Strings sub-class.
+   *
+   * @see Strings
+   * @return A concrete VM-specific Strings instance.
+   */
+  public org.mmtk.vm.Strings newStrings() {
+    try {
+      return new Strings();
+    } catch (Exception e) {
+      VM.sysFail("Failed to allocate new Strings!");
+      return null; // never get here
+    }
+  }
+
+  /**
+   * Create a new SynchronizedCounter instance using the appropriate
+   * VM-specific concrete SynchronizedCounter sub-class.
+   *
+   * @see SynchronizedCounter
+   *
+   * @return A concrete VM-specific SynchronizedCounter instance.
+   */
+  public org.mmtk.vm.SynchronizedCounter newSynchronizedCounter() {
+    try {
+      return new SynchronizedCounter();
+    } catch (Exception e) {
+     VM.sysFail("Failed to allocate new SynchronizedCounter!");
+      return null; // never get here
+    }
+  }
+
+  /**
+   * Create a new TraceInterface instance using the appropriate VM-specific
+   * concrete TraceInterface sub-class.
+   *
+   * @see TraceInterface
+   * @return A concrete VM-specific TraceInterface instance.
+   */
+  public org.mmtk.vm.TraceInterface newTraceInterface() {
+    try {
+      return new TraceInterface();
+    } catch (Exception e) {
+      VM.sysFail("Failed to allocate new TraceInterface!");
+      return null; // never get here
+    }
+  }
+
+  /**
+   * Create a new MMTk_Events instance using the appropriate VM-specific
+   * concrete MMTk_Events sub-class.
+   *
+   * @see MMTk_Events
+   * @return A concrete VM-specific MMTk_Events instance.
+   */
+  public org.mmtk.vm.MMTk_Events newEvents() {
+    try {
+      return new MMTk_Events();
+    } catch (Exception e) {
+      VM.sysFail("Failed to allocate new MMTk_Events!");
+      return null; // never get here
+    }
+  }
+
+  public org.mmtk.vm.Debug newDebug() {
+    return new Debug();
+  }
+
+  /**********************************************************************
+   * GCspy methods
+   */
+
+  /**
+   * Create a new Util instance using the appropriate VM-specific
+   * concrete Util sub-class.
+   *
+   * @see org.mmtk.vm.gcspy.Util
+   * @return A concrete VM-specific Util instance.
+   */
+  public org.mmtk.vm.gcspy.Util newGCspyUtil() {
+    try {
+      return null;
+    } catch (Exception e) {
+      VM.sysFail("Failed to allocate new Util!");
+      return null; // never get here
+    }
+  }
+
+  /**
+   * Create a new ServerInterpreter instance using the appropriate VM-specific
+   * concrete ServerInterpreter sub-class.
+   *
+   * @see org.mmtk.vm.gcspy.ServerInterpreter
+   * @return A concrete VM-specific ServerInterpreter instance.
+   */
+  public org.mmtk.vm.gcspy.ServerInterpreter newGCspyServerInterpreter() {
+    try {
+      return null;
+    } catch (Exception e) {
+      VM.sysFail("Failed to allocate new ServerInterpreter!");
+      return null; // never get here
+    }
+  }
+
+  /**
+   * Create a new ServerSpace instance using the appropriate VM-specific
+   * concrete ServerSpace sub-class.
+   *
+   * @param serverInterpreter The server that owns this space
+   * @param serverName The server's name
+   * @param driverName The space driver's name
+   * @param title Title for the space
+   * @param blockInfo A label for each block
+   * @param tileNum Max number of tiles in this space
+   * @param unused A label for unused blocks
+   * @param mainSpace Whether this space is the main space
+   *
+   * @see org.mmtk.vm.gcspy.ServerSpace
+   * @return A concrete VM-specific ServerSpace instance.
+   */
+  public org.mmtk.vm.gcspy.ServerSpace newGCspyServerSpace(
+      org.mmtk.vm.gcspy.ServerInterpreter serverInterpreter,
+      String serverName,
+      String driverName,
+      String title,
+      String blockInfo,
+      int tileNum,
+      String unused,
+      boolean mainSpace){
+    try {
+      return null;
+    } catch (Exception e) {
+      VM.sysFail("Failed to allocate new ServerSpace!");
+      return null; // never get here
+    }
+  }
+
+  /**
+   * Create a new ByteStream instance using the appropriate
+   * VM-specific concrete ByteStream sub-class.
+   *
+   * @param driver        The driver that owns this Stream
+   * @param name           The name of the stream (e.g. "Used space")
+   * @param minValue       The minimum value for any item in this stream.
+   *                       Values less than this will be represented as "minValue-"
+   * @param maxValue       The maximum value for any item in this stream.
+   *                       Values greater than this will be represented as "maxValue+"
+   * @param zeroValue      The zero value for this stream
+   * @param defaultValue   The default value for this stream
+   * @param stringPre      A string to prefix values (e.g. "Used: ")
+   * @param stringPost     A string to suffix values (e.g. " bytes.")
+   * @param presentation   How a stream value is to be presented.
+   * @param paintStyle     How the value is to be painted.
+   * @param indexMaxStream The index of the maximum stream if the presentation is *_VAR.
+   * @param colour         The default colour for tiles of this stream
+   * @see org.mmtk.vm.gcspy.IntStream
+   *
+   * @return A concrete VM-specific ByteStream instance.
+   */
+  public org.mmtk.vm.gcspy.ByteStream newGCspyByteStream(
+      AbstractDriver driver,
+      String name,
+      byte minValue,
+      byte maxValue,
+      byte zeroValue,
+      byte defaultValue,
+      String stringPre,
+      String stringPost,
+      int presentation,
+      int paintStyle,
+      int indexMaxStream,
+      Color colour,
+      boolean summary) {
+    try {
+      return null;
+    } catch (Exception e) {
+      VM.sysFail("Failed to allocate new ByteStream!");
+      return null; // never get here
+    }
+  }
+  /**
+   * Create a new IntStream instance using the appropriate
+   * VM-specific concrete IntStream sub-class.
+   *
+   * @param driver        The driver that owns this Stream
+   * @param name           The name of the stream (e.g. "Used space")
+   * @param minValue       The minimum value for any item in this stream.
+   *                       Values less than this will be represented as "minValue-"
+   * @param maxValue       The maximum value for any item in this stream.
+   *                       Values greater than this will be represented as "maxValue+"
+   * @param zeroValue      The zero value for this stream
+   * @param defaultValue   The default value for this stream
+   * @param stringPre      A string to prefix values (e.g. "Used: ")
+   * @param stringPost     A string to suffix values (e.g. " bytes.")
+   * @param presentation   How a stream value is to be presented.
+   * @param paintStyle     How the value is to be painted.
+   * @param indexMaxStream The index of the maximum stream if the presentation is *_VAR.
+   * @param colour         The default colour for tiles of this stream
+   * @see org.mmtk.vm.gcspy.IntStream
+   *
+   * @return A concrete VM-specific IntStream instance.
+   */
+  public org.mmtk.vm.gcspy.IntStream newGCspyIntStream(
+      AbstractDriver driver,
+      String name,
+      int minValue,
+      int maxValue,
+      int zeroValue,
+      int defaultValue,
+      String stringPre,
+      String stringPost,
+      int presentation,
+      int paintStyle,
+      int indexMaxStream,
+      Color colour,
+      boolean summary) {
+    try {
+      return null;
+    } catch (Exception e) {
+      VM.sysFail("Failed to allocate new IntStream!");
+      return null; // never get here
+    }
+  }
+
+  /**
+   * Create a new ShortStream instance using the appropriate
+   * VM-specific concrete ShortStream sub-class.
+   *
+   * @param driver        The driver that owns this Stream
+   * @param name           The name of the stream (e.g. "Used space")
+   * @param minValue       The minimum value for any item in this stream.
+   *                       Values less than this will be represented as "minValue-"
+   * @param maxValue       The maximum value for any item in this stream.
+   *                       Values greater than this will be represented as "maxValue+"
+   * @param zeroValue      The zero value for this stream
+   * @param defaultValue   The default value for this stream
+   * @param stringPre      A string to prefix values (e.g. "Used: ")
+   * @param stringPost     A string to suffix values (e.g. " bytes.")
+   * @param presentation   How a stream value is to be presented.
+   * @param paintStyle     How the value is to be painted.
+   * @param indexMaxStream The index of the maximum stream if the presentation is *_VAR.
+   * @param colour         The default colour for tiles of this stream
+   * @see org.mmtk.vm.gcspy.IntStream
+   *
+   * @return A concrete VM-specific ShortStream instance.
+   */
+  public org.mmtk.vm.gcspy.ShortStream newGCspyShortStream(
+      AbstractDriver driver,
+      String name,
+      short minValue,
+      short maxValue,
+      short zeroValue,
+      short defaultValue,
+      String stringPre,
+      String stringPost,
+      int presentation,
+      int paintStyle,
+      int indexMaxStream,
+      Color colour,
+      boolean summary) {
+    try {
+      return null;
+    } catch (Exception e) {
+      VM.sysFail("Failed to allocate new ShortStream!");
+      return null; // never get here
+    }
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/FinalizableProcessor.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/FinalizableProcessor.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/j3/mmtk/FinalizableProcessor.java (added)
+++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/FinalizableProcessor.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,68 @@
+//===---------------------- FinalizableProcessor.java ---------------------===//
+//
+//                            The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+package org.j3.mmtk;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+import org.j3.runtime.VM;
+import org.j3.config.Selected;
+import org.mmtk.plan.TraceLocal;
+
+/**
+ * This class manages the processing of finalizable objects.
+ */
+
+ at Uninterruptible
+public final class FinalizableProcessor extends org.mmtk.vm.FinalizableProcessor {
+
+  /********************************************************************
+   * Class fields
+   */
+
+  /** The FinalizableProcessor singleton */
+  private static final FinalizableProcessor finalizableProcessor = new FinalizableProcessor();
+
+  public static FinalizableProcessor getProcessor() {
+    return finalizableProcessor;
+  }
+
+  public native void clear();
+
+  /**
+   * Scan through all entries in the table and forward.
+   *
+   * Currently ignores the nursery hint.
+   *
+   * TODO parallelise this code?
+   *
+   * @param trace The trace
+   * @param nursery Is this a nursery collection ?
+   */
+  @Override
+  public native void forward(TraceLocal trace, boolean nursery);
+
+  /**
+   * Scan through the list of references. Calls ReferenceProcessor's
+   * processReference method for each reference and builds a new
+   * list of those references still active.
+   *
+   * Depending on the value of <code>nursery</code>, we will either
+   * scan all references, or just those created since the last scan.
+   *
+   * TODO parallelise this code
+   *
+   * @param nursery Scan only the newly created references
+   */
+  @Override
+  @UninterruptibleNoWarn
+  public native void scan(TraceLocal trace, boolean nursery);
+
+}

Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/Lock.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/Lock.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/j3/mmtk/Lock.java (added)
+++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/Lock.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,39 @@
+//===--------------------------- Lock.java --------------------------------===//
+//
+//                            The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+package org.j3.mmtk;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+ at Uninterruptible public class Lock extends org.mmtk.vm.Lock {
+
+  private int state;
+  private String name;        // logical name of lock
+
+  // Diagnosis Instance fields
+  public Lock(String name) {
+    this();
+    this.name = name;
+  }
+
+  public Lock() {
+    state = 0;
+  }
+
+  public void setName(String str) {
+    name = str;
+  }
+
+  public native void acquire();
+
+  public native void check(int w);
+
+  public native void release();
+}

Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/MMTk_Events.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/MMTk_Events.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/j3/mmtk/MMTk_Events.java (added)
+++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/MMTk_Events.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,32 @@
+//===-------------------- --- MMTk_Events.java ----------------------------===//
+//
+//                            The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+package org.j3.mmtk;
+
+import org.mmtk.policy.Space;
+import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.unboxed.Address;
+import org.vmmagic.unboxed.Extent;
+
+/**
+ * Implementation of simple MMTK event generation hooks
+ * to allow MMTk to generate TuningFork events.
+ */
+ at Uninterruptible
+public class MMTk_Events extends org.mmtk.vm.MMTk_Events {
+
+  public void tracePageAcquired(Space space, Address startAddress, int numPages) {
+  }
+
+  public void tracePageReleased(Space space, Address startAddress, int numPages) {
+  }
+
+  public void heapSizeChanged(Extent heapSize) {
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/Memory.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/Memory.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/j3/mmtk/Memory.java (added)
+++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/Memory.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,147 @@
+//===-------------------------- Memory.java -------------------------------===//
+//
+//                            The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+package org.j3.mmtk;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.policy.ImmortalSpace;
+import org.mmtk.utility.Constants;
+import org.mmtk.utility.heap.VMRequest;
+
+import org.j3.runtime.VM;
+import org.jikesrvm.Magic;
+import org.jikesrvm.SizeConstants;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+ at Uninterruptible
+public final class Memory extends org.mmtk.vm.Memory {
+
+  protected native final Address getHeapStartConstant();
+  protected native final Address getHeapEndConstant();
+  protected native final Address getAvailableStartConstant();
+  protected native final Address getAvailableEndConstant();
+  protected final byte getLogBytesInAddressConstant() { return (byte)SizeConstants.LOG_BYTES_IN_ADDRESS; }
+  protected final byte getLogBytesInWordConstant() { return (byte)SizeConstants.LOG_BYTES_IN_WORD; }
+  protected final byte getLogBytesInPageConstant() { return (byte)SizeConstants.LOG_BYTES_IN_PAGE; }
+  protected final byte getLogMinAlignmentConstant() { return (byte)SizeConstants.LOG_BYTES_IN_INT;}
+  protected final int getMaxBytesPaddingConstant() { return (byte)SizeConstants.BYTES_IN_DOUBLE; }
+  protected final int getAlignmentValueConstant() { return 0xdeadbeef; }
+
+  /* On Intel we align code to 16 bytes as recommended in the optimization manual */
+  protected final byte getMaxAlignmentShiftConstant() { 
+    return (byte)((VM.BuildForIA32 ? 1 : 0) + SizeConstants.LOG_BYTES_IN_LONG - SizeConstants.LOG_BYTES_IN_INT);
+  }
+
+  private static ImmortalSpace bootSpace;
+
+  /**
+   * Return the space associated with/reserved for the VM.
+   */
+  @Interruptible
+  public final ImmortalSpace getVMSpace() {
+    if (bootSpace == null) {
+      bootSpace = new ImmortalSpace("boot", Plan.DEFAULT_POLL_FREQUENCY, VMRequest.create());
+    }
+    return bootSpace;
+  }
+
+  /** Global preparation for a collection. */
+  public final void globalPrepareVMSpace() { bootSpace.prepare(); }
+
+  /** Per-collector preparation for a collection. */
+  public final void collectorPrepareVMSpace() {}
+
+  /** Per-collector post-collection work. */
+  public final void collectorReleaseVMSpace() {}
+
+  /** Global post-collection work. */
+  public final void globalReleaseVMSpace() { bootSpace.release(); }
+
+  /**
+   * Sets the range of addresses associated with a heap.
+   *
+   * @param id the heap identifier
+   * @param start the address of the start of the heap
+   * @param end the address of the end of the heap
+   */
+  public final void setHeapRange(int id, Address start, Address end) {}
+
+ /**
+   * Demand zero mmaps an area of virtual memory.
+   *
+   * @param start the address of the start of the area to be mapped
+   * @param size the size, in bytes, of the area to be mapped
+   * @return 0 if successful, otherwise the system errno
+   */
+  public native final int dzmmap(Address start, int size);
+
+  /**
+   * Protects access to an area of virtual memory.
+   *
+   * @param start the address of the start of the area to be mapped
+   * @param size the size, in bytes, of the area to be mapped
+   * @return <code>true</code> if successful, otherwise
+   * <code>false</code>
+   */
+  public native final boolean mprotect(Address start, int size);
+
+  /**
+   * Allows access to an area of virtual memory.
+   *
+   * @param start the address of the start of the area to be mapped
+   * @param size the size, in bytes, of the area to be mapped
+   * @return <code>true</code> if successful, otherwise
+   * <code>false</code>
+   */
+  public native final boolean munprotect(Address start, int size);
+
+  /**
+   * Zero a region of memory.
+   * @param start Start of address range (inclusive)
+   * @param len Length in bytes of range to zero
+   * Returned: nothing
+   */
+  public native final void zero(Address start, Extent len);
+
+  /**
+   * Zero a range of pages of memory.
+   * @param start Start of address range (must be a page address)
+   * @param len Length in bytes of range (must be multiple of page size)
+   */
+  public native final void zeroPages(Address start, int len);
+
+  /**
+   * Logs the contents of an address and the surrounding memory to the
+   * error output.
+   *
+   * @param start the address of the memory to be dumped
+   * @param beforeBytes the number of bytes before the address to be
+   * included
+   * @param afterBytes the number of bytes after the address to be
+   * included
+   */
+  public native final void dumpMemory(Address start, int beforeBytes,
+                                      int afterBytes);
+
+  /*
+   * Utilities from the VM class
+   */
+
+  @Inline
+  public final void sync() {
+    Magic.sync();
+  }
+
+  @Inline
+  public final void isync() {
+    Magic.isync();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/ObjectModel.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/ObjectModel.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/j3/mmtk/ObjectModel.java (added)
+++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/ObjectModel.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,237 @@
+//===------------------------ ObjectModel.java ----------------------------===//
+//
+//                            The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+package org.j3.mmtk;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+ at Uninterruptible
+public final class ObjectModel extends org.mmtk.vm.ObjectModel {
+
+  protected native Offset getArrayBaseOffset();
+
+  /**
+   * Copy an object using a plan's allocCopy to get space and install
+   * the forwarding pointer.  On entry, <code>from</code> must have
+   * been reserved for copying by the caller.  This method calls the
+   * plan's <code>getStatusForCopy()</code> method to establish a new
+   * status word for the copied object and <code>postCopy()</code> to
+   * allow the plan to perform any post copy actions.
+   *
+   * @param from the address of the object to be copied
+   * @return the address of the new object
+   */
+  @Inline
+  public native ObjectReference copy(ObjectReference from, int allocator);
+
+  /**
+   * Copy an object to be pointer to by the to address. This is required
+   * for delayed-copy collectors such as compacting collectors. During the
+   * collection, MMTk reserves a region in the heap for an object as per
+   * requirements found from ObjectModel and then asks ObjectModel to
+   * determine what the object's reference will be post-copy.
+   *
+   * @param from the address of the object to be copied
+   * @param to The target location.
+   * @param region The start (or an address less than) the region that was reserved for this object.
+   * @return Address The address past the end of the copied object
+   */
+  @Inline
+  public native Address copyTo(ObjectReference from, ObjectReference to, Address region);
+
+  /**
+   * Return the reference that an object will be refered to after it is copied
+   * to the specified region. Used in delayed-copy collectors such as compacting
+   * collectors.
+   *
+   * @param from The object to be copied.
+   * @param to The region to be copied to.
+   * @return The resulting reference.
+   */
+  public native ObjectReference getReferenceWhenCopiedTo(ObjectReference from, Address to);
+
+  /**
+   * Gets a pointer to the address just past the end of the object.
+   *
+   * @param object The object.
+   */
+  public native Address getObjectEndAddress(ObjectReference object);
+
+  /**
+   * Return the size required to copy an object
+   *
+   * @param object The object whose size is to be queried
+   * @return The size required to copy <code>obj</code>
+   */
+  public native int getSizeWhenCopied(ObjectReference object);
+
+  /**
+   * Return the alignment requirement for a copy of this object
+   *
+   * @param object The object whose size is to be queried
+   * @return The alignment required for a copy of <code>obj</code>
+   */
+  public native int getAlignWhenCopied(ObjectReference object);
+
+  /**
+   * Return the alignment offset requirements for a copy of this object
+   *
+   * @param object The object whose size is to be queried
+   * @return The alignment offset required for a copy of <code>obj</code>
+   */
+  public native int getAlignOffsetWhenCopied(ObjectReference object);
+
+  /**
+   * Return the size used by an object
+   *
+   * @param object The object whose size is to be queried
+   * @return The size of <code>obj</code>
+   */
+  public native int getCurrentSize(ObjectReference object);
+
+  /**
+   * Return the next object in the heap under contiguous allocation
+   */
+  public native ObjectReference getNextObject(ObjectReference object);
+
+  /**
+   * Return an object reference from knowledge of the low order word
+   */
+  public native ObjectReference getObjectFromStartAddress(Address start);
+
+  /**
+   * Get the type descriptor for an object.
+   *
+   * @param ref address of the object
+   * @return byte array with the type descriptor
+   */
+  public native byte [] getTypeDescriptor(ObjectReference ref);
+
+  @Inline
+  public native int getArrayLength(ObjectReference object);
+
+  /**
+   * Is the passed object an array?
+   *
+   * @param object address of the object
+   */
+  public native boolean isArray(ObjectReference object);
+
+  /**
+   * Is the passed object a primitive array?
+   *
+   * @param object address of the object
+   */
+  public native boolean isPrimitiveArray(ObjectReference object);
+
+  /**
+   * Attempts to set the bits available for memory manager use in an
+   * object.  The attempt will only be successful if the current value
+   * of the bits matches <code>oldVal</code>.  The comparison with the
+   * current value and setting are atomic with respect to other
+   * allocators.
+   *
+   * @param object the address of the object
+   * @param oldVal the required current value of the bits
+   * @param newVal the desired new value of the bits
+   * @return <code>true</code> if the bits were set,
+   * <code>false</code> otherwise
+   */
+  public native boolean attemptAvailableBits(ObjectReference object,
+                                             Word oldVal, Word newVal);
+
+  /**
+   * Gets the value of bits available for memory manager use in an
+   * object, in preparation for setting those bits.
+   *
+   * @param object the address of the object
+   * @return the value of the bits
+   */
+  public native Word prepareAvailableBits(ObjectReference object);
+
+  /**
+   * Sets the byte available for memory manager use in an object.
+   *
+   * @param object the address of the object
+   * @param val the new value of the byte
+   */
+  public native void writeAvailableByte(ObjectReference object, byte val);
+
+  /**
+   * Read the byte available for memory manager use in an object.
+   *
+   * @param object the address of the object
+   * @return the value of the byte
+   */
+  public native byte readAvailableByte(ObjectReference object);
+
+  /**
+   * Sets the bits available for memory manager use in an object.
+   *
+   * @param object the address of the object
+   * @param val the new value of the bits
+   */
+  public native void writeAvailableBitsWord(ObjectReference object, Word val);
+
+  /**
+   * Read the bits available for memory manager use in an object.
+   *
+   * @param object the address of the object
+   * @return the value of the bits
+   */
+  public native Word readAvailableBitsWord(ObjectReference object);
+
+  /**
+   * Gets the offset of the memory management header from the object
+   * reference address.  XXX The object model / memory manager
+   * interface should be improved so that the memory manager does not
+   * need to know this.
+   *
+   * @return the offset, relative the object reference address
+   */
+  /* AJG: Should this be a variable rather than method? */
+  public native Offset GC_HEADER_OFFSET();
+
+  /**
+   * Returns the lowest address of the storage associated with an object.
+   *
+   * @param object the reference address of the object
+   * @return the lowest address of the object
+   */
+  @Inline
+  public native Address objectStartRef(ObjectReference object);
+
+  /**
+   * Returns an address guaranteed to be inside the storage assocatied
+   * with and object.
+   *
+   * @param object the reference address of the object
+   * @return an address inside the object
+   */
+  public native Address refToAddress(ObjectReference object);
+
+  /**
+   * Checks if a reference of the given type in another object is
+   * inherently acyclic.
+   *
+   * @return <code>true</code> if a reference of the type is
+   * inherently acyclic
+   */
+  @Inline
+  public native boolean isAcyclic(ObjectReference typeRef);
+
+  /**
+   * Dump debugging information for an object.
+   *
+   * @param object The object whose information is to be dumped
+   */
+  public native void dumpObject(ObjectReference object);
+}
+

Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/ReferenceProcessor.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/ReferenceProcessor.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/j3/mmtk/ReferenceProcessor.java (added)
+++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/ReferenceProcessor.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,103 @@
+//===--------------------- ReferenceProcessor.java ------------------------===//
+//
+//                            The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+package org.j3.mmtk;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.utility.options.Options;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+import org.j3.runtime.VM;
+
+ at Uninterruptible
+public final class ReferenceProcessor extends org.mmtk.vm.ReferenceProcessor {
+
+  /********************************************************************
+   * Class fields
+   */
+
+  private static final ReferenceProcessor softReferenceProcessor =
+    new ReferenceProcessor(Semantics.SOFT);
+  private static final ReferenceProcessor weakReferenceProcessor =
+    new ReferenceProcessor(Semantics.WEAK);
+  private static final ReferenceProcessor phantomReferenceProcessor =
+    new ReferenceProcessor(Semantics.PHANTOM);
+  
+  private final Semantics semantics;
+
+  private ReferenceProcessor(Semantics semantics) {
+    this.semantics = semantics;
+  }
+  
+  /** 
+   * Factory method.
+   * Creates an instance of the appropriate reference type processor.
+   * @return the reference processor
+   */
+  @Interruptible
+  public static ReferenceProcessor get(Semantics semantics) {
+    switch(semantics) {
+    case WEAK:    return weakReferenceProcessor;
+    case SOFT:    return softReferenceProcessor;
+    case PHANTOM: return phantomReferenceProcessor;
+    default:
+      VM._assert(false,"Unrecognized semantics");
+      return null;
+    }   
+  }
+
+  /**
+   * Scan through all references and forward.
+   *
+   * Collectors like MarkCompact determine liveness and move objects
+   * using separate traces.
+   *
+   * Currently ignores the nursery hint.
+   *
+   * TODO parallelise this code
+   *
+   * @param trace The trace
+   * @param nursery Is this a nursery collection ?
+   */
+  @Override
+  public native void forward(TraceLocal trace, boolean nursery);
+
+  /**
+   * Clear the contents of the table. This is called when reference types are
+   * disabled to make it easier for VMs to change this setting at runtime.
+   */
+  @Override
+  public native void clear();
+
+  /**
+   * Scan through the list of references. Calls ReferenceProcessor's
+   * processReference method for each reference and builds a new
+   * list of those references still active.
+   *
+   * Depending on the value of <code>nursery</code>, we will either
+   * scan all references, or just those created since the last scan.
+   *
+   * TODO parallelise this code
+   *
+   * @param nursery Scan only the newly created references
+   */
+  @Override
+  public native void scan(TraceLocal trace, boolean nursery);
+
+  /***********************************************************************
+   *
+   * Statistics and debugging
+   */
+
+  public native int countWaitingReferences();
+}

Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/Scanning.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/Scanning.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/j3/mmtk/Scanning.java (added)
+++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/Scanning.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,145 @@
+//===------------------------- Scanning.java ------------------------------===//
+//
+//                            The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+package org.j3.mmtk;
+
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.plan.TransitiveClosure;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+ at Uninterruptible
+public final class Scanning extends org.mmtk.vm.Scanning {
+  
+  @Inline
+  public native void scanObject(TransitiveClosure trace, ObjectReference object);
+
+  /**
+   * Invoke a specialized scan method. Note that these methods must have been allocated
+   * explicitly through Plan and PlanConstraints.
+   *
+   * @param id The specialized method id
+   * @param trace The trace the method has been specialized for
+   * @param object The object to be scanned
+   */
+  @Inline
+  public native void specializedScanObject(int id, TransitiveClosure trace, ObjectReference object);
+
+
+  /**
+   * Precopying of a object's fields, processing each pointer field encountered.
+   *
+   * @param trace The trace being used.
+   * @param object The object to be scanned.
+   */
+  @Inline
+  public native void precopyChildren(TraceLocal trace, ObjectReference object);
+
+  /**
+   * Prepares for using the <code>computeAllRoots</code> method.  The
+   * thread counter allows multiple GC threads to co-operatively
+   * iterate through the thread data structure (if load balancing
+   * parallel GC threads were not important, the thread counter could
+   * simply be replaced by a for loop).
+   */
+  public native void resetThreadCounter();
+
+  /**
+   * Pre-copy all potentially movable instances used in the course of
+   * GC.  This includes the thread objects representing the GC threads
+   * themselves.  It is crucial that these instances are forwarded
+   * <i>prior</i> to the GC proper.  Since these instances <i>are
+   * not</i> enqueued for scanning, it is important that when roots
+   * are computed the same instances are explicitly scanned and
+   * included in the set of roots.  The existence of this method
+   * allows the actions of calculating roots and forwarding GC
+   * instances to be decoupled.
+   *
+   * The thread table is scanned in parallel by each processor, by striding
+   * through the table at a gap of chunkSize*numProcs.  Feel free to adjust
+   * chunkSize if you want to tune a parallel collector.
+   *
+   * Explicitly no-inlined to prevent over-inlining of collectionPhase.
+   *
+   * TODO Experiment with specialization to remove virtual dispatch ?
+   */
+  @NoInline
+  public native void preCopyGCInstances(TraceLocal trace);
+
+  /**
+   * Computes static roots.  This method establishes all such roots for
+   * collection and places them in the root locations queue.  This method
+   * should not have side effects (such as copying or forwarding of
+   * objects).  There are a number of important preconditions:
+   *
+   * <ul>
+   * <li> All objects used in the course of GC (such as the GC thread
+   * objects) need to be "pre-copied" prior to calling this method.
+   * <li> The <code>threadCounter</code> must be reset so that load
+   * balancing parallel GC can share the work of scanning threads.
+   * </ul>
+   *
+   * @param trace The trace to use for computing roots.
+   */
+  public native void computeStaticRoots(TraceLocal trace);
+
+  /**
+   * Computes global roots.  This method establishes all such roots for
+   * collection and places them in the root locations queue.  This method
+   * should not have side effects (such as copying or forwarding of
+   * objects).  There are a number of important preconditions:
+   *
+   * <ul>
+   * <li> All objects used in the course of GC (such as the GC thread
+   * objects) need to be "pre-copied" prior to calling this method.
+   * <li> The <code>threadCounter</code> must be reset so that load
+   * balancing parallel GC can share the work of scanning threads.
+   * </ul>
+   *
+   * @param trace The trace to use for computing roots.
+   */
+  public native void computeGlobalRoots(TraceLocal trace);
+
+  /**
+   * Computes roots pointed to by threads, their associated registers
+   * and stacks.  This method places these roots in the root values,
+   * root locations and interior root locations queues.  This method
+   * should not have side effects (such as copying or forwarding of
+   * objects).  There are a number of important preconditions:
+   *
+   * <ul>
+   * <li> All objects used in the course of GC (such as the GC thread
+   * objects) need to be "pre-copied" prior to calling this method.
+   * <li> The <code>threadCounter</code> must be reset so that load
+   * balancing parallel GC can share the work of scanning threads.
+   * </ul>
+   *
+   * TODO rewrite to avoid the per-thread synchronization, like precopy.
+   *
+   * @param trace The trace to use for computing roots.
+   */
+  public native void computeThreadRoots(TraceLocal trace);
+
+  /**
+   * Compute all roots out of the VM's boot image (if any).  This method is a no-op
+   * in the case where the VM does not maintain an MMTk-visible Java space.   However,
+   * when the VM does maintain a space (such as a boot image) which is visible to MMTk,
+   * that space could either be scanned by MMTk as part of its transitive closure over
+   * the whole heap, or as a (considerable) performance optimization, MMTk could avoid
+   * scanning the space if it is aware of all pointers out of that space.  This method
+   * is used to establish the root set out of the scannable space in the case where
+   * such a space exists.
+   *
+   * @param trace The trace object to use to report root locations.
+   */
+  public void computeBootImageRoots(TraceLocal trace) {
+  }
+}
+

Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/Statistics.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/Statistics.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/j3/mmtk/Statistics.java (added)
+++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/Statistics.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,89 @@
+//===------------------------ Statistics.java -----------------------------===//
+//
+//                            The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+package org.j3.mmtk;
+
+import org.vmmagic.pragma.*;
+
+ at Uninterruptible
+public final class Statistics extends org.mmtk.vm.Statistics {
+  /**
+   * Returns the number of collections that have occurred.
+   *
+   * @return The number of collections that have occurred.
+   */
+  @Uninterruptible
+  public native int getCollectionCount();
+
+  /**
+   * Read nanoTime (high resolution, monotonically increasing clock).
+   * Has same semantics as java.lang.System.nanoTime().
+   */
+  public native long nanoTime();
+
+  /**
+   * Read a cycle counter (high resolution, non-monotonic clock).
+   * This method should be used with care as the cycle counters (especially on IA32 SMP machines)
+   * are not a reliably time source.
+   */
+  public native long cycles();
+
+  /**
+   * Convert nanoseconds to milliseconds
+   */
+  public double nanosToMillis(long c) {
+    return ((double)c)/1e6;
+  }
+
+  /**
+   * Convert nanoseconds to seconds
+   */
+  public double nanosToSecs(long c) {
+    return ((double)c)/1e9;
+  }
+
+  /**
+   * Convert milliseconds to nanoseconds
+   */
+  public long millisToNanos(double t) {
+    return (long)(t * 1e6);
+  }
+
+  /**
+   * Convert seconds to nanoseconds
+   */
+  public long secsToNanos(double t) {
+    return (long)(t * 1e9);
+  }
+
+  /**
+   * Initialize performance counters
+   *
+   * @param metric An integer identifying the metric being read
+   */
+  public native void perfCtrInit(int metric);
+
+  /**
+   * Read the current cycle count from the perfctr libraries
+   *
+   * @return the current cycle count from the perfctr libraries
+   */
+  public native long perfCtrReadCycles();
+
+  /**
+   * Read the current event count for the metric being measured by the
+   * perfctr libraries
+   *
+   * @return the current event count for the metric being measured by the
+   * perfctr libraries
+   */
+  public native long perfCtrReadMetric();
+
+}
+

Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/Strings.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/Strings.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/j3/mmtk/Strings.java (added)
+++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/Strings.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,49 @@
+//===------------------------- Strings.java -------------------------------===//
+//
+//                            The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+package org.j3.mmtk;
+
+import org.vmmagic.pragma.Uninterruptible;
+
+
+ at Uninterruptible
+public final class Strings extends org.mmtk.vm.Strings {
+  /**
+   * Log a message.
+   *
+   * @param c character array with message starting at index 0
+   * @param len number of characters in message
+   */
+  public native void write(char [] c, int len);
+
+  /**
+   * Log a thread identifier and a message.
+   *
+   * @param c character array with message starting at index 0
+   * @param len number of characters in message
+   */
+  public native void writeThreadId(char [] c, int len);
+
+  /**
+   * Copies characters from the string into the character array.
+   * Thread switching is disabled during this method's execution.
+   * <p>
+   * <b>TODO:</b> There are special memory management semantics here that
+   * someone should document.
+   *
+   * @param src the source string
+   * @param dst the destination array
+   * @param dstBegin the start offset in the desination array
+   * @param dstEnd the index after the last character in the
+   * destination to copy to
+   * @return the number of characters copied.
+   */
+  public native int copyStringToChars(String src, char [] dst,
+      int dstBegin, int dstEnd);
+}

Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/SynchronizedCounter.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/SynchronizedCounter.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/j3/mmtk/SynchronizedCounter.java (added)
+++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/SynchronizedCounter.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,27 @@
+//===---------- SynchronizedCounter.java - Atomic counter -----------------===//
+//
+//                            The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+package org.j3.mmtk;
+
+/**
+ * A counter that supports atomic increment and reset.
+ */
+public final class SynchronizedCounter extends org.mmtk.vm.SynchronizedCounter {
+
+  private int count = 0;
+
+  public native int reset();
+  
+  public native int increment();
+
+  public int peek() {
+    return count;
+  }
+
+}

Added: vmkit/trunk/mmtk/java/src/org/j3/mmtk/TraceInterface.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/mmtk/TraceInterface.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/j3/mmtk/TraceInterface.java (added)
+++ vmkit/trunk/mmtk/java/src/org/j3/mmtk/TraceInterface.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,80 @@
+//===----------------------- TraceInterface.java --------------------------===//
+//
+//                            The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+
+package org.j3.mmtk;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * Class that supports scanning Objects or Arrays for references
+ * during tracing, handling those references, and computing death times
+ */
+ at Uninterruptible
+public class TraceInterface extends org.mmtk.vm.TraceInterface {
+
+
+  /***********************************************************************
+   *
+   * Public Methods
+   */
+
+  /**
+   * Returns if the VM is ready for a garbage collection.
+   *
+   * @return True if the VM is ready for GC, false otherwise.
+   */
+  public native boolean gcEnabled();
+
+  /**
+   * This adjusts the offset into an object to reflect what it would look like
+   * if the fields were laid out in memory space immediately after the object
+   * pointer.
+   *
+   * @param isScalar If this is a pointer store to a scalar object
+   * @param src The address of the source object
+   * @param slot The address within <code>src</code> into which
+   * the update will be stored
+   * @return The easy to understand offset of the slot
+   */
+  public native Offset adjustSlotOffset(boolean isScalar,
+                                        ObjectReference src,
+                                        Address slot);
+
+  /**
+   * This skips over the frames added by the tracing algorithm, outputs
+   * information identifying the method the containts the "new" call triggering
+   * the allocation, and returns the address of the first non-trace, non-alloc
+   * stack frame.
+   *
+   *@param typeRef The type reference (tib) of the object just allocated
+   * @return The frame pointer address for the method that allocated the object
+   */
+  @Interruptible
+  public native Address skipOwnFramesAndDump(ObjectReference typeRef);
+
+  /***********************************************************************
+   *
+   * Wrapper methods
+   */
+  public native void updateDeathTime(ObjectReference obj);
+  public native void setDeathTime(ObjectReference ref, Word time_);
+  public native void setLink(ObjectReference ref, ObjectReference link);
+  public native void updateTime(Word time_);
+  public native Word getOID(ObjectReference ref);
+  public native Word getDeathTime(ObjectReference ref);
+  public native ObjectReference getLink(ObjectReference ref);
+  public native Address getBootImageLink();
+  public native Word getOID();
+  public native void setOID(Word oid);
+  public native int getHeaderSize();
+  public native int getHeaderEndOffset();
+}

Added: vmkit/trunk/mmtk/java/src/org/j3/options/OptionSet.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/options/OptionSet.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/j3/options/OptionSet.java (added)
+++ vmkit/trunk/mmtk/java/src/org/j3/options/OptionSet.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,161 @@
+//===------------------------- OptionSet.java -----------------------------===//
+//
+//                            The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+package org.j3.options;
+
+
+import org.mmtk.utility.Constants;
+import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.unboxed.Extent;
+import org.vmmagic.unboxed.Word;
+import org.vmutil.options.AddressOption;
+import org.vmutil.options.BooleanOption;
+import org.vmutil.options.EnumOption;
+import org.vmutil.options.FloatOption;
+import org.vmutil.options.IntOption;
+import org.vmutil.options.MicrosecondsOption;
+import org.vmutil.options.Option;
+import org.vmutil.options.PagesOption;
+import org.vmutil.options.StringOption;
+
+import org.jikesrvm.SizeConstants;
+import org.j3.runtime.VM;
+
+/**
+ * Class to handle command-line arguments and options for GC.
+ */
+public final class OptionSet extends org.vmutil.options.OptionSet {
+
+  private String prefix;
+
+  public static final OptionSet gc = new OptionSet("-X:gc");
+
+  private OptionSet(String prefix) {
+    this.prefix = prefix;
+  }
+
+  /**
+   * Format and log an option value.
+   *
+   * @param o The option.
+   * @param forXml Is this part of xml output?
+   */
+  protected void logValue(Option o, boolean forXml) {
+    switch (o.getType()) {
+    case Option.BOOLEAN_OPTION:
+      VM.sysWrite(((BooleanOption) o).getValue() ? "true" : "false");
+      break;
+    case Option.INT_OPTION:
+      VM.sysWrite(((IntOption) o).getValue());
+      break;
+    case Option.ADDRESS_OPTION:
+      VM.sysWrite(((AddressOption) o).getValue());
+      break;
+    case Option.FLOAT_OPTION:
+      VM.sysWrite(((FloatOption) o).getValue());
+      break;
+    case Option.MICROSECONDS_OPTION:
+      VM.sysWrite(((MicrosecondsOption) o).getMicroseconds());
+      VM.sysWrite(" usec");
+      break;
+    case Option.PAGES_OPTION:
+      VM.sysWrite(((PagesOption) o).getBytes());
+      VM.sysWrite(" bytes");
+      break;
+    case Option.STRING_OPTION:
+      VM.sysWrite(((StringOption) o).getValue());
+      break;
+    case Option.ENUM_OPTION:
+      VM.sysWrite(((EnumOption) o).getValueString());
+      break;
+    }
+  }
+
+  /**
+   * Log a string.
+   */
+  protected void logString(String s) {
+    VM.sysWrite(s);
+  }
+
+  /**
+   * Print a new line.
+   */
+  protected void logNewLine() {
+    VM.sysWriteln();
+  }
+
+  /**
+   * Determine the VM specific key for a given option name. Option names are
+   * space delimited with capitalised words (e.g. "GC Verbosity Level").
+   *
+   * @param name The option name.
+   * @return The VM specific key.
+   */
+  protected String computeKey(String name) {
+    int space = name.indexOf(' ');
+    if (space < 0) return name.toLowerCase();
+
+    String word = name.substring(0, space);
+    String key = word.toLowerCase();
+
+    do {
+      int old = space+1;
+      space = name.indexOf(' ', old);
+      if (space < 0) {
+        key += name.substring(old);
+        return key;
+      }
+      key += name.substring(old, space);
+    } while (true);
+  }
+
+  /**
+   * A non-fatal error occurred during the setting of an option. This method
+   * calls into the VM and shall not cause the system to stop.
+   *
+   * @param o The responsible option.
+   * @param message The message associated with the warning.
+   */
+  protected void warn(Option o, String message) {
+    VM.sysWriteln("WARNING: Option '" + o.getKey() + "' : " + message);
+  }
+
+  /**
+   * A fatal error occurred during the setting of an option. This method
+   * calls into the VM and is required to cause the system to stop.
+   *
+   * @param o The responsible option.
+   * @param message The error message associated with the failure.
+   */
+  protected void fail(Option o, String message) {
+    VM.sysFail("ERROR: Option '" + o.getKey() + "' : " + message);
+  }
+
+  /**
+   * Convert bytes into pages, rounding up if necessary.
+   *
+   * @param bytes The number of bytes.
+   * @return The corresponding number of pages.
+   */
+  @Uninterruptible
+  protected int bytesToPages(Extent bytes) {
+    return bytes.plus(Constants.BYTES_IN_PAGE-1).toWord().rshl(Constants.LOG_BYTES_IN_PAGE).toInt();
+  }
+
+  /**
+   * Convert from pages into bytes.
+   * @param pages the number of pages.
+   * @return The corresponding number of bytes.
+   */
+  @Uninterruptible
+  protected Extent pagesToBytes(int pages) {
+    return Word.fromIntZeroExtend(pages).lsh(Constants.LOG_BYTES_IN_PAGE).toExtent();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/j3/runtime/VM.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/j3/runtime/VM.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/j3/runtime/VM.java (added)
+++ vmkit/trunk/mmtk/java/src/org/j3/runtime/VM.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,41 @@
+//===---------------------------- VM.java ---------------------------------===//
+//
+//                            The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+package org.j3.runtime;
+
+import org.vmmagic.unboxed.Address;
+import org.vmmagic.unboxed.Extent;
+
+public final class VM {
+
+  private native static boolean verifyAssertions();
+  private native static boolean buildForIA32();
+  private native static boolean buildFor64Addr();
+
+  public final static boolean NOT_REACHED = false;
+
+  public final static boolean VerifyAssertions = verifyAssertions();
+  public final static boolean runningVM = false;
+  public final static boolean BuildForIA32 = buildForIA32();
+  public final static boolean BuildFor64Addr = buildFor64Addr();
+
+
+  public native static void sysFail(String a);
+  public native static void sysExit(int a);
+  public native static void _assert(boolean cond);
+  public native static void _assert(boolean cond, String msg);
+  public native static void sysWriteln(String a);
+  public native static void sysWriteln();
+  public native static void sysWrite(String a);
+  public native static void sysWrite(int a);
+  public native static void sysWrite(float a);
+  public native static void sysWrite(Address a);
+  public native static void sysWrite(Extent a);
+}

Added: vmkit/trunk/mmtk/java/src/org/jikesrvm/Magic.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/jikesrvm/Magic.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/jikesrvm/Magic.java (added)
+++ vmkit/trunk/mmtk/java/src/org/jikesrvm/Magic.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,352 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.jikesrvm;
+
+import org.vmmagic.Intrinsic;
+import org.vmmagic.pragma.Entrypoint;
+import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.unboxed.Address;
+import org.vmmagic.unboxed.Offset;
+import org.vmmagic.unboxed.Word;
+import org.vmmagic.unboxed.WordArray;
+
+import org.j3.runtime.VM;
+
+/**
+ * Magic methods for accessing raw machine memory, registers, and
+ * operating system calls.
+ *
+ * <p> These are "inline assembler functions" that cannot be implemented in
+ * Java code. Their names are recognized by RVM's compilers
+ * and cause inline machine code to be generated instead of
+ * actual method calls.
+ */
+ at SuppressWarnings({"UnusedDeclaration"})
+ at Intrinsic
+public final class Magic {
+
+  /**
+   * Read contents of hardware time base registers.
+   * Note:     we think that 1 "tick" == 4 "machine cycles", but this seems to be
+   *           undocumented and may vary across processor implementations.
+   * @return number of ticks (epoch undefined)
+   */
+  public static long getTimeBase() {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+    return -1;
+  }
+
+  //---------------------------------------//
+  //           Memory Access.              //
+  //---------------------------------------//
+
+  /**
+   * Get unsigned byte at arbitrary (byte) offset from object. The
+   * most significant 24bits of the result will be 0.
+   */
+  public static byte getUnsignedByteAtOffset(Object object, Offset offset) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+    return -1;
+  }
+
+  /**
+   * Get byte at arbitrary (byte) offset from object. The most
+   * significant 24bits of the result will be the same as the most
+   * significant bit in the byte.
+   */
+  public static byte getByteAtOffset(Object object, Offset offset) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+    return -1;
+  }
+
+  /**
+   * Get short at arbitrary (byte) offset from object. The most
+   * significant 16bits will be the same as the most significant bit
+   * in the short.
+   */
+  public static short getShortAtOffset(Object object, Offset offset) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+    return (short) -1;
+  }
+
+  /**
+   * Get char at arbitrary (byte) offset from object. The most
+   * significant 16bits will be 0.
+   */
+  public static char getCharAtOffset(Object object, Offset offset) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+    return (char) -1;
+  }
+
+  /**
+   * Get int at arbitrary (byte) offset from object.
+   * Use getIntAtOffset(obj, ofs) instead of getMemoryInt(objectAsAddress(obj)+ofs)
+   */
+  public static int getIntAtOffset(Object object, Offset offset) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+    return -1;
+  }
+
+  /**
+   * Get Word at arbitrary (byte) offset from object.
+   * Use getWordAtOffset(obj, ofs) instead of getMemoryWord(objectAsAddress(obj)+ofs)
+   */
+  public static Word getWordAtOffset(Object object, Offset offset) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+    return Word.max();
+  }
+
+  /**
+   * Get Object at arbitrary (byte) offset from object.
+   * Use getObjectAtOffset(obj, ofs) instead of
+   * addressAsObject(getMemoryAddress(objectAsAddress(obj)+ofs))
+   */
+  public static Object getObjectAtOffset(Object object, Offset offset) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+    return null;
+  }
+
+  /**
+   * Get Object at arbitrary (byte) offset from object.
+   * Use getObjectAtOffset(obj, ofs) instead of
+   * addressAsObject(getMemoryAddress(objectAsAddress(obj)+ofs))
+   */
+  public static Object getObjectAtOffset(Object object, Offset offset, int locationMetadata) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+    return null;
+  }
+
+  /**
+   * Get Word at arbitrary (byte) offset from object.
+   */
+  public static Word getWordAtOffset(Object object, Offset offset, int locationMetadata) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+    return null;
+  }
+
+  /**
+   * Get long at arbitrary (byte) offset from object.
+   * Use getlongAtOffset(obj, ofs) instead of two getIntAtOffset
+   */
+  public static long getLongAtOffset(Object object, Offset offset) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+    return -1;
+  }
+
+  /**
+   * Get double at arbitrary (byte) offset from object.
+   * Use getDoubleAtOffset(obj, ofs) instead of two getIntAtOffset
+   */
+  public static double getDoubleAtOffset(Object object, Offset offset) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+    return -1;
+  }
+
+  /**
+   * Set byte at arbitrary (byte) offset from object.
+   */
+  public static void setByteAtOffset(Object object, Offset offset, byte newvalue) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+  }
+
+  /**
+   * Set char at arbitrary (byte) offset from object.
+   */
+  public static void setCharAtOffset(Object object, Offset offset, char newvalue) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+  }
+
+  /**
+   * Set int at arbitrary (byte) offset from object.
+   * Use setIntAtOffset(obj, ofs, new) instead of setMemoryWord(objectAsAddress(obj)+ofs, new)
+   */
+  public static void setIntAtOffset(Object object, Offset offset, int newvalue) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+  }
+
+  /**
+   * Set word at arbitrary (byte) offset from object.
+   * Use setWordAtOffset(obj, ofs, new) instead of setMemoryWord(objectAsAddress(obj)+ofs, new)
+   */
+  public static void setWordAtOffset(Object object, Offset offset, Word newvalue) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+  }
+
+  /**
+   * Set word at arbitrary (byte) offset from object.
+   * Use setWordAtOffset(obj, ofs, new) instead of setMemoryWord(objectAsAddress(obj)+ofs, new)
+   */
+  public static void setWordAtOffset(Object object, Offset offset, Word newvalue, int locationMetadata) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+  }
+
+  /**
+   * Set Object at arbitrary (byte) offset from object.
+   * Use setObjectAtOffset(obj, ofs, new) instead of setMemoryWord(objectAsAddress(obj)+ofs, objectAsAddress(new))
+   */
+  public static void setObjectAtOffset(Object object, Offset offset, Object newvalue) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+  }
+
+  /**
+   * Set Object at arbitrary (byte) offset from object.
+   */
+  public static void setObjectAtOffset(Object object, Offset offset, Object newvalue, int locationMetadata) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+  }
+
+  /**
+   * Set long at arbitrary (byte) offset from object.
+   * Use setlongAtOffset(obj, ofs) instead of two setIntAtOffset
+   */
+  public static void setLongAtOffset(Object object, Offset offset, long newvalue) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+  }
+
+  /**
+   * Set double at arbitrary (byte) offset from object.
+   * Use setDoubleAtOffset(obj, ofs) instead of two setIntAtOffset
+   */
+  public static void setDoubleAtOffset(Object object, Offset offset, double newvalue) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+  }
+
+  //---------------------------------------//
+  //    Atomic Memory Access Primitives.   //
+  //---------------------------------------//
+
+  /**
+   * Get contents of (object + offset) and begin conditional critical section.
+   */
+  public static int prepareInt(Object object, Offset offset) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+    return -1;
+  }
+
+  /**
+   * Get contents of (object + offset) and begin conditional critical section.
+   */
+  public static Object prepareObject(Object object, Offset offset) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+    return null;
+  }
+
+  /**
+   * Get contents of (object + offset) and begin conditional critical section.
+   */
+  public static Address prepareAddress(Object object, Offset offset) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+    return Address.max();
+  }
+
+  /**
+   * Get contents of (object + offset) and begin conditional critical section.
+   */
+  public static Word prepareWord(Object object, Offset offset) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+    return Word.max();
+  }
+
+  /**
+   * Get contents of (object + offset) and begin conditional critical section.
+   */
+  @Uninterruptible
+  public static long prepareLong(Object object, Offset offset) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+    return -1;
+  }
+
+  /**
+   * Sets the memory at (object + offset) to newValue if its contents are oldValue.
+   * Must be paired with a preceding prepare (which returned the oldValue)
+   * Returns true if successful.
+   * Ends conditional critical section.
+   */
+  public static boolean attemptInt(Object object, Offset offset, int oldValue, int newValue) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+    return false;
+  }
+
+  /**
+   * Sets the memory at (object + offset) to newValue if its contents are oldValue.
+   * Must be paired with a preceding prepare (which returned the oldValue)
+   * Returns true if successful.
+   * Ends conditional critical section.
+   */
+  public static boolean attemptObject(Object object, Offset offset, Object oldValue, Object newValue) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+    return false;
+  }
+
+  /**
+   * Sets the memory at (object + offset) to newValue if its contents are oldValue.
+   * Must be paired with a preceding prepare (which returned the oldValue)
+   * Returns true if successful.
+   * Ends conditional critical section.
+   */
+  public static boolean attemptAddress(Object object, Offset offset, Address oldValue, Address newValue) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+    return false;
+  }
+
+  /**
+   * Sets the memory at (object + offset) to newValue if its contents are oldValue.
+   * Must be paired with a preceding prepare (which returned the oldValue)
+   * Returns true if successful.
+   * Ends conditional critical section.
+   */
+  public static boolean attemptWord(Object object, Offset offset, Word oldValue, Word newValue) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+    return false;
+  }
+
+  /**
+   * Sets the memory at (object + offset) to newValue if its contents are oldValue.
+   * Must be paired with a preceding prepare (which returned the oldValue)
+   * Returns true if successful.
+   * Ends conditional critical section.
+   */
+  public static boolean attemptLong(Object object, Offset offset, long oldValue,
+      long newValue) {
+    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+    return false;
+  }
+
+  //---------------------------------------//
+  //            Cache Management.          //
+  //---------------------------------------//
+
+  /**** NOTE: all per-address operations now live in vmmagic.Address *****/
+
+  /**
+   * Wait for preceeding cache flush/invalidate instructions to
+   * complete on all processors.
+   */
+  public static void sync() {
+    if (VM.runningVM && VM.VerifyAssertions) {
+      VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+    }
+  }
+
+  /**
+   * Wait for all preceeding instructions to complete and discard any
+   * prefetched instructions on this processor.
+   */
+  public static void isync() {
+    if (VM.runningVM && VM.VerifyAssertions) {
+      VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+    }
+  }
+
+}
+

Added: vmkit/trunk/mmtk/java/src/org/jikesrvm/SizeConstants.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/jikesrvm/SizeConstants.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/jikesrvm/SizeConstants.java (added)
+++ vmkit/trunk/mmtk/java/src/org/jikesrvm/SizeConstants.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,76 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.jikesrvm;
+
+import org.j3.runtime.VM;
+
+/**
+ * Constants defining the basic sizes of primitive quantities
+ */
+public interface SizeConstants {
+
+  int LOG_BYTES_IN_BYTE = 0;
+  int BYTES_IN_BYTE = 1;
+  int LOG_BITS_IN_BYTE = 3;
+  int BITS_IN_BYTE = 1 << LOG_BITS_IN_BYTE;
+
+  int LOG_BYTES_IN_BOOLEAN = 0;
+  int BYTES_IN_BOOLEAN = 1 << LOG_BYTES_IN_BOOLEAN;
+  int LOG_BITS_IN_BOOLEAN = LOG_BITS_IN_BYTE + LOG_BYTES_IN_BOOLEAN;
+  int BITS_IN_BOOLEAN = 1 << LOG_BITS_IN_BOOLEAN;
+
+  int LOG_BYTES_IN_CHAR = 1;
+  int BYTES_IN_CHAR = 1 << LOG_BYTES_IN_CHAR;
+  int LOG_BITS_IN_CHAR = LOG_BITS_IN_BYTE + LOG_BYTES_IN_CHAR;
+  int BITS_IN_CHAR = 1 << LOG_BITS_IN_CHAR;
+
+  int LOG_BYTES_IN_SHORT = 1;
+  int BYTES_IN_SHORT = 1 << LOG_BYTES_IN_SHORT;
+  int LOG_BITS_IN_SHORT = LOG_BITS_IN_BYTE + LOG_BYTES_IN_SHORT;
+  int BITS_IN_SHORT = 1 << LOG_BITS_IN_SHORT;
+
+  int LOG_BYTES_IN_INT = 2;
+  int BYTES_IN_INT = 1 << LOG_BYTES_IN_INT;
+  int LOG_BITS_IN_INT = LOG_BITS_IN_BYTE + LOG_BYTES_IN_INT;
+  int BITS_IN_INT = 1 << LOG_BITS_IN_INT;
+
+  int LOG_BYTES_IN_FLOAT = 2;
+  int BYTES_IN_FLOAT = 1 << LOG_BYTES_IN_FLOAT;
+  int LOG_BITS_IN_FLOAT = LOG_BITS_IN_BYTE + LOG_BYTES_IN_FLOAT;
+  int BITS_IN_FLOAT = 1 << LOG_BITS_IN_FLOAT;
+
+  int LOG_BYTES_IN_LONG = 3;
+  int BYTES_IN_LONG = 1 << LOG_BYTES_IN_LONG;
+  int LOG_BITS_IN_LONG = LOG_BITS_IN_BYTE + LOG_BYTES_IN_LONG;
+  int BITS_IN_LONG = 1 << LOG_BITS_IN_LONG;
+
+  int LOG_BYTES_IN_DOUBLE = 3;
+  int BYTES_IN_DOUBLE = 1 << LOG_BYTES_IN_DOUBLE;
+  int LOG_BITS_IN_DOUBLE = LOG_BITS_IN_BYTE + LOG_BYTES_IN_DOUBLE;
+  int BITS_IN_DOUBLE = 1 << LOG_BITS_IN_DOUBLE;
+
+  int LOG_BYTES_IN_ADDRESS = VM.BuildFor64Addr ? 3 : 2;
+  int BYTES_IN_ADDRESS = 1 << LOG_BYTES_IN_ADDRESS;
+  int LOG_BITS_IN_ADDRESS = LOG_BITS_IN_BYTE + LOG_BYTES_IN_ADDRESS;
+  int BITS_IN_ADDRESS = 1 << LOG_BITS_IN_ADDRESS;
+
+  int LOG_BYTES_IN_WORD = VM.BuildFor64Addr ? 3 : 2;
+  int BYTES_IN_WORD = 1 << LOG_BYTES_IN_WORD;
+  int LOG_BITS_IN_WORD = LOG_BITS_IN_BYTE + LOG_BYTES_IN_WORD;
+  int BITS_IN_WORD = 1 << LOG_BITS_IN_WORD;
+
+  int LOG_BYTES_IN_PAGE = 12;
+  int BYTES_IN_PAGE = 1 << LOG_BYTES_IN_PAGE;
+  int LOG_BITS_IN_PAGE = LOG_BITS_IN_BYTE + LOG_BYTES_IN_PAGE;
+  int BITS_IN_PAGE = 1 << LOG_BITS_IN_PAGE;
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/CollectorContext.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/CollectorContext.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/CollectorContext.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/CollectorContext.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,205 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan;
+
+import org.mmtk.policy.ImmortalLocal;
+import org.mmtk.utility.sanitychecker.SanityCheckerLocal;
+import org.mmtk.utility.alloc.Allocator;
+import org.mmtk.utility.alloc.BumpPointer;
+import org.mmtk.utility.Constants;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class (and its sub-classes) implement <i>per-collector thread</i>
+ * behavior.  We assume <i>N</i> collector threads and <i>M</i>
+ * mutator threads, where <i>N</i> is often equal to the number of
+ * available processors, P (for P-way parallelism at GC-time), and
+ * <i>M</i> may simply be the number of mutator (application) threads.
+ * Both <i>N</i> and <i>M</i> are determined by the VM, not MMTk.  In
+ * the case where a VM uses posix threads (pthreads) for each mutator
+ * ("1:1" threading), <i>M</i> will typically be equal to the number of
+ * mutator threads.  When a uses "green threads" or a hybrid threading
+ * scheme (such as Jikes RVM), <i>M</i> will typically be equal to the
+ * level of <i>true</i> parallelism (ie the number of underlying
+ * kernel threads).</p>
+ *
+ * <p>Collector operations are separated into <i>per-collector thread</i>
+ * operations (the bulk of the GC), and <i>per-mutator thread</i> operations
+ * (important in flushing and restoring per-mutator state such as allocator
+ * state and write buffer/remset state).  {@link SimplePhase}
+ * ensures that per-collector thread GC phases are performed by each
+ * collector thread, and that the <i>M</i> per-mutator thread operations
+ * are multiplexed across the <i>N</i> active collector threads.</p>
+ *
+ * <p>MMTk assumes that the VM instantiates instances of {@link CollectorContext}
+ * in thread local storage (TLS) for each thread participating in
+ * collection.  Accesses to this state are therefore assumed to be
+ * low-cost at GC time.<p>
+ *
+ * <p>MMTk explicitly separates thread-local (this class) and global
+ * operations (See {@link Plan}), so that syncrhonization is localized
+ * and explicit, and thus hopefully minimized (See {@link Plan}). Global (Plan)
+ * and per-thread (this class) state are also explicitly separated.
+ * Operations in this class (and its children) are therefore strictly
+ * local to each collector thread, and synchronized operations always
+ * happen via access to explicitly global classes such as Plan and its
+ * children.</p>
+ *
+ * <p>This class (and its children) therefore typically implement per-collector
+ * thread structures such as collection work queues.</p>
+ *
+ * @see MutatorContext
+ * @see org.mmtk.vm.ActivePlan
+ * @see Plan
+ */
+ at Uninterruptible public abstract class CollectorContext implements Constants {
+
+  /****************************************************************************
+   * Instance fields
+   */
+  /** Unique collector identifier */
+  private int id;
+
+  /** Per-collector allocator into the immortal space */
+  protected final BumpPointer immortal = new ImmortalLocal(Plan.immortalSpace);
+
+  /** Used for aborting concurrent phases pre-empted by stop the world collection */
+  protected boolean resetConcurrentWork;
+
+  /** Used for sanity checking */
+  protected final SanityCheckerLocal sanityLocal = new SanityCheckerLocal();
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+  protected CollectorContext() {
+  }
+
+  /**
+   * Notify that the collector context is registered and ready to execute.
+   *
+   * @param id The id of this collector context.
+   */
+  public void initCollector(int id) {
+    this.id = id;
+  }
+
+  /****************************************************************************
+   * Collection-time allocation.
+   */
+
+  /**
+   * Allocate memory when copying an object.
+   *
+   * @param original The object that is being copied.
+   * @param bytes The number of bytes required for the copy.
+   * @param align Required alignment for the copy.
+   * @param offset Offset associated with the alignment.
+   * @param allocator The allocator associated with this request.
+   * @return The address of the newly allocated region.
+   */
+  public Address allocCopy(ObjectReference original, int bytes,
+      int align, int offset, int allocator) {
+    VM.assertions.fail("Collector has not implemented allocCopy");
+    return Address.max();
+  }
+
+  /**
+   * Perform any post-copy actions.
+   *
+   * @param ref The newly allocated object.
+   * @param typeRef the type reference for the instance being created.
+   * @param bytes The size of the space to be allocated (in bytes).
+   * @param allocator The allocator statically assigned to this allocation.
+   */
+  public void postCopy(ObjectReference ref, ObjectReference typeRef,
+      int bytes, int allocator) {
+    VM.assertions.fail("Collector has not implemented postCopy");
+  }
+
+  /**
+   * Run-time check of the allocator to use for a given copy allocation
+   *
+   * At the moment this method assumes that allocators will use the simple
+   * (worst) method of aligning to determine if the object is a large object
+   * to ensure that no objects are larger than other allocators can handle.
+   *
+   * @param from The object that is being copied.
+   * @param bytes The number of bytes to be allocated.
+   * @param align The requested alignment.
+   * @param allocator The allocator statically assigned to this allocation.
+   * @return The allocator dyncamically assigned to this allocation.
+   */
+  @Inline
+  public int copyCheckAllocator(ObjectReference from, int bytes,
+      int align, int allocator) {
+      boolean large = Allocator.getMaximumAlignedSize(bytes, align) > Plan.MAX_NON_LOS_COPY_BYTES;
+      return large ? Plan.ALLOC_LOS : allocator;
+  }
+
+  /****************************************************************************
+   * Collection.
+   */
+
+  /** Perform a garbage collection */
+  public abstract void collect();
+
+  /** Perform some concurrent garbage collection */
+  public abstract void concurrentCollect();
+
+  /**
+   * Perform a (local) collection phase.
+   *
+   * @param phaseId The unique phase identifier
+   * @param primary Should this thread be used to execute any single-threaded
+   * local operations?
+   */
+  public abstract void collectionPhase(short phaseId, boolean primary);
+
+  /**
+   * Perform some concurrent collection work.
+   *
+   * @param phaseId The unique phase identifier
+   */
+  public abstract void concurrentCollectionPhase(short phaseId);
+
+  /** @return The current trace instance. */
+  public abstract TraceLocal getCurrentTrace();
+
+  /**
+   * Abort concurrent work due to pre-empt by stop the world collection.
+   */
+  protected void resetConcurrentWork() {
+    resetConcurrentWork = true;
+  }
+
+  /**
+   * Allow concurrent work to continue.
+   */
+  protected void clearResetConcurrentWork() {
+    resetConcurrentWork = false;
+  }
+
+  /****************************************************************************
+   * Miscellaneous.
+   */
+
+  /** @return the unique identifier for this collector context. */
+  @Inline
+  public int getId() { return id; }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/ComplexPhase.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/ComplexPhase.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/ComplexPhase.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/ComplexPhase.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,134 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan;
+
+import org.mmtk.utility.Constants;
+import org.mmtk.utility.statistics.Timer;
+import org.mmtk.utility.Log;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * Phases of a garbage collection.
+ *
+ * A complex phase is a sequence of phases.
+ *
+ */
+ at Uninterruptible
+public final class ComplexPhase extends Phase
+  implements Constants {
+
+  /****************************************************************************
+   * Instance fields
+   */
+
+  /**
+   * The phases that comprise this phase.
+   */
+  private final int[] scheduledSubPhases;
+
+  /**
+   * Construct a complex phase from an array of phase IDs.
+   *
+   * @param name The name of the phase.
+   * @param scheduledSubPhases The sub phases
+   */
+  protected ComplexPhase(String name, int[] scheduledSubPhases) {
+    super(name);
+    this.scheduledSubPhases = scheduledSubPhases;
+    checkPhases();
+  }
+
+  /**
+   * Construct a complex phase from an array of phase IDs, but using
+   * the specified timer rather than creating one.
+   *
+   * @param name The name of the phase.
+   * @param timer The timer for this phase to contribute to.
+   * @param scheduledSubPhases The sub phases
+   */
+  protected ComplexPhase(String name, Timer timer, int[] scheduledSubPhases) {
+    super(name, timer);
+    this.scheduledSubPhases = scheduledSubPhases;
+    checkPhases();
+  }
+
+  /**
+   * Validate the scheduled sub phases.
+   */
+  private void checkPhases() {
+    if (VM.VERIFY_ASSERTIONS) {
+      VM.assertions._assert(scheduledSubPhases.length > 0);
+      for(int scheduledPhase: scheduledSubPhases) {
+        VM.assertions._assert(getSchedule(scheduledPhase) > 0);
+        VM.assertions._assert(getPhaseId(scheduledPhase) > 0);
+      }
+    }
+  }
+
+  /**
+   * The number of scheduled sub phases.
+   */
+  protected int count() {
+    return scheduledSubPhases.length;
+  }
+
+  /**
+   * Return an individual scheduled sub phase.
+   *
+   * @param index The index
+   * @return The scheduled phase.
+   */
+  protected int get(int index) {
+    return scheduledSubPhases[index];
+  }
+
+  /**
+   * Display a description of this phase, for debugging purposes.
+   */
+  protected void logPhase() {
+    Log.write("ComplexPhase(");
+    Log.write(name);
+    Log.write(", < ");
+    for (int subPhase : scheduledSubPhases) {
+      short ordering = getSchedule(subPhase);
+      short phaseId = getPhaseId(subPhase);
+      Log.write(getScheduleName(ordering));
+      Log.write("(");
+      Log.write(getName(phaseId));
+      Log.write(") ");
+    }
+    Log.write(">)");
+  }
+
+  /**
+   * Replace a scheduled phase. Used for example to replace a placeholder.
+   *
+   * @param oldScheduledPhase The scheduled phase to replace.
+   * @param newScheduledPhase The new scheduled phase.
+   */
+  public void replacePhase(int oldScheduledPhase, int newScheduledPhase) {
+    for (int i = 0; i < scheduledSubPhases.length; i++) {
+      int scheduledPhase = scheduledSubPhases[i];
+      if (scheduledPhase == oldScheduledPhase) {
+        /* Replace */
+        scheduledSubPhases[i] = newScheduledPhase;
+      } else if (getSchedule(scheduledPhase) == SCHEDULE_COMPLEX) {
+        /* Recurse */
+        ComplexPhase p = (ComplexPhase)getPhase(getPhaseId(scheduledPhase));
+        p.replacePhase(oldScheduledPhase, newScheduledPhase);
+      }
+    }
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/GCspyPlan.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/GCspyPlan.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/GCspyPlan.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/GCspyPlan.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,32 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan;
+
+import org.mmtk.policy.ImmortalSpace;
+import org.mmtk.utility.heap.VMRequest;
+
+/**
+ * This interface provides an immortal allocation space for GCspy objects.
+ */
+public interface GCspyPlan {
+
+  /**
+   * Any GCspy objects allocated after booting are allocated
+   * in a separate immortal space.
+   */
+  ImmortalSpace gcspySpace =
+      new ImmortalSpace("gcspy", Plan.DEFAULT_POLL_FREQUENCY, VMRequest.create());
+
+  /** The descriptor for the GCspy allocation space */
+  int GCSPY = gcspySpace.getDescriptor();
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/MutatorContext.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/MutatorContext.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/MutatorContext.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/MutatorContext.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,423 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan;
+
+import org.mmtk.policy.MarkSweepLocal;
+import org.mmtk.policy.Space;
+import org.mmtk.policy.ImmortalLocal;
+import org.mmtk.policy.LargeObjectLocal;
+import org.mmtk.utility.alloc.Allocator;
+import org.mmtk.utility.alloc.BumpPointer;
+import org.mmtk.utility.Constants;
+import org.mmtk.utility.Log;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class (and its sub-classes) implement <i>per-mutator thread</i>
+ * behavior.  We assume <i>N</i> collector threads and <i>M</i>
+ * mutator threads, where <i>N</i> is often equal to the number of
+ * available processors, P (for P-way parallelism at GC-time), and
+ * <i>M</i> may simply be the number of mutator (application) threads.
+ * Both <i>N</i> and <i>M</i> are determined by the VM, not MMTk.  In
+ * the case where a VM uses posix threads (pthreads) for each mutator
+ * ("1:1" threading), <i>M</i> will typically be equal to the number of
+ * mutator threads.  When a uses "green threads" or a hybrid threading
+ * scheme (such as Jikes RVM), <i>M</i> will typically be equal to the
+ * level of <i>true</i> parallelism (ie the number of underlying
+ * kernel threads).<p>
+ *
+ * MMTk assumes that the VM instantiates instances of MutatorContext
+ * in thread local storage (TLS) for each thread participating in
+ * collection.  Accesses to this state are therefore assumed to be
+ * low-cost during mutator time.<p>
+ *
+ * This class (and its children) is therefore used for unsynchronized
+ * per-mutator operations such as <i>allocation</i> and <i>write barriers</i>.
+ * The semantics and necessary state for these operations are therefore
+ * specified in the GC-specific subclasses of this class.
+ *
+ * MMTk explicitly separates thread-local (this class) and global
+ * operations (@see Plan), so that syncrhonization is localized
+ * and explicit, and thus hopefully minimized (@see Plan). Gloabl (Plan)
+ * and per-thread (this class) state are also explicitly separated.
+ * Operations in this class (and its children) are therefore strictly
+ * local to each mutator thread, and synchronized operations always
+ * happen via access to explicitly global classes such as Plan and its
+ * children.  Therefore only <i>"fast path"</i> (unsynchronized)
+ * allocation and barrier semantics are defined in MutatorContext and
+ * its subclasses.  These call out to <i>"slow path"</i> (synchronize(d)
+ * methods which have global state and are globally synchronized.  For
+ * example, an allocation fast path may bump a pointer without any
+ * syncrhonization (the "fast path") until a limit is reached, at which
+ * point the "slow path" is called, and more memory is aquired from a
+ * global resource.<p>
+ *
+ * As the super-class of all per-mutator contexts, this class implements
+ * basic per-mutator behavior common to all MMTk collectors, including
+ * support for immortal and large object space allocation, as well as
+ * empty stubs for write barriers (to be overridden by sub-classes as
+ * needed).
+ *
+ * @see CollectorContext
+ * @see org.mmtk.vm.ActivePlan
+ * @see Plan
+ */
+ at Uninterruptible
+public abstract class MutatorContext implements Constants {
+
+  /****************************************************************************
+   * Initialization
+   */
+
+
+  /**
+   * Notify that the mutator context is registered and ready to execute. From
+   * this point it will be included in iterations over mutators.
+   *
+   * @param id The id of this mutator context.
+   */
+  public void initMutator(int id) {
+    this.id = id;
+  }
+
+  /**
+   * The mutator is about to be cleaned up, make sure all local data is returned.
+   */
+  public void deinitMutator() {
+    flush();
+  }
+
+  /****************************************************************************
+   * Instance fields
+   */
+
+  /** Unique mutator identifier */
+  private int id;
+
+  /** Used for printing log information in a thread safe manner */
+  protected final Log log = new Log();
+
+  /** Per-mutator allocator into the immortal space */
+  protected final BumpPointer immortal = new ImmortalLocal(Plan.immortalSpace);
+
+  /** Per-mutator allocator into the large object space */
+  protected final LargeObjectLocal los = new LargeObjectLocal(Plan.loSpace);
+
+  /** Per-mutator allocator into the small code space */
+  private final MarkSweepLocal smcode = Plan.USE_CODE_SPACE ? new MarkSweepLocal(Plan.smallCodeSpace) : null;
+
+  /** Per-mutator allocator into the large code space */
+  private final LargeObjectLocal lgcode = Plan.USE_CODE_SPACE ? new LargeObjectLocal(Plan.largeCodeSpace) : null;
+
+  /** Per-mutator allocator into the non moving space */
+  private final MarkSweepLocal nonmove = new MarkSweepLocal(Plan.nonMovingSpace);
+
+
+  /****************************************************************************
+   *
+   * Collection.
+   */
+
+  /**
+   * Perform a per-mutator collection phase.
+   *
+   * @param phaseId The unique phase identifier
+   * @param primary Should this thread be used to execute any single-threaded
+   * local operations?
+   */
+  public abstract void collectionPhase(short phaseId, boolean primary);
+
+  /****************************************************************************
+   *
+   * Allocation.
+   */
+
+  /**
+   * Run-time check of the allocator to use for a given allocation
+   *
+   * At the moment this method assumes that allocators will use the simple
+   * (worst) method of aligning to determine if the object is a large object
+   * to ensure that no objects are larger than other allocators can handle.
+   *
+   * @param bytes The number of bytes to be allocated
+   * @param align The requested alignment.
+   * @param allocator The allocator statically assigned to this allocation
+   * @return The allocator dynamically assigned to this allocation
+   */
+  @Inline
+  public int checkAllocator(int bytes, int align, int allocator) {
+    int maxBytes = Allocator.getMaximumAlignedSize(bytes, align);
+    if (allocator == Plan.ALLOC_DEFAULT) {
+      return (maxBytes > Plan.MAX_NON_LOS_DEFAULT_ALLOC_BYTES) ? Plan.ALLOC_LOS : allocator;
+    }
+
+    if (Plan.USE_CODE_SPACE && allocator == Plan.ALLOC_CODE) {
+      return (maxBytes > Plan.MAX_NON_LOS_NONMOVING_ALLOC_BYTES) ? Plan.ALLOC_LARGE_CODE : allocator;
+    }
+
+    if (allocator == Plan.ALLOC_NON_REFERENCE) {
+      return (maxBytes > Plan.MAX_NON_LOS_DEFAULT_ALLOC_BYTES) ? Plan.ALLOC_LOS : Plan.ALLOC_DEFAULT;
+    }
+
+    if (allocator == Plan.ALLOC_NON_MOVING) {
+      return (maxBytes > Plan.MAX_NON_LOS_NONMOVING_ALLOC_BYTES) ? Plan.ALLOC_LOS : allocator;
+    }
+
+    return allocator;
+  }
+
+  /**
+   * Allocate memory for an object.
+   *
+   * @param bytes The number of bytes required for the object.
+   * @param align Required alignment for the object.
+   * @param offset Offset associated with the alignment.
+   * @param allocator The allocator associated with this request.
+   * @param site Allocation site
+   * @return The low address of the allocated chunk.
+   */
+  @Inline
+  public Address alloc(int bytes, int align, int offset, int allocator, int site) {
+    switch (allocator) {
+    case      Plan.ALLOC_LOS: return los.alloc(bytes, align, offset);
+    case      Plan.ALLOC_IMMORTAL: return immortal.alloc(bytes, align, offset);
+    case      Plan.ALLOC_CODE: return smcode.alloc(bytes, align, offset);
+    case      Plan.ALLOC_LARGE_CODE: return lgcode.alloc(bytes, align, offset);
+    case      Plan.ALLOC_NON_MOVING: return nonmove.alloc(bytes, align, offset);
+    default:
+      VM.assertions.fail("No such allocator");
+      return Address.zero();
+    }
+  }
+
+  /**
+   * Perform post-allocation actions.  For many allocators none are
+   * required.
+   *
+   * @param ref The newly allocated object
+   * @param typeRef the type reference for the instance being created
+   * @param bytes The size of the space to be allocated (in bytes)
+   * @param allocator The allocator number to be used for this allocation
+   */
+  @Inline
+  public void postAlloc(ObjectReference ref, ObjectReference typeRef,
+      int bytes, int allocator) {
+    switch (allocator) {
+    case           Plan.ALLOC_LOS: Plan.loSpace.initializeHeader(ref, true); return;
+    case      Plan.ALLOC_IMMORTAL: Plan.immortalSpace.initializeHeader(ref);  return;
+    case          Plan.ALLOC_CODE: Plan.smallCodeSpace.initializeHeader(ref, true); return;
+    case    Plan.ALLOC_LARGE_CODE: Plan.largeCodeSpace.initializeHeader(ref, true); return;
+    case    Plan.ALLOC_NON_MOVING: Plan.nonMovingSpace.initializeHeader(ref, true); return;
+    default:
+      VM.assertions.fail("No such allocator");
+    }
+  }
+
+  /****************************************************************************
+   *
+   * Space - Allocator mapping.
+   */
+
+  /**
+   * Return the allocator instance associated with a space
+   * <code>space</code>, for this plan instance.
+   *
+   * @param space The space for which the allocator instance is desired.
+   * @return The allocator instance associated with this plan instance
+   * which is allocating into <code>space</code>, or <code>null</code>
+   * if no appropriate allocator can be established.
+   */
+  public Allocator getAllocatorFromSpace(Space space) {
+    if (space == Plan.immortalSpace)  return immortal;
+    if (space == Plan.loSpace)        return los;
+    if (space == Plan.nonMovingSpace) return nonmove;
+    if (Plan.USE_CODE_SPACE && space == Plan.smallCodeSpace) return smcode;
+    if (Plan.USE_CODE_SPACE && space == Plan.largeCodeSpace) return lgcode;
+
+    // Invalid request has been made
+    if (space == Plan.metaDataSpace) {
+      VM.assertions.fail("MutatorContext.getAllocatorFromSpace given meta space");
+    } else if (space != null) {
+      VM.assertions.fail("MutatorContext.getAllocatorFromSpace given invalid space");
+    } else {
+      VM.assertions.fail("MutatorContext.getAllocatorFromSpace given null space");
+    }
+
+    return null;
+  }
+
+  /****************************************************************************
+   *
+   * Write and read barriers. By default do nothing, override if
+   * appropriate.
+   */
+
+  /**
+   * A new reference is about to be created. Take appropriate write
+   * barrier actions.<p>
+   *
+   * <b>By default do nothing, override if appropriate.</b>
+   *
+   * @param src The object into which the new reference will be stored
+   * @param slot The address into which the new reference will be
+   * stored.
+   * @param tgt The target of the new reference
+   * @param metaDataA A value that assists the host VM in creating a store
+   * @param metaDataB A value that assists the host VM in creating a store
+   * @param mode The context in which the store occurred
+   */
+  public void writeBarrier(ObjectReference src, Address slot,
+      ObjectReference tgt, Word metaDataA,
+      Word metaDataB, int mode) {
+    // Either: write barriers are used and this is overridden, or
+    // write barriers are not used and this is never called
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(false);
+  }
+
+  /**
+   * Attempt to atomically exchange the value in the given slot
+   * with the passed replacement value. If a new reference is
+   * created, we must then take appropriate write barrier actions.<p>
+   *
+   * <b>By default do nothing, override if appropriate.</b>
+   *
+   * @param src The object into which the new reference will be stored
+   * @param slot The address into which the new reference will be
+   * stored.
+   * @param old The old reference to be swapped out
+   * @param tgt The target of the new reference
+   * @param metaDataA A value that assists the host VM in creating a store
+   * @param metaDataB A value that assists the host VM in creating a store
+   * @param mode The context in which the store occurred
+   * @return True if the swap was successful.
+   */
+  public boolean tryCompareAndSwapWriteBarrier(ObjectReference src, Address slot,
+      ObjectReference old, ObjectReference tgt, Word metaDataA,
+      Word metaDataB, int mode) {
+    // Either: write barriers are used and this is overridden, or
+    // write barriers are not used and this is never called
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(false);
+    return false;
+  }
+
+  /**
+   * A number of references are about to be copied from object
+   * <code>src</code> to object <code>dst</code> (as in an array
+   * copy).  Thus, <code>dst</code> is the mutated object.  Take
+   * appropriate write barrier actions.<p>
+   *
+   * @param src The source of the values to be copied
+   * @param srcOffset The offset of the first source address, in
+   * bytes, relative to <code>src</code> (in principle, this could be
+   * negative).
+   * @param dst The mutated object, i.e. the destination of the copy.
+   * @param dstOffset The offset of the first destination address, in
+   * bytes relative to <code>tgt</code> (in principle, this could be
+   * negative).
+   * @param bytes The size of the region being copied, in bytes.
+   * @return True if the update was performed by the barrier, false if
+   * left to the caller (always false in this case).
+   */
+  public boolean writeBarrier(ObjectReference src, Offset srcOffset,
+      ObjectReference dst, Offset dstOffset,
+      int bytes) {
+    // Either: write barriers are used and this is overridden, or
+    // write barriers are not used and this is never called
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(false);
+    return false;
+  }
+
+  /**
+   * Read a reference type. In a concurrent collector this may
+   * involve adding the referent to the marking queue.
+   *
+   * @param referent The referent being read.
+   * @return The new referent.
+   */
+  @Inline
+  public ObjectReference referenceTypeReadBarrier(ObjectReference referent) {
+    // Either: read barriers are used and this is overridden, or
+    // read barriers are not used and this is never called
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(false);
+    return ObjectReference.nullReference();
+  }
+
+  /**
+   * Read a reference. Take appropriate read barrier action, and
+   * return the value that was read.<p> This is a <b>substituting<b>
+   * barrier.  The call to this barrier takes the place of a load.<p>
+   *
+   * @param src The object reference holding the field being read.
+   * @param slot The address of the slot being read.
+   * @param metaDataA A value that assists the host VM in creating a load
+   * @param metaDataB A value that assists the host VM in creating a load
+   * @param mode The context in which the load occurred
+   * @return The reference that was read.
+   */
+  @Inline
+  public ObjectReference readBarrier(ObjectReference src, Address slot, Word metaDataA, Word metaDataB, int mode) {
+    // Either: read barriers are used and this is overridden, or
+    // read barriers are not used and this is never called
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(false);
+    return ObjectReference.nullReference();
+  }
+
+  /**
+   * Flush mutator context, in response to a requestMutatorFlush.
+   * Also called by the default implementation of deinitMutator.
+   */
+  public void flush() {
+    flushRememberedSets();
+    smcode.flush();
+    nonmove.flush();
+  }
+
+  /**
+   * Flush per-mutator remembered sets into the global remset pool.
+   */
+  public void flushRememberedSets() {
+    // Either: write barriers are used and this is overridden, or
+    // write barriers are not used and this is a no-op
+  }
+
+  /**
+   * Assert that the remsets have been flushed.  This is critical to
+   * correctness.  We need to maintain the invariant that remset entries
+   * do not accrue during GC.  If the host JVM generates barrier entires
+   * it is its own responsibility to ensure that they are flushed before
+   * returning to MMTk.
+   */
+  public void assertRemsetsFlushed() {
+    // Either: write barriers are used and this is overridden, or
+    // write barriers are not used and this is a no-op
+  }
+
+  /***********************************************************************
+   *
+   * Miscellaneous
+   */
+
+  /** @return the <code>Log</code> instance for this PlanLocal */
+  public final Log getLog() {
+    return log;
+  }
+
+  /** @return the unique identifier for this mutator context. */
+  @Inline
+  public int getId() { return id; }
+
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/Phase.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/Phase.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/Phase.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/Phase.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,658 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan;
+
+import org.mmtk.utility.Constants;
+import org.mmtk.utility.Log;
+import org.mmtk.utility.options.Options;
+import org.mmtk.utility.statistics.Timer;
+import org.mmtk.vm.Collection;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * A garbage collection proceeds as a sequence of phases. Each
+ * phase is either simple (singular) or complex (an array).
+ *
+ * The context an individual phase executes in may be global, mutator,
+ * or collector.
+ *
+ * Phases are executed within a stack and all synchronization between
+ * parallel GC threads is managed from within this class.
+ *
+ * @see CollectorContext#collectionPhase
+ * @see MutatorContext#collectionPhase
+ * @see Plan#collectionPhase
+ */
+ at Uninterruptible
+public abstract class Phase implements Constants {
+  /***********************************************************************
+  *
+  * Phase allocation and storage.
+  */
+
+  /** The maximum number of phases */
+  private static final int MAX_PHASES = 64;
+  /** The array of phase instances. Zero is unused. */
+  private static final Phase[] phases = new Phase[MAX_PHASES];
+  /** The id to be allocated for the next phase */
+  private static short nextPhaseId = 1;
+
+  /** Run the phase globally. */
+  protected static final short SCHEDULE_GLOBAL = 1;
+  /** Run the phase on collectors. */
+  protected static final short SCHEDULE_COLLECTOR = 2;
+  /** Run the phase on mutators. */
+  protected static final short SCHEDULE_MUTATOR = 3;
+  /** Don't run this phase. */
+  protected static final short SCHEDULE_PLACEHOLDER = 100;
+  /** This is a complex phase. */
+  protected static final short SCHEDULE_COMPLEX = 101;
+
+  /**
+   * Retrieve a phase by the unique phase identifier.
+   *
+   * @param id The phase identifier.
+   * @return The Phase instance.
+   */
+  public static Phase getPhase(short id) {
+    if (VM.VERIFY_ASSERTIONS) {
+      VM.assertions._assert(id < nextPhaseId, "Phase ID unknown");
+      VM.assertions._assert(phases[id] != null, "Uninitialised phase");
+    }
+    return phases[id];
+  }
+
+  /** Get the phase id component of an encoded phase */
+  protected static short getPhaseId(int scheduledPhase) {
+    short phaseId = (short)(scheduledPhase & 0x0000FFFF);
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(phaseId > 0);
+    return phaseId;
+  }
+
+  /**
+   * @param phaseId The unique phase identifier.
+   * @return The name of the phase.
+   */
+  public static String getName(short phaseId) {
+    return phases[phaseId].name;
+  }
+
+  /** Get the ordering component of an encoded phase */
+  protected static short getSchedule(int scheduledPhase) {
+    short ordering = (short)((scheduledPhase >> 16) & 0x0000FFFF);
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(ordering > 0);
+    return ordering;
+  }
+
+  /** Get the ordering component of an encoded phase */
+  protected static String getScheduleName(short ordering) {
+    switch (ordering) {
+      case SCHEDULE_GLOBAL:      return "Global";
+      case SCHEDULE_COLLECTOR:   return "Collector";
+      case SCHEDULE_MUTATOR:     return "Mutator";
+      case SCHEDULE_PLACEHOLDER: return "Placeholder";
+      case SCHEDULE_COMPLEX:     return "Complex";
+      default:                   return "UNKNOWN!";
+    }
+  }
+
+  /**
+   * Construct a phase.
+   *
+   * @param name Display name of the phase
+   */
+  @Interruptible
+  public static short createSimple(String name) {
+    return new SimplePhase(name).getId();
+  }
+
+  /**
+   * Construct a phase, re-using a specified timer.
+   *
+   * @param name Display name of the phase
+   */
+  @Interruptible
+  public static short createSimple(String name, Timer timer) {
+    return new SimplePhase(name, timer).getId();
+  }
+
+  /**
+   * Construct a complex phase.
+   *
+   * @param name Display name of the phase
+   * @param scheduledPhases The phases in this complex phase.
+   */
+  @Interruptible
+  public static short createComplex(String name,int... scheduledPhases) {
+    return new ComplexPhase(name, scheduledPhases).getId();
+  }
+
+  /**
+   * Construct a complex phase, re-using a specified timer.
+   *
+   * @param name Display name of the phase
+   * @param timer Timer for this phase to contribute to
+   * @param scheduledPhases The phases in this complex phase.
+   */
+  @Interruptible
+  public static short createComplex(String name, Timer timer, int... scheduledPhases) {
+    return new ComplexPhase(name, timer, scheduledPhases).getId();
+  }
+
+  /**
+   * Take the passed phase and return an encoded phase to
+   * run that phase as a complex phase.
+   *
+   * @param phaseId The phase to run as complex
+   * @return The encoded phase value.
+   */
+  public static int scheduleComplex(short phaseId) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Phase.getPhase(phaseId) instanceof ComplexPhase);
+    return (SCHEDULE_COMPLEX << 16) + phaseId;
+  }
+
+  /**
+   * Take the passed phase and return an encoded phase to
+   * run that phase in a global context;
+   *
+   * @param phaseId The phase to run globally
+   * @return The encoded phase value.
+   */
+  public static int scheduleGlobal(short phaseId) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Phase.getPhase(phaseId) instanceof SimplePhase);
+    return (SCHEDULE_GLOBAL << 16) + phaseId;
+  }
+
+  /**
+   * Take the passed phase and return an encoded phase to
+   * run that phase in a collector context;
+   *
+   * @param phaseId The phase to run on collectors
+   * @return The encoded phase value.
+   */
+  public static int scheduleCollector(short phaseId) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Phase.getPhase(phaseId) instanceof SimplePhase);
+    return (SCHEDULE_COLLECTOR << 16) + phaseId;
+  }
+
+  /**
+   * Take the passed phase and return an encoded phase to
+   * run that phase in a mutator context;
+   *
+   * @param phaseId The phase to run on mutators
+   * @return The encoded phase value.
+   */
+  public static int scheduleMutator(short phaseId) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Phase.getPhase(phaseId) instanceof SimplePhase);
+    return (SCHEDULE_MUTATOR << 16) + phaseId;
+  }
+
+  /**
+   * Take the passed phase and return an encoded phase to
+   * run that phase in a mutator context;
+   *
+   * @param phaseId The phase to run on mutators
+   * @return The encoded phase value.
+   */
+  public static int schedulePlaceholder(short phaseId) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Phase.getPhase(phaseId) instanceof SimplePhase);
+    return (SCHEDULE_PLACEHOLDER << 16) + phaseId;
+  }
+
+  /***********************************************************************
+   *
+   * Phase instance fields/methods.
+   */
+
+  /**
+   * The unique phase identifier.
+   */
+  protected final short id;
+
+  /**
+   * The name of the phase.
+   */
+  protected final String name;
+
+  /**
+   * The Timer that is started and stopped around the execution of this
+   * phase.
+   */
+  protected final Timer timer;
+
+  /**
+   * Create a new Phase. This involves creating a corresponding Timer
+   * instance, allocating a unique identifier, and registering the
+   * Phase.
+   *
+   * @param name The name for the phase.
+   */
+  protected Phase(String name) {
+    this(name, new Timer(name, false, true));
+  }
+
+  /**
+   * Create a new phase. This involves setting the corresponding Timer
+   * instance, allocating a unique identifier, and registering the Phase.
+   *
+   * @param name The name of the phase.
+   * @param timer The timer, or null if this is an untimed phase.
+   */
+  protected Phase(String name, Timer timer) {
+    this.name = name;
+    this.timer = timer;
+    this.id = nextPhaseId++;
+    phases[this.id] = this;
+  }
+
+  /**
+   * @return The unique identifier for this phase.
+   */
+  public final short getId() {
+    return this.id;
+  }
+
+  /**
+   * Display a phase for debugging purposes.
+   */
+  protected abstract void logPhase();
+
+  /***********************************************************************
+   *
+   * Phase stack
+   */
+
+  /** The maximum stack depth for the phase stack. */
+  private static final int MAX_PHASE_STACK_DEPTH = MAX_PHASES;
+
+  /** Stores the current sub phase for a complex phase. Each entry corresponds to a phase stack entry */
+  private static int[] complexPhaseCursor = new int[MAX_PHASE_STACK_DEPTH];
+
+  /** The phase stack. Stores the current nesting of phases */
+  private static int[] phaseStack = new int[MAX_PHASE_STACK_DEPTH];
+
+  /** The current stack pointer */
+  private static int phaseStackPointer = -1;
+
+  /**
+   * The current even (0 mod 2) scheduled phase.
+   * As we only sync at the end of a phase we need this to ensure that
+   * the primary thread setting the phase does not race with the other
+   * threads reading it.
+   */
+  private static int evenScheduledPhase;
+
+  /**
+   * The current odd (1 mod 2) scheduled phase.
+   * As we only sync at the end of a phase we need this to ensure that
+   * the primary thread setting the phase does not race with the other
+   * threads reading it.
+   */
+  private static int oddScheduledPhase;
+
+  /**
+   * Do we need to add a sync point to reset the mutator count. This
+   * is necessary for consecutive mutator phases and unneccessary
+   * otherwise. Again we separate in even and odd to ensure that there
+   * is no race between the primary thread setting and the helper
+   * threads reading.
+   */
+  private static boolean evenMutatorResetRendezvous;
+
+  /**
+   * Do we need to add a sync point to reset the mutator count. This
+   * is necessary for consecutive mutator phases and unneccessary
+   * otherwise. Again we separate in even and odd to ensure that there
+   * is no race between the primary thread setting and the helper
+   * threads reading.
+   */
+  private static boolean oddMutatorResetRendezvous;
+
+  /**
+   * The complex phase whose timer should be started after the next
+   * rendezvous. We can not start the timer at the point we determine
+   * the next complex phase as we determine the next phase at the
+   * end of the previous phase before the sync point.
+   */
+  private static short startComplexTimer;
+
+  /**
+   * The complex phase whose timer should be stopped after the next
+   * rendezvous. We can not start the timer at the point we determine
+   * the next complex phase as we determine the next phase at the
+   * end of the previous phase before the sync point.
+   */
+  private static short stopComplexTimer;
+
+  /**
+   * Place a phase on the phase stack and begin processing.
+   *
+   * @param scheduledPhase The phase to execute
+   * @return True if the phase stack is exhausted.
+   */
+  public static boolean beginNewPhaseStack(int scheduledPhase) {
+    int order = VM.collection.rendezvous(1001);
+
+    if (order == 1) {
+      pushScheduledPhase(scheduledPhase);
+    }
+    return processPhaseStack(false);
+  }
+
+  /**
+   * Process the phase stack. This method is called by multiple threads.
+   */
+  private static boolean processPhaseStack(boolean resume) {
+    int order = VM.collection.rendezvous(1001);
+    final boolean primary = order == 1;
+
+    boolean log = Options.verbose.getValue() >= 6;
+    boolean logDetails = Options.verbose.getValue() >= 7;
+
+    if (primary && resume) {
+      if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!Phase.isPhaseStackEmpty());
+      if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!Plan.gcInProgress());
+      Plan.setGCStatus(Plan.GC_PROPER);
+    }
+
+    /* In order to reduce the need for synchronization, we keep an odd or even
+     * counter for the number of phases processed. As each phase has a single
+     * rendezvous it is only possible to be out by one so the odd or even counter
+     * protects us. */
+    boolean isEvenPhase = true;
+
+    if (primary) {
+      /* First phase will be even, so we say we are odd here so that the next phase set is even*/
+      setNextPhase(false, getNextPhase(), false);
+    }
+
+    /* Make sure everyone sees the first phase */
+    VM.collection.rendezvous(1002);
+
+    /* Global and Collector instances used in phases */
+    Plan plan = VM.activePlan.global();
+    CollectorContext collector = VM.activePlan.collector();
+
+    /* The main phase execution loop */
+    int scheduledPhase;
+    while((scheduledPhase = getCurrentPhase(isEvenPhase)) > 0) {
+      short schedule = getSchedule(scheduledPhase);
+      short phaseId = getPhaseId(scheduledPhase);
+      Phase p = getPhase(phaseId);
+
+      /* Start the timer(s) */
+      if (primary) {
+        if (resume) {
+          resumeComplexTimers();
+        }
+        if (p.timer != null) p.timer.start();
+        if (startComplexTimer > 0) {
+          Phase.getPhase(startComplexTimer).timer.start();
+          startComplexTimer = 0;
+        }
+      }
+
+      if (log) {
+        Log.write("Execute ");
+        p.logPhase();
+      }
+
+      /* Execute a single simple scheduled phase */
+      switch (schedule) {
+        /* Global phase */
+        case SCHEDULE_GLOBAL: {
+          if (logDetails) Log.writeln(" as Global...");
+          if (primary) {
+            if (VM.DEBUG) VM.debugging.globalPhase(phaseId,true);
+            plan.collectionPhase(phaseId);
+            if (VM.DEBUG) VM.debugging.globalPhase(phaseId,false);
+          }
+          break;
+        }
+
+        /* Collector phase */
+        case SCHEDULE_COLLECTOR: {
+          if (logDetails) Log.writeln(" as Collector...");
+          if (VM.DEBUG) VM.debugging.collectorPhase(phaseId,order,true);
+          collector.collectionPhase(phaseId, primary);
+          if (VM.DEBUG) VM.debugging.collectorPhase(phaseId,order,false);
+          break;
+        }
+
+        /* Mutator phase */
+        case SCHEDULE_MUTATOR: {
+          if (logDetails) Log.writeln(" as Mutator...");
+          /* Iterate through all mutator contexts */
+          MutatorContext mutator;
+          while ((mutator = VM.activePlan.getNextMutator()) != null) {
+            if (VM.DEBUG) VM.debugging.mutatorPhase(phaseId,mutator.getId(),true);
+            mutator.collectionPhase(phaseId, primary);
+            if (VM.DEBUG) VM.debugging.mutatorPhase(phaseId,mutator.getId(),false);
+          }
+          break;
+        }
+
+        default: {
+          /* getNextPhase has done the wrong thing */
+          VM.assertions.fail("Invalid schedule in Phase.processPhaseStack");
+          break;
+        }
+      }
+
+      if (primary) {
+        /* Set the next phase by processing the stack */
+        int next = getNextPhase();
+        boolean needsResetRendezvous = (next > 0) && (schedule == SCHEDULE_MUTATOR && getSchedule(next) == SCHEDULE_MUTATOR);
+        setNextPhase(isEvenPhase, next, needsResetRendezvous);
+      }
+
+      /* Sync point after execution of a phase */
+      VM.collection.rendezvous(1004);
+
+      /* Mutator phase reset */
+      if (primary && schedule == SCHEDULE_MUTATOR) {
+        VM.activePlan.resetMutatorIterator();
+      }
+
+      /* At this point, in the case of consecutive phases with mutator
+       * scheduling, we have to double-synchronize to ensure all
+       * collector threads see the reset mutator counter. */
+      if (needsMutatorResetRendezvous(isEvenPhase)) {
+        VM.collection.rendezvous(1005);
+      }
+
+      /* Stop the timer(s) */
+      if (primary) {
+        if (p.timer != null) p.timer.stop();
+        if (stopComplexTimer > 0) {
+          Phase.getPhase(stopComplexTimer).timer.stop();
+          stopComplexTimer = 0;
+        }
+      }
+
+      /* Flip the even / odd phase sense */
+      isEvenPhase = !isEvenPhase;
+      resume = false;
+    }
+
+    /* Phase stack exhausted so we return true */
+    return true;
+  }
+
+  /**
+   * Get the next phase.
+   */
+  private static int getCurrentPhase(boolean isEvenPhase) {
+    return isEvenPhase ? evenScheduledPhase : oddScheduledPhase;
+  }
+
+  /**
+   * Do we need a mutator reset rendezvous in this phase?
+   */
+  private static boolean needsMutatorResetRendezvous(boolean isEvenPhase) {
+    return isEvenPhase ? evenMutatorResetRendezvous : oddMutatorResetRendezvous;
+  }
+  /**
+   * Set the next phase. If we are in an even phase the next phase is odd.
+   */
+  private static void setNextPhase(boolean isEvenPhase, int scheduledPhase, boolean needsResetRendezvous) {
+    if (isEvenPhase) {
+      oddScheduledPhase = scheduledPhase;
+      evenMutatorResetRendezvous = needsResetRendezvous;
+    } else {
+      evenScheduledPhase = scheduledPhase;
+      oddMutatorResetRendezvous = needsResetRendezvous;
+    }
+  }
+
+  /**
+   * Pull the next scheduled phase off the stack. This may involve
+   * processing several complex phases and skipping placeholders, etc.
+   *
+   * @return The next phase to run, or -1 if no phases are left.
+   */
+  private static int getNextPhase() {
+    boolean allowConcurrentPhase = Plan.collectionTrigger == Collection.INTERNAL_PHASE_GC_TRIGGER;
+
+    while (phaseStackPointer >= 0) {
+      int scheduledPhase = peekScheduledPhase();
+      short schedule = getSchedule(scheduledPhase);
+      short phaseId = getPhaseId(scheduledPhase);
+
+      switch(schedule) {
+        case SCHEDULE_PLACEHOLDER: {
+          /* Placeholders are ignored and we continue looking */
+          popScheduledPhase();
+          continue;
+        }
+
+        case SCHEDULE_GLOBAL:
+        case SCHEDULE_COLLECTOR:
+        case SCHEDULE_MUTATOR: {
+          /* Simple phases are just popped off the stack and executed */
+          popScheduledPhase();
+          return scheduledPhase;
+        }
+
+        case SCHEDULE_COMPLEX: {
+          /* A complex phase may either be a newly pushed complex phase,
+           * or a complex phase we are in the process of executing in
+           * which case we move to the next subphase. */
+          ComplexPhase p = (ComplexPhase)getPhase(phaseId);
+          int cursor = incrementComplexPhaseCursor();
+          if (cursor == 0 && p.timer != null) {
+            /* Tell the primary thread to start the timer after the next sync. */
+            startComplexTimer = phaseId;
+          }
+          if (cursor < p.count()) {
+            /* There are more entries, we push the next one and continue */
+            pushScheduledPhase(p.get(cursor));
+            continue;
+          }
+
+          /* We have finished this complex phase */
+          popScheduledPhase();
+          if (p.timer != null) {
+            /* Tell the primary thread to stop the timer after the next sync. */
+            stopComplexTimer = phaseId;
+          }
+          continue;
+        }
+
+        default: {
+          VM.assertions.fail("Invalid phase type encountered");
+        }
+      }
+    }
+    return -1;
+  }
+
+  /**
+   * Pause all of the timers for the complex phases sitting in the stack.
+   */
+  private static void pauseComplexTimers() {
+    for(int i=phaseStackPointer; i >=0; i--) {
+      Phase p = getPhase(getPhaseId(phaseStack[i]));
+      if (p.timer != null) p.timer.stop();
+    }
+  }
+
+  /**
+   * Resume all of the timers for the complex phases sitting in the stack.
+   */
+  private static void resumeComplexTimers() {
+    for(int i=phaseStackPointer; i >=0; i--) {
+      Phase p = getPhase(getPhaseId(phaseStack[i]));
+      if (p.timer != null) p.timer.start();
+    }
+  }
+
+  /**
+   * Return true if phase stack is empty, false otherwise.
+   *
+   * @return true if phase stack is empty, false otherwise.
+   */
+  @Inline
+  public static boolean isPhaseStackEmpty() {
+    return phaseStackPointer < 0;
+  }
+
+  /**
+   * Clears the scheduled phase stack.
+   */
+  @Inline
+  public static void resetPhaseStack() {
+    phaseStackPointer = -1;
+  }
+
+  /**
+   * Push a scheduled phase onto the top of the work stack.
+   *
+   * @param scheduledPhase The scheduled phase.
+   */
+  @Inline
+  public static void pushScheduledPhase(int scheduledPhase) {
+    phaseStack[++phaseStackPointer] = scheduledPhase;
+    complexPhaseCursor[phaseStackPointer] = 0;
+  }
+
+  /**
+   * Increment the cursor associated with the current phase
+   * stack entry. This is used to remember the current sub phase
+   * when executing a complex phase.
+   *
+   * @return The old value of the cursor.
+   */
+  @Inline
+  private static int incrementComplexPhaseCursor() {
+    return complexPhaseCursor[phaseStackPointer]++;
+  }
+
+  /**
+   * Pop off the scheduled phase at the top of the work stack.
+   */
+  @Inline
+  private static int popScheduledPhase() {
+    return phaseStack[phaseStackPointer--];
+  }
+
+  /**
+   * Peek the scheduled phase at the top of the work stack.
+   */
+  @Inline
+  private static int peekScheduledPhase() {
+    return phaseStack[phaseStackPointer];
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/Plan.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/Plan.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/Plan.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/Plan.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,1051 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan;
+
+import org.mmtk.policy.MarkSweepSpace;
+import org.mmtk.policy.Space;
+import org.mmtk.policy.ImmortalSpace;
+import org.mmtk.policy.RawPageSpace;
+import org.mmtk.policy.LargeObjectSpace;
+import org.mmtk.utility.alloc.LinearScan;
+import org.mmtk.utility.Constants;
+import org.mmtk.utility.Conversions;
+import org.mmtk.utility.heap.HeapGrowthManager;
+import org.mmtk.utility.heap.Map;
+import org.mmtk.utility.heap.VMRequest;
+import org.mmtk.utility.Log;
+import org.mmtk.utility.options.*;
+import org.mmtk.utility.sanitychecker.SanityChecker;
+import org.mmtk.utility.statistics.PerfCounter;
+import org.mmtk.utility.statistics.Timer;
+import org.mmtk.utility.statistics.Stats;
+
+import org.mmtk.vm.VM;
+import org.mmtk.vm.Collection;
+
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This abstract class implements the global core functionality for all
+ * memory management schemes.  All global MMTk plans should inherit from
+ * this class.<p>
+ *
+ * All plans make a clear distinction between <i>global</i> and
+ * <i>thread-local</i> activities, and divides global and local state
+ * into separate class hierarchies.  Global activities must be
+ * synchronized, whereas no synchronization is required for
+ * thread-local activities.  There is a single instance of Plan (or the
+ * appropriate sub-class), and a 1:1 mapping of PlanLocal to "kernel
+ * threads" (aka CPUs).  Thus instance
+ * methods of PlanLocal allow fast, unsynchronized access to functions such as
+ * allocation and collection.
+ *
+ * The global instance defines and manages static resources
+ * (such as memory and virtual memory resources).  This mapping of threads to
+ * instances is crucial to understanding the correctness and
+ * performance properties of MMTk plans.
+ */
+ at Uninterruptible
+public abstract class Plan implements Constants {
+  /****************************************************************************
+   * Constants
+   */
+
+  /* GC State */
+  public static final int NOT_IN_GC = 0; // this must be zero for C code
+  public static final int GC_PREPARE = 1; // before setup and obtaining root
+  public static final int GC_PROPER = 2;
+
+  /* Polling */
+  public static final int DEFAULT_POLL_FREQUENCY = (128 << 10) >> LOG_BYTES_IN_PAGE;
+  public static final int META_DATA_POLL_FREQUENCY = DEFAULT_POLL_FREQUENCY;
+
+  /* Space Size Constants. */
+  public static final boolean USE_CODE_SPACE = true;
+  public static final float PLOS_FRAC = 0.07f;
+  public static final int HEAP_FULL_MINIMUM = (1 << 17) >> LOG_BYTES_IN_PAGE; // 128K
+  public static final int HEAP_FULL_PERCENTAGE = 2;
+
+  /* Allocator Constants */
+  public static final int ALLOC_DEFAULT = 0;
+  public static final int ALLOC_NON_REFERENCE = 1;
+  public static final int ALLOC_NON_MOVING = 2;
+  public static final int ALLOC_IMMORTAL = 3;
+  public static final int ALLOC_LOS = 4;
+  public static final int ALLOC_PRIMITIVE_LOS = 5;
+  public static final int ALLOC_GCSPY = 6;
+  public static final int ALLOC_CODE = 7;
+  public static final int ALLOC_LARGE_CODE = 8;
+  public static final int ALLOC_HOT_CODE = USE_CODE_SPACE ? ALLOC_CODE : ALLOC_DEFAULT;
+  public static final int ALLOC_COLD_CODE = USE_CODE_SPACE ? ALLOC_CODE : ALLOC_DEFAULT;
+  public static final int ALLOC_STACK = ALLOC_LOS;
+  public static final int ALLOCATORS = 9;
+  public static final int DEFAULT_SITE = -1;
+
+  /* Miscellaneous Constants */
+//  public static final int LOS_SIZE_THRESHOLD = SegregatedFreeListSpace.MAX_CELL_SIZE;
+  public static final int NON_PARTICIPANT = 0;
+  public static final boolean GATHER_WRITE_BARRIER_STATS = false;
+  public static final int DEFAULT_MIN_NURSERY = (256 * 1024) >> LOG_BYTES_IN_PAGE;
+  public static final int DEFAULT_MAX_NURSERY = (32 << 20) >> LOG_BYTES_IN_PAGE;
+  public static final boolean SCAN_BOOT_IMAGE = true;  // scan it for roots rather than trace it
+  public static final int MAX_COLLECTION_ATTEMPTS = 10;
+ // public static final boolean REQUIRES_LOS = VM.activePlan.constraints().requiresLOS();
+  public static final int MAX_NON_LOS_DEFAULT_ALLOC_BYTES = VM.activePlan.constraints().maxNonLOSDefaultAllocBytes();
+  public static final int MAX_NON_LOS_NONMOVING_ALLOC_BYTES = VM.activePlan.constraints().maxNonLOSNonMovingAllocBytes();
+  public static final int MAX_NON_LOS_COPY_BYTES = VM.activePlan.constraints().maxNonLOSCopyBytes();
+
+
+/* Do we support a log bit in the object header?  Some write barriers may use it */
+  public static final boolean NEEDS_LOG_BIT_IN_HEADER = VM.activePlan.constraints().needsLogBitInHeader();
+  public static final Word LOG_SET_MASK = VM.activePlan.constraints().unloggedBit();
+  private static final Word LOG_CLEAR_MASK = LOG_SET_MASK.not();
+  public static final Word UNLOGGED_BIT = VM.activePlan.constraints().unloggedBit();
+
+  /****************************************************************************
+   * Class variables
+   */
+
+  /** The space that holds any VM specific objects (e.g. a boot image) */
+  public static final Space vmSpace = VM.memory.getVMSpace();
+
+  /** Any immortal objects allocated after booting are allocated here. */
+  public static final ImmortalSpace immortalSpace = new ImmortalSpace("immortal", DEFAULT_POLL_FREQUENCY, VMRequest.create());
+
+  /** All meta data that is used by MMTk is allocated (and accounted for) in the meta data space. */
+  public static final RawPageSpace metaDataSpace = new RawPageSpace("meta", DEFAULT_POLL_FREQUENCY, VMRequest.create());
+
+  /** Large objects are allocated into a special large object space. */
+  public static final LargeObjectSpace loSpace = new LargeObjectSpace("los", DEFAULT_POLL_FREQUENCY, VMRequest.create());
+
+  /** Space used by the sanity checker (used at runtime only if sanity checking enabled */
+  public static final RawPageSpace sanitySpace = new RawPageSpace("sanity", Integer.MAX_VALUE, VMRequest.create());
+
+  /** Space used to allocate objects that cannot be moved. we do not need a large space as the LOS is non-moving. */
+  public static final MarkSweepSpace nonMovingSpace = new MarkSweepSpace("non-moving", DEFAULT_POLL_FREQUENCY, VMRequest.create());
+
+  public static final MarkSweepSpace smallCodeSpace = USE_CODE_SPACE ? new MarkSweepSpace("sm-code", DEFAULT_POLL_FREQUENCY, VMRequest.create()) : null;
+  public static final LargeObjectSpace largeCodeSpace = USE_CODE_SPACE ? new LargeObjectSpace("lg-code", DEFAULT_POLL_FREQUENCY, VMRequest.create()) : null;
+
+  /* Space descriptors */
+  public static final int IMMORTAL = immortalSpace.getDescriptor();
+  public static final int VM_SPACE = vmSpace.getDescriptor();
+  public static final int META = metaDataSpace.getDescriptor();
+  public static final int LOS = loSpace.getDescriptor();
+  public static final int SANITY = sanitySpace.getDescriptor();
+  public static final int NON_MOVING = nonMovingSpace.getDescriptor();
+  public static final int SMALL_CODE = USE_CODE_SPACE ? smallCodeSpace.getDescriptor() : 0;
+  public static final int LARGE_CODE = USE_CODE_SPACE ? largeCodeSpace.getDescriptor() : 0;
+
+  /** Timer that counts total time */
+  public static final Timer totalTime = new Timer("time");
+
+  /** Performance counters */
+  public static final PerfCounter totalPerfCnt = new PerfCounter("perf");
+
+  /** Support for time-limited GCs */
+  protected static long timeCap;
+
+  /** Support for allocation-site identification */
+  protected static int allocationSiteCount = 0;
+
+  /** Global sanity checking state **/
+  public static final SanityChecker sanityChecker = new SanityChecker();
+
+  /****************************************************************************
+   * Constructor.
+   */
+  public Plan() {
+    /* Create base option instances */
+    Options.verbose = new Verbose();
+    Options.verboseTiming = new VerboseTiming();
+    Options.stressFactor = new StressFactor();
+    Options.noFinalizer = new NoFinalizer();
+    Options.noReferenceTypes = new NoReferenceTypes();
+    Options.fullHeapSystemGC = new FullHeapSystemGC();
+    Options.harnessAll = new HarnessAll();
+    Options.ignoreSystemGC = new IgnoreSystemGC();
+    Options.metaDataLimit = new MetaDataLimit();
+    Options.nurserySize = new NurserySize();
+    Options.variableSizeHeap = new VariableSizeHeap();
+    Options.eagerMmapSpaces = new EagerMmapSpaces();
+    Options.sanityCheck = new SanityCheck();
+    Options.debugAddress = new DebugAddress();
+    Options.perfMetric = new PerfMetric();
+    Map.finalizeStaticSpaceMap();
+    registerSpecializedMethods();
+  }
+
+  /****************************************************************************
+   * Boot.
+   */
+
+  /**
+   * The boot method is called early in the boot process before any
+   * allocation.
+   */
+  @Interruptible
+  public void boot() {
+  }
+
+  /**
+   * The postBoot method is called by the runtime immediately after
+   * command-line arguments are available.  Note that allocation must
+   * be supported prior to this point because the runtime
+   * infrastructure may require allocation in order to parse the
+   * command line arguments.  For this reason all plans should operate
+   * gracefully on the default minimum heap size until the point that
+   * boot is called.
+   */
+  @Interruptible
+  public void postBoot() {
+    VM.statistics.perfCtrInit(Options.perfMetric.getValue());
+    if (Options.verbose.getValue() > 2) Space.printVMMap();
+    if (Options.verbose.getValue() > 3) VM.config.printConfig();
+    if (Options.verbose.getValue() > 0) Stats.startAll();
+    if (Options.eagerMmapSpaces.getValue()) Space.eagerlyMmapMMTkSpaces();
+  }
+
+  /**
+   * The fullyBooted method is called by the runtime just before normal
+   * execution commences.
+   */
+  @Interruptible
+  public void fullyBooted() {
+    initialized = true;
+    if (Options.harnessAll.getValue()) harnessBegin();
+  }
+
+  /**
+   * The VM is about to exit. Perform any clean up operations.
+   *
+   * @param value The exit value
+   */
+  @Interruptible
+  public void notifyExit(int value) {
+    if (Options.harnessAll.getValue()) harnessEnd();
+    if (Options.verbose.getValue() == 1) {
+      Log.write("[End ");
+      totalTime.printTotalSecs();
+      Log.writeln(" s]");
+    } else if (Options.verbose.getValue() == 2) {
+      Log.write("[End ");
+      totalTime.printTotalMillis();
+      Log.writeln(" ms]");
+    }
+    if (Options.verboseTiming.getValue()) printDetailedTiming(true);
+  }
+
+  /**
+   * Any Plan can override this to provide additional plan specific
+   * timing information.
+   *
+   * @param totals Print totals
+   */
+  protected void printDetailedTiming(boolean totals) {}
+
+  /**
+   * Perform any required initialization of the GC portion of the header.
+   * Called for objects created at boot time.
+   *
+   * @param ref the object ref to the storage to be initialized
+   * @param typeRef the type reference for the instance being created
+   * @param size the number of bytes allocated by the GC system for
+   * this object.
+   * @param status the initial value of the status word
+   * @return The new value of the status word
+   */
+  @Inline
+  public Word setBootTimeGCBits(Address ref, ObjectReference typeRef,
+                                int size, Word status) {
+    if (NEEDS_LOG_BIT_IN_HEADER)
+      return status.or(UNLOGGED_BIT);
+    else
+    return status; // nothing to do (no bytes of GC header)
+  }
+
+  /**
+   * Perform any required write barrier action when installing an object reference
+   * a boot time.
+   *
+   * @param reference the reference value that is to be stored
+   * @return The raw value to be
+   */
+  public Word bootTimeWriteBarrier(Word reference) {
+    return reference;
+  }
+
+  /****************************************************************************
+   * Allocation
+   */
+  public static int getAllocationSite(boolean compileTime) {
+    if (compileTime) // a new allocation site is being compiled
+      return allocationSiteCount++;
+    else             // an anonymous site
+      return DEFAULT_SITE;
+  }
+
+  /****************************************************************************
+   * Collection.
+   */
+
+  /**
+   * Perform a (global) collection phase.
+   */
+  public abstract void collectionPhase(short phase);
+
+  /**
+   * Replace a phase.
+   *
+   * @param oldScheduledPhase The scheduled phase to insert after
+   * @param scheduledPhase The scheduled phase to insert
+   */
+  @Interruptible
+  public void replacePhase(int oldScheduledPhase, int scheduledPhase) {
+    VM.assertions.fail("replacePhase not implemented for this plan");
+  }
+
+
+  /**
+   * Insert a phase.
+   *
+   * @param markerScheduledPhase The scheduled phase to insert after
+   * @param scheduledPhase The scheduled phase to insert
+   */
+  @Interruptible
+  public void insertPhaseAfter(int markerScheduledPhase, int scheduledPhase) {
+    short tempPhase = Phase.createComplex("auto-gen", null, markerScheduledPhase, scheduledPhase);
+    replacePhase(markerScheduledPhase, Phase.scheduleComplex(tempPhase));
+  }
+
+  /**
+   * @return Whether last GC was an exhaustive attempt to collect the heap.  For many collectors this is the same as asking whether the last GC was a full heap collection.
+   */
+  public boolean lastCollectionWasExhaustive() {
+    return lastCollectionFullHeap();
+  }
+
+  /**
+   * @return Whether last GC is a full GC.
+   */
+  public boolean lastCollectionFullHeap() {
+    return true;
+  }
+
+  /**
+   * @return Is last GC a full collection?
+   */
+  public static boolean isEmergencyCollection() {
+    return emergencyCollection;
+  }
+
+  /**
+   * @return True if we have run out of heap space.
+   */
+  public final boolean lastCollectionFailed() {
+    return !(collectionTrigger == Collection.EXTERNAL_GC_TRIGGER ||
+             collectionTrigger == Collection.INTERNAL_PHASE_GC_TRIGGER) &&
+      (getPagesAvail() < getHeapFullThreshold() || getPagesAvail() < requiredAtStart);
+  }
+
+  /**
+   * Force the next collection to be full heap.
+   */
+  public void forceFullHeapCollection() {}
+
+  /**
+   * @return Is current GC only collecting objects allocated since last GC.
+   */
+  public boolean isCurrentGCNursery() {
+    return false;
+  }
+
+  private long lastStressPages = 0;
+
+  /**
+   * Return the expected reference count. For non-reference counting
+   * collectors this becomes a true/false relationship.
+   *
+   * @param object The object to check.
+   * @param sanityRootRC The number of root references to the object.
+   * @return The expected (root excluded) reference count.
+   */
+  public int sanityExpectedRC(ObjectReference object, int sanityRootRC) {
+    Space space = Space.getSpaceForObject(object);
+    return space.isReachable(object) ? SanityChecker.ALIVE : SanityChecker.DEAD;
+  }
+
+  /**
+   * Perform a linear scan of all spaces to check for possible leaks.
+   * This is only called after a full-heap GC.
+   *
+   * @param scanner The scanner callback to use.
+   */
+  public void sanityLinearScan(LinearScan scanner) {
+  }
+
+  /**
+   * @return True is a stress test GC is required
+   */
+  @Inline
+  public final boolean stressTestGCRequired() {
+    long pages = Space.cumulativeCommittedPages();
+    if (initialized &&
+        ((pages ^ lastStressPages) > Options.stressFactor.getPages())) {
+      lastStressPages = pages;
+      return true;
+    } else
+      return false;
+  }
+
+  /****************************************************************************
+   * GC State
+   */
+
+  protected static int requiredAtStart;
+  protected static int collectionTrigger;
+  protected static boolean emergencyCollection;
+  protected static boolean awaitingAsyncCollection;
+  protected static boolean stacksPrepared;
+
+  private static boolean initialized = false;
+  private static boolean collectionTriggered;
+  @Entrypoint
+  private static int gcStatus = NOT_IN_GC; // shared variable
+
+  /** @return Is the memory management system initialized? */
+  public static boolean isInitialized() {
+    return initialized;
+  }
+
+  /**
+   * Has collection has triggered?
+   */
+  public static boolean isCollectionTriggered() {
+    return collectionTriggered;
+  }
+
+  /**
+   * Set that a collection has been triggered.
+   */
+  public static void setCollectionTriggered() {
+    collectionTriggered = true;
+  }
+
+  /**
+   * A collection has fully completed.  Clear the triggered flag.
+   */
+  public static void collectionComplete() {
+    collectionTriggered = false;
+  }
+
+  /**
+   * Return true if stacks have been prepared in this collection cycle.
+   *
+   * @return True if stacks have been prepared in this collection cycle.
+   */
+  public static boolean stacksPrepared() {
+    return stacksPrepared;
+  }
+  /**
+   * Return true if a collection is in progress.
+   *
+   * @return True if a collection is in progress.
+   */
+  public static boolean gcInProgress() {
+    return gcStatus != NOT_IN_GC;
+  }
+
+  /**
+   * Return true if a collection is in progress and past the preparatory stage.
+   *
+   * @return True if a collection is in progress and past the preparatory stage.
+   */
+  public static boolean gcInProgressProper() {
+    return gcStatus == GC_PROPER;
+  }
+
+  /**
+   * Sets the GC status.
+   *
+   * @param s The new GC status.
+   */
+  public static void setGCStatus(int s) {
+    if (gcStatus == NOT_IN_GC) {
+      /* From NOT_IN_GC to any phase */
+      stacksPrepared = false;
+      if (Stats.gatheringStats()) {
+        Stats.startGC();
+        VM.activePlan.global().printPreStats();
+      }
+    }
+    VM.memory.isync();
+    gcStatus = s;
+    VM.memory.sync();
+    if (gcStatus == NOT_IN_GC) {
+      /* From any phase to NOT_IN_GC */
+      if (Stats.gatheringStats()) {
+        Stats.endGC();
+        VM.activePlan.global().printPostStats();
+      }
+    }
+  }
+
+  /**
+   * Print out statistics at the start of a GC
+   */
+  public void printPreStats() {
+    if ((Options.verbose.getValue() == 1) ||
+        (Options.verbose.getValue() == 2)) {
+      Log.write("[GC "); Log.write(Stats.gcCount());
+      if (Options.verbose.getValue() == 1) {
+        Log.write(" Start ");
+        Plan.totalTime.printTotalSecs();
+        Log.write(" s");
+      } else {
+        Log.write(" Start ");
+        Plan.totalTime.printTotalMillis();
+        Log.write(" ms");
+      }
+      Log.write("   ");
+      Log.write(Conversions.pagesToKBytes(getPagesUsed()));
+      Log.write("KB ");
+      Log.flush();
+    }
+    if (Options.verbose.getValue() > 2) {
+      Log.write("Collection "); Log.write(Stats.gcCount());
+      Log.write(":        ");
+      printUsedPages();
+      Log.write("  Before Collection: ");
+      Space.printUsageMB();
+      if (Options.verbose.getValue() >= 4) {
+        Log.write("                     ");
+        Space.printUsagePages();
+      }
+      if (Options.verbose.getValue() >= 5) {
+        Space.printVMMap();
+      }
+    }
+  }
+
+  /**
+   * Print out statistics at the end of a GC
+   */
+  public final void printPostStats() {
+    if ((Options.verbose.getValue() == 1) ||
+        (Options.verbose.getValue() == 2)) {
+      Log.write("-> ");
+      Log.writeDec(Conversions.pagesToBytes(getPagesUsed()).toWord().rshl(10));
+      Log.write("KB   ");
+      if (Options.verbose.getValue() == 1) {
+        totalTime.printLast();
+        Log.writeln(" ms]");
+      } else {
+        Log.write("End ");
+        totalTime.printTotal();
+        Log.writeln(" ms]");
+      }
+    }
+    if (Options.verbose.getValue() > 2) {
+      Log.write("   After Collection: ");
+      Space.printUsageMB();
+      if (Options.verbose.getValue() >= 4) {
+        Log.write("                     ");
+        Space.printUsagePages();
+      }
+      if (Options.verbose.getValue() >= 5) {
+        Space.printVMMap();
+      }
+      Log.write("                     ");
+      printUsedPages();
+      Log.write("    Collection time: ");
+      totalTime.printLast();
+      Log.writeln(" ms");
+    }
+  }
+
+  public final void printUsedPages() {
+    Log.write("reserved = ");
+    Log.write(Conversions.pagesToMBytes(getPagesReserved()));
+    Log.write(" MB (");
+    Log.write(getPagesReserved());
+    Log.write(" pgs)");
+    Log.write("      total = ");
+    Log.write(Conversions.pagesToMBytes(getTotalPages()));
+    Log.write(" MB (");
+    Log.write(getTotalPages());
+    Log.write(" pgs)");
+    Log.writeln();
+  }
+
+  /**
+   * Set the collection trigger.
+   */
+  public static void setCollectionTrigger(int trigger) {
+    collectionTrigger = trigger;
+  }
+
+  /****************************************************************************
+   * Harness
+   */
+  protected static boolean insideHarness = false;
+
+  /**
+   * Generic hook to allow benchmarks to be harnessed.  A plan may use
+   * this to perform certain actions prior to the commencement of a
+   * benchmark, such as a full heap collection, turning on
+   * instrumentation, etc.  By default we do a full heap GC,
+   * and then start stats collection.
+   */
+  @Interruptible
+  public static void harnessBegin() {
+    // Save old values.
+    boolean oldFullHeap = Options.fullHeapSystemGC.getValue();
+    boolean oldIgnore = Options.ignoreSystemGC.getValue();
+
+    // Set desired values.
+    Options.fullHeapSystemGC.setValue(true);
+    Options.ignoreSystemGC.setValue(false);
+
+    // Trigger a full heap GC.
+    System.gc();
+
+    // Restore old values.
+    Options.ignoreSystemGC.setValue(oldIgnore);
+    Options.fullHeapSystemGC.setValue(oldFullHeap);
+
+    // Start statistics
+    insideHarness = true;
+    Stats.startAll();
+  }
+
+  /**
+   * Generic hook to allow benchmarks to be harnessed.  A plan may use
+   * this to perform certain actions after the completion of a
+   * benchmark, such as a full heap collection, turning off
+   * instrumentation, etc.  By default we stop all statistics objects
+   * and print their values.
+   */
+  @Interruptible
+  public static void harnessEnd()  {
+    Stats.stopAll();
+    insideHarness = false;
+  }
+
+  /****************************************************************************
+   * VM Accounting
+   */
+
+  /* Global accounting and static access */
+
+  /**
+   * Return the amount of <i>free memory</i>, in bytes (where free is
+   * defined as not in use).  Note that this may overstate the amount
+   * of <i>available memory</i>, which must account for unused memory
+   * that is held in reserve for copying, and therefore unavailable
+   * for allocation.
+   *
+   * @return The amount of <i>free memory</i>, in bytes (where free is
+   * defined as not in use).
+   */
+  public static Extent freeMemory() {
+    return totalMemory().minus(usedMemory());
+  }
+
+  /**
+   * Return the amount of <i>available memory</i>, in bytes.  Note
+   * that this accounts for unused memory that is held in reserve
+   * for copying, and therefore unavailable for allocation.
+   *
+   * @return The amount of <i>available memory</i>, in bytes.
+   */
+  public static Extent availableMemory() {
+    return totalMemory().minus(reservedMemory());
+  }
+
+  /**
+   * Return the amount of <i>memory in use</i>, in bytes.  Note that
+   * this excludes unused memory that is held in reserve for copying,
+   * and therefore unavailable for allocation.
+   *
+   * @return The amount of <i>memory in use</i>, in bytes.
+   */
+  public static Extent usedMemory() {
+    return Conversions.pagesToBytes(VM.activePlan.global().getPagesUsed());
+  }
+
+
+  /**
+   * Return the amount of <i>memory in use</i>, in bytes.  Note that
+   * this includes unused memory that is held in reserve for copying,
+   * and therefore unavailable for allocation.
+   *
+   * @return The amount of <i>memory in use</i>, in bytes.
+   */
+  public static Extent reservedMemory() {
+    return Conversions.pagesToBytes(VM.activePlan.global().getPagesReserved());
+  }
+
+  /**
+   * Return the total amount of memory managed to the memory
+   * management system, in bytes.
+   *
+   * @return The total amount of memory managed to the memory
+   * management system, in bytes.
+   */
+  public static Extent totalMemory() {
+    return HeapGrowthManager.getCurrentHeapSize();
+  }
+
+  /* Instance methods */
+
+  /**
+   * Return the total amount of memory managed to the memory
+   * management system, in pages.
+   *
+   * @return The total amount of memory managed to the memory
+   * management system, in pages.
+   */
+  public final int getTotalPages() {
+    return totalMemory().toWord().rshl(LOG_BYTES_IN_PAGE).toInt();
+  }
+
+  /**
+   * Return the number of pages available for allocation.
+   *
+   * @return The number of pages available for allocation.
+   */
+  public int getPagesAvail() {
+    return getTotalPages() - getPagesReserved();
+  }
+
+  /**
+   * Return the number of pages reserved for use given the pending
+   * allocation.  Sub-classes must override the getCopyReserve method,
+   * as the arithmetic here is fixed.
+   *
+   * @return The number of pages reserved given the pending
+   * allocation, including space reserved for copying.
+   */
+  public final int getPagesReserved() {
+    return getPagesUsed() + getCollectionReserve();
+  }
+
+  /**
+   * Return the number of pages reserved for collection.
+   * In most cases this is a copy reserve, all subclasses that
+   * manage a copying space must add the copying contribution.
+   *
+   * @return The number of pages reserved given the pending
+   * allocation, including space reserved for collection.
+   */
+  public int getCollectionReserve() {
+    return 0;
+  }
+
+  /**
+   * Return the number of pages reserved for use given the pending
+   * allocation.
+   *
+   * @return The number of pages reserved given the pending
+   * allocation, excluding space reserved for copying.
+   */
+  public int getPagesUsed() {
+    return loSpace.reservedPages() +
+           immortalSpace.reservedPages() + metaDataSpace.reservedPages() +
+           nonMovingSpace.reservedPages();
+  }
+
+  /**
+   * Calculate the number of pages a collection is required to free to satisfy
+   * outstanding allocation requests.
+   *
+   * @return the number of pages a collection is required to free to satisfy
+   * outstanding allocation requests.
+   */
+  public int getPagesRequired() {
+    return loSpace.requiredPages() +
+      metaDataSpace.requiredPages() + immortalSpace.requiredPages() +
+      nonMovingSpace.requiredPages();
+  }
+
+  /**
+   * The minimum number of pages a GC must have available after a collection
+   * for us to consider the collection successful.
+   */
+  public int getHeapFullThreshold() {
+    int threshold = (getTotalPages() * HEAP_FULL_PERCENTAGE) / 100;
+    if (threshold < HEAP_FULL_MINIMUM) threshold = HEAP_FULL_MINIMUM;
+    return threshold;
+  }
+
+  /**
+   * Return the number of metadata pages reserved for use given the pending
+   * allocation.
+   *
+   * @return The number of pages reserved given the pending
+   * allocation, excluding space reserved for copying.
+   */
+  public int getMetaDataPagesUsed() {
+    return metaDataSpace.reservedPages();
+  }
+
+  /**
+   * Return the cycle time at which this GC should complete.
+   *
+   * @return The time cap for this GC (i.e. the time by which it
+   * should complete).
+   */
+  public static long getTimeCap() {
+    return timeCap;
+  }
+
+  /****************************************************************************
+   * Internal read/write barriers.
+   */
+
+  /**
+   * Store an object reference
+   *
+   * @param slot The location of the reference
+   * @param value The value to store
+   */
+  @Inline
+  public void storeObjectReference(Address slot, ObjectReference value) {
+    slot.store(value);
+  }
+
+  /**
+   * Load an object reference
+   *
+   * @param slot The location of the reference
+   * @return the object reference loaded from slot
+   */
+  @Inline
+  public ObjectReference loadObjectReference(Address slot) {
+    return slot.loadObjectReference();
+  }
+
+  /****************************************************************************
+   * Collection.
+   */
+
+  /**
+   * This method is called periodically by the allocation subsystem
+   * (by default, each time a page is consumed), and provides the
+   * collector with an opportunity to collect.
+   *
+   * @param spaceFull Space request failed, must recover pages within 'space'.
+   * @param space The space that triggered the poll.
+   * @return true if a collection is required.
+   */
+  @LogicallyUninterruptible
+  public final boolean poll(boolean spaceFull, Space space) {
+    if (isCollectionTriggered()) {
+      if (space == metaDataSpace) {
+        /* This is not, in general, in a GC safe point. */
+        return false;
+      }
+      /* Someone else initiated a collection, we should join it */
+      logPoll(space, "Joining collection");
+      VM.collection.joinCollection();
+      return true;
+    }
+
+    if (collectionRequired(spaceFull)) {
+      if (space == metaDataSpace) {
+        /* In general we must not trigger a GC on metadata allocation since
+         * this is not, in general, in a GC safe point.  Instead we initiate
+         * an asynchronous GC, which will occur at the next safe point.
+         */
+        logPoll(space, "Asynchronous collection requested");
+        setAwaitingAsyncCollection();
+        return false;
+      }
+      logPoll(space, "Triggering collection");
+      VM.collection.triggerCollection(Collection.RESOURCE_GC_TRIGGER);
+      return true;
+    }
+
+    if (concurrentCollectionRequired()) {
+      logPoll(space, "Triggering collection");
+      VM.collection.triggerCollection(Collection.INTERNAL_PHASE_GC_TRIGGER);
+      return true;
+    }
+
+    return false;
+  }
+
+  /**
+   * Check whether an asynchronous collection is pending.<p>
+   *
+   * This is decoupled from the poll() mechanism because the
+   * triggering of asynchronous collections can trigger write
+   * barriers, which can trigger an asynchronous collection.  Thus, if
+   * the triggering were tightly coupled with the request to alloc()
+   * within the write buffer code, then inifinite regress could
+   * result.  There is no race condition in the following code since
+   * there is no harm in triggering the collection more than once,
+   * thus it is unsynchronized.
+   */
+  @Inline
+  public static void checkForAsyncCollection() {
+    if (awaitingAsyncCollection && VM.collection.noThreadsInGC()) {
+      awaitingAsyncCollection = false;
+      VM.collection.triggerAsyncCollection(Collection.RESOURCE_GC_TRIGGER);
+    }
+  }
+
+  /** Request an async GC */
+  protected static void setAwaitingAsyncCollection() {
+    awaitingAsyncCollection = true;
+  }
+
+  /**
+   * Log a message from within 'poll'
+   * @param space
+   * @param message
+   */
+  private void logPoll(Space space, String message) {
+    if (Options.verbose.getValue() >= 3) {
+      Log.write("  [POLL] ");
+      Log.write(space.getName());
+      Log.write(": ");
+      Log.writeln(message);
+    }
+  }
+
+  /**
+   * This method controls the triggering of a GC. It is called periodically
+   * during allocation. Returns true to trigger a collection.
+   *
+   * @param spaceFull Space request failed, must recover pages within 'space'.
+   * @return True if a collection is requested by the plan.
+   */
+  protected boolean collectionRequired(boolean spaceFull) {
+    boolean stressForceGC = stressTestGCRequired();
+    boolean heapFull = getPagesReserved() > getTotalPages();
+
+    return spaceFull || stressForceGC || heapFull;
+  }
+
+  /**
+   * This method controls the triggering of an atomic phase of a concurrent
+   * collection. It is called periodically during allocation.
+   *
+   * @return True if a collection is requested by the plan.
+   */
+  protected boolean concurrentCollectionRequired() {
+    return false;
+  }
+
+  /**
+   * Start GCspy server.
+   *
+   * @param port The port to listen on,
+   * @param wait Should we wait for a client to connect?
+   */
+  @Interruptible
+  public void startGCspyServer(int port, boolean wait) {
+    VM.assertions.fail("startGCspyServer called on non GCspy plan");
+  }
+
+  /**
+   * Can this object ever move.  Used by the VM to make decisions about
+   * whether it needs to copy IO buffers etc.
+   *
+   * @param object The object in question
+   * @return True if it is not possible that the object will ever move.
+   */
+  public boolean willNeverMove(ObjectReference object) {
+    if (!VM.activePlan.constraints().movesObjects())
+      return true;
+    if (Space.isInSpace(LOS, object))
+      return true;
+    if (Space.isInSpace(IMMORTAL, object))
+      return true;
+    if (Space.isInSpace(VM_SPACE, object))
+      return true;
+    if (Space.isInSpace(NON_MOVING, object))
+      return true;
+    if (USE_CODE_SPACE && Space.isInSpace(SMALL_CODE, object))
+      return true;
+    if (USE_CODE_SPACE && Space.isInSpace(LARGE_CODE, object))
+      return true;
+    /*
+     * Default to false- this preserves correctness over efficiency.
+     * Individual plans should override for non-moving spaces they define.
+     */
+    return false;
+  }
+
+  /****************************************************************************
+   * Support for logging bits (this is cross-cutting).
+   */
+
+  /**
+   * Return true if the specified object needs to be logged.
+   *
+   * @param src The object in question
+   * @return True if the object in question needs to be logged (remembered).
+   */
+  public static final boolean logRequired(ObjectReference src) {
+    int value = VM.objectModel.readAvailableByte(src);
+    return !((value & LOG_SET_MASK.toInt()) == 0);
+  }
+
+  /**
+   * Mark an object as logged.  Since duplicate logging does
+   * not raise any correctness issues, we do <i>not</i> worry
+   * about synchronization and allow threads to race to log the
+   * object, potentially including it twice (unlike reference
+   * counting where duplicates would lead to incorrect reference
+   * counts).
+   *
+   * @param object The object to be marked as logged
+   */
+  public static final void markAsLogged(ObjectReference object) {
+    int value = VM.objectModel.readAvailableByte(object);
+    VM.objectModel.writeAvailableByte(object, (byte) (value & LOG_CLEAR_MASK.toInt()));
+  }
+
+  /**
+   * Mark an object as unlogged.
+   *
+   * @param object The object to be marked as unlogged
+   */
+  public static final void markAsUnlogged(ObjectReference object) {
+    int value = VM.objectModel.readAvailableByte(object);
+    VM.objectModel.writeAvailableByte(object, (byte) (value | UNLOGGED_BIT.toInt()));
+  }
+
+  /****************************************************************************
+   * Specialized Methods
+   */
+
+  /**
+   * Register specialized methods.
+   */
+   @Interruptible
+  protected void registerSpecializedMethods() {
+  }
+
+  /**
+   * Get the specialized scan with the given id.
+   */
+  public final Class<?> getSpecializedScanClass(int id) {
+    return TransitiveClosure.getSpecializedScanClass(id);
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/PlanConstraints.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/PlanConstraints.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/PlanConstraints.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/PlanConstraints.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,92 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan;
+
+import org.mmtk.policy.SegregatedFreeListSpace;
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.Word;
+
+/**
+ * This class and its subclasses communicate to the host VM/Runtime
+ * any features of the selected plan that it needs to know.  This is
+ * separate from the main Plan/PlanLocal class in order to bypass any
+ * issues with ordering of static initialization.
+ */
+ at Uninterruptible public abstract class PlanConstraints {
+  /** @return True if this Plan requires write barriers. */
+  public boolean needsWriteBarrier() { return false; }
+
+  /** @return True of this Plan requires read barriers on reference types. */
+  public boolean needsReferenceTypeReadBarrier() { return false; }
+
+  /** @return True of this Plan requires read barriers. */
+  public boolean needsReadBarrier() { return false; }
+
+  /** @return True if this Plan requires static write barriers. */
+  public boolean needsStaticWriteBarrier() { return false;}
+
+  /** @return True if this Plan requires static read barriers. */
+  public boolean needsStaticReadBarrier() { return false; }
+
+  /** @return True if this Plan requires linear scanning. */
+  public boolean needsLinearScan() { return org.mmtk.utility.Constants.SUPPORT_CARD_SCANNING;}
+
+  /** @return True if this Plan does not support parallel collection. */
+  public boolean noParallelGC() { return false;}
+
+  /** @return True if this Plan moves objects. */
+  public boolean movesObjects() { return false;}
+
+  /** @return Size (in bytes) beyond which new regular objects must be allocated to the LOS */
+  public int maxNonLOSDefaultAllocBytes() { return org.mmtk.utility.Constants.MAX_INT;}
+
+  /** @return Size (in bytes) beyond which new non-moving objects must be allocated to the LOS */
+  public int maxNonLOSNonMovingAllocBytes() { return SegregatedFreeListSpace.MAX_FREELIST_OBJECT_BYTES;}
+
+  /** @return Size (in bytes) beyond which copied objects must be copied to the LOS */
+  public int maxNonLOSCopyBytes() { return org.mmtk.utility.Constants.MAX_INT;}
+
+  /** @return True if this object forwards objects <i>after</i>
+   * determining global object liveness (e.g. many compacting collectors). */
+  public boolean needsForwardAfterLiveness() { return false;}
+
+  /** @return Is this plan generational in nature. */
+  public boolean generational() { return false;}
+
+  /** @return The number of header bits that are required. */
+  public abstract int gcHeaderBits();
+
+  /** @return The number of header words that are required. */
+  public abstract int gcHeaderWords();
+
+  /** @return True if this plan contains GCspy. */
+  public boolean withGCspy() { return false; }
+
+  /** @return True if this plan contains GCTrace. */
+  public boolean generateGCTrace() { return false; }
+
+  /** @return The specialized scan methods required */
+  public int numSpecializedScans() { return 0; }
+
+  /** @return True if this plan requires concurrent worker threads */
+  public boolean needsConcurrentWorkers() { return false; }
+
+  /** @return True if this Plan requires a header bit for object logging */
+  public boolean needsLogBitInHeader() { return false; }
+
+  /** @return A bit which represents that a header is unlogged */
+  public Word unloggedBit() {return Word.zero(); }
+
+  /** @return A bit which represents that a header is unlogged */
+  public Word logSetBitMask() {return Word.zero(); }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/Simple.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/Simple.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/Simple.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/Simple.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,286 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan;
+
+import org.mmtk.policy.Space;
+import org.mmtk.utility.Constants;
+import org.mmtk.utility.Log;
+import org.mmtk.utility.options.*;
+import org.mmtk.utility.statistics.Timer;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This abstract class implements the core functionality for
+ * simple collectors.<p>
+ *
+ * This class defines the collection phases, and provides base
+ * level implementations of them.  Subclasses should provide
+ * implementations for the spaces that they introduce, and
+ * delegate up the class hierarchy.<p>
+ *
+ * For details of the split between global and thread-local operations
+ * @see org.mmtk.plan.Plan
+ */
+ at Uninterruptible
+public abstract class Simple extends Plan implements Constants {
+  /****************************************************************************
+   * Constants
+   */
+
+  /* Shared Timers */
+  private static final Timer refTypeTime = new Timer("refType", false, true);
+  private static final Timer scanTime = new Timer("scan", false, true);
+  private static final Timer finalizeTime = new Timer("finalize", false, true);
+
+  /* Phases */
+  public static final short SET_COLLECTION_KIND = Phase.createSimple("set-collection-kind", null);
+  public static final short INITIATE            = Phase.createSimple("initiate", null);
+  public static final short PREPARE             = Phase.createSimple("prepare");
+  public static final short PRECOPY             = Phase.createSimple("precopy");
+  public static final short PREPARE_STACKS      = Phase.createSimple("prepare-stacks", null);
+  public static final short STACK_ROOTS         = Phase.createSimple("stacks");
+  public static final short ROOTS               = Phase.createSimple("root");
+  public static final short CLOSURE             = Phase.createSimple("closure", scanTime);
+  public static final short SOFT_REFS           = Phase.createSimple("soft-ref", refTypeTime);
+  public static final short WEAK_REFS           = Phase.createSimple("weak-ref", refTypeTime);
+  public static final short FINALIZABLE         = Phase.createSimple("finalize", finalizeTime);
+  public static final short WEAK_TRACK_REFS     = Phase.createSimple("weak-track-ref", refTypeTime);
+  public static final short PHANTOM_REFS        = Phase.createSimple("phantom-ref", refTypeTime);
+  public static final short FORWARD             = Phase.createSimple("forward");
+  public static final short FORWARD_REFS        = Phase.createSimple("forward-ref", refTypeTime);
+  public static final short FORWARD_FINALIZABLE = Phase.createSimple("forward-finalize", finalizeTime);
+  public static final short RELEASE             = Phase.createSimple("release");
+  public static final short COMPLETE            = Phase.createSimple("complete", null);
+
+  /* Sanity placeholder */
+  public static final short PRE_SANITY_PLACEHOLDER  = Phase.createSimple("pre-sanity-placeholder", null);
+  public static final short POST_SANITY_PLACEHOLDER = Phase.createSimple("post-sanity-placeholder", null);
+
+  /* Sanity phases */
+  public static final short SANITY_SET_PREGC    = Phase.createSimple("sanity-setpre", null);
+  public static final short SANITY_SET_POSTGC   = Phase.createSimple("sanity-setpost", null);
+  public static final short SANITY_PREPARE      = Phase.createSimple("sanity-prepare", null);
+  public static final short SANITY_ROOTS        = Phase.createSimple("sanity-roots", null);
+  public static final short SANITY_COPY_ROOTS   = Phase.createSimple("sanity-copy-roots", null);
+  public static final short SANITY_BUILD_TABLE  = Phase.createSimple("sanity-build-table", null);
+  public static final short SANITY_CHECK_TABLE  = Phase.createSimple("sanity-check-table", null);
+  public static final short SANITY_RELEASE      = Phase.createSimple("sanity-release", null);
+
+  // CHECKSTYLE:OFF
+
+  /** Ensure stacks are ready to be scanned */
+  protected static final short prepareStacks = Phase.createComplex("prepare-stacks", null,
+      Phase.scheduleCollector  (PREPARE_STACKS),
+      Phase.scheduleMutator    (PREPARE_STACKS),
+      Phase.scheduleGlobal     (PREPARE_STACKS));
+
+  /** Trace and set up a sanity table */
+  protected static final short sanityBuildPhase = Phase.createComplex("sanity-build", null,
+      Phase.scheduleGlobal     (SANITY_PREPARE),
+      Phase.scheduleCollector  (SANITY_PREPARE),
+      Phase.scheduleComplex    (prepareStacks),
+      Phase.scheduleCollector  (SANITY_ROOTS),
+      Phase.scheduleGlobal     (SANITY_ROOTS),
+      Phase.scheduleCollector  (SANITY_COPY_ROOTS),
+      Phase.scheduleGlobal     (SANITY_BUILD_TABLE));
+
+  /** Validate a sanity table */
+  protected static final short sanityCheckPhase = Phase.createComplex("sanity-check", null,
+      Phase.scheduleGlobal     (SANITY_CHECK_TABLE),
+      Phase.scheduleCollector  (SANITY_RELEASE),
+      Phase.scheduleGlobal     (SANITY_RELEASE));
+
+  /** Start the collection, including preparation for any collected spaces. */
+  protected static final short initPhase = Phase.createComplex("init",
+      Phase.scheduleGlobal     (SET_COLLECTION_KIND),
+      Phase.scheduleGlobal     (INITIATE),
+      Phase.schedulePlaceholder(PRE_SANITY_PLACEHOLDER));
+
+  /**
+   * Perform the initial determination of liveness from the roots.
+   */
+  protected static final short rootClosurePhase = Phase.createComplex("initial-closure", null,
+      Phase.scheduleMutator    (PREPARE),
+      Phase.scheduleGlobal     (PREPARE),
+      Phase.scheduleCollector  (PREPARE),
+      Phase.scheduleComplex    (prepareStacks),
+      Phase.scheduleCollector  (PRECOPY),
+      Phase.scheduleCollector  (STACK_ROOTS),
+      Phase.scheduleCollector  (ROOTS),
+      Phase.scheduleGlobal     (ROOTS),
+      Phase.scheduleGlobal     (CLOSURE),
+      Phase.scheduleCollector  (CLOSURE));
+
+  /**
+   * Complete closure including reference types and finalizable objects.
+   */
+  protected static final short refTypeClosurePhase = Phase.createComplex("refType-closure", null,
+      Phase.scheduleCollector  (SOFT_REFS),
+      Phase.scheduleGlobal     (CLOSURE),
+      Phase.scheduleCollector  (CLOSURE),
+      Phase.scheduleCollector  (WEAK_REFS),
+      Phase.scheduleCollector  (FINALIZABLE),
+      Phase.scheduleGlobal     (CLOSURE),
+      Phase.scheduleCollector  (CLOSURE),
+      Phase.schedulePlaceholder(WEAK_TRACK_REFS),
+      Phase.scheduleCollector  (PHANTOM_REFS));
+
+  /**
+   * Ensure that all references in the system are correct.
+   */
+  protected static final short forwardPhase = Phase.createComplex("forward-all", null,
+      /* Finish up */
+      Phase.schedulePlaceholder(FORWARD),
+      Phase.scheduleCollector  (FORWARD_REFS),
+      Phase.scheduleCollector  (FORWARD_FINALIZABLE));
+
+  /**
+   * Complete closure including reference types and finalizable objects.
+   */
+  protected static final short completeClosurePhase = Phase.createComplex("release", null,
+      Phase.scheduleMutator    (RELEASE),
+      Phase.scheduleCollector  (RELEASE),
+      Phase.scheduleGlobal     (RELEASE));
+
+
+  /**
+   * The collection scheme - this is a small tree of complex phases.
+   */
+  protected static final short finishPhase = Phase.createComplex("finish",
+      Phase.schedulePlaceholder(POST_SANITY_PLACEHOLDER),
+      Phase.scheduleCollector  (COMPLETE),
+      Phase.scheduleGlobal     (COMPLETE));
+
+  /**
+   * This is the phase that is executed to perform a collection.
+   */
+  public short collection = Phase.createComplex("collection", null,
+      Phase.scheduleComplex(initPhase),
+      Phase.scheduleComplex(rootClosurePhase),
+      Phase.scheduleComplex(refTypeClosurePhase),
+      Phase.scheduleComplex(forwardPhase),
+      Phase.scheduleComplex(completeClosurePhase),
+      Phase.scheduleComplex(finishPhase));
+
+  // CHECKSTYLE:ON
+
+  /**
+   * The current collection attempt.
+   */
+  protected int collectionAttempt;
+
+  /****************************************************************************
+   * Collection
+   */
+
+  /**
+   * Perform a (global) collection phase.
+   *
+   * @param phaseId The unique of the phase to perform.
+   */
+  @Inline
+  public void collectionPhase(short phaseId) {
+    if (phaseId == SET_COLLECTION_KIND) {
+      requiredAtStart = getPagesRequired();
+      collectionAttempt = VM.collection.maximumCollectionAttempt();
+      emergencyCollection = lastCollectionWasExhaustive() && collectionAttempt > 1;
+      if (collectionAttempt > MAX_COLLECTION_ATTEMPTS) {
+        VM.assertions.fail("Too many collection attempts. Suspect plan is not setting FullHeap flag");
+      }
+      if (emergencyCollection) {
+        if (Options.verbose.getValue() >= 1) Log.write("[Emergency]");
+        forceFullHeapCollection();
+      }
+      return;
+    }
+
+    if (phaseId == INITIATE) {
+      setGCStatus(GC_PREPARE);
+      return;
+    }
+
+    if (phaseId == PREPARE_STACKS) {
+      stacksPrepared = true;
+      return;
+    }
+
+    if (phaseId == PREPARE) {
+      loSpace.prepare(true);
+      nonMovingSpace.prepare(true);
+      if (USE_CODE_SPACE) {
+        smallCodeSpace.prepare(true);
+        largeCodeSpace.prepare(true);
+      }
+      immortalSpace.prepare();
+      VM.memory.globalPrepareVMSpace();
+      return;
+    }
+
+    if (phaseId == ROOTS) {
+      VM.scanning.resetThreadCounter();
+      setGCStatus(GC_PROPER);
+      return;
+    }
+
+    if (phaseId == RELEASE) {
+      loSpace.release(true);
+      nonMovingSpace.release();
+      if (USE_CODE_SPACE) {
+        smallCodeSpace.release();
+        largeCodeSpace.release(true);
+      }
+      immortalSpace.release();
+      VM.memory.globalReleaseVMSpace();
+      return;
+    }
+
+    if (phaseId == COMPLETE) {
+      setGCStatus(NOT_IN_GC);
+      Space.clearAllAllocationFailed();
+      awaitingAsyncCollection = false;
+      return;
+    }
+
+    if (Options.sanityCheck.getValue() && sanityChecker.collectionPhase(phaseId)) {
+      return;
+    }
+
+    Log.write("Global phase "); Log.write(Phase.getName(phaseId));
+    Log.writeln(" not handled.");
+    VM.assertions.fail("Global phase not handled!");
+  }
+
+  /**
+   * Replace a scheduled phase. Used for example to replace a placeholder.
+   *
+   * @param oldScheduledPhase The scheduled phase to replace.
+   * @param newScheduledPhase The new scheduled phase.
+   */
+  public void replacePhase(int oldScheduledPhase, int newScheduledPhase) {
+    ComplexPhase cp = (ComplexPhase)Phase.getPhase(collection);
+    cp.replacePhase(oldScheduledPhase, newScheduledPhase);
+  }
+
+  /**
+   * Replace a placeholder phase.
+   *
+   * @param placeHolderPhase The placeholder phase
+   * @param newScheduledPhase The new scheduled phase.
+   */
+  public void replacePlaceholderPhase(short placeHolderPhase, int newScheduledPhase) {
+    ComplexPhase cp = (ComplexPhase)Phase.getPhase(collection);
+    cp.replacePhase(Phase.schedulePlaceholder(placeHolderPhase), newScheduledPhase);
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleCollector.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleCollector.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleCollector.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleCollector.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,174 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan;
+
+import org.mmtk.utility.Log;
+import org.mmtk.utility.options.Options;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class (and its sub-classes) implement <i>per-collector thread</i>
+ * behavior and state.
+ *
+ * MMTk assumes that the VM instantiates instances of CollectorContext
+ * in thread local storage (TLS) for each thread participating in
+ * collection.  Accesses to this state are therefore assumed to be
+ * low-cost during mutator time.<p>
+ *
+ * @see CollectorContext
+ */
+ at Uninterruptible
+public abstract class SimpleCollector extends CollectorContext {
+
+  /****************************************************************************
+   * Instance fields
+   */
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a per-collector collection phase.
+   *
+   * @param phaseId The unique phase identifier
+   * @param primary Should this thread be used to execute any single-threaded
+   * local operations?
+   */
+  @Inline
+  public void collectionPhase(short phaseId, boolean primary) {
+    if (phaseId == Simple.PREPARE_STACKS) {
+      if (!Plan.stacksPrepared()) {
+        VM.collection.prepareCollector(this);
+      }
+      return;
+    }
+
+    if (phaseId == Simple.PREPARE) {
+      // Nothing to do
+      return;
+    }
+
+    if (phaseId == Simple.PRECOPY) {
+      if (VM.activePlan.constraints().movesObjects()) {
+        VM.scanning.preCopyGCInstances(getCurrentTrace());
+      }
+      return;
+    }
+
+    if (phaseId == Simple.STACK_ROOTS) {
+      VM.scanning.computeThreadRoots(getCurrentTrace());
+      return;
+    }
+
+    if (phaseId == Simple.ROOTS) {
+      VM.scanning.computeGlobalRoots(getCurrentTrace());
+      VM.scanning.computeStaticRoots(getCurrentTrace());
+      if (Plan.SCAN_BOOT_IMAGE) {
+        VM.scanning.computeBootImageRoots(getCurrentTrace());
+      }
+      return;
+    }
+
+    if (phaseId == Simple.SOFT_REFS) {
+      if (primary) {
+        if (Options.noReferenceTypes.getValue())
+          VM.softReferences.clear();
+        else
+          VM.softReferences.scan(getCurrentTrace(),global().isCurrentGCNursery());
+      }
+      return;
+    }
+
+    if (phaseId == Simple.WEAK_REFS) {
+      if (primary) {
+        if (Options.noReferenceTypes.getValue())
+          VM.weakReferences.clear();
+        else
+          VM.weakReferences.scan(getCurrentTrace(),global().isCurrentGCNursery());
+      }
+      return;
+    }
+
+    if (phaseId == Simple.FINALIZABLE) {
+      if (primary) {
+        if (Options.noFinalizer.getValue())
+          VM.finalizableProcessor.clear();
+        else
+          VM.finalizableProcessor.scan(getCurrentTrace(),global().isCurrentGCNursery());
+      }
+      return;
+    }
+
+    if (phaseId == Simple.PHANTOM_REFS) {
+      if (primary) {
+        if (Options.noReferenceTypes.getValue())
+          VM.phantomReferences.clear();
+        else
+          VM.phantomReferences.scan(getCurrentTrace(),global().isCurrentGCNursery());
+      }
+      return;
+    }
+
+    if (phaseId == Simple.FORWARD_REFS) {
+      if (primary && !Options.noReferenceTypes.getValue() &&
+          VM.activePlan.constraints().needsForwardAfterLiveness()) {
+        VM.softReferences.forward(getCurrentTrace(),global().isCurrentGCNursery());
+        VM.weakReferences.forward(getCurrentTrace(),global().isCurrentGCNursery());
+        VM.phantomReferences.forward(getCurrentTrace(),global().isCurrentGCNursery());
+      }
+      return;
+    }
+
+    if (phaseId == Simple.FORWARD_FINALIZABLE) {
+      if (primary && !Options.noFinalizer.getValue() &&
+          VM.activePlan.constraints().needsForwardAfterLiveness()) {
+        VM.finalizableProcessor.forward(getCurrentTrace(),global().isCurrentGCNursery());
+      }
+      return;
+    }
+
+    if (phaseId == Simple.COMPLETE) {
+      // Nothing to do
+      return;
+    }
+
+    if (phaseId == Simple.RELEASE) {
+      // Nothing to do
+      return;
+    }
+
+    if (Options.sanityCheck.getValue() && sanityLocal.collectionPhase(phaseId, primary)) {
+      return;
+    }
+
+    Log.write("Per-collector phase "); Log.write(Phase.getName(phaseId));
+    Log.writeln(" not handled.");
+    VM.assertions.fail("Per-collector phase not handled!");
+  }
+
+  /****************************************************************************
+   *
+   * Miscellaneous.
+   */
+
+  /** @return The active global plan as a <code>Simple</code> instance. */
+  @Inline
+  private static Simple global() {
+    return (Simple) VM.activePlan.global();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleConstraints.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleConstraints.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleConstraints.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleConstraints.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,22 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * Constraints specific to simple collectors.
+ */
+ at Uninterruptible
+public abstract class SimpleConstraints extends PlanConstraints {
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleMutator.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleMutator.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleMutator.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimpleMutator.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,73 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan;
+
+import org.mmtk.utility.Log;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class (and its sub-classes) implement <i>per-mutator thread</i>
+ * behavior and state.
+ *
+ * MMTk assumes that the VM instantiates instances of MutatorContext
+ * in thread local storage (TLS) for each application thread. Accesses
+ * to this state are therefore assumed to be low-cost during mutator
+ * time.<p>
+ *
+ * @see MutatorContext
+ */
+ at Uninterruptible
+public abstract class SimpleMutator extends MutatorContext {
+
+  /****************************************************************************
+   *
+   * Collection.
+   */
+
+  /**
+   * Perform a per-mutator collection phase.   This is executed by
+   * one collector thread on behalf of a mutator thread.
+   *
+   * @param phaseId The unique phase identifier
+   * @param primary Should this thread be used to execute any single-threaded
+   * local operations?
+   */
+  @Inline
+  public void collectionPhase(short phaseId, boolean primary) {
+    if (phaseId == Simple.PREPARE_STACKS) {
+      if (!Plan.stacksPrepared()) {
+        VM.collection.prepareMutator(this);
+      }
+      flushRememberedSets();
+      return;
+    }
+
+    if (phaseId == Simple.PREPARE) {
+      los.prepare(true);
+      VM.memory.collectorPrepareVMSpace();
+      return;
+    }
+
+    if (phaseId == Simple.RELEASE) {
+      los.release(true);
+      VM.memory.collectorReleaseVMSpace();
+      return;
+    }
+
+    Log.write("Per-mutator phase \""); Phase.getPhase(phaseId).logPhase();
+    Log.writeln("\" not handled.");
+    VM.assertions.fail("Per-mutator phase not handled!");
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimplePhase.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimplePhase.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimplePhase.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/SimplePhase.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,60 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan;
+
+import org.mmtk.utility.Constants;
+import org.mmtk.utility.statistics.Timer;
+import org.mmtk.utility.Log;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * Phases of a garbage collection.
+ *
+ */
+ at Uninterruptible
+public final class SimplePhase extends Phase
+  implements Constants {
+  /****************************************************************************
+   * Instance fields
+   */
+
+  /**
+   * Construct a phase given just a name and a global/local ordering
+   * scheme.
+   *
+   * @param name The name of the phase
+   */
+  protected SimplePhase(String name) {
+    super(name);
+  }
+
+  /**
+   * Construct a phase, re-using a specified timer.
+   *
+   * @param name Display name of the phase
+   * @param timer Timer for this phase to contribute to
+   */
+  protected SimplePhase(String name, Timer timer) {
+    super(name, timer);
+  }
+
+  /**
+   * Display a phase for debugging purposes.
+   */
+  protected void logPhase() {
+    Log.write("SimplePhase(");
+    Log.write(name);
+    Log.write(")");
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorld.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorld.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorld.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorld.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,69 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan;
+
+import org.mmtk.utility.Log;
+import org.mmtk.utility.options.Options;
+import org.vmmagic.pragma.*;
+
+/**
+ * This abstract class implements the core functionality for
+ * stop-the-world collectors.  Stop-the-world collectors should
+ * inherit from this class.<p>
+ *
+ * This class defines the collection phases, and provides base
+ * level implementations of them.  Subclasses should provide
+ * implementations for the spaces that they introduce, and
+ * delegate up the class hierarchy.<p>
+ *
+ * For details of the split between global and thread-local operations
+ * @see org.mmtk.plan.Plan
+ */
+ at Uninterruptible
+public abstract class StopTheWorld extends Simple {
+
+  // CHECKSTYLE:OFF
+
+  /** Build and validate a sanity table */
+  protected static final short preSanityPhase = Phase.createComplex("pre-sanity", null,
+      Phase.scheduleGlobal     (SANITY_SET_PREGC),
+      Phase.scheduleComplex    (sanityBuildPhase),
+      Phase.scheduleComplex    (sanityCheckPhase));
+
+  /** Build and validate a sanity table */
+  protected static final short postSanityPhase = Phase.createComplex("post-sanity", null,
+      Phase.scheduleGlobal     (SANITY_SET_POSTGC),
+      Phase.scheduleComplex    (sanityBuildPhase),
+      Phase.scheduleComplex    (sanityCheckPhase));
+
+  // CHECKSTYLE:ON
+
+  /****************************************************************************
+   * Collection
+   */
+
+  /**
+   * The boot method is called early in the boot process before any
+   * allocation.
+   */
+  @Interruptible
+  public void postBoot() {
+    super.postBoot();
+
+    if (Options.sanityCheck.getValue()) {
+      Log.writeln("Collection sanity checking enabled.");
+      replacePhase(Phase.schedulePlaceholder(PRE_SANITY_PLACEHOLDER),  Phase.scheduleComplex(preSanityPhase));
+      replacePhase(Phase.schedulePlaceholder(POST_SANITY_PLACEHOLDER), Phase.scheduleComplex(postSanityPhase));
+    }
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldCollector.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldCollector.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldCollector.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldCollector.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,66 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan;
+
+import org.mmtk.vm.VM;
+import org.vmmagic.pragma.*;
+
+/**
+ * This class (and its sub-classes) implement <i>per-collector thread</i>
+ * behavior and state.
+ *
+ * MMTk assumes that the VM instantiates instances of CollectorContext
+ * in thread local storage (TLS) for each thread participating in
+ * collection.  Accesses to this state are therefore assumed to be
+ * low-cost during mutator time.<p>
+ *
+ * @see CollectorContext
+ */
+ at Uninterruptible
+public abstract class StopTheWorldCollector extends SimpleCollector {
+
+  /****************************************************************************
+   *
+   * Collection.
+   */
+
+  /** Perform garbage collection */
+  public void collect() {
+    Phase.beginNewPhaseStack(Phase.scheduleComplex(global().collection));
+  }
+
+  /** Perform some concurrent garbage collection */
+  public final void concurrentCollect() {
+    VM.assertions.fail("concurrentCollect called on StopTheWorld collector");
+  }
+
+  /**
+   * Perform some concurrent collection work.
+   *
+   * @param phaseId The unique phase identifier
+   */
+  public void concurrentCollectionPhase(short phaseId) {
+    VM.assertions.fail("concurrentCollectionPhase triggered on StopTheWorld collector");
+  }
+
+  /****************************************************************************
+   *
+   * Miscellaneous.
+   */
+
+  /** @return The active global plan as a <code>StopTheWorld</code> instance. */
+  @Inline
+  private static StopTheWorld global() {
+    return (StopTheWorld) VM.activePlan.global();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldConstraints.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldConstraints.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldConstraints.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldConstraints.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,22 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * Constraints specific to Stop-the-world collectors.
+ */
+ at Uninterruptible
+public abstract class StopTheWorldConstraints extends SimpleConstraints {
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldMutator.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldMutator.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldMutator.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/StopTheWorldMutator.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,30 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class (and its sub-classes) implement <i>per-mutator thread</i>
+ * behavior and state.
+ *
+ * MMTk assumes that the VM instantiates instances of MutatorContext
+ * in thread local storage (TLS) for each application thread. Accesses
+ * to this state are therefore assumed to be low-cost during mutator
+ * time.<p>
+ *
+ * @see MutatorContext
+ */
+ at Uninterruptible
+public abstract class StopTheWorldMutator extends SimpleMutator {
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/Trace.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/Trace.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/Trace.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/Trace.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,72 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan;
+
+import org.mmtk.utility.Constants;
+import org.mmtk.utility.deque.SharedDeque;
+import org.mmtk.policy.RawPageSpace;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This abstract class implements the core functionality for a transitive
+ * closure over the heap.  This class holds the global state, TraceLocal
+ * and its super-classes handle per-thread state.
+ */
+ at Uninterruptible
+public class Trace implements Constants {
+
+  // Global pools for load-balancing deques
+  final SharedDeque valuePool;
+  final SharedDeque rootLocationPool;
+
+  /**
+   * Constructor
+   */
+  public Trace(RawPageSpace metaDataSpace) {
+    valuePool = new SharedDeque("valuePool",metaDataSpace, 1);
+    rootLocationPool = new SharedDeque("rootLocations", metaDataSpace, 1);
+  }
+
+  /**
+   * Prepare for a new collection pass.
+   */
+  public void prepareNonBlocking() {
+    valuePool.prepareNonBlocking();
+    rootLocationPool.prepareNonBlocking();
+  }
+
+  /**
+   * Prepare for a new collection pass.
+   * All active GC threads take part.
+   */
+  public void prepare() {
+    valuePool.prepare();
+    rootLocationPool.prepareNonBlocking();
+  }
+
+  /**
+   * Release resources after completing a collection pass.
+   */
+  public void release() {
+    valuePool.reset();
+    rootLocationPool.reset();
+  }
+
+  /**
+   * Is there any work outstanding in this trace. That is are there any pages in the pools.
+   */
+  public boolean hasWork() {
+    return (valuePool.enqueuedPages() + rootLocationPool.enqueuedPages()) > 0;
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/TraceLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/TraceLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/TraceLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/TraceLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,571 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan;
+
+import org.mmtk.policy.Space;
+import org.mmtk.utility.Constants;
+import org.mmtk.utility.Log;
+import org.mmtk.utility.deque.*;
+import org.mmtk.utility.options.Options;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This abstract class and its global counterpart implement the core
+ * functionality for a transitive closure over the heap graph. This class
+ * specifically implements the unsynchronized thread-local component
+ * (ie the 'fast path') of the trace mechanism.<p>
+ *
+ * @see org.mmtk.plan.Plan
+ * @see org.mmtk.plan.Trace
+ */
+ at Uninterruptible
+public abstract class TraceLocal extends TransitiveClosure implements Constants {
+  /****************************************************************************
+   *
+   * Instance variables
+   */
+  /* gray object */
+  protected final ObjectReferenceDeque values;
+  /* delayed root slots */
+  protected final AddressDeque rootLocations;
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * Constructor
+   *
+   * @param trace The global trace class to use.
+   */
+  public TraceLocal(Trace trace) {
+    this(-1, trace);
+  }
+
+  /**
+   * Constructor
+   *
+   * @param specializedScan The specialized scan id.
+   * @param trace The global trace class to use.
+   */
+  public TraceLocal(int specializedScan, Trace trace) {
+    super(specializedScan);
+    values = new ObjectReferenceDeque("value", trace.valuePool);
+    rootLocations = new AddressDeque("roots", trace.rootLocationPool);
+  }
+
+  /****************************************************************************
+   *
+   * Internally visible Object processing and tracing
+   */
+
+  /**
+   * Trace a reference during GC.  This involves determining which
+   * collection policy applies and calling the appropriate
+   * <code>trace</code> method.
+   *
+   * @param source The source of the reference.
+   * @param slot The location containing the object reference to be
+   *        traced.  The object reference is <i>NOT</i> an interior pointer.
+   */
+  @Inline
+  public final void processEdge(ObjectReference source, Address slot) {
+    ObjectReference object = VM.activePlan.global().loadObjectReference(slot);
+    ObjectReference newObject = traceObject(object, false);
+    VM.activePlan.global().storeObjectReference(slot, newObject);
+  }
+
+  /**
+   * Report a root edge to be processed during GC. As the given reference
+   * may theoretically point to an object required during root scanning,
+   * the caller has requested processing be delayed.
+   *
+   * NOTE: delayed roots are assumed to be raw.
+   *
+   * @param slot The location containing the object reference to be
+   * traced.  The object reference is <i>NOT</i> an interior pointer.
+   */
+  @Inline
+  public final void reportDelayedRootEdge(Address slot) {
+    rootLocations.push(slot);
+  }
+
+  /**
+   * Trace a reference during GC.  This involves determining which
+   * collection policy applies and calling the appropriate
+   * <code>trace</code> method.
+   *
+   * @param slot The location containing the object reference to be
+   * traced.  The object reference is <i>NOT</i> an interior pointer.
+   * @param untraced True if <code>objLoc</code> is an untraced root.
+   */
+  @Inline
+  public final void processRootEdge(Address slot, boolean untraced) {
+    ObjectReference object;
+    if (untraced) object = slot.loadObjectReference();
+    else     object = VM.activePlan.global().loadObjectReference(slot);
+    ObjectReference newObject = traceObject(object, true);
+    if (untraced) slot.store(newObject);
+    else     VM.activePlan.global().storeObjectReference(slot, newObject);
+  }
+
+  /**
+   * Trace a reference during GC.  This involves determining which
+   * collection policy applies and calling the appropriate
+   * <code>trace</code> method.
+   *
+   * @param target The object the interior edge points within.
+   * @param slot The location of the interior edge.
+   * @param root True if this is a root edge.
+   */
+  public final void processInteriorEdge(ObjectReference target, Address slot, boolean root) {
+    Address interiorRef = slot.loadAddress();
+    Offset offset = interiorRef.diff(target.toAddress());
+    ObjectReference newTarget = traceObject(target, root);
+    if (VM.VERIFY_ASSERTIONS) {
+      if (offset.sLT(Offset.zero()) || offset.sGT(Offset.fromIntSignExtend(1<<24))) {
+        // There is probably no object this large
+        Log.writeln("ERROR: Suspiciously large delta to interior pointer");
+        Log.write("       object base = "); Log.writeln(target);
+        Log.write("       interior reference = "); Log.writeln(interiorRef);
+        Log.write("       delta = "); Log.writeln(offset);
+        VM.assertions._assert(false);
+      }
+    }
+    slot.store(newTarget.toAddress().plus(offset));
+  }
+
+  /**
+   * Collectors that move objects <b>must</b> override this method.
+   * It performs the deferred scanning of objects which are forwarded
+   * during bootstrap of each copying collection.  Because of the
+   * complexities of the collection bootstrap (such objects are
+   * generally themselves gc-critical), the forwarding and scanning of
+   * the objects must be dislocated.  It is an error for a non-moving
+   * collector to call this method.
+   *
+   * @param object The forwarded object to be scanned
+   */
+  @Inline
+  protected void scanObject(ObjectReference object) {
+    if (specializedScan >= 0) {
+      VM.scanning.specializedScanObject(specializedScan, this, object);
+    } else {
+      VM.scanning.scanObject(this, object);
+    }
+  }
+
+
+  /****************************************************************************
+   *
+   * Externally visible Object processing and tracing
+   */
+
+  /**
+   * Add a gray object
+   *
+   * @param object The object to be enqueued
+   */
+  @Inline
+  public final void processNode(ObjectReference object) {
+    values.push(object);
+  }
+
+  /**
+   * Flush the local buffers of all deques.
+   */
+  public final void flush() {
+    values.flushLocal();
+    rootLocations.flushLocal();
+  }
+
+  /**
+   * Is the specified object live?
+   *
+   * @param object The object.
+   * @return True if the object is live.
+   */
+  @Inline
+  public boolean isLive(ObjectReference object) {
+    Space space = Space.getSpaceForObject(object);
+    if (space == Plan.loSpace)
+      return Plan.loSpace.isLive(object);
+    else if (space == Plan.nonMovingSpace)
+      return Plan.nonMovingSpace.isLive(object);
+    else if (Plan.USE_CODE_SPACE && space == Plan.smallCodeSpace)
+      return Plan.smallCodeSpace.isLive(object);
+    else if (Plan.USE_CODE_SPACE && space == Plan.largeCodeSpace)
+      return Plan.largeCodeSpace.isLive(object);
+    else if (space == null) {
+      if (VM.VERIFY_ASSERTIONS) {
+        Log.write("space failure: "); Log.writeln(object);
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Is the specified object reachable? Used for GC Trace
+   *
+   * @param object The object.
+   * @return True if the object is live.
+   */
+  @Inline
+  public boolean isReachable(ObjectReference object) {
+    return Space.getSpaceForObject(object).isReachable(object);
+  }
+
+  /**
+   * Is the specified referent of a reference type object live?
+   *
+   * @param object The object.
+   * @return True if the reference object is live.
+   */
+  @Inline
+  public boolean isReferentLive(ObjectReference object) {
+    return isLive(object);
+  }
+
+  /**
+   * This method is the core method during the trace of the object graph.
+   * The role of this method is to:
+   *
+   * 1. Ensure the traced object is not collected.
+   * 2. If this is the first visit to the object enqueue it to be scanned.
+   * 3. Return the forwarded reference to the object.
+   *
+   * @param object The object to be traced.
+   * @return The new reference to the same object instance.
+   */
+  @Inline
+  public ObjectReference traceObject(ObjectReference object) {
+    if (Space.isInSpace(Plan.VM_SPACE, object))
+      return (Plan.SCAN_BOOT_IMAGE) ? object : Plan.vmSpace.traceObject(this, object);
+    if (Space.isInSpace(Plan.IMMORTAL, object))
+      return Plan.immortalSpace.traceObject(this, object);
+    if (Space.isInSpace(Plan.LOS, object))
+      return Plan.loSpace.traceObject(this, object);
+    if (Space.isInSpace(Plan.NON_MOVING, object))
+      return Plan.nonMovingSpace.traceObject(this, object);
+    if (Plan.USE_CODE_SPACE && Space.isInSpace(Plan.SMALL_CODE, object))
+      return Plan.smallCodeSpace.traceObject(this, object);
+    if (Plan.USE_CODE_SPACE && Space.isInSpace(Plan.LARGE_CODE, object))
+      return Plan.largeCodeSpace.traceObject(this, object);
+    if (VM.VERIFY_ASSERTIONS) {
+      Log.write("Failing object => "); Log.writeln(object);
+      Space.printVMMap();
+      VM.assertions._assert(false, "No special case for space in traceObject");
+    }
+    return ObjectReference.nullReference();
+  }
+
+
+  /**
+   * Ensure that this object will not move for the rest of the GC.
+   *
+   * @param object The object that must not move
+   * @return The new object, guaranteed stable for the rest of the GC.
+   */
+  @Inline
+  public ObjectReference precopyObject(ObjectReference object) {
+    return traceObject(object);
+  }
+
+  /**
+   * This method traces an object with knowledge of the fact that object
+   * is a root or not. In simple collectors the fact it is a root is not
+   * important so this is the default implementation given here.
+   *
+   * @param object The object to be traced.
+   * @return The new reference to the same object instance.
+   */
+  @Inline
+  public ObjectReference traceObject(ObjectReference object, boolean root) {
+    return traceObject(object);
+  }
+
+  /**
+   * Ensure that the referenced object will not move from this point through
+   * to the end of the collection. This can involve forwarding the object
+   * if necessary.
+   *
+   * <i>Non-copying collectors do nothing, copying collectors must
+   * override this method in each of their trace classes.</i>
+   *
+   * @param object The object that must not move during the collection.
+   * @return True If the object will not move during collection
+   */
+  public boolean willNotMoveInCurrentCollection(ObjectReference object) {
+    if (!VM.activePlan.constraints().movesObjects())
+      return true;
+    if (Space.isInSpace(Plan.LOS, object))
+      return true;
+    if (Space.isInSpace(Plan.IMMORTAL, object))
+      return true;
+    if (Space.isInSpace(Plan.VM_SPACE, object))
+      return true;
+    if (Space.isInSpace(Plan.NON_MOVING, object))
+      return true;
+    if (Plan.USE_CODE_SPACE && Space.isInSpace(Plan.SMALL_CODE, object))
+      return true;
+    if (Plan.USE_CODE_SPACE && Space.isInSpace(Plan.LARGE_CODE, object))
+      return true;
+    if (VM.VERIFY_ASSERTIONS)
+      VM.assertions._assert(false, "willNotMove not defined properly in subclass");
+    return false;
+  }
+
+  /**
+   * If a Finalizable object has moved, return the new location.
+   *
+   * @param object The object which may have been forwarded.
+   * @return The new location of <code>object</code>.
+   */
+  public ObjectReference getForwardedFinalizable(ObjectReference object) {
+    return getForwardedReference(object);
+  }
+
+  /**
+   * If the reference object (from a Reference Type) has object has moved,
+   * return the new location.
+   *
+   * @param object The object which may have been forwarded.
+   * @return The new location of <code>object</code>.
+   */
+  @Inline
+  public ObjectReference getForwardedReferent(ObjectReference object) {
+    return getForwardedReference(object);
+  }
+
+  /**
+   * If the Reference Type object has moved, return the new location.
+   *
+   * @param object The object which may have been forwarded.
+   * @return The new location of <code>object</code>.
+   */
+  @Inline
+  public ObjectReference getForwardedReferenceType(ObjectReference object) {
+    return getForwardedReference(object);
+  }
+
+  /**
+   * If the referenced object has moved, return the new location.
+   *
+   * Some copying collectors will need to override this method.
+   *
+   * @param object The object which may have been forwarded.
+   * @return The new location of <code>object</code>.
+   */
+  @Inline
+  public ObjectReference getForwardedReference(ObjectReference object) {
+    return traceObject(object);
+  }
+
+  /**
+   * Make alive a referent object that is known not to be live
+   * (isLive is false). This is used by the ReferenceProcessor.
+   *
+   * <i>For many collectors these semantics relfect those of
+   * <code>traceObject</code>, which is implemented here.  Other
+   * collectors must override this method.</i>
+   *
+   * @param object The object which is to be made alive.
+   * @return The possibly forwarded address of the object.
+   */
+  @Inline
+  public ObjectReference retainReferent(ObjectReference object) {
+    return traceObject(object);
+  }
+
+  /**
+   * An object is unreachable and is about to be added to the
+   * finalizable queue.  The collector must ensure the object is not
+   * collected (despite being otherwise unreachable), and should
+   * return its forwarded address if keeping the object alive involves
+   * forwarding. This is only ever called once for an object.<p>
+   *
+   * <i>For many collectors these semantics relfect those of
+   * <code>traceObject</code>, which is implemented here.  Other
+   * collectors must override this method.</i>
+   *
+   * @param object The object which may have been forwarded.
+   * @return The forwarded value for <code>object</code>.  <i>In this
+   * case return <code>object</code>, copying collectors must override
+   *         this method.
+   */
+  public ObjectReference retainForFinalize(ObjectReference object) {
+    return traceObject(object);
+  }
+
+  /**
+   * Return true if an object is ready to move to the finalizable
+   * queue, i.e. it has no regular references to it.  This method may
+   * (and in some cases is) be overridden by subclasses. If this method
+   * returns true then it can be assumed that retainForFinalize will be
+   * called during the current collection.
+   *
+   * <i>For many collectors these semantics relfect those of
+   * <code>isLive</code>, which is implemented here.  Other
+   * collectors must override this method.</i>
+   *
+   * @param object The object being queried.
+   * @return <code>true</code> if the object has no regular references
+   * to it.
+   */
+  public boolean readyToFinalize(ObjectReference object) {
+    return !isLive(object);
+  }
+
+  /****************************************************************************
+   *
+   * Collection
+   *
+   * Important notes:
+   *   . Global actions are executed by only one thread
+   *   . Thread-local actions are executed by all threads
+   *   . The following order is guaranteed by BasePlan, with each
+   *     separated by a synchronization barrier.
+   *      1. globalPrepare()
+   *      2. threadLocalPrepare()
+   *      3. threadLocalRelease()
+   *      4. globalRelease()
+   */
+  public void prepare() {
+    // Nothing to do
+  }
+
+  public void release() {
+    values.reset();
+    rootLocations.reset();
+  }
+
+  /**
+   * Process any roots for which processing was delayed.
+   */
+  @Inline
+  public void processRoots() {
+    logMessage(5, "processing delayed root objects");
+    while (!rootLocations.isEmpty()) {
+      processRootEdge(rootLocations.pop(), true);
+    }
+  }
+
+  /**
+   * Finishing processing all GC work.  This method iterates until all work queues
+   * are empty.
+   */
+  @Inline
+  public void completeTrace() {
+    logMessage(4, "Processing GC in parallel");
+    if (!rootLocations.isEmpty()) {
+      processRoots();
+    }
+    logMessage(5, "processing gray objects");
+    assertMutatorRemsetsFlushed();
+    do {
+      while (!values.isEmpty()) {
+        ObjectReference v = values.pop();
+        scanObject(v);
+      }
+      processRememberedSets();
+    } while (!values.isEmpty());
+    assertMutatorRemsetsFlushed();
+  }
+
+  /**
+   * Process GC work until either complete or workLimit
+   * units of work are completed.
+   *
+   * @param workLimit The maximum units of work to perform.
+   * @return True if all work was completed within workLimit.
+   */
+  @Inline
+  public boolean incrementalTrace(int workLimit) {
+    logMessage(4, "Continuing GC in parallel (incremental)");
+    logMessage(5, "processing gray objects");
+    int units = 0;
+    do {
+      while (!values.isEmpty() && units < workLimit) {
+        ObjectReference v = values.pop();
+        scanObject(v);
+        units++;
+      }
+    } while (!values.isEmpty() && units < workLimit);
+    return values.isEmpty();
+  }
+
+  /**
+   * Flush any remembered sets pertaining to the current collection.
+   * Non-generational collectors do nothing.
+   */
+
+  protected void processRememberedSets() {}
+
+  /**
+   * Assert that the remsets have been flushed.  This is critical to
+   * correctness.  We need to maintain the invariant that remset entries
+   * do not accrue during GC.  If the host JVM generates barrier entires
+   * it is its own responsibility to ensure that they are flushed before
+   * returning to MMTk.
+   */
+  private void assertMutatorRemsetsFlushed() {
+    /* FIXME: PNT
+    if (VM.VERIFY_ASSERTIONS) {
+      for (int m = 0; m < VM.activePlan.mutatorCount(); m++) {
+        VM.activePlan.mutator(m).assertRemsetsFlushed();
+      }
+    }
+    */
+  }
+
+  /**
+   * This method logs a message with preprended thread id, if the
+   * verbosity level is greater or equal to the passed level.
+   *
+   * @param minVerbose The required verbosity level
+   * @param message The message to display
+   */
+  @Inline
+  protected final void logMessage(int minVerbose, String message) {
+    if (Options.verbose.getValue() >= minVerbose) {
+      Log.prependThreadId();
+      Log.write("    ");
+      Log.writeln(message);
+    }
+  }
+
+  /**
+   * Given a slot (ie the address of an ObjectReference), ensure that the
+   * referent will not move for the rest of the GC. This is achieved by
+   * calling the precopyObject method.
+   *
+   * @param slot The slot to check
+   * @param untraced Is this is an untraced reference?
+   */
+  @Inline
+  public final void processPrecopyEdge(Address slot, boolean untraced) {
+    ObjectReference child;
+    if (untraced) child = slot.loadObjectReference();
+    else          child = VM.activePlan.global().loadObjectReference(slot);
+    if (!child.isNull()) {
+      child = precopyObject(child);
+      if (untraced) slot.store(child);
+      else          VM.activePlan.global().storeObjectReference(slot, child);
+    }
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/TraceWriteBuffer.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/TraceWriteBuffer.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/TraceWriteBuffer.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/TraceWriteBuffer.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,72 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan;
+
+import org.mmtk.utility.deque.WriteBuffer;
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class is used to push values in one direction during a trace. It
+ * was designed for use in mutators that use write barriers to push
+ * work to collector threads during concurrent tracing.
+ *
+ * @see org.mmtk.plan.TraceLocal
+ */
+ at Uninterruptible
+public final class TraceWriteBuffer extends TransitiveClosure {
+  /****************************************************************************
+   *
+   * Instance variables
+   */
+  private final WriteBuffer buffer;
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * Constructor
+   *
+   * @param trace The global trace class to use.
+   */
+  public TraceWriteBuffer(Trace trace) {
+    buffer = new WriteBuffer(trace.valuePool);
+  }
+
+  /**
+   * Flush the buffer to the trace.
+   */
+  public void flush() {
+    buffer.flushLocal();
+  }
+
+
+  /**
+   * @return True if the buffer is flushed.
+   */
+  public boolean isFlushed() {
+    return buffer.isFlushed();
+  }
+
+  /**
+   * Enqueue an object during a trace.
+   *
+   * @param object The object to enqueue
+   */
+  @Inline
+  public void processNode(ObjectReference object) {
+    buffer.insert(object.toAddress());
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/TransitiveClosure.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/TransitiveClosure.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/TransitiveClosure.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/TransitiveClosure.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,94 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan;
+
+import org.mmtk.vm.VM;
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This abstract class is the fundamental mechanism for performing a
+ * transitive closure over an object graph.<p>
+ *
+ * Some mechanisms only operate on nodes or edges, but due to limitations
+ * of inheritance we have combined these two here.
+ *
+ * @see org.mmtk.plan.TraceLocal
+ */
+ at Uninterruptible
+public abstract class TransitiveClosure {
+
+  /** Database of specialized scan classes. */
+  private static final Class<?>[] specializedScans = new Class[VM.activePlan.constraints().numSpecializedScans()];
+
+  /**
+   * A transitive closure has been created that is designed to work with a specialized scan method. We must
+   * register it here so the specializer can return the class when queried.
+   *
+   * @param id The method id to register.
+   * @param specializedScanClass The class to register.
+   */
+  @Interruptible
+  public static synchronized void registerSpecializedScan(int id, Class<?> specializedScanClass) {
+    specializedScans[id] = specializedScanClass;
+  }
+
+  /**
+   * Get the specialized scan with the given id.
+   */
+  public static Class<?> getSpecializedScanClass(int id) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(specializedScans[id] != null);
+    return specializedScans[id];
+  }
+
+  /** The specialized scan identifier */
+  protected final int specializedScan;
+
+  /**
+   * Constructor
+   */
+  protected TransitiveClosure() {
+    this(-1);
+  }
+
+  /**
+   * Constructor
+   *
+   * @param specializedScan The specialized scan for this trace.
+   */
+  protected TransitiveClosure(int specializedScan) {
+    this.specializedScan = specializedScan;
+    if (specializedScan >= 0) {
+      if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(getClass() == getSpecializedScanClass(specializedScan));
+    }
+  }
+
+  /**
+   * Trace an edge during GC.
+   *
+   * @param source The source of the reference.
+   * @param slot The location containing the object reference.
+   */
+  public void processEdge(ObjectReference source, Address slot) {
+    VM.assertions.fail("processEdge not implemented.");
+  }
+
+  /**
+   * Trace a node during GC.
+   *
+   * @param object The object to be processed.
+   */
+  public void processNode(ObjectReference object) {
+    VM.assertions.fail("processNode not implemented.");
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMS.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMS.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMS.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMS.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,204 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.copyms;
+
+import org.mmtk.plan.*;
+import org.mmtk.policy.CopySpace;
+import org.mmtk.policy.MarkSweepSpace;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.heap.VMRequest;
+import org.mmtk.utility.options.Options;
+import org.mmtk.utility.sanitychecker.SanityChecker;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.ObjectReference;
+
+/**
+ * This class implements the global state of a full-heap collector
+ * with a copying nursery and mark-sweep mature space.  Unlike a full
+ * generational collector, there is no write barrier, no remembered set, and
+ * every collection is full-heap.
+ *
+ * All plans make a clear distinction between <i>global</i> and
+ * <i>thread-local</i> activities, and divides global and local state
+ * into separate class hierarchies.  Global activities must be
+ * synchronized, whereas no synchronization is required for
+ * thread-local activities.  There is a single instance of Plan (or the
+ * appropriate sub-class), and a 1:1 mapping of PlanLocal to "kernel
+ * threads" (aka CPUs).  Thus instance
+ * methods of PlanLocal allow fast, unsychronized access to functions such as
+ * allocation and collection.
+ *
+ * The global instance defines and manages static resources
+ * (such as memory and virtual memory resources).  This mapping of threads to
+ * instances is crucial to understanding the correctness and
+ * performance properties of MMTk plans.
+ */
+ at Uninterruptible
+public class CopyMS extends StopTheWorld {
+
+  /****************************************************************************
+   * Constants
+   */
+
+  /****************************************************************************
+   * Class variables
+   */
+  public static final CopySpace nurserySpace = new CopySpace("nursery", DEFAULT_POLL_FREQUENCY, false, VMRequest.create(0.15f, true));
+  public static final MarkSweepSpace msSpace = new MarkSweepSpace("ms", DEFAULT_POLL_FREQUENCY, VMRequest.create());
+
+  public static final int NURSERY = nurserySpace.getDescriptor();
+  public static final int MARK_SWEEP = msSpace.getDescriptor();
+
+  public static final int ALLOC_NURSERY = ALLOC_DEFAULT;
+  public static final int ALLOC_MS = StopTheWorld.ALLOCATORS + 1;
+
+  public static final int SCAN_COPYMS = 0;
+
+  /****************************************************************************
+   * Instance variables
+   */
+
+  public final Trace trace;
+
+  /**
+   * Constructor.
+ */
+  public CopyMS() {
+    trace = new Trace(metaDataSpace);
+  }
+
+
+  /*****************************************************************************
+   * Collection
+   */
+
+  /**
+   * Perform a (global) collection phase.
+   *
+   * @param phaseId Collection phase to execute.
+   */
+  @Inline
+  public final void collectionPhase(short phaseId) {
+    if (phaseId == PREPARE) {
+      super.collectionPhase(phaseId);
+      trace.prepare();
+      msSpace.prepare(true);
+      nurserySpace.prepare(true);
+      return;
+    }
+    if (phaseId == CLOSURE) {
+      trace.prepare();
+      return;
+    }
+    if (phaseId == RELEASE) {
+      trace.release();
+      msSpace.release();
+      nurserySpace.release();
+      super.collectionPhase(phaseId);
+      return;
+    }
+
+    super.collectionPhase(phaseId);
+  }
+
+  /**
+   * This method controls the triggering of a GC. It is called periodically
+   * during allocation. Returns true to trigger a collection.
+   *
+   * @param spaceFull Space request failed, must recover pages within 'space'.
+   * @return True if a collection is requested by the plan.
+   */
+  public final boolean collectionRequired(boolean spaceFull) {
+    boolean nurseryFull = nurserySpace.reservedPages() > Options.nurserySize.getMaxNursery();
+
+    return super.collectionRequired(spaceFull) || nurseryFull;
+  }
+
+  /*****************************************************************************
+   *
+   * Accounting
+   */
+
+  /**
+   * Return the number of pages reserved for use given the pending
+   * allocation.
+   *
+   * @return The number of pages reserved given the pending
+   * allocation, excluding space reserved for copying.
+   */
+  public int getPagesUsed() {
+    return super.getPagesUsed() +
+      msSpace.reservedPages() +
+      nurserySpace.reservedPages();
+  }
+
+  /**
+   * Return the number of pages reserved for collection.
+   * For mark sweep this is a fixed fraction of total pages.
+   *
+   * @return The number of pages reserved given the pending
+   * allocation, including space reserved for collection.
+   */
+  public int getCollectionReserve() {
+    return nurserySpace.reservedPages() + super.getCollectionReserve();
+  }
+
+  /**
+   * @return The number of pages available for allocation, <i>assuming
+   * all future allocation is to the nursery</i>.
+   */
+  public final int getPagesAvail() {
+    return (getTotalPages() - getPagesReserved()) >> 1;
+  }
+
+  /**
+   * Calculate the number of pages a collection is required to free to satisfy
+   * outstanding allocation requests.
+   *
+   * @return the number of pages a collection is required to free to satisfy
+   * outstanding allocation requests.
+   */
+  public int getPagesRequired() {
+    return super.getPagesRequired() + msSpace.requiredPages() +
+      (nurserySpace.requiredPages() << 1);
+  }
+
+  /**
+   * Return the expected reference count. For non-reference counting
+   * collectors this becomes a true/false relationship.
+   *
+   * @param object The object to check.
+   * @param sanityRootRC The number of root references to the object.
+   * @return The expected (root excluded) reference count.
+   */
+  public int sanityExpectedRC(ObjectReference object, int sanityRootRC) {
+    Space space = Space.getSpaceForObject(object);
+
+    // Nursery
+    if (space == CopyMS.nurserySpace) {
+      return SanityChecker.DEAD;
+    }
+
+    return space.isReachable(object) ? SanityChecker.ALIVE : SanityChecker.DEAD;
+  }
+
+  /**
+   * Register specialized methods.
+   */
+  @Interruptible
+  protected void registerSpecializedMethods() {
+    TransitiveClosure.registerSpecializedScan(SCAN_COPYMS, CopyMSTraceLocal.class);
+    super.registerSpecializedMethods();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSCollector.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSCollector.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSCollector.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSCollector.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,159 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.copyms;
+
+import org.mmtk.plan.*;
+import org.mmtk.policy.LargeObjectLocal;
+import org.mmtk.policy.MarkSweepLocal;
+import org.mmtk.utility.alloc.Allocator;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements <i>per-collector thread</i> behavior
+ * and state for the <i>CopyMS</i> plan.<p>
+ *
+ * Specifically, this class defines <i>CopyMS</i>
+ * collection behavior (through <code>trace</code> and
+ * the <code>collectionPhase</code> method), and
+ * collection-time allocation into the mature space.
+ *
+ * @see CopyMS
+ * @see CopyMSMutator
+ * @see StopTheWorldCollector
+ * @see CollectorContext
+ */
+ at Uninterruptible
+public class CopyMSCollector extends StopTheWorldCollector {
+
+  /****************************************************************************
+   * Instance fields
+   */
+
+  private MarkSweepLocal mature;
+  private CopyMSTraceLocal trace;
+
+  protected final LargeObjectLocal los;
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * Create a new (local) instance.
+   */
+  public CopyMSCollector() {
+    los = new LargeObjectLocal(Plan.loSpace);
+    mature = new MarkSweepLocal(CopyMS.msSpace);
+    trace = new CopyMSTraceLocal(global().trace);
+ }
+
+  /****************************************************************************
+   *
+   * Collection-time allocation
+   */
+
+  /**
+   * Allocate space for copying an object (this method <i>does not</i>
+   * copy the object, it only allocates space)
+   *
+   * @param original A reference to the original object
+   * @param bytes The size of the space to be allocated (in bytes)
+   * @param align The requested alignment.
+   * @param offset The alignment offset.
+   * @return The address of the first byte of the allocated region
+   */
+  @Inline
+  public final Address allocCopy(ObjectReference original, int bytes,
+      int align, int offset, int allocator) {
+    if (allocator == Plan.ALLOC_LOS) {
+      if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Allocator.getMaximumAlignedSize(bytes, align) > Plan.MAX_NON_LOS_COPY_BYTES);
+      return los.alloc(bytes, align, offset);
+    } else {
+      if (VM.VERIFY_ASSERTIONS) {
+        VM.assertions._assert(bytes <= Plan.MAX_NON_LOS_COPY_BYTES);
+        VM.assertions._assert(allocator == CopyMS.ALLOC_MS);
+      }
+      return mature.alloc(bytes, align, offset);
+    }
+  }
+
+  /**
+   * Perform any post-copy actions.
+   *
+   * @param object The newly allocated object
+   * @param typeRef the type reference for the instance being created
+   * @param bytes The size of the space to be allocated (in bytes)
+   */
+  @Inline
+  public final void postCopy(ObjectReference object, ObjectReference typeRef,
+      int bytes, int allocator) {
+    if (allocator == Plan.ALLOC_LOS)
+      Plan.loSpace.initializeHeader(object, false);
+    else
+      CopyMS.msSpace.postCopy(object, true);
+  }
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a per-collector collection phase.
+   *
+   * @param phaseId The collection phase to perform
+   * @param primary Use this thread for single-threaded local activities.
+   */
+  @Inline
+  public final void collectionPhase(short phaseId, boolean primary) {
+    if (phaseId == CopyMS.PREPARE) {
+      super.collectionPhase(phaseId, primary);
+      mature.prepare();
+      trace.prepare();
+      return;
+    }
+
+    if (phaseId == CopyMS.CLOSURE) {
+      trace.completeTrace();
+      return;
+    }
+
+    if (phaseId == CopyMS.RELEASE) {
+      mature.release();
+      trace.release();
+      super.collectionPhase(phaseId, primary);
+      return;
+    }
+
+    super.collectionPhase(phaseId, primary);
+  }
+
+  /****************************************************************************
+   *
+   * Miscellaneous
+   */
+
+  /** @return the active global plan as an <code>MS</code> instance. */
+  @Inline
+  private static CopyMS global() {
+    return (CopyMS) VM.activePlan.global();
+  }
+
+  /** @return The current trace instance. */
+  public final TraceLocal getCurrentTrace() { return trace; }
+
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSConstraints.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSConstraints.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSConstraints.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSConstraints.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,41 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.copyms;
+
+import org.mmtk.plan.StopTheWorldConstraints;
+
+import org.mmtk.policy.CopySpace;
+import org.mmtk.policy.SegregatedFreeListSpace;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class and its subclasses communicate to the host VM/Runtime
+ * any features of the selected plan that it needs to know.  This is
+ * separate from the main Plan/PlanLocal class in order to bypass any
+ * issues with ordering of static initialization.
+ */
+ at Uninterruptible
+public class CopyMSConstraints extends StopTheWorldConstraints {
+
+  @Override
+  public int gcHeaderBits() { return CopySpace.LOCAL_GC_BITS_REQUIRED; }
+  @Override
+  public int gcHeaderWords() { return CopySpace.GC_HEADER_WORDS_REQUIRED; }
+  @Override
+  public int numSpecializedScans() { return 1; }
+  @Override
+  public boolean movesObjects() { return true; }
+  @Override
+  public int maxNonLOSCopyBytes() { return SegregatedFreeListSpace.MAX_FREELIST_OBJECT_BYTES;}
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSMutator.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSMutator.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSMutator.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSMutator.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,163 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.copyms;
+
+import org.mmtk.plan.StopTheWorldMutator;
+import org.mmtk.policy.CopyLocal;
+import org.mmtk.policy.MarkSweepLocal;
+import org.mmtk.policy.Space;
+
+import org.mmtk.utility.alloc.Allocator;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements <i>per-mutator thread</i> behavior
+ * and state for the <i>CopyMS</i> plan.<p>
+ *
+ * Specifically, this class defines <i>CopyMS</i> mutator-time
+ * allocation into the nursery and mature space (through pre-tenuring).
+ * Per-mutator thread collection semantics are also defined (flushing
+ * and restoring per-mutator allocator state).
+ *
+ * @see CopyMS
+ * @see CopyMSCollector
+ * @see org.mmtk.plan.StopTheWorldMutator
+ * @see org.mmtk.plan.MutatorContext
+ */
+ at Uninterruptible
+public class CopyMSMutator extends StopTheWorldMutator {
+
+  /****************************************************************************
+   * Instance fields
+   */
+
+  private final MarkSweepLocal mature;
+  private final CopyLocal nursery;
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * Constructor
+   */
+  public CopyMSMutator() {
+    mature = new MarkSweepLocal(CopyMS.msSpace);
+    nursery = new CopyLocal(CopyMS.nurserySpace);
+  }
+
+  /****************************************************************************
+   *
+   * Mutator-time allocation
+   */
+
+  /**
+   * Allocate memory for an object. This class handles the default allocator
+   * from the mark sweep space, and delegates everything else to the
+   * superclass.
+   *
+   * @param bytes The number of bytes required for the object.
+   * @param align Required alignment for the object.
+   * @param offset Offset associated with the alignment.
+   * @param allocator The allocator associated with this request.
+   * @return The low address of the allocated memory.
+   */
+  @Inline
+  public Address alloc(int bytes, int align, int offset, int allocator, int site) {
+    if (allocator == CopyMS.ALLOC_DEFAULT)
+      return nursery.alloc(bytes, align, offset);
+    if (allocator == CopyMS.ALLOC_MS)
+      return mature.alloc(bytes, align, offset);
+
+    return super.alloc(bytes, align, offset, allocator, site);
+  }
+
+  /**
+   * Perform post-allocation actions.  Initialize the object header for
+   * objects in the mark-sweep space, and delegate to the superclass for
+   * other objects.
+   *
+   * @param ref The newly allocated object
+   * @param typeRef the type reference for the instance being created
+   * @param bytes The size of the space to be allocated (in bytes)
+   * @param allocator The allocator number to be used for this allocation
+   */
+  @SuppressWarnings({"UnnecessaryReturnStatement"})
+  @Inline
+  public void postAlloc(ObjectReference ref, ObjectReference typeRef,
+      int bytes, int allocator) {
+    if (allocator == CopyMS.ALLOC_DEFAULT)
+      return;
+    else if (allocator == CopyMS.ALLOC_MS)
+      CopyMS.msSpace.initializeHeader(ref, true);
+    else
+      super.postAlloc(ref, typeRef, bytes, allocator);
+  }
+
+  /**
+   * Return the allocator instance associated with a space
+   * <code>space</code>, for this plan instance.
+   *
+   * @param space The space for which the allocator instance is desired.
+   * @return The allocator instance associated with this plan instance
+   * which is allocating into <code>space</code>, or <code>null</code>
+   * if no appropriate allocator can be established.
+   */
+  public Allocator getAllocatorFromSpace(Space space) {
+    if (space == CopyMS.nurserySpace) return nursery;
+    if (space == CopyMS.msSpace) return mature;
+    return super.getAllocatorFromSpace(space);
+  }
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a per-mutator collection phase.
+   *
+   * @param phaseId The collection phase to perform
+   * @param primary Use this thread for single-threaded local activities.
+   */
+  @Inline
+  public final void collectionPhase(short phaseId, boolean primary) {
+    if (phaseId == CopyMS.PREPARE) {
+      super.collectionPhase(phaseId, primary);
+      mature.prepare();
+      return;
+    }
+
+    if (phaseId == CopyMS.RELEASE) {
+      nursery.reset();
+      mature.release();
+      super.collectionPhase(phaseId, primary);
+      return;
+    }
+
+    super.collectionPhase(phaseId, primary);
+  }
+
+  /**
+   * Flush mutator context, in response to a requestMutatorFlush.
+   * Also called by the default implementation of deinitMutator.
+   */
+  @Override
+  public void flush() {
+    super.flush();
+    mature.flush();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSTraceLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSTraceLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSTraceLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/copyms/CopyMSTraceLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,111 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.copyms;
+
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.plan.Trace;
+import org.mmtk.policy.Space;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements the thread-local functionality for a
+ * transitive closure over a coping/mark-sweep hybrid collector.
+ */
+ at Uninterruptible
+public final class CopyMSTraceLocal extends TraceLocal {
+
+  /**
+   * Constructor
+   */
+  public CopyMSTraceLocal(Trace trace) {
+    super(CopyMS.SCAN_COPYMS, trace);
+  }
+
+  /****************************************************************************
+   *
+   * Externally visible Object processing and tracing
+   */
+
+  /**
+   * Is the specified object reachable?
+   *
+   * @param object The object.
+   * @return True if the object is live.
+   */
+  @Override
+  public boolean isLive(ObjectReference object) {
+    if (object.isNull()) return false;
+    if (Space.isInSpace(CopyMS.NURSERY, object)) {
+      return CopyMS.nurserySpace.isLive(object);
+    }
+    if (Space.isInSpace(CopyMS.MARK_SWEEP, object)) {
+      return CopyMS.msSpace.isLive(object);
+    }
+    return super.isLive(object);
+  }
+
+  /**
+   * This method is the core method during the trace of the object graph.
+   * The role of this method is to:
+   *
+   * 1. Ensure the traced object is not collected.
+   * 2. If this is the first visit to the object enqueue it to be scanned.
+   * 3. Return the forwarded reference to the object.
+   *
+   * In this instance, we refer objects in the mark-sweep space to the
+   * msSpace for tracing, and defer to the superclass for all others.
+   *
+   * @param object The object to be traced.
+   * @return The new reference to the same object instance.
+   */
+  @Inline
+  @Override
+  public ObjectReference traceObject(ObjectReference object) {
+    if (object.isNull()) return object;
+    if (Space.isInSpace(CopyMS.NURSERY, object))
+      return CopyMS.nurserySpace.traceObject(this, object, CopyMS.ALLOC_MS);
+    if (Space.isInSpace(CopyMS.MARK_SWEEP, object))
+      return CopyMS.msSpace.traceObject(this, object);
+    return super.traceObject(object);
+  }
+
+
+  /**
+   * Ensure that this object will not move for the rest of the GC.
+   *
+   * @param object The object that must not move
+   * @return The new object, guaranteed stable for the rest of the GC.
+   */
+  @Inline
+  @Override
+  public ObjectReference precopyObject(ObjectReference object) {
+    if (object.isNull()) return object;
+    else if (Space.isInSpace(CopyMS.NURSERY, object))
+      return CopyMS.nurserySpace.traceObject(this, object, CopyMS.ALLOC_MS);
+    else
+      return object;
+  }
+
+  /**
+   * Will this object move from this point on, during the current collection ?
+   *
+   * @param object The object to query.
+   * @return True if the object will not move during this collection.
+   */
+  @Override
+  public boolean willNotMoveInCurrentCollection(ObjectReference object) {
+    return !Space.isInSpace(CopyMS.NURSERY, object);
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/Gen.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/Gen.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/Gen.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/Gen.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,468 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.generational;
+
+import org.mmtk.plan.*;
+import org.mmtk.policy.CopySpace;
+import org.mmtk.policy.Space;
+
+import org.mmtk.utility.deque.*;
+import org.mmtk.utility.heap.Map;
+import org.mmtk.utility.heap.VMRequest;
+import org.mmtk.utility.Log;
+import org.mmtk.utility.options.Options;
+import org.mmtk.utility.sanitychecker.SanityChecker;
+import org.mmtk.utility.statistics.*;
+
+import org.mmtk.vm.Collection;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This abstract class implements the core functionality of generic
+ * two-generationa copying collectors.  Nursery collections occur when
+ * either the heap is full or the nursery is full.  The nursery size
+ * is determined by an optional command line argument.  If undefined,
+ * the nursery size is "infinite", so nursery collections only occur
+ * when the heap is full (this is known as a flexible-sized nursery
+ * collector).  Thus both fixed and flexible nursery sizes are
+ * supported.  Full heap collections occur when the nursery size has
+ * dropped to a statically defined threshold,
+ * <code>NURSERY_THRESHOLD</code><p>
+ *
+ * See also Plan.java for general comments on local vs global plan
+ * classes.
+ */
+ at Uninterruptible
+public abstract class Gen extends StopTheWorld {
+
+  /*****************************************************************************
+   *
+   * Constants
+   */
+  protected static final float SURVIVAL_ESTIMATE = 0.8f; // est yield
+  protected static final float MATURE_FRACTION = 0.5f; // est yield
+  private static final float WORST_CASE_COPY_EXPANSION = 1.5f; // worst case for addition of one word overhead due to address based hashing
+  public static final boolean IGNORE_REMSETS = false;
+  public static final boolean USE_STATIC_WRITE_BARRIER = false;
+  public static final boolean USE_OBJECT_BARRIER_FOR_AASTORE = false; // choose between slot and object barriers
+  public static final boolean USE_OBJECT_BARRIER_FOR_PUTFIELD = false; // choose between slot and object barriers
+  public static final boolean USE_OBJECT_BARRIER = USE_OBJECT_BARRIER_FOR_AASTORE || USE_OBJECT_BARRIER_FOR_PUTFIELD;
+  private static final boolean USE_DISCONTIGUOUS_NURSERY = false;
+
+  // Allocators
+  public static final int ALLOC_NURSERY        = ALLOC_DEFAULT;
+  public static final int ALLOC_MATURE         = StopTheWorld.ALLOCATORS + 1;
+  public static final int ALLOC_MATURE_MINORGC = StopTheWorld.ALLOCATORS + 2;
+  public static final int ALLOC_MATURE_MAJORGC = StopTheWorld.ALLOCATORS + 3;
+
+  public static final int SCAN_NURSERY = 0;
+  public static final int SCAN_MATURE  = 1;
+
+  /*****************************************************************************
+   *
+   * Class fields
+   */
+
+  /* Statistics */
+  protected static final BooleanCounter fullHeap = new BooleanCounter("majorGC", true, true);
+  private static final Timer fullHeapTime = new Timer("majorGCTime", false, true);
+  protected static final EventCounter wbFast;
+  protected static final EventCounter wbSlow;
+  public static final SizeCounter nurseryMark;
+  public static final SizeCounter nurseryCons;
+
+  /** The nursery space is where all new objects are allocated by default */
+  private static final VMRequest vmRequest = USE_DISCONTIGUOUS_NURSERY ? VMRequest.create() : VMRequest.create(0.15f, true);
+  public static final CopySpace nurserySpace = new CopySpace("nursery", DEFAULT_POLL_FREQUENCY, false, vmRequest);
+
+  public static final int NURSERY = nurserySpace.getDescriptor();
+  private static final Address NURSERY_START = nurserySpace.getStart();
+  protected static final int MAX_NURSERY_ALLOC_BYTES = USE_DISCONTIGUOUS_NURSERY ? org.mmtk.utility.Constants.MAX_INT : nurserySpace.getExtent().toInt();
+
+  /*****************************************************************************
+   *
+   * Instance fields
+   */
+  /* status fields */
+  public boolean gcFullHeap = false;
+  public boolean nextGCFullHeap = false;
+
+  /* The trace object */
+  public final Trace nurseryTrace = new Trace(metaDataSpace);
+
+  /**
+   * Remset pools
+   */
+  public final SharedDeque modbufPool = new SharedDeque("modBufs",metaDataSpace, 1);
+  public final SharedDeque remsetPool = new SharedDeque("remSets",metaDataSpace, 1);
+  public final SharedDeque arrayRemsetPool = new SharedDeque("arrayRemSets",metaDataSpace, 2);
+
+  /*
+   * Class initializer
+   */
+  static {
+    if (GATHER_WRITE_BARRIER_STATS) {
+      wbFast = new EventCounter("wbFast");
+      wbSlow = new EventCounter("wbSlow");
+    } else {
+      wbFast = null;
+      wbSlow = null;
+    }
+    if (Stats.GATHER_MARK_CONS_STATS) {
+      nurseryMark = new SizeCounter("nurseryMark", true, true);
+      nurseryCons = new SizeCounter("nurseryCons", true, true);
+    } else {
+      nurseryMark = null;
+      nurseryCons = null;
+    }
+  }
+
+  /*****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Force the next collection to be full heap.
+   */
+  public void forceFullHeapCollection() {
+    nextGCFullHeap = true;
+  }
+
+  /**
+   * Perform a (global) collection phase.
+   *
+   * @param phaseId Collection phase to execute.
+   */
+  @NoInline
+  public void collectionPhase(short phaseId) {
+    if (phaseId == SET_COLLECTION_KIND) {
+      super.collectionPhase(phaseId);
+      gcFullHeap = requiresFullHeapCollection();
+      return;
+    }
+
+    if (phaseId == PREPARE) {
+      nurserySpace.prepare(true);
+      if (traceFullHeap()){
+        if (gcFullHeap) {
+          if (Stats.gatheringStats()) fullHeap.set();
+          fullHeapTime.start();
+        }
+        super.collectionPhase(phaseId);
+
+        // we can throw away the remsets (but not modbuf) for a full heap GC
+        remsetPool.clearDeque(1);
+        arrayRemsetPool.clearDeque(2);
+      }
+      return;
+    }
+
+    if (phaseId == CLOSURE) {
+      if (!traceFullHeap()) {
+        nurseryTrace.prepare();
+      }
+      return;
+    }
+    if (phaseId == RELEASE) {
+      nurserySpace.release();
+      modbufPool.clearDeque(1);
+      remsetPool.clearDeque(1);
+      arrayRemsetPool.clearDeque(2);
+      if (!traceFullHeap()) {
+        nurseryTrace.release();
+      } else {
+        super.collectionPhase(phaseId);
+        if (gcFullHeap) fullHeapTime.stop();
+      }
+      nextGCFullHeap = (getPagesAvail() < Options.nurserySize.getMinNursery());
+      return;
+    }
+
+    super.collectionPhase(phaseId);
+  }
+
+  /**
+   * This method controls the triggering of a GC. It is called periodically
+   * during allocation. Returns true to trigger a collection.
+   *
+   * @param spaceFull Space request failed, must recover pages within 'space'.
+   * @return True if a collection is requested by the plan.
+   */
+  public final boolean collectionRequired(boolean spaceFull) {
+    int nurseryPages = nurserySpace.reservedPages();
+
+    if (nurseryPages > Options.nurserySize.getMaxNursery()) {
+      return true;
+    }
+
+    if (virtualMemoryExhausted())
+      return true;
+
+    return super.collectionRequired(spaceFull);
+  }
+
+  /**
+   * Determine if this GC should be a full heap collection.
+   *
+   * @return True is this GC should be a full heap collection.
+   */
+  protected boolean requiresFullHeapCollection() {
+    if (collectionTrigger == Collection.EXTERNAL_GC_TRIGGER && Options.fullHeapSystemGC.getValue()) {
+      return true;
+    }
+
+    if (nextGCFullHeap || collectionAttempt > 1) {
+      // Forces full heap collection
+      return true;
+    }
+
+    if (loSpace.allocationFailed() ||
+        nonMovingSpace.allocationFailed() ||
+        (USE_CODE_SPACE && (largeCodeSpace.allocationFailed() || smallCodeSpace.allocationFailed()))) {
+      // We need space from the nursery
+      return true;
+    }
+
+    if (virtualMemoryExhausted())
+      return true;
+
+    int smallNurseryPages = nurserySpace.committedPages();
+    int smallNurseryYield = (int)((smallNurseryPages << 1) * SURVIVAL_ESTIMATE);
+
+    if (smallNurseryYield < getPagesRequired()) {
+      // Our total yield is insufficent.
+      return true;
+    }
+
+    if (nurserySpace.allocationFailed()) {
+      if (smallNurseryYield < (nurserySpace.requiredPages() << 1)) {
+        // We have run out of VM pages in the nursery
+        return true;
+      }
+    }
+
+
+    return false;
+  }
+
+  /**
+   * Independent of how many pages remain in the page budget (a function of
+   * heap size), we must ensure we never exhaust virtual memory.  Therefore
+   * we must never let the nursery grow to the extent that it can't be
+   * copied into the mature space.
+   *
+   * @return True if the nursery has grown to the extent that it may not be
+   * able to be copied into the mature space.
+   */
+  private boolean virtualMemoryExhausted() {
+    return ((int) (nurserySpace.reservedPages()*WORST_CASE_COPY_EXPANSION) >= getMaturePhysicalPagesAvail());
+  }
+
+  /*****************************************************************************
+   *
+   * Correctness
+   */
+
+  /*****************************************************************************
+   *
+   * Accounting
+   */
+
+  /**
+   * Return the number of pages in use given the pending
+   * allocation.  Simply add the nursery's contribution to that of
+   * the superclass.
+   *
+   * @return The number of pages reserved given the pending
+   * allocation, excluding space reserved for copying.
+   */
+  @Override
+  public int getPagesUsed() {
+    return (nurserySpace.reservedPages() + super.getPagesUsed());
+  }
+
+  /**
+   * Return the number of pages available for allocation, <i>assuming
+   * all future allocation is to the nursery</i>.
+   *
+   * @return The number of pages available for allocation, <i>assuming
+   * all future allocation is to the nursery</i>.
+   */
+  @Override
+  public int getPagesAvail() {
+    return super.getPagesAvail() >> 1;
+  }
+
+  /**
+   * Return the number of pages reserved for copying.
+   *
+   * @return The number of pages reserved given the pending
+   * allocation, including space reserved for copying.
+   */
+  @Override
+  public int getCollectionReserve() {
+    return nurserySpace.reservedPages() + super.getCollectionReserve();
+  }
+
+  /**
+   * Return the number of pages available for allocation into the mature
+   * space.
+   *
+   * @return The number of pages available for allocation into the mature
+   * space.
+   */
+  public abstract int getMaturePhysicalPagesAvail();
+
+  /**
+   * Calculate the number of pages a collection is required to free to satisfy
+   * outstanding allocation requests.
+   *
+   * @return the number of pages a collection is required to free to satisfy
+   * outstanding allocation requests.
+   */
+  @Override
+  public int getPagesRequired() {
+    /* We don't currently pretenure, so mature space must be zero */
+    return super.getPagesRequired() + (nurserySpace.requiredPages() << 1);
+  }
+
+  /*****************************************************************************
+   *
+   * Miscellaneous
+   */
+
+  /**
+   * Return true if the address resides within the nursery
+   *
+   * @param addr The object to be tested
+   * @return true if the address resides within the nursery
+   */
+  @Inline
+  static boolean inNursery(Address addr) {
+    if (USE_DISCONTIGUOUS_NURSERY)
+      return Map.getDescriptorForAddress(addr) == NURSERY;
+    else
+      return addr.GE(NURSERY_START);
+  }
+
+  /**
+   * Return true if the object resides within the nursery
+   *
+   * @param obj The object to be tested
+   * @return true if the object resides within the nursery
+   */
+  @Inline
+  static boolean inNursery(ObjectReference obj) {
+    return inNursery(obj.toAddress());
+  }
+
+  /**
+   * @return Does the mature space do copying ?
+   */
+  protected boolean copyMature() {
+    return false;
+  }
+
+  /**
+   * Print pre-collection statistics. In this class we prefix the output
+   * indicating whether the collection was full heap or not.
+   */
+  public void printPreStats() {
+    if ((Options.verbose.getValue() >= 1) && (gcFullHeap))
+      Log.write("[Full heap]");
+    super.printPreStats();
+  }
+
+  /**
+   * @return The mature space, set by each subclass of <code>Gen</code>.
+   */
+  protected abstract Space activeMatureSpace();
+
+  /**
+   * @return True if we should trace the whole heap during collection. True if
+   *         we're ignorning remsets or if we're doing a full heap GC.
+   */
+  public final boolean traceFullHeap() {
+    return IGNORE_REMSETS || gcFullHeap;
+  }
+
+  /**
+   * @return Is current GC only collecting objects allocated since last GC.
+   */
+  public final boolean isCurrentGCNursery() {
+    return !gcFullHeap;
+  }
+
+  /**
+   * @return Is last GC a full collection?
+   */
+  public final boolean lastCollectionFullHeap() {
+    return gcFullHeap;
+  }
+
+  /**
+   * @see org.mmtk.plan.Plan#willNeverMove
+   *
+   * @param object Object in question
+   * @return True if the object will never move
+   */
+  @Override
+  public boolean willNeverMove(ObjectReference object) {
+    if (Space.isInSpace(NURSERY, object))
+      return false;
+    return super.willNeverMove(object);
+  }
+
+  /**
+   * Return the expected reference count. For non-reference counting
+   * collectors this becomes a true/false relationship.
+   *
+   * @param object The object to check.
+   * @param sanityRootRC The number of root references to the object.
+   * @return The expected (root excluded) reference count.
+   */
+  public int sanityExpectedRC(ObjectReference object, int sanityRootRC) {
+    Space space = Space.getSpaceForObject(object);
+
+    // Nursery
+    if (space == Gen.nurserySpace) {
+      return SanityChecker.DEAD;
+    }
+
+    // Immortal spaces
+    if (space == Gen.immortalSpace || space == Gen.vmSpace) {
+      return space.isReachable(object) ? SanityChecker.ALIVE : SanityChecker.DEAD;
+    }
+
+    // Mature space (nursery collection)
+    if (VM.activePlan.global().isCurrentGCNursery()) {
+      return SanityChecker.UNSURE;
+    }
+
+    // Mature space (full heap collection)
+    return space.isReachable(object) ? SanityChecker.ALIVE : SanityChecker.DEAD;
+  }
+
+  /**
+   * Register specialized methods.
+   */
+  @Interruptible
+  protected void registerSpecializedMethods() {
+    TransitiveClosure.registerSpecializedScan(SCAN_NURSERY, GenNurseryTraceLocal.class);
+    super.registerSpecializedMethods();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenCollector.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenCollector.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenCollector.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenCollector.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,147 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.generational;
+
+import org.mmtk.plan.*;
+import org.mmtk.policy.LargeObjectLocal;
+import org.mmtk.utility.deque.*;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This abstract class implements <i>per-collector thread</i>
+ * behavior and state for <i>generational copying collectors</i>.<p>
+ *
+ * Specifically, this class defines nursery collection behavior (through
+ * <code>nurseryTrace</code> and the <code>collectionPhase</code> method).
+ * Per-collector thread remset consumers are instantiated here (used by
+ * sub-classes).
+ *
+ * @see Gen
+ * @see GenMutator
+ * @see StopTheWorldCollector
+ * @see CollectorContext
+ */
+ at Uninterruptible public abstract class GenCollector extends StopTheWorldCollector {
+
+  /*****************************************************************************
+   * Instance fields
+   */
+
+  protected final GenNurseryTraceLocal nurseryTrace;
+
+  protected final LargeObjectLocal los;
+
+  // remembered set consumers
+  protected final ObjectReferenceDeque modbuf;
+  protected final AddressDeque remset;
+  protected final AddressPairDeque arrayRemset;
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * Constructor
+   *
+   * Note that the collector is a consumer of remsets, while the
+   * mutator is a producer.  The <code>GenMutator</code> class is
+   * responsible for construction of the WriteBuffer (producer).
+   * @see GenMutator
+   */
+  public GenCollector() {
+    los = new LargeObjectLocal(Plan.loSpace);
+    arrayRemset = new AddressPairDeque(global().arrayRemsetPool);
+    remset = new AddressDeque("remset", global().remsetPool);
+    modbuf = new ObjectReferenceDeque("modbuf", global().modbufPool);
+    nurseryTrace = new GenNurseryTraceLocal(global().nurseryTrace, this);
+  }
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a per-collector collection phase.
+   *
+   * @param phaseId The collection phase to perform
+   * @param primary Use this thread for single-threaded local activities.
+   */
+  @NoInline
+  public void collectionPhase(short phaseId, boolean primary) {
+
+    if (phaseId == Gen.PREPARE) {
+      los.prepare(true);
+      global().arrayRemsetPool.prepareNonBlocking();
+      global().remsetPool.prepareNonBlocking();
+      global().modbufPool.prepareNonBlocking();
+      nurseryTrace.prepare();
+      return;
+    }
+
+    if (phaseId == StopTheWorld.ROOTS) {
+      VM.scanning.computeGlobalRoots(getCurrentTrace());
+      if (!Gen.USE_STATIC_WRITE_BARRIER || global().traceFullHeap()) {
+        VM.scanning.computeStaticRoots(getCurrentTrace());
+      }
+      if (Plan.SCAN_BOOT_IMAGE && global().traceFullHeap()) {
+        VM.scanning.computeBootImageRoots(getCurrentTrace());
+      }
+      return;
+    }
+
+    if (phaseId == Gen.CLOSURE) {
+      if (!global().gcFullHeap) {
+        nurseryTrace.completeTrace();
+      }
+      return;
+    }
+
+    if (phaseId == Gen.RELEASE) {
+      los.release(true);
+      if (!global().traceFullHeap()) {
+        nurseryTrace.release();
+        global().arrayRemsetPool.reset();
+        global().remsetPool.reset();
+        global().modbufPool.reset();
+      }
+      return;
+    }
+
+    super.collectionPhase(phaseId, primary);
+  }
+
+  /****************************************************************************
+   *
+   * Miscellaneous
+   */
+
+  /** @return The active global plan as a <code>Gen</code> instance. */
+  @Inline
+  private static Gen global() {
+    return (Gen) VM.activePlan.global();
+  }
+
+  public final TraceLocal getCurrentTrace() {
+    if (global().traceFullHeap()) return getFullHeapTrace();
+    return nurseryTrace;
+  }
+
+  /** @return The trace to use when collecting the mature space */
+  public abstract TraceLocal getFullHeapTrace();
+
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenConstraints.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenConstraints.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenConstraints.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenConstraints.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,72 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.generational;
+
+import org.mmtk.plan.StopTheWorldConstraints;
+
+import org.mmtk.policy.CopySpace;
+import org.mmtk.policy.MarkSweepSpace;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.Word;
+
+/**
+ * This class and its subclasses communicate to the host VM/Runtime
+ * any features of the selected plan that it needs to know.  This is
+ * separate from the main Plan/PlanLocal class in order to bypass any
+ * issues with ordering of static initialization.
+ */
+ at Uninterruptible
+public class GenConstraints extends StopTheWorldConstraints {
+
+  /** @return True if this plan is generational. */
+  @Override
+  public boolean generational() { return true; }
+
+  /** @return True if this plan moves objects. */
+  @Override
+  public boolean movesObjects() { return true; }
+
+  /** @return The number of header bits that are required. */
+  @Override
+  public int gcHeaderBits() { return CopySpace.LOCAL_GC_BITS_REQUIRED; }
+
+  /** @return The number of header words that are required. */
+  @Override
+  public int gcHeaderWords() { return CopySpace.GC_HEADER_WORDS_REQUIRED; }
+
+  /** @return True if this plan requires a write barrier */
+  @Override
+  public boolean needsWriteBarrier() { return true; }
+
+  /** @return True if this plan requires a static barrier */
+  @Override
+  public boolean needsStaticWriteBarrier() { return Gen.USE_STATIC_WRITE_BARRIER; }
+
+  /** @return The specialized scan methods required */
+  @Override
+  public int numSpecializedScans() { return 2; }
+
+  /** @return True if this Plan requires a header bit for object logging */
+  @Override
+  public boolean needsLogBitInHeader() { return Gen.USE_OBJECT_BARRIER; }
+
+  /** @return A bit which represents that a header is unlogged */
+  @Override
+  public Word unloggedBit() {return MarkSweepSpace.UNLOGGED_BIT; }
+
+  /** @return The maximum size of an object that may be allocated directly into the nursery */
+  @Override
+  public int maxNonLOSDefaultAllocBytes() { return Gen.MAX_NURSERY_ALLOC_BYTES; }
+
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenMatureTraceLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenMatureTraceLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenMatureTraceLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenMatureTraceLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,140 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.generational;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.plan.Trace;
+import org.mmtk.utility.deque.*;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This abstract class implments the core functionality for a transitive
+ * closure over the heap graph.
+ */
+ at Uninterruptible
+public abstract class GenMatureTraceLocal extends TraceLocal {
+
+  /****************************************************************************
+   *
+   * Instance fields.
+   */
+  private final ObjectReferenceDeque modbuf;
+  private final AddressDeque remset;
+  private final AddressPairDeque arrayRemset;
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * Constructor
+   */
+  public GenMatureTraceLocal(int specializedScan, Trace trace, GenCollector plan) {
+    super(specializedScan, trace);
+    this.modbuf = plan.modbuf;
+    this.remset = plan.remset;
+    this.arrayRemset = plan.arrayRemset;
+  }
+
+  /**
+   * Constructor
+   */
+  public GenMatureTraceLocal(Trace trace, GenCollector plan) {
+    super(Gen.SCAN_MATURE, trace);
+    this.modbuf = plan.modbuf;
+    this.remset = plan.remset;
+    this.arrayRemset = plan.arrayRemset;
+  }
+
+  /****************************************************************************
+   *
+   * Object processing and tracing
+   */
+
+  /**
+   * Is the specified object live?
+   *
+   * @param object The object.
+   * @return True if the object is live.
+   */
+  @Inline
+  public boolean isLive(ObjectReference object) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!object.isNull());
+    if (Gen.inNursery(object)) {
+      return Gen.nurserySpace.isLive(object);
+    }
+    return super.isLive(object);
+  }
+
+  /**
+   * Return true if this object is guaranteed not to move during this
+   * collection (i.e. this object is defintely not an unforwarded
+   * object).
+   *
+   * @param object
+   * @return True if this object is guaranteed not to move during this
+   *         collection.
+   */
+  public boolean willNotMoveInCurrentCollection(ObjectReference object) {
+    if (Gen.inNursery(object))
+      return false;
+    else
+      return super.willNotMoveInCurrentCollection(object);
+  }
+
+  /**
+   * This method is the core method during the trace of the object graph.
+   * The role of this method is to:
+   *
+   * 1. Ensure the traced object is not collected.
+   * 2. If this is the first visit to the object enqueue it to be scanned.
+   * 3. Return the forwarded reference to the object.
+   *
+   * @param object The object to be traced.
+   * @return The new reference to the same object instance.
+   */
+  @Inline
+  public ObjectReference traceObject(ObjectReference object) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!object.isNull());
+    if (Gen.inNursery(object))
+      return Gen.nurserySpace.traceObject(this, object, Gen.ALLOC_MATURE_MAJORGC);
+    return super.traceObject(object);
+  }
+
+  /**
+   * Process any remembered set entries.
+   */
+  protected void processRememberedSets() {
+    logMessage(5, "clearing modbuf");
+    ObjectReference obj;
+    while (!(obj = modbuf.pop()).isNull()) {
+      Plan.markAsUnlogged(obj);
+    }
+    logMessage(5, "clearing remset");
+    while (!remset.isEmpty()) {
+      remset.pop();
+    }
+    logMessage(5, "clearing array remset");
+    while (!arrayRemset.isEmpty()) {
+      arrayRemset.pop1();
+      arrayRemset.pop2();
+    }
+  }
+
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenMutator.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenMutator.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenMutator.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenMutator.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,315 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.generational;
+
+import org.mmtk.plan.*;
+import org.mmtk.policy.CopyLocal;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.deque.*;
+import org.mmtk.utility.alloc.Allocator;
+import org.mmtk.utility.statistics.Stats;
+import org.mmtk.vm.VM;
+import static org.mmtk.plan.generational.Gen.USE_OBJECT_BARRIER_FOR_AASTORE;
+import static org.mmtk.plan.generational.Gen.USE_OBJECT_BARRIER_FOR_PUTFIELD;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This abstract class implements <i>per-mutator thread</i> behavior
+ * and state for <i>generational copying collectors</i>.<p>
+ *
+ * Specifically, this class defines mutator-time allocation into the nursery;
+ * write barrier semantics, and per-mutator thread collection semantics
+ * (flushing and restoring per-mutator allocator and remset state).
+ *
+ * @see Gen
+ * @see GenCollector
+ * @see StopTheWorldMutator
+ * @see MutatorContext
+ */
+ at Uninterruptible public class GenMutator extends StopTheWorldMutator {
+
+  /*****************************************************************************
+   *
+   * Instance fields
+   */
+  protected final CopyLocal nursery = new CopyLocal(Gen.nurserySpace);
+
+  private final ObjectReferenceDeque modbuf;    /* remember modified scalars */
+  protected final WriteBuffer remset;           /* remember modified array fields */
+  protected final AddressPairDeque arrayRemset; /* remember modified array ranges */
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * Constructor
+   *
+   * Note that each mutator is a producer of remsets, while each
+   * collector is a consumer.  The <code>GenCollector</code> class
+   * is responsible for construction of the consumer.
+   * @see GenCollector
+   */
+  public GenMutator() {
+    modbuf = new ObjectReferenceDeque("modbuf", global().modbufPool);
+    remset = new WriteBuffer(global().remsetPool);
+    arrayRemset = new AddressPairDeque(global().arrayRemsetPool);
+  }
+
+  /****************************************************************************
+   *
+   * Mutator-time allocation
+   */
+
+  /**
+   * Allocate memory for an object.
+   *
+   * @param bytes The number of bytes required for the object.
+   * @param align Required alignment for the object.
+   * @param offset Offset associated with the alignment.
+   * @param allocator The allocator associated with this request.
+   * @param site Allocation site
+   * @return The low address of the allocated memory.
+   */
+  @Inline
+  public Address alloc(int bytes, int align, int offset, int allocator, int site) {
+    if (allocator == Gen.ALLOC_NURSERY) {
+      if (Stats.GATHER_MARK_CONS_STATS) Gen.nurseryCons.inc(bytes);
+      return nursery.alloc(bytes, align, offset);
+    }
+    return super.alloc(bytes, align, offset, allocator, site);
+  }
+
+  /**
+   * Perform post-allocation actions.  For many allocators none are
+   * required.
+   *
+   * @param ref The newly allocated object
+   * @param typeRef the type reference for the instance being created
+   * @param bytes The size of the space to be allocated (in bytes)
+   * @param allocator The allocator number to be used for this allocation
+   */
+  @Inline
+  public void postAlloc(ObjectReference ref, ObjectReference typeRef,
+      int bytes, int allocator) {
+    if (allocator != Gen.ALLOC_NURSERY) {
+      super.postAlloc(ref, typeRef, bytes, allocator);
+    }
+  }
+
+  /**
+   * Return the allocator instance associated with a space
+   * <code>space</code>, for this plan instance.
+   *
+   * @param space The space for which the allocator instance is desired.
+   * @return The allocator instance associated with this plan instance
+   * which is allocating into <code>space</code>, or <code>null</code>
+   * if no appropriate allocator can be established.
+   */
+  public Allocator getAllocatorFromSpace(Space space) {
+    if (space == Gen.nurserySpace) return nursery;
+    return super.getAllocatorFromSpace(space);
+  }
+
+  /****************************************************************************
+   *
+   * Barriers
+   */
+
+  /**
+   * Perform the write barrier fast path, which may involve remembering
+   * a reference if necessary.
+   *
+   * @param src The object into which the new reference will be stored
+   * @param slot The address into which the new reference will be
+   * stored.
+   * @param tgt The target of the new reference
+   * @param mode The mode of the store (eg putfield, putstatic etc)
+   */
+  @Inline
+  private void fastPath(ObjectReference src, Address slot, ObjectReference tgt, int mode) {
+    if (Gen.GATHER_WRITE_BARRIER_STATS) Gen.wbFast.inc();
+    if ((mode == AASTORE_WRITE_BARRIER && USE_OBJECT_BARRIER_FOR_AASTORE) ||
+        (mode == PUTFIELD_WRITE_BARRIER && USE_OBJECT_BARRIER_FOR_PUTFIELD)) {
+      if (Plan.logRequired(src)) {
+        if (Gen.GATHER_WRITE_BARRIER_STATS) Gen.wbSlow.inc();
+        Plan.markAsLogged(src);
+        modbuf.insert(src);
+      }
+    } else {
+      if (!Gen.inNursery(slot) && Gen.inNursery(tgt)) {
+        if (Gen.GATHER_WRITE_BARRIER_STATS) Gen.wbSlow.inc();
+        remset.insert(slot);
+      }
+    }
+  }
+
+  /**
+   * A new reference is about to be created.  Take appropriate write
+   * barrier actions.<p>
+   *
+   * In this case, we remember the address of the source of the
+   * pointer if the new reference points into the nursery from
+   * non-nursery space.
+   *
+   * @param src The object into which the new reference will be stored
+   * @param slot The address into which the new reference will be
+   * stored.
+   * @param tgt The target of the new reference
+   * @param metaDataA A value that assists the host VM in creating a store
+   * @param metaDataB A value that assists the host VM in creating a store
+   * @param mode The mode of the store (eg putfield, putstatic etc)
+   */
+  @Inline
+  public final void writeBarrier(ObjectReference src, Address slot,
+      ObjectReference tgt, Word metaDataA,
+      Word metaDataB, int mode) {
+    fastPath(src, slot, tgt, mode);
+    VM.barriers.performWriteInBarrier(src, slot, tgt, metaDataA, metaDataB, mode);
+  }
+
+  /**
+   * Attempt to atomically exchange the value in the given slot
+   * with the passed replacement value. If a new reference is
+   * created, we must then take appropriate write barrier actions.<p>
+   *
+   * In this case, we remember the address of the source of the
+   * pointer if the new reference points into the nursery from
+   * non-nursery space.
+   *
+   * @param src The object into which the new reference will be stored
+   * @param slot The address into which the new reference will be
+   * stored.
+   * @param old The old reference to be swapped out
+   * @param tgt The target of the new reference
+   * @param metaDataA A value that assists the host VM in creating a store
+   * @param metaDataB A value that assists the host VM in creating a store
+   * @param mode The context in which the store occured
+   * @return True if the swap was successful.
+   */
+  @Inline
+  public boolean tryCompareAndSwapWriteBarrier(ObjectReference src, Address slot,
+      ObjectReference old, ObjectReference tgt, Word metaDataA,
+      Word metaDataB, int mode) {
+    boolean result = VM.barriers.tryCompareAndSwapWriteInBarrier(src, slot, old, tgt, metaDataA, metaDataB, mode);
+    if (result)
+      fastPath(src, slot, tgt, mode);
+    return result;
+  }
+
+  /**
+   * A number of references are about to be copied from object
+   * <code>src</code> to object <code>dst</code> (as in an array
+   * copy).  Thus, <code>dst</code> is the mutated object.  Take
+   * appropriate write barrier actions.<p>
+   *
+   * In this case, we remember the mutated source address range and
+   * will scan that address range at GC time.
+   *
+   * @param src The source of the values to copied
+   * @param srcOffset The offset of the first source address, in
+   * bytes, relative to <code>src</code> (in principle, this could be
+   * negative).
+   * @param dst The mutated object, i.e. the destination of the copy.
+   * @param dstOffset The offset of the first destination address, in
+   * bytes relative to <code>tgt</code> (in principle, this could be
+   * negative).
+   * @param bytes The size of the region being copied, in bytes.
+   * @return True if the update was performed by the barrier, false if
+   * left to the caller (always false in this case).
+   */
+  @Inline
+  public final boolean writeBarrier(ObjectReference src, Offset srcOffset,
+      ObjectReference dst, Offset dstOffset,
+      int bytes) {
+    // We can ignore when src is in old space, right?
+    if (!Gen.inNursery(dst))
+      arrayRemset.insert(dst.toAddress().plus(dstOffset),
+          dst.toAddress().plus(dstOffset.plus(bytes)));
+    return false;
+  }
+
+  /**
+   * Flush per-mutator remembered sets into the global remset pool.
+   */
+  public final void flushRememberedSets() {
+    modbuf.flushLocal();
+    remset.flushLocal();
+    arrayRemset.flushLocal();
+    assertRemsetsFlushed();
+  }
+
+  /**
+   * Assert that the remsets have been flushed.  This is critical to
+   * correctness.  We need to maintain the invariant that remset entries
+   * do not accrue during GC.  If the host JVM generates barrier entires
+   * it is its own responsibility to ensure that they are flushed before
+   * returning to MMTk.
+   */
+  public final void assertRemsetsFlushed() {
+    if (VM.VERIFY_ASSERTIONS) {
+      VM.assertions._assert(modbuf.isFlushed());
+      VM.assertions._assert(remset.isFlushed());
+      VM.assertions._assert(arrayRemset.isFlushed());
+    }
+  }
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a per-mutator collection phase.
+   */
+  @NoInline
+  public void collectionPhase(short phaseId, boolean primary) {
+
+    if (phaseId == Gen.PREPARE) {
+      nursery.reset();
+      if (global().traceFullHeap()) {
+        super.collectionPhase(phaseId, primary);
+        modbuf.flushLocal();
+        remset.resetLocal();
+        arrayRemset.resetLocal();
+      } else {
+        flushRememberedSets();
+      }
+      return;
+    }
+
+    if (phaseId == Gen.RELEASE) {
+      if (global().traceFullHeap()) {
+        super.collectionPhase(phaseId, primary);
+      }
+      assertRemsetsFlushed();
+      return;
+    }
+
+    super.collectionPhase(phaseId, primary);
+  }
+
+  /****************************************************************************
+   *
+   * Miscellaneous
+   */
+
+  /** @return The active global plan as a <code>Gen</code> instance. */
+  @Inline
+  private static Gen global() {
+    return (Gen) VM.activePlan.global();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenNurseryTraceLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenNurseryTraceLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenNurseryTraceLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/GenNurseryTraceLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,131 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.generational;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.plan.Trace;
+import org.mmtk.utility.deque.*;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implments the core functionality for a transitive
+ * closure over the heap graph.
+ */
+ at Uninterruptible
+public final class GenNurseryTraceLocal extends TraceLocal {
+
+  /****************************************************************************
+   *
+   * Instance fields.
+   */
+  private final ObjectReferenceDeque modbuf;
+  private final AddressDeque remset;
+  private final AddressPairDeque arrayRemset;
+
+
+  /**
+   * Constructor
+   */
+  public GenNurseryTraceLocal(Trace trace, GenCollector plan) {
+    super(Gen.SCAN_NURSERY, trace);
+    this.modbuf = plan.modbuf;
+    this.remset = plan.remset;
+    this.arrayRemset = plan.arrayRemset;
+  }
+
+  /****************************************************************************
+   *
+   * Externally visible Object processing and tracing
+   */
+
+  /**
+   * Is the specified object live?
+   *
+   * @param object The object.
+   * @return True if the object is live.
+   */
+  public boolean isLive(ObjectReference object) {
+    if (object.isNull()) return false;
+    if (Gen.inNursery(object)) {
+      return Gen.nurserySpace.isLive(object);
+    }
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(super.isLive(object));
+    return true;
+  }
+
+  /**
+   * This method is the core method during the trace of the object graph.
+   * The role of this method is to:
+   *
+   * 1. Ensure the traced object is not collected.
+   * 2. If this is the first visit to the object enqueue it to be scanned.
+   * 3. Return the forwarded reference to the object.
+   *
+   * @param object The object to be traced.
+   * @return The new reference to the same object instance.
+   */
+  @Inline
+  public ObjectReference traceObject(ObjectReference object) {
+    if (Gen.inNursery(object)) {
+      return Gen.nurserySpace.traceObject(this, object, Gen.ALLOC_MATURE_MINORGC);
+    }
+    return object;
+  }
+
+  /**
+   * Process any remembered set entries.
+   */
+  @Inline
+  protected void processRememberedSets() {
+    logMessage(5, "processing modbuf");
+    ObjectReference obj;
+    while (!(obj = modbuf.pop()).isNull()) {
+      if (VM.DEBUG) VM.debugging.modbufEntry(obj);
+      Plan.markAsUnlogged(obj);
+      scanObject(obj);
+    }
+    logMessage(5, "processing remset");
+    while (!remset.isEmpty()) {
+      Address loc = remset.pop();
+      if (VM.DEBUG) VM.debugging.remsetEntry(loc);
+      processRootEdge(loc, false);
+    }
+    logMessage(5, "processing array remset");
+    arrayRemset.flushLocal();
+    while (!arrayRemset.isEmpty()) {
+      Address start = arrayRemset.pop1();
+      Address guard = arrayRemset.pop2();
+      if (VM.DEBUG) VM.debugging.arrayRemsetEntry(start,guard);
+      while (start.LT(guard)) {
+        processRootEdge(start, false);
+        start = start.plus(BYTES_IN_ADDRESS);
+      }
+    }
+  }
+
+  /**
+   * Will the object move from now on during the collection.
+   *
+   * @param object The object to query.
+   * @return True if the object is guaranteed not to move.
+   */
+  public boolean willNotMoveInCurrentCollection(ObjectReference object) {
+    if (object.isNull()) return false;
+    return !Gen.inNursery(object);
+  }
+
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopy.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopy.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopy.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopy.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,232 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.generational.copying;
+
+import org.mmtk.policy.CopySpace;
+import org.mmtk.policy.Space;
+import org.mmtk.plan.generational.*;
+import org.mmtk.plan.Trace;
+import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.utility.heap.VMRequest;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements the functionality of a standard
+ * two-generation copying collector.  Nursery collections occur when
+ * either the heap is full or the nursery is full.  The nursery size
+ * is determined by an optional command line argument.  If undefined,
+ * the nursery size is "infinite", so nursery collections only occur
+ * when the heap is full (this is known as a flexible-sized nursery
+ * collector).  Thus both fixed and flexible nursery sizes are
+ * supported.  Full heap collections occur when the nursery size has
+ * dropped to a statically defined threshold,
+ * <code>NURSERY_THRESHOLD</code><p>
+ *
+ * See the Jones & Lins GC book, chapter 7 for a detailed discussion
+ * of generational collection and section 7.3 for an overview of the
+ * flexible nursery behavior ("The Standard ML of New Jersey
+ * collector"), or go to Appel's paper "Simple generational garbage
+ * collection and fast allocation." SP&E 19(2):171--183, 1989.<p>
+ *
+ * All plans make a clear distinction between <i>global</i> and
+ * <i>thread-local</i> activities.  Global activities must be
+ * synchronized, whereas no synchronization is required for
+ * thread-local activities.  Instances of Plan map 1:1 to "kernel
+ * threads" (aka CPUs).  Thus instance
+ * methods allow fast, unsychronized access to Plan utilities such as
+ * allocation and collection.  Each instance rests on static resources
+ * (such as memory and virtual memory resources) which are "global"
+ * and therefore "static" members of Plan.  This mapping of threads to
+ * instances is crucial to understanding the correctness and
+ * performance proprties of this plan.
+ */
+ at Uninterruptible public class GenCopy extends Gen {
+
+  /****************************************************************************
+   *
+   * Class variables
+   */
+
+  // GC state
+  static boolean hi = false; // True if copying to "higher" semispace
+
+  /**
+   * The low half of the copying mature space.  We allocate into this space
+   * when <code>hi</code> is <code>false</code>.
+   */
+  static CopySpace matureSpace0 = new CopySpace("ss0", DEFAULT_POLL_FREQUENCY, false, VMRequest.create());
+  static final int MS0 = matureSpace0.getDescriptor();
+
+  /**
+   * The high half of the copying mature space. We allocate into this space
+   * when <code>hi</code> is <code>true</code>.
+   */
+  static CopySpace matureSpace1 = new CopySpace("ss1", DEFAULT_POLL_FREQUENCY, true, VMRequest.create());
+  static final int MS1 = matureSpace1.getDescriptor();
+
+
+  /****************************************************************************
+   *
+   * Instance fields
+   */
+  final Trace matureTrace;
+
+  /**
+   * Constructor
+   */
+  public GenCopy() {
+    super();
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!IGNORE_REMSETS); // Not supported for GenCopy
+    matureTrace = new Trace(metaDataSpace);
+  }
+
+  /**
+   * @return Does the mature space do copying ?
+   */
+  protected boolean copyMature() {
+    return true;
+  }
+
+  /**
+   * @return The semispace we are currently allocating into
+   */
+  static CopySpace toSpace() {
+    return hi ? matureSpace1 : matureSpace0;
+  }
+
+  /**
+   * @return Space descriptor for to-space.
+   */
+  static int toSpaceDesc() { return hi ? MS1 : MS0; }
+
+  /**
+   * @return The semispace we are currently copying from
+   * (or copied from at last major GC)
+   */
+  static CopySpace fromSpace() {
+    return hi ? matureSpace0 : matureSpace1;
+  }
+
+  /**
+   * @return Space descriptor for from-space
+   */
+  static int fromSpaceDesc() { return hi ? MS0 : MS1; }
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a phase of the currently active collection.
+   *
+   * @param phaseId Collection phase to process
+   */
+  @Inline
+  public void collectionPhase(short phaseId) {
+    if (traceFullHeap()) {
+      if (phaseId == PREPARE) {
+        super.collectionPhase(phaseId);
+        hi = !hi; // flip the semi-spaces
+        matureSpace0.prepare(hi);
+        matureSpace1.prepare(!hi);
+        matureTrace.prepare();
+        return;
+      }
+      if (phaseId == CLOSURE) {
+        matureTrace.prepare();
+        return;
+      }
+      if (phaseId == RELEASE) {
+        matureTrace.release();
+        fromSpace().release();
+        super.collectionPhase(phaseId);
+        return;
+      }
+    }
+    super.collectionPhase(phaseId);
+  }
+
+  /*****************************************************************************
+   *
+   * Accounting
+   */
+
+  /**
+   * Return the number of pages reserved for use given the pending
+   * allocation.
+   *
+   * @return The number of pages reserved given the pending
+   * allocation, excluding space reserved for copying.
+   */
+  @Inline
+  public int getPagesUsed() {
+    return toSpace().reservedPages() + super.getPagesUsed();
+  }
+
+  /**
+   * Return the number of pages reserved for copying.
+   *
+   * @return the number of pages reserved for copying.
+   */
+  public final int getCollectionReserve() {
+    // we must account for the number of pages required for copying,
+    // which equals the number of semi-space pages reserved
+    return toSpace().reservedPages() + super.getCollectionReserve();
+  }
+
+  /**
+   * Calculate the number of pages a collection is required to free to satisfy
+   * outstanding allocation requests.
+   *
+   * @return the number of pages a collection is required to free to satisfy
+   * outstanding allocation requests.
+   */
+  public int getPagesRequired() {
+    return super.getPagesRequired() + (toSpace().requiredPages() << 1);
+  }
+
+  /**
+   * Return the number of pages available for allocation into the mature
+   * space.
+   *
+   * @return The number of pages available for allocation into the mature
+   * space.
+   */
+  public int getMaturePhysicalPagesAvail() {
+    return toSpace().availablePhysicalPages() >> 1;
+  }
+
+  /**************************************************************************
+   * Miscellaneous methods
+   */
+
+  /**
+   * @return The mature space we are currently allocating into
+   */
+  @Inline
+  public Space activeMatureSpace() {
+    return toSpace();
+  }
+
+  /**
+   * Register specialized methods.
+   */
+  @Interruptible
+  protected void registerSpecializedMethods() {
+    TransitiveClosure.registerSpecializedScan(SCAN_MATURE, GenCopyMatureTraceLocal.class);
+    super.registerSpecializedMethods();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyCollector.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyCollector.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyCollector.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyCollector.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,171 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.generational.copying;
+
+import org.mmtk.plan.generational.Gen;
+import org.mmtk.plan.generational.GenCollector;
+import org.mmtk.plan.Plan;
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.policy.CopyLocal;
+import org.mmtk.policy.CopySpace;
+import org.mmtk.utility.alloc.Allocator;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements <i>per-collector thread</i> behavior and state for
+ * the <code>GenCopy</code> two-generational copying collector.<p>
+ *
+ * Specifically, this class defines semantics specific to the collection of
+ * the mature generation (<code>GenCollector</code> defines nursery semantics).
+ * In particular the mature space allocator is defined (for collection-time
+ * allocation into the mature space), and the mature space per-collector thread
+ * collection time semantics are defined.<p>
+ *
+ * @see GenCopy for a description of the <code>GenCopy</code> algorithm.
+ *
+ * @see GenCopy
+ * @see GenCopyMutator
+ * @see GenCollector
+ * @see org.mmtk.plan.StopTheWorldCollector
+ * @see org.mmtk.plan.CollectorContext
+ */
+ at Uninterruptible
+public class GenCopyCollector extends GenCollector {
+
+  /******************************************************************
+   * Instance fields
+   */
+
+  /** The allocator for the mature space */
+  private final CopyLocal mature;
+
+  /** The trace object for full-heap collections */
+  private final GenCopyMatureTraceLocal matureTrace;
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * Constructor
+   */
+  public GenCopyCollector() {
+    mature = new CopyLocal(GenCopy.toSpace());
+    matureTrace = new GenCopyMatureTraceLocal(global().matureTrace, this);
+  }
+
+  /****************************************************************************
+   *
+   * Collection-time allocation
+   */
+
+  /**
+   * Allocate space for copying an object (this method <i>does not</i>
+   * copy the object, it only allocates space)
+   *
+   * @param original A reference to the original object
+   * @param bytes The size of the space to be allocated (in bytes)
+   * @param align The requested alignment.
+   * @param offset The alignment offset.
+   * @return The address of the first byte of the allocated region
+   */
+  @Inline
+  public Address allocCopy(ObjectReference original, int bytes,
+      int align, int offset, int allocator) {
+    if (allocator == Plan.ALLOC_LOS) {
+      if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Allocator.getMaximumAlignedSize(bytes, align) > Plan.MAX_NON_LOS_COPY_BYTES);
+      return los.alloc(bytes, align, offset);
+    } else {
+      if (VM.VERIFY_ASSERTIONS) {
+        VM.assertions._assert(bytes <= Plan.MAX_NON_LOS_COPY_BYTES);
+        VM.assertions._assert(allocator == GenCopy.ALLOC_MATURE_MINORGC ||
+            allocator == GenCopy.ALLOC_MATURE_MAJORGC);
+      }
+      return mature.alloc(bytes, align, offset);
+    }
+  }
+
+  /**
+   * Perform any post-copy actions.  In this case we clear any bits used
+   * for this object's GC metadata.
+   *
+   * @param object The newly allocated object
+   * @param typeRef the type reference for the instance being created
+   * @param bytes The size of the space to be allocated (in bytes)
+   * @param allocator The allocator to allocate from
+   */
+  @Inline
+  public final void postCopy(ObjectReference object, ObjectReference typeRef,
+      int bytes, int allocator) {
+    CopySpace.clearGCBits(object);
+    if (allocator == Plan.ALLOC_LOS)
+      Plan.loSpace.initializeHeader(object, false);
+    else if (GenCopy.IGNORE_REMSETS)
+      CopySpace.markObject(getCurrentTrace(),object, GenCopy.immortalSpace.getMarkState());
+    if (Gen.USE_OBJECT_BARRIER)
+      Plan.markAsUnlogged(object);
+  }
+
+
+  /*****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Execute a per-collector collection phase.
+   *
+   * @param phaseId The phase to execute.
+   * @param primary True if this thread should peform local single-threaded
+   * actions.
+   */
+  public void collectionPhase(short phaseId, boolean primary) {
+    if (global().traceFullHeap()) {
+      if (phaseId == GenCopy.PREPARE) {
+        super.collectionPhase(phaseId, primary);
+        if (global().gcFullHeap) mature.rebind(GenCopy.toSpace());
+      }
+      if (phaseId == GenCopy.CLOSURE) {
+        matureTrace.completeTrace();
+        return;
+      }
+      if (phaseId == GenCopy.RELEASE) {
+        matureTrace.release();
+        super.collectionPhase(phaseId, primary);
+        return;
+      }
+    }
+    super.collectionPhase(phaseId, primary);
+  }
+
+  /*****************************************************************************
+   *
+   * Miscellaneous
+   */
+
+  /** @return The active global plan as a <code>GenCopy</code> instance. */
+  private static GenCopy global() {
+    return (GenCopy) VM.activePlan.global();
+  }
+
+  /** Show the status of the mature allocator. */
+  protected final void showMature() {
+    mature.show();
+  }
+
+  public final TraceLocal getFullHeapTrace() { return matureTrace; }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyConstraints.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyConstraints.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyConstraints.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyConstraints.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,22 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.generational.copying;
+
+import org.mmtk.plan.generational.GenConstraints;
+import org.vmmagic.pragma.*;
+
+/**
+ * GenCopy constants.
+ */
+ at Uninterruptible public class GenCopyConstraints extends GenConstraints {
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyMatureTraceLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyMatureTraceLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyMatureTraceLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyMatureTraceLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,105 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.generational.copying;
+
+import org.mmtk.plan.generational.Gen;
+import org.mmtk.plan.generational.GenCollector;
+import org.mmtk.plan.generational.GenMatureTraceLocal;
+import org.mmtk.plan.Trace;
+import org.mmtk.policy.Space;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implments the core functionality for a transitive
+ * closure over the heap graph, specifically in a Generational copying
+ * collector.
+ */
+ at Uninterruptible
+public final class GenCopyMatureTraceLocal extends GenMatureTraceLocal {
+
+  /**
+   * Constructor
+   */
+  public GenCopyMatureTraceLocal(Trace global, GenCollector plan) {
+    super(global, plan);
+  }
+
+  private static GenCopy global() {
+    return (GenCopy) VM.activePlan.global();
+  }
+
+  /**
+   * Trace a reference into the mature space during GC. This involves
+   * determining whether the instance is in from space, and if so,
+   * calling the <code>traceObject</code> method of the Copy
+   * collector.
+   *
+   * @param object The object reference to be traced.  This is <i>NOT</i> an
+   * interior pointer.
+   * @return The possibly moved reference.
+   */
+  public ObjectReference traceObject(ObjectReference object) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(global().traceFullHeap());
+    if (object.isNull()) return object;
+
+    if (Space.isInSpace(GenCopy.MS0, object))
+      return GenCopy.matureSpace0.traceObject(this, object, Gen.ALLOC_MATURE_MAJORGC);
+    if (Space.isInSpace(GenCopy.MS1, object))
+      return GenCopy.matureSpace1.traceObject(this, object, Gen.ALLOC_MATURE_MAJORGC);
+    return super.traceObject(object);
+  }
+
+  /**
+   * Return true if <code>obj</code> is a live object.
+   *
+   * @param object The object in question
+   * @return True if <code>obj</code> is a live object.
+   */
+  public boolean isLive(ObjectReference object) {
+    if (object.isNull()) return false;
+    if (Space.isInSpace(GenCopy.MS0, object))
+      return GenCopy.hi ? GenCopy.matureSpace0.isLive(object) : true;
+    if (Space.isInSpace(GenCopy.MS1, object))
+      return GenCopy.hi ? true : GenCopy.matureSpace1.isLive(object);
+    return super.isLive(object);
+  }
+
+  /****************************************************************************
+   *
+   * Object processing and tracing
+   */
+
+
+  /**
+   * Return true if this object is guaranteed not to move during this
+   * collection (i.e. this object is defintely not an unforwarded
+   * object).
+   *
+   * @param object
+   * @return True if this object is guaranteed not to move during this
+   *         collection.
+   */
+  public boolean willNotMoveInCurrentCollection(ObjectReference object) {
+    if (Space.isInSpace(GenCopy.toSpaceDesc(), object)) {
+      return true;
+    }
+    if (Space.isInSpace(GenCopy.fromSpaceDesc(), object)) {
+      return false;
+    }
+    return super.willNotMoveInCurrentCollection(object);
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyMutator.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyMutator.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyMutator.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/copying/GenCopyMutator.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,165 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.generational.copying;
+
+import org.mmtk.plan.generational.GenMutator;
+import org.mmtk.policy.CopyLocal;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.alloc.Allocator;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements <i>per-mutator thread</i> behavior and state for
+ * the <code>GenCopy</code> two-generational copying collector.<p>
+ *
+ * Specifically, this class defines mutator-time semantics specific to the
+ * mature generation (<code>GenMutator</code> defines nursery semantics).
+ * In particular the mature space allocator is defined (for mutator-time
+ * allocation into the mature space via pre-tenuring), and the mature space
+ * per-mutator thread collection time semantics are defined (rebinding
+ * the mature space allocator).<p>
+ *
+ * @see GenCopy for a description of the <code>GenCopy</code> algorithm.
+ *
+ * @see GenCopy
+ * @see GenCopyCollector
+ * @see GenMutator
+ * @see org.mmtk.plan.StopTheWorldMutator
+ * @see org.mmtk.plan.MutatorContext
+ */
+ at Uninterruptible
+public class GenCopyMutator extends GenMutator {
+  /******************************************************************
+   * Instance fields
+   */
+
+  /**
+   * The allocator for the copying mature space (the mutator may
+   * "pretenure" objects into this space otherwise used only by
+   * the collector)
+   */
+  private CopyLocal mature;
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * Constructor
+   */
+  public GenCopyMutator() {
+    mature = new CopyLocal();
+  }
+
+  /**
+   * Called before the MutatorContext is used, but after the context has been
+   * fully registered and is visible to collection.
+   */
+  public void initMutator(int id) {
+    super.initMutator(id);
+    mature.rebind(GenCopy.toSpace());
+  }
+
+  /****************************************************************************
+   *
+   * Mutator-time allocation
+   */
+
+  /**
+   * Allocate space (for an object) in the specified space
+   *
+   * @param bytes The size of the space to be allocated (in bytes)
+   * @param align The requested alignment.
+   * @param offset The alignment offset.
+   * @param allocator The allocator to allocate from
+   * @param site Allocation site
+   * @return The address of the first byte of the allocated region
+   */
+  @Inline
+  public final Address alloc(int bytes, int align, int offset, int allocator, int site) {
+    if (allocator == GenCopy.ALLOC_MATURE) {
+      return mature.alloc(bytes, align, offset);
+    }
+    return super.alloc(bytes, align, offset, allocator, site);
+  }
+
+  /**
+   * Perform post-allocation initialization of an object
+   *
+   * @param object The newly allocated object
+   * @param typeRef the type reference for the instance being created
+   * @param allocator The allocator to allocate from
+   * @param bytes The size of the space allocated (in bytes)
+   */
+  @Inline
+  public final void postAlloc(ObjectReference object, ObjectReference typeRef,
+      int bytes, int allocator) {
+    // nothing to be done
+    if (allocator == GenCopy.ALLOC_MATURE) return;
+    super.postAlloc(object, typeRef, bytes, allocator);
+  }
+
+  /**
+   * Return the allocator instance associated with a space
+   * <code>space</code>, for this plan instance.
+   *
+   * @param space The space for which the allocator instance is desired.
+   * @return The allocator instance associated with this plan instance
+   * which is allocating into <code>space</code>, or <code>null</code>
+   * if no appropriate allocator can be established.
+   */
+  public final Allocator getAllocatorFromSpace(Space space) {
+    if (space == GenCopy.matureSpace0 || space == GenCopy.matureSpace1) return mature;
+    return super.getAllocatorFromSpace(space);
+  }
+
+
+  /*****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Execute a per-mutator collection phase.
+   *
+   * @param phaseId The phase to execute.
+   * @param primary True if this thread should peform local single-threaded
+   * actions.
+   */
+  public void collectionPhase(short phaseId, boolean primary) {
+    if (global().traceFullHeap()) {
+      if (phaseId == GenCopy.PREPARE) {
+        super.collectionPhase(phaseId, primary);
+        if (global().gcFullHeap) mature.rebind(GenCopy.toSpace());
+        return;
+      }
+    }
+
+    super.collectionPhase(phaseId, primary);
+  }
+
+  /*****************************************************************************
+   *
+   * Miscellaneous
+   */
+
+  /** @return The active global plan as a <code>GenCopy</code> instance. */
+  private static GenCopy global() {
+    return (GenCopy) VM.activePlan.global();
+  }
+
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmix.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmix.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmix.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmix.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,196 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.generational.immix;
+
+import org.mmtk.plan.generational.Gen;
+import org.mmtk.plan.Trace;
+import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.policy.immix.ImmixSpace;
+import org.mmtk.policy.immix.ObjectHeader;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.heap.VMRequest;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements the functionality of a two-generation copying
+ * collector where <b>the higher generation is an immix space</b>.
+ *
+ * Nursery collections occur when either the heap is full or the nursery
+ * is full.  The nursery size is determined by an optional command line
+ * argument. If undefined, the nursery size is "infinite", so nursery
+ * collections only occur when the heap is full (this is known as a
+ * flexible-sized nursery collector).  Thus both fixed and flexible
+ * nursery sizes are supported.  Full heap collections occur when the
+ * nursery size has dropped to a statically defined threshold,
+ * <code>NURSERY_THRESHOLD</code><p>
+ *
+ * See the PLDI'08 paper by Blackburn and McKinley for a description
+ * of the algorithm: http://doi.acm.org/10.1145/1375581.1375586
+ *
+ * See the Jones & Lins GC book, chapter 7 for a detailed discussion
+ * of generational collection and section 7.3 for an overview of the
+ * flexible nursery behavior ("The Standard ML of New Jersey
+ * collector"), or go to Appel's paper "Simple generational garbage
+ * collection and fast allocation." SP&E 19(2):171--183, 1989.<p>
+ *
+ *
+ * For general comments about the global/local distinction among classes refer
+ * to Plan.java and PlanLocal.java.
+ */
+ at Uninterruptible
+public class GenImmix extends Gen {
+
+  /*****************************************************************************
+   *
+   * Class fields
+   */
+
+  /** The mature space, which for GenImmix uses a mark sweep collection policy. */
+  public static final ImmixSpace immixSpace = new ImmixSpace("immix", DEFAULT_POLL_FREQUENCY, VMRequest.create());
+
+  public static final int IMMIX = immixSpace.getDescriptor();
+
+  public static final int SCAN_IMMIX = 1;
+  public static final int SCAN_DEFRAG = 2;
+
+  /****************************************************************************
+   *
+   * Instance fields
+   */
+  /* The trace class for a full-heap collection */
+  public final Trace matureTrace = new Trace(metaDataSpace);
+  private boolean lastGCWasDefrag = false;
+
+  /*****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a (global) collection phase.
+   */
+  @Inline
+  @Override
+  public final void collectionPhase(short phaseId) {
+    if (phaseId == SET_COLLECTION_KIND) {
+      super.collectionPhase(phaseId);
+      if (gcFullHeap)
+        immixSpace.decideWhetherToDefrag(emergencyCollection, true, collectionAttempt, collectionTrigger);
+      return;
+    }
+
+    if (traceFullHeap()) {
+      if (phaseId == PREPARE) {
+        super.collectionPhase(phaseId);
+        matureTrace.prepare();
+        immixSpace.prepare(true);
+        return;
+      }
+
+      if (phaseId == CLOSURE) {
+        matureTrace.prepare();
+        return;
+      }
+
+      if (phaseId == RELEASE) {
+        matureTrace.release();
+        lastGCWasDefrag = immixSpace.release(true);
+        super.collectionPhase(phaseId);
+        return;
+      }
+    } else
+      lastGCWasDefrag = false;
+
+    super.collectionPhase(phaseId);
+  }
+
+  /**
+   * @return Whether last GC was an exhaustive attempt to collect the heap.  For many collectors this is the same as asking whether the last GC was a full heap collection.
+   */
+  @Override
+  public boolean lastCollectionWasExhaustive() {
+    return lastGCWasDefrag;
+  }
+
+  /*****************************************************************************
+   *
+   * Accounting
+   */
+
+  /**
+   * Return the number of pages reserved for use given the pending
+   * allocation.
+   *
+   * @return The number of pages reserved given the pending
+   * allocation, excluding space reserved for copying.
+   */
+  @Inline
+  @Override
+  public int getPagesUsed() {
+    return immixSpace.reservedPages() + super.getPagesUsed();
+  }
+
+  /**
+   * Return the number of pages available for allocation into the mature
+   * space.
+   *
+   * @return The number of pages available for allocation into the mature
+   * space.
+   */
+  public int getMaturePhysicalPagesAvail() {
+    return immixSpace.availablePhysicalPages();
+  }
+
+  /*****************************************************************************
+   *
+   * Miscellaneous
+   */
+
+  /**
+   * Accessor method to allow the generic generational code in Gen.java
+   * to access the mature space.
+   *
+   * @return The active mature space
+   */
+  @Inline
+  protected final Space activeMatureSpace() {
+    return immixSpace;
+  }
+
+  /**
+   * @see org.mmtk.plan.Plan#willNeverMove
+   *
+   * @param object Object in question
+   * @return true if the object will never move
+   */
+  @Override
+  public boolean willNeverMove(ObjectReference object) {
+    if (Space.isInSpace(IMMIX, object)) {
+      ObjectHeader.pinObject(object);
+      return true;
+    } else
+      return super.willNeverMove(object);
+  }
+
+  /**
+   * Register specialized methods.
+   */
+  @Interruptible
+  protected void registerSpecializedMethods() {
+    TransitiveClosure.registerSpecializedScan(SCAN_IMMIX, GenImmixMatureTraceLocal.class);
+    TransitiveClosure.registerSpecializedScan(SCAN_DEFRAG, GenImmixMatureDefragTraceLocal.class);
+    super.registerSpecializedMethods();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixCollector.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixCollector.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixCollector.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixCollector.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,186 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.generational.immix;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.plan.generational.*;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.alloc.Allocator;
+import org.mmtk.utility.alloc.ImmixAllocator;
+import org.mmtk.utility.statistics.Stats;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements <i>per-collector thread</i> behavior and state for
+ * the <code>GenImmix</code> two-generational copying collector.<p>
+ *
+ * Specifically, this class defines semantics specific to the collection of
+ * the copy generation (<code>GenCollector</code> defines nursery semantics).
+ * In particular the copy space allocator is defined (for collection-time
+ * allocation into the copy space), and the copy space per-collector thread
+ * collection time semantics are defined.<p>
+ *
+ * @see GenImmix for a description of the <code>GenImmix</code> algorithm.
+ *
+ * @see GenImmix
+ * @see GenImmixMutator
+ * @see GenCollector
+ * @see org.mmtk.plan.StopTheWorldCollector
+ * @see org.mmtk.plan.CollectorContext
+ */
+ at Uninterruptible
+public class GenImmixCollector extends GenCollector {
+
+  /*****************************************************************************
+   *
+   * Instance fields
+   */
+  private final GenImmixMatureTraceLocal matureTrace = new GenImmixMatureTraceLocal(global().matureTrace, this);
+  private final GenImmixMatureDefragTraceLocal defragTrace = new GenImmixMatureDefragTraceLocal(global().matureTrace, this);
+
+  private final org.mmtk.policy.immix.CollectorLocal immix = new org.mmtk.policy.immix.CollectorLocal(GenImmix.immixSpace);
+
+  private final ImmixAllocator copy = new ImmixAllocator(GenImmix.immixSpace, true, false);
+  private final ImmixAllocator defragCopy = new ImmixAllocator(GenImmix.immixSpace, true, true);
+
+  /****************************************************************************
+   *
+   * Collection-time allocation
+   */
+
+  /**
+   * Allocate space for copying an object (this method <i>does not</i>
+   * copy the object, it only allocates space)
+   *
+   * @param original A reference to the original object
+   * @param bytes The size of the space to be allocated (in bytes)
+   * @param align The requested alignment.
+   * @param offset The alignment offset.
+   * @param allocator The allocator to use.
+   * @return The address of the first byte of the allocated region
+   */
+  @Inline
+  public final Address allocCopy(ObjectReference original, int bytes,
+                                 int align, int offset, int allocator) {
+
+    if (Stats.GATHER_MARK_CONS_STATS) {
+      if (Space.isInSpace(GenImmix.NURSERY, original)) GenImmix.nurseryMark.inc(bytes);
+    }
+    if (allocator == Plan.ALLOC_LOS) {
+      if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Allocator.getMaximumAlignedSize(bytes, align) > Plan.MAX_NON_LOS_COPY_BYTES);
+      return los.alloc(bytes, align, offset);
+    } else {
+      if (VM.VERIFY_ASSERTIONS) {
+        VM.assertions._assert(bytes <= Plan.MAX_NON_LOS_COPY_BYTES);
+        if (GenImmix.immixSpace.inImmixCollection())
+          VM.assertions._assert(allocator == GenImmix.ALLOC_MATURE_MAJORGC);
+        else
+          VM.assertions._assert(allocator == GenImmix.ALLOC_MATURE_MINORGC);
+      }
+      if (GenImmix.immixSpace.inImmixDefragCollection()) {
+        return defragCopy.alloc(bytes, align, offset);
+      } else
+        return copy.alloc(bytes, align, offset);
+    }
+  }
+
+  /**
+   * Perform any post-copy actions.
+   *
+   * @param object The newly allocated object
+   * @param typeRef the type reference for the instance being created
+   * @param bytes The size of the space to be allocated (in bytes)
+   */
+  @Inline
+  public final void postCopy(ObjectReference object, ObjectReference typeRef,
+      int bytes, int allocator) {
+    if (allocator == Plan.ALLOC_LOS)
+      Plan.loSpace.initializeHeader(object, false);
+    else {
+      if (VM.VERIFY_ASSERTIONS) {
+        VM.assertions._assert((!GenImmix.immixSpace.inImmixCollection() && allocator == GenImmix.ALLOC_MATURE_MINORGC) ||
+            (GenImmix.immixSpace.inImmixCollection() && allocator == GenImmix.ALLOC_MATURE_MAJORGC));
+      }
+      GenImmix.immixSpace.postCopy(object, bytes, allocator == GenImmix.ALLOC_MATURE_MAJORGC);
+    }
+    if (Gen.USE_OBJECT_BARRIER)
+      Plan.markAsUnlogged(object);
+  }
+
+  /*****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a (local) collection phase.
+   *
+   * @param phaseId Collection phase to perform
+   * @param primary Is this thread to do the one-off thread-local tasks
+   */
+  @NoInline
+  public void collectionPhase(short phaseId, boolean primary) {
+    TraceLocal trace = GenImmix.immixSpace.inImmixDefragCollection() ? defragTrace : matureTrace;
+
+    if (global().traceFullHeap()) {
+      if (phaseId == GenImmix.PREPARE) {
+        super.collectionPhase(phaseId, primary);
+        trace.prepare();
+        copy.reset();
+        if (global().gcFullHeap) {
+          immix.prepare(true);
+          defragCopy.reset();
+        }
+        return;
+      }
+
+      if (phaseId == GenImmix.CLOSURE) {
+        trace.completeTrace();
+        return;
+      }
+
+      if (phaseId == GenImmix.RELEASE) {
+        trace.release();
+        if (global().gcFullHeap) {
+          immix.release(true);
+          copy.reset();
+        }
+        super.collectionPhase(phaseId, primary);
+        return;
+      }
+    }
+
+    super.collectionPhase(phaseId, primary);
+  }
+
+  @Inline
+  public final TraceLocal getFullHeapTrace() {
+    return GenImmix.immixSpace.inImmixDefragCollection() ? defragTrace : matureTrace;
+  }
+
+  /****************************************************************************
+   *
+   * Miscellaneous
+   */
+
+  /** @return The active global plan as a <code>GenImmix</code> instance. */
+  @Inline
+  private static GenImmix global() {
+    return (GenImmix) VM.activePlan.global();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixConstraints.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixConstraints.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixConstraints.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixConstraints.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,34 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.generational.immix;
+
+import org.mmtk.plan.generational.GenConstraints;
+import static org.mmtk.policy.immix.ImmixConstants.MAX_IMMIX_OBJECT_BYTES;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class and its subclasses communicate to the host VM/Runtime
+ * any features of the selected plan that it needs to know.  This is
+ * separate from the main Plan/PlanLocal class in order to bypass any
+ * issues with ordering of static initialization.
+ *
+ */
+ at Uninterruptible
+public class GenImmixConstraints extends GenConstraints {
+  /** @return The specialized scan methods required */
+  @Override
+  public int numSpecializedScans() { return 3; }
+  @Override
+  public int maxNonLOSCopyBytes() { return MAX_IMMIX_OBJECT_BYTES;}
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMatureDefragTraceLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMatureDefragTraceLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMatureDefragTraceLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMatureDefragTraceLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,125 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.generational.immix;
+
+import static org.mmtk.policy.immix.ImmixConstants.MARK_LINE_AT_SCAN_TIME;
+
+import org.mmtk.plan.generational.GenCollector;
+import org.mmtk.plan.generational.GenMatureTraceLocal;
+import org.mmtk.plan.Trace;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.Log;
+import org.mmtk.utility.options.Options;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implments the core functionality for a transitive
+ * closure over the heap graph, specifically in a defragmenting pass over
+ * a generational immix collector.
+ */
+ at Uninterruptible
+public final class GenImmixMatureDefragTraceLocal extends GenMatureTraceLocal{
+
+  /**
+   * Constructor
+   */
+  public GenImmixMatureDefragTraceLocal(Trace global, GenCollector plan) {
+    super(GenImmix.SCAN_DEFRAG, global, plan);
+  }
+
+  /**
+   * Is the specified object live?
+   *
+   * @param object The object.
+   * @return True if the object is live.
+   */
+  public boolean isLive(ObjectReference object) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(GenImmix.immixSpace.inImmixDefragCollection());
+    if (object.isNull()) return false;
+    if (Space.isInSpace(GenImmix.IMMIX, object)) {
+      return GenImmix.immixSpace.isLive(object);
+    }
+    return super.isLive(object);
+  }
+
+  /**
+   * This method is the core method during the trace of the object graph.
+   * The role of this method is to:
+   *
+   * 1. Ensure the traced object is not collected.
+   * 2. If this is the first visit to the object enqueue it to be scanned.
+   * 3. Return the forwarded reference to the object.
+   *
+   * @param object The object to be traced.
+   * @return The new reference to the same object instance.
+   */
+  @Inline
+  public ObjectReference traceObject(ObjectReference object) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(GenImmix.immixSpace.inImmixDefragCollection());
+    if (object.isNull()) return object;
+    if (Space.isInSpace(GenImmix.IMMIX, object))
+      return GenImmix.immixSpace.traceObject(this, object, GenImmix.ALLOC_MATURE_MAJORGC);
+    return super.traceObject(object);
+  }
+
+  @Inline
+  @Override
+  public ObjectReference precopyObject(ObjectReference object) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(GenImmix.immixSpace.inImmixDefragCollection());
+    ObjectReference rtn = traceObject(object);
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(willNotMoveInCurrentCollection(rtn));
+    return rtn;
+  }
+
+  /**
+   * Return true if this object is guaranteed not to move during this
+   * collection (i.e. this object is defintely not an unforwarded
+   * object).
+   *
+   * @param object
+   * @return True if this object is guaranteed not to move during this
+   *         collection.
+   */
+  @Override
+  public boolean willNotMoveInCurrentCollection(ObjectReference object) {
+    if (Space.isInSpace(GenImmix.IMMIX, object)) {
+      return GenImmix.immixSpace.willNotMoveThisGC(object);
+    }
+    return super.willNotMoveInCurrentCollection(object);
+  }
+
+  /**
+   * Collectors that move objects <b>must</b> override this method.
+   * It performs the deferred scanning of objects which are forwarded
+   * during bootstrap of each copying collection.  Because of the
+   * complexities of the collection bootstrap (such objects are
+   * generally themselves gc-critical), the forwarding and scanning of
+   * the objects must be dislocated.  It is an error for a non-moving
+   * collector to call this method.
+   *
+   * @param object The forwarded object to be scanned
+   */
+  @Inline
+  @Override
+  protected void scanObject(ObjectReference object) {
+    if (VM.VERIFY_ASSERTIONS && Options.verbose.getValue() >= 9) {
+      Log.write("SO["); Log.write(object); Log.writeln("]");
+    }
+    super.scanObject(object);
+    if (MARK_LINE_AT_SCAN_TIME && Space.isInSpace(GenImmix.IMMIX, object))
+      GenImmix.immixSpace.markLines(object);
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMatureTraceLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMatureTraceLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMatureTraceLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMatureTraceLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,110 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.generational.immix;
+
+import static org.mmtk.policy.immix.ImmixConstants.MARK_LINE_AT_SCAN_TIME;
+
+import org.mmtk.plan.generational.GenCollector;
+import org.mmtk.plan.generational.GenMatureTraceLocal;
+import org.mmtk.plan.Trace;
+import org.mmtk.policy.Space;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements the core functionality for a transitive
+ * closure over the heap graph, specifically in a generational immix
+ * collector.
+ */
+ at Uninterruptible
+public final class GenImmixMatureTraceLocal extends GenMatureTraceLocal{
+
+  /**
+   * Constructor
+   */
+  public GenImmixMatureTraceLocal(Trace global, GenCollector plan) {
+    super(GenImmix.SCAN_IMMIX, global, plan);
+  }
+
+  /**
+   * This method is the core method during the trace of the object graph.
+   * The role of this method is to:
+   *
+   * 1. Ensure the traced object is not collected.
+   * 2. If this is the first visit to the object enqueue it to be scanned.
+   * 3. Return the forwarded reference to the object.
+   *
+   * @param object The object to be traced.
+   * @return The new reference to the same object instance.
+   */
+  @Inline
+  public ObjectReference traceObject(ObjectReference object) {
+    if (object.isNull()) return object;
+
+    if (Space.isInSpace(GenImmix.IMMIX, object)) {
+      return GenImmix.immixSpace.fastTraceObject(this, object);
+    }
+    return super.traceObject(object);
+  }
+
+  /**
+   * Is the specified object live?
+   *
+   * @param object The object.
+   * @return True if the object is live.
+   */
+  public boolean isLive(ObjectReference object) {
+    if (object.isNull()) return false;
+    if (Space.isInSpace(GenImmix.IMMIX, object)) {
+      return GenImmix.immixSpace.isLive(object);
+    }
+    return super.isLive(object);
+  }
+
+  /**
+   * Return true if this object is guaranteed not to move during this
+   * collection (i.e. this object is defintely not an unforwarded
+   * object).
+   *
+   * @param object
+   * @return True if this object is guaranteed not to move during this
+   *         collection.
+   */
+  @Override
+  public boolean willNotMoveInCurrentCollection(ObjectReference object) {
+    if (Space.isInSpace(GenImmix.IMMIX, object)) {
+      return true;
+    }
+    return super.willNotMoveInCurrentCollection(object);
+  }
+
+  /**
+   * Collectors that move objects <b>must</b> override this method.
+   * It performs the deferred scanning of objects which are forwarded
+   * during bootstrap of each copying collection.  Because of the
+   * complexities of the collection bootstrap (such objects are
+   * generally themselves gc-critical), the forwarding and scanning of
+   * the objects must be dislocated.  It is an error for a non-moving
+   * collector to call this method.
+   *
+   * @param object The forwarded object to be scanned
+   */
+  @Inline
+  @Override
+  protected void scanObject(ObjectReference object) {
+    super.scanObject(object);
+    if (MARK_LINE_AT_SCAN_TIME && Space.isInSpace(GenImmix.IMMIX, object))
+      GenImmix.immixSpace.markLines(object);
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMutator.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMutator.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMutator.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/immix/GenImmixMutator.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,169 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.generational.immix;
+
+import org.mmtk.plan.generational.*;
+import org.mmtk.policy.Space;
+import org.mmtk.policy.immix.MutatorLocal;
+import org.mmtk.utility.alloc.Allocator;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements <i>per-mutator thread</i> behavior and state for
+ * the <code>GenImmix</code> two-generational copying collector.<p>
+ *
+ * Specifically, this class defines mutator-time semantics specific to the
+ * mature generation (<code>GenMutator</code> defines nursery semantics).
+ * In particular the mature space allocator is defined (for mutator-time
+ * allocation into the mature space via pre-tenuring), and the mature space
+ * per-mutator thread collection time semantics are defined (rebinding
+ * the mature space allocator).<p>
+ *
+ * See {@link GenImmix} for a description of the <code>GenImmix</code> algorithm.
+ *
+ * @see GenImmix
+ * @see GenImmixCollector
+ * @see org.mmtk.plan.generational.GenMutator
+ * @see org.mmtk.plan.StopTheWorldMutator
+ * @see org.mmtk.plan.MutatorContext
+ * @see org.mmtk.plan.Phase
+ */
+ at Uninterruptible
+public class GenImmixMutator extends GenMutator {
+
+  /******************************************************************
+   * Instance fields
+   */
+
+  /**
+   * The allocator for the mark-sweep mature space (the mutator may
+   * "pretenure" objects into this space which is otherwise used
+   * only by the collector)
+   */
+  private final MutatorLocal mature;
+
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * Constructor
+   */
+  public GenImmixMutator() {
+    mature = new MutatorLocal(GenImmix.immixSpace, false);
+  }
+
+  /****************************************************************************
+   *
+   * Mutator-time allocation
+   */
+
+  /**
+   * Allocate memory for an object.
+   *
+   * @param bytes The number of bytes required for the object.
+   * @param align Required alignment for the object.
+   * @param offset Offset associated with the alignment.
+   * @param allocator The allocator associated with this request.
+   * @param site Allocation site
+   * @return The low address of the allocated memory.
+   */
+  @Inline
+  public final Address alloc(int bytes, int align, int offset, int allocator, int site) {
+    if (allocator == GenImmix.ALLOC_MATURE) {
+      if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(false); // no pretenuring yet
+      return mature.alloc(bytes, align, offset);
+    }
+    return super.alloc(bytes, align, offset, allocator, site);
+  }
+
+  /**
+   * Perform post-allocation actions.  For many allocators none are
+   * required.
+   *
+   * @param ref The newly allocated object
+   * @param typeRef the type reference for the instance being created
+   * @param bytes The size of the space to be allocated (in bytes)
+   * @param allocator The allocator number to be used for this allocation
+   */
+  @Inline
+  public final void postAlloc(ObjectReference ref, ObjectReference typeRef,
+      int bytes, int allocator) {
+    if (allocator == GenImmix.ALLOC_MATURE) {
+      if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(false); // no pretenuring yet
+    } else {
+      super.postAlloc(ref, typeRef, bytes, allocator);
+    }
+  }
+
+  /**
+   * Return the allocator instance associated with a space
+   * <code>space</code>, for this plan instance.
+   *
+   * @param space The space for which the allocator instance is desired.
+   * @return The allocator instance associated with this plan instance
+   * which is allocating into <code>space</code>, or <code>null</code>
+   * if no appropriate allocator can be established.
+   */
+  public Allocator getAllocatorFromSpace(Space space) {
+    if (space == GenImmix.immixSpace) return mature;
+    return super.getAllocatorFromSpace(space);
+  }
+
+  /*****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a per-mutator collection phase.
+   *
+   * @param phaseId Collection phase to perform
+   * @param primary Is this thread to do the one-off thread-local tasks
+   */
+  @NoInline
+  public void collectionPhase(short phaseId, boolean primary) {
+    if (global().traceFullHeap()) {
+      if (phaseId == GenImmix.PREPARE) {
+        super.collectionPhase(phaseId, primary);
+        if (global().gcFullHeap) mature.prepare();
+        return;
+      }
+
+      if (phaseId == GenImmix.RELEASE) {
+        if (global().gcFullHeap) mature.release();
+        super.collectionPhase(phaseId, primary);
+        return;
+      }
+    }
+
+    super.collectionPhase(phaseId, primary);
+  }
+
+  /****************************************************************************
+   *
+   * Miscellaneous
+   */
+
+  /** @return The active global plan as a <code>GenImmix</code> instance. */
+  @Inline
+  private static GenImmix global() {
+    return (GenImmix) VM.activePlan.global();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMS.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMS.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMS.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMS.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,179 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.generational.marksweep;
+
+import org.mmtk.plan.generational.Gen;
+import org.mmtk.plan.Trace;
+import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.policy.MarkSweepSpace;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.heap.VMRequest;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements the functionality of a two-generation copying
+ * collector where <b>the higher generation is a mark-sweep space</b>
+ * (free list allocation, mark-sweep collection).  Nursery collections
+ * occur when either the heap is full or the nursery is full.  The
+ * nursery size is determined by an optional command line argument.
+ * If undefined, the nursery size is "infinite", so nursery
+ * collections only occur when the heap is full (this is known as a
+ * flexible-sized nursery collector).  Thus both fixed and flexible
+ * nursery sizes are supported.  Full heap collections occur when the
+ * nursery size has dropped to a statically defined threshold,
+ * <code>NURSERY_THRESHOLD</code><p>
+ *
+ * See the Jones & Lins GC book, chapter 7 for a detailed discussion
+ * of generational collection and section 7.3 for an overview of the
+ * flexible nursery behavior ("The Standard ML of New Jersey
+ * collector"), or go to Appel's paper "Simple generational garbage
+ * collection and fast allocation." SP&E 19(2):171--183, 1989.<p>
+ *
+ *
+ * For general comments about the global/local distinction among classes refer
+ * to Plan.java and PlanLocal.java.
+ */
+ at Uninterruptible
+public class GenMS extends Gen {
+
+  /*****************************************************************************
+   *
+   * Class fields
+   */
+
+  /** The mature space, which for GenMS uses a mark sweep collection policy. */
+  public static final MarkSweepSpace msSpace = new MarkSweepSpace("ms", DEFAULT_POLL_FREQUENCY, VMRequest.create());
+
+  public static final int MS = msSpace.getDescriptor();
+
+  /****************************************************************************
+   *
+   * Instance fields
+   */
+
+  /* The trace class for a full-heap collection */
+  public final Trace matureTrace = new Trace(metaDataSpace);
+
+  /*****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a (global) collection phase.
+   */
+  @Inline
+  @Override
+  public final void collectionPhase(short phaseId) {
+    if (traceFullHeap()) {
+      if (phaseId == PREPARE) {
+        super.collectionPhase(phaseId);
+        matureTrace.prepare();
+        msSpace.prepare(true);
+        return;
+      }
+
+      if (phaseId == CLOSURE) {
+        matureTrace.prepare();
+        return;
+      }
+      if (phaseId == RELEASE) {
+        matureTrace.release();
+        msSpace.release();
+        super.collectionPhase(phaseId);
+        return;
+      }
+    }
+    super.collectionPhase(phaseId);
+  }
+
+  /*****************************************************************************
+   *
+   * Accounting
+   */
+
+  /**
+   * Return the number of pages reserved for use given the pending
+   * allocation.
+   *
+   * @return The number of pages reserved given the pending
+   * allocation, excluding space reserved for copying.
+   */
+  @Inline
+  @Override
+  public int getPagesUsed() {
+    return msSpace.reservedPages() + super.getPagesUsed();
+  }
+
+  /**
+   * Calculate the number of pages a collection is required to free to satisfy
+   * outstanding allocation requests.
+   *
+   * @return the number of pages a collection is required to free to satisfy
+   * outstanding allocation requests.
+   */
+  public int getPagesRequired() {
+    return super.getPagesRequired() + msSpace.requiredPages();
+  }
+
+  /**
+   * Return the number of pages available for allocation into the mature
+   * space.
+   *
+   * @return The number of pages available for allocation into the mature
+   * space.
+   */
+  public int getMaturePhysicalPagesAvail() {
+    return (int) (msSpace.availablePhysicalPages()/MarkSweepSpace.WORST_CASE_FRAGMENTATION);
+  }
+
+  /*****************************************************************************
+   *
+   * Miscellaneous
+   */
+
+  /**
+   * Accessor method to allow the generic generational code in Gen.java
+   * to access the mature space.
+   *
+   * @return The active mature space
+   */
+  @Inline
+  protected final Space activeMatureSpace() {
+    return msSpace;
+  }
+
+  /**
+   * @see org.mmtk.plan.Plan#willNeverMove
+   *
+   * @param object Object in question
+   * @return True if the object will never move
+   */
+  @Override
+  public boolean willNeverMove(ObjectReference object) {
+    if (Space.isInSpace(MS, object))
+      return true;
+    return super.willNeverMove(object);
+  }
+
+  /**
+   * Register specialized methods.
+   */
+  @Interruptible
+  protected void registerSpecializedMethods() {
+    TransitiveClosure.registerSpecializedScan(SCAN_MATURE, GenMSMatureTraceLocal.class);
+    super.registerSpecializedMethods();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSCollector.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSCollector.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSCollector.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSCollector.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,175 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.generational.marksweep;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.plan.generational.*;
+import org.mmtk.policy.MarkSweepLocal;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.alloc.Allocator;
+import org.mmtk.utility.statistics.Stats;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements <i>per-collector thread</i> behavior and state for
+ * the <code>GenMS</code> two-generational copying collector.<p>
+ *
+ * Specifically, this class defines semantics specific to the collection of
+ * the mature generation (<code>GenCollector</code> defines nursery semantics).
+ * In particular the mature space allocator is defined (for collection-time
+ * allocation into the mature space), and the mature space per-collector thread
+ * collection time semantics are defined.<p>
+ *
+ * @see GenMS for a description of the <code>GenMS</code> algorithm.
+ *
+ * @see GenMS
+ * @see GenMSMutator
+ * @see GenCollector
+ * @see org.mmtk.plan.StopTheWorldCollector
+ * @see org.mmtk.plan.CollectorContext
+ */
+ at Uninterruptible
+public class GenMSCollector extends GenCollector {
+
+  /*****************************************************************************
+   *
+   * Instance fields
+   */
+
+  /** The allocator for the mature space */
+  private final MarkSweepLocal mature;
+  private final GenMSMatureTraceLocal matureTrace;
+
+  /**
+   * Constructor
+   */
+  public GenMSCollector() {
+    mature = new MarkSweepLocal(GenMS.msSpace);
+    matureTrace = new GenMSMatureTraceLocal(global().matureTrace, this);
+  }
+
+  /****************************************************************************
+   * Collection-time allocation
+   */
+
+  /**
+   * Allocate space for copying an object (this method <i>does not</i>
+   * copy the object, it only allocates space)
+   *
+   * @param original A reference to the original object
+   * @param bytes The size of the space to be allocated (in bytes)
+   * @param align The requested alignment.
+   * @param offset The alignment offset.
+   * @param allocator The allocator to use.
+   * @return The address of the first byte of the allocated region
+   */
+  @Inline
+  @Override
+  public final Address allocCopy(ObjectReference original, int bytes,
+                                 int align, int offset, int allocator) {
+    if (Stats.GATHER_MARK_CONS_STATS) {
+      if (Space.isInSpace(GenMS.NURSERY, original)) GenMS.nurseryMark.inc(bytes);
+    }
+
+    if (allocator == Plan.ALLOC_LOS) {
+      if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Allocator.getMaximumAlignedSize(bytes, align) > Plan.MAX_NON_LOS_COPY_BYTES);
+      return los.alloc(bytes, align, offset);
+    } else {
+      if (VM.VERIFY_ASSERTIONS) {
+        VM.assertions._assert(bytes <= Plan.MAX_NON_LOS_COPY_BYTES);
+        VM.assertions._assert(allocator == GenMS.ALLOC_MATURE_MINORGC ||
+            allocator == GenMS.ALLOC_MATURE_MAJORGC);
+      }
+      return mature.alloc(bytes, align, offset);
+    }
+  }
+
+  /**
+   * Perform any post-copy actions.
+   *
+   * @param object The newly allocated object
+   * @param typeRef the type reference for the instance being created
+   * @param bytes The size of the space to be allocated (in bytes)
+   */
+  @Inline
+  @Override
+  public final void postCopy(ObjectReference object, ObjectReference typeRef,
+                             int bytes, int allocator) {
+    if (allocator == Plan.ALLOC_LOS)
+      Plan.loSpace.initializeHeader(object, false);
+    else
+      GenMS.msSpace.postCopy(object, allocator == GenMS.ALLOC_MATURE_MAJORGC);
+    if (Gen.USE_OBJECT_BARRIER)
+      Plan.markAsUnlogged(object);
+  }
+
+  /*****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a (local) collection phase.
+   *
+   * @param phaseId Collection phase to perform
+   * @param primary Is this thread to do the one-off thread-local tasks
+   */
+  @NoInline
+  public void collectionPhase(short phaseId, boolean primary) {
+    if (global().traceFullHeap()) {
+      if (phaseId == GenMS.PREPARE) {
+        super.collectionPhase(phaseId, primary);
+        matureTrace.prepare();
+        if (global().gcFullHeap) mature.prepare();
+        return;
+      }
+
+      if (phaseId == GenMS.CLOSURE) {
+        matureTrace.completeTrace();
+        return;
+      }
+
+      if (phaseId == GenMS.RELEASE) {
+        matureTrace.release();
+        if (global().gcFullHeap) {
+          mature.release();
+        }
+        super.collectionPhase(phaseId, primary);
+        return;
+      }
+    }
+
+    super.collectionPhase(phaseId, primary);
+  }
+
+  @Inline
+  public final TraceLocal getFullHeapTrace() {
+    return matureTrace;
+  }
+
+  /****************************************************************************
+   *
+   * Miscellaneous
+   */
+
+  /** @return The active global plan as a <code>GenMS</code> instance. */
+  @Inline
+  private static GenMS global() {
+    return (GenMS) VM.activePlan.global();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSConstraints.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSConstraints.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSConstraints.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSConstraints.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,30 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.generational.marksweep;
+
+import org.mmtk.plan.generational.GenConstraints;
+import static org.mmtk.policy.SegregatedFreeListSpace.MAX_FREELIST_OBJECT_BYTES;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class and its subclasses communicate to the host VM/Runtime
+ * any features of the selected plan that it needs to know.  This is
+ * separate from the main Plan/PlanLocal class in order to bypass any
+ * issues with ordering of static initialization.
+ */
+ at Uninterruptible
+public class GenMSConstraints extends GenConstraints {
+  @Override
+  public int maxNonLOSCopyBytes() { return MAX_FREELIST_OBJECT_BYTES;}
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSMatureTraceLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSMatureTraceLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSMatureTraceLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSMatureTraceLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,88 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.generational.marksweep;
+
+import org.mmtk.plan.generational.GenCollector;
+import org.mmtk.plan.generational.GenMatureTraceLocal;
+import org.mmtk.plan.Trace;
+import org.mmtk.policy.Space;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implments the core functionality for a transitive
+ * closure over the heap graph, specifically in a Generational Mark-Sweep
+ * collector.
+ */
+ at Uninterruptible
+public final class GenMSMatureTraceLocal extends GenMatureTraceLocal{
+
+  /**
+   * Constructor
+   */
+  public GenMSMatureTraceLocal(Trace global, GenCollector plan) {
+    super(global, plan);
+  }
+
+  /**
+   * This method is the core method during the trace of the object graph.
+   * The role of this method is to:
+   *
+   * 1. Ensure the traced object is not collected.
+   * 2. If this is the first visit to the object enqueue it to be scanned.
+   * 3. Return the forwarded reference to the object.
+   *
+   * @param object The object to be traced.
+   * @return The new reference to the same object instance.
+   */
+  @Inline
+  public ObjectReference traceObject(ObjectReference object) {
+    if (object.isNull()) return object;
+
+    if (Space.isInSpace(GenMS.MS, object)) {
+      return GenMS.msSpace.traceObject(this, object);
+    }
+    return super.traceObject(object);
+  }
+
+  /**
+   * Is the specified object live?
+   *
+   * @param object The object.
+   * @return True if the object is live.
+   */
+  public boolean isLive(ObjectReference object) {
+    if (object.isNull()) return false;
+    if (Space.isInSpace(GenMS.MS, object)) {
+      return GenMS.msSpace.isLive(object);
+    }
+    return super.isLive(object);
+  }
+
+  /**
+   * Return true if this object is guaranteed not to move during this
+   * collection (i.e. this object is defintely not an unforwarded
+   * object).
+   *
+   * @param object
+   * @return True if this object is guaranteed not to move during this
+   *         collection.
+   */
+  public boolean willNotMoveInCurrentCollection(ObjectReference object) {
+    if (Space.isInSpace(GenMS.MS, object)) {
+      return true;
+    }
+    return super.willNotMoveInCurrentCollection(object);
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSMutator.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSMutator.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSMutator.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/generational/marksweep/GenMSMutator.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,176 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.generational.marksweep;
+
+import org.mmtk.plan.generational.*;
+import org.mmtk.policy.MarkSweepLocal;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.alloc.Allocator;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements <i>per-mutator thread</i> behavior and state for
+ * the <code>GenMS</code> two-generational copying collector.<p>
+ *
+ * Specifically, this class defines mutator-time semantics specific to the
+ * mature generation (<code>GenMutator</code> defines nursery semantics).
+ * In particular the mature space allocator is defined (for mutator-time
+ * allocation into the mature space via pre-tenuring), and the mature space
+ * per-mutator thread collection time semantics are defined (rebinding
+ * the mature space allocator).<p>
+ *
+ * See {@link GenMS} for a description of the <code>GenMS</code> algorithm.
+ *
+ * @see GenMS
+ * @see GenMSCollector
+ * @see GenMutator
+ * @see org.mmtk.plan.StopTheWorldMutator
+ * @see org.mmtk.plan.MutatorContext
+ */
+ at Uninterruptible
+public class GenMSMutator extends GenMutator {
+  /******************************************************************
+   * Instance fields
+   */
+
+  /**
+   * The allocator for the mark-sweep mature space (the mutator may
+   * "pretenure" objects into this space which is otherwise used
+   * only by the collector)
+   */
+  private final MarkSweepLocal mature;
+
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * Constructor
+   */
+  public GenMSMutator() {
+    mature = new MarkSweepLocal(GenMS.msSpace);
+  }
+
+  /****************************************************************************
+   *
+   * Mutator-time allocation
+   */
+
+  /**
+   * Allocate memory for an object.
+   *
+   * @param bytes The number of bytes required for the object.
+   * @param align Required alignment for the object.
+   * @param offset Offset associated with the alignment.
+   * @param allocator The allocator associated with this request.
+   * @param site Allocation site
+   * @return The low address of the allocated memory.
+   */
+  @Inline
+  public final Address alloc(int bytes, int align, int offset, int allocator, int site) {
+    if (allocator == GenMS.ALLOC_MATURE) {
+      return mature.alloc(bytes, align, offset);
+    }
+    return super.alloc(bytes, align, offset, allocator, site);
+  }
+
+  /**
+   * Perform post-allocation actions.  For many allocators none are
+   * required.
+   *
+   * @param ref The newly allocated object
+   * @param typeRef the type reference for the instance being created
+   * @param bytes The size of the space to be allocated (in bytes)
+   * @param allocator The allocator number to be used for this allocation
+   */
+  @Inline
+  public final void postAlloc(ObjectReference ref, ObjectReference typeRef,
+      int bytes, int allocator) {
+    if (allocator == GenMS.ALLOC_MATURE) {
+      GenMS.msSpace.initializeHeader(ref, true);
+    } else {
+      super.postAlloc(ref, typeRef, bytes, allocator);
+    }
+  }
+
+  /**
+   * Return the allocator instance associated with a space
+   * <code>space</code>, for this plan instance.
+   *
+   * @param space The space for which the allocator instance is desired.
+   * @return The allocator instance associated with this plan instance
+   * which is allocating into <code>space</code>, or <code>null</code>
+   * if no appropriate allocator can be established.
+   */
+  public Allocator getAllocatorFromSpace(Space space) {
+    if (space == GenMS.msSpace) return mature;
+    return super.getAllocatorFromSpace(space);
+  }
+
+  /*****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a per-mutator collection phase.
+   *
+   * @param phaseId Collection phase to perform
+   * @param primary Is this thread to do the one-off thread-local tasks
+   */
+  @NoInline
+  public void collectionPhase(short phaseId, boolean primary) {
+    if (global().traceFullHeap()) {
+      if (phaseId == GenMS.PREPARE) {
+        super.collectionPhase(phaseId, primary);
+        if (global().gcFullHeap) mature.prepare();
+        return;
+      }
+
+      if (phaseId == GenMS.RELEASE) {
+        if (global().gcFullHeap) mature.release();
+        super.collectionPhase(phaseId, primary);
+        return;
+      }
+    }
+
+    super.collectionPhase(phaseId, primary);
+  }
+
+  /**
+   * Flush mutator context, in response to a requestMutatorFlush.
+   * Also called by the default implementation of deinitMutator.
+   */
+  @Override
+  public void flush() {
+    super.flush();
+    mature.flush();
+  }
+
+  /****************************************************************************
+   *
+   * Miscellaneous
+   */
+
+  /** @return The active global plan as a <code>GenMS</code> instance. */
+  @Inline
+  private static GenMS global() {
+    return (GenMS) VM.activePlan.global();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/Immix.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/Immix.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/Immix.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/Immix.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,179 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.immix;
+
+import org.mmtk.plan.*;
+import org.mmtk.policy.Space;
+import org.mmtk.policy.immix.ImmixSpace;
+import org.mmtk.policy.immix.ObjectHeader;
+import org.mmtk.utility.heap.VMRequest;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements the global state of an immix collector.
+ *
+ * See the PLDI'08 paper by Blackburn and McKinley for a description
+ * of the algorithm: http://doi.acm.org/10.1145/1375581.1375586
+ *
+ * All plans make a clear distinction between <i>global</i> and
+ * <i>thread-local</i> activities, and divides global and local state
+ * into separate class hierarchies.  Global activities must be
+ * synchronized, whereas no synchronization is required for
+ * thread-local activities.  There is a single instance of Plan (or the
+ * appropriate sub-class), and a 1:1 mapping of PlanLocal to "kernel
+ * threads" (aka CPUs or in Jikes RVM, Processors).  Thus instance
+ * methods of PlanLocal allow fast, unsychronized access to functions such as
+ * allocation and collection.
+ *
+ * The global instance defines and manages static resources
+ * (such as memory and virtual memory resources).  This mapping of threads to
+ * instances is crucial to understanding the correctness and
+ * performance properties of MMTk plans.
+ */
+ at Uninterruptible
+public class Immix extends StopTheWorld {
+
+  /****************************************************************************
+   * Constants
+   */
+
+  /****************************************************************************
+   * Class variables
+   */
+  public static final ImmixSpace immixSpace = new ImmixSpace("immix", DEFAULT_POLL_FREQUENCY, VMRequest.create());
+  public static final int IMMIX = immixSpace.getDescriptor();
+
+  public static final int SCAN_IMMIX = 0;
+  public static final int SCAN_DEFRAG = 1;
+
+  /****************************************************************************
+   * Instance variables
+   */
+
+  public final Trace immixTrace = new Trace(metaDataSpace);
+  /** will the next collection collect the whole heap? */
+  public boolean nextGCWholeHeap = true;
+  /** will this collection collect the whole heap */
+  public boolean collectWholeHeap = nextGCWholeHeap;
+  protected boolean lastGCWasDefrag = false;
+
+  /**
+   * Constructor.
+   *
+   */
+  public Immix() {
+  }
+
+  /*****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a (global) collection phase.
+   *
+   * @param phaseId Collection phase to execute.
+   */
+  @Inline
+  public void collectionPhase(short phaseId) {
+    if (phaseId == SET_COLLECTION_KIND) {
+      super.collectionPhase(phaseId);
+      immixSpace.decideWhetherToDefrag(emergencyCollection, collectWholeHeap, collectionAttempt, collectionTrigger);
+      return;
+    }
+
+    if (phaseId == PREPARE) {
+      super.collectionPhase(phaseId);
+      immixTrace.prepare();
+      immixSpace.prepare(true);
+      return;
+    }
+
+    if (phaseId == CLOSURE) {
+      immixTrace.prepare();
+      return;
+    }
+
+    if (phaseId == RELEASE) {
+      immixTrace.release();
+      lastGCWasDefrag = immixSpace.release(true);
+      super.collectionPhase(phaseId);
+      return;
+    }
+
+    super.collectionPhase(phaseId);
+  }
+
+  /**
+   * @return Whether last GC was an exhaustive attempt to collect the heap.  For many collectors this is the same as asking whether the last GC was a full heap collection.
+   */
+  @Override
+  public boolean lastCollectionWasExhaustive() {
+    return lastGCWasDefrag;
+  }
+
+  /*****************************************************************************
+   *
+   * Accounting
+   */
+
+  /**
+   * Return the number of pages reserved for use given the pending
+   * allocation.  The superclass accounts for its spaces, we just
+   * augment this with the mark-sweep space's contribution.
+   *
+   * @return The number of pages reserved given the pending
+   * allocation, excluding space reserved for copying.
+   */
+  public int getPagesUsed() {
+    return immixSpace.reservedPages() + super.getPagesUsed();
+  }
+
+  /**
+   * Calculate the number of pages a collection is required to free to satisfy
+   * outstanding allocation requests.
+   *
+   * @return the number of pages a collection is required to free to satisfy
+   * outstanding allocation requests.
+   */
+  public int getPagesRequired() {
+    return super.getPagesRequired() + immixSpace.requiredPages();
+  }
+
+  /**
+   * @see org.mmtk.plan.Plan#willNeverMove
+   *
+   * @param object Object in question
+   * @return True if the object will never move
+   */
+  @Override
+  public boolean willNeverMove(ObjectReference object) {
+    if (Space.isInSpace(IMMIX, object)) {
+      ObjectHeader.pinObject(object);
+      return true;
+    } else
+      return super.willNeverMove(object);
+  }
+
+  /**
+   * Register specialized methods.
+   */
+  @Interruptible
+  protected void registerSpecializedMethods() {
+    TransitiveClosure.registerSpecializedScan(SCAN_IMMIX, ImmixTraceLocal.class);
+    TransitiveClosure.registerSpecializedScan(SCAN_DEFRAG, ImmixDefragTraceLocal.class);
+    super.registerSpecializedMethods();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixCollector.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixCollector.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixCollector.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixCollector.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,175 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.immix;
+
+import org.mmtk.plan.*;
+import org.mmtk.policy.ImmortalLocal;
+import org.mmtk.policy.immix.CollectorLocal;
+import org.mmtk.utility.alloc.BumpPointer;
+import org.mmtk.utility.alloc.ImmixAllocator;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.Address;
+import org.vmmagic.unboxed.ObjectReference;
+
+/**
+ * This class implements <i>per-collector thread</i> behavior
+ * and state for the <i>Immix</i> plan, which implements a full-heap
+ * immix collector.<p>
+ *
+ * Specifically, this class defines <i>Immix</i> collection behavior
+ * (through <code>fastTrace</code> and the <code>collectionPhase</code>
+ * method).<p>
+ *
+ * @see Immix for an overview of the immix algorithm.<p>
+ *
+ * FIXME The SegregatedFreeList class (and its decendents such as
+ * MarkSweepLocal) does not properly separate mutator and collector
+ * behaviors, so the immix field below should really not exist in
+ * this class as there is no collection-time allocation in this
+ * collector.
+ *
+ * @see Immix
+ * @see org.mmtk.policy.immix.MutatorLocal
+ * @see StopTheWorldCollector
+ * @see CollectorContext
+ * @see Phase
+ */
+ at Uninterruptible
+public class ImmixCollector extends StopTheWorldCollector {
+
+  /****************************************************************************
+   * Instance fields
+   */
+   protected ImmixTraceLocal fastTrace;
+   protected ImmixDefragTraceLocal defragTrace;
+   protected CollectorLocal immix;
+   protected final ImmixAllocator copy;
+   protected final BumpPointer immortal;
+   protected TraceLocal currentTrace;
+
+  /****************************************************************************
+   * Initialization
+   */
+
+  /**
+   * Constructor
+   */
+  public ImmixCollector() {
+    fastTrace = new ImmixTraceLocal(global().immixTrace, null);
+    defragTrace = new ImmixDefragTraceLocal(global().immixTrace, null);
+    immix = new CollectorLocal(Immix.immixSpace);
+    copy = new ImmixAllocator(Immix.immixSpace, true, true);
+    immortal = new ImmortalLocal(Plan.immortalSpace);
+  }
+
+ /****************************************************************************
+  *
+  * Collection-time allocation
+  */
+
+ /**
+  * Allocate space for copying an object (this method <i>does not</i>
+  * copy the object, it only allocates space)
+  *
+  * @param original A reference to the original object
+  * @param bytes The size of the space to be allocated (in bytes)
+  * @param align The requested alignment.
+  * @param offset The alignment offset.
+  * @return The address of the first byte of the allocated region
+  */
+  @Inline
+  public Address allocCopy(ObjectReference original, int bytes,
+      int align, int offset, int allocator) {
+    if (VM.VERIFY_ASSERTIONS) {
+      VM.assertions._assert(bytes <= Plan.MAX_NON_LOS_COPY_BYTES);
+      VM.assertions._assert(allocator == Immix.ALLOC_DEFAULT);
+    }
+    return copy.alloc(bytes, align, offset);
+  }
+
+ /**
+  * Perform any post-copy actions.
+  *
+  * @param object The newly allocated object
+  * @param typeRef the type reference for the instance being created
+  * @param bytes The size of the space to be allocated (in bytes)
+  */
+  @Inline
+  public void postCopy(ObjectReference object, ObjectReference typeRef,
+      int bytes, int allocator) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(allocator == Immix.ALLOC_DEFAULT);
+    Immix.immixSpace.postCopy(object, bytes, true);
+
+    if (VM.VERIFY_ASSERTIONS) {
+      VM.assertions._assert(getCurrentTrace().isLive(object));
+      VM.assertions._assert(getCurrentTrace().willNotMoveInCurrentCollection(object));
+    }
+  }
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a per-collector collection phase.
+   *
+   * @param phaseId The collection phase to perform
+   * @param primary Perform any single-threaded activities using this thread.
+   */
+  @Inline
+  public void collectionPhase(short phaseId, boolean primary) {
+
+    if (phaseId == Immix.PREPARE) {
+      super.collectionPhase(phaseId, primary);
+      currentTrace = Immix.immixSpace.inImmixDefragCollection() ? defragTrace : fastTrace;
+      immix.prepare(true);
+      currentTrace.prepare();
+      copy.reset();
+      return;
+    }
+
+    if (phaseId == Immix.CLOSURE) {
+      currentTrace.completeTrace();
+      return;
+    }
+
+    if (phaseId == Immix.RELEASE) {
+      currentTrace.release();
+      immix.release(true);
+      super.collectionPhase(phaseId, primary);
+      return;
+    }
+
+    super.collectionPhase(phaseId, primary);
+  }
+
+  /****************************************************************************
+   *
+   * Miscellaneous
+   */
+
+  /** @return The active global plan as an <code>Immix</code> instance. */
+  @Inline
+  private static Immix global() {
+    return (Immix) VM.activePlan.global();
+  }
+
+  /** @return The current fastTrace instance. */
+  @Inline
+  public final TraceLocal getCurrentTrace() {
+    return currentTrace;
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixConstraints.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixConstraints.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixConstraints.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixConstraints.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,53 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.immix;
+
+import org.mmtk.plan.StopTheWorldConstraints;
+import org.mmtk.policy.immix.ObjectHeader;
+import static org.mmtk.policy.immix.ImmixConstants.MAX_IMMIX_OBJECT_BYTES;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class and its subclasses communicate to the host VM/Runtime
+ * any features of the selected plan that it needs to know.  This is
+ * separate from the main Plan/PlanLocal class in order to bypass any
+ * issues with ordering of static initialization.
+ */
+ at Uninterruptible
+public class ImmixConstraints extends StopTheWorldConstraints {
+
+  /** @return The number of header bits that are required. */
+  @Override
+  public int gcHeaderBits() { return ObjectHeader.LOCAL_GC_BITS_REQUIRED; }
+
+  /** @return The number of header words that are required. */
+  @Override
+  public int gcHeaderWords() { return ObjectHeader.GC_HEADER_WORDS_REQUIRED; }
+
+  /** @return True if this plan moves objects. */
+  @Override
+  public boolean movesObjects() { return true;}
+
+  /** @return The specialized scan methods required */
+  @Override
+  public int numSpecializedScans() { return 2; }
+
+  /** @return Size (in bytes) beyond which new regular objects must be allocated to the LOS */
+  @Override
+  public int maxNonLOSDefaultAllocBytes() { return MAX_IMMIX_OBJECT_BYTES; }
+
+  /** @return Size (in bytes) beyond which copied objects must be copied to the LOS */
+  @Override
+  public int maxNonLOSCopyBytes() { return MAX_IMMIX_OBJECT_BYTES; }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixDefragTraceLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixDefragTraceLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixDefragTraceLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixDefragTraceLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,152 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.immix;
+
+import static org.mmtk.policy.immix.ImmixConstants.MARK_LINE_AT_SCAN_TIME;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.plan.Trace;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.deque.ObjectReferenceDeque;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements the thread-local functionality for a defragmenting
+ * transitive closure over an immix space.
+ */
+ at Uninterruptible
+public final class ImmixDefragTraceLocal extends TraceLocal {
+
+  /****************************************************************************
+  *
+  * Instance fields
+  */
+ private final ObjectReferenceDeque modBuffer;
+
+ /**
+   * Constructor
+   * @param modBuffer TODO
+   */
+  public ImmixDefragTraceLocal(Trace trace, ObjectReferenceDeque modBuffer) {
+    super(Immix.SCAN_DEFRAG, trace);
+    this.modBuffer = modBuffer;
+  }
+
+  /****************************************************************************
+   *
+   * Externally visible Object processing and tracing
+   */
+
+  /**
+   * Is the specified object live?
+   *
+   * @param object The object.
+   * @return True if the object is live.
+   */
+  public boolean isLive(ObjectReference object) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Immix.immixSpace.inImmixDefragCollection());
+    if (object.isNull()) return false;
+    if (Space.isInSpace(Immix.IMMIX, object)) {
+      return Immix.immixSpace.isLive(object);
+    }
+    return super.isLive(object);
+  }
+
+  /**
+   * This method is the core method during the trace of the object graph.
+   * The role of this method is to:
+   *
+   * 1. Ensure the traced object is not collected.
+   * 2. If this is the first visit to the object enqueue it to be scanned.
+   * 3. Return the forwarded reference to the object.
+   *
+   * In this instance, we refer objects in the mark-sweep space to the
+   * immixSpace for tracing, and defer to the superclass for all others.
+   *
+   * @param object The object to be traced.
+   * @return The new reference to the same object instance.
+   */
+  @Inline
+  public ObjectReference traceObject(ObjectReference object) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Immix.immixSpace.inImmixDefragCollection());
+    if (object.isNull()) return object;
+    if (Space.isInSpace(Immix.IMMIX, object))
+      return Immix.immixSpace.traceObject(this, object, Plan.ALLOC_DEFAULT);
+    return super.traceObject(object);
+  }
+
+  @Inline
+  @Override
+  public ObjectReference precopyObject(ObjectReference object) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Immix.immixSpace.inImmixDefragCollection());
+    ObjectReference rtn = traceObject(object);
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(willNotMoveInCurrentCollection(rtn));
+    return rtn;
+  }
+
+  /**
+   * Return true if this object is guaranteed not to move during this
+   * collection (i.e. this object is defintely not an unforwarded
+   * object).
+   *
+   * @param object
+   * @return True if this object is guaranteed not to move during this
+   *         collection.
+   */
+  @Override
+  public boolean willNotMoveInCurrentCollection(ObjectReference object) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Immix.immixSpace.inImmixDefragCollection());
+    if (Space.isInSpace(Immix.IMMIX, object))
+      return Immix.immixSpace.willNotMoveThisGC(object);
+    return true;
+  }
+
+  /**
+   * Collectors that move objects <b>must</b> override this method.
+   * It performs the deferred scanning of objects which are forwarded
+   * during bootstrap of each copying collection.  Because of the
+   * complexities of the collection bootstrap (such objects are
+   * generally themselves gc-critical), the forwarding and scanning of
+   * the objects must be dislocated.  It is an error for a non-moving
+   * collector to call this method.
+   *
+   * @param object The forwarded object to be scanned
+   */
+  @Inline
+  @Override
+  protected void scanObject(ObjectReference object) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Immix.immixSpace.inImmixDefragCollection());
+    super.scanObject(object);
+    if (MARK_LINE_AT_SCAN_TIME && Space.isInSpace(Immix.IMMIX, object))
+      Immix.immixSpace.markLines(object);
+  }
+
+  /**
+   * Process any remembered set entries.  This means enumerating the
+   * mod buffer and for each entry, marking the object as unlogged
+   * (we don't enqueue for scanning since we're doing a full heap GC).
+   */
+  protected void processRememberedSets() {
+    if (modBuffer != null) {
+      logMessage(5, "clearing modBuffer");
+      while (!modBuffer.isEmpty()) {
+        ObjectReference src = modBuffer.pop();
+        Plan.markAsUnlogged(src);
+      }
+    }
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixMutator.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixMutator.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixMutator.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixMutator.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,142 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.immix;
+
+import org.mmtk.plan.*;
+import org.mmtk.policy.Space;
+import org.mmtk.policy.immix.MutatorLocal;
+
+import org.mmtk.utility.alloc.Allocator;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements <i>per-mutator thread</i> behavior
+ * and state for the <i>Immix</i> plan, which implements a full-heap
+ * immix collector.<p>
+ *
+ * Specifically, this class defines <i>Immix</i> mutator-time allocation
+ * and per-mutator thread collection semantics (flushing and restoring
+ * per-mutator allocator state).<p>
+ *
+ * @see Immix
+ * @see org.mmtk.policy.immix.CollectorLocal
+ * @see StopTheWorldMutator
+ * @see MutatorContext
+ */
+ at Uninterruptible
+public class ImmixMutator extends StopTheWorldMutator {
+
+  /****************************************************************************
+   * Instance fields
+   */
+  protected final MutatorLocal immix;
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * Constructor
+   */
+  public ImmixMutator() {
+    immix = new org.mmtk.policy.immix.MutatorLocal(Immix.immixSpace, false);
+  }
+
+  /****************************************************************************
+   *
+   * MutatorLocal-time allocation
+   */
+
+  /**
+   * Allocate memory for an object. This class handles the default allocator
+   * from the mark sweep space, and delegates everything else to the
+   * superclass.
+   *
+   * @param bytes The number of bytes required for the object.
+   * @param align Required alignment for the object.
+   * @param offset Offset associated with the alignment.
+   * @param allocator The allocator associated with this request.
+   * @return The low address of the allocated memory.
+   */
+  @Inline
+  public Address alloc(int bytes, int align, int offset, int allocator, int site) {
+    if (allocator == Immix.ALLOC_DEFAULT)
+      return immix.alloc(bytes, align, offset);
+    return super.alloc(bytes, align, offset, allocator, site);
+  }
+
+  /**
+   * Perform post-allocation actions.  Initialize the object header for
+   * objects in the mark-sweep space, and delegate to the superclass for
+   * other objects.
+   *
+   * @param ref The newly allocated object
+   * @param typeRef the type reference for the instance being created
+   * @param bytes The size of the space to be allocated (in bytes)
+   * @param allocator The allocator number to be used for this allocation
+   */
+  @Inline
+  public void postAlloc(ObjectReference ref, ObjectReference typeRef,
+      int bytes, int allocator) {
+    if (allocator == Immix.ALLOC_DEFAULT)
+      Immix.immixSpace.postAlloc(ref, bytes);
+    else
+      super.postAlloc(ref, typeRef, bytes, allocator);
+  }
+
+  /**
+   * Return the allocator instance associated with a space
+   * <code>space</code>, for this plan instance.
+   *
+   * @param space The space for which the allocator instance is desired.
+   * @return The allocator instance associated with this plan instance
+   * which is allocating into <code>space</code>, or <code>null</code>
+   * if no appropriate allocator can be established.
+   */
+  public Allocator getAllocatorFromSpace(Space space) {
+    if (space == Immix.immixSpace) return immix;  // FIXME is it not a problem that we have a 2:1 mapping?
+    return super.getAllocatorFromSpace(space);
+  }
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a per-mutator collection phase.
+   *
+   * @param phaseId The collection phase to perform
+   * @param primary Perform any single-threaded activities using this thread.
+   */
+  @Inline
+  public void collectionPhase(short phaseId, boolean primary) {
+
+    if (phaseId == Immix.PREPARE) {
+      super.collectionPhase(phaseId, primary);
+      immix.prepare();
+      return;
+    }
+
+    if (phaseId == Immix.RELEASE) {
+      immix.release();
+      super.collectionPhase(phaseId, primary);
+      return;
+    }
+
+    super.collectionPhase(phaseId, primary);
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixTraceLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixTraceLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixTraceLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/immix/ImmixTraceLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,140 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.immix;
+
+import static org.mmtk.policy.immix.ImmixConstants.MARK_LINE_AT_SCAN_TIME;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.plan.Trace;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.deque.ObjectReferenceDeque;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements the thread-local functionality for a transitive
+ * closure over an immix space.
+ */
+ at Uninterruptible
+public final class ImmixTraceLocal extends TraceLocal {
+
+  /****************************************************************************
+  *
+  * Instance fields
+  */
+ private final ObjectReferenceDeque modBuffer;
+
+  /**
+   * Constructor
+   *
+   * @param trace The trace associated with this trace local.
+   * @param modBuffer The modified objects buffer associated with this trace local.  Possibly null.
+   */
+  public ImmixTraceLocal(Trace trace, ObjectReferenceDeque modBuffer) {
+    super(Immix.SCAN_IMMIX, trace);
+    this.modBuffer = modBuffer;
+  }
+
+  /****************************************************************************
+   *
+   * Externally visible Object processing and tracing
+   */
+
+  /**
+   * Is the specified object live?
+   *
+   * @param object The object.
+   * @return True if the object is live.
+   */
+  public boolean isLive(ObjectReference object) {
+    if (object.isNull()) return false;
+    if (Space.isInSpace(Immix.IMMIX, object)) {
+      return Immix.immixSpace.fastIsLive(object);
+    }
+    return super.isLive(object);
+  }
+
+  /**
+   * This method is the core method during the trace of the object graph.
+   * The role of this method is to:
+   *
+   * 1. Ensure the traced object is not collected.
+   * 2. If this is the first visit to the object enqueue it to be scanned.
+   * 3. Return the forwarded reference to the object.
+   *
+   * In this instance, we refer objects in the mark-sweep space to the
+   * immixSpace for tracing, and defer to the superclass for all others.
+   *
+   * @param object The object to be traced.
+   * @return The new reference to the same object instance.
+   */
+  @Inline
+  public ObjectReference traceObject(ObjectReference object) {
+    if (object.isNull()) return object;
+    if (Space.isInSpace(Immix.IMMIX, object))
+      return Immix.immixSpace.fastTraceObject(this, object);
+    return super.traceObject(object);
+  }
+
+  /**
+   * Ensure that the referenced object will not move from this point through
+   * to the end of the collection. This can involve forwarding the object
+   * if necessary.
+   *
+   * @param object The object that must not move during the collection.
+   * @return True If the object will not move during collection
+   */
+  @Inline
+  @Override
+  public boolean willNotMoveInCurrentCollection(ObjectReference object) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!Immix.immixSpace.inImmixDefragCollection());
+    return true;
+  }
+
+  /**
+   * Collectors that move objects <b>must</b> override this method.
+   * It performs the deferred scanning of objects which are forwarded
+   * during bootstrap of each copying collection.  Because of the
+   * complexities of the collection bootstrap (such objects are
+   * generally themselves gc-critical), the forwarding and scanning of
+   * the objects must be dislocated.  It is an error for a non-moving
+   * collector to call this method.
+   *
+   * @param object The forwarded object to be scanned
+   */
+  @Inline
+  @Override
+  protected void scanObject(ObjectReference object) {
+    super.scanObject(object);
+    if (MARK_LINE_AT_SCAN_TIME && Space.isInSpace(Immix.IMMIX, object))
+      Immix.immixSpace.markLines(object);
+  }
+
+  /**
+   * Process any remembered set entries.  This means enumerating the
+   * mod buffer and for each entry, marking the object as unlogged
+   * (we don't enqueue for scanning since we're doing a full heap GC).
+   */
+  protected void processRememberedSets() {
+    if (modBuffer != null) {
+      logMessage(5, "clearing modBuffer");
+      while (!modBuffer.isEmpty()) {
+        ObjectReference src = modBuffer.pop();
+        Plan.markAsUnlogged(src);
+      }
+    }
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MC.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MC.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MC.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MC.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,229 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.markcompact;
+
+import org.mmtk.plan.*;
+import org.mmtk.policy.MarkCompactSpace;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.heap.VMRequest;
+import org.mmtk.utility.sanitychecker.SanityChecker;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.ObjectReference;
+
+/**
+ * This class implements the global state of a simple sliding mark-compact
+ * collector.
+ *
+ * FIXME Need algorithmic overview and references.
+ *
+ * All plans make a clear distinction between <i>global</i> and
+ * <i>thread-local</i> activities, and divides global and local state
+ * into separate class hierarchies.  Global activities must be
+ * synchronized, whereas no synchronization is required for
+ * thread-local activities.  There is a single instance of Plan (or the
+ * appropriate sub-class), and a 1:1 mapping of PlanLocal to "kernel
+ * threads" (aka CPUs).  Thus instance
+ * methods of PlanLocal allow fast, unsychronized access to functions such as
+ * allocation and collection.
+ *
+ * The global instance defines and manages static resources
+ * (such as memory and virtual memory resources).  This mapping of threads to
+ * instances is crucial to understanding the correctness and
+ * performance properties of MMTk plans.
+ */
+ at Uninterruptible public class MC extends StopTheWorld {
+
+  /****************************************************************************
+   * Class variables
+   */
+
+  public static final MarkCompactSpace mcSpace = new MarkCompactSpace("mc", DEFAULT_POLL_FREQUENCY, VMRequest.create(0.6f));
+  public static final int MARK_COMPACT = mcSpace.getDescriptor();
+
+  public static final int SCAN_MARK    = 0;
+  public static final int SCAN_FORWARD = 1;
+
+  /* Phases */
+  public static final short PREPARE_FORWARD     = Phase.createSimple("fw-prepare");
+  public static final short FORWARD_CLOSURE     = Phase.createSimple("fw-closure");
+  public static final short RELEASE_FORWARD     = Phase.createSimple("fw-release");
+
+  /* FIXME these two phases need to be made per-collector phases */
+  public static final short CALCULATE_FP        = Phase.createSimple("calc-fp");
+  public static final short COMPACT             = Phase.createSimple("compact");
+
+  // CHECKSTYLE:OFF
+
+  /**
+   * This is the phase that is executed to perform a mark-compact collection.
+   *
+   * FIXME: Far too much duplication and inside knowledge of StopTheWorld
+   */
+  public short mcCollection = Phase.createComplex("collection", null,
+      Phase.scheduleComplex  (initPhase),
+      Phase.scheduleComplex  (rootClosurePhase),
+      Phase.scheduleComplex  (refTypeClosurePhase),
+      Phase.scheduleComplex  (completeClosurePhase),
+      Phase.scheduleMutator  (CALCULATE_FP),
+      Phase.scheduleGlobal   (PREPARE_FORWARD),
+      Phase.scheduleCollector(PREPARE_FORWARD),
+      Phase.scheduleMutator  (PREPARE),
+      Phase.scheduleCollector(STACK_ROOTS),
+      Phase.scheduleCollector(ROOTS),
+      Phase.scheduleGlobal   (ROOTS),
+      Phase.scheduleComplex  (forwardPhase),
+      Phase.scheduleCollector(FORWARD_CLOSURE),
+      Phase.scheduleMutator  (RELEASE),
+      Phase.scheduleCollector(RELEASE_FORWARD),
+      Phase.scheduleGlobal   (RELEASE_FORWARD),
+      Phase.scheduleMutator  (COMPACT),
+      Phase.scheduleComplex  (finishPhase));
+
+  // CHECKSTYLE:ON
+
+  /****************************************************************************
+   * Instance variables
+   */
+
+  public final Trace markTrace;
+  public final Trace forwardTrace;
+
+  /**
+   * Constructor.
+ */
+  public MC() {
+    markTrace = new Trace(metaDataSpace);
+    forwardTrace = new Trace(metaDataSpace);
+    collection = mcCollection;
+  }
+
+  /*****************************************************************************
+   *
+   * Collection
+   */
+
+
+  /**
+   * Perform a (global) collection phase.
+   *
+   * @param phaseId Collection phase to execute.
+   */
+  @Inline
+  public final void collectionPhase(short phaseId) {
+    if (phaseId == PREPARE) {
+      super.collectionPhase(phaseId);
+      markTrace.prepare();
+      mcSpace.prepare();
+      return;
+    }
+    if (phaseId == CLOSURE) {
+      markTrace.prepare();
+      return;
+    }
+    if (phaseId == RELEASE) {
+      markTrace.release();
+      mcSpace.release();
+      super.collectionPhase(phaseId);
+      return;
+    }
+
+    if (phaseId == PREPARE_FORWARD) {
+      super.collectionPhase(PREPARE);
+      forwardTrace.prepare();
+      mcSpace.prepare();
+      return;
+    }
+    if (phaseId == RELEASE_FORWARD) {
+      forwardTrace.release();
+      mcSpace.release();
+      super.collectionPhase(RELEASE);
+      return;
+    }
+
+    super.collectionPhase(phaseId);
+  }
+
+  /*****************************************************************************
+   *
+   * Accounting
+   */
+
+  /**
+   * Return the number of pages reserved for use given the pending
+   * allocation.  The superclass accounts for its spaces, we just
+   * augment this with the mark-sweep space's contribution.
+   *
+   * @return The number of pages reserved given the pending
+   * allocation, excluding space reserved for copying.
+   */
+  public int getPagesUsed() {
+    return (mcSpace.reservedPages() + super.getPagesUsed());
+  }
+
+  /**
+   * Calculate the number of pages a collection is required to free to satisfy
+   * outstanding allocation requests.
+   *
+   * @return the number of pages a collection is required to free to satisfy
+   * outstanding allocation requests.
+   */
+  public int getPagesRequired() {
+    return super.getPagesRequired() + mcSpace.requiredPages();
+  }
+
+  /**
+   * @see org.mmtk.plan.Plan#willNeverMove
+   *
+   * @param object Object in question
+   * @return True if the object will never move
+   */
+  @Override
+  public boolean willNeverMove(ObjectReference object) {
+    if (Space.isInSpace(MARK_COMPACT, object))
+      return false;
+    return super.willNeverMove(object);
+  }
+
+  /**
+   * Return the expected reference count. For non-reference counting
+   * collectors this becomes a true/false relationship.
+   * @param object The object to check.
+   * @param sanityRootRC The number of root references to the object.
+   *
+   * @return The expected (root excluded) reference count.
+   */
+  public int sanityExpectedRC(ObjectReference object, int sanityRootRC) {
+    Space space = Space.getSpaceForObject(object);
+
+    // Nursery
+    if (space == MC.mcSpace) {
+      // We are never sure about objects in MC.
+      // This is not very satisfying but allows us to use the sanity checker to
+      // detect dangling pointers.
+      return SanityChecker.UNSURE;
+    } else {
+      return super.sanityExpectedRC(object, sanityRootRC);
+    }
+  }
+
+  /**
+   * Register specialized methods.
+   */
+  @Interruptible
+  protected void registerSpecializedMethods() {
+    TransitiveClosure.registerSpecializedScan(SCAN_MARK, MCMarkTraceLocal.class);
+    TransitiveClosure.registerSpecializedScan(SCAN_FORWARD, MCForwardTraceLocal.class);
+    super.registerSpecializedMethods();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCCollector.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCCollector.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCCollector.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCCollector.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,176 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.markcompact;
+
+import org.mmtk.plan.*;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements <i>per-collector thread</i> behavior
+ * and state for the <i>MC</i> plan, which implements a full-heap
+ * mark-compact collector.<p>
+ *
+ * Specifically, this class defines <i>MC</i> collection behavior
+ * (through <code>trace</code> and the <code>collectionPhase</code>
+ * method), and collection-time allocation.<p>
+ *
+ * @see MC for an overview of the mark-compact algorithm.<p>
+ *
+ * FIXME Currently MC does not properly separate mutator and collector
+ * behaviors, so some of the collection logic in MCMutator should
+ * really be per-collector thread, not per-mutator thread.
+ *
+ * @see MC
+ * @see MCMutator
+ * @see StopTheWorldCollector
+ * @see CollectorContext
+ */
+ at Uninterruptible public class MCCollector extends StopTheWorldCollector {
+
+  private static final boolean TRACE_MARK = false;
+  private static final boolean TRACE_FORWARD = true;
+
+  /****************************************************************************
+   * Instance fields
+   */
+
+  private final MCMarkTraceLocal markTrace;
+  private final MCForwardTraceLocal forwardTrace;
+  private boolean currentTrace;
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * Constructor
+   */
+  public MCCollector() {
+    markTrace = new MCMarkTraceLocal(global().markTrace);
+    forwardTrace = new MCForwardTraceLocal(global().forwardTrace);
+  }
+
+
+  /****************************************************************************
+   *
+   * Collection-time allocation
+   */
+
+  /**
+   * Allocate space for copying an object (this method <i>does not</i>
+   * copy the object, it only allocates space)
+   *
+   * @param original A reference to the original object
+   * @param bytes The size of the space to be allocated (in bytes)
+   * @param align The requested alignment.
+   * @param offset The alignment offset.
+   * @return The address of the first byte of the allocated region
+   */
+  @Inline
+  public Address allocCopy(ObjectReference original, int bytes,
+      int align, int offset, int allocator) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(allocator == MC.ALLOC_IMMORTAL);
+
+    return immortal.alloc(bytes, align, offset);
+  }
+
+  /**
+   * Perform any post-copy actions.
+   *
+   * @param object The newly allocated object
+   * @param typeRef the type reference for the instance being created
+   * @param bytes The size of the space to be allocated (in bytes)
+   */
+  @Inline
+  public void postCopy(ObjectReference object, ObjectReference typeRef,
+      int bytes, int allocator) {
+    MC.immortalSpace.initializeHeader(object);
+  }
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a per-collector collection phase.
+   *
+   * @param phaseId The collection phase to perform
+   * @param primary Perform any single-threaded activities using this thread.
+   */
+  @Inline
+  public final void collectionPhase(short phaseId, boolean primary) {
+    if (phaseId == MC.PREPARE) {
+      currentTrace = TRACE_MARK;
+      super.collectionPhase(phaseId, primary);
+      markTrace.prepare();
+      return;
+    }
+
+    if (phaseId == MC.CLOSURE) {
+      markTrace.completeTrace();
+      return;
+    }
+
+    if (phaseId == MC.RELEASE) {
+      markTrace.release();
+      super.collectionPhase(phaseId, primary);
+      return;
+    }
+
+    if (phaseId == MC.PREPARE_FORWARD) {
+      currentTrace = TRACE_FORWARD;
+      super.collectionPhase(MC.PREPARE, primary);
+      forwardTrace.prepare();
+      return;
+    }
+
+    if (phaseId == MC.FORWARD_CLOSURE) {
+      forwardTrace.completeTrace();
+      return;
+    }
+
+    if (phaseId == MC.RELEASE_FORWARD) {
+      forwardTrace.release();
+      super.collectionPhase(MC.RELEASE, primary);
+      return;
+    }
+
+    super.collectionPhase(phaseId, primary);
+  }
+
+  /****************************************************************************
+   *
+   * Miscellaneous
+   */
+
+  /** @return The current trace instance. */
+  public final TraceLocal getCurrentTrace() {
+    if (currentTrace == TRACE_MARK) {
+      return markTrace;
+    } else {
+      return forwardTrace;
+    }
+  }
+
+  /** @return The active global plan as an <code>MC</code> instance. */
+  @Inline
+  private static MC global() {
+    return (MC) VM.activePlan.global();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCConstraints.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCConstraints.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCConstraints.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCConstraints.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,41 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.markcompact;
+
+import org.mmtk.plan.StopTheWorldConstraints;
+
+import org.mmtk.policy.MarkCompactSpace;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class and its subclasses communicate to the host VM/Runtime
+ * any features of the selected plan that it needs to know.  This is
+ * separate from the main Plan/PlanLocal class in order to bypass any
+ * issues with ordering of static initialization.
+ */
+ at Uninterruptible
+public class MCConstraints extends StopTheWorldConstraints {
+  @Override
+  public boolean movesObjects() { return true; }
+  @Override
+  public boolean needsForwardAfterLiveness() { return true; }
+  @Override
+  public boolean needsLinearScan() { return true; }
+  @Override
+  public int gcHeaderBits() { return MarkCompactSpace.LOCAL_GC_BITS_REQUIRED; }
+  @Override
+  public int gcHeaderWords() { return MarkCompactSpace.GC_HEADER_WORDS_REQUIRED; }
+  @Override
+  public int numSpecializedScans() { return 2; }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCForwardTraceLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCForwardTraceLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCForwardTraceLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCForwardTraceLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,102 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.markcompact;
+
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.plan.Trace;
+import org.mmtk.policy.Space;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implments the thread-local functionality for a transitive
+ * closure over a mark-compact space during the forwarding phase.
+ */
+ at Uninterruptible
+public final class MCForwardTraceLocal extends TraceLocal {
+  /**
+   * Constructor
+   */
+  public MCForwardTraceLocal(Trace trace) {
+    super(MC.SCAN_FORWARD, trace);
+  }
+
+  /****************************************************************************
+   *
+   * Externally visible Object processing and tracing
+   */
+
+  /**
+   * Is the specified object live?
+   *
+   * @param object The object.
+   * @return True if the object is live.
+   */
+  public boolean isLive(ObjectReference object) {
+    if (object.isNull()) return false;
+    if (Space.isInSpace(MC.MARK_COMPACT, object)) {
+      return MC.mcSpace.isLive(object);
+    }
+    return super.isLive(object);
+  }
+
+  /**
+   * This method is the core method during the trace of the object graph.
+   * The role of this method is to:
+   *
+   * 1. Ensure the traced object is not collected.
+   * 2. If this is the first visit to the object enqueue it to be scanned.
+   * 3. Return the forwarded reference to the object.
+   *
+   * In this instance, we refer objects in the mark-sweep space to the
+   * msSpace for tracing, and defer to the superclass for all others.
+   *
+   * @param object The object to be traced.
+   * @return The new reference to the same object instance.
+   */
+  @Inline
+  public ObjectReference traceObject(ObjectReference object) {
+    if (object.isNull()) return object;
+    if (Space.isInSpace(MC.MARK_COMPACT, object))
+      return MC.mcSpace.traceForwardObject(this, object);
+    return super.traceObject(object);
+  }
+
+  /**
+   * Will this object move from this point on, during the current trace ?
+   *
+   * @param object The object to query.
+   * @return True if the object will not move.
+   */
+  public boolean willNotMoveInCurrentCollection(ObjectReference object) {
+    return !Space.isInSpace(MC.MARK_COMPACT, object);
+  }
+
+  /**
+   * Ensure that this object will not move for the rest of the GC.
+   *
+   * @param object The object that must not move
+   * @return The new object, guaranteed stable for the rest of the GC.
+   */
+  @Inline
+  public ObjectReference precopyObject(ObjectReference object) {
+    if (VM.VERIFY_ASSERTIONS) {
+      // All precopying must occur during the initial trace.
+      VM.assertions._assert(!Space.isInSpace(MC.MARK_COMPACT, object));
+    }
+    return super.precopyObject(object);
+  }
+
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCMarkTraceLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCMarkTraceLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCMarkTraceLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCMarkTraceLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,113 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.markcompact;
+
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.plan.Trace;
+import org.mmtk.policy.MarkCompactSpace;
+import org.mmtk.policy.Space;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implments the thread-local functionality for a transitive
+ * closure over a mark-compact space during the initial marking phase.
+ */
+ at Uninterruptible
+public final class MCMarkTraceLocal extends TraceLocal {
+  /**
+   * Constructor
+   */
+  public MCMarkTraceLocal(Trace trace) {
+    super(MC.SCAN_MARK, trace);
+  }
+
+  /****************************************************************************
+   *
+   * Externally visible Object processing and tracing
+   */
+
+  /**
+   * Is the specified object live?
+   *
+   * @param object The object.
+   * @return True if the object is live.
+   */
+  public boolean isLive(ObjectReference object) {
+    if (object.isNull()) return false;
+    if (Space.isInSpace(MC.MARK_COMPACT, object)) {
+      return MC.mcSpace.isLive(object);
+    }
+    return super.isLive(object);
+  }
+
+  /**
+   * This method is the core method during the trace of the object graph.
+   * The role of this method is to:
+   *
+   * 1. Ensure the traced object is not collected.
+   * 2. If this is the first visit to the object enqueue it to be scanned.
+   * 3. Return the forwarded reference to the object.
+   *
+   * In this instance, we refer objects in the mark-sweep space to the
+   * msSpace for tracing, and defer to the superclass for all others.
+   *
+   * @param object The object to be traced.
+   * @return The new reference to the same object instance.
+   */
+  @Inline
+  public ObjectReference traceObject(ObjectReference object) {
+    if (object.isNull()) return object;
+    if (Space.isInSpace(MC.MARK_COMPACT, object))
+      return MC.mcSpace.traceMarkObject(this, object);
+    return super.traceObject(object);
+  }
+
+  /**
+   * Ensure that this object will not move for the rest of the GC.
+   *
+   * @param object The object that must not move
+   * @return The new object, guaranteed stable for the rest of the GC.
+   */
+  @Inline
+  public ObjectReference precopyObject(ObjectReference object) {
+    if (Space.isInSpace(MC.MARK_COMPACT, object)) {
+      if (MarkCompactSpace.testAndMark(object)) {
+        // TODO: If precopy returns many different objects, this will cause a leak.
+        // Currently, Jikes RVM does not require many objects to be precopied.
+        ObjectReference newObject = VM.objectModel.copy(object, MC.ALLOC_IMMORTAL);
+        MarkCompactSpace.setForwardingPointer(object, newObject);
+        processNode(newObject);
+        return newObject;
+      }
+      // Somebody else got to it first
+      while (MarkCompactSpace.getForwardingPointer(object).isNull());
+      return MarkCompactSpace.getForwardingPointer(object);
+    }
+    return super.precopyObject(object);
+  }
+
+  /**
+   * Will this object move from this point on, during the current trace ?
+   *
+   * @param object The object to query.
+   * @return True if the object will not move.
+   */
+  public boolean willNotMoveInCurrentCollection(ObjectReference object) {
+    // All objects in the MC space may move
+    return !Space.isInSpace(MC.MARK_COMPACT, object);
+  }
+
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCMutator.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCMutator.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCMutator.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/markcompact/MCMutator.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,159 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.markcompact;
+
+import org.mmtk.plan.StopTheWorldMutator;
+import org.mmtk.policy.MarkCompactLocal;
+import org.mmtk.policy.Space;
+
+import org.mmtk.utility.alloc.Allocator;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements <i>per-mutator thread</i> behavior
+ * and state for the <i>MC</i> plan, which implements a full-heap
+ * mark-compact collector.<p>
+ *
+ * Specifically, this class defines <i>MC</i> mutator-time allocation
+ * and per-mutator thread collection semantics (flushing and restoring
+ * per-mutator allocator state).
+ *
+ * See {@link MC} for an overview of the mark-compact algorithm.<p>
+ *
+ * FIXME Currently MC does not properly separate mutator and collector
+ * behaviors, so some of the collection logic here should really be
+ * per-collector thread, not per-mutator thread.
+ *
+ * @see MC
+ * @see MCCollector
+ * @see org.mmtk.plan.StopTheWorldMutator
+ * @see org.mmtk.plan.MutatorContext
+ */
+ at Uninterruptible public class MCMutator extends StopTheWorldMutator {
+
+  /****************************************************************************
+   * Instance fields
+   */
+  private MarkCompactLocal mc;
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * Constructor
+   */
+  public MCMutator() {
+    mc = new MarkCompactLocal(MC.mcSpace);
+  }
+
+  /****************************************************************************
+   *
+   * Mutator-time allocation
+   */
+
+  /**
+   * Allocate memory for an object. This class handles the default allocator
+   * from the mark sweep space, and delegates everything else to the
+   * superclass.
+   *
+   * @param bytes The number of bytes required for the object.
+   * @param align Required alignment for the object.
+   * @param offset Offset associated with the alignment.
+   * @param allocator The allocator associated with this request.
+   * @param site Allocation site
+   * @return The low address of the allocated memory.
+   */
+  @Inline
+  public Address alloc(int bytes, int align, int offset, int allocator, int site) {
+    if (allocator == MC.ALLOC_DEFAULT) {
+      return mc.alloc(bytes, align, offset);
+    }
+    return super.alloc(bytes, align, offset, allocator, site);
+  }
+
+  /**
+   * Perform post-allocation actions.  Initialize the object header for
+   * objects in the mark-sweep space, and delegate to the superclass for
+   * other objects.
+   *
+   * @param ref The newly allocated object
+   * @param typeRef the type reference for the instance being created
+   * @param bytes The size of the space to be allocated (in bytes)
+   * @param allocator The allocator number to be used for this allocation
+   */
+  @Inline
+  public void postAlloc(ObjectReference ref, ObjectReference typeRef,
+      int bytes, int allocator) {
+    if (allocator == MC.ALLOC_DEFAULT)
+      MC.mcSpace.initializeHeader(ref);
+    else
+      super.postAlloc(ref, typeRef, bytes, allocator);
+  }
+
+  /**
+   * Return the allocator instance associated with a space
+   * <code>space</code>, for this plan instance.
+   *
+   * @param space The space for which the allocator instance is desired.
+   * @return The allocator instance associated with this plan instance
+   * which is allocating into <code>space</code>, or <code>null</code>
+   * if no appropriate allocator can be established.
+   */
+  public Allocator getAllocatorFromSpace(Space space) {
+    if (space == MC.mcSpace) return mc;
+    return super.getAllocatorFromSpace(space);
+  }
+
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a per-mutator collection phase.
+   *
+   * @param phaseId The collection phase to perform
+   * @param primary Perform any single-threaded activities using this thread.
+   */
+  @Inline
+  public final void collectionPhase(short phaseId, boolean primary) {
+    if (phaseId == MC.PREPARE) {
+      super.collectionPhase(phaseId, primary);
+      return;
+    }
+
+    /* FIXME this needs to be made a per-collector phase */
+    if (phaseId == MC.CALCULATE_FP) {
+      mc.calculateForwardingPointers();
+      return;
+    }
+
+    /* FIXME this needs to be made a per-collector phase */
+    if (phaseId == MC.COMPACT) {
+      mc.compact();
+      return;
+    }
+
+    if (phaseId == MC.RELEASE) {
+      super.collectionPhase(phaseId, primary);
+      return;
+    }
+    super.collectionPhase(phaseId, primary);
+  }
+
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MS.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MS.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MS.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MS.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,149 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.marksweep;
+
+import org.mmtk.plan.*;
+import org.mmtk.policy.MarkSweepSpace;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.heap.VMRequest;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements the global state of a simple mark-sweep collector.
+ *
+ * All plans make a clear distinction between <i>global</i> and
+ * <i>thread-local</i> activities, and divides global and local state
+ * into separate class hierarchies.  Global activities must be
+ * synchronized, whereas no synchronization is required for
+ * thread-local activities.  There is a single instance of Plan (or the
+ * appropriate sub-class), and a 1:1 mapping of PlanLocal to "kernel
+ * threads" (aka CPUs).  Thus instance
+ * methods of PlanLocal allow fast, unsychronized access to functions such as
+ * allocation and collection.
+ *
+ * The global instance defines and manages static resources
+ * (such as memory and virtual memory resources).  This mapping of threads to
+ * instances is crucial to understanding the correctness and
+ * performance properties of MMTk plans.
+ */
+ at Uninterruptible
+public class MS extends StopTheWorld {
+
+  /****************************************************************************
+   * Class variables
+   */
+  public static final MarkSweepSpace msSpace = new MarkSweepSpace("ms", DEFAULT_POLL_FREQUENCY, VMRequest.create());
+  public static final int MARK_SWEEP = msSpace.getDescriptor();
+
+  public static final int SCAN_MARK = 0;
+
+
+  /****************************************************************************
+   * Instance variables
+   */
+  public final Trace msTrace = new Trace(metaDataSpace);
+
+
+  /*****************************************************************************
+   * Collection
+   */
+
+  /**
+   * Perform a (global) collection phase.
+   *
+   * @param phaseId Collection phase to execute.
+   */
+  @Inline
+  @Override
+  public void collectionPhase(short phaseId) {
+
+    if (phaseId == PREPARE) {
+      super.collectionPhase(phaseId);
+      msTrace.prepare();
+      msSpace.prepare(true);
+      return;
+    }
+
+    if (phaseId == CLOSURE) {
+      msTrace.prepare();
+      return;
+    }
+    if (phaseId == RELEASE) {
+      msTrace.release();
+      msSpace.release();
+      super.collectionPhase(phaseId);
+      return;
+    }
+
+    super.collectionPhase(phaseId);
+  }
+
+  /*****************************************************************************
+   * Accounting
+   */
+
+  /**
+   * Return the number of pages reserved for use given the pending
+   * allocation.  The superclass accounts for its spaces, we just
+   * augment this with the mark-sweep space's contribution.
+   *
+   * @return The number of pages reserved given the pending
+   * allocation, excluding space reserved for copying.
+   */
+  @Override
+  public int getPagesUsed() {
+    return (msSpace.reservedPages() + super.getPagesUsed());
+  }
+
+  /**
+   * Calculate the number of pages a collection is required to free to satisfy
+   * outstanding allocation requests.
+   *
+   * @return the number of pages a collection is required to free to satisfy
+   * outstanding allocation requests.
+   */
+  @Override
+  public int getPagesRequired() {
+    return super.getPagesRequired() + msSpace.requiredPages();
+  }
+
+
+  /*****************************************************************************
+   * Miscellaneous
+   */
+
+  /**
+   * @see org.mmtk.plan.Plan#willNeverMove
+   *
+   * @param object Object in question
+   * @return True if the object will never move
+   */
+  @Override
+  public boolean willNeverMove(ObjectReference object) {
+    if (Space.isInSpace(MARK_SWEEP, object))
+      return true;
+    return super.willNeverMove(object);
+  }
+
+  /**
+   * Register specialized methods.
+   */
+  @Interruptible
+  @Override
+  protected void registerSpecializedMethods() {
+    TransitiveClosure.registerSpecializedScan(SCAN_MARK, MSTraceLocal.class);
+    super.registerSpecializedMethods();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSCollector.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSCollector.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSCollector.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSCollector.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,95 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.marksweep;
+
+import org.mmtk.plan.*;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements <i>per-collector thread</i> behavior
+ * and state for the <i>MS</i> plan, which implements a full-heap
+ * mark-sweep collector.<p>
+ *
+ * Specifically, this class defines <i>MS</i> collection behavior
+ * (through <code>trace</code> and the <code>collectionPhase</code>
+ * method).<p>
+ *
+ * @see MS for an overview of the mark-sweep algorithm.<p>
+ *
+ * @see MS
+ * @see MSMutator
+ * @see StopTheWorldCollector
+ * @see CollectorContext
+ */
+ at Uninterruptible
+public class MSCollector extends StopTheWorldCollector {
+
+  /****************************************************************************
+   * Instance fields
+   */
+  protected MSTraceLocal fullTrace = new MSTraceLocal(global().msTrace, null);;
+  protected TraceLocal currentTrace = fullTrace;
+
+
+  /****************************************************************************
+   * Collection
+   */
+
+  /**
+   * Perform a per-collector collection phase.
+   *
+   * @param phaseId The collection phase to perform
+   * @param primary Perform any single-threaded activities using this thread.
+   */
+  @Inline
+  @Override
+  public void collectionPhase(short phaseId, boolean primary) {
+    if (phaseId == MS.PREPARE) {
+      super.collectionPhase(phaseId, primary);
+      fullTrace.prepare();
+      return;
+    }
+
+    if (phaseId == MS.CLOSURE) {
+      fullTrace.completeTrace();
+      return;
+    }
+
+    if (phaseId == MS.RELEASE) {
+      fullTrace.release();
+      super.collectionPhase(phaseId, primary);
+      return;
+    }
+
+    super.collectionPhase(phaseId, primary);
+  }
+
+
+  /****************************************************************************
+   * Miscellaneous
+   */
+
+  /** @return The active global plan as an <code>MS</code> instance. */
+  @Inline
+  private static MS global() {
+    return (MS) VM.activePlan.global();
+  }
+
+  /** @return The current trace instance. */
+  @Override
+  public final TraceLocal getCurrentTrace() {
+    return currentTrace;
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSConstraints.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSConstraints.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSConstraints.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSConstraints.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,38 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.marksweep;
+
+import org.mmtk.plan.StopTheWorldConstraints;
+
+import org.mmtk.policy.MarkSweepSpace;
+import org.mmtk.policy.SegregatedFreeListSpace;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class and its subclasses communicate to the host VM/Runtime
+ * any features of the selected plan that it needs to know.  This is
+ * separate from the main Plan/PlanLocal class in order to bypass any
+ * issues with ordering of static initialization.
+ */
+ at Uninterruptible
+public class MSConstraints extends StopTheWorldConstraints {
+  @Override
+  public int gcHeaderBits() { return MarkSweepSpace.LOCAL_GC_BITS_REQUIRED; }
+  @Override
+  public int gcHeaderWords() { return MarkSweepSpace.GC_HEADER_WORDS_REQUIRED; }
+  @Override
+  public int maxNonLOSDefaultAllocBytes() { return SegregatedFreeListSpace.MAX_FREELIST_OBJECT_BYTES; }
+  @Override
+  public int numSpecializedScans() { return 1; }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSMutator.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSMutator.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSMutator.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSMutator.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,143 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.marksweep;
+
+import org.mmtk.plan.*;
+import org.mmtk.policy.MarkSweepLocal;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.alloc.Allocator;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements <i>per-mutator thread</i> behavior
+ * and state for the <i>MS</i> plan, which implements a full-heap
+ * mark-sweep collector.<p>
+ *
+ * Specifically, this class defines <i>MS</i> mutator-time allocation
+ * and per-mutator thread collection semantics (flushing and restoring
+ * per-mutator allocator state).<p>
+ *
+ * @see MS
+ * @see MSCollector
+ * @see StopTheWorldMutator
+ * @see MutatorContext
+ */
+ at Uninterruptible
+public class MSMutator extends StopTheWorldMutator {
+
+  /****************************************************************************
+   * Instance fields
+   */
+  protected MarkSweepLocal ms = new MarkSweepLocal(MS.msSpace);
+
+
+  /****************************************************************************
+   * Mutator-time allocation
+   */
+
+  /**
+   * Allocate memory for an object. This class handles the default allocator
+   * from the mark sweep space, and delegates everything else to the
+   * superclass.
+   *
+   * @param bytes The number of bytes required for the object.
+   * @param align Required alignment for the object.
+   * @param offset Offset associated with the alignment.
+   * @param allocator The allocator associated with this request.
+   * @return The low address of the allocated memory.
+   */
+  @Inline
+  @Override
+  public Address alloc(int bytes, int align, int offset, int allocator, int site) {
+    if (allocator == MS.ALLOC_DEFAULT) {
+      return ms.alloc(bytes, align, offset);
+    }
+    return super.alloc(bytes, align, offset, allocator, site);
+  }
+
+  /**
+   * Perform post-allocation actions.  Initialize the object header for
+   * objects in the mark-sweep space, and delegate to the superclass for
+   * other objects.
+   *
+   * @param ref The newly allocated object
+   * @param typeRef the type reference for the instance being created
+   * @param bytes The size of the space to be allocated (in bytes)
+   * @param allocator The allocator number to be used for this allocation
+   */
+  @Inline
+  @Override
+  public void postAlloc(ObjectReference ref, ObjectReference typeRef,
+      int bytes, int allocator) {
+    if (allocator == MS.ALLOC_DEFAULT)
+      MS.msSpace.postAlloc(ref);
+    else
+      super.postAlloc(ref, typeRef, bytes, allocator);
+  }
+
+  /**
+   * Return the allocator instance associated with a space
+   * <code>space</code>, for this plan instance.
+   *
+   * @param space The space for which the allocator instance is desired.
+   * @return The allocator instance associated with this plan instance
+   * which is allocating into <code>space</code>, or <code>null</code>
+   * if no appropriate allocator can be established.
+   */
+  @Override
+  public Allocator getAllocatorFromSpace(Space space) {
+    if (space == MS.msSpace) return ms;
+    return super.getAllocatorFromSpace(space);
+  }
+
+
+  /****************************************************************************
+   * Collection
+   */
+
+  /**
+   * Perform a per-mutator collection phase.
+   *
+   * @param phaseId The collection phase to perform
+   * @param primary Perform any single-threaded activities using this thread.
+   */
+  @Inline
+  @Override
+  public void collectionPhase(short phaseId, boolean primary) {
+    if (phaseId == MS.PREPARE) {
+      super.collectionPhase(phaseId, primary);
+      ms.prepare();
+      return;
+    }
+
+    if (phaseId == MS.RELEASE) {
+      ms.release();
+      super.collectionPhase(phaseId, primary);
+      return;
+    }
+
+    super.collectionPhase(phaseId, primary);
+  }
+
+  /**
+   * Flush mutator context, in response to a requestMutatorFlush.
+   * Also called by the default implementation of deinitMutator.
+   */
+  @Override
+  public void flush() {
+    super.flush();
+    ms.flush();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSTraceLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSTraceLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSTraceLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/marksweep/MSTraceLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,100 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.marksweep;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.plan.Trace;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.deque.ObjectReferenceDeque;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements the thread-local functionality for a transitive
+ * closure over a mark-sweep space.
+ */
+ at Uninterruptible
+public final class MSTraceLocal extends TraceLocal {
+  /****************************************************************************
+   * Instance fields
+   */
+  private final ObjectReferenceDeque modBuffer;
+
+  /**
+   * Constructor
+   */
+  public MSTraceLocal(Trace trace, ObjectReferenceDeque modBuffer) {
+    super(MS.SCAN_MARK, trace);
+    this.modBuffer = modBuffer;
+  }
+
+
+  /****************************************************************************
+   * Externally visible Object processing and tracing
+   */
+
+  /**
+   * Is the specified object live?
+   *
+   * @param object The object.
+   * @return <code>true</code> if the object is live.
+   */
+  @Override
+  public boolean isLive(ObjectReference object) {
+    if (object.isNull()) return false;
+    if (Space.isInSpace(MS.MARK_SWEEP, object)) {
+      return MS.msSpace.isLive(object);
+    }
+    return super.isLive(object);
+  }
+
+  /**
+   * This method is the core method during the trace of the object graph.
+   * The role of this method is to:
+   *
+   * 1. Ensure the traced object is not collected.
+   * 2. If this is the first visit to the object enqueue it to be scanned.
+   * 3. Return the forwarded reference to the object.
+   *
+   * In this instance, we refer objects in the mark-sweep space to the
+   * msSpace for tracing, and defer to the superclass for all others.
+   *
+   * @param object The object to be traced.
+   * @return The new reference to the same object instance.
+   */
+  @Inline
+  @Override
+  public ObjectReference traceObject(ObjectReference object) {
+    if (object.isNull()) return object;
+    if (Space.isInSpace(MS.MARK_SWEEP, object))
+      return MS.msSpace.traceObject(this, object);
+    return super.traceObject(object);
+  }
+
+  /**
+   * Process any remembered set entries.  This means enumerating the
+   * mod buffer and for each entry, marking the object as unlogged
+   * (we don't enqueue for scanning since we're doing a full heap GC).
+   */
+  protected void processRememberedSets() {
+    if (modBuffer != null) {
+      logMessage(5, "clearing modBuffer");
+      while (!modBuffer.isEmpty()) {
+        ObjectReference src = modBuffer.pop();
+        Plan.markAsUnlogged(src);
+      }
+    }
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGC.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGC.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGC.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGC.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,97 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.nogc;
+
+import org.mmtk.plan.*;
+import org.mmtk.policy.ImmortalSpace;
+import org.mmtk.utility.heap.VMRequest;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+
+
+/**
+ * This class implements the global state of a a simple allocator
+ * without a collector.
+ */
+ at Uninterruptible
+public class NoGC extends Plan {
+
+  /*****************************************************************************
+   * Class variables
+   */
+  public static final ImmortalSpace noGCSpace = new ImmortalSpace("default", DEFAULT_POLL_FREQUENCY, VMRequest.create());
+  public static final int NOGC = noGCSpace.getDescriptor();
+
+
+  /*****************************************************************************
+   * Instance variables
+   */
+  public final Trace trace = new Trace(metaDataSpace);
+
+
+  /*****************************************************************************
+   * Collection
+   */
+
+  /**
+   * Perform a (global) collection phase.
+   *
+   * @param phaseId Collection phase
+   */
+  @Inline
+  @Override
+  public final void collectionPhase(short phaseId) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(false);
+    /*
+    if (phaseId == PREPARE) {
+    }
+    if (phaseId == CLOSURE) {
+    }
+    if (phaseId == RELEASE) {
+    }
+    super.collectionPhase(phaseId);
+    */
+  }
+
+  /*****************************************************************************
+   * Accounting
+   */
+
+  /**
+   * Return the number of pages reserved for use given the pending
+   * allocation.  The superclass accounts for its spaces, we just
+   * augment this with the default space's contribution.
+   *
+   * @return The number of pages reserved given the pending
+   * allocation, excluding space reserved for copying.
+   */
+  @Override
+  public int getPagesUsed() {
+    return (noGCSpace.reservedPages() + super.getPagesUsed());
+  }
+
+
+  /*****************************************************************************
+   * Miscellaneous
+   */
+
+  /**
+   * Register specialized methods.
+   */
+  @Interruptible
+  @Override
+  protected void registerSpecializedMethods() {
+    super.registerSpecializedMethods();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCCollector.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCCollector.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCCollector.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCCollector.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,111 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.nogc;
+
+import org.mmtk.plan.*;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements <i>per-collector thread</i> behavior and state
+ * for the <i>NoGC</i> plan, which simply allocates (without ever collecting
+ * until the available space is exhausted.<p>
+ *
+ * Specifically, this class <i>would</i> define <i>NoGC</i> collection time semantics,
+ * however, since this plan never collects, this class consists only of stubs which
+ * may be useful as a template for implementing a basic collector.
+ *
+ * @see NoGC
+ * @see NoGCMutator
+ * @see CollectorContext
+ */
+ at Uninterruptible
+public class NoGCCollector extends CollectorContext {
+
+  /************************************************************************
+   * Instance fields
+   */
+  private final NoGCTraceLocal trace = new NoGCTraceLocal(global().trace);
+  protected final TraceLocal currentTrace = trace;
+
+
+  /****************************************************************************
+   * Collection
+   */
+
+  /**
+   * Perform a garbage collection
+   */
+  @Override
+  public final void collect() {
+    VM.assertions.fail("GC Triggered in NoGC Plan. Is -X:gc:ignoreSystemGC=true ?");
+  }
+
+  /** Perform some concurrent garbage collection */
+  @Override
+  public final void concurrentCollect() {
+    VM.assertions.fail("Concurrent GC Triggered in NoGC Plan.");
+  }
+
+  /**
+   * Perform a per-collector collection phase.
+   *
+   * @param phaseId The collection phase to perform
+   * @param primary perform any single-threaded local activities.
+   */
+  @Inline
+  @Override
+  public final void collectionPhase(short phaseId, boolean primary) {
+    VM.assertions.fail("GC Triggered in NoGC Plan.");
+    /*
+    if (phaseId == NoGC.PREPARE) {
+    }
+
+    if (phaseId == NoGC.CLOSURE) {
+    }
+
+    if (phaseId == NoGC.RELEASE) {
+    }
+
+    super.collectionPhase(phaseId, primary);
+    */
+  }
+
+  /**
+   * Perform some concurrent collection work.
+   *
+   * @param phaseId The unique phase identifier
+   */
+  @Override
+  public void concurrentCollectionPhase(short phaseId) {
+    VM.assertions.fail("GC Triggered in NoGC Plan.");
+  }
+
+
+  /****************************************************************************
+   * Miscellaneous
+   */
+
+  /** @return The active global plan as a <code>NoGC</code> instance. */
+  @Inline
+  private static NoGC global() {
+    return (NoGC) VM.activePlan.global();
+  }
+
+  /** @return The current trace instance. */
+  @Override
+  public final TraceLocal getCurrentTrace() {
+    return currentTrace;
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCConstraints.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCConstraints.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCConstraints.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCConstraints.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,31 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.nogc;
+
+import org.mmtk.plan.PlanConstraints;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class and its subclasses communicate to the host VM/Runtime
+ * any features of the selected plan that it needs to know.  This is
+ * separate from the main Plan/PlanLocal class in order to bypass any
+ * issues with ordering of static initialization.
+ */
+ at Uninterruptible
+public class NoGCConstraints extends PlanConstraints {
+  @Override
+  public int gcHeaderBits() { return 0; }
+  @Override
+  public int gcHeaderWords() { return 0; }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCMutator.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCMutator.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCMutator.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCMutator.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,128 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.nogc;
+
+import org.mmtk.plan.MutatorContext;
+import org.mmtk.policy.ImmortalLocal;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.alloc.Allocator;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements <i>per-mutator thread</i> behavior and state
+ * for the <i>NoGC</i> plan, which simply allocates (without ever collecting
+ * until the available space is exhausted.<p>
+ *
+ * Specifically, this class defines <i>NoGC</i> mutator-time allocation
+ * through a bump pointer (<code>def</code>) and includes stubs for
+ * per-mutator thread collection semantics (since there is no collection
+ * in this plan, these remain just stubs).
+ *
+ * @see NoGC
+ * @see NoGCCollector
+ * @see org.mmtk.plan.StopTheWorldMutator
+ * @see org.mmtk.plan.MutatorContext
+ */
+ at Uninterruptible
+public class NoGCMutator extends MutatorContext {
+
+  /************************************************************************
+   * Instance fields
+   */
+  private final ImmortalLocal nogc = new ImmortalLocal(NoGC.noGCSpace);
+
+
+  /****************************************************************************
+   * Mutator-time allocation
+   */
+
+  /**
+   * Allocate memory for an object.
+   *
+   * @param bytes The number of bytes required for the object.
+   * @param align Required alignment for the object.
+   * @param offset Offset associated with the alignment.
+   * @param allocator The allocator associated with this request.
+   * @param site Allocation site
+   * @return The address of the newly allocated memory.
+   */
+  @Inline
+  @Override
+  public Address alloc(int bytes, int align, int offset, int allocator, int site) {
+    if (allocator == NoGC.ALLOC_DEFAULT) {
+      return nogc.alloc(bytes, align, offset);
+    }
+    return super.alloc(bytes, align, offset, allocator, site);
+  }
+
+  /**
+   * Perform post-allocation actions.  For many allocators none are
+   * required.
+   *
+   * @param ref The newly allocated object
+   * @param typeRef the type reference for the instance being created
+   * @param bytes The size of the space to be allocated (in bytes)
+   * @param allocator The allocator number to be used for this allocation
+   */
+  @Inline
+  @Override
+  public void postAlloc(ObjectReference ref, ObjectReference typeRef,
+      int bytes, int allocator) {
+    if (allocator != NoGC.ALLOC_DEFAULT) {
+      super.postAlloc(ref, typeRef, bytes, allocator);
+    }
+  }
+
+  /**
+   * Return the allocator instance associated with a space
+   * <code>space</code>, for this plan instance.
+   *
+   * @param space The space for which the allocator instance is desired.
+   * @return The allocator instance associated with this plan instance
+   * which is allocating into <code>space</code>, or <code>null</code>
+   * if no appropriate allocator can be established.
+   */
+  @Override
+  public Allocator getAllocatorFromSpace(Space space) {
+    if (space == NoGC.noGCSpace) return nogc;
+    return super.getAllocatorFromSpace(space);
+  }
+
+
+  /****************************************************************************
+   * Collection
+   */
+
+  /**
+   * Perform a per-mutator collection phase.
+   *
+   * @param phaseId The collection phase to perform
+   * @param primary perform any single-threaded local activities.
+   */
+  @Inline
+  @Override
+  public final void collectionPhase(short phaseId, boolean primary) {
+    VM.assertions.fail("GC Triggered in NoGC Plan.");
+    /*
+     if (phaseId == NoGC.PREPARE) {
+     }
+
+     if (phaseId == NoGC.RELEASE) {
+     }
+     super.collectionPhase(phaseId, primary);
+     */
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCTraceLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCTraceLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCTraceLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/nogc/NoGCTraceLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,75 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.nogc;
+
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.plan.Trace;
+import org.mmtk.policy.Space;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements the thread-local core functionality for a transitive
+ * closure over the heap graph.
+ */
+ at Uninterruptible
+public final class NoGCTraceLocal extends TraceLocal {
+
+  /**
+   * Constructor
+   */
+  public NoGCTraceLocal(Trace trace) {
+    super(trace);
+  }
+
+
+  /****************************************************************************
+   * Externally visible Object processing and tracing
+   */
+
+  /**
+   * Is the specified object live?
+   *
+   * @param object The object.
+   * @return <code>true</code> if the object is live.
+   */
+  @Override
+  public boolean isLive(ObjectReference object) {
+    if (object.isNull()) return false;
+    if (Space.isInSpace(NoGC.NOGC, object)) {
+      return NoGC.noGCSpace.isLive(object);
+    }
+    return super.isLive(object);
+  }
+
+  /**
+   * This method is the core method during the trace of the object graph.
+   * The role of this method is to:
+   *
+   * 1. Ensure the traced object is not collected.
+   * 2. If this is the first visit to the object enqueue it to be scanned.
+   * 3. Return the forwarded reference to the object.
+   *
+   * @param object The object to be traced.
+   * @return The new reference to the same object instance.
+   */
+  @Inline
+  @Override
+  public ObjectReference traceObject(ObjectReference object) {
+    if (object.isNull()) return object;
+    if (Space.isInSpace(NoGC.NOGC, object))
+      return NoGC.noGCSpace.traceObject(this, object);
+    return super.traceObject(object);
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/Poisoned.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/Poisoned.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/Poisoned.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/Poisoned.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,80 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.poisoned;
+
+import org.mmtk.plan.marksweep.MS;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.Address;
+import org.vmmagic.unboxed.ObjectReference;
+import org.vmmagic.unboxed.Word;
+
+/**
+ * This class implements a poisoned collector, that is essentially a test
+ * case for read and write barriers in the VM.
+ */
+ at Uninterruptible
+public class Poisoned extends MS {
+  /**
+   * Perform any required write barrier action when installing an object reference
+   * a boot time.
+   *
+   * @param reference the reference value that is to be stored
+   * @return The raw value to be
+   */
+  public Word bootTimeWriteBarrier(Word reference) {
+    return reference.or(Word.one());
+  }
+
+  /**
+   * Poison a reference value.
+   */
+  @Inline
+  public static Word poison(ObjectReference reference) {
+    return reference.toAddress().toWord().or(Word.one());
+  }
+
+  /**
+   * DePoison a reference value.
+   */
+  @Inline
+  public static ObjectReference depoison(Word value) {
+    return value.and(Word.one().not()).toAddress().toObjectReference();
+  }
+
+  /****************************************************************************
+   * Internal read/write barriers.
+   */
+
+  /**
+   * Store an object reference
+   *
+   * @param slot The location of the reference
+   * @param value The value to store
+   */
+  @Inline
+  public void storeObjectReference(Address slot, ObjectReference value) {
+    slot.store(poison(value));
+  }
+
+  /**
+   * Load an object reference
+   *
+   * @param slot The location of the reference
+   * @return the object reference loaded from slot
+   */
+  @Inline
+  public ObjectReference loadObjectReference(Address slot) {
+    return depoison(slot.loadWord());
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedCollector.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedCollector.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedCollector.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedCollector.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,25 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.poisoned;
+
+import org.mmtk.plan.marksweep.MSCollector;
+
+import org.vmmagic.pragma.Uninterruptible;
+
+/**
+ * This class implements a poisoned collector, that is essentially a test
+ * case for read and write barriers in the VM.
+ */
+ at Uninterruptible
+public class PoisonedCollector extends MSCollector {
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedConstraints.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedConstraints.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedConstraints.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedConstraints.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,34 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.poisoned;
+
+import org.mmtk.plan.marksweep.MSConstraints;
+import org.vmmagic.pragma.*;
+
+/**
+ * This class and its subclasses communicate to the host VM/Runtime
+ * any features of the selected plan that it needs to know.  This is
+ * separate from the main Plan/PlanLocal class in order to bypass any
+ * issues with ordering of static initialization.
+ */
+ at Uninterruptible
+public class PoisonedConstraints extends MSConstraints {
+  @Override
+  public boolean needsWriteBarrier() { return true; }
+  @Override
+  public boolean needsReadBarrier() { return true; }
+  @Override
+  public boolean needsStaticWriteBarrier() { return false; }
+  @Override
+  public boolean needsStaticReadBarrier() { return false; }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedMutator.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedMutator.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedMutator.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/poisoned/PoisonedMutator.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,123 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.poisoned;
+
+import org.mmtk.plan.marksweep.MSMutator;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.Address;
+import org.vmmagic.unboxed.ObjectReference;
+import org.vmmagic.unboxed.Offset;
+import org.vmmagic.unboxed.Word;
+
+/**
+ * This class implements a poisoned collector, that is essentially a test
+ * case for read and write barriers in the VM.
+ */
+ at Uninterruptible
+public class PoisonedMutator extends MSMutator {
+
+  /****************************************************************************
+   *
+   * Write and read barriers. By default do nothing, override if
+   * appropriate.
+   */
+
+  /**
+   * A new reference is about to be created. Take appropriate write
+   * barrier actions.<p>
+   *
+   * <b>By default do nothing, override if appropriate.</b>
+   *
+   * @param src The object into which the new reference will be stored
+   * @param slot The address into which the new reference will be
+   * stored.
+   * @param tgt The target of the new reference
+   * @param metaDataA A value that assists the host VM in creating a store
+   * @param metaDataB A value that assists the host VM in creating a store
+   * @param mode The context in which the store occurred
+   */
+  @Inline
+  @Override
+  public void writeBarrier(ObjectReference src, Address slot, ObjectReference tgt, Word metaDataA, Word metaDataB, int mode) {
+    VM.barriers.performRawWriteInBarrier(src, slot, Poisoned.poison(tgt), metaDataA, metaDataB, mode);
+  }
+
+  /**
+   * Attempt to atomically exchange the value in the given slot
+   * with the passed replacement value. If a new reference is
+   * created, we must then take appropriate write barrier actions.<p>
+   *
+   * <b>By default do nothing, override if appropriate.</b>
+   *
+   * @param src The object into which the new reference will be stored
+   * @param slot The address into which the new reference will be
+   * stored.
+   * @param old The old reference to be swapped out
+   * @param tgt The target of the new reference
+   * @param metaDataA A value that assists the host VM in creating a store
+   * @param metaDataB A value that assists the host VM in creating a store
+   * @param mode The context in which the store occurred
+   * @return True if the swap was successful.
+   */
+  @Override
+  public boolean tryCompareAndSwapWriteBarrier(ObjectReference src, Address slot, ObjectReference old, ObjectReference tgt,
+                                               Word metaDataA, Word metaDataB, int mode) {
+    return VM.barriers.tryRawCompareAndSwapWriteInBarrier(src, slot, Poisoned.poison(old), Poisoned.poison(tgt), metaDataA, metaDataB, mode);
+  }
+
+  /**
+   * A number of references are about to be copied from object
+   * <code>src</code> to object <code>dst</code> (as in an array
+   * copy).  Thus, <code>dst</code> is the mutated object.  Take
+   * appropriate write barrier actions.<p>
+   *
+   * @param src The source of the values to be copied
+   * @param srcOffset The offset of the first source address, in
+   * bytes, relative to <code>src</code> (in principle, this could be
+   * negative).
+   * @param dst The mutated object, i.e. the destination of the copy.
+   * @param dstOffset The offset of the first destination address, in
+   * bytes relative to <code>tgt</code> (in principle, this could be
+   * negative).
+   * @param bytes The size of the region being copied, in bytes.
+   * @return True if the update was performed by the barrier, false if
+   * left to the caller (always false in this case).
+   */
+  @Override
+  public boolean writeBarrier(ObjectReference src, Offset srcOffset, ObjectReference dst, Offset dstOffset, int bytes) {
+    // TODO: Currently, read barriers implies that this is never used, perhaps
+    //       we might want to use it sometime anyway?
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(false);
+    return false;
+  }
+
+  /**
+   * Read a reference. Take appropriate read barrier action, and
+   * return the value that was read.<p> This is a <b>substituting<b>
+   * barrier.  The call to this barrier takes the place of a load.<p>
+   *
+   * @param src The object reference holding the field being read.
+   * @param slot The address of the slot being read.
+   * @param metaDataA A value that assists the host VM in creating a load
+   * @param metaDataB A value that assists the host VM in creating a load
+   * @param mode The context in which the load occurred
+   * @return The reference that was read.
+   */
+  @Inline
+  @Override
+  public ObjectReference readBarrier(ObjectReference src, Address slot, Word metaDataA, Word metaDataB, int mode) {
+    return Poisoned.depoison(VM.barriers.performRawReadInBarrier(src, slot, metaDataA, metaDataB, mode));
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBase.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBase.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBase.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBase.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,299 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.refcount;
+
+import org.mmtk.plan.Phase;
+import org.mmtk.plan.StopTheWorld;
+import org.mmtk.plan.Trace;
+import org.mmtk.plan.refcount.backuptrace.BTFreeLargeObjectSweeper;
+import org.mmtk.plan.refcount.backuptrace.BTScanLargeObjectSweeper;
+import org.mmtk.plan.refcount.backuptrace.BTSweeper;
+import org.mmtk.policy.ExplicitFreeListSpace;
+import org.mmtk.policy.ExplicitLargeObjectSpace;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.Log;
+import org.mmtk.utility.alloc.LinearScan;
+import org.mmtk.utility.deque.SharedDeque;
+import org.mmtk.utility.heap.VMRequest;
+import org.mmtk.utility.options.Options;
+import org.mmtk.utility.sanitychecker.SanityChecker;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.ObjectReference;
+
+/**
+ * This class implements the global state of a a simple reference counting collector.
+ */
+ at Uninterruptible
+public class RCBase extends StopTheWorld {
+  public static final short PROCESS_OLDROOTBUFFER  = Phase.createSimple("old-root");
+  public static final short PROCESS_NEWROOTBUFFER  = Phase.createSimple("new-root");
+  public static final short PROCESS_MODBUFFER      = Phase.createSimple("mods");
+  public static final short PROCESS_DECBUFFER      = Phase.createSimple("decs");
+
+  /** Is cycle collection enabled? */
+  public static final boolean CC_ENABLED           = true;
+  /** Force full cycle collection at each GC? */
+  public static final boolean CC_FORCE_FULL        = false;
+  /** Use backup tracing for cycle collection (currently the only option) */
+  public static final boolean CC_BACKUP_TRACE      = true;
+
+  public static boolean performCycleCollection;
+  public static final short BT_CLOSURE             = Phase.createSimple("closure-bt");
+
+  // CHECKSTYLE:OFF
+
+  /**
+   * Reference counting specific collection steps.
+   */
+  protected static final short refCountCollectionPhase = Phase.createComplex("release", null,
+      Phase.scheduleGlobal     (PROCESS_OLDROOTBUFFER),
+      Phase.scheduleCollector  (PROCESS_OLDROOTBUFFER),
+      Phase.scheduleGlobal     (PROCESS_NEWROOTBUFFER),
+      Phase.scheduleCollector  (PROCESS_NEWROOTBUFFER),
+      Phase.scheduleMutator    (PROCESS_DECBUFFER),
+      Phase.scheduleGlobal     (PROCESS_DECBUFFER),
+      Phase.scheduleCollector  (PROCESS_DECBUFFER),
+      Phase.scheduleGlobal     (BT_CLOSURE),
+      Phase.scheduleCollector  (BT_CLOSURE));
+
+  /**
+   * Perform the initial determination of liveness from the roots.
+   */
+  protected static final short rootClosurePhase = Phase.createComplex("initial-closure", null,
+      Phase.scheduleMutator    (PREPARE),
+      Phase.scheduleGlobal     (PREPARE),
+      Phase.scheduleCollector  (PREPARE),
+      Phase.scheduleComplex    (prepareStacks),
+      Phase.scheduleCollector  (PRECOPY),
+      Phase.scheduleCollector  (STACK_ROOTS),
+      Phase.scheduleCollector  (ROOTS),
+      Phase.scheduleGlobal     (ROOTS),
+      Phase.scheduleMutator    (PROCESS_MODBUFFER),
+      Phase.scheduleGlobal     (PROCESS_MODBUFFER),
+      Phase.scheduleCollector  (PROCESS_MODBUFFER),
+      Phase.scheduleGlobal     (CLOSURE),
+      Phase.scheduleCollector  (CLOSURE));
+
+  /**
+   * This is the phase that is executed to perform a collection.
+   */
+  public short collection = Phase.createComplex("collection", null,
+      Phase.scheduleComplex(initPhase),
+      Phase.scheduleComplex(rootClosurePhase),
+      Phase.scheduleComplex(refCountCollectionPhase),
+      Phase.scheduleComplex(completeClosurePhase),
+      Phase.scheduleComplex(finishPhase));
+
+  // CHECKSTYLE:ON
+
+  /*****************************************************************************
+   *
+   * Class fields
+   */
+  public static final ExplicitFreeListSpace rcSpace = new ExplicitFreeListSpace("rc", DEFAULT_POLL_FREQUENCY, VMRequest.create());
+  public static final ExplicitLargeObjectSpace rcloSpace = new ExplicitLargeObjectSpace("rclos", DEFAULT_POLL_FREQUENCY, VMRequest.create());
+
+  public static final int REF_COUNT = rcSpace.getDescriptor();
+  public static final int REF_COUNT_LOS = rcloSpace.getDescriptor();
+
+  public final SharedDeque modPool = new SharedDeque("mod", metaDataSpace, 1);
+  public final SharedDeque decPool = new SharedDeque("dec", metaDataSpace, 1);
+  public final SharedDeque newRootPool = new SharedDeque("newRoot", metaDataSpace, 1);
+  public final SharedDeque oldRootPool = new SharedDeque("oldRoot", metaDataSpace, 1);
+
+  /*****************************************************************************
+   *
+   * Instance fields
+   */
+  public final Trace rootTrace;
+  public final Trace backupTrace;
+  private final BTSweeper rcSweeper;
+  private final BTScanLargeObjectSweeper loScanSweeper;
+  private final BTFreeLargeObjectSweeper loFreeSweeper;
+
+  /**
+   * Constructor
+   */
+  public RCBase() {
+    Options.noReferenceTypes.setDefaultValue(true);
+    Options.noFinalizer.setDefaultValue(true);
+
+    rootTrace = new Trace(metaDataSpace);
+    backupTrace = new Trace(metaDataSpace);
+    rcSweeper = new BTSweeper();
+    loScanSweeper = new BTScanLargeObjectSweeper();
+    loFreeSweeper = new BTFreeLargeObjectSweeper();
+  }
+
+  /**
+   * The boot method is called early in the boot process before any
+   * allocation.
+   */
+  @Interruptible
+  public void postBoot() {
+    super.postBoot();
+
+    if (!Options.noReferenceTypes.getValue()) {
+      VM.assertions.fail("Reference Types are not supported by RC");
+    }
+    if (!Options.noFinalizer.getValue()) {
+      VM.assertions.fail("Finalizers are not supported by RC");
+    }
+  }
+
+  /*****************************************************************************
+   *
+   * Collection
+   */
+
+  public static final boolean isRCObject(ObjectReference object) {
+    return !object.isNull() && !Space.isInSpace(VM_SPACE, object);
+  }
+
+  /**
+   * @return Whether last GC is a full GC.
+   */
+  public boolean lastCollectionFullHeap() {
+    return performCycleCollection;
+  }
+
+  /**
+   * Perform a (global) collection phase.
+   *
+   * @param phaseId Collection phase
+   */
+  public void collectionPhase(short phaseId) {
+    if (phaseId == SET_COLLECTION_KIND) {
+      super.collectionPhase(phaseId);
+      if (CC_ENABLED) {
+        performCycleCollection = (collectionAttempt > 1) || emergencyCollection || CC_FORCE_FULL;
+        if (performCycleCollection && Options.verbose.getValue() > 0) Log.write(" [CC] ");
+      }
+      return;
+    }
+
+    if (phaseId == PREPARE) {
+      VM.finalizableProcessor.clear();
+      VM.weakReferences.clear();
+      VM.softReferences.clear();
+      VM.phantomReferences.clear();
+      rootTrace.prepare();
+      rcSpace.prepare();
+      if (CC_BACKUP_TRACE && performCycleCollection) {
+        backupTrace.prepare();
+      }
+      return;
+    }
+
+    if (phaseId == CLOSURE) {
+      rootTrace.prepare();
+      return;
+    }
+
+    if (phaseId == BT_CLOSURE) {
+      if (CC_BACKUP_TRACE && performCycleCollection) {
+        backupTrace.prepare();
+      }
+      return;
+    }
+
+    if (phaseId == PROCESS_OLDROOTBUFFER) {
+      oldRootPool.prepare();
+      return;
+    }
+
+    if (phaseId == PROCESS_NEWROOTBUFFER) {
+      newRootPool.prepare();
+      return;
+    }
+
+
+    if (phaseId == PROCESS_MODBUFFER) {
+      modPool.prepare();
+      return;
+    }
+
+    if (phaseId == PROCESS_DECBUFFER) {
+      decPool.prepare();
+      return;
+    }
+
+    if (phaseId == RELEASE) {
+      rootTrace.release();
+      if (CC_BACKUP_TRACE && performCycleCollection) {
+        backupTrace.release();
+        rcSpace.sweepCells(rcSweeper);
+        rcloSpace.sweep(loScanSweeper);
+        rcloSpace.sweep(loFreeSweeper);
+      } else {
+        rcSpace.release();
+      }
+      return;
+    }
+
+    super.collectionPhase(phaseId);
+  }
+
+  /*****************************************************************************
+   *
+   * Accounting
+   */
+
+  /**
+   * Return the number of pages used given the pending
+   * allocation.
+   *
+   * @return The number of pages reserved given the pending
+   * allocation, excluding space reserved for copying.
+   */
+  public int getPagesUsed() {
+    return (rcSpace.reservedPages() + rcloSpace.reservedPages() + super.getPagesUsed());
+  }
+
+  /**
+   * Perform a linear scan across all objects in the heap to check for leaks.
+   */
+  public void sanityLinearScan(LinearScan scan) {
+    //rcSpace.linearScan(scan);
+  }
+
+  /**
+   * Return the expected reference count. For non-reference counting
+   * collectors this becomes a true/false relationship.
+   *
+   * @param object The object to check.
+   * @param sanityRootRC The number of root references to the object.
+   * @return The expected (root excluded) reference count.
+   */
+  public int sanityExpectedRC(ObjectReference object, int sanityRootRC) {
+    if (RCBase.isRCObject(object)) {
+      int fullRC = RCHeader.getRC(object);
+      if (fullRC == 0) {
+        return SanityChecker.DEAD;
+      }
+      if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(fullRC >= sanityRootRC);
+      return fullRC - sanityRootRC;
+    }
+    return SanityChecker.ALIVE;
+  }
+
+  /**
+   * Register specialized methods.
+   */
+  @Interruptible
+  protected void registerSpecializedMethods() {
+    super.registerSpecializedMethods();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseCollector.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseCollector.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseCollector.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseCollector.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,182 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.refcount;
+
+import org.mmtk.plan.Phase;
+import org.mmtk.plan.StopTheWorldCollector;
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.plan.refcount.backuptrace.BTTraceLocal;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.deque.ObjectReferenceDeque;
+import org.mmtk.vm.VM;
+import org.vmmagic.pragma.Inline;
+import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.unboxed.ObjectReference;
+
+/**
+ * This class implements the collector context for a simple reference counting
+ * collector.
+ */
+ at Uninterruptible
+public abstract class RCBaseCollector extends StopTheWorldCollector {
+
+  /************************************************************************
+   * Initialization
+   */
+  protected final ObjectReferenceDeque newRootBuffer;
+  private final BTTraceLocal backupTrace;
+  private final ObjectReferenceDeque modBuffer;
+  private final ObjectReferenceDeque oldRootBuffer;
+  private final RCDecBuffer decBuffer;
+  private final RCZero zero;
+
+  /**
+   * Constructor.
+   */
+  public RCBaseCollector() {
+    newRootBuffer = new ObjectReferenceDeque("new-root", global().newRootPool);
+    oldRootBuffer = new ObjectReferenceDeque("old-root", global().oldRootPool);
+    modBuffer = new ObjectReferenceDeque("mod buf", global().modPool);
+    decBuffer = new RCDecBuffer(global().decPool);
+    backupTrace = new BTTraceLocal(global().backupTrace);
+    zero = new RCZero();
+  }
+
+  /**
+   * Get the modified processor to use.
+   */
+  protected abstract TransitiveClosure getModifiedProcessor();
+
+  /**
+   * Get the root trace to use.
+   */
+  protected abstract TraceLocal getRootTrace();
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /** Perform garbage collection */
+  public void collect() {
+    Phase.beginNewPhaseStack(Phase.scheduleComplex(global().collection));
+  }
+
+  /**
+   * Perform a per-collector collection phase.
+   *
+   * @param phaseId The collection phase to perform
+   * @param primary perform any single-threaded local activities.
+   */
+  public void collectionPhase(short phaseId, boolean primary) {
+    if (phaseId == RCBase.PREPARE) {
+      getRootTrace().prepare();
+      if (RCBase.CC_BACKUP_TRACE && RCBase.performCycleCollection) backupTrace.prepare();
+      return;
+    }
+
+    if (phaseId == RCBase.CLOSURE) {
+      getRootTrace().completeTrace();
+      newRootBuffer.flushLocal();
+      return;
+    }
+
+    if (phaseId == RCBase.BT_CLOSURE) {
+      if (RCBase.CC_BACKUP_TRACE && RCBase.performCycleCollection) {
+        backupTrace.completeTrace();
+      }
+      return;
+    }
+
+    if (phaseId == RCBase.PROCESS_OLDROOTBUFFER) {
+      ObjectReference current;
+      while(!(current = oldRootBuffer.pop()).isNull()) {
+        decBuffer.push(current);
+      }
+      return;
+    }
+
+    if (phaseId == RCBase.PROCESS_NEWROOTBUFFER) {
+      ObjectReference current;
+      while(!(current = newRootBuffer.pop()).isNull()) {
+        RCHeader.incRC(current);
+        oldRootBuffer.push(current);
+        if (RCBase.CC_BACKUP_TRACE && RCBase.performCycleCollection) {
+          if (RCHeader.testAndMark(current)) {
+            backupTrace.processNode(current);
+          }
+        }
+      }
+      oldRootBuffer.flushLocal();
+      return;
+    }
+
+    if (phaseId == RCBase.PROCESS_MODBUFFER) {
+      ObjectReference current;
+      while(!(current = modBuffer.pop()).isNull()) {
+        RCHeader.makeUnlogged(current);
+        VM.scanning.scanObject(getModifiedProcessor(), current);
+      }
+      return;
+    }
+
+    if (phaseId == RCBase.PROCESS_DECBUFFER) {
+      ObjectReference current;
+      while(!(current = decBuffer.pop()).isNull()) {
+        if (RCHeader.decRC(current) == RCHeader.DEC_KILL) {
+          decBuffer.processChildren(current);
+          if (Space.isInSpace(RCBase.REF_COUNT, current)) {
+            RCBase.rcSpace.free(current);
+          } else if (Space.isInSpace(RCBase.REF_COUNT_LOS, current)) {
+            RCBase.rcloSpace.free(current);
+          } else if (Space.isInSpace(RCBase.IMMORTAL, current)) {
+            VM.scanning.scanObject(zero, current);
+          }
+        }
+      }
+      return;
+    }
+
+    if (phaseId == RCBase.RELEASE) {
+      if (RCBase.CC_BACKUP_TRACE && RCBase.performCycleCollection) {
+        backupTrace.release();
+      }
+      getRootTrace().release();
+      if (VM.VERIFY_ASSERTIONS) {
+        VM.assertions._assert(newRootBuffer.isEmpty());
+        VM.assertions._assert(modBuffer.isEmpty());
+        VM.assertions._assert(decBuffer.isEmpty());
+      }
+      return;
+    }
+
+    super.collectionPhase(phaseId, primary);
+  }
+
+  /****************************************************************************
+   *
+   * Miscellaneous
+   */
+
+  /** @return The active global plan as an <code>RC</code> instance. */
+  @Inline
+  protected static RCBase global() {
+    return (RCBase) VM.activePlan.global();
+  }
+
+  /** @return The current trace instance. */
+  public final TraceLocal getCurrentTrace() {
+    return getRootTrace();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseConstraints.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseConstraints.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseConstraints.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseConstraints.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,36 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.refcount;
+
+import static org.mmtk.policy.SegregatedFreeListSpace.MAX_FREELIST_OBJECT_BYTES;
+import org.mmtk.plan.StopTheWorldConstraints;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class and its subclasses communicate to the host VM/Runtime
+ * any features of the selected plan that it needs to know.  This is
+ * separate from the main Plan/PlanLocal class in order to bypass any
+ * issues with ordering of static initialization.
+ */
+ at Uninterruptible
+public class RCBaseConstraints extends StopTheWorldConstraints {
+  @Override
+  public int gcHeaderBits() { return RCHeader.GLOBAL_GC_BITS_REQUIRED; }
+  @Override
+  public int gcHeaderWords() { return RCHeader.GC_HEADER_WORDS_REQUIRED; }
+  @Override
+  public boolean needsWriteBarrier() { return true; }
+  @Override
+  public int maxNonLOSDefaultAllocBytes() { return MAX_FREELIST_OBJECT_BYTES; }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseMutator.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseMutator.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseMutator.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCBaseMutator.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,334 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.refcount;
+
+import org.mmtk.plan.StopTheWorldMutator;
+import org.mmtk.plan.refcount.backuptrace.BTSweepImmortalScanner;
+import org.mmtk.policy.ExplicitFreeListLocal;
+import org.mmtk.policy.ExplicitFreeListSpace;
+import org.mmtk.policy.LargeObjectLocal;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.alloc.Allocator;
+import org.mmtk.utility.deque.ObjectReferenceDeque;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements the mutator context for a simple reference counting collector.
+ */
+ at Uninterruptible
+public class RCBaseMutator extends StopTheWorldMutator {
+
+  /************************************************************************
+   * Instance fields
+   */
+  private final ExplicitFreeListLocal rc;
+  private final LargeObjectLocal rclos;
+  private final ObjectReferenceDeque modBuffer;
+  private final RCDecBuffer decBuffer;
+  private final BTSweepImmortalScanner btSweepImmortal;
+
+  /************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * Constructor. One instance is created per physical processor.
+   */
+  public RCBaseMutator() {
+    rc = new ExplicitFreeListLocal(RCBase.rcSpace);
+    rclos = new LargeObjectLocal(RCBase.rcloSpace);
+    modBuffer = new ObjectReferenceDeque("mod", global().modPool);
+    decBuffer = new RCDecBuffer(global().decPool);
+    btSweepImmortal = new BTSweepImmortalScanner();
+  }
+
+  /****************************************************************************
+   *
+   * Mutator-time allocation
+   */
+
+  /**
+   * Allocate memory for an object.
+   *
+   * @param bytes The number of bytes required for the object.
+   * @param align Required alignment for the object.
+   * @param offset Offset associated with the alignment.
+   * @param allocator The allocator associated with this request.
+   * @param site Allocation site
+   * @return The address of the newly allocated memory.
+   */
+  @Inline
+  public Address alloc(int bytes, int align, int offset, int allocator, int site) {
+    switch (allocator) {
+      case RCBase.ALLOC_DEFAULT:
+      case RCBase.ALLOC_NON_MOVING:
+      case RCBase.ALLOC_CODE:
+        return rc.alloc(bytes, align, offset);
+      case RCBase.ALLOC_LOS:
+      case RCBase.ALLOC_PRIMITIVE_LOS:
+      case RCBase.ALLOC_LARGE_CODE:
+        return rclos.alloc(bytes, align, offset);
+      case RCBase.ALLOC_IMMORTAL:
+        return super.alloc(bytes, align, offset, allocator, site);
+      default:
+        VM.assertions.fail("Allocator not understood by RC");
+        return Address.zero();
+    }
+  }
+
+  /**
+   * Perform post-allocation actions.  For many allocators none are
+   * required.
+   *
+   * @param ref The newly allocated object
+   * @param typeRef the type reference for the instance being created
+   * @param bytes The size of the space to be allocated (in bytes)
+   * @param allocator The allocator number to be used for this allocation
+   */
+  @Inline
+  public void postAlloc(ObjectReference ref, ObjectReference typeRef, int bytes, int allocator) {
+    switch (allocator) {
+    case RCBase.ALLOC_DEFAULT:
+    case RCBase.ALLOC_NON_MOVING:
+      modBuffer.push(ref);
+    case RCBase.ALLOC_CODE:
+      decBuffer.push(ref);
+      RCHeader.initializeHeader(ref, true);
+      ExplicitFreeListSpace.unsyncSetLiveBit(ref);
+      break;
+    case RCBase.ALLOC_LOS:
+      modBuffer.push(ref);
+    case RCBase.ALLOC_PRIMITIVE_LOS:
+    case RCBase.ALLOC_LARGE_CODE:
+      decBuffer.push(ref);
+      RCHeader.initializeHeader(ref, true);
+      RCBase.rcloSpace.initializeHeader(ref, true);
+      return;
+    case RCBase.ALLOC_IMMORTAL:
+      modBuffer.push(ref);
+      decBuffer.push(ref);
+      RCHeader.initializeHeader(ref, true);
+      return;
+    default:
+      VM.assertions.fail("Allocator not understood by RC");
+      return;
+    }
+  }
+
+  /**
+   * Return the allocator instance associated with a space
+   * <code>space</code>, for this plan instance.
+   *
+   * @param space The space for which the allocator instance is desired.
+   * @return The allocator instance associated with this plan instance
+   * which is allocating into <code>space</code>, or <code>null</code>
+   * if no appropriate allocator can be established.
+   */
+  public Allocator getAllocatorFromSpace(Space space) {
+    if (space == RCBase.rcSpace) return rc;
+    if (space == RCBase.rcloSpace) return rclos;
+
+    return super.getAllocatorFromSpace(space);
+  }
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a per-mutator collection phase.
+   *
+   * @param phaseId The collection phase to perform
+   * @param primary perform any single-threaded local activities.
+   */
+  public void collectionPhase(short phaseId, boolean primary) {
+    if (phaseId == RCBase.PREPARE) {
+      rc.prepare();
+      return;
+    }
+
+    if (phaseId == RCBase.PROCESS_MODBUFFER) {
+      modBuffer.flushLocal();
+      return;
+    }
+
+    if (phaseId == RCBase.PROCESS_DECBUFFER) {
+      decBuffer.flushLocal();
+      return;
+    }
+
+    if (phaseId == RCBase.RELEASE) {
+      if (RCBase.CC_BACKUP_TRACE && RCBase.performCycleCollection) {
+        immortal.linearScan(btSweepImmortal);
+      }
+      rc.release();
+      if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(modBuffer.isEmpty());
+      if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(decBuffer.isEmpty());
+      return;
+    }
+
+    super.collectionPhase(phaseId, primary);
+  }
+
+  /**
+   * Flush per-mutator remembered sets into the global remset pool.
+   */
+  public final void flushRememberedSets() {
+    decBuffer.flushLocal();
+    modBuffer.flushLocal();
+    assertRemsetsFlushed();
+  }
+
+  /**
+   * Assert that the remsets have been flushed.  This is critical to
+   * correctness.  We need to maintain the invariant that remset entries
+   * do not accrue during GC.  If the host JVM generates barrier entires
+   * it is its own responsibility to ensure that they are flushed before
+   * returning to MMTk.
+   */
+  public final void assertRemsetsFlushed() {
+    if (VM.VERIFY_ASSERTIONS) {
+      VM.assertions._assert(decBuffer.isFlushed());
+      VM.assertions._assert(modBuffer.isFlushed());
+    }
+  }
+
+  /**
+   * Flush mutator context, in response to a requestMutatorFlush.
+   * Also called by the default implementation of deinitMutator.
+   */
+  @Override
+  public void flush() {
+    super.flush();
+    rc.flush();
+  }
+
+  /****************************************************************************
+   *
+   * Write barriers.
+   */
+
+  /**
+   * A new reference is about to be created. Take appropriate write
+   * barrier actions.<p>
+   *
+   * <b>By default do nothing, override if appropriate.</b>
+   *
+   * @param src The object into which the new reference will be stored
+   * @param slot The address into which the new reference will be
+   * stored.
+   * @param tgt The target of the new reference
+   * @param metaDataA A value that assists the host VM in creating a store
+   * @param metaDataB A value that assists the host VM in creating a store
+   * @param mode The context in which the store occurred
+   */
+  @Inline
+  public void writeBarrier(ObjectReference src, Address slot,
+                           ObjectReference tgt, Word metaDataA,
+                           Word metaDataB, int mode) {
+    if (RCHeader.logRequired(src)) {
+      coalescingWriteBarrierSlow(src);
+    }
+    VM.barriers.performWriteInBarrier(src,slot,tgt, metaDataA, metaDataB, mode);
+  }
+
+  /**
+   * Attempt to atomically exchange the value in the given slot
+   * with the passed replacement value. If a new reference is
+   * created, we must then take appropriate write barrier actions.<p>
+   *
+   * <b>By default do nothing, override if appropriate.</b>
+   *
+   * @param src The object into which the new reference will be stored
+   * @param slot The address into which the new reference will be
+   * stored.
+   * @param old The old reference to be swapped out
+   * @param tgt The target of the new reference
+   * @param metaDataA A value that assists the host VM in creating a store
+   * @param metaDataB A value that assists the host VM in creating a store
+   * @param mode The context in which the store occured
+   * @return True if the swap was successful.
+   */
+  @Inline
+  public boolean tryCompareAndSwapWriteBarrier(ObjectReference src, Address slot,
+                                               ObjectReference old, ObjectReference tgt, Word metaDataA,
+                                               Word metaDataB, int mode) {
+    if (RCHeader.logRequired(src)) {
+      coalescingWriteBarrierSlow(src);
+    }
+    return VM.barriers.tryCompareAndSwapWriteInBarrier(src,slot,old,tgt,metaDataA,metaDataB,mode);
+  }
+
+  /**
+   * A number of references are about to be copied from object
+   * <code>src</code> to object <code>dst</code> (as in an array
+   * copy).  Thus, <code>dst</code> is the mutated object.  Take
+   * appropriate write barrier actions.<p>
+   *
+   * @param src The source of the values to be copied
+   * @param srcOffset The offset of the first source address, in
+   * bytes, relative to <code>src</code> (in principle, this could be
+   * negative).
+   * @param dst The mutated object, i.e. the destination of the copy.
+   * @param dstOffset The offset of the first destination address, in
+   * bytes relative to <code>tgt</code> (in principle, this could be
+   * negative).
+   * @param bytes The size of the region being copied, in bytes.
+   * @return True if the update was performed by the barrier, false if
+   * left to the caller (always false in this case).
+   */
+  @Inline
+  public boolean writeBarrier(ObjectReference src, Offset srcOffset,
+                              ObjectReference dst, Offset dstOffset, int bytes) {
+    if (RCHeader.logRequired(dst)) {
+      coalescingWriteBarrierSlow(dst);
+    }
+    return false;
+  }
+
+  /**
+   * Slow path of the coalescing write barrier.
+   *
+   * <p> Attempt to log the source object. If successful in racing for
+   * the log bit, push an entry into the modified buffer and add a
+   * decrement buffer entry for each referent object (in the RC space)
+   * before setting the header bit to indicate that it has finished
+   * logging (allowing others in the race to continue).
+   *
+   * @param srcObj The object being mutated
+   */
+  @NoInline
+  private void coalescingWriteBarrierSlow(ObjectReference srcObj) {
+    if (RCHeader.attemptToLog(srcObj)) {
+      modBuffer.push(srcObj);
+      decBuffer.processChildren(srcObj);
+      RCHeader.makeLogged(srcObj);
+    }
+  }
+
+  /****************************************************************************
+   *
+   * Miscellaneous
+   */
+
+  /** @return The active global plan as an <code>RC</code> instance. */
+  @Inline
+  private static RCBase global() {
+    return (RCBase) VM.activePlan.global();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCDecBuffer.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCDecBuffer.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCDecBuffer.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCDecBuffer.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,53 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.refcount;
+
+import org.mmtk.utility.Constants;
+import org.mmtk.utility.deque.*;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements a dec-buffer for a reference counting collector
+ *
+ * @see org.mmtk.plan.TransitiveClosure
+ */
+ at Uninterruptible
+public final class RCDecBuffer extends ObjectReferenceBuffer implements Constants {
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * Constructor
+   *
+   * @param queue The shared deque that is used.
+   */
+  public RCDecBuffer(SharedDeque queue) {
+    super("dec", queue);
+  }
+
+  /**
+   * This is the method that ensures
+   *
+   * @param object The object to process.
+   */
+  @Inline
+  protected void process(ObjectReference object) {
+    if (RCBase.isRCObject(object)) {
+      push(object);
+    }
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCHeader.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCHeader.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCHeader.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCHeader.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,276 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.refcount;
+
+import org.mmtk.utility.Constants;
+import org.mmtk.vm.VM;
+import org.vmmagic.pragma.Inline;
+import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.unboxed.ObjectReference;
+import org.vmmagic.unboxed.Offset;
+import org.vmmagic.unboxed.Word;
+
+ at Uninterruptible
+public class RCHeader implements Constants {
+  /* Requirements */
+  public static final int LOCAL_GC_BITS_REQUIRED = 0;
+  public static final int GLOBAL_GC_BITS_REQUIRED = 2;
+  public static final int GC_HEADER_WORDS_REQUIRED = 1;
+
+  /****************************************************************************
+   * Object Logging (applies to *all* objects)
+   */
+
+  /* Mask bits to signify the start/finish of logging an object */
+  public static final int      LOG_BIT  = 0;
+  public static final Word       LOGGED = Word.zero();                          //...00000
+  public static final Word    UNLOGGED  = Word.one();                           //...00001
+  public static final Word BEING_LOGGED = Word.one().lsh(2).minus(Word.one());  //...00011
+  public static final Word LOGGING_MASK = LOGGED.or(UNLOGGED).or(BEING_LOGGED); //...00011
+
+  /**
+   * Return true if <code>object</code> is yet to be logged (for
+   * coalescing RC).
+   *
+   * @param object The object in question
+   * @return <code>true</code> if <code>object</code> needs to be logged.
+   */
+  @Inline
+  @Uninterruptible
+  public static boolean logRequired(ObjectReference object) {
+    Word value = VM.objectModel.readAvailableBitsWord(object);
+    return value.and(LOGGING_MASK).EQ(UNLOGGED);
+  }
+
+  /**
+   * Attempt to log <code>object</code> for coalescing RC. This is
+   * used to handle a race to log the object, and returns
+   * <code>true</code> if we are to log the object and
+   * <code>false</code> if we lost the race to log the object.
+   *
+   * <p>If this method returns <code>true</code>, it leaves the object
+   * in the <code>BEING_LOGGED</code> state.  It is the responsibility
+   * of the caller to change the object to <code>LOGGED</code> once
+   * the logging is complete.
+   *
+   * @see #makeLogged(ObjectReference)
+   * @param object The object in question
+   * @return <code>true</code> if the race to log
+   * <code>object</code>was won.
+   */
+  @Inline
+  @Uninterruptible
+  public static boolean attemptToLog(ObjectReference object) {
+    Word oldValue;
+    do {
+      oldValue = VM.objectModel.prepareAvailableBits(object);
+      if (oldValue.and(LOGGING_MASK).EQ(LOGGED)) {
+        return false;
+      }
+    } while ((oldValue.and(LOGGING_MASK).EQ(BEING_LOGGED)) ||
+             !VM.objectModel.attemptAvailableBits(object, oldValue, oldValue.or(BEING_LOGGED)));
+    if (VM.VERIFY_ASSERTIONS) {
+      Word value = VM.objectModel.readAvailableBitsWord(object);
+      VM.assertions._assert(value.and(LOGGING_MASK).EQ(BEING_LOGGED));
+    }
+    return true;
+  }
+
+
+  /**
+   * Signify completion of logging <code>object</code>.
+   *
+   * <code>object</code> is left in the <code>LOGGED</code> state.
+   *
+   * @see #attemptToLog(ObjectReference)
+   * @param object The object whose state is to be changed.
+   */
+  @Inline
+  @Uninterruptible
+  public static void makeLogged(ObjectReference object) {
+    Word value = VM.objectModel.readAvailableBitsWord(object);
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(value.and(LOGGING_MASK).NE(LOGGED));
+    VM.objectModel.writeAvailableBitsWord(object, value.and(LOGGING_MASK.not()));
+  }
+
+  /**
+   * Change <code>object</code>'s state to <code>UNLOGGED</code>.
+   *
+   * @param object The object whose state is to be changed.
+   */
+  @Inline
+  @Uninterruptible
+  public static void makeUnlogged(ObjectReference object) {
+    Word value = VM.objectModel.readAvailableBitsWord(object);
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(value.and(LOGGING_MASK).EQ(LOGGED));
+    VM.objectModel.writeAvailableBitsWord(object, value.or(UNLOGGED));
+  }
+
+  /************************************************************************
+   * RC header word
+   */
+
+  /* Header offset */
+  public static final Offset RC_HEADER_OFFSET = VM.objectModel.GC_HEADER_OFFSET();
+
+  /* Reserved to allow alignment hole filling to work */
+  public static final int RESERVED_ALIGN_BIT = 0;
+
+  /* The mark bit used for backup tracing. */
+  public static final int MARK_BIT = 1;
+  public static final Word MARK_BIT_MASK = Word.one().lsh(MARK_BIT);
+
+  /* Current not using any bits for cycle detection, etc */
+  public static final int BITS_USED = 2;
+
+  /* Reference counting increments */
+  public static final int INCREMENT_SHIFT = BITS_USED;
+  public static final Word INCREMENT = Word.one().lsh(INCREMENT_SHIFT);
+  public static final int AVAILABLE_BITS = BITS_IN_ADDRESS - BITS_USED;
+  public static final Word INCREMENT_LIMIT = Word.one().lsh(BITS_IN_ADDRESS-1).not();
+  public static final Word LIVE_THRESHOLD = INCREMENT;
+
+  /* Return values from decRC */
+  public static final int DEC_KILL = 0;
+  public static final int DEC_ALIVE = 1;
+
+  /**
+   * Has this object been marked by the most recent backup trace.
+   */
+  @Inline
+  public static boolean isMarked(ObjectReference object) {
+    return isHeaderMarked(object.toAddress().loadWord(RC_HEADER_OFFSET));
+  }
+
+  /**
+   * Has this object been marked by the most recent backup trace.
+   */
+  @Inline
+  public static void clearMarked(ObjectReference object) {
+    Word oldValue, newValue;
+    do {
+      oldValue = object.toAddress().prepareWord(RC_HEADER_OFFSET);
+      if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isHeaderMarked(oldValue));
+      newValue = oldValue.and(MARK_BIT_MASK.not());
+    } while (!object.toAddress().attempt(oldValue, newValue, RC_HEADER_OFFSET));
+    /*
+    Word header = object.toAddress().loadWord(RC_HEADER_OFFSET);
+    object.toAddress().store(header.and(MARK_BIT_MASK.not()), RC_HEADER_OFFSET);*/
+  }
+
+  /**
+   * Has this object been marked by the most recent backup trace.
+   */
+  @Inline
+  private static boolean isHeaderMarked(Word header) {
+    return header.and(MARK_BIT_MASK).EQ(MARK_BIT_MASK);
+  }
+
+  /**
+   * Attempt to atomically mark this object. Return true if the mark was performed.
+   */
+  @Inline
+  public static boolean testAndMark(ObjectReference object) {
+    Word oldValue, newValue;
+    do {
+      oldValue = object.toAddress().prepareWord(RC_HEADER_OFFSET);
+      if (isHeaderMarked(oldValue)) {
+        return false;
+      }
+      newValue = oldValue.or(MARK_BIT_MASK);
+    } while (!object.toAddress().attempt(oldValue, newValue, RC_HEADER_OFFSET));
+    return true;
+  }
+
+  /**
+   * Perform any required initialization of the GC portion of the header.
+   *
+   * @param object the object
+   * @param initialInc start with a reference count of 1 (0 if false)
+   */
+  @Inline
+  public static void initializeHeader(ObjectReference object, boolean initialInc) {
+    Word initialValue =  (initialInc) ? INCREMENT : Word.zero();
+    object.toAddress().store(initialValue, RC_HEADER_OFFSET);
+  }
+
+  /**
+   * Return true if given object is live
+   *
+   * @param object The object whose liveness is to be tested
+   * @return True if the object is alive
+   */
+  @Inline
+  @Uninterruptible
+  public static boolean isLiveRC(ObjectReference object) {
+    return object.toAddress().loadWord(RC_HEADER_OFFSET).GE(LIVE_THRESHOLD);
+  }
+
+  /**
+   * Return the reference count for the object.
+   *
+   * @param object The object whose liveness is to be tested
+   * @return True if the object is alive
+   */
+  @Inline
+  @Uninterruptible
+  public static int getRC(ObjectReference object) {
+    return object.toAddress().loadWord(RC_HEADER_OFFSET).rshl(INCREMENT_SHIFT).toInt();
+  }
+
+  /**
+   * Increment the reference count of an object.
+   *
+   * @param object The object whose reference count is to be incremented.
+   */
+  @Inline
+  public static void incRC(ObjectReference object) {
+    Word oldValue, newValue;
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(RCBase.isRCObject(object));
+    do {
+      oldValue = object.toAddress().prepareWord(RC_HEADER_OFFSET);
+      newValue = oldValue.plus(INCREMENT);
+      if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(newValue.LE(INCREMENT_LIMIT));
+    } while (!object.toAddress().attempt(oldValue, newValue, RC_HEADER_OFFSET));
+  }
+
+  /**
+   * Decrement the reference count of an object.  Return either
+   * <code>DEC_KILL</code> if the count went to zero,
+   * <code>DEC_ALIVE</code> if the count did not go to zero.
+   *
+   * @param object The object whose RC is to be decremented.
+   * @return <code>DEC_KILL</code> if the count went to zero,
+   * <code>DEC_ALIVE</code> if the count did not go to zero.
+   */
+  @Inline
+  @Uninterruptible
+  public static int decRC(ObjectReference object) {
+    Word oldValue, newValue;
+    int rtn;
+    if (VM.VERIFY_ASSERTIONS) {
+      VM.assertions._assert(RCBase.isRCObject(object));
+      VM.assertions._assert(isLiveRC(object));
+    }
+    do {
+      oldValue = object.toAddress().prepareWord(RC_HEADER_OFFSET);
+      newValue = oldValue.minus(INCREMENT);
+      if (newValue.LT(LIVE_THRESHOLD)) {
+        rtn = DEC_KILL;
+      } else {
+        rtn = DEC_ALIVE;
+      }
+    } while (!object.toAddress().attempt(oldValue, newValue, RC_HEADER_OFFSET));
+    return rtn;
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCZero.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCZero.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCZero.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/RCZero.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,40 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.refcount;
+
+import org.mmtk.plan.TransitiveClosure;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class is the fundamental mechanism for performing a
+ * transitive closure over an object graph.<p>
+ *
+ * @see org.mmtk.plan.TraceLocal
+ */
+ at Uninterruptible
+public final class RCZero extends TransitiveClosure {
+
+  /**
+   * Trace an edge during GC.
+   *
+   * @param source The source of the reference.
+   * @param slot The location containing the object reference.
+   */
+  @Inline
+  public void processEdge(ObjectReference source, Address slot) {
+    slot.store(ObjectReference.nullReference());
+  }
+}
+

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTDecMarked.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTDecMarked.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTDecMarked.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTDecMarked.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,51 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.refcount.backuptrace;
+
+import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.plan.refcount.RCBase;
+import org.mmtk.plan.refcount.RCHeader;
+import org.mmtk.policy.Space;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class is the fundamental mechanism for performing a
+ * transitive closure over an object graph.<p>
+ *
+ * @see org.mmtk.plan.TraceLocal
+ */
+ at Uninterruptible
+public final class BTDecMarked extends TransitiveClosure {
+
+  /**
+   * Trace an edge during GC.
+   *
+   * @param source The source of the reference.
+   * @param slot The location containing the object reference.
+   */
+  @Inline
+  public void processEdge(ObjectReference source, Address slot) {
+    ObjectReference object = slot.loadObjectReference();
+    if (!object.isNull()) {
+      if ((Space.isInSpace(RCBase.REF_COUNT, object) && RCBase.rcSpace.isLive(object)) ||
+          Space.isInSpace(RCBase.REF_COUNT_LOS, object) ||
+          Space.isInSpace(RCBase.IMMORTAL, object)) {
+        int result = RCHeader.decRC(object);
+        if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(result != RCHeader.DEC_KILL || !RCHeader.isMarked(object));
+      }
+    }
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTDecMarkedAndZero.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTDecMarkedAndZero.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTDecMarkedAndZero.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTDecMarkedAndZero.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,52 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.refcount.backuptrace;
+
+import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.plan.refcount.RCBase;
+import org.mmtk.plan.refcount.RCHeader;
+import org.mmtk.policy.Space;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class is the fundamental mechanism for performing a
+ * transitive closure over an object graph.<p>
+ *
+ * @see org.mmtk.plan.TraceLocal
+ */
+ at Uninterruptible
+public final class BTDecMarkedAndZero extends TransitiveClosure {
+
+  /**
+   * Trace an edge during GC.
+   *
+   * @param source The source of the reference.
+   * @param slot The location containing the object reference.
+   */
+  @Inline
+  public void processEdge(ObjectReference source, Address slot) {
+    ObjectReference object = slot.loadObjectReference();
+    slot.store(ObjectReference.nullReference());
+    if (!object.isNull()) {
+      if ((Space.isInSpace(RCBase.REF_COUNT, object) && RCBase.rcSpace.isLive(object)) ||
+          Space.isInSpace(RCBase.REF_COUNT_LOS, object) ||
+          Space.isInSpace(RCBase.IMMORTAL, object)) {
+        int result = RCHeader.decRC(object);
+        if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(result != RCHeader.DEC_KILL || !RCHeader.isMarked(object));
+      }
+    }
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTFreeLargeObjectSweeper.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTFreeLargeObjectSweeper.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTFreeLargeObjectSweeper.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTFreeLargeObjectSweeper.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,36 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.refcount.backuptrace;
+
+import org.mmtk.plan.refcount.RCHeader;
+import org.mmtk.policy.ExplicitLargeObjectSpace;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements the freeing of large objects during a backup trace.
+ */
+ at Uninterruptible
+public final class BTFreeLargeObjectSweeper extends ExplicitLargeObjectSpace.Sweeper {
+
+  public boolean sweepLargeObject(ObjectReference object) {
+    if (!RCHeader.isMarked(object)) {
+      // Free the object
+      return true;
+    }
+    // Clear the mark-bit and retain the object.
+    RCHeader.clearMarked(object);
+    return false;
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTScanLargeObjectSweeper.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTScanLargeObjectSweeper.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTScanLargeObjectSweeper.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTScanLargeObjectSweeper.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,37 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.refcount.backuptrace;
+
+import org.mmtk.plan.refcount.RCHeader;
+import org.mmtk.policy.ExplicitLargeObjectSpace;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements the scanning of dead large objects during a backup trace.
+ */
+ at Uninterruptible
+public final class BTScanLargeObjectSweeper extends ExplicitLargeObjectSpace.Sweeper {
+
+  private final BTDecMarked sdm = new BTDecMarked();
+
+  public boolean sweepLargeObject(ObjectReference object) {
+    if (!RCHeader.isMarked(object)) {
+      VM.scanning.scanObject(sdm, object);
+    }
+    // Do not free any objects at this time
+    return false;
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTSweepImmortalScanner.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTSweepImmortalScanner.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTSweepImmortalScanner.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTSweepImmortalScanner.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,43 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.refcount.backuptrace;
+
+import org.mmtk.plan.refcount.RCHeader;
+import org.mmtk.utility.alloc.LinearScan;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class is used in backup tracing to sweep and zero any dead 'immortal' objects.
+ */
+ at Uninterruptible
+public final class BTSweepImmortalScanner extends LinearScan {
+
+  private final BTDecMarkedAndZero sdmAZ = new BTDecMarkedAndZero();
+
+  /**
+   * Scan an object during sweep.
+   *
+   * @param object The source of the reference.
+   */
+  @Inline
+  public void scan(ObjectReference object) {
+    if (!RCHeader.isMarked(object)) {
+      VM.scanning.scanObject(sdmAZ, object);
+    } else {
+      RCHeader.clearMarked(object);
+    }
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTSweeper.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTSweeper.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTSweeper.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTSweeper.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,40 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.refcount.backuptrace;
+
+import org.mmtk.plan.refcount.RCHeader;
+import org.mmtk.policy.ExplicitFreeListSpace;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements the thread-local core functionality for a transitive
+ * closure over the heap graph.
+ */
+ at Uninterruptible
+public final class BTSweeper extends ExplicitFreeListSpace.Sweeper {
+
+  private final BTDecMarked sdm = new BTDecMarked();
+
+  public boolean sweepCell(ObjectReference object) {
+    if (!RCHeader.isMarked(object)) {
+      VM.scanning.scanObject(sdm, object);
+      return true;
+    } else {
+      RCHeader.clearMarked(object);
+    }
+    return false;
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTTraceLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTTraceLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTTraceLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/backuptrace/BTTraceLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,66 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.refcount.backuptrace;
+
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.plan.Trace;
+import org.mmtk.plan.refcount.RCBase;
+import org.mmtk.plan.refcount.RCHeader;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements the thread-local core functionality for a transitive
+ * closure over the heap graph.
+ */
+ at Uninterruptible
+public final class BTTraceLocal extends TraceLocal {
+  /**
+   * Constructor
+   */
+  public BTTraceLocal(Trace trace) {
+    super(trace);
+  }
+
+  /****************************************************************************
+   *
+   * Externally visible Object processing and tracing
+   */
+
+  /**
+   * Is the specified object reachable?
+   *
+   * @param object The object.
+   * @return <code>true</code> if the object is reachable.
+   */
+  public boolean isLive(ObjectReference object) {
+    return !RCBase.isRCObject(object) || RCHeader.isMarked(object);
+  }
+
+  /**
+   * When we trace a non-root object we do nothing.
+   *
+   * @param object The object to be traced.
+   * @return The new reference to the same object instance.
+   */
+  @Inline
+  public ObjectReference traceObject(ObjectReference object) {
+    if (RCBase.isRCObject(object)) {
+      if (RCHeader.testAndMark(object)) {
+        processNode(object);
+      }
+    }
+    return object;
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RC.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RC.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RC.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RC.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,23 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.refcount.fullheap;
+
+import org.mmtk.plan.refcount.RCBase;
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements the global state of a a simple reference counting collector.
+ */
+ at Uninterruptible
+public class RC extends RCBase {
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCCollector.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCCollector.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCCollector.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCCollector.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,53 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.refcount.fullheap;
+
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.plan.refcount.RCBaseCollector;
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements the collector context for a simple reference counting
+ * collector.
+ */
+ at Uninterruptible
+public class RCCollector extends RCBaseCollector {
+  /************************************************************************
+   * Initialization
+   */
+  private final RCFindRootSetTraceLocal rootTrace;
+  private final RCModifiedProcessor modProcessor;
+
+  /**
+   * Constructor.
+   */
+  public RCCollector() {
+    rootTrace = new RCFindRootSetTraceLocal(global().rootTrace, newRootBuffer);
+    modProcessor = new RCModifiedProcessor();
+  }
+
+  /**
+   * Get the modified processor to use.
+   */
+  protected final TransitiveClosure getModifiedProcessor() {
+    return modProcessor;
+  }
+
+  /**
+   * Get the root trace to use.
+   */
+  protected final TraceLocal getRootTrace() {
+    return rootTrace;
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCConstraints.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCConstraints.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCConstraints.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCConstraints.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,26 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.refcount.fullheap;
+
+import org.mmtk.plan.refcount.RCBaseConstraints;
+import org.vmmagic.pragma.*;
+
+/**
+ * This class and its subclasses communicate to the host VM/Runtime
+ * any features of the selected plan that it needs to know.  This is
+ * separate from the main Plan/PlanLocal class in order to bypass any
+ * issues with ordering of static initialization.
+ */
+ at Uninterruptible
+public class RCConstraints extends RCBaseConstraints {
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCFindRootSetTraceLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCFindRootSetTraceLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCFindRootSetTraceLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCFindRootSetTraceLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,80 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.refcount.fullheap;
+
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.plan.Trace;
+import org.mmtk.plan.refcount.RCBase;
+import org.mmtk.plan.refcount.RCHeader;
+import org.mmtk.utility.deque.ObjectReferenceDeque;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements the thread-local core functionality for a transitive
+ * closure over the heap graph.
+ */
+ at Uninterruptible
+public final class RCFindRootSetTraceLocal extends TraceLocal {
+
+  private final ObjectReferenceDeque rootBuffer;
+
+  /**
+   * Constructor
+   */
+  public RCFindRootSetTraceLocal(Trace trace, ObjectReferenceDeque rootBuffer) {
+    super(trace);
+    this.rootBuffer = rootBuffer;
+  }
+
+  /****************************************************************************
+   *
+   * Externally visible Object processing and tracing
+   */
+
+  /**
+   * Is the specified object reachable?
+   *
+   * @param object The object.
+   * @return <code>true</code> if the object is reachable.
+   */
+  public boolean isLive(ObjectReference object) {
+    return RCBase.isRCObject(object) && RCHeader.isLiveRC(object) || super.isLive(object);
+  }
+
+  /**
+   * When we trace a non-root object we do nothing.
+   *
+   * @param object The object to be traced.
+   * @return The new reference to the same object instance.
+   */
+  @Inline
+  public ObjectReference traceObject(ObjectReference object) {
+    return object;
+  }
+
+  /**
+   * When we trace a root object we remember it.
+   *
+   * @param object The object to be traced.
+   * @return The new reference to the same object instance.
+   */
+  @Inline
+  public ObjectReference traceObject(ObjectReference object, boolean root) {
+    if (root && RCBase.isRCObject(object)) {
+      rootBuffer.push(object);
+    }
+    return object;
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCModifiedProcessor.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCModifiedProcessor.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCModifiedProcessor.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCModifiedProcessor.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,44 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.refcount.fullheap;
+
+import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.plan.refcount.RCBase;
+import org.mmtk.plan.refcount.RCHeader;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class is the fundamental mechanism for performing a
+ * transitive closure over an object graph.<p>
+ *
+ * @see org.mmtk.plan.TraceLocal
+ */
+ at Uninterruptible
+public final class RCModifiedProcessor extends TransitiveClosure {
+
+  /**
+   * Trace an edge during GC.
+   *
+   * @param source The source of the reference.
+   * @param slot The location containing the object reference.
+   */
+  @Inline
+  public void processEdge(ObjectReference source, Address slot) {
+    ObjectReference object = slot.loadObjectReference();
+    if (RCBase.isRCObject(object)) {
+      RCHeader.incRC(object);
+    }
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCMutator.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCMutator.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCMutator.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/fullheap/RCMutator.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,23 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.refcount.fullheap;
+
+import org.mmtk.plan.refcount.RCBaseMutator;
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements the mutator context for a simple reference counting collector.
+ */
+ at Uninterruptible
+public class RCMutator extends RCBaseMutator {
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRC.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRC.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRC.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRC.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,128 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.refcount.generational;
+
+import org.mmtk.plan.refcount.RCBase;
+import org.mmtk.policy.CopySpace;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.heap.VMRequest;
+import org.mmtk.utility.options.Options;
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.ObjectReference;
+
+/**
+ * This class implements the global state of a a simple reference counting collector.
+ */
+ at Uninterruptible
+public class GenRC extends RCBase {
+
+  public static final int ALLOC_NURSERY = ALLOC_DEFAULT;
+  public static final int ALLOC_RC      = RCBase.ALLOCATORS + 1;
+
+  /** The nursery space is where all new objects are allocated by default */
+  public static final CopySpace nurserySpace = new CopySpace("nursery", DEFAULT_POLL_FREQUENCY, false, VMRequest.create(0.15f, true));
+
+  public static final int NURSERY = nurserySpace.getDescriptor();
+
+  /*****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a (global) collection phase.
+   *
+   * @param phaseId Collection phase
+   */
+  public final void collectionPhase(short phaseId) {
+   if (phaseId == PREPARE) {
+      nurserySpace.prepare(true);
+      super.collectionPhase(phaseId);
+      return;
+    }
+
+    if (phaseId == RELEASE) {
+      super.collectionPhase(phaseId);
+      nurserySpace.release();
+      return;
+    }
+
+    super.collectionPhase(phaseId);
+  }
+
+  /**
+   * This method controls the triggering of a GC. It is called periodically
+   * during allocation. Returns true to trigger a collection.
+   *
+   * @param spaceFull Space request failed, must recover pages within 'space'.
+   * @return True if a collection is requested by the plan.
+   */
+  public final boolean collectionRequired(boolean spaceFull) {
+    boolean nurseryFull = nurserySpace.reservedPages() > Options.nurserySize.getMaxNursery();
+    return super.collectionRequired(spaceFull) || nurseryFull;
+  }
+
+  /*****************************************************************************
+   *
+   * Accounting
+   */
+
+  /**
+   * Return the number of pages available for allocation, <i>assuming
+   * all future allocation is to the nursery</i>.
+   *
+   * @return The number of pages available for allocation, <i>assuming
+   * all future allocation is to the nursery</i>.
+   */
+  public int getPagesAvail() {
+    return super.getPagesAvail() >> 1;
+  }
+
+  /**
+   * Return the number of pages reserved for copying.
+   *
+   * @return The number of pages reserved given the pending
+   * allocation, including space reserved for copying.
+   */
+  public final int getCollectionReserve() {
+    return nurserySpace.reservedPages() + super.getCollectionReserve();
+  }
+
+  /**
+   * Calculate the number of pages a collection is required to free to satisfy
+   * outstanding allocation requests.
+   *
+   * @return the number of pages a collection is required to free to satisfy
+   * outstanding allocation requests.
+   */
+  public int getPagesRequired() {
+    return super.getPagesRequired() + (nurserySpace.requiredPages() << 1);
+  }
+
+  /**
+   * @see org.mmtk.plan.Plan#willNeverMove
+   *
+   * @param object Object in question
+   * @return True if the object will never move
+   */
+  @Override
+  public boolean willNeverMove(ObjectReference object) {
+    if (Space.isInSpace(NURSERY, object)) {
+      return false;
+    }
+    if (Space.isInSpace(REF_COUNT_LOS, object)) {
+      return true;
+    }
+    return super.willNeverMove(object);
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCCollector.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCCollector.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCCollector.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCCollector.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,124 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.refcount.generational;
+
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.plan.refcount.RCBase;
+import org.mmtk.plan.refcount.RCBaseCollector;
+import org.mmtk.plan.refcount.RCHeader;
+import org.mmtk.policy.CopySpace;
+import org.mmtk.policy.ExplicitFreeListLocal;
+import org.mmtk.policy.ExplicitFreeListSpace;
+import org.mmtk.vm.VM;
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.Address;
+import org.vmmagic.unboxed.ObjectReference;
+
+/**
+ * This class implements the collector context for a simple reference counting
+ * collector.
+ */
+ at Uninterruptible
+public class GenRCCollector extends RCBaseCollector {
+  private final GenRCFindRootSetTraceLocal rootTrace;
+  private final GenRCModifiedProcessor modProcessor;
+  private final ExplicitFreeListLocal rc;
+
+  public GenRCCollector() {
+    rc = new ExplicitFreeListLocal(GenRC.rcSpace);
+    rootTrace = new GenRCFindRootSetTraceLocal(global().rootTrace, newRootBuffer);
+    modProcessor = new GenRCModifiedProcessor(rootTrace);
+  }
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a per-collector collection phase.
+   *
+   * @param phaseId The collection phase to perform
+   * @param primary perform any single-threaded local activities.
+   */
+  public final void collectionPhase(short phaseId, boolean primary) {
+    if (phaseId == RCBase.PREPARE) {
+      super.collectionPhase(phaseId, primary);
+      rc.prepare();
+      return;
+    }
+
+    if (phaseId == RCBase.RELEASE) {
+      rc.release();
+      super.collectionPhase(phaseId, primary);
+      return;
+    }
+
+    super.collectionPhase(phaseId, primary);
+  }
+
+  /****************************************************************************
+   *
+   * Collection-time allocation
+   */
+
+  /**
+   * Allocate space for copying an object (this method <i>does not</i>
+   * copy the object, it only allocates space)
+   *
+   * @param original A reference to the original object
+   * @param bytes The size of the space to be allocated (in bytes)
+   * @param align The requested alignment
+   * @param offset The alignment offset
+   * @return The address of the first byte of the allocated region
+   */
+  @Inline
+  public final Address allocCopy(ObjectReference original, int bytes,
+      int align, int offset, int allocator) {
+    if (VM.VERIFY_ASSERTIONS) {
+      VM.assertions._assert(allocator == GenRC.ALLOC_RC);
+    }
+    return rc.alloc(bytes, align, offset);
+  }
+
+  /**
+   * Perform any post-copy actions.  In this case nothing is required.
+   *
+   * @param object The newly allocated object
+   * @param typeRef the type reference for the instance being created
+   * @param bytes The size of the space to be allocated (in bytes)
+   */
+  @Inline
+  public final void postCopy(ObjectReference object, ObjectReference typeRef,
+                             int bytes, int allocator) {
+    CopySpace.clearGCBits(object);
+    RCHeader.initializeHeader(object, false);
+    RCHeader.makeUnlogged(object);
+    ExplicitFreeListSpace.unsyncSetLiveBit(object);
+  }
+
+  /**
+   * Get the modified processor to use.
+   */
+  protected final TransitiveClosure getModifiedProcessor() {
+    return modProcessor;
+  }
+
+  /**
+   * Get the root trace to use.
+   */
+  protected final TraceLocal getRootTrace() {
+    return rootTrace;
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCConstraints.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCConstraints.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCConstraints.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCConstraints.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,32 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.refcount.generational;
+
+import static org.mmtk.policy.SegregatedFreeListSpace.MAX_FREELIST_OBJECT_BYTES;
+
+import org.mmtk.plan.refcount.RCBaseConstraints;
+import org.vmmagic.pragma.*;
+
+/**
+ * This class and its subclasses communicate to the host VM/Runtime
+ * any features of the selected plan that it needs to know.  This is
+ * separate from the main Plan/PlanLocal class in order to bypass any
+ * issues with ordering of static initialization.
+ */
+ at Uninterruptible
+public class GenRCConstraints extends RCBaseConstraints {
+  @Override
+  public boolean movesObjects() { return true; }
+  @Override
+  public int maxNonLOSCopyBytes() { return MAX_FREELIST_OBJECT_BYTES;}
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCFindRootSetTraceLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCFindRootSetTraceLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCFindRootSetTraceLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCFindRootSetTraceLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,123 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.refcount.generational;
+
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.plan.Trace;
+import org.mmtk.plan.refcount.RCHeader;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.deque.ObjectReferenceDeque;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements the thread-local core functionality for a transitive
+ * closure over the heap graph.
+ */
+ at Uninterruptible
+public final class GenRCFindRootSetTraceLocal extends TraceLocal {
+
+  private final ObjectReferenceDeque rootBuffer;
+
+  /**
+   * Constructor
+   */
+  public GenRCFindRootSetTraceLocal(Trace trace, ObjectReferenceDeque rootBuffer) {
+    super(trace);
+    this.rootBuffer = rootBuffer;
+  }
+
+  /****************************************************************************
+   *
+   * Externally visible Object processing and tracing
+   */
+
+  /**
+   * Is the specified object reachable?
+   *
+   * @param object The object.
+   * @return <code>true</code> if the object is reachable.
+   */
+  public boolean isLive(ObjectReference object) {
+    return GenRC.isRCObject(object) && RCHeader.isLiveRC(object) ||
+          (!Space.isInSpace(GenRC.NURSERY, object) && super.isLive(object));
+  }
+
+  /**
+   * When we trace a non-root object we do nothing.
+   *
+   * @param object The object to be traced.
+   * @return The new reference to the same object instance.
+   */
+  @Inline
+  public ObjectReference traceObject(ObjectReference object) {
+    return traceObject(object, false);
+  }
+
+  /**
+   * When we trace a root object we remember it.
+   *
+   * @param object The object to be traced.
+   * @return The new reference to the same object instance.
+   */
+  @Inline
+  public ObjectReference traceObject(ObjectReference object, boolean root) {
+    if (object.isNull()) return object;
+
+    if (Space.isInSpace(GenRC.NURSERY, object)) {
+      object = GenRC.nurserySpace.traceObject(this, object, GenRC.ALLOC_RC);
+    } else if (!GenRC.isRCObject(object)) {
+      return object;
+    }
+
+    if (root) {
+      rootBuffer.push(object);
+    } else {
+      RCHeader.incRC(object);
+    }
+
+    return object;
+  }
+
+  /**
+   * Ensure that the referenced object will not move from this point through
+   * to the end of the collection. This can involve forwarding the object
+   * if necessary.
+   *
+   * <i>Non-copying collectors do nothing, copying collectors must
+   * override this method in each of their trace classes.</i>
+   *
+   * @param object The object that must not move during the collection.
+   * @return True If the object will not move during collection
+   */
+  public boolean willNotMoveInCurrentCollection(ObjectReference object) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!object.isNull());
+    return !(Space.isInSpace(GenRC.NURSERY, object));
+  }
+
+  /**
+   * Ensure that this object will not move for the rest of the GC.
+   *
+   * @param object The object that must not move
+   * @return The new object, guaranteed stable for the rest of the GC.
+   */
+  public ObjectReference precopyObject(ObjectReference object) {
+    if (Space.isInSpace(GenRC.NURSERY, object)) {
+      return GenRC.nurserySpace.traceObject(this, object, GenRC.ALLOC_RC);
+    }
+    return object;
+  }
+
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCModifiedProcessor.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCModifiedProcessor.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCModifiedProcessor.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCModifiedProcessor.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,56 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.refcount.generational;
+
+import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.plan.refcount.RCHeader;
+import org.mmtk.policy.Space;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class is the fundamental mechanism for performing a
+ * transitive closure over an object graph.<p>
+ *
+ * @see org.mmtk.plan.TraceLocal
+ */
+ at Uninterruptible
+public final class GenRCModifiedProcessor extends TransitiveClosure {
+
+    private final GenRCFindRootSetTraceLocal trace;
+
+    public GenRCModifiedProcessor(GenRCFindRootSetTraceLocal trace) {
+      this.trace = trace;
+    }
+
+  /**
+   * Trace an edge during GC.
+   *
+   * @param source The source of the reference.
+   * @param slot The location containing the object reference.
+   */
+  @Inline
+  public void processEdge(ObjectReference source, Address slot) {
+    ObjectReference object = slot.loadObjectReference();
+    if (!object.isNull()) {
+      if (Space.isInSpace(GenRC.NURSERY, object)) {
+        object = GenRC.nurserySpace.traceObject(trace, object, GenRC.ALLOC_RC);
+        RCHeader.incRC(object);
+        slot.store(object);
+      } else if (GenRC.isRCObject(object)) {
+        RCHeader.incRC(object);
+      }
+    }
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCMutator.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCMutator.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCMutator.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/refcount/generational/GenRCMutator.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,113 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.refcount.generational;
+
+import org.mmtk.plan.refcount.RCBase;
+import org.mmtk.plan.refcount.RCBaseMutator;
+import org.mmtk.policy.CopyLocal;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.alloc.Allocator;
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.Address;
+import org.vmmagic.unboxed.ObjectReference;
+
+/**
+ * This class implements the mutator context for a simple reference counting collector.
+ */
+ at Uninterruptible
+public class GenRCMutator extends RCBaseMutator {
+  /************************************************************************
+   * Instance fields
+   */
+  private final CopyLocal nursery;
+
+  public GenRCMutator() {
+    nursery = new CopyLocal(GenRC.nurserySpace);
+  }
+
+  /****************************************************************************
+   *
+   * Mutator-time allocation
+   */
+
+  /**
+   * Allocate memory for an object.
+   *
+   * @param bytes The number of bytes required for the object.
+   * @param align Required alignment for the object.
+   * @param offset Offset associated with the alignment.
+   * @param allocator The allocator associated with this request.
+   * @param site Allocation site
+   * @return The address of the newly allocated memory.
+   */
+  @Inline
+  public Address alloc(int bytes, int align, int offset, int allocator, int site) {
+    if (allocator == GenRC.ALLOC_NURSERY) {
+      return nursery.alloc(bytes, align, offset);
+    }
+    return super.alloc(bytes, align, offset, allocator, site);
+  }
+
+  /**
+   * Perform post-allocation actions.  For many allocators none are
+   * required.
+   *
+   * @param ref The newly allocated object
+   * @param typeRef the type reference for the instance being created
+   * @param bytes The size of the space to be allocated (in bytes)
+   * @param allocator The allocator number to be used for this allocation
+   */
+  @Inline
+  public void postAlloc(ObjectReference ref, ObjectReference typeRef, int bytes, int allocator) {
+    if (allocator == GenRC.ALLOC_NURSERY) {
+      return;
+    }
+    super.postAlloc(ref, typeRef, bytes, allocator);
+  }
+
+  /**
+   * Return the allocator instance associated with a space
+   * <code>space</code>, for this plan instance.
+   *
+   * @param space The space for which the allocator instance is desired.
+   * @return The allocator instance associated with this plan instance
+   * which is allocating into <code>space</code>, or <code>null</code>
+   * if no appropriate allocator can be established.
+   */
+  public Allocator getAllocatorFromSpace(Space space) {
+    if (space == GenRC.nurserySpace) return nursery;
+
+    return super.getAllocatorFromSpace(space);
+  }
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a per-mutator collection phase.
+   *
+   * @param phaseId The collection phase to perform
+   * @param primary perform any single-threaded local activities.
+   */
+  public final void collectionPhase(short phaseId, boolean primary) {
+    if (phaseId == RCBase.PREPARE) {
+      nursery.rebind(GenRC.nurserySpace);
+      super.collectionPhase(phaseId, primary);
+      return;
+    }
+
+    super.collectionPhase(phaseId, primary);
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SS.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SS.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SS.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SS.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,206 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.semispace;
+
+import org.mmtk.policy.CopySpace;
+import org.mmtk.policy.Space;
+import org.mmtk.plan.*;
+import org.mmtk.utility.heap.VMRequest;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements a simple semi-space collector. See the Jones
+ * & Lins GC book, section 2.2 for an overview of the basic
+ * algorithm. This implementation also includes a large object space
+ * (LOS), and an uncollected "immortal" space.<p>
+ *
+ * All plans make a clear distinction between <i>global</i> and
+ * <i>thread-local</i> activities.  Global activities must be
+ * synchronized, whereas no synchronization is required for
+ * thread-local activities.  Instances of Plan map 1:1 to "kernel
+ * threads" (aka CPUs).  Thus instance
+ * methods allow fast, unsychronized access to Plan utilities such as
+ * allocation and collection.  Each instance rests on static resources
+ * (such as memory and virtual memory resources) which are "global"
+ * and therefore "static" members of Plan.  This mapping of threads to
+ * instances is crucial to understanding the correctness and
+ * performance proprties of this plan.
+ */
+ at Uninterruptible
+public class SS extends StopTheWorld {
+
+  /****************************************************************************
+   *
+   * Class variables
+   */
+
+  /** True if allocating into the "higher" semispace */
+  public static boolean hi = false; // True if allocing to "higher" semispace
+
+  /** One of the two semi spaces that alternate roles at each collection */
+  public static final CopySpace copySpace0 = new CopySpace("ss0", DEFAULT_POLL_FREQUENCY, false, VMRequest.create());
+  public static final int SS0 = copySpace0.getDescriptor();
+
+  /** One of the two semi spaces that alternate roles at each collection */
+  public static final CopySpace copySpace1 = new CopySpace("ss1", DEFAULT_POLL_FREQUENCY, true, VMRequest.create());
+  public static final int SS1 = copySpace1.getDescriptor();
+
+  public final Trace ssTrace;
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * Class variables
+   */
+  public static final int ALLOC_SS = Plan.ALLOC_DEFAULT;
+
+  public static final int SCAN_SS = 0;
+
+  /**
+   * Constructor
+   */
+  public SS() {
+    ssTrace = new Trace(metaDataSpace);
+  }
+
+  /**
+   * @return The to space for the current collection.
+   */
+  @Inline
+  public static CopySpace toSpace() {
+    return hi ? copySpace1 : copySpace0;
+  }
+
+  /**
+   * @return The from space for the current collection.
+   */
+  @Inline
+  public static CopySpace fromSpace() {
+    return hi ? copySpace0 : copySpace1;
+  }
+
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a (global) collection phase.
+   *
+   * @param phaseId Collection phase
+   */
+  @Inline
+  public void collectionPhase(short phaseId) {
+    if (phaseId == SS.PREPARE) {
+      hi = !hi; // flip the semi-spaces
+      // prepare each of the collected regions
+      copySpace0.prepare(hi);
+      copySpace1.prepare(!hi);
+      ssTrace.prepare();
+      super.collectionPhase(phaseId);
+      return;
+    }
+    if (phaseId == CLOSURE) {
+      ssTrace.prepare();
+      return;
+    }
+    if (phaseId == SS.RELEASE) {
+      // release the collected region
+      fromSpace().release();
+
+      super.collectionPhase(phaseId);
+      return;
+    }
+
+    super.collectionPhase(phaseId);
+  }
+
+  /****************************************************************************
+   *
+   * Accounting
+   */
+
+  /**
+   * Return the number of pages reserved for copying.
+   *
+   * @return The number of pages reserved given the pending
+   * allocation, including space reserved for copying.
+   */
+  public final int getCollectionReserve() {
+    // we must account for the number of pages required for copying,
+    // which equals the number of semi-space pages reserved
+    return toSpace().reservedPages() + super.getCollectionReserve();
+  }
+
+  /**
+   * Return the number of pages reserved for use given the pending
+   * allocation.  This is <i>exclusive of</i> space reserved for
+   * copying.
+   *
+   * @return The number of pages reserved given the pending
+   * allocation, excluding space reserved for copying.
+   */
+  public int getPagesUsed() {
+    return super.getPagesUsed() + toSpace().reservedPages();
+  }
+
+  /**
+   * Return the number of pages available for allocation, <i>assuming
+   * all future allocation is to the semi-space</i>.
+   *
+   * @return The number of pages available for allocation, <i>assuming
+   * all future allocation is to the semi-space</i>.
+   */
+  public final int getPagesAvail() {
+    return(super.getPagesAvail()) >> 1;
+  }
+
+  /**
+   * Calculate the number of pages a collection is required to free to satisfy
+   * outstanding allocation requests.
+   *
+   * @return the number of pages a collection is required to free to satisfy
+   * outstanding allocation requests.
+   */
+  public int getPagesRequired() {
+    return super.getPagesRequired() + (toSpace().requiredPages() << 1);
+  }
+
+  /**
+   * @see org.mmtk.plan.Plan#willNeverMove
+   *
+   * @param object Object in question
+   * @return True if the object will never move
+   */
+  @Override
+  public boolean willNeverMove(ObjectReference object) {
+    if (Space.isInSpace(SS0, object) || Space.isInSpace(SS1, object))
+      return false;
+    return super.willNeverMove(object);
+  }
+
+  /**
+   * Register specialized methods.
+   */
+  @Interruptible
+  protected void registerSpecializedMethods() {
+    TransitiveClosure.registerSpecializedScan(SCAN_SS, SSTraceLocal.class);
+    super.registerSpecializedMethods();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSCollector.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSCollector.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSCollector.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSCollector.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,188 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.semispace;
+
+import org.mmtk.plan.*;
+import org.mmtk.policy.CopySpace;
+import org.mmtk.policy.CopyLocal;
+import org.mmtk.policy.LargeObjectLocal;
+import org.mmtk.policy.Space;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements <i>per-collector thread</i> behavior
+ * and state for the <i>SS</i> plan, which implements a full-heap
+ * semi-space collector.<p>
+ *
+ * Specifically, this class defines <i>SS</i> collection behavior
+ * (through <code>trace</code> and the <code>collectionPhase</code>
+ * method), and collection-time allocation (copying of objects).<p>
+ *
+ * See {@link SS} for an overview of the semi-space algorithm.<p>
+ *
+ * @see SS
+ * @see SSMutator
+ * @see StopTheWorldCollector
+ * @see CollectorContext
+ */
+ at Uninterruptible
+public class SSCollector extends StopTheWorldCollector {
+
+  /****************************************************************************
+   * Instance fields
+   */
+
+  protected final SSTraceLocal trace;
+  protected final CopyLocal ss;
+  protected final LargeObjectLocal los;
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * Constructor
+   */
+  public SSCollector() {
+    this(new SSTraceLocal(global().ssTrace));
+  }
+
+  /**
+   * Constructor
+   * @param tr The trace to use
+   */
+  protected SSCollector(SSTraceLocal tr) {
+    ss = new CopyLocal();
+    los = new LargeObjectLocal(Plan.loSpace);
+    trace = tr;
+  }
+
+  /****************************************************************************
+   *
+   * Collection-time allocation
+   */
+
+  /**
+   * Allocate space for copying an object (this method <i>does not</i>
+   * copy the object, it only allocates space)
+   *
+   * @param original A reference to the original object
+   * @param bytes The size of the space to be allocated (in bytes)
+   * @param align The requested alignment.
+   * @param offset The alignment offset.
+   * @return The address of the first byte of the allocated region
+   */
+  @Inline
+  public Address allocCopy(ObjectReference original, int bytes,
+      int align, int offset, int allocator) {
+    if (allocator == Plan.ALLOC_LOS) {
+      if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(bytes > Plan.MAX_NON_LOS_COPY_BYTES);
+      return los.alloc(bytes, align, offset);
+    } else {
+      if (VM.VERIFY_ASSERTIONS) {
+        VM.assertions._assert(bytes <= Plan.MAX_NON_LOS_COPY_BYTES);
+        VM.assertions._assert(allocator == SS.ALLOC_SS);
+      }
+      return ss.alloc(bytes, align, offset);
+    }
+  }
+
+  /**
+   * Perform any post-copy actions.
+   *
+   * @param object The newly allocated object
+   * @param typeRef the type reference for the instance being created
+   * @param bytes The size of the space to be allocated (in bytes)
+   */
+  @Inline
+  public void postCopy(ObjectReference object, ObjectReference typeRef,
+      int bytes, int allocator) {
+    CopySpace.clearGCBits(object);
+    if (allocator == Plan.ALLOC_LOS)
+      Plan.loSpace.initializeHeader(object, false);
+  }
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a per-collector collection phase.
+   *
+   * @param phaseId The collection phase to perform
+   * @param primary Perform any single-threaded activities using this thread.
+   */
+  @Inline
+  public void collectionPhase(short phaseId, boolean primary) {
+    if (phaseId == SS.PREPARE) {
+      // rebind the copy bump pointer to the appropriate semispace.
+      ss.rebind(SS.toSpace());
+      los.prepare(true);
+      super.collectionPhase(phaseId, primary);
+      return;
+    }
+
+    if (phaseId == SS.CLOSURE) {
+      trace.completeTrace();
+      return;
+    }
+
+    if (phaseId == SS.RELEASE) {
+      trace.release();
+      los.release(true);
+      super.collectionPhase(phaseId, primary);
+      return;
+    }
+
+    super.collectionPhase(phaseId, primary);
+  }
+
+
+  /****************************************************************************
+   *
+   * Object processing and tracing
+   */
+
+  /**
+   * Return true if the given reference is to an object that is within
+   * one of the semi-spaces.
+   *
+   * @param object The object in question
+   * @return True if the given reference is to an object that is within
+   * one of the semi-spaces.
+   */
+  public static boolean isSemiSpaceObject(ObjectReference object) {
+    return Space.isInSpace(SS.SS0, object) || Space.isInSpace(SS.SS1, object);
+  }
+
+  /****************************************************************************
+   *
+   * Miscellaneous
+   */
+
+  /** @return The active global plan as an <code>SS</code> instance. */
+  @Inline
+  private static SS global() {
+    return (SS) VM.activePlan.global();
+  }
+
+  /** @return the current trace object. */
+  public TraceLocal getCurrentTrace() {
+    return trace;
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSConstraints.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSConstraints.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSConstraints.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSConstraints.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,32 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.semispace;
+
+import org.mmtk.plan.*;
+import org.mmtk.policy.CopySpace;
+import org.vmmagic.pragma.*;
+
+/**
+ * SemiSpace common constants.
+ */
+ at Uninterruptible
+public class SSConstraints extends StopTheWorldConstraints {
+  @Override
+  public boolean movesObjects() { return true; }
+  @Override
+  public int gcHeaderBits() { return CopySpace.LOCAL_GC_BITS_REQUIRED; }
+  @Override
+  public int gcHeaderWords() { return CopySpace.GC_HEADER_WORDS_REQUIRED; }
+  @Override
+  public int numSpecializedScans() { return 1; }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSMutator.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSMutator.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSMutator.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSMutator.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,163 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.semispace;
+
+import org.mmtk.plan.*;
+import org.mmtk.policy.CopyLocal;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.alloc.Allocator;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements <i>per-mutator thread</i> behavior
+ * and state for the <i>SS</i> plan, which implements a full-heap
+ * semi-space collector.<p>
+ *
+ * Specifically, this class defines <i>SS</i> mutator-time allocation
+ * and per-mutator thread collection semantics (flushing and restoring
+ * per-mutator allocator state).<p>
+ *
+ * See {@link SS} for an overview of the semi-space algorithm.<p>
+ *
+ * @see SS
+ * @see SSCollector
+ * @see StopTheWorldMutator
+ * @see MutatorContext
+ */
+ at Uninterruptible
+public class SSMutator extends StopTheWorldMutator {
+  /****************************************************************************
+   * Instance fields
+   */
+  protected final CopyLocal ss;
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * Constructor
+   */
+  public SSMutator() {
+    ss = new CopyLocal();
+  }
+
+  /**
+   * Called before the MutatorContext is used, but after the context has been
+   * fully registered and is visible to collection.
+   */
+  public void initMutator(int id) {
+    super.initMutator(id);
+    ss.rebind(SS.toSpace());
+  }
+
+  /****************************************************************************
+   *
+   * Mutator-time allocation
+   */
+
+  /**
+   * Allocate space (for an object)
+   *
+   * @param bytes The size of the space to be allocated (in bytes)
+   * @param align The requested alignment.
+   * @param offset The alignment offset.
+   * @param allocator The allocator number to be used for this allocation
+   * @param site Allocation site
+   * @return The address of the first byte of the allocated region
+   */
+  @Inline
+  public Address alloc(int bytes, int align, int offset, int allocator, int site) {
+    if (allocator == SS.ALLOC_SS)
+      return ss.alloc(bytes, align, offset);
+    else
+      return super.alloc(bytes, align, offset, allocator, site);
+  }
+
+  /**
+   * Perform post-allocation actions.  For many allocators none are
+   * required.
+   *
+   * @param object The newly allocated object
+   * @param typeRef The type reference for the instance being created
+   * @param bytes The size of the space to be allocated (in bytes)
+   * @param allocator The allocator number to be used for this allocation
+   */
+  @Inline
+  public void postAlloc(ObjectReference object, ObjectReference typeRef,
+      int bytes, int allocator) {
+    if (allocator == SS.ALLOC_SS) return;
+    super.postAlloc(object, typeRef, bytes, allocator);
+  }
+
+  /**
+   * Return the allocator instance associated with a space
+   * <code>space</code>, for this plan instance.
+   *
+   * @param space The space for which the allocator instance is desired.
+   * @return The allocator instance associated with this plan instance
+   * which is allocating into <code>space</code>, or <code>null</code>
+   * if no appropriate allocator can be established.
+   */
+  public Allocator getAllocatorFromSpace(Space space) {
+    if (space == SS.copySpace0 || space == SS.copySpace1) return ss;
+    return super.getAllocatorFromSpace(space);
+  }
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a per-mutator collection phase.
+   *
+   * @param phaseId The collection phase to perform
+   * @param primary Perform any single-threaded activities using this thread.
+   */
+  @Inline
+  public void collectionPhase(short phaseId, boolean primary) {
+    if (phaseId == SS.PREPARE) {
+      super.collectionPhase(phaseId, primary);
+      return;
+    }
+
+    if (phaseId == SS.RELEASE) {
+      super.collectionPhase(phaseId, primary);
+      // rebind the allocation bump pointer to the appropriate semispace.
+      ss.rebind(SS.toSpace());
+      return;
+    }
+
+    super.collectionPhase(phaseId, primary);
+  }
+
+
+  /****************************************************************************
+   *
+   * Miscellaneous
+   */
+
+  /**
+   * Show the status of each of the allocators.
+   */
+  public final void show() {
+    ss.show();
+    los.show();
+    immortal.show();
+  }
+
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSTraceLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSTraceLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSTraceLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/SSTraceLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,110 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.semispace;
+
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.plan.Trace;
+import org.mmtk.policy.Space;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implments the core functionality for a transitive
+ * closure over the heap graph.
+ */
+ at Uninterruptible
+public class SSTraceLocal extends TraceLocal {
+  /**
+   * Constructor
+   */
+  public SSTraceLocal(Trace trace, boolean specialized) {
+    super(specialized ? SS.SCAN_SS : -1, trace);
+  }
+
+  /**
+   * Constructor
+   */
+  public SSTraceLocal(Trace trace) {
+    this(trace, true);
+  }
+
+  /****************************************************************************
+   *
+   * Externally visible Object processing and tracing
+   */
+
+  /**
+   * Return true if <code>obj</code> is a live object.
+   *
+   * @param object The object in question
+   * @return True if <code>obj</code> is a live object.
+   */
+  public boolean isLive(ObjectReference object) {
+    if (object.isNull()) return false;
+    if (Space.isInSpace(SS.SS0, object))
+      return SS.hi ? SS.copySpace0.isLive(object) : true;
+    if (Space.isInSpace(SS.SS1, object))
+      return SS.hi ? true : SS.copySpace1.isLive(object);
+    return super.isLive(object);
+  }
+
+
+  /**
+   * This method is the core method during the trace of the object graph.
+   * The role of this method is to:
+   *
+   * 1. Ensure the traced object is not collected.
+   * 2. If this is the first visit to the object enqueue it to be scanned.
+   * 3. Return the forwarded reference to the object.
+   *
+   * @param object The object to be traced.
+   * @return The new reference to the same object instance.
+   */
+  @Inline
+  public ObjectReference traceObject(ObjectReference object) {
+    if (object.isNull()) return object;
+    if (Space.isInSpace(SS.SS0, object))
+      return SS.copySpace0.traceObject(this, object, SS.ALLOC_SS);
+    if (Space.isInSpace(SS.SS1, object))
+      return SS.copySpace1.traceObject(this, object, SS.ALLOC_SS);
+    return super.traceObject(object);
+  }
+
+  /**
+   * Ensure that this object will not move for the rest of the GC.
+   *
+   * @param object The object that must not move
+   * @return The new object, guaranteed stable for the rest of the GC.
+   */
+  @Inline
+  public ObjectReference precopyObject(ObjectReference object) {
+    if (object.isNull()) return object;
+    if (Space.isInSpace(SS.SS0, object))
+      return SS.copySpace0.traceObject(this, object, SS.ALLOC_SS);
+    if (Space.isInSpace(SS.SS1, object))
+      return SS.copySpace1.traceObject(this, object, SS.ALLOC_SS);
+    return object;
+  }
+
+  /**
+   * Will this object move from this point on, during the current trace ?
+   *
+   * @param object The object to query.
+   * @return True if the object will not move.
+   */
+  public boolean willNotMoveInCurrentCollection(ObjectReference object) {
+    return (SS.hi && !Space.isInSpace(SS.SS0, object)) ||
+           (!SS.hi && !Space.isInSpace(SS.SS1, object));
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspy.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspy.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspy.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspy.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,353 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.semispace.gcspy;
+
+import org.mmtk.plan.GCspyPlan;
+import org.mmtk.plan.Phase;
+import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.plan.semispace.SS;
+import org.mmtk.policy.CopySpace;
+import org.mmtk.policy.LargeObjectSpace;
+import org.mmtk.utility.gcspy.drivers.AbstractDriver;
+import org.mmtk.utility.gcspy.drivers.LinearSpaceDriver;
+import org.mmtk.utility.gcspy.drivers.ImmortalSpaceDriver;
+import org.mmtk.utility.gcspy.drivers.TreadmillDriver;
+import org.mmtk.utility.gcspy.GCspy;
+import org.mmtk.utility.Log;
+import org.mmtk.utility.options.Options;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class extends a simple semi-space collector to instrument it for
+ * GCspy. <p>
+ *
+ * See the Jones & Lins GC book, section 2.2 for an overview of the basic
+ * algorithm. This implementation also includes a large object space
+ * (LOS), and an uncollected "immortal" space.<p>
+ *
+ * All plans make a clear distinction between <i>global</i> and
+ * <i>thread-local</i> activities.  Global activities must be
+ * synchronized, whereas no synchronization is required for
+ * thread-local activities.  Instances of Plan map 1:1 to "kernel
+ * threads" (aka CPUs).  Thus instance
+ * methods allow fast, unsychronized access to Plan utilities such as
+ * allocation and collection.  Each instance rests on static resources
+ * (such as memory and virtual memory resources) which are "global"
+ * and therefore "static" members of Plan.  This mapping of threads to
+ * instances is crucial to understanding the correctness and
+ * performance proprties of this plan.
+ *
+ * FIXME This seems to have changed
+ * The order of phases and GCspy actions is important here. It is:
+ *   PREPARE phase
+ *      SSGCspyMutator.gcspyGatherData(SSGCspy.BEFORE_COLLECTION); // safepoint
+ *      SSMutator.PREPARE // FIXME DOES NOT ss.rebind(SS.toSpace());
+ *
+ *   PREPARE phase
+ *      SS.PREPARE // flip semispaces
+ *      gcspySpace.prepare();
+ *      SSGCspyCollector.gcspyGatherData(SSGCspy.BEFORE_COLLECTION);
+ *      SSCollector.PREPARE // ss.rebind(SS.toSpace());
+ *
+ *
+ *   FORWARD_FINALIZABLE phase
+ *      SSCollector.FORWARD_FINALIZABLE
+ *      SSGCspyCollector.gcspyGatherData(SSGCspy.SEMISPACE_COPIED);
+ *
+ *   RELEASE phase
+ *      SSGCspyMutator.gcspyGatherData(SSGCspy.SEMISPACE_COPIED); // safepoint
+ *      SSMutator.RELEASE // FIXME ss.rebind(SS.toSpace());
+ *      SSGCspyMutator.gcspyGatherData(SSGCspy.AFTER_COLLECTION);
+ *
+ *   RELEASE phase
+ *      SSCollector.RELEASE
+ *      SSGCspyCollector.gcspyGatherData(SSGCspy.AFTER_COLLECTION);
+ *      SS.RELEASE
+ *      gcspySpace.release();
+ *      SSGCspy.gcspyGatherData(); // safepoint
+ *
+ * Note that SSMutator has changed the point at which it rebinds toSpace
+ * from PREPARE (2.4.6) to after RELEASE (3.x.x).
+ *
+ --Phase Collector.initiate
+ --Phase Mutator.initiate-mutator
+ --Phase Mutator.prepare-mutator
+     SSGCspyMutator.gcspyGatherData, event=0
+ --Phase Plan.prepare
+ --Phase Collector.prepare
+     SSGCspyCollector.gcspyGatherData, event=0
+ --Phase Collector.precopy
+ --Phase Collector.bootimage-root
+ --Phase Collector.root
+ --Phase Plan.root
+ --Phase Collector.start-closure
+ --Phase Collector.soft-ref
+ --Phase Collector.complete-closure
+ --Phase Collector.weak-ref
+ --Phase Collector.finalize
+ --Phase Collector.complete-closure
+ --Phase Collector.phantom-ref
+ --Phase Collector.forward-ref
+ --Phase Collector.forward-finalize
+     SSGCspyCollector.gcspyGatherData, event=1
+ --Phase Mutator.release-mutator
+     SSGCspyMutator.gcspyGatherData, event=1
+     SSGCspyMutator.gcspyGatherData, event=2
+ --Phase Collector.release
+     SSGCspyCollector.gcspyGatherData, event=2
+ --Phase Plan.release
+     SSGCspy.gcspyGatherData, event=2
+ --Phase Collector.complete
+ --Phase Plan.complete
+ */
+ at Uninterruptible public class SSGCspy extends SS implements GCspyPlan {
+
+  /****************************************************************************
+   *
+   * Class variables
+   */
+
+  // The events, BEFORE_COLLECTION, SEMISPACE_COPIED or AFTER_COLLECTION
+
+  /**
+   * Before a collection has started,
+   * i.e. before SS.collectionPhase(SS.PREPARE,..).
+   */
+  static final int BEFORE_COLLECTION = 0;
+
+  /**
+   * After the semispace has been copied and the large object space has been traced
+   * At this time the Large Object Space has not been swept.
+   */
+  static final int SEMISPACE_COPIED  = BEFORE_COLLECTION + 1;
+
+  /**
+   * The collection is complete,
+   * i.e. immediately after SS.collectionPhase(SS.RELEASE,..).
+   * The Large Object Space has been swept.
+   */
+  static final int AFTER_COLLECTION  = SEMISPACE_COPIED + 1;
+
+  static int gcspyEvent_ = BEFORE_COLLECTION;
+
+  // The specific drivers for this collector
+  static LinearSpaceDriver ss0Driver;
+  static LinearSpaceDriver ss1Driver;
+  static ImmortalSpaceDriver immortalDriver;
+  static TreadmillDriver losNurseryDriver;
+  static TreadmillDriver losDriver;
+  static TreadmillDriver plosNurseryDriver;
+  static TreadmillDriver plosDriver;
+
+  private static final boolean DEBUG = false;
+
+
+  static {
+    GCspy.createOptions();
+  }
+
+  /**
+   * Start the server and wait if necessary.
+   * This method has the following responsibilities.
+   * <ol>
+   * <li> Create and initialise the GCspy server by calling.
+   *      <pre>server = ServerInterpreter.init(name, portNumber, verbose);</pre>
+   * <li> Add each event to the ServerInterpreter
+   *      <pre>server.addEvent(eventID, eventName);</pre>
+   * <li> Set some general information about the server (e.g. name of the collector, build, etc).
+   *      <pre>server.setGeneralInfo(info); </pre>
+   * <li> Create new drivers for each component to be visualised.
+   *      <pre>myDriver = new MyDriver(server, args...);</pre>
+   *      Drivers extend AbstractDriver and register their spce with the
+   *      ServerInterpreter. In addition to the server, drivers will take as
+   *      arguments the name of the space, the MMTk space, the tilesize, and
+   *      whether this space is to be the main space in the visualiser.
+   * </ol>
+   *
+   * WARNING: allocates memory.
+   * @param wait Whether to wait
+   * @param port The port to talk to the GCspy client (e.g. visualiser)
+   */
+  @Interruptible
+  public final void startGCspyServer(int port, boolean wait) {
+    GCspy.server.init("SemiSpaceServerInterpreter", port, true/*verbose*/);
+    if (DEBUG) Log.writeln("SSGCspy: ServerInterpreter initialised");
+
+    GCspy.server.addEvent(BEFORE_COLLECTION, "Before collection");
+    GCspy.server.addEvent(SEMISPACE_COPIED, "Semispace copied; LOS traced");
+    GCspy.server.addEvent(AFTER_COLLECTION, "After collection; LOS swept");
+    GCspy.server.setGeneralInfo(
+        "SSGCspy\n\nRichard Jones, October 2006\\http://www.cs.kent.ac.uk/~rej/");
+    if (DEBUG) Log.writeln("SSGCspy: events added to ServerInterpreter");
+
+    // Initialise each driver
+    ss0Driver      = newLinearSpaceDriver("Semispace 0 Space", copySpace0, true);
+    ss1Driver      = newLinearSpaceDriver("Semispace 1 Space", copySpace1, false);
+    immortalDriver = new ImmortalSpaceDriver(
+                         GCspy.server,  "Immortal Space", immortalSpace,
+                         Options.gcspyTileSize.getValue(), false);
+    losNurseryDriver  = newTreadmillDriver("LOS Nursery", loSpace);
+    losDriver         = newTreadmillDriver("LOS", loSpace);
+
+    if (DEBUG) Log.write("SemiServerInterpreter initialised\n");
+
+    // Register drivers to allow immortal space to notify direct references
+    immortalDriver.registerDriversForReferenceNotification(
+      new AbstractDriver[] {ss0Driver, ss1Driver, immortalDriver,
+                            losNurseryDriver, losDriver,
+                            plosNurseryDriver, plosDriver});
+    if (DEBUG) Log.writeln("SSGCspy: registered drivers");
+
+    gcspyEvent_ = BEFORE_COLLECTION;
+
+    // Start the server
+    GCspy.server.startServer(wait);
+  }
+
+  /**
+   * Create a new LinearSpaceDriver
+   * TODO is this the best name or should we call it LargeObjectSpaceDriver?
+   * @param name Name of the space
+   * @param space The space
+   * @return A new GCspy driver for this space
+   */
+  @Interruptible
+  private LinearSpaceDriver newLinearSpaceDriver(String name, CopySpace space, boolean mainSpace) {
+    // TODO What if tileSize is too small (i.e. too many tiles for GCspy buffer)
+    // TODO stop the GCspy spaces in the visualiser from fluctuating in size
+    // so much as we resize them.
+    return new LinearSpaceDriver(GCspy.server, name, space,
+            Options.gcspyTileSize.getValue(), mainSpace);
+  }
+
+  /**
+   * Create a new TreadmillDriver
+   * TODO is this the best name or should we call it LargeObjectSpaceDriver?
+   * @param name Name of the space
+   * @param space The space
+   * @return A new GCspy driver for this space
+   */
+  @Interruptible
+  private TreadmillDriver newTreadmillDriver(String name, LargeObjectSpace space) {
+    return new TreadmillDriver(GCspy.server, name, space,
+            Options.gcspyTileSize.getValue(), MAX_NON_LOS_COPY_BYTES, false);
+  }
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a (global) collection phase.
+   *
+   * @param phaseId Collection phase
+   */
+  @Inline
+  public void collectionPhase(short phaseId) {
+    if (DEBUG) { Log.write("--Phase Plan."); Log.writeln(Phase.getName(phaseId)); }
+
+    if (phaseId == SSGCspy.PREPARE) {
+      super.collectionPhase(phaseId);
+      gcspySpace.prepare();
+      return;
+    }
+
+    if (phaseId == SSGCspy.RELEASE) {
+      super.collectionPhase(phaseId);
+      gcspySpace.release();
+      //if (primary)
+       gcspyGatherData(SSGCspy.AFTER_COLLECTION);
+      return;
+    }
+
+    super.collectionPhase(phaseId);
+  }
+
+  /**
+   * Gather data for GCspy for the semispaces, the immortal space and the large
+   * object space.
+   * <p>
+   * This method sweeps the semispace under consideration to gather data.
+   * Alternatively and more efficiently, 'used space' can obviously be
+   * discovered in constant time simply by comparing the start and the end
+   * addresses of the semispace. However, per-object information can only be
+   * gathered by sweeping through the space and we do this here for tutorial
+   * purposes.
+   *
+   * @param event
+   *          The event, either BEFORE_COLLECTION, SEMISPACE_COPIED or
+   *          AFTER_COLLECTION
+   */
+  private void gcspyGatherData(int event) {
+    if(DEBUG) {
+      Log.writeln("SSGCspy.gcspyGatherData, event=", event);
+      Log.writeln("SSGCspy.gcspyGatherData, port=", GCspy.getGCspyPort());
+    }
+
+    // If port = 0 there can be no GCspy client connected
+    if (GCspy.getGCspyPort() == 0)
+      return;
+
+    // This is a safepoint for the server, i.e. it is a point at which
+    // the server can pause.
+    // The Mutator is called after the Collector so the Mutator must set the safepoint
+    if(DEBUG) Log.writeln("SSGCspy safepoint");
+    GCspy.server.serverSafepoint(event);
+  }
+
+  /****************************************************************************
+   *
+   * Accounting
+   */
+
+  /**
+   * Return the number of pages reserved for use given the pending
+   * allocation.  This is <i>exclusive of</i> space reserved for
+   * copying.
+   *
+   * @return The number of pages reserved given the pending
+   * allocation, excluding space reserved for copying.
+   */
+  public final int getPagesUsed() {
+    return super.getPagesUsed() + gcspySpace.reservedPages();
+  }
+
+
+  /**
+   * Report information on the semispaces
+   */
+  static void reportSpaces() {
+    Log.write("\n  Low semispace:  ");
+    Log.write(SSGCspy.copySpace0.getStart());
+    Log.write(" - ");
+    Log.write(SSGCspy.copySpace0.getStart()
+        .plus(SSGCspy.copySpace0.getExtent()));
+    Log.write("\n  High semispace: ");
+    Log.write(SSGCspy.copySpace1.getStart());
+    Log.write(" - ");
+    Log.write(SSGCspy.copySpace1.getStart()
+        .plus(SSGCspy.copySpace1.getExtent()));
+    Log.flush();
+  }
+
+  /**
+   * Register specialized methods.
+   */
+  @Interruptible
+  protected void registerSpecializedMethods() {
+    super.registerSpecializedMethods();
+    TransitiveClosure.registerSpecializedScan(SCAN_SS, SSGCspyTraceLocal.class);
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyCollector.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyCollector.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyCollector.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyCollector.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,265 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.semispace.gcspy;
+
+import org.mmtk.plan.Phase;
+import org.mmtk.plan.semispace.SS;
+import org.mmtk.plan.semispace.SSCollector;
+import org.mmtk.policy.CopySpace;
+import org.mmtk.utility.Log;
+import org.mmtk.utility.gcspy.GCspy;
+import org.mmtk.utility.gcspy.drivers.LinearSpaceDriver;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements <i>per-collector thread</i> behavior and state for the
+ * <i>SSGCspy</i> plan.<p>
+ *
+ * See {@link SSGCspy} for an overview of the GC-spy mechanisms.<p>
+ *
+ * @see SSCollector
+ * @see SSGCspy
+ * @see SSGCspyMutator
+ * @see org.mmtk.plan.StopTheWorldCollector
+ * @see org.mmtk.plan.CollectorContext
+ * @see org.mmtk.plan.SimplePhase
+ */
+ at Uninterruptible public class SSGCspyCollector extends SSCollector {
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /*****************************************************************************
+   * Instance fields
+   */
+
+  private static final boolean DEBUG = false;
+
+  /**
+   * Constructor
+   */
+  public SSGCspyCollector() {
+    super(new SSGCspyTraceLocal(global().ssTrace));
+  }
+
+
+  /****************************************************************************
+   *
+   * Data gathering
+   */
+
+  /**
+   * Perform a (local) collection phase.
+   * Before a collection, we need to discover
+   * <ul>
+   * <li>the tospace objects copied by the collector in the last GC cycle
+   * <li>the semispace objects allocated since by the mutator.
+   * <li>all immortal objects allocated by the mutator
+   * <li>all large objects allocated by the mutator
+   * </ul>
+   * After the semispace has been copied, we need to discover
+   * <ul>
+   * <li>the tospace objects copied by the collector
+   * <li>all immortal objects allocated by the mutator
+   * <li>all large objects allocated by the mutator
+   * </ul>
+   */
+  @Inline
+  public final void collectionPhase(short phaseId, boolean primary) {
+    if (DEBUG) { Log.write("--Phase Collector."); Log.writeln(Phase.getName(phaseId)); }
+
+    //TODO do we need to worry any longer about primary??
+    if (phaseId == SS.PREPARE) {
+      //if (primary)
+        gcspyGatherData(SSGCspy.BEFORE_COLLECTION);
+      super.collectionPhase(phaseId, primary);
+      return;
+    }
+
+    if (phaseId == SS.FORWARD_FINALIZABLE) {
+      super.collectionPhase(phaseId, primary);
+      //if (primary)
+        gcspyGatherData(SSGCspy.SEMISPACE_COPIED);
+      return;
+    }
+
+    if (phaseId == SS.RELEASE) {
+      //if (primary)
+        //gcspyGatherData(SSGCspy.SEMISPACE_COPIED);
+      super.collectionPhase(phaseId, primary);
+      //if (primary)
+        gcspyGatherData(SSGCspy.AFTER_COLLECTION);
+      return;
+    }
+
+    super.collectionPhase(phaseId, primary);
+  }
+
+  /**
+   * Gather data for GCspy for the semispaces only.
+   * <p>
+   * This method sweeps the semispace under consideration to gather data.
+   * Alternatively and more efficiently, 'used space' can obviously be
+   * discovered in constant time simply by comparing the start and the end
+   * addresses of the semispace. However, per-object information can only be
+   * gathered by sweeping through the space and we do this here for tutorial
+   * purposes.
+   *
+   * @param event
+   *          The event, either BEFORE_COLLECTION, SEMISPACE_COPIED or
+   *          AFTER_COLLECTION
+   */
+  private void gcspyGatherData(int event) {
+    if(DEBUG) {
+      Log.writeln("SSGCspyCollector.gcspyGatherData, event=", event);
+      Log.writeln("SSGCspyCollector.gcspyGatherData, port=", GCspy.getGCspyPort());
+    }
+
+    // If port = 0 there can be no GCspy client connected
+    if (GCspy.getGCspyPort() == 0)
+      return;
+
+    // If the server is connected to a client that is interested in this
+    // event, then we gather data. But first we start a timer to
+    // compensate for the time spent gathering data here.
+    if (GCspy.server.isConnected(event)) {
+
+      if (DEBUG) {
+        if (SSGCspy.hi)
+          Log.write("\nCollector Examining Lowspace (event ", event);
+        else
+          Log.write("\nCollector Examining Highspace (event ", event);
+        Log.write(")");
+        SSGCspy.reportSpaces(); Log.writeln();
+      }
+
+      if (event == SSGCspy.BEFORE_COLLECTION) {
+        if (DEBUG) debugSpaces(SSGCspy.fromSpace());
+
+        // Just send the old values again
+        if (DEBUG) {
+          Log.write("SSGCspyCollector.gcspyGatherData transmit driver, ");
+          Log.writeln(SSGCspy.fromSpace().getName());
+        }
+
+        fromSpaceDriver().transmit(event);
+        // Mutator.gcspyGatherData follows so leave safepoint to there.
+      } else if (event == SSGCspy.SEMISPACE_COPIED) {
+        if (DEBUG) debugSpaces(SSGCspy.toSpace());
+
+        // We need to reset, scan and send values for tospace
+        // We'll leave resetting fromspace to AFTER_COLLECTION
+        if (DEBUG) {
+          Log.write("SSGCspyCollector.gcspyGatherData reset, gather and transmit driver ");
+          Log.writeln(SSGCspy.toSpace().getName());
+        }
+
+        GCspy.server.startCompensationTimer();
+        toSpaceDriver().resetData();
+        ss.gcspyGatherData(toSpaceDriver(), SSGCspy.toSpace());
+        GCspy.server.stopCompensationTimer();
+        toSpaceDriver().transmit(event);
+
+        // We'll leave the safepoint to RELEASE
+      } else if (event == SSGCspy.AFTER_COLLECTION) {
+        if (DEBUG) {
+          Log.write("SSGCspyCollector.gcspyGatherData transmit toSpaceDriver, ");
+          Log.writeln(SSGCspy.toSpace().getName());
+          Log.write("SSGCspyCollector.gcspyGatherData reset fromSpaceDriver, ");
+          Log.writeln(SSGCspy.fromSpace().getName());
+        }
+
+        toSpaceDriver().transmit(event);
+
+        // Here we reset fromspace data
+        fromSpaceDriver().resetData();
+        Address start = SSGCspy.fromSpace().getStart();
+        fromSpaceDriver().setRange(start, start);
+        fromSpaceDriver().transmit(event);
+      }
+
+    }
+    // else Log.write("not transmitting...");
+  }
+
+  /**
+   * Print some debugging info
+   * @param scannedSpace
+   */
+  private void debugSpaces(CopySpace scannedSpace) {
+    Log.write("SSGCspyCollector.gcspyGatherData: gather data for active semispace ");
+    Log.write(scannedSpace.getStart()); Log.write("-",ss.getCursor()); Log.flush();
+    Log.write(". The space is: "); Log.writeln(ss.getSpace().getName());
+    Log.write("scannedSpace is "); Log.writeln(scannedSpace.getName());
+    Log.write("The range is "); Log.write(ss.getSpace().getStart());
+    Log.write(" to "); Log.writeln(ss.getCursor());
+    SSGCspy.reportSpaces();
+  }
+
+  /**
+   * Reset all root streams.<p>
+   */
+  void resetRootStreams() {
+    SSGCspy.ss0Driver.resetRootsStream();
+    SSGCspy.ss1Driver.resetRootsStream();
+    SSGCspy.immortalDriver.resetRootsStream();
+    SSGCspy.losNurseryDriver.resetRootsStream();
+    SSGCspy.losDriver.resetRootsStream();
+    SSGCspy.plosNurseryDriver.resetRootsStream();
+    SSGCspy.plosDriver.resetRootsStream();
+    ss.getCursor();
+  }
+
+  /**
+   * Pass a root to all drivers.<p>
+   * @param addr The Address of the object to be checked
+   */
+  protected void checkAllDriversForRootAddress(Address addr) {
+    if(addr.isZero())
+      return;
+
+    SSGCspy.ss0Driver.handleRoot(addr);
+    SSGCspy.ss1Driver.handleRoot(addr);
+    SSGCspy.immortalDriver.handleRoot(addr);
+    SSGCspy.losNurseryDriver.handleRoot(addr);
+    SSGCspy.losDriver.handleRoot(addr);
+    SSGCspy.plosNurseryDriver.handleRoot(addr);
+    SSGCspy.plosDriver.handleRoot(addr);
+  }
+
+  /****************************************************************************
+   *
+   * Miscellaneous
+   */
+
+  /** @return The active global plan as an <code>SSGCspy</code> instance. */
+  @Inline
+  private static SSGCspy global() {
+    return (SSGCspy) VM.activePlan.global();
+  }
+
+  /** @return the driver for toSpace */
+  private LinearSpaceDriver toSpaceDriver() {
+    return SSGCspy.hi ? SSGCspy.ss1Driver : SSGCspy.ss0Driver;
+  }
+
+  /** @return the driver for fromSpace */
+  private LinearSpaceDriver fromSpaceDriver() {
+    return SSGCspy.hi ? SSGCspy.ss0Driver : SSGCspy.ss1Driver;
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyConstraints.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyConstraints.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyConstraints.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyConstraints.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,27 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.semispace.gcspy;
+
+import org.mmtk.plan.semispace.SSConstraints;
+import org.vmmagic.pragma.*;
+
+/**
+ * Semi space GCspy constants.
+ */
+ at Uninterruptible
+public class SSGCspyConstraints extends SSConstraints {
+  @Override
+  public boolean needsLinearScan() { return true; }
+  @Override
+  public boolean withGCspy() { return true; }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyMutator.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyMutator.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyMutator.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyMutator.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,348 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.semispace.gcspy;
+
+import org.mmtk.plan.Phase;
+import org.mmtk.plan.semispace.SSMutator;
+import org.mmtk.policy.CopySpace;
+import org.mmtk.policy.Space;
+import org.mmtk.policy.ImmortalLocal;
+import org.mmtk.utility.Log;
+import org.mmtk.utility.alloc.BumpPointer;
+import org.mmtk.utility.alloc.Allocator;
+import org.mmtk.utility.gcspy.GCspy;
+import org.mmtk.utility.gcspy.drivers.LinearSpaceDriver;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements <i>per-mutator thread</i> behavior and state for the
+ * <i>SSGCspy</i> plan.
+ *
+ * See {@link SSGCspy} for an overview of the GC-spy mechanisms.
+ * <p>
+ *
+ * @see SSMutator
+ * @see SSGCspy
+ * @see SSGCspyCollector
+ * @see org.mmtk.plan.StopTheWorldMutator
+ * @see org.mmtk.plan.MutatorContext
+ */
+ at Uninterruptible public class SSGCspyMutator extends SSMutator {
+
+  /*****************************************************************************
+   * Instance fields
+   */
+
+  private static final boolean DEBUG = false;
+
+  private static final boolean LOS_TOSPACE = true;    // gather from tospace
+  private static final boolean LOS_FROMSPACE = false; // gather from fromspace
+
+  /** Per-mutator allocator into GCspy's space */
+  private BumpPointer gcspy = new ImmortalLocal(SSGCspy.gcspySpace);
+
+
+
+  /*****************************************************************************
+   *
+   * Mutator-time allocation
+   */
+
+  /**
+   * Allocate space (for an object)
+   *
+   * @param bytes The size of the space to be allocated (in bytes)
+   * @param align The requested alignment.
+   * @param offset The alignment offset.
+   * @param allocator The allocator number to be used for this allocation
+   * @param site Allocation site
+   * @return The address of the first byte of the allocated region
+   */
+  @Inline
+  public Address alloc(int bytes, int align, int offset, int allocator, int site) {
+    if (allocator == SSGCspy.ALLOC_GCSPY)
+      return gcspy.alloc(bytes, align, offset);
+    else
+      return super.alloc(bytes, align, offset, allocator, site);
+  }
+
+  /**
+   * Perform post-allocation actions. For many allocators none are required.
+   *
+   * @param object The newly allocated object
+   * @param typeRef The type reference for the instance being created
+   * @param bytes The size of the space to be allocated (in bytes)
+   * @param allocator The allocator number to be used for this allocation
+   */
+  @Inline
+  public void postAlloc(ObjectReference object, ObjectReference typeRef,
+                        int bytes, int allocator) {
+    if (allocator == SSGCspy.ALLOC_GCSPY)
+      SSGCspy.gcspySpace.initializeHeader(object);
+    else
+      super.postAlloc(object, typeRef, bytes, allocator);
+  }
+
+  /**
+   * Return the allocator instance associated with a space
+   * <code>space</code>, for this plan instance.
+   *
+   * @param space The space for which the allocator instance is desired.
+   * @return The allocator instance associated with this plan instance
+   * which is allocating into <code>space</code>, or <code>null</code>
+   * if no appropriate allocator can be established.
+   */
+  public Allocator getAllocatorFromSpace(Space space) {
+    if (space == SSGCspy.gcspySpace) return gcspy;
+    return super.getAllocatorFromSpace(space);
+  }
+
+  /*****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a per-mutator collection phase.
+   * Before a collection, we need to discover
+   * <ul>
+   * <li>the tospace objects copied by the collector in the last GC cycle
+   * <li>the ojects allocated since by the mutator.
+   * <li>all immortal objects allocated by the mutator
+   * <li>all large objects allocated by the mutator
+   * </ul>
+   * After the semispace has been copied, we need to discover
+   * <ul>
+   * <li>the tospace objects copied by the collector
+   * <li>all immortal objects allocated by the mutator
+   * <li>all large objects allocated by the mutator
+   * </ul>
+   */
+  @Inline
+  public final void collectionPhase(short phaseId, boolean primary) {
+    if (DEBUG) { Log.write("--Phase Mutator."); Log.writeln(Phase.getName(phaseId)); }
+
+    // TODO do we need to worry any longer about primary??
+    if (phaseId == SSGCspy.PREPARE) {
+      //if (primary)
+        gcspyGatherData(SSGCspy.BEFORE_COLLECTION);
+      super.collectionPhase(phaseId, primary);
+      return;
+    }
+
+    if (phaseId == SSGCspy.RELEASE) {
+      //if (primary)
+        gcspyGatherData(SSGCspy.SEMISPACE_COPIED);
+      super.collectionPhase(phaseId, primary);
+      //if (primary)
+        gcspyGatherData(SSGCspy.AFTER_COLLECTION);
+      return;
+    }
+
+    super.collectionPhase(phaseId, primary);
+  }
+
+  /**
+   * Gather data for GCspy for the semispaces, the immortal space and the large
+   * object space.
+   * <p>
+   * This method sweeps the semispace under consideration to gather data.
+   * Alternatively and more efficiently, 'used space' can obviously be
+   * discovered in constant time simply by comparing the start and the end
+   * addresses of the semispace. However, per-object information can only be
+   * gathered by sweeping through the space and we do this here for tutorial
+   * purposes.
+   *
+   * @param event
+   *          The event, either BEFORE_COLLECTION, SEMISPACE_COPIED or
+   *          AFTER_COLLECTION
+   */
+  private void gcspyGatherData(int event) {
+    if(DEBUG) {
+      Log.writeln("SSGCspyMutator.gcspyGatherData, event=", event);
+      Log.writeln("SSGCspyMutator.gcspyGatherData, port=", GCspy.getGCspyPort());
+    }
+
+    // If port = 0 there can be no GCspy client connected
+    if (GCspy.getGCspyPort() == 0)
+      return;
+
+    // If the server is connected to a client that is interested in this
+    // event, then we gather data. But first we start a timer to
+    // compensate for the time spent gathering data here.
+    if (GCspy.server.isConnected(event)) {
+
+      if (DEBUG) {
+        if (SSGCspy.hi)
+          Log.write("\nMutator Examining Lowspace (event ", event);
+        else
+          Log.write("\nMutator Examining Highspace (event ", event);
+        Log.write(")");
+        SSGCspy.reportSpaces(); Log.writeln();
+      }
+
+      if (event == SSGCspy.BEFORE_COLLECTION) {
+        // Before the flip
+        // Mutator has not rebound toSpace yet
+        GCspy.server.startCompensationTimer();
+
+        // -- Handle the semispaces
+        // Here I need to scan newly allocated objects
+        if (DEBUG) {
+          //debugSpaces(SSGCspy.fromSpace());
+          debugSpaces(SSGCspy.toSpace());
+          Log.write("SSGCspyMutator.gcspyGatherData reset, gather and transmit driver ");
+          //Log.writeln(SSGCspy.fromSpace().getName());
+          Log.writeln(SSGCspy.toSpace().getName());
+        }
+        //ss.gcspyGatherData(fromSpaceDriver(), SSGCspy.fromSpace());
+        ss.gcspyGatherData(toSpaceDriver(), SSGCspy.toSpace());
+
+        // -- Handle the immortal space --
+        gatherImmortal(event);
+
+        // -- Handle the LOSes
+
+        // reset, collect and scan los data for the nursery and tospace
+        SSGCspy.losNurseryDriver.resetData();
+        los.gcspyGatherData(event, SSGCspy.losNurseryDriver);
+        SSGCspy.losDriver.resetData();
+        los.gcspyGatherData(event, SSGCspy.losDriver, LOS_TOSPACE);
+
+        // transmit the data
+        GCspy.server.stopCompensationTimer();
+        //fromSpaceDriver().transmit(event);
+        toSpaceDriver().transmit(event);
+        SSGCspy.immortalDriver.transmit(event);
+        SSGCspy.losNurseryDriver.transmit(event);
+        SSGCspy.losDriver.transmit(event);
+        SSGCspy.plosNurseryDriver.transmit(event);
+        SSGCspy.plosDriver.transmit(event);
+
+        // As this follows Collector.gcspyGatherData, I'll safepoint here
+        // This is a safepoint for the server, i.e. it is a point at which
+        // the server can pause.
+        GCspy.server.serverSafepoint(event);
+      } else if (event == SSGCspy.SEMISPACE_COPIED) {
+        // We have flipped
+        // toSpace still has not been rebound
+
+        // -- Handle the semispaces
+        if (DEBUG) {
+          //debugSpaces(SSGCspy.toSpace());
+          debugSpaces(SSGCspy.fromSpace());
+          Log.writeln("SSGCspyMutator.gcspyGatherData: do nothing");
+        }
+
+        // -- Handle the immortal space --
+        GCspy.server.startCompensationTimer();
+        gatherImmortal(event);
+
+        // reset, scan and send the los for the nursery and tospace
+        // and fromspace as well if full heap collection
+        SSGCspy.losNurseryDriver.resetData();
+        los.gcspyGatherData(event, SSGCspy.losNurseryDriver);
+        SSGCspy.losDriver.resetData();
+        los.gcspyGatherData(event, SSGCspy.losDriver, LOS_FROMSPACE);
+        los.gcspyGatherData(event, SSGCspy.losDriver, LOS_TOSPACE);
+
+        // transmit
+        GCspy.server.stopCompensationTimer();
+        SSGCspy.immortalDriver.transmit(event);
+        SSGCspy.losNurseryDriver.transmit(event);
+        SSGCspy.losDriver.transmit(event);
+        SSGCspy.plosNurseryDriver.transmit(event);
+        SSGCspy.plosDriver.transmit(event);
+
+        // As this follows Collector.gcspyGatherData, I'll safepoint here
+        // This is a safepoint for the server, i.e. it is a point at which
+        // the server can pause.
+        GCspy.server.serverSafepoint(event);
+      } else if (event == SSGCspy.AFTER_COLLECTION) {
+        // We have flipped
+        // And toSpace has been rebound
+
+        GCspy.server.startCompensationTimer();
+
+        // -- Handle the semispaces
+        if (DEBUG) debugSpaces(SSGCspy.toSpace());
+
+        // -- Handle the immortal space --
+        gatherImmortal(event);
+
+        // -- Handle the LOSes
+
+        // reset, scan and send the los
+        SSGCspy.losNurseryDriver.resetData();
+        SSGCspy.losDriver.resetData();
+        // no need to scan empty nursery
+        los.gcspyGatherData(event, SSGCspy.losDriver, LOS_TOSPACE);
+
+        //transmit
+        GCspy.server.stopCompensationTimer();
+        SSGCspy.immortalDriver.transmit(event);
+        SSGCspy.losNurseryDriver.transmit(event);
+        SSGCspy.losDriver.transmit(event);
+        SSGCspy.plosNurseryDriver.transmit(event);
+        SSGCspy.plosDriver.transmit(event);
+
+        // Reset fromspace
+        if (DEBUG) {
+          Log.write("SSGCspyMutator.gcspyGatherData: reset and zero range for driver ");
+          Log.write(SSGCspy.toSpace().getName());
+        }
+      }
+
+    }
+    // else Log.write("not transmitting...");
+  }
+
+  /**
+   * Gather data for the immortal space
+   * @param event
+   * The event, either BEFORE_COLLECTION, SEMISPACE_COPIED or
+   *          AFTER_COLLECTION
+   */
+  private void gatherImmortal(int event) {
+    // We want to do this at every GCspy event
+    if (DEBUG) {
+      Log.write("SSGCspyMutator.gcspyGatherData: gather data for immortal space ");
+      Log.write(SSGCspy.immortalSpace.getStart()); Log.writeln("-",immortal.getCursor());
+    }
+    SSGCspy.immortalDriver.resetData();
+    immortal.gcspyGatherData(SSGCspy.immortalDriver);
+    if (DEBUG) Log.writeln("Finished immortal space.");
+  }
+
+  /**
+   * Debugging info for the semispaces
+   * @param scannedSpace the space to output debug for.
+   */
+  private void debugSpaces(CopySpace scannedSpace) {
+    Log.write("SSGCspyMutator.gcspyGatherData: gather data for active semispace ");
+    Log.write(scannedSpace.getStart()); Log.write("-",ss.getCursor()); Log.flush();
+    Log.write(". The space is: "); Log.writeln(ss.getSpace().getName());
+    Log.write("scannedSpace is "); Log.writeln(scannedSpace.getName());
+    Log.write("The range is "); Log.write(ss.getSpace().getStart());
+    Log.write(" to "); Log.writeln(ss.getCursor());
+    SSGCspy.reportSpaces();
+  }
+
+  /** @return the driver for toSpace */
+  private LinearSpaceDriver toSpaceDriver() {
+    return SSGCspy.hi ? SSGCspy.ss1Driver : SSGCspy.ss0Driver;
+  }
+
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyTraceLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyTraceLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyTraceLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gcspy/SSGCspyTraceLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,70 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.semispace.gcspy;
+
+import org.mmtk.plan.Trace;
+import org.mmtk.plan.semispace.SSTraceLocal;
+import org.mmtk.policy.Space;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implments the core functionality for a transitive
+ * closure over the heap graph.
+ */
+ at Uninterruptible
+public final class SSGCspyTraceLocal extends SSTraceLocal {
+  /**
+   * Constructor
+   */
+  public SSGCspyTraceLocal(Trace trace) {
+    super(trace);
+  }
+
+  /****************************************************************************
+   *
+   * Externally visible Object processing and tracing
+   */
+
+  /**
+   * This method is the core method during the trace of the object graph.
+   * The role of this method is to:
+   *
+   * 1. Ensure the traced object is not collected.
+   * 2. If this is the first visit to the object enqueue it to be scanned.
+   * 3. Return the forwarded reference to the object.
+   *
+   * @param object The object to be traced.
+   * @return The new reference to the same object instance.
+   */
+  @Inline
+  public ObjectReference traceObject(ObjectReference object) {
+    if (object.isNull()) return object;
+    if (Space.isInSpace(SSGCspy.GCSPY, object))
+      return SSGCspy.gcspySpace.traceObject(this, object);
+    return super.traceObject(object);
+  }
+
+  /**
+   * Will this object move from this point on, during the current trace ?
+   *
+   * @param object The object to query.
+   * @return True if the object will not move.
+   */
+  public boolean willNotMoveInCurrentCollection(ObjectReference object) {
+    if (Space.isInSpace(SSGCspy.GCSPY, object))
+      return true;
+    return super.willNotMoveInCurrentCollection(object);
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTrace.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTrace.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTrace.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTrace.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,208 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.semispace.gctrace;
+
+import org.mmtk.plan.semispace.*;
+import org.mmtk.policy.RawPageSpace;
+import org.mmtk.utility.deque.SortTODSharedDeque;
+import org.mmtk.utility.heap.VMRequest;
+import org.mmtk.utility.TraceGenerator;
+import org.mmtk.utility.options.Options;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This plan has been modified slightly to perform the processing necessary
+ * for GC trace generation.  To maximize performance, it attempts to remain
+ * as faithful as possible to semiSpace/Plan.java.
+ *
+ * The generated trace format is as follows:
+ *    B 345678 12
+ *      (Object 345678 was created in the boot image with a size of 12 bytes)
+ *    U 59843 234 47298
+ *      (Update object 59843 at the slot at offset 234 to refer to 47298)
+ *    S 1233 12345
+ *      (Update static slot 1233 to refer to 12345)
+ *    T 4567 78924
+ *      (The TIB of 4567 is set to refer to 78924)
+ *    D 342789
+ *      (Object 342789 became unreachable)
+ *    A 6860 24 346648 3
+ *      (Object 6860 was allocated, requiring 24 bytes, with fp 346648 on
+ *        thread 3; this allocation has perfect knowledge)
+ *    a 6884 24 346640 5
+ *      (Object 6864 was allocated, requiring 24 bytes, with fp 346640 on
+ * thread 5; this allocation DOES NOT have perfect knowledge)
+ *    I 6860 24 346648 3
+ *      (Object 6860 was allocated into immortal space, requiring 24 bytes,
+ *        with fp 346648 on thread 3; this allocation has perfect knowledge)
+ *    i 6884 24 346640 5
+ *      (Object 6864 was allocated into immortal space, requiring 24 bytes,
+ *        with fp 346640 on thread 5; this allocation DOES NOT have perfect
+ *        knowledge)
+ *    48954->[345]LObject;:blah()V:23   Ljava/lang/Foo;
+ *      (Citation for: a) where the was allocated, fp of 48954,
+ *         at the method with ID 345 -- or void Object.blah() -- and bytecode
+ *         with offset 23; b) the object allocated is of type java.lang.Foo)
+ *    D 342789 361460
+ *      (Object 342789 became unreachable after 361460 was allocated)
+ *
+ * This class implements a simple semi-space collector. See the Jones
+ * & Lins GC book, section 2.2 for an overview of the basic
+ * algorithm. This implementation also includes a large object space
+ * (LOS), and an uncollected "immortal" space.<p>
+ *
+ * All plans make a clear distinction between <i>global</i> and
+ * <i>thread-local</i> activities.  Global activities must be
+ * synchronized, whereas no synchronization is required for
+ * thread-local activities.  Instances of Plan map 1:1 to "kernel
+ * threads" (aka CPUs).  Thus instance
+ * methods allow fast, unsychronized access to Plan utilities such as
+ * allocation and collection.  Each instance rests on static resources
+ * (such as memory and virtual memory resources) which are "global"
+ * and therefore "static" members of Plan.  This mapping of threads to
+ * instances is crucial to understanding the correctness and
+ * performance proprties of this plan.
+ */
+ at Uninterruptible public class GCTrace extends SS {
+
+  /****************************************************************************
+   *
+   * Class variables
+   */
+
+  /* Spaces */
+  public static final RawPageSpace traceSpace = new RawPageSpace("trace", DEFAULT_POLL_FREQUENCY, VMRequest.create());
+  public static final int TRACE = traceSpace.getDescriptor();
+
+  /* GC state */
+  public static boolean lastGCWasTracing = false; // True when previous GC was for tracing
+  public static boolean traceInducedGC = false; // True if trace triggered GC
+  public static boolean deathScan = false;
+  public static boolean finalDead = false;
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * Constructor
+   */
+  public GCTrace() {
+    SortTODSharedDeque workList = new SortTODSharedDeque("workList",traceSpace, 1);
+    SortTODSharedDeque traceBuf = new SortTODSharedDeque("traceBuf",traceSpace, 1);
+    workList.prepareNonBlocking();
+    traceBuf.prepareNonBlocking();
+    TraceGenerator.init(workList, traceBuf);
+  }
+
+  /**
+   * The postBoot method is called by the runtime immediately after
+   * command-line arguments are available.
+   */
+  @Interruptible
+  public void postBoot() {
+    Options.noFinalizer.setValue(true);
+  }
+
+  /**
+   * The planExit method is called at RVM termination to allow the
+   * trace process to finish.
+   */
+  @Interruptible
+  public final void notifyExit(int value) {
+    super.notifyExit(value);
+    finalDead = true;
+    traceInducedGC = false;
+    deathScan = true;
+    TraceGenerator.notifyExit(value);
+  }
+
+  /**
+   * This method controls the triggering of a GC. It is called periodically
+   * during allocation. Returns true to trigger a collection.
+   *
+   * @param spaceFull Space request failed, must recover pages within 'space'.
+   * @return True if a collection is requested by the plan.
+   */
+  public final boolean collectionRequired(boolean spaceFull) {
+    if (super.collectionRequired(spaceFull)) {
+      traceInducedGC = false;
+      return true;
+    }
+    return false;
+  }
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  public void collectionPhase(short phaseId) {
+    if (phaseId == PREPARE) {
+      lastGCWasTracing = traceInducedGC;
+    }
+    if (phaseId == RELEASE) {
+      if (traceInducedGC) {
+        /* Clean up following a trace-induced scan */
+        deathScan = false;
+      } else {
+        /* Finish the collection by calculating the unreachable times */
+        deathScan = true;
+        TraceGenerator.postCollection();
+        deathScan = false;
+        /* Perform the semispace collections. */
+        super.collectionPhase(phaseId);
+      }
+    } else if (!traceInducedGC ||
+               (phaseId == INITIATE) ||
+               (phaseId == PREPARE_STACKS) ||
+               (phaseId == ROOTS) ||
+               (phaseId == STACK_ROOTS) ||
+               (phaseId == COMPLETE)) {
+      /* Performing normal GC; sponge off of parent's work. */
+      super.collectionPhase(phaseId);
+    }
+  }
+
+
+  /****************************************************************************
+   *
+   * Space management
+   */
+
+  /**
+   * @return Since trace induced collections are not called to free up memory,
+   *         their failure to return memory isn't cause for concern.
+   */
+  public boolean isLastGCFull() {
+    return !lastGCWasTracing;
+  }
+
+  /**
+   * @return the active PlanLocal as a GCTraceLocal
+   */
+  public static GCTraceCollector local() {
+    return ((GCTraceCollector) VM.activePlan.collector());
+  }
+
+  /**
+   * @return the active Plan as a GCTrace
+   */
+  public static GCTrace global() {
+    return ((GCTrace) VM.activePlan.global());
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceCollector.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceCollector.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceCollector.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceCollector.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,108 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.semispace.gctrace;
+
+import org.mmtk.plan.*;
+import org.mmtk.plan.semispace.*;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+
+
+/**
+ * This class implements <i>per-collector thread</i> behavior and state for the
+ * <i>GCTrace</i> plan, which implements a GC tracing algorithm.<p>
+ *
+ * Specifically, this class defines <i>SS</i> collection behavior
+ * (through <code>inducedTrace</code> and the <code>collectionPhase</code>
+ * method), and collection-time allocation (copying of objects).<p>
+ *
+ * See {@link GCTrace} for an overview of the GC trace algorithm.<p>
+ *
+ * @see SSCollector
+ * @see GCTrace
+ * @see GCTraceMutator
+ * @see org.mmtk.plan.StopTheWorldCollector
+ * @see org.mmtk.plan.CollectorContext
+ */
+ at Uninterruptible public class GCTraceCollector extends SSCollector {
+  /****************************************************************************
+   * Instance fields
+   */
+  protected final GCTraceTraceLocal inducedTrace;
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * Constructor
+   */
+  public GCTraceCollector() {
+    inducedTrace = new GCTraceTraceLocal(global().ssTrace);
+  }
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a per-collector collection phase.
+   *
+   * @param phaseId The collection phase to perform
+   * @param primary perform any single-threaded local activities.
+   */
+  public void collectionPhase(short phaseId, boolean primary) {
+    if (phaseId == GCTrace.CLOSURE) {
+      inducedTrace.completeTrace();
+      return;
+    }
+
+    if (phaseId == GCTrace.RELEASE) {
+      inducedTrace.release();
+      if (!GCTrace.traceInducedGC) {
+        super.collectionPhase(phaseId, primary);
+      }
+      return;
+    }
+
+    /* fall through case */
+    if (!GCTrace.traceInducedGC ||
+        ((phaseId != StopTheWorld.SOFT_REFS) &&
+         (phaseId != StopTheWorld.WEAK_REFS) &&
+         (phaseId != StopTheWorld.PHANTOM_REFS) &&
+         (phaseId != StopTheWorld.FINALIZABLE) &&
+         (phaseId != SS.PREPARE))) {
+      // Delegate up.
+      super.collectionPhase(phaseId, primary);
+    }
+  }
+
+  /****************************************************************************
+   *
+   * Miscellaneous
+   */
+
+  /** @return The active global plan as a <code>GCTrace</code> instance. */
+  @Inline
+  private static GCTrace global() {
+    return (GCTrace) VM.activePlan.global();
+  }
+
+  /** @return The current trace instance */
+  public TraceLocal getCurrentTrace() {
+    return inducedTrace;
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceConstraints.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceConstraints.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceConstraints.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceConstraints.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,28 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.semispace.gctrace;
+
+import org.mmtk.plan.semispace.SSConstraints;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * GCTrace constants.
+ */
+ at Uninterruptible
+public class GCTraceConstraints extends SSConstraints {
+  @Override
+  public boolean needsWriteBarrier() { return true; }
+  @Override
+  public boolean generateGCTrace() { return true; }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceMutator.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceMutator.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceMutator.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceMutator.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,180 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.semispace.gctrace;
+
+import org.mmtk.plan.semispace.SSMutator;
+import org.mmtk.plan.*;
+import org.mmtk.utility.TraceGenerator;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements <i>per-mutator thread</i> behavior and state for the
+ * <i>GCTrace</i> plan, which implements a GC tracing algorithm.<p>
+ *
+ * Specifically, this class defines <i>SS</i> mutator-time allocation, write
+ * barriers, and per-mutator collection semantics.<p>
+ *
+ * See {@link GCTrace} for an overview of the GC trace algorithm.<p>
+ *
+ * @see SSMutator
+ * @see GCTrace
+ * @see GCTraceCollector
+ * @see org.mmtk.plan.StopTheWorldMutator
+ * @see org.mmtk.plan.MutatorContext
+ */
+ at Uninterruptible public class GCTraceMutator extends SSMutator {
+
+  /****************************************************************************
+   *
+   * Mutator-time allocation
+   */
+
+  /**
+   * Perform post-allocation actions.  For many allocators none are
+   * required.
+   *
+   * @param object The newly allocated object
+   * @param typeRef the type reference for the instance being created
+   * @param bytes The size of the space to be allocated (in bytes)
+   * @param allocator The allocator number to be used for this allocation
+   */
+  @Inline
+  public final void postAlloc(ObjectReference object, ObjectReference typeRef,
+      int bytes, int allocator) {
+    /* Make the trace generator aware of the new object. */
+    TraceGenerator.addTraceObject(object, allocator);
+
+    super.postAlloc(object, typeRef, bytes, allocator);
+
+    /* Now have the trace process aware of the new allocation. */
+    GCTrace.traceInducedGC = TraceGenerator.MERLIN_ANALYSIS;
+    TraceGenerator.traceAlloc(allocator == GCTrace.ALLOC_IMMORTAL, object, typeRef, bytes);
+    GCTrace.traceInducedGC = false;
+  }
+
+
+  /****************************************************************************
+   *
+   * Write barrier.
+   */
+
+  /**
+   * A new reference is about to be created.  Take appropriate write
+   * barrier actions.<p>
+   *
+   * In this case, we remember the address of the source of the
+   * pointer if the new reference points into the nursery from
+   * non-nursery space.
+   *
+   * @param src The object into which the new reference will be stored
+   * @param slot The address into which the new reference will be
+   * stored.
+   * @param tgt The target of the new reference
+   * @param metaDataA A value that assists the host VM in creating a store
+   * @param metaDataB A value that assists the host VM in creating a store
+   * being modified
+   * @param mode The mode of the store (eg putfield, putstatic etc)
+   */
+  @Inline
+  public final void writeBarrier(ObjectReference src, Address slot,
+      ObjectReference tgt, Word metaDataA,
+      Word metaDataB, int mode) {
+    TraceGenerator.processPointerUpdate(mode == PUTFIELD_WRITE_BARRIER,
+        src, slot, tgt);
+    VM.barriers.performWriteInBarrier(src, slot, tgt, metaDataA, metaDataB, mode);
+  }
+
+  /**
+   * Attempt to atomically exchange the value in the given slot
+   * with the passed replacement value. If a new reference is
+   * created, we must then take appropriate write barrier actions.<p>
+   *
+   * <b>By default do nothing, override if appropriate.</b>
+   *
+   * @param src The object into which the new reference will be stored
+   * @param slot The address into which the new reference will be
+   * stored.
+   * @param old The old reference to be swapped out
+   * @param tgt The target of the new reference
+   * @param metaDataA A value that assists the host VM in creating a store
+   * @param metaDataB A value that assists the host VM in creating a store
+   * @param mode The context in which the store occured
+   * @return True if the swap was successful.
+   */
+  @Inline
+  public boolean tryCompareAndSwapWriteBarrier(ObjectReference src, Address slot,
+      ObjectReference old, ObjectReference tgt, Word metaDataA,
+      Word metaDataB, int mode) {
+    boolean result = VM.barriers.tryCompareAndSwapWriteInBarrier(src, slot, old, tgt, metaDataA, metaDataB, mode);
+    if (result) {
+      TraceGenerator.processPointerUpdate(mode == PUTFIELD_WRITE_BARRIER, src, slot, tgt);
+    }
+    return result;
+  }
+
+  /**
+   * A number of references are about to be copied from object
+   * <code>src</code> to object <code>dst</code> (as in an array
+   * copy).  Thus, <code>dst</code> is the mutated object.  Take
+   * appropriate write barrier actions.<p>
+   *
+   * @param src The source of the values to be copied
+   * @param srcOffset The offset of the first source address, in
+   * bytes, relative to <code>src</code> (in principle, this could be
+   * negative).
+   * @param dst The mutated object, i.e. the destination of the copy.
+   * @param dstOffset The offset of the first destination address, in
+   * bytes relative to <code>tgt</code> (in principle, this could be
+   * negative).
+   * @param bytes The size of the region being copied, in bytes.
+   * @return True if the update was performed by the barrier, false if
+   * left to the caller (always false in this case).
+   */
+  public boolean writeBarrier(ObjectReference src, Offset srcOffset,
+      ObjectReference dst, Offset dstOffset, int bytes) {
+    /* These names seem backwards, but are defined to be compatable with the
+     * previous writeBarrier method. */
+    Address slot = dst.toAddress().plus(dstOffset);
+    Address tgtLoc = src.toAddress().plus(srcOffset);
+    for (int i = 0; i < bytes; i += BYTES_IN_ADDRESS) {
+      ObjectReference tgt = tgtLoc.loadObjectReference();
+      TraceGenerator.processPointerUpdate(false, dst, slot, tgt);
+      slot = slot.plus(BYTES_IN_ADDRESS);
+      tgtLoc = tgtLoc.plus(BYTES_IN_ADDRESS);
+    }
+    return false;
+  }
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a per-mutator collection phase.
+   *
+   * @param phaseId The collection phase to perform
+   * @param primary perform any single-threaded local activities.
+   */
+  public void collectionPhase(short phaseId, boolean primary) {
+    if (!GCTrace.traceInducedGC ||
+        (phaseId != StopTheWorld.PREPARE) &&
+        (phaseId != StopTheWorld.RELEASE)) {
+      // Delegate up.
+      super.collectionPhase(phaseId, primary);
+    }
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceTraceLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceTraceLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceTraceLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/semispace/gctrace/GCTraceTraceLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,199 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.semispace.gctrace;
+
+import org.mmtk.plan.Trace;
+import org.mmtk.plan.semispace.*;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.TraceGenerator;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This plan has been modified slightly to perform the processing necessary
+ * for GC trace generation.  To maximize performance, it attempts to remain
+ * as faithful as possible to semiSpace/Plan.java.
+ *
+ * The generated trace format is as follows:
+ *    B 345678 12
+ *      (Object 345678 was created in the boot image with a size of 12 bytes)
+ *    U 59843 234 47298
+ *      (Update object 59843 at the slot at offset 234 to refer to 47298)
+ *    S 1233 12345
+ *      (Update static slot 1233 to refer to 12345)
+ *    T 4567 78924
+ *      (The TIB of 4567 is set to refer to 78924)
+ *    D 342789
+ *      (Object 342789 became unreachable)
+ *    A 6860 24 346648 3
+ *      (Object 6860 was allocated, requiring 24 bytes, with fp 346648 on
+ *        thread 3; this allocation has perfect knowledge)
+ *    a 6884 24 346640 5
+ *      (Object 6864 was allocated, requiring 24 bytes, with fp 346640 on
+ * thread 5; this allocation DOES NOT have perfect knowledge)
+ *    I 6860 24 346648 3
+ *      (Object 6860 was allocated into immortal space, requiring 24 bytes,
+ *        with fp 346648 on thread 3; this allocation has perfect knowledge)
+ *    i 6884 24 346640 5
+ *      (Object 6864 was allocated into immortal space, requiring 24 bytes,
+ *        with fp 346640 on thread 5; this allocation DOES NOT have perfect
+ *        knowledge)
+ *    48954->[345]LObject;:blah()V:23   Ljava/lang/Foo;
+ *      (Citation for: a) where the was allocated, fp of 48954,
+ *         at the method with ID 345 -- or void Object.blah() -- and bytecode
+ *         with offset 23; b) the object allocated is of type java.lang.Foo)
+ *    D 342789 361460
+ *      (Object 342789 became unreachable after 361460 was allocated)
+ *
+ * This class implements a simple semi-space collector. See the Jones
+ * & Lins GC book, section 2.2 for an overview of the basic
+ * algorithm. This implementation also includes a large object space
+ * (LOS), and an uncollected "immortal" space.<p>
+ *
+ * All plans make a clear distinction between <i>global</i> and
+ * <i>thread-local</i> activities.  Global activities must be
+ * synchronized, whereas no synchronization is required for
+ * thread-local activities.  Instances of Plan map 1:1 to "kernel
+ * threads" (aka CPUs).  Thus instance
+ * methods allow fast, unsychronized access to Plan utilities such as
+ * allocation and collection.  Each instance rests on static resources
+ * (such as memory and virtual memory resources) which are "global"
+ * and therefore "static" members of Plan.  This mapping of threads to
+ * instances is crucial to understanding the correctness and
+ * performance proprties of this plan.
+ */
+ at Uninterruptible
+public final class GCTraceTraceLocal extends SSTraceLocal {
+
+  /**
+   * Constructor
+   *
+   * @param trace The global trace to use.
+   */
+  public GCTraceTraceLocal(Trace trace) {
+    super(trace, false);
+  }
+
+  /****************************************************************************
+   *
+   * Object processing and tracing
+   */
+
+  /**
+   * Trace a reference during GC.  This involves determining which
+   * collection policy applies (such as those needed for trace generation)
+   * and taking the appropriate actions.
+   *
+   * @param object The object reference to be traced.  In certain
+   * cases, this should <i>NOT</i> be an interior pointer.
+   * @return The possibly moved reference.
+   */
+  @Inline
+  public ObjectReference traceObject(ObjectReference object) {
+    if (object.isNull()) return object;
+    if (GCTrace.traceInducedGC) {
+      /* We are performing a root scan following an allocation. */
+      TraceGenerator.rootEnumerate(object);
+      return object;
+    } else if (GCTrace.deathScan) {
+      /* We are performing the last scan before program termination. */
+      TraceGenerator.propagateDeathTime(object);
+      return object;
+    } else {
+      /* *gasp* We are actually performing garbage collection */
+      return super.traceObject(object);
+    }
+  }
+
+  /**
+   * Ensure that the referenced object will not move during a collection
+   * by 'precopying' it at the beginning.
+   *
+   * @param object The object to ensure will not move.
+   */
+  @Inline
+  public ObjectReference precopyObject(ObjectReference object) {
+    if (object.isNull()) return object;
+    if (GCTrace.traceInducedGC) {
+      /* We are performing a root scan following an allocation. */
+      TraceGenerator.rootEnumerate(object);
+      return object;
+    } else if (GCTrace.deathScan) {
+      /* We are performing the last scan before program termination. */
+      TraceGenerator.propagateDeathTime(object);
+      return object;
+    } else {
+      return super.precopyObject(object);
+    }
+  }
+
+
+  /**
+   * If the referenced object has moved, return the new location.
+   *
+   * Some copying collectors will need to override this method.
+   *
+   * @param object The object which may have been forwarded.
+   * @return The new location of <code>object</code>.
+   */
+  @Inline
+  public ObjectReference getForwardedReference(ObjectReference object) {
+    if (object.isNull()) return object;
+    if (SS.hi && Space.isInSpace(SS.SS0, object)) {
+      return SS.copySpace0.traceObject(this, object, GCTrace.ALLOC_SS);
+    } else if (!SS.hi && Space.isInSpace(SS.SS1, object)) {
+      return SS.copySpace1.traceObject(this, object, GCTrace.ALLOC_SS);
+    }
+    return object;
+  }
+
+  /**
+   * Return true if <code>obj</code> is a live object.
+   *
+   * @param object The object in question
+   * @return True if <code>obj</code> is a live object.
+   */
+  public boolean isLive(ObjectReference object) {
+      if (object.isNull()) return false;
+      else if (GCTrace.traceInducedGC) return true;
+      else return super.isLive(object);
+  }
+
+  /**
+   * Return true if <code>obj</code> is a reachable object.
+   *
+   * @param object The object in question
+   * @return True if <code>obj</code> is a reachable object;
+   * unreachable objects may still be live, however
+   */
+  public boolean isReachable(ObjectReference object) {
+    if (GCTrace.finalDead) return false;
+    else if (object.isNull()) return false;
+    else {
+      Space space = Space.getSpaceForObject(object);
+      return space.isReachable(object);
+    }
+  }
+
+  /**
+   * Is this object guaranteed not to move during the collection.
+   *
+   * @param object The object to check.
+   * @return True if the object is guaranteed not to move.
+   */
+  public boolean willNotMoveInCurrentCollection(ObjectReference object) {
+    if (GCTrace.traceInducedGC) return true;
+    else return super.willNotMoveInCurrentCollection(object);
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmix.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmix.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmix.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmix.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,237 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.stickyimmix;
+
+import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.plan.immix.Immix;
+import org.mmtk.utility.Log;
+import org.mmtk.utility.deque.SharedDeque;
+import org.mmtk.utility.options.Options;
+import org.mmtk.utility.statistics.BooleanCounter;
+import org.mmtk.utility.statistics.Stats;
+import org.mmtk.vm.Collection;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements the global state of a simple sticky mark bits collector,
+ * based on an immix collector.  The sticky mark bits algorithm is
+ * due to Demmers et al. (http://doi.acm.org/10.1145/96709.96735), and allows
+ * generational collection to be performed in a non-moving heap by overloading
+ * the role of mark bits to also indicate whether an object is new (nursery) or
+ * not.  Thus nursery objects are identified by a bit in their header, not by
+ * where they lie within the address space.  While Demmers et al. did their work
+ * in a conservative collector, here we have an exact collector, so we can use
+ * a regular write barrier, and don't need to use page protection etc.
+ *
+ * See the PLDI'08 paper by Blackburn and McKinley for a description
+ * of the algorithm: http://doi.acm.org/10.1145/1375581.1375586
+ *
+ * All plans make a clear distinction between <i>global</i> and
+ * <i>thread-local</i> activities, and divides global and local state
+ * into separate class hierarchies.  Global activities must be
+ * synchronized, whereas no synchronization is required for
+ * thread-local activities.  There is a single instance of Plan (or the
+ * appropriate sub-class), and a 1:1 mapping of PlanLocal to "kernel
+ * threads" (aka CPUs or in Jikes RVM, Processors).  Thus instance
+ * methods of PlanLocal allow fast, unsychronized access to functions such as
+ * allocation and collection.
+ *
+ * The global instance defines and manages static resources
+ * (such as memory and virtual memory resources).  This mapping of threads to
+ * instances is crucial to understanding the correctness and
+ * performance properties of MMTk plans.
+ */
+ at Uninterruptible
+public class StickyImmix extends Immix {
+
+  /****************************************************************************
+   * Constants
+   */
+  /** If true, then new PLOS objects are collected at each nursery GC */
+  static final boolean NURSERY_COLLECT_PLOS = true;
+  /** If true then we only do full heap GCs---so we're like MarkSweep (+ write barrier) */
+  static final boolean MAJOR_GC_ONLY = false;
+  /** estimated collection yield */
+  protected static final float SURVIVAL_ESTIMATE = (float) 0.8;
+
+  public static int SCAN_NURSERY = 2;
+
+  /****************************************************************************
+   * Class variables
+   */
+  private static int lastCommittedImmixPages = 0;
+
+  /* statistics */
+  public static BooleanCounter fullHeap = new BooleanCounter("majorGC", true, true);
+
+  /****************************************************************************
+   * Instance variables
+   */
+  /* Remset pool */
+  public final SharedDeque modPool = new SharedDeque("msgen mod objects", metaDataSpace, 1);
+
+  /**
+   * Constructor.
+   *
+   */
+  public StickyImmix() {
+    collectWholeHeap = nextGCWholeHeap = false;
+  }
+
+  /*****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * A user-triggered GC has been initiated.
+   */
+  public void userTriggeredGC() {
+    nextGCWholeHeap |= Options.fullHeapSystemGC.getValue();
+  }
+
+  /**
+   * Force the next collection to be full heap.
+   */
+  @Override
+  public void forceFullHeapCollection() {
+    nextGCWholeHeap = true;
+  }
+
+  /**
+   * Perform a (global) collection phase.
+   *
+   * @param phaseId Collection phase to execute.
+   */
+  @Inline
+  @Override
+  public final void collectionPhase(short phaseId) {
+
+    if (phaseId == SET_COLLECTION_KIND) {
+      collectWholeHeap = requiresFullHeapCollection();
+      if (Stats.gatheringStats() && collectWholeHeap) fullHeap.set();
+      super.collectionPhase(phaseId);
+      return;
+    }
+
+    if (!collectWholeHeap && phaseId == PREPARE) {
+      immixTrace.prepare();
+      immixSpace.prepare(false);
+      return;
+    }
+
+    if (phaseId == RELEASE) {
+      if (collectWholeHeap) {
+        super.collectionPhase(RELEASE);
+      } else {
+        immixTrace.release();
+        lastGCWasDefrag = immixSpace.release(false);
+      }
+      modPool.reset();
+      lastCommittedImmixPages = immixSpace.committedPages();
+      nextGCWholeHeap = (getPagesAvail() < Options.nurserySize.getMinNursery());
+      return;
+    }
+
+    super.collectionPhase(phaseId);
+  }
+
+  /*****************************************************************************
+   *
+   * Accounting
+   */
+
+  /**
+   * This method controls the triggering of a GC. It is called periodically
+   * during allocation. Returns true to trigger a collection.
+   *
+   * @param spaceFull Space request failed, must recover pages within 'space'.
+   * @return True if a collection is requested by the plan.
+   */
+  public final boolean collectionRequired(boolean spaceFull) {
+    boolean nurseryFull = immixSpace.getPagesAllocated() > Options.nurserySize.getMaxNursery();
+    return super.collectionRequired(spaceFull) || nurseryFull;
+  }
+
+  /**
+   * Determine whether this GC should be a full heap collection.
+   *
+   * @return True if this GC should be a full heap collection.
+   */
+  protected boolean requiresFullHeapCollection() {
+    if (collectionTrigger == Collection.EXTERNAL_GC_TRIGGER && Options.fullHeapSystemGC.getValue()) {
+      return true;
+    }
+    if (nextGCWholeHeap || collectionAttempt > 1) {
+      // Forces full heap collection
+      return true;
+    }
+    if (loSpace.allocationFailed()) {
+      // We need space from the nursery
+      return true;
+    }
+
+    // Estimate the yield from small nursery pages
+    int smallNurseryPages = immixSpace.committedPages() - lastCommittedImmixPages;
+    int smallNurseryYield = (int)(smallNurseryPages * SURVIVAL_ESTIMATE);
+
+    if (smallNurseryYield < getPagesRequired()) {
+      // Our total yield is insufficient.
+      return true;
+    }
+
+    if (immixSpace.allocationFailed()) {
+      if (smallNurseryYield < immixSpace.requiredPages()) {
+        // We have run out of VM pages in the nursery
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  /**
+   * Print pre-collection statistics. In this class we prefix the output
+   * indicating whether the collection was full heap or not.
+   */
+  @Override
+  public void printPreStats() {
+    if ((Options.verbose.getValue() >= 1) && (collectWholeHeap))
+      Log.write("[Full heap]");
+    super.printPreStats();
+  }
+
+  /**
+   * @return Is current GC only collecting objects allocated since last GC.
+   */
+  public final boolean isCurrentGCNursery() {
+    return !collectWholeHeap;
+  }
+
+  /**
+   * @return Is last GC a full collection?
+   */
+  public final boolean isLastGCFull() {
+    return collectWholeHeap;
+  }
+
+  /**
+   * Register specialized methods.
+   */
+  @Interruptible
+  protected void registerSpecializedMethods() {
+    TransitiveClosure.registerSpecializedScan(SCAN_NURSERY, StickyImmixNurseryTraceLocal.class);
+    super.registerSpecializedMethods();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixCollector.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixCollector.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixCollector.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixCollector.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,127 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.stickyimmix;
+
+import org.mmtk.plan.*;
+import org.mmtk.plan.immix.Immix;
+import org.mmtk.plan.immix.ImmixCollector;
+import org.mmtk.plan.immix.ImmixDefragTraceLocal;
+import org.mmtk.plan.immix.ImmixTraceLocal;
+import org.mmtk.policy.immix.CollectorLocal;
+import org.mmtk.utility.alloc.ImmixAllocator;
+import org.mmtk.utility.deque.ObjectReferenceDeque;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements <i>per-collector thread</i> behavior
+ * and state for the <i>StickMS</i> plan, which implements a generational
+ * sticky mark bits immix collector.<p>
+ *
+ * Specifically, this class defines <i>StickyMS</i> collection behavior
+ * (through <code>trace</code> and the <code>collectionPhase</code>
+ * method).<p>
+ *
+ * @see StickyImmix for an overview of the algorithm.<p>
+ * @see StickyImmixMutator
+ * @see StopTheWorldCollector
+ * @see CollectorContext
+ * @see Phase
+ */
+ at Uninterruptible
+public class StickyImmixCollector extends ImmixCollector {
+
+  /****************************************************************************
+   * Instance fields
+   */
+  private StickyImmixNurseryTraceLocal nurseryTrace;
+  private final ImmixAllocator nurseryCopy;
+
+  /****************************************************************************
+   * Initialization
+   */
+
+  /**
+   * Constructor
+   */
+  public StickyImmixCollector() {
+    ObjectReferenceDeque modBuffer = new ObjectReferenceDeque("mod buffer", global().modPool);
+    fastTrace = new ImmixTraceLocal(global().immixTrace, modBuffer);
+    defragTrace = new ImmixDefragTraceLocal(global().immixTrace, modBuffer);
+    nurseryTrace = new StickyImmixNurseryTraceLocal(global().immixTrace, modBuffer);
+    immix = new CollectorLocal(StickyImmix.immixSpace);
+    nurseryCopy = new ImmixAllocator(Immix.immixSpace, true, true);
+  }
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a per-collector collection phase.
+   *
+   * @param phaseId The collection phase to perform
+   * @param primary Perform any single-threaded activities using this thread.
+   */
+  @Inline
+  public final void collectionPhase(short phaseId, boolean primary) {
+    boolean collectWholeHeap = global().collectWholeHeap;
+
+    if (phaseId == StickyImmix.PREPARE) {
+      global().modPool.prepareNonBlocking();  /* always do this */
+    }
+
+    if (!collectWholeHeap) {
+      if (phaseId == StickyImmix.PREPARE) {
+        currentTrace = (TraceLocal) nurseryTrace;
+        immix.prepare(false);
+        nurseryTrace.prepare();
+        nurseryCopy.reset();
+        copy.reset();
+        return;
+      }
+
+      if (phaseId == StickyImmix.ROOTS) {
+        VM.scanning.computeStaticRoots(currentTrace);
+        VM.scanning.computeGlobalRoots(currentTrace);
+        return;
+      }
+
+      if (phaseId == StickyImmix.CLOSURE) {
+        nurseryTrace.completeTrace();
+        return;
+      }
+
+      if (phaseId == StickyImmix.RELEASE) {
+        nurseryTrace.release();
+        immix.release(false);
+        global().modPool.reset();
+        return;
+      }
+    }
+
+    super.collectionPhase(phaseId, primary);
+  }
+
+  /****************************************************************************
+   *
+   * Miscellaneous
+   */
+
+  /** @return The active global plan as an <code>StickyImmix</code> instance. */
+  private static StickyImmix global() {
+    return (StickyImmix) VM.activePlan.global();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixConstraints.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixConstraints.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixConstraints.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixConstraints.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,55 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.stickyimmix;
+
+import static org.mmtk.policy.immix.ImmixConstants.MAX_IMMIX_OBJECT_BYTES;
+
+import org.mmtk.plan.immix.ImmixConstraints;
+
+import org.mmtk.policy.MarkSweepSpace;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.Word;
+
+/**
+ * This class and its subclasses communicate to the host VM/Runtime
+ * any features of the selected plan that it needs to know.  This is
+ * separate from the main Plan/PlanLocal class in order to bypass any
+ * issues with ordering of static initialization.
+ */
+ at Uninterruptible
+public class StickyImmixConstraints extends ImmixConstraints {
+  /** @return The number of specialized scans.  We need nursery & full heap. */
+  @Override
+  public int numSpecializedScans() { return 3; }
+
+  /** @return True if this plan requires a write barrier */
+  @Override
+  public boolean needsWriteBarrier() { return true; }
+
+  /** @return True if this Plan requires a header bit for object logging */
+  @Override
+  public boolean needsLogBitInHeader() { return true; }
+
+  /** @return A bit which represents that a header is unlogged */
+  @Override
+  public Word unloggedBit() {return MarkSweepSpace.UNLOGGED_BIT; }
+
+  /** @return Size (in bytes) beyond which new regular objects must be allocated to the LOS */
+  @Override
+  public int maxNonLOSDefaultAllocBytes() { return MAX_IMMIX_OBJECT_BYTES; }
+
+  /** @return Size (in bytes) beyond which copied objects must be copied to the LOS */
+  @Override
+  public int maxNonLOSCopyBytes() { return MAX_IMMIX_OBJECT_BYTES; }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixMutator.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixMutator.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixMutator.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixMutator.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,201 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.stickyimmix;
+
+import org.mmtk.plan.*;
+import org.mmtk.plan.immix.ImmixMutator;
+
+import org.mmtk.utility.deque.ObjectReferenceDeque;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements <i>per-mutator thread</i> behavior
+ * and state for the <i>StickyImmix</i> plan, which implements a
+ * generational mark-sweep collector.<p>
+ *
+ * Specifically, this class defines <i>MS</i> mutator-time allocation
+ * and per-mutator thread collection semantics (flushing and restoring
+ * per-mutator allocator state).<p>
+ * *
+ * @see StickyImmix
+ * @see StickyImmixCollector
+ * @see MutatorContext
+ * @see Phase
+ */
+ at Uninterruptible
+public class StickyImmixMutator extends ImmixMutator {
+
+  /****************************************************************************
+   * Instance fields
+   */
+
+  private ObjectReferenceDeque modBuffer;
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * Constructor
+   */
+  public StickyImmixMutator() {
+    super();
+    modBuffer = new ObjectReferenceDeque("mod buf", global().modPool);
+  }
+
+  /****************************************************************************
+   *
+   * Barriers
+   */
+
+  /**
+   * A new reference is about to be created.  Take appropriate write
+   * barrier actions.<p>
+   *
+   * In this case, we remember the address of the source of the
+   * pointer if the new reference points into the nursery from
+   * non-nursery space.
+   *
+   * @param src The object into which the new reference will be stored
+   * @param slot The address into which the new reference will be
+   * stored.
+   * @param tgt The target of the new reference
+   * @param metaDataA A value that assists the host VM in creating a store
+   * @param metaDataB A value that assists the host VM in creating a store
+   * @param mode The mode of the store (eg putfield, putstatic etc)
+   */
+  @Inline
+  public final void writeBarrier(ObjectReference src, Address slot,
+      ObjectReference tgt, Word metaDataA, Word metaDataB, int mode) {
+    if (Plan.logRequired(src))
+      logSource(src);
+    VM.barriers.performWriteInBarrier(src, slot, tgt, metaDataA, metaDataB, mode);
+  }
+
+  /**
+   * A number of references are about to be copied from object
+   * <code>src</code> to object <code>dst</code> (as in an array
+   * copy).  Thus, <code>dst</code> is the mutated object.  Take
+   * appropriate write barrier actions.<p>
+   *
+   * In this case, we remember the mutated source address range and
+   * will scan that address range at GC time.
+   *
+   * @param src The source of the values to copied
+   * @param srcOffset The offset of the first source address, in
+   * bytes, relative to <code>src</code> (in principle, this could be
+   * negative).
+   * @param dst The mutated object, i.e. the destination of the copy.
+   * @param dstOffset The offset of the first destination address, in
+   * bytes relative to <code>tgt</code> (in principle, this could be
+   * negative).
+   * @param bytes The size of the region being copied, in bytes.
+   * @return True if the update was performed by the barrier, false if
+   * left to the caller (always false in this case).
+   */
+  @Inline
+  public final boolean writeBarrier(ObjectReference src, Offset srcOffset,
+      ObjectReference dst, Offset dstOffset, int bytes) {
+    if (Plan.logRequired(src))
+      logSource(src);
+    return false;
+  }
+
+  /**
+   * Add an object to the modified objects buffer and mark the
+   * object has having been logged.  Since duplicate entries do
+   * not raise any correctness issues, we do <i>not</i> worry
+   * about synchronization and allow threads to race to log the
+   * object, potentially including it twice (unlike reference
+   * counting where duplicates would lead to incorrect reference
+   * counts).
+   *
+   * @param src The object to be logged
+   */
+  private void logSource(ObjectReference src) {
+   Plan.markAsLogged(src);
+   modBuffer.push(src);
+  }
+
+  /**
+   * Flush per-mutator remembered sets into the global remset pool.
+   */
+  public final void flushRememberedSets() {
+    modBuffer.flushLocal();
+    assertRemsetFlushed();
+  }
+
+  /**
+   * Assert that the remsets have been flushed.  This is critical to
+   * correctness.  We need to maintain the invariant that remset entries
+   * do not accrue during GC.  If the host JVM generates barrier entires
+   * it is its own responsibility to ensure that they are flushed before
+   * returning to MMTk.
+   */
+  public final void assertRemsetFlushed() {
+    if (VM.VERIFY_ASSERTIONS) {
+      VM.assertions._assert(modBuffer.isFlushed());
+    }
+  }
+
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a per-mutator collection phase.
+   *
+   * @param phaseId The collection phase to perform
+   * @param primary Perform any single-threaded activities using this thread.
+   */
+  @Inline
+  public final void collectionPhase(short phaseId, boolean primary) {
+    if (phaseId == StickyImmix.PREPARE) {
+      flushRememberedSets();
+    }
+    if (phaseId == StickyImmix.RELEASE) {
+      assertRemsetFlushed();
+    }
+
+    if (!global().collectWholeHeap) {
+      if (phaseId == StickyImmix.PREPARE) {
+        immix.prepare();
+        return;
+      }
+
+      if (phaseId == StickyImmix.RELEASE) {
+        immix.release();
+        return;
+      }
+    }
+
+    super.collectionPhase(phaseId, primary);
+  }
+
+  /****************************************************************************
+   *
+   * Miscellaneous
+   */
+
+  /** @return The active global plan as an <code>MSGen</code> instance. */
+  @Inline
+  private static StickyImmix global() {
+    return (StickyImmix) VM.activePlan.global();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixNurseryTraceLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixNurseryTraceLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixNurseryTraceLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyimmix/StickyImmixNurseryTraceLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,143 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.stickyimmix;
+
+import static org.mmtk.policy.immix.ImmixConstants.MARK_LINE_AT_SCAN_TIME;
+import static org.mmtk.policy.immix.ImmixConstants.TMP_PREFER_COPY_ON_NURSERY_GC;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.plan.Trace;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.deque.ObjectReferenceDeque;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements the thread-local functionality for a transitive
+ * closure over a sticky-immix space.
+ */
+ at Uninterruptible
+public final class StickyImmixNurseryTraceLocal extends TraceLocal {
+
+  /****************************************************************************
+  *
+  * Instance fields.
+  */
+ private final ObjectReferenceDeque modBuffer;
+
+  /**
+   * Constructor
+   */
+  public StickyImmixNurseryTraceLocal(Trace trace, ObjectReferenceDeque modBuffer) {
+    super(StickyImmix.SCAN_NURSERY, trace);
+    this.modBuffer = modBuffer;
+  }
+
+  /****************************************************************************
+   *
+   * Externally visible Object processing and tracing
+   */
+
+  /**
+   * Is the specified object live?
+   *
+   * @param object The object.
+   * @return True if the object is live.
+   */
+  public boolean isLive(ObjectReference object) {
+    if (object.isNull()) return false;
+    if (Space.isInSpace(StickyImmix.IMMIX, object))
+      return TMP_PREFER_COPY_ON_NURSERY_GC ? StickyImmix.immixSpace.copyNurseryIsLive(object) : StickyImmix.immixSpace.fastIsLive(object);
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(super.isLive(object));
+    return true;
+  }
+
+  /**
+   * This method is the core method during the trace of the object graph.
+   * The role of this method is to:
+   *
+   * 1. Ensure the traced object is not collected.
+   * 2. If this is the first visit to the object enqueue it to be scanned.
+   * 3. Return the forwarded reference to the object.
+   *
+   * In this instance, we refer objects in the mark-sweep space to the
+   * msSpace for tracing, and defer to the superclass for all others.
+   *
+   * @param object The object to be traced.
+   * @return The new reference to the same object instance.
+   */
+  @Inline
+  public ObjectReference traceObject(ObjectReference object) {
+    if (object.isNull()) return object;
+    if (Space.isInSpace(StickyImmix.IMMIX, object))
+      return StickyImmix.immixSpace.nurseryTraceObject(this, object, StickyImmix.ALLOC_DEFAULT);
+    else
+      return object;
+  }
+
+  /**
+   * Return true if this object is guaranteed not to move during this
+   * collection (i.e. this object is definitely not an unforwarded
+   * object).
+   *
+   * @param object
+   * @return True if this object is guaranteed not to move during this
+   *         collection.
+   */
+  @Override
+  public boolean willNotMoveInCurrentCollection(ObjectReference object) {
+    if (Space.isInSpace(StickyImmix.IMMIX, object)) {
+      if (!TMP_PREFER_COPY_ON_NURSERY_GC)
+        return true;
+      else
+        return StickyImmix.immixSpace.willNotMoveThisNurseryGC(object);
+    }
+    return super.willNotMoveInCurrentCollection(object);
+  }
+
+  /**
+   * Collectors that move objects <b>must</b> override this method.
+   * It performs the deferred scanning of objects which are forwarded
+   * during bootstrap of each copying collection.  Because of the
+   * complexities of the collection bootstrap (such objects are
+   * generally themselves gc-critical), the forwarding and scanning of
+   * the objects must be dislocated.  It is an error for a non-moving
+   * collector to call this method.
+   *
+   * @param object The forwarded object to be scanned
+   */
+  @Inline
+  @Override
+  protected void scanObject(ObjectReference object) {
+    super.scanObject(object);
+    if (MARK_LINE_AT_SCAN_TIME && Space.isInSpace(StickyImmix.IMMIX, object))
+      StickyImmix.immixSpace.markLines(object);
+  }
+
+  /**
+   * Process any remembered set entries.  This means enumerating the
+   * mod buffer and for each entry, marking the object as unlogged
+   * and enqueing it for scanning.
+   */
+  protected void processRememberedSets() {
+    logMessage(2, "processing modBuffer");
+    while (!modBuffer.isEmpty()) {
+      ObjectReference src = modBuffer.pop();
+      Plan.markAsUnlogged(src);
+      processNode(src);
+    }
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMS.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMS.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMS.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMS.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,206 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.stickyms;
+
+import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.plan.marksweep.MS;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.Log;
+import org.mmtk.utility.deque.SharedDeque;
+import org.mmtk.utility.options.Options;
+import org.mmtk.utility.sanitychecker.SanityChecker;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.ObjectReference;
+
+/**
+ * This class implements the global state of a simple sticky mark bits collector,
+ * based a simple on mark-sweep collector.  The sticky mark bits algorithm is
+ * due to Demmers et al. (http://doi.acm.org/10.1145/96709.96735), and allows
+ * generational collection to be performed in a non-moving heap by overloading
+ * the role of mark bits to also indicate whether an object is new (nursery) or
+ * not.  Thus nursery objects are identified by a bit in their header, not by
+ * where they lie within the address space.  While Demmers et al. did their work
+ * in a conservative collector, here we have an exact collector, so we can use
+ * a regular write barrier, and don't need to use page protection etc.
+ *
+ * All plans make a clear distinction between <i>global</i> and
+ * <i>thread-local</i> activities, and divides global and local state
+ * into separate class hierarchies.  Global activities must be
+ * synchronized, whereas no synchronization is required for
+ * thread-local activities.  There is a single instance of Plan (or the
+ * appropriate sub-class), and a 1:1 mapping of PlanLocal to "kernel
+ * threads" (aka CPUs or in Jikes RVM, Processors).  Thus instance
+ * methods of PlanLocal allow fast, unsychronized access to functions such as
+ * allocation and collection.
+ *
+ * The global instance defines and manages static resources
+ * (such as memory and virtual memory resources).  This mapping of threads to
+ * instances is crucial to understanding the correctness and
+ * performance properties of MMTk plans.
+ */
+ at Uninterruptible
+public class StickyMS extends MS {
+
+  /****************************************************************************
+   * Constants
+   */
+  /** If true, then new PLOS objects are collected at each nursery GC */
+  static final boolean NURSERY_COLLECT_PLOS = true;
+  /** If true then we only do full heap GCs---so we're like MarkSweep (+ write barrier) */
+  static final boolean MAJOR_GC_ONLY = false;
+
+  /****************************************************************************
+   * Class variables
+   */
+
+  public static int SCAN_NURSERY = 1;
+
+  /****************************************************************************
+   * Instance variables
+   */
+  /* status fields */
+  /** will the next collection collect the whole heap? */
+  public boolean nextGCWholeHeap = false;
+  /** will this collection collect the whole heap */
+  public boolean collectWholeHeap = nextGCWholeHeap;
+
+  /* Remset pool */
+  public final SharedDeque modPool = new SharedDeque("msgen mod objects", metaDataSpace, 1);
+
+  /****************************************************************************
+   * Static initialization
+   */
+  {
+    msSpace.isAgeSegregatedSpace();  /* this space is to be collected generationally */
+  }
+
+  /*****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * A user-triggered GC has been initiated.
+   */
+  public void userTriggeredGC() {
+    nextGCWholeHeap |= Options.fullHeapSystemGC.getValue();
+  }
+
+  /**
+   * Force the next collection to be full heap.
+   */
+  @Override
+  public void forceFullHeapCollection() {
+    nextGCWholeHeap = true;
+  }
+
+  /**
+   * Perform a (global) collection phase.
+   *
+   * @param phaseId Collection phase to execute.
+   */
+  @Inline
+  @Override
+  public final void collectionPhase(short phaseId) {
+
+    if (phaseId == INITIATE) {
+      collectWholeHeap = MAJOR_GC_ONLY || emergencyCollection || nextGCWholeHeap;
+      nextGCWholeHeap = false;
+      super.collectionPhase(phaseId);
+      return;
+    }
+
+    if (!collectWholeHeap) {
+      if (phaseId == PREPARE) {
+        msTrace.prepare();
+        msSpace.prepare(false);
+        return;
+      }
+
+      if (phaseId == RELEASE) {
+        msTrace.release();
+        msSpace.release();
+        modPool.reset();
+        nextGCWholeHeap = (getPagesAvail() < Options.nurserySize.getMinNursery());
+        return;
+      }
+    }
+
+    super.collectionPhase(phaseId);
+  }
+
+  /*****************************************************************************
+   *
+   * Accounting
+   */
+
+  /**
+   * Print pre-collection statistics. In this class we prefix the output
+   * indicating whether the collection was full heap or not.
+   */
+  @Override
+  public void printPreStats() {
+    if ((Options.verbose.getValue() >= 1) && (collectWholeHeap))
+      Log.write("[Full heap]");
+    super.printPreStats();
+  }
+
+  /**
+   * @return Is current GC only collecting objects allocated since last GC.
+   */
+  public final boolean isCurrentGCNursery() {
+    return !collectWholeHeap;
+  }
+
+  /**
+   * @return Is last GC a full collection?
+   */
+  public final boolean isLastGCFull() {
+    return collectWholeHeap;
+  }
+
+  /**
+   * Return the expected reference count. For non-reference counting
+   * collectors this becomes a true/false relationship.
+   * @param object The object to check.
+   * @param sanityRootRC The number of root references to the object.
+   *
+   * @return The expected (root excluded) reference count.
+   */
+  public int sanityExpectedRC(ObjectReference object, int sanityRootRC) {
+    Space space = Space.getSpaceForObject(object);
+
+    // Immortal spaces
+    if (space == StickyMS.immortalSpace || space == StickyMS.vmSpace) {
+      return space.isReachable(object) ? SanityChecker.ALIVE : SanityChecker.DEAD;
+    }
+
+    // Mature space (nursery collection)
+    if (VM.activePlan.global().isCurrentGCNursery() && space != StickyMS.msSpace) {
+      return SanityChecker.UNSURE;
+    }
+
+    return super.sanityExpectedRC(object, sanityRootRC);
+  }
+
+  /**
+   * Register specialized methods.
+   */
+  @Interruptible
+  protected void registerSpecializedMethods() {
+    TransitiveClosure.registerSpecializedScan(SCAN_NURSERY, StickyMSNurseryTraceLocal.class);
+    super.registerSpecializedMethods();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSCollector.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSCollector.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSCollector.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSCollector.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,116 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.stickyms;
+
+import org.mmtk.plan.*;
+import org.mmtk.plan.marksweep.MSCollector;
+import org.mmtk.plan.marksweep.MSTraceLocal;
+import org.mmtk.utility.deque.ObjectReferenceDeque;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements <i>per-collector thread</i> behavior
+ * and state for the <i>StickMS</i> plan, which implements a generational
+ * sticky mark bits mark-sweep collector.<p>
+ *
+ * Specifically, this class defines <i>StickyMS</i> collection behavior
+ * (through <code>trace</code> and the <code>collectionPhase</code>
+ * method).<p>
+ *
+ * @see StickyMS for an overview of the algorithm.<p>
+ * @see StickyMSMutator
+ * @see StopTheWorldCollector
+ * @see CollectorContext
+ * @see Phase
+ */
+ at Uninterruptible
+public class StickyMSCollector extends MSCollector {
+
+  /****************************************************************************
+   * Instance fields
+   */
+  private StickyMSNurseryTraceLocal nurseryTrace;
+
+  /****************************************************************************
+   * Initialization
+   */
+
+  /**
+   * Constructor
+   */
+  public StickyMSCollector() {
+    ObjectReferenceDeque modBuffer = new ObjectReferenceDeque("mod buffer", global().modPool);
+    fullTrace = new  MSTraceLocal(global().msTrace, modBuffer);
+    nurseryTrace = new StickyMSNurseryTraceLocal(global().msTrace, modBuffer);
+  }
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a per-collector collection phase.
+   *
+   * @param phaseId The collection phase to perform
+   * @param primary Perform any single-threaded activities using this thread.
+   */
+  @Inline
+  public final void collectionPhase(short phaseId, boolean primary) {
+    boolean collectWholeHeap = global().collectWholeHeap;
+
+    if (phaseId == StickyMS.PREPARE) {
+      currentTrace = collectWholeHeap ? (TraceLocal) fullTrace : (TraceLocal) nurseryTrace;
+      global().modPool.prepareNonBlocking();  /* always do this */
+    }
+
+    if (!collectWholeHeap) {
+      if (phaseId == StickyMS.PREPARE) {
+        nurseryTrace.prepare();
+        return;
+      }
+
+      if (phaseId == StickyMS.ROOTS) {
+        VM.scanning.computeStaticRoots(currentTrace);
+        VM.scanning.computeGlobalRoots(currentTrace);
+        return;
+      }
+
+      if (phaseId == StickyMS.CLOSURE) {
+        nurseryTrace.completeTrace();
+        return;
+      }
+
+      if (phaseId == StickyMS.RELEASE) {
+        nurseryTrace.release();
+        global().modPool.reset();
+        return;
+      }
+    }
+
+    super.collectionPhase(phaseId, primary);
+  }
+
+  /****************************************************************************
+   *
+   * Miscellaneous
+   */
+
+  /** @return The active global plan as an <code>MS</code> instance. */
+  @Inline
+  private static StickyMS global() {
+    return (StickyMS) VM.activePlan.global();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSConstraints.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSConstraints.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSConstraints.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSConstraints.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,48 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.stickyms;
+
+import org.mmtk.plan.marksweep.MSConstraints;
+
+import org.mmtk.policy.MarkSweepSpace;
+import org.mmtk.policy.SegregatedFreeListSpace;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.Word;
+
+/**
+ * This class and its subclasses communicate to the host VM/Runtime
+ * any features of the selected plan that it needs to know.  This is
+ * separate from the main Plan/PlanLocal class in order to bypass any
+ * issues with ordering of static initialization.
+ */
+ at Uninterruptible
+public class StickyMSConstraints extends MSConstraints {
+  /** @return The number of specialized scans.  We need nursery & full heap. */
+  @Override
+  public int numSpecializedScans() { return 2; }
+
+  /** @return True if this plan requires a write barrier */
+  @Override
+  public boolean needsWriteBarrier() { return true; }
+
+  /** @return True if this Plan requires a header bit for object logging */
+  @Override
+  public boolean needsLogBitInHeader() { return true; }
+
+  /** @return A bit which represents that a header is unlogged */
+  @Override
+  public Word unloggedBit() {return MarkSweepSpace.UNLOGGED_BIT; }
+  @Override
+  public int maxNonLOSDefaultAllocBytes() { return SegregatedFreeListSpace.MAX_FREELIST_OBJECT_BYTES; }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSMutator.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSMutator.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSMutator.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSMutator.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,213 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.stickyms;
+
+import org.mmtk.plan.*;
+import org.mmtk.plan.marksweep.MSMutator;
+import org.mmtk.policy.MarkSweepLocal;
+
+import org.mmtk.utility.deque.ObjectReferenceDeque;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements <i>per-mutator thread</i> behavior
+ * and state for the <i>StickyMS</i> plan, which implements a
+ * generational mark-sweep collector.<p>
+ *
+ * Specifically, this class defines <i>MS</i> mutator-time allocation
+ * and per-mutator thread collection semantics (flushing and restoring
+ * per-mutator allocator state).<p>
+ * *
+ * @see StickyMS
+ * @see StickyMSCollector
+ * @see MutatorContext
+ * @see Phase
+ */
+ at Uninterruptible
+public class StickyMSMutator extends MSMutator {
+
+  /****************************************************************************
+   * Instance fields
+   */
+
+  private ObjectReferenceDeque modBuffer;
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * Constructor
+   */
+  public StickyMSMutator() {
+    ms = new MarkSweepLocal(StickyMS.msSpace);
+    modBuffer = new ObjectReferenceDeque("mod buf", global().modPool);
+  }
+
+  /****************************************************************************
+   *
+   * Barriers
+   */
+
+  /**
+   * A new reference is about to be created.  Take appropriate write
+   * barrier actions.<p>
+   *
+   * In this case, we remember the address of the source of the
+   * pointer if the new reference points into the nursery from
+   * non-nursery space.
+   *
+   * @param src The object into which the new reference will be stored
+   * @param slot The address into which the new reference will be
+   * stored.
+   * @param tgt The target of the new reference
+   * @param metaDataA A value that assists the host VM in creating a store
+   * @param metaDataB A value that assists the host VM in creating a store
+   * @param mode The mode of the store (eg putfield, putstatic etc)
+   */
+  @Inline
+  public final void writeBarrier(ObjectReference src, Address slot,
+      ObjectReference tgt, Word metaDataA, Word metaDataB, int mode) {
+    if (Plan.logRequired(src))
+      logSource(src);
+    VM.barriers.performWriteInBarrier(src, slot, tgt, metaDataA, metaDataB, mode);
+  }
+
+  /**
+   * A number of references are about to be copied from object
+   * <code>src</code> to object <code>dst</code> (as in an array
+   * copy).  Thus, <code>dst</code> is the mutated object.  Take
+   * appropriate write barrier actions.<p>
+   *
+   * In this case, we remember the mutated source address range and
+   * will scan that address range at GC time.
+   *
+   * @param src The source of the values to copied
+   * @param srcOffset The offset of the first source address, in
+   * bytes, relative to <code>src</code> (in principle, this could be
+   * negative).
+   * @param dst The mutated object, i.e. the destination of the copy.
+   * @param dstOffset The offset of the first destination address, in
+   * bytes relative to <code>tgt</code> (in principle, this could be
+   * negative).
+   * @param bytes The size of the region being copied, in bytes.
+   * @return True if the update was performed by the barrier, false if
+   * left to the caller (always false in this case).
+   */
+  @Inline
+  public final boolean writeBarrier(ObjectReference src, Offset srcOffset,
+      ObjectReference dst, Offset dstOffset, int bytes) {
+    if (Plan.logRequired(src))
+      logSource(src);
+    return false;
+  }
+
+  /**
+   * Add an object to the modified objects buffer and mark the
+   * object has having been logged.  Since duplicate entries do
+   * not raise any correctness issues, we do <i>not</i> worry
+   * about synchronization and allow threads to race to log the
+   * object, potentially including it twice (unlike reference
+   * counting where duplicates would lead to incorrect reference
+   * counts).
+   *
+   * @param src The object to be logged
+   */
+  private void logSource(ObjectReference src) {
+   Plan.markAsLogged(src);
+   modBuffer.push(src);
+  }
+
+  /**
+   * Flush per-mutator remembered sets into the global remset pool.
+   */
+  public final void flushRememberedSets() {
+    modBuffer.flushLocal();
+    assertRemsetFlushed();
+  }
+
+  /**
+   * Assert that the remsets have been flushed.  This is critical to
+   * correctness.  We need to maintain the invariant that remset entries
+   * do not accrue during GC.  If the host JVM generates barrier entires
+   * it is its own responsibility to ensure that they are flushed before
+   * returning to MMTk.
+   */
+  public final void assertRemsetFlushed() {
+    if (VM.VERIFY_ASSERTIONS) {
+      VM.assertions._assert(modBuffer.isFlushed());
+    }
+  }
+
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Perform a per-mutator collection phase.
+   *
+   * @param phaseId The collection phase to perform
+   * @param primary Perform any single-threaded activities using this thread.
+   */
+  @Inline
+  public final void collectionPhase(short phaseId, boolean primary) {
+    if (phaseId == StickyMS.PREPARE) {
+      flushRememberedSets();
+    }
+    if (phaseId == StickyMS.RELEASE) {
+      assertRemsetFlushed();
+    }
+
+    if (!global().collectWholeHeap) {
+      if (phaseId == StickyMS.PREPARE) {
+        ms.prepare();
+        return;
+      }
+
+      if (phaseId == StickyMS.RELEASE) {
+        ms.release();
+        return;
+      }
+    }
+
+    super.collectionPhase(phaseId, primary);
+  }
+
+
+  /**
+   * Flush mutator context, in response to a requestMutatorFlush.
+   * Also called by the default implementation of deinitMutator.
+   */
+  @Override
+  public void flush() {
+    super.flush();
+    ms.flush();
+  }
+
+  /****************************************************************************
+   *
+   * Miscellaneous
+   */
+
+  /** @return The active global plan as an <code>MSGen</code> instance. */
+  @Inline
+  private static StickyMS global() {
+    return (StickyMS) VM.activePlan.global();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSNurseryTraceLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSNurseryTraceLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSNurseryTraceLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/plan/stickyms/StickyMSNurseryTraceLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,101 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.plan.stickyms;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.plan.Trace;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.deque.ObjectReferenceDeque;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements the thread-local functionality for a transitive
+ * closure over a mark-sweep space.
+ */
+ at Uninterruptible
+public final class StickyMSNurseryTraceLocal extends TraceLocal {
+
+  /****************************************************************************
+  *
+  * Instance fields.
+  */
+ private final ObjectReferenceDeque modBuffer;
+
+  /**
+   * Constructor
+   */
+  public StickyMSNurseryTraceLocal(Trace trace, ObjectReferenceDeque modBuffer) {
+    super(StickyMS.SCAN_NURSERY, trace);
+    this.modBuffer = modBuffer;
+  }
+
+  /****************************************************************************
+   *
+   * Externally visible Object processing and tracing
+   */
+
+  /**
+   * Is the specified object live?
+   *
+   * @param object The object.
+   * @return True if the object is live.
+   */
+  public boolean isLive(ObjectReference object) {
+    if (object.isNull()) return false;
+    if (Space.isInSpace(StickyMS.MARK_SWEEP, object))
+      return StickyMS.msSpace.isLive(object);
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(super.isLive(object));
+    return true;
+  }
+
+  /**
+   * This method is the core method during the trace of the object graph.
+   * The role of this method is to:
+   *
+   * 1. Ensure the traced object is not collected.
+   * 2. If this is the first visit to the object enqueue it to be scanned.
+   * 3. Return the forwarded reference to the object.
+   *
+   * In this instance, we refer objects in the mark-sweep space to the
+   * msSpace for tracing, and defer to the superclass for all others.
+   *
+   * @param object The object to be traced.
+   * @return The new reference to the same object instance.
+   */
+  @Inline
+  public ObjectReference traceObject(ObjectReference object) {
+    if (object.isNull()) return object;
+    if (Space.isInSpace(StickyMS.MARK_SWEEP, object))
+      return StickyMS.msSpace.traceObject(this, object);
+    else
+      return object;
+  }
+
+  /**
+   * Process any remembered set entries.  This means enumerating the
+   * mod buffer and for each entry, marking the object as unlogged
+   * and enqueing it for scanning.
+   */
+  protected void processRememberedSets() {
+    logMessage(2, "processing modBuffer");
+    while (!modBuffer.isEmpty()) {
+      ObjectReference src = modBuffer.pop();
+      Plan.markAsUnlogged(src);
+      processNode(src);
+    }
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/BaseLargeObjectSpace.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/BaseLargeObjectSpace.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/policy/BaseLargeObjectSpace.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/BaseLargeObjectSpace.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,126 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.policy;
+
+import org.mmtk.utility.heap.FreeListPageResource;
+import org.mmtk.utility.heap.VMRequest;
+import org.mmtk.utility.Constants;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * Each instance of this class corresponds to one treadmill *space*.
+ *
+ * Each of the instance methods of this class may be called by any
+ * thread (i.e. synchronization must be explicit in any instance or
+ * class method).
+ *
+ * This stands in contrast to TreadmillLocal, which is instantiated
+ * and called on a per-thread basis, where each instance of
+ * TreadmillLocal corresponds to one thread operating over one space.
+ */
+ at Uninterruptible
+public abstract class BaseLargeObjectSpace extends Space implements Constants {
+
+  /****************************************************************************
+   *
+   * Class variables
+   */
+  protected static final Word PAGE_MASK = Word.fromIntSignExtend(~(BYTES_IN_PAGE - 1));
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * The caller specifies the region of virtual memory to be used for
+   * this space.  If this region conflicts with an existing space,
+   * then the constructor will fail.
+   *
+   * @param name The name of this space (used when printing error messages etc)
+   * @param pageBudget The number of pages this space may consume
+   * before consulting the plan
+   * @param vmRequest An object describing the virtual memory requested.
+   */
+  public BaseLargeObjectSpace(String name, int pageBudget, VMRequest vmRequest) {
+    super(name, false, false, vmRequest);
+    if (vmRequest.isDiscontiguous()) {
+      pr = new FreeListPageResource(pageBudget, this, 0);
+    } else {
+      pr = new FreeListPageResource(pageBudget, this, start, extent);
+    }
+  }
+
+  /**
+   * Calculate the header size required for the large object.
+   *
+   * Must be multiple of MIN_ALIGNMENT.
+   */
+  public final int getHeaderSize() {
+    return superPageHeaderSize() + cellHeaderSize();
+  }
+
+  /****************************************************************************
+   *
+   * Freeing
+   */
+
+  /**
+   * Free a cell.  If the cell is large (own superpage) then release
+   * the superpage, if not add to the super page's free list and if
+   * all cells on the superpage are free, then release the
+   * superpage.
+   *
+   * @param cell The address of the first byte of the cell to be freed
+   */
+  @Inline
+  public final void free(Address cell) {
+    release(getSuperPage(cell));
+  }
+
+  /****************************************************************************
+   *
+   * Superpages
+   */
+
+  protected abstract int superPageHeaderSize();
+  protected abstract int cellHeaderSize();
+
+  /**
+   * Return the superpage for a given cell.  If the cell is a small
+   * cell then this is found by masking the cell address to find the
+   * containing page.  Otherwise the first word of the cell contains
+   * the address of the page.
+   *
+   * @param cell The address of the first word of the cell (exclusive
+   * of any sub-class specific metadata).
+   * @return The address of the first word of the superpage containing
+   *         <code>cell</code>.
+   */
+  @Inline
+  public static Address getSuperPage(Address cell) {
+    return cell.toWord().and(PAGE_MASK).toAddress();
+  }
+
+  /**
+   * Return the size of the super page
+   *
+   * @param first the Address of the first word in the superpage
+   * @return the size in bytes
+   */
+  public Extent getSize(Address first) {
+    return ((FreeListPageResource) pr).getSize(first);
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/CopyLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/CopyLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/policy/CopyLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/CopyLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,44 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.policy;
+
+import org.mmtk.utility.alloc.BumpPointer;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements unsynchronized (local) elements of a
+ * copying collector. Allocation is via the bump pointer
+ * (@see BumpPointer).
+ *
+ * @see BumpPointer
+ * @see CopySpace
+ */
+ at Uninterruptible public final class CopyLocal extends BumpPointer {
+
+  /**
+   * Constructor
+   *
+   * @param space The space to bump point into.
+   */
+  public CopyLocal(CopySpace space) {
+    super(space, true);
+  }
+
+  /**
+   * Constructor
+   */
+  public CopyLocal() {
+    super(null, true);
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/CopySpace.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/CopySpace.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/policy/CopySpace.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/CopySpace.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,407 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.policy;
+
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.utility.heap.*;
+import org.mmtk.utility.options.Options;
+import org.mmtk.utility.Constants;
+import org.mmtk.utility.Log;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements tracing functionality for a simple copying
+ * space.  Since no state needs to be held globally or locally, all
+ * methods are static.
+ */
+ at Uninterruptible public final class CopySpace extends Space
+  implements Constants {
+
+  /****************************************************************************
+   *
+   * Class variables
+   */
+  public static final int LOCAL_GC_BITS_REQUIRED = 2;
+  public static final int GLOBAL_GC_BITS_REQUIRED = 0;
+  public static final int GC_HEADER_WORDS_REQUIRED = 0;
+
+  private static final int META_DATA_PAGES_PER_REGION = CARD_META_PAGES_PER_REGION;
+
+  /*
+   *  The forwarding process uses three states to deal with a GC race:
+   *  1.      !GC_FORWARDED: Unforwarded
+   *  2. GC_BEING_FORWARDED: Being forwarded (forwarding is underway)
+   *  3.       GC_FORWARDED: Forwarded
+   */
+  /** If this bit is set, then forwarding of this object has commenced */
+  private static final Word GC_FORWARDED = Word.one().lsh(1); // ...10
+  /** If this bit is set, then forwarding of this object is incomplete */
+  private static final Word GC_BEING_FORWARDED  = Word.one().lsh(2).minus(Word.one());  // ...11
+  /** This mask is used to reveal which state this object is in with respect to forwarding */
+  private static final Word GC_FORWARDING_MASK  = GC_FORWARDED.or(GC_BEING_FORWARDED);
+
+  /** A single bit is used to indicate a mark when tracing (but not copying) the space */
+  private static final Word GC_MARK_BIT_MASK = Word.one();
+
+  /****************************************************************************
+   *
+   * Instance variables
+   */
+  private boolean fromSpace = true;
+
+  public boolean isFromSpace() {
+    return fromSpace;
+  }
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * The caller specifies the region of virtual memory to be used for
+   * this space.  If this region conflicts with an existing space,
+   * then the constructor will fail.
+   *
+   * @param name The name of this space (used when printing error messages etc)
+   * @param pageBudget The number of pages this space may consume
+   * before consulting the plan
+   * @param fromSpace The does this instance start life as from-space
+   * (or to-space)?
+   * @param vmRequest An object describing the virtual memory requested.
+   */
+  public CopySpace(String name, int pageBudget, boolean fromSpace, VMRequest vmRequest) {
+    super(name, true, false, vmRequest);
+    this.fromSpace = fromSpace;
+    if (vmRequest.isDiscontiguous()) {
+      pr = new MonotonePageResource(pageBudget, this, META_DATA_PAGES_PER_REGION);
+    } else {
+      pr = new MonotonePageResource(pageBudget, this, start, extent, META_DATA_PAGES_PER_REGION);
+    }
+  }
+
+  /****************************************************************************
+   *
+   * Prepare and release
+   */
+
+  /**
+   * Prepare this space instance for a collection.  Set the
+   * "fromSpace" field according to whether this space is the
+   * source or target of the collection.
+   *
+   * @param fromSpace Set the fromSpace field to this value
+   */
+  public void prepare(boolean fromSpace) { this.fromSpace = fromSpace; }
+
+  /**
+   * Release this copy space after a collection.  This means releasing
+   * all pages associated with this (now empty) space.
+   */
+  public void release() {
+    ((MonotonePageResource) pr).reset();
+    lastDiscontiguousRegion = Address.zero();
+    fromSpace = false;
+  }
+
+  /**
+   * Release an allocated page or pages.  In this case we do nothing
+   * because we only release pages enmasse.
+   *
+   * @param start The address of the start of the page or pages
+   */
+  @Inline
+  public void release(Address start) {
+    if (VM.VERIFY_ASSERTIONS)
+      VM.assertions._assert(false); // this policy only releases pages enmasse
+  }
+
+  /****************************************************************************
+   *
+   * Tracing and forwarding
+   */
+
+  /**
+   * Trace an object under a copying collection policy.
+   *
+   * We use a tri-state algorithm to deal with races to forward
+   * the object.  The tracer must wait if the object is concurrently
+   * being forwarded by another thread.
+   *
+   * If the object is already forwarded, the copy is returned.
+   * Otherwise, the object is forwarded and the copy is returned.
+   *
+   * @param trace The trace being conducted.
+   * @param object The object to be forwarded.
+   * @return The forwarded object.
+   */
+  @Inline
+  public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object) {
+    VM.assertions.fail("CopySpace.traceLocal called without allocator");
+    return ObjectReference.nullReference();
+  }
+
+  /**
+   * Trace an object under a copying collection policy.
+   *
+   * We use a tri-state algorithm to deal with races to forward
+   * the object.  The tracer must wait if the object is concurrently
+   * being forwarded by another thread.
+   *
+   * If the object is already forwarded, the copy is returned.
+   * Otherwise, the object is forwarded and the copy is returned.
+   *
+   * @param trace The trace being conducted.
+   * @param object The object to be forwarded.
+   * @param allocator The allocator to use when copying.
+   * @return The forwarded object.
+   */
+  @Inline
+  public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object, int allocator) {
+    /* If the object in question is already in to-space, then do nothing */
+    if (!fromSpace) return object;
+
+    /* Try to forward the object */
+    Word forwardingPtr = attemptToForward(object);
+
+    if (stateIsForwardedOrBeingForwarded(forwardingPtr)) {
+      /* Somebody else got to it first. */
+
+      /* We must wait (spin) if the object is not yet fully forwarded */
+      while (stateIsBeingForwarded(forwardingPtr))
+        forwardingPtr = getForwardingWord(object);
+
+      /* Now extract the object reference from the forwarding word and return it */
+      return forwardingPtr.and(GC_FORWARDING_MASK.not()).toAddress().toObjectReference();
+    } else {
+      /* We are the designated copier, so forward it and enqueue it */
+      ObjectReference newObject = VM.objectModel.copy(object, allocator);
+      setForwardingPointer(object, newObject);
+      trace.processNode(newObject); // Scan it later
+
+      if (VM.VERIFY_ASSERTIONS && Options.verbose.getValue() >= 9) {
+        Log.write("C["); Log.write(object); Log.write("/");
+        Log.write(getName()); Log.write("] -> ");
+        Log.write(newObject); Log.write("/");
+        Log.write(Space.getSpaceForObject(newObject).getName());
+        Log.writeln("]");
+      }
+      return newObject;
+    }
+  }
+
+  /**
+   * Return true if this object is live in this GC
+   *
+   * @param object The object in question
+   * @return True if this object is live in this GC (has it been forwarded?)
+   */
+  public boolean isLive(ObjectReference object) {
+    return isForwarded(object);
+  }
+
+  /**
+   * Has the object in this space been reached during the current collection.
+   * This is used for GC Tracing.
+   *
+   * @param object The object reference.
+   * @return True if the object is reachable.
+   */
+  public boolean isReachable(ObjectReference object) {
+    return !fromSpace || isForwarded(object);
+  }
+
+  /****************************************************************************
+   *
+   * Non-copying tracing (just mark, don't forward)
+   */
+
+  /**
+   * Mark an object as having been traversed, *WITHOUT* forwarding the object.
+   * This is only used when
+   *
+   * @param object The object to be marked
+   * @param markState The sense of the mark bit (flips from 0 to 1)
+   */
+  @Inline
+  public static void markObject(TraceLocal trace, ObjectReference object,
+      Word markState) {
+    if (testAndMark(object, markState))
+      trace.processNode(object);
+  }
+
+  /****************************************************************************
+   *
+   * Header manipulation
+   */
+
+  /**
+   * Perform any required post-allocation initialization
+   *
+   * <i>Nothing to be done in this case</i>
+   *
+   * @param object the object ref to the storage to be initialized
+   */
+   @Inline
+   public void postAlloc(ObjectReference object) {}
+
+  /**
+   * Clear the GC portion of the header for an object.
+   *
+   * @param object the object ref to the storage to be initialized
+   */
+  @Inline
+  public static void clearGCBits(ObjectReference object) {
+    Word header = VM.objectModel.readAvailableBitsWord(object);
+    VM.objectModel.writeAvailableBitsWord(object, header.and(GC_FORWARDING_MASK.not()));
+  }
+
+  /**
+   * Has an object been forwarded?
+   *
+   * @param object The object to be checked
+   * @return True if the object has been forwarded
+   */
+  @Inline
+  public static boolean isForwarded(ObjectReference object) {
+    return stateIsForwarded(getForwardingWord(object));
+  }
+
+  /**
+   * Has an object been forwarded or being forwarded?
+   *
+   * @param object The object to be checked
+   * @return True if the object has been forwarded or is being forwarded
+   */
+  @Inline
+  public static boolean isForwardedOrBeingForwarded(ObjectReference object) {
+    return stateIsForwardedOrBeingForwarded(getForwardingWord(object));
+  }
+
+  /**
+   * Non-atomic read of forwarding pointer word
+   *
+   * @param object The object whose forwarding word is to be read
+   * @return The forwarding word stored in <code>object</code>'s
+   * header.
+   */
+  @Inline
+  private static Word getForwardingWord(ObjectReference object) {
+    return VM.objectModel.readAvailableBitsWord(object);
+  }
+
+  /**
+   * Non-atomic read of forwarding pointer
+   *
+   * @param object The object whose forwarding pointer is to be read
+   * @return The forwarding pointer stored in <code>object</code>'s
+   * header.
+   */
+  @Inline
+  public static ObjectReference getForwardingPointer(ObjectReference object) {
+    return getForwardingWord(object).and(GC_FORWARDING_MASK.not()).toAddress().toObjectReference();
+  }
+
+  /**
+   * Used to mark boot image objects during a parallel scan of objects
+   * during GC Returns true if marking was done.
+   *
+   * @param object The object to be marked
+   * @param value The value to store in the mark bit
+   */
+  @Inline
+  private static boolean testAndMark(ObjectReference object, Word value) {
+    Word oldValue;
+    do {
+      oldValue = VM.objectModel.prepareAvailableBits(object);
+      Word markBit = oldValue.and(GC_MARK_BIT_MASK);
+      if (markBit.EQ(value)) return false;
+    } while (!VM.objectModel.attemptAvailableBits(object, oldValue,
+                                                oldValue.xor(GC_MARK_BIT_MASK)));
+    return true;
+  }
+
+  /**
+   * Either return the forwarding pointer if the object is already
+   * forwarded (or being forwarded) or write the bit pattern that
+   * indicates that the object is being forwarded
+   *
+   * @param object The object to be forwarded
+   * @return The forwarding pointer for the object if it has already
+   * been forwarded.
+   */
+  @Inline
+  private static Word attemptToForward(ObjectReference object) {
+    Word oldValue;
+    do {
+      oldValue = VM.objectModel.prepareAvailableBits(object);
+      if (oldValue.and(GC_FORWARDING_MASK).EQ(GC_FORWARDED)) return oldValue;
+    } while (!VM.objectModel.attemptAvailableBits(object, oldValue,
+                                                oldValue.or(GC_BEING_FORWARDED)));
+    return oldValue;
+  }
+
+  /**
+   * Is the state of the forwarding word being forwarded?
+   *
+   * @param fword A forwarding word.
+   * @return True if the forwarding word's state is being forwarded.
+   */
+  @Inline
+  private static boolean stateIsBeingForwarded(Word fword) {
+    return fword.and(GC_FORWARDING_MASK).EQ(GC_BEING_FORWARDED);
+  }
+
+  /**
+   * Is the state of the forwarding word forwarded?
+   *
+   * @param fword A forwarding word.
+   * @return True if the forwarding word's state is forwarded.
+   */
+  @Inline
+  private static boolean stateIsForwarded(Word fword) {
+    return fword.and(GC_FORWARDING_MASK).EQ(GC_FORWARDED);
+  }
+
+  /**
+   * Is the state of the forwarding word forwarded or being forwarded?
+   *
+   * @param fword A forwarding word.
+   * @return True if the forwarding word's state is forwarded or being
+   *         forwarded.
+   */
+  @Inline
+  public static boolean stateIsForwardedOrBeingForwarded(Word fword) {
+    return !(fword.and(GC_FORWARDED).isZero());
+  }
+
+  /**
+   * Non-atomic write of forwarding pointer word (assumption, thread
+   * doing the set has done attempt to forward and owns the right to
+   * copy the object)
+   *
+   * @param object The object whose forwarding pointer is to be set
+   * @param ptr The forwarding pointer to be stored in the object's
+   * forwarding word
+   */
+  @Inline
+  private static void setForwardingPointer(ObjectReference object,
+                                           ObjectReference ptr) {
+    VM.objectModel.writeAvailableBitsWord(object, ptr.toAddress().toWord().or(GC_FORWARDED));
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitFreeListLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitFreeListLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitFreeListLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitFreeListLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,77 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.policy;
+
+import org.mmtk.utility.alloc.SegregatedFreeListLocal;
+import org.mmtk.utility.Constants;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements unsynchronized (local) elements of an
+ * explicity managed collector.  Allocation is via the segregated free list
+ * (@see org.mmtk.utility.alloc.SegregatedFreeList).<p>
+ *
+ * @see org.mmtk.utility.alloc.SegregatedFreeList
+ * @see ExplicitFreeListSpace
+ */
+ at Uninterruptible
+public final class ExplicitFreeListLocal extends SegregatedFreeListLocal<ExplicitFreeListSpace> implements Constants {
+
+  /****************************************************************************
+   *
+   * Class variables
+   */
+
+  /****************************************************************************
+   *
+   * Instance variables
+   */
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * Constructor
+   *
+   * @param space The rc space to which this allocator
+   * instances is bound.
+   */
+  public ExplicitFreeListLocal(ExplicitFreeListSpace space) {
+    super(space);
+  }
+
+  /****************************************************************************
+   *
+   * Allocation
+   */
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Prepare for a collection. If paranoid, perform a sanity check.
+   */
+  public void prepare() {
+    flush();
+  }
+
+  /**
+   * Finish up after a collection.
+   */
+  public void release() {}
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitFreeListSpace.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitFreeListSpace.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitFreeListSpace.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitFreeListSpace.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,175 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.policy;
+
+import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.utility.heap.*;
+import org.mmtk.utility.Constants;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * Each instance of this class corresponds to one *space*.
+ * Each of the instance methods of this class may be called by any
+ * thread (i.e. synchronization must be explicit in any instance or
+ * class method).  This contrasts with the MarkSweepLocal, where
+ * instances correspond to *plan* instances and therefore to kernel
+ * threads.  Thus unlike this class, synchronization is not necessary
+ * in the instance methods of MarkSweepLocal.
+ */
+ at Uninterruptible
+public final class ExplicitFreeListSpace extends SegregatedFreeListSpace implements Constants {
+
+  /****************************************************************************
+   *
+   * Class variables
+   */
+  public static final int LOCAL_GC_BITS_REQUIRED = 0;
+  public static final int GLOBAL_GC_BITS_REQUIRED = 0;
+  public static final int GC_HEADER_WORDS_REQUIRED = 0;
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * The caller specifies the region of virtual memory to be used for
+   * this space.  If this region conflicts with an existing space,
+   * then the constructor will fail.
+   *
+   * @param name The name of this space (used when printing error messages etc)
+   * @param pageBudget The number of pages this space may consume
+   * before consulting the plan
+   * @param vmRequest An object describing the virtual memory requested.
+   */
+  public ExplicitFreeListSpace(String name, int pageBudget, VMRequest vmRequest) {
+    super(name, pageBudget, 0, vmRequest);
+  }
+
+  /**
+   * Should SegregatedFreeListSpace manage a side bitmap to keep track of live objects?
+   */
+  @Inline
+  protected boolean maintainSideBitmap() {
+    return true;
+  }
+
+  /**
+   * Do we need to preserve free lists as we move blocks around.
+   */
+  @Inline
+  protected boolean preserveFreeList() {
+    return false;
+  }
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Prepare the next block in the free block list for use by the free
+   * list allocator.  In the case of lazy sweeping this involves
+   * sweeping the available cells.  <b>The sweeping operation must
+   * ensure that cells are pre-zeroed</b>, as this method must return
+   * pre-zeroed cells.
+   *
+   * @param block The block to be prepared for use
+   * @param sizeClass The size class of the block
+   * @return The address of the first pre-zeroed cell in the free list
+   * for this block, or zero if there are no available cells.
+   */
+  protected Address advanceToBlock(Address block, int sizeClass) {
+    return makeFreeList(block, sizeClass);
+  }
+
+  /**
+   * Notify that a new block has been installed. This is to ensure that
+   * appropriate collection state can be initialized for the block
+   *
+   * @param block The new block
+   * @param sizeClass The block's sizeclass.
+   */
+  protected void notifyNewBlock(Address block, int sizeClass) {
+    clearLiveBits(block, sizeClass);
+  }
+
+  /**
+   * Free an object.
+   *
+   * @param object The object to be freed.
+   */
+  @Inline
+  public void free(ObjectReference object) {
+    clearLiveBit(object);
+  }
+
+  /**
+   * Prepare for a new collection increment.
+   */
+  public void prepare() {
+    flushAvailableBlocks();
+  }
+
+  /**
+   * A new collection increment has completed.
+   */
+  public void release() {
+    sweepConsumedBlocks(true);
+  }
+
+  /**
+   * Release an allocated page or pages
+   *
+   * @param start The address of the start of the page or pages
+   */
+  @Inline
+  public void release(Address start) {
+    ((FreeListPageResource) pr).releasePages(start);
+  }
+
+  /****************************************************************************
+   *
+   * Object processing and tracing
+   */
+
+  /**
+   * Trace a reference to an object under a mark sweep collection
+   * policy.  If the object header is not already marked, mark the
+   * object in either the bitmap or by moving it off the treadmill,
+   * and enqueue the object for subsequent processing. The object is
+   * marked as (an atomic) side-effect of checking whether already
+   * marked.
+   *
+   * @param object The object to be traced.
+   * @return The object (there is no object forwarding in this
+   * collector, so we always return the same object: this could be a
+   * void method but for compliance to a more general interface).
+   */
+  @Inline
+  public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object) {
+    return object;
+  }
+
+  /**
+   *
+   * @param object The object in question
+   * @return True if this object is known to be live (i.e. it is marked)
+   */
+  @Inline
+  public boolean isLive(ObjectReference object) {
+    return liveBitSet(object);
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitLargeObjectSpace.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitLargeObjectSpace.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitLargeObjectSpace.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/ExplicitLargeObjectSpace.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,193 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.policy;
+
+import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.utility.heap.FreeListPageResource;
+import org.mmtk.utility.heap.VMRequest;
+import org.mmtk.utility.DoublyLinkedList;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * Each instance of this class corresponds to one explicitly managed
+ * large object space.
+ */
+ at Uninterruptible
+public final class ExplicitLargeObjectSpace extends BaseLargeObjectSpace {
+
+  /****************************************************************************
+   *
+   * Instance variables
+   */
+  private final DoublyLinkedList cells;
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * The caller specifies the region of virtual memory to be used for
+   * this space.  If this region conflicts with an existing space,
+   * then the constructor will fail.
+   *
+   * @param name The name of this space (used when printing error messages etc)
+   * @param pageBudget The number of pages this space may consume
+   * before consulting the plan
+   * @param vmRequest An object describing the virtual memory requested.
+   */
+  public ExplicitLargeObjectSpace(String name, int pageBudget, VMRequest vmRequest) {
+    super(name, pageBudget, vmRequest);
+    cells = new DoublyLinkedList(LOG_BYTES_IN_PAGE, true);
+  }
+
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Prepare for a new collection increment.
+   */
+  public void prepare() {
+  }
+
+  /**
+   * A new collection increment has completed.
+   */
+  public void release() {
+  }
+
+  /**
+   * Release a group of pages that were allocated together.
+   *
+   * @param first The first page in the group of pages that were
+   * allocated together.
+   */
+  @Inline
+  public void release(Address first) {
+    ((FreeListPageResource) pr).releasePages(first);
+  }
+
+  /**
+   * Perform any required initialization of the GC portion of the header.
+   *
+   * @param object the object ref to the storage to be initialized
+   * @param alloc is this initialization occuring due to (initial) allocation
+   * (true) or due to copying (false)?
+   */
+  @Inline
+  public void initializeHeader(ObjectReference object, boolean alloc) {
+    Address cell = VM.objectModel.objectStartRef(object);
+    cells.add(DoublyLinkedList.midPayloadToNode(cell));
+  }
+
+  /****************************************************************************
+   *
+   * Object processing and tracing
+   */
+
+  /**
+   * Trace a reference to an object under a mark sweep collection
+   * policy.  If the object header is not already marked, mark the
+   * object in either the bitmap or by moving it off the treadmill,
+   * and enqueue the object for subsequent processing. The object is
+   * marked as (an atomic) side-effect of checking whether already
+   * marked.
+   *
+   * @param trace The trace being conducted.
+   * @param object The object to be traced.
+   * @return The object (there is no object forwarding in this
+   * collector, so we always return the same object: this could be a
+   * void method but for compliance to a more general interface).
+   */
+  @Inline
+  public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object) {
+    return object;
+  }
+
+  /**
+   * @param object The object in question
+   * @return True if this object is known to be live (i.e. it is marked)
+   */
+  @Inline
+  public boolean isLive(ObjectReference object) {
+    return true;
+  }
+
+  /**
+   * Return the size of the per-superpage header required by this
+   * system.  In this case it is just the underlying superpage header
+   * size.
+   *
+   * @return The size of the per-superpage header required by this
+   * system.
+   */
+  @Inline
+  protected int superPageHeaderSize() {
+    return DoublyLinkedList.headerSize();
+  }
+
+  /**
+   * Return the size of the per-cell header for cells of a given class
+   * size.
+   *
+   * @return The size of the per-cell header for cells of a given class
+   * size.
+   */
+  @Inline
+  protected int cellHeaderSize() { return 0; }
+
+  /**
+   * Sweep through all the objects in this space.
+   *
+   * @param sweeper The sweeper callback to use.
+   */
+  @Inline
+  public void sweep(Sweeper sweeper) {
+    Address cell = cells.getHead();
+    while (!cell.isZero()) {
+      Address next = cells.getNext(cell);
+      ObjectReference obj = VM.objectModel.getObjectFromStartAddress(cell.plus(DoublyLinkedList.headerSize()));
+      if (sweeper.sweepLargeObject(obj)) {
+        free(obj);
+      }
+      cell = next;
+    }
+  }
+
+  /**
+   * Free an object
+   *
+   * @param object The object to be freed.
+   */
+  @Inline
+  public void free(ObjectReference object) {
+    Address cell = getSuperPage(VM.objectModel.refToAddress(object));
+    cells.remove(cell);
+    release(cell);
+  }
+
+  /**
+   * A callback used to perform sweeping of the large object space.
+   */
+  @Uninterruptible
+  public abstract static class Sweeper {
+    public abstract boolean sweepLargeObject(ObjectReference object);
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/ImmortalLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/ImmortalLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/policy/ImmortalLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/ImmortalLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,37 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.policy;
+
+import org.mmtk.utility.alloc.BumpPointer;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements unsynchronized (local) elements of an
+ * immortal space. Allocation is via the bump pointer
+ * (@see BumpPointer).
+ *
+ * @see BumpPointer
+ * @see ImmortalSpace
+ */
+ at Uninterruptible public final class ImmortalLocal extends BumpPointer {
+
+  /**
+   * Constructor
+   *
+   * @param space The space to bump point into.
+   */
+  public ImmortalLocal(ImmortalSpace space) {
+    super(space, true);
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/ImmortalSpace.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/ImmortalSpace.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/policy/ImmortalSpace.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/ImmortalSpace.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,171 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.policy;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.utility.heap.MonotonePageResource;
+import org.mmtk.utility.heap.VMRequest;
+import org.mmtk.utility.Constants;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements tracing for a simple immortal collection
+ * policy.  Under this policy all that is required is for the
+ * "collector" to propogate marks in a liveness trace.  It does not
+ * actually collect.  This class does not hold any state, all methods
+ * are static.
+ */
+ at Uninterruptible public final class ImmortalSpace extends Space
+  implements Constants {
+
+  /****************************************************************************
+   *
+   * Class variables
+   */
+  static final Word GC_MARK_BIT_MASK = Word.one();
+  private static final int META_DATA_PAGES_PER_REGION = CARD_META_PAGES_PER_REGION;
+
+  /****************************************************************************
+   *
+   * Instance variables
+   */
+  private Word markState = Word.zero(); // when GC off, the initialization value
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+  /**
+   * The caller specifies the region of virtual memory to be used for
+   * this space.  If this region conflicts with an existing space,
+   * then the constructor will fail.
+   *
+   * @param name The name of this space (used when printing error messages etc)
+   * @param pageBudget The number of pages this space may consume
+   * before consulting the plan
+   * @param vmRequest An object describing the virtual memory requested.
+   */
+  public ImmortalSpace(String name, int pageBudget, VMRequest vmRequest) {
+    super(name, false, true, vmRequest);
+    if (vmRequest.isDiscontiguous()) {
+      pr = new MonotonePageResource(pageBudget, this, META_DATA_PAGES_PER_REGION);
+    } else {
+      pr = new MonotonePageResource(pageBudget, this, start, extent, META_DATA_PAGES_PER_REGION);
+    }
+  }
+
+  /** @return the current mark state */
+  @Inline
+  public Word getMarkState() { return markState; }
+
+  /****************************************************************************
+   *
+   * Object header manipulations
+   */
+
+  /**
+   * Initialize the object header post-allocation.  We need to set the mark state
+   * correctly and set the logged bit if necessary.
+   *
+   * @param object The newly allocated object instance whose header we are initializing
+   */
+  public void initializeHeader(ObjectReference object) {
+    Word oldValue = VM.objectModel.readAvailableBitsWord(object);
+    Word newValue = oldValue.and(GC_MARK_BIT_MASK.not()).or(markState);
+    if (Plan.NEEDS_LOG_BIT_IN_HEADER) newValue = newValue.or(Plan.UNLOGGED_BIT);
+    VM.objectModel.writeAvailableBitsWord(object, newValue);
+  }
+
+  /**
+   * Used to mark boot image objects during a parallel scan of objects during GC
+   * Returns true if marking was done.
+   */
+  @Inline
+  private static boolean testAndMark(ObjectReference object, Word value) {
+    Word oldValue;
+    do {
+      oldValue = VM.objectModel.prepareAvailableBits(object);
+      Word markBit = oldValue.and(GC_MARK_BIT_MASK);
+      if (markBit.EQ(value)) return false;
+    } while (!VM.objectModel.attemptAvailableBits(object, oldValue,
+                                               oldValue.xor(GC_MARK_BIT_MASK)));
+    return true;
+  }
+
+  /**
+   * Trace a reference to an object under an immortal collection
+   * policy.  If the object is not already marked, enqueue the object
+   * for subsequent processing. The object is marked as (an atomic)
+   * side-effect of checking whether already marked.
+   *
+   * @param trace The trace being conducted.
+   * @param object The object to be traced.
+   */
+  @Inline
+  public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object) {
+    if (testAndMark(object, markState))
+      trace.processNode(object);
+    return object;
+  }
+
+  /**
+   * Prepare for a new collection increment.  For the immortal
+   * collector we must flip the state of the mark bit between
+   * collections.
+   */
+  public void prepare() {
+    markState = GC_MARK_BIT_MASK.minus(markState);
+  }
+
+  public void release() {}
+
+  /**
+   * Release an allocated page or pages.  In this case we do nothing
+   * because we only release pages enmasse.
+   *
+   * @param start The address of the start of the page or pages
+   */
+  @Inline
+  public void release(Address start) {
+    if (VM.VERIFY_ASSERTIONS)
+      VM.assertions._assert(false); // this policy only releases pages enmasse
+  }
+
+  @Inline
+  public boolean isLive(ObjectReference object) {
+    return true;
+  }
+
+  /**
+   * Returns if the object in question is currently thought to be reachable.
+   * This is done by comparing the mark bit to the current mark state. For the
+   * immortal collector reachable and live are different, making this method
+   * necessary.
+   *
+   * @param object The address of an object in immortal space to test
+   * @return True if <code>ref</code> may be a reachable object (e.g., having
+   *         the current mark state).  While all immortal objects are live,
+   *         some may be unreachable.
+   */
+  public boolean isReachable(ObjectReference object) {
+    if (Plan.SCAN_BOOT_IMAGE && this == Plan.vmSpace)
+      return true;  // ignore boot image "reachabilty" if we're not tracing it
+    else
+      return (VM.objectModel.readAvailableBitsWord(object).and(GC_MARK_BIT_MASK).EQ(markState));
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/LargeObjectLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/LargeObjectLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/policy/LargeObjectLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/LargeObjectLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,110 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.policy;
+
+import org.mmtk.utility.alloc.LargeObjectAllocator;
+import org.mmtk.utility.gcspy.drivers.TreadmillDriver;
+import org.mmtk.utility.Constants;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * Each instance of this class is intended to provide fast,
+ * unsynchronized access to a treadmill.  Therefore instances must not
+ * be shared across truely concurrent threads (CPUs).  Rather, one or
+ * more instances of this class should be bound to each CPU.  The
+ * shared VMResource used by each instance is the point of global
+ * synchronization, and synchronization only occurs at the granularity
+ * of aquiring (and releasing) chunks of memory from the VMResource.
+ *
+ * If there are C CPUs and T TreadmillSpaces, there must be C X T
+ * instances of this class, one for each CPU, TreadmillSpace pair.
+ */
+ at Uninterruptible
+public final class LargeObjectLocal extends LargeObjectAllocator implements Constants {
+
+  /****************************************************************************
+   *
+   * Class variables
+   */
+
+  /****************************************************************************
+   *
+   * Instance variables
+   */
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * Constructor
+   *
+   * @param space The treadmill space to which this thread instance is
+   * bound.
+   */
+  public LargeObjectLocal(BaseLargeObjectSpace space) {
+    super(space);
+  }
+
+  /****************************************************************************
+   *
+   * Allocation
+   */
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Prepare for a collection.  Clear the treadmill to-space head and
+   * prepare the collector.  If paranoid, perform a sanity check.
+   */
+  public void prepare(boolean fullHeap) {
+  }
+
+  /**
+   * Finish up after a collection.
+   */
+  public void release(boolean fullHeap) {
+  }
+
+  /****************************************************************************
+   *
+   * Miscellaneous size-related methods
+   */
+
+  /**
+   * Gather data for GCSpy from the nursery
+   * @param event the gc event
+   * @param losDriver the GCSpy space driver
+   */
+  public void gcspyGatherData(int event, TreadmillDriver losDriver) {
+    // TODO: assumes single threaded
+    // TODO: assumes non-explit LOS
+    ((LargeObjectSpace)space).getTreadmill().gcspyGatherData(event, losDriver);
+  }
+
+  /**
+   * Gather data for GCSpy for an older space
+   * @param event the gc event
+   * @param losDriver the GCSpy space driver
+   * @param tospace gather from tospace?
+   */
+  public void gcspyGatherData(int event, TreadmillDriver losDriver, boolean tospace) {
+    // TODO: assumes single threaded
+    ((LargeObjectSpace)space).getTreadmill().gcspyGatherData(event, losDriver, tospace);
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/LargeObjectSpace.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/LargeObjectSpace.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/policy/LargeObjectSpace.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/LargeObjectSpace.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,284 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.policy;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.utility.heap.FreeListPageResource;
+import org.mmtk.utility.heap.VMRequest;
+import org.mmtk.utility.Treadmill;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * Each instance of this class corresponds to one explicitly managed
+ * large object space.
+ */
+ at Uninterruptible
+public final class LargeObjectSpace extends BaseLargeObjectSpace {
+
+  /****************************************************************************
+   *
+   * Class variables
+   */
+  public static final int LOCAL_GC_BITS_REQUIRED = 2;
+  public static final int GLOBAL_GC_BITS_REQUIRED = 0;
+  private static final Word MARK_BIT = Word.one(); // ...01
+  private static final Word NURSERY_BIT = Word.fromIntZeroExtend(2); // ...10
+  private static final Word LOS_BIT_MASK = Word.fromIntZeroExtend(3); // ...11
+
+  /****************************************************************************
+   *
+   * Instance variables
+   */
+  private Word markState;
+  private boolean inNurseryGC;
+  private final Treadmill treadmill;
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * The caller specifies the region of virtual memory to be used for
+   * this space.  If this region conflicts with an existing space,
+   * then the constructor will fail.
+   *
+   * @param name The name of this space (used when printing error messages etc)
+   * @param pageBudget The number of pages this space may consume
+   * before consulting the plan
+   * @param vmRequest An object describing the virtual memory requested.
+   */
+  public LargeObjectSpace(String name, int pageBudget, VMRequest vmRequest) {
+    super(name, pageBudget, vmRequest);
+    treadmill = new Treadmill(LOG_BYTES_IN_PAGE, true);
+    markState = Word.zero();
+  }
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Prepare for a new collection increment.  For the mark-sweep
+   * collector we must flip the state of the mark bit between
+   * collections.
+   */
+  public void prepare(boolean fullHeap) {
+    if (fullHeap) {
+      if (VM.VERIFY_ASSERTIONS) {
+        VM.assertions._assert(treadmill.fromSpaceEmpty());
+      }
+      markState = MARK_BIT.minus(markState);
+    }
+    treadmill.flip(fullHeap);
+    inNurseryGC = !fullHeap;
+  }
+
+  /**
+   * A new collection increment has completed.  For the mark-sweep
+   * collector this means we can perform the sweep phase.
+   */
+  public void release(boolean fullHeap) {
+    // sweep the large objects
+    sweepLargePages(true);                // sweep the nursery
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(treadmill.nurseryEmpty());
+    if (fullHeap) sweepLargePages(false); // sweep the mature space
+  }
+
+  /**
+   * Sweep through the large pages, releasing all superpages on the
+   * "from space" treadmill.
+   */
+  private void sweepLargePages(boolean sweepNursery) {
+    while (true) {
+      Address cell = sweepNursery ? treadmill.popNursery() : treadmill.pop();
+      if (cell.isZero()) break;
+      release(getSuperPage(cell));
+    }
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(sweepNursery ? treadmill.nurseryEmpty() : treadmill.fromSpaceEmpty());
+  }
+
+  /**
+   * Release a group of pages that were allocated together.
+   *
+   * @param first The first page in the group of pages that were
+   * allocated together.
+   */
+  @Inline
+  public void release(Address first) {
+    ((FreeListPageResource) pr).releasePages(first);
+  }
+
+  /****************************************************************************
+   *
+   * Object processing and tracing
+   */
+
+  /**
+   * Trace a reference to an object under a mark sweep collection
+   * policy.  If the object header is not already marked, mark the
+   * object in either the bitmap or by moving it off the treadmill,
+   * and enqueue the object for subsequent processing. The object is
+   * marked as (an atomic) side-effect of checking whether already
+   * marked.
+   *
+   * @param trace The trace being conducted.
+   * @param object The object to be traced.
+   * @return The object (there is no object forwarding in this
+   * collector, so we always return the same object: this could be a
+   * void method but for compliance to a more general interface).
+   */
+  @Inline
+  public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object) {
+    boolean nurseryObject = isInNursery(object);
+    if (!inNurseryGC || nurseryObject) {
+      if (testAndMark(object, markState)) {
+        internalMarkObject(object, nurseryObject);
+        trace.processNode(object);
+      }
+    }
+    return object;
+  }
+
+  /**
+   * @param object The object in question
+   * @return True if this object is known to be live (i.e. it is marked)
+   */
+   @Inline
+   public boolean isLive(ObjectReference object) {
+    return testMarkBit(object, markState);
+  }
+
+  /**
+   * An object has been marked (identifiged as live).  Large objects
+   * are added to the to-space treadmill, while all other objects will
+   * have a mark bit set in the superpage header.
+   *
+   * @param object The object which has been marked.
+   */
+  @Inline
+  private void internalMarkObject(ObjectReference object, boolean nurseryObject) {
+
+    Address cell = VM.objectModel.objectStartRef(object);
+    Address node = Treadmill.midPayloadToNode(cell);
+    treadmill.copy(node, nurseryObject);
+  }
+
+  /****************************************************************************
+   *
+   * Header manipulation
+   */
+
+  /**
+   * Perform any required initialization of the GC portion of the header.
+   *
+   * @param object the object ref to the storage to be initialized
+   * @param alloc is this initialization occuring due to (initial) allocation
+   * (true) or due to copying (false)?
+   */
+  @Inline
+  public void initializeHeader(ObjectReference object, boolean alloc) {
+    Word oldValue = VM.objectModel.readAvailableBitsWord(object);
+    Word newValue = oldValue.and(LOS_BIT_MASK.not()).or(markState);
+    if (alloc) newValue = newValue.or(NURSERY_BIT);
+    if (Plan.NEEDS_LOG_BIT_IN_HEADER) newValue = newValue.or(Plan.UNLOGGED_BIT);
+    VM.objectModel.writeAvailableBitsWord(object, newValue);
+    Address cell = VM.objectModel.objectStartRef(object);
+    treadmill.addToTreadmill(Treadmill.midPayloadToNode(cell), alloc);
+  }
+
+  /**
+   * Atomically attempt to set the mark bit of an object.  Return true
+   * if successful, false if the mark bit was already set.
+   *
+   * @param object The object whose mark bit is to be written
+   * @param value The value to which the mark bit will be set
+   */
+  @Inline
+  private boolean testAndMark(ObjectReference object, Word value) {
+    Word oldValue, markBit;
+    do {
+      oldValue = VM.objectModel.prepareAvailableBits(object);
+      markBit = oldValue.and(inNurseryGC ? LOS_BIT_MASK : MARK_BIT);
+      if (markBit.EQ(value)) return false;
+    } while (!VM.objectModel.attemptAvailableBits(object, oldValue,
+                                                  oldValue.and(LOS_BIT_MASK.not()).or(value)));
+    return true;
+  }
+
+  /**
+   * Return true if the mark bit for an object has the given value.
+   *
+   * @param object The object whose mark bit is to be tested
+   * @param value The value against which the mark bit will be tested
+   * @return True if the mark bit for the object has the given value.
+   */
+  @Inline
+  private boolean testMarkBit(ObjectReference object, Word value) {
+    return VM.objectModel.readAvailableBitsWord(object).and(MARK_BIT).EQ(value);
+  }
+
+  /**
+   * Return true if the object is in the logical nursery
+   *
+   * @param object The object whose status is to be tested
+   * @return True if the object is in the logical nursery
+   */
+  @Inline
+  private boolean isInNursery(ObjectReference object) {
+     return VM.objectModel.readAvailableBitsWord(object).and(NURSERY_BIT).EQ(NURSERY_BIT);
+  }
+
+  /**
+   * Return the size of the per-superpage header required by this
+   * system.  In this case it is just the underlying superpage header
+   * size.
+   *
+   * @return The size of the per-superpage header required by this
+   * system.
+   */
+  @Inline
+  protected int superPageHeaderSize() {
+    return Treadmill.headerSize();
+  }
+
+  /**
+   * Return the size of the per-cell header for cells of a given class
+   * size.
+   *
+   * @return The size of the per-cell header for cells of a given class
+   * size.
+   */
+  @Inline
+  protected int cellHeaderSize() {
+    return 0;
+  }
+
+  /**
+   * This is the treadmill used by the large object space.
+   *
+   * Note that it depends on the specific local in use whether this
+   * is being used.
+   *
+   * @return The treadmill associated with this large object space.
+   */
+  public Treadmill getTreadmill() {
+    return this.treadmill;
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkCompactLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkCompactLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkCompactLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkCompactLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,210 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.policy;
+
+import org.mmtk.plan.markcompact.MC;
+import org.mmtk.utility.Conversions;
+import org.mmtk.utility.alloc.Allocator;
+import org.mmtk.utility.alloc.BumpPointer;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.Address;
+import org.vmmagic.unboxed.Extent;
+import org.vmmagic.unboxed.ObjectReference;
+
+/**
+ * This class implements unsynchronized (local) elements of a
+ * sliding mark-compact collector. Allocation is via the bump pointer
+ * (@see BumpPointer).
+ *
+ * @see BumpPointer
+ * @see MarkCompactSpace
+ */
+ at Uninterruptible public final class MarkCompactLocal extends BumpPointer {
+
+  /**
+   * Constructor
+   *
+   * @param space The space to bump point into.
+   */
+  public MarkCompactLocal(MarkCompactSpace space) {
+    super(space, true);
+  }
+
+  /**
+   * Perform the compacting phase of the collection.
+   */
+  public void compact() {
+    /* Has this allocator ever allocated anything? */
+    if (initialRegion.isZero()) return;
+
+    /* Loop through active regions or until the last region */
+    Address start = initialRegion;
+    Address allocStart = initialRegion;
+    Address allocEnd = initialRegion.plus(REGION_LIMIT_OFFSET).loadAddress();
+    Address allocCursor = allocStart.plus(DATA_START_OFFSET);
+
+    /* Keep track of which regions are being used */
+    int oldPages = 0;
+    int newPages = Conversions.bytesToPages(allocEnd.diff(allocStart).plus(BYTES_IN_ADDRESS));
+
+    while (!start.isZero()) {
+      /* Get the end of this region */
+      Address end = start.plus(REGION_LIMIT_OFFSET).loadAddress();
+      Address dataEnd = start.plus(DATA_END_OFFSET).loadAddress();
+      Address nextRegion = start.plus(NEXT_REGION_OFFSET).loadAddress();
+      oldPages += Conversions.bytesToPages(end.diff(start).plus(BYTES_IN_ADDRESS));
+
+      /* dataEnd = zero represents the current region. */
+      Address currentLimit = (dataEnd.isZero() ? cursor : dataEnd);
+      ObjectReference current =
+        VM.objectModel.getObjectFromStartAddress(start.plus(DATA_START_OFFSET));
+
+      while (VM.objectModel.refToAddress(current).LT(currentLimit) && !current.isNull()) {
+        ObjectReference next = VM.objectModel.getNextObject(current);
+
+        ObjectReference copyTo = MarkCompactSpace.getForwardingPointer(current);
+
+        if (!copyTo.isNull() && Space.isInSpace(MC.MARK_COMPACT, copyTo)) {
+          if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!MarkCompactSpace.isMarked(current));
+          // To be copied.
+          if (copyTo.toAddress().GT(allocEnd) || copyTo.toAddress().LT(allocStart)) {
+            // changed regions.
+
+            VM.memory.zero(allocCursor, allocEnd.diff(allocCursor).toWord().toExtent().plus(BYTES_IN_ADDRESS));
+
+            allocStart.store(allocCursor, DATA_END_OFFSET);
+            allocStart = allocStart.plus(NEXT_REGION_OFFSET).loadAddress();
+            allocEnd = allocStart.plus(REGION_LIMIT_OFFSET).loadAddress();
+            allocCursor = allocStart.plus(DATA_START_OFFSET);
+
+            newPages += Conversions.bytesToPages(allocEnd.diff(allocStart).plus(BYTES_IN_ADDRESS));
+
+            if (VM.VERIFY_ASSERTIONS) {
+              VM.assertions._assert(allocCursor.LT(allocEnd) && allocCursor.GE(allocStart));
+            }
+          }
+          allocCursor = VM.objectModel.copyTo(current, copyTo, allocCursor);
+          MarkCompactSpace.setForwardingPointer(copyTo, ObjectReference.nullReference());
+        }
+        current = next;
+      }
+      if (dataEnd.isZero()) {
+        break;
+      }
+      start = nextRegion;
+    }
+    Extent zeroBytes = allocEnd.diff(allocCursor).toWord().toExtent().plus(BYTES_IN_ADDRESS);
+    VM.memory.zero(allocCursor, zeroBytes);
+
+    allocStart.store(Address.zero(), DATA_END_OFFSET);
+    region = allocStart;
+    cursor = allocCursor;
+    updateLimit(allocEnd, region, 0);
+    if (oldPages > newPages) {
+      ((MarkCompactSpace) space).unusePages((oldPages - newPages));
+    }
+
+    // Zero during GC to help debugging.
+    allocStart = allocStart.loadAddress(NEXT_REGION_OFFSET);
+    while (!allocStart.isZero()) {
+      allocStart.store(Address.zero(), DATA_END_OFFSET);
+      if (VM.VERIFY_ASSERTIONS) {
+        Address low = allocStart.plus(DATA_START_OFFSET);
+        Extent size = allocStart.loadAddress(REGION_LIMIT_OFFSET).diff(allocStart).toWord().toExtent().minus(2 * BYTES_IN_ADDRESS);
+        VM.memory.zero(low, size);
+      }
+      allocStart = allocStart.loadAddress(NEXT_REGION_OFFSET);
+    }
+  }
+
+  /**
+   * Perform a linear scan through the objects allocated by this bump pointer,
+   * calculating where each live object will be post collection.
+   */
+  public void calculateForwardingPointers() {
+    /* Has this allocator ever allocated anything? */
+    if (initialRegion.isZero()) return;
+
+    /* Loop through active regions or until the last region */
+    Address start = initialRegion;
+    Address allocStart = initialRegion;
+    Address allocDataEnd = initialRegion.plus(DATA_END_OFFSET).loadAddress();
+    Address allocLimit = (allocDataEnd.isZero() ? cursor : allocDataEnd);
+    Address allocCursor = start.plus(DATA_START_OFFSET);
+
+    while (!start.isZero()) {
+      /* Get the end of this region */
+      Address dataEnd = start.plus(DATA_END_OFFSET).loadAddress();
+
+      /* dataEnd = zero represents the current region. */
+      Address currentLimit = (dataEnd.isZero() ? cursor : dataEnd);
+      ObjectReference current =
+        VM.objectModel.getObjectFromStartAddress(start.plus(DATA_START_OFFSET));
+
+      while (VM.objectModel.refToAddress(current).LT(currentLimit) && !current.isNull()) {
+        ObjectReference next = VM.objectModel.getNextObject(current);
+
+        if (MarkCompactSpace.toBeCompacted(current)) {
+          if (VM.VERIFY_ASSERTIONS)
+            VM.assertions._assert(MarkCompactSpace.getForwardingPointer(current).isNull());
+
+          // Fake - allocate it.
+          int size = VM.objectModel.getSizeWhenCopied(current);
+          int align = VM.objectModel.getAlignWhenCopied(current);
+          int offset = VM.objectModel.getAlignOffsetWhenCopied(current);
+          allocCursor = Allocator.alignAllocationNoFill(allocCursor, align, offset);
+
+          boolean sameRegion = allocStart.EQ(start);
+
+          if (!sameRegion && allocCursor.plus(size).GT(allocLimit)) {
+            allocStart = allocStart.plus(NEXT_REGION_OFFSET).loadAddress();
+            allocDataEnd = allocStart.plus(DATA_END_OFFSET).loadAddress();
+            allocLimit = (allocDataEnd.isZero() ? cursor : allocDataEnd);
+            allocCursor = Allocator.alignAllocationNoFill(allocStart.plus(DATA_START_OFFSET), align, offset);
+          }
+
+          ObjectReference target = VM.objectModel.getReferenceWhenCopiedTo(current, allocCursor);
+          if (sameRegion && target.toAddress().GE(current.toAddress())) {
+            MarkCompactSpace.setForwardingPointer(current, current);
+            allocCursor = VM.objectModel.getObjectEndAddress(current);
+          } else {
+            MarkCompactSpace.setForwardingPointer(current, target);
+            allocCursor = allocCursor.plus(size);
+          }
+        }
+        current = next;
+      }
+      if (dataEnd.isZero()) {
+        break;
+      }
+      start = start.plus(NEXT_REGION_OFFSET).loadAddress(); // Move on to next
+    }
+  }
+
+  /**
+   * Some pages are about to be re-used to satisfy a slow path request.
+   * @param pages The number of pages.
+   */
+  protected void reusePages(int pages) {
+    ((MarkCompactSpace)space).reusePages(pages);
+  }
+
+  /**
+   * Maximum size of a single region. Important for children that implement
+   * load balancing or increments based on region size.
+   * @return the maximum region size
+   */
+  protected Extent maximumRegionSize() { return Extent.fromIntZeroExtend(4 << LOG_BLOCK_SIZE) ; }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkCompactSpace.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkCompactSpace.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkCompactSpace.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkCompactSpace.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,335 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.policy;
+
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.utility.heap.*;
+import org.mmtk.utility.Constants;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements functionality for a simple sliding mark-compact
+ * space.
+ */
+ at Uninterruptible public final class MarkCompactSpace extends Space
+  implements Constants {
+
+  /****************************************************************************
+   *
+   * Class variables
+   */
+  public static final int LOCAL_GC_BITS_REQUIRED = 1;
+  public static final int GLOBAL_GC_BITS_REQUIRED = 0;
+  public static final int GC_HEADER_WORDS_REQUIRED = 1;
+
+  private static final Word GC_MARK_BIT_MASK = Word.one();
+  private static final Offset FORWARDING_POINTER_OFFSET = VM.objectModel.GC_HEADER_OFFSET();
+
+  /****************************************************************************
+   *
+   * Instance variables
+   */
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * The caller specifies the region of virtual memory to be used for
+   * this space.  If this region conflicts with an existing space,
+   * then the constructor will fail.
+   *
+   * @param name The name of this space (used when printing error messages etc)
+   * @param pageBudget The number of pages this space may consume
+   * before consulting the plan
+   * @param vmRequest An object describing the virtual memory requested.
+   */
+  public MarkCompactSpace(String name, int pageBudget, VMRequest vmRequest) {
+    super(name, true, false, vmRequest);
+    if (vmRequest.isDiscontiguous()) {
+      pr = new MonotonePageResource(pageBudget, this, 0);
+    } else {
+      pr = new MonotonePageResource(pageBudget, this, start, extent, 0);
+    }
+  }
+
+  /**
+   * Prepare for a collection
+   */
+  public void prepare() {
+    // nothing to do
+  }
+
+  /**
+   * Release after a collection
+   */
+  public void release() {
+    // nothing to do
+  }
+
+
+  /**
+   * Notify that several pages are no longer in use.
+   *
+   * @param pages The number of pages
+   */
+  public void unusePages(int pages) {
+    ((MonotonePageResource) pr).unusePages(pages);
+  }
+
+  /**
+   * Notify that several pages are no longer in use.
+   *
+   * @param pages The number of pages
+   */
+  public void reusePages(int pages) {
+    ((MonotonePageResource) pr).reusePages(pages);
+  }
+
+  /**
+   * Release an allocated page or pages.  In this case we do nothing
+   * because we only release pages enmasse.
+   *
+   * @param start The address of the start of the page or pages
+   */
+  @Inline
+  public void release(Address start) {
+    if (VM.VERIFY_ASSERTIONS)
+      VM.assertions._assert(false); // this policy only releases pages enmasse
+  }
+
+  /**
+   * Trace an object under a copying collection policy.
+   * If the object is already copied, the copy is returned.
+   * Otherwise, a copy is created and returned.
+   * In either case, the object will be marked on return.
+   *
+   * @param trace The trace being conducted.
+   * @param object The object to be forwarded.
+   * @return The forwarded object.
+   */
+  @Inline
+  public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object) {
+    if (VM.VERIFY_ASSERTIONS)
+      VM.assertions._assert(false);
+    return null;
+  }
+
+  /**
+   * Trace an object under a copying collection policy.
+   * If the object is already copied, the copy is returned.
+   * Otherwise, a copy is created and returned.
+   * In either case, the object will be marked on return.
+   *
+   * @param trace The trace being conducted.
+   * @param object The object to be forwarded.
+   * @return The forwarded object.
+   */
+  @Inline
+  public ObjectReference traceMarkObject(TraceLocal trace, ObjectReference object) {
+    if (testAndMark(object)) {
+      trace.processNode(object);
+    } else if (!getForwardingPointer(object).isNull()) {
+      return getForwardingPointer(object);
+    }
+    return object;
+  }
+
+  /**
+   * Trace an object under a copying collection policy.
+   * If the object is already copied, the copy is returned.
+   * Otherwise, a copy is created and returned.
+   * In either case, the object will be marked on return.
+   *
+   * @param trace The trace being conducted.
+   * @param object The object to be forwarded.
+   * @return The forwarded object.
+   */
+  @Inline
+  public ObjectReference traceForwardObject(TraceLocal trace, ObjectReference object) {
+    if (testAndClearMark(object)) {
+      trace.processNode(object);
+    }
+    ObjectReference newObject = getForwardingPointer(object);
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!newObject.isNull());
+    return getForwardingPointer(object);
+  }
+
+  /**
+   * Is this object live?
+   *
+   * @param object The object
+   * @return True if the object is live
+   */
+  public boolean isLive(ObjectReference object) {
+    return isMarked(object);
+  }
+
+  /**
+   * Has the object in this space been reached during the current collection.
+   * This is used for GC Tracing.
+   *
+   * @param object The object reference.
+   * @return True if the object is reachable.
+   */
+  public boolean isReachable(ObjectReference object) {
+    return isMarked(object);
+  }
+
+
+  /****************************************************************************
+   *
+   * Header manipulation
+   */
+
+  /**
+   * Perform any required post-allocation initialization
+   *
+   * <i>Nothing to be done in this case</i>
+   *
+   * @param object the object ref to the storage to be initialized
+   */
+  @Inline
+  public void postAlloc(ObjectReference object) {
+  }
+
+  /**
+   * Non-atomic read of forwarding pointer
+   *
+   * @param object The object whose forwarding pointer is to be read
+   * @return The forwarding pointer stored in <code>object</code>'s
+   * header.
+   */
+  @Inline
+  public static ObjectReference getForwardingPointer(ObjectReference object) {
+    return object.toAddress().loadObjectReference(FORWARDING_POINTER_OFFSET);
+  }
+
+  /**
+   * Initialise the header of the object.
+   *
+   * @param object The object to initialise
+   */
+  @Inline
+  public void initializeHeader(ObjectReference object) {
+    // nothing to do
+  }
+
+  /**
+   * Used to mark boot image objects during a parallel scan of objects
+   * during GC Returns true if marking was done.
+   *
+   * @param object The object to be marked
+   */
+  @Inline
+  public static boolean testAndMark(ObjectReference object) {
+    Word oldValue;
+    do {
+      oldValue = VM.objectModel.prepareAvailableBits(object);
+      Word markBit = oldValue.and(GC_MARK_BIT_MASK);
+      if (!markBit.isZero()) return false;
+    } while (!VM.objectModel.attemptAvailableBits(object, oldValue,
+                                                oldValue.or(GC_MARK_BIT_MASK)));
+    return true;
+  }
+
+  /**
+   * Used to mark boot image objects during a parallel scan of objects
+   * during GC Returns true if marking was done.
+   *
+   * @param object The object to be marked
+   */
+  @Inline
+  public static boolean isMarked(ObjectReference object) {
+    Word oldValue = VM.objectModel.readAvailableBitsWord(object);
+    Word markBit = oldValue.and(GC_MARK_BIT_MASK);
+    return (!markBit.isZero());
+  }
+
+  /**
+   * Used to mark boot image objects during a parallel scan of objects
+   * during GC Returns true if marking was done.
+   *
+   * @param object The object to be marked
+   */
+  @Inline
+  private static boolean testAndClearMark(ObjectReference object) {
+    Word oldValue;
+    do {
+      oldValue = VM.objectModel.prepareAvailableBits(object);
+      Word markBit = oldValue.and(GC_MARK_BIT_MASK);
+      if (markBit.isZero()) return false;
+    } while (!VM.objectModel.attemptAvailableBits(object, oldValue,
+                                                oldValue.and(GC_MARK_BIT_MASK.not())));
+    return true;
+  }
+
+
+  /**
+   * Used to mark boot image objects during a parallel scan of objects
+   * during GC Returns true if marking was done.
+   *
+   * @param object The object to be marked
+   */
+  @Inline
+  public static boolean toBeCompacted(ObjectReference object) {
+    Word oldValue = VM.objectModel.readAvailableBitsWord(object);
+    Word markBit = oldValue.and(GC_MARK_BIT_MASK);
+    return !markBit.isZero() && getForwardingPointer(object).isNull();
+  }
+
+  /**
+   * Used to mark boot image objects during a parallel scan of objects
+   * during GC Returns true if marking was done.
+   *
+   * @param object The object to be marked
+   */
+  @Inline
+  public static void clearMark(ObjectReference object) {
+    Word oldValue = VM.objectModel.readAvailableBitsWord(object);
+    VM.objectModel.writeAvailableBitsWord(object, oldValue.and(GC_MARK_BIT_MASK.not()));
+  }
+
+  /**
+   * Non-atomic write of forwarding pointer word (assumption, thread
+   * doing the set has done attempt to forward and owns the right to
+   * copy the object)
+   *
+   * @param object The object whose forwarding pointer is to be set
+   * @param ptr The forwarding pointer to be stored in the object's
+   * forwarding word
+   */
+  @Inline
+  public static void setForwardingPointer(ObjectReference object,
+                                           ObjectReference ptr) {
+    object.toAddress().store(ptr.toAddress(), FORWARDING_POINTER_OFFSET);
+  }
+
+  /**
+   * Non-atomic clear of forwarding pointer word (assumption, thread
+   * doing the set has done attempt to forward and owns the right to
+   * copy the object)
+   *
+   * @param object The object whose forwarding pointer is to be set
+   */
+  @Inline
+  public static void clearForwardingPointer(ObjectReference object) {
+    object.toAddress().store(Address.zero(), FORWARDING_POINTER_OFFSET);
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkSweepLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkSweepLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkSweepLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkSweepLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,76 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.policy;
+
+import org.mmtk.utility.alloc.SegregatedFreeListLocal;
+import org.mmtk.utility.Constants;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements unsynchronized (local) elements of a
+ * mark-sweep collector.  Allocation is via the segregated free list
+ * (@see SegregatedFreeList).  Marking is done using both a bit in
+ * each header's object word, and a mark bitmap.  Sweeping is
+ * performed lazily.<p>
+ *
+ * A free list block is a contiguous region of memory containing cells
+ * of a single size class, and is a construct of the
+ * SegregatedFreeList.  This class extends the block to include a mark
+ * bitmap.  During the mark phase, if an object is encountered with
+ * the mark bit in its header unset, it is set and the mark bit in the
+ * block header corresponding to that object is set.  The rationale
+ * behind this approach is that testing (and setting) the mark bit in
+ * the object header is cheap, while using a bitmap makes sweeping
+ * more efficient.  This approach maximizes the speed of the common
+ * case when marking, while also allowing for fast sweeping, with
+ * minimal space overhead (2 bits per object).
+ *
+ * @see org.mmtk.utility.alloc.SegregatedFreeList
+ * @see MarkSweepSpace
+ */
+ at Uninterruptible
+public final class MarkSweepLocal extends SegregatedFreeListLocal<MarkSweepSpace> implements Constants {
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * Constructor
+   *
+   * @param space The mark-sweep space to which this allocator
+   * instances is bound.
+   */
+  public MarkSweepLocal(MarkSweepSpace space) {
+    super(space);
+  }
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Prepare for a collection. If paranoid, perform a sanity check.
+   */
+  public void prepare() {
+    flush();
+  }
+
+  /**
+   * Finish up after a collection.
+   */
+  public void release() {}
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkSweepSpace.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkSweepSpace.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkSweepSpace.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/MarkSweepSpace.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,428 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.policy;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.utility.heap.*;
+import org.mmtk.utility.options.Options;
+import org.mmtk.utility.options.MarkSweepMarkBits;
+import org.mmtk.utility.options.EagerCompleteSweep;
+import org.mmtk.utility.Constants;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * Each instance of this class corresponds to one mark-sweep *space*.
+ * Each of the instance methods of this class may be called by any
+ * thread (i.e. synchronization must be explicit in any instance or
+ * class method).  This contrasts with the MarkSweepLocal, where
+ * instances correspond to *plan* instances and therefore to kernel
+ * threads.  Thus unlike this class, synchronization is not necessary
+ * in the instance methods of MarkSweepLocal.
+ */
+ at Uninterruptible
+public final class MarkSweepSpace extends SegregatedFreeListSpace implements Constants {
+
+  /****************************************************************************
+   *
+   * Class variables
+   */
+  /**
+   * Select between using mark bits in a side bitmap, or mark bits
+   * in the headers of object (or other sub-class scheme), and a single
+   * mark bit per block.
+   */
+  public static final boolean HEADER_MARK_BITS = VM.config.HEADER_MARK_BITS;
+  /** highest bit bits we may use */
+  private static final int MAX_BITS = 4;
+
+  /* mark bits */
+  private static final int COUNT_BASE = 0;
+  public static final int DEFAULT_MARKCOUNT_BITS = 2;
+  public static final int MAX_MARKCOUNT_BITS = Plan.NEEDS_LOG_BIT_IN_HEADER ? MAX_BITS - 1 : MAX_BITS;
+  public static final Word UNLOGGED_BIT = Word.one().lsh(MAX_BITS - 1).lsh(COUNT_BASE);
+  private static final Word MARK_COUNT_INCREMENT = Word.one().lsh(COUNT_BASE);
+  private static final Word MARK_COUNT_MASK = Word.one().lsh(MAX_MARKCOUNT_BITS).minus(Word.one()).lsh(COUNT_BASE);
+  private static final Word MARK_BITS_MASK = Word.one().lsh(MAX_BITS).minus(Word.one());
+
+  private static final boolean EAGER_MARK_CLEAR = Plan.NEEDS_LOG_BIT_IN_HEADER;
+
+  /* header requirements */
+  public static final int LOCAL_GC_BITS_REQUIRED = MAX_BITS;
+  public static final int GLOBAL_GC_BITS_REQUIRED = 0;
+  public static final int GC_HEADER_WORDS_REQUIRED = 0;
+
+
+  /****************************************************************************
+   *
+   * Instance variables
+   */
+  private Word markState = Word.one();
+  private Word allocState = Word.zero();
+  private boolean inMSCollection;
+  private static final boolean usingStickyMarkBits = VM.activePlan.constraints().needsLogBitInHeader(); /* are sticky mark bits in use? */
+  private boolean isAgeSegregated = false; /* is this space a nursery space? */
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  static {
+    Options.markSweepMarkBits = new MarkSweepMarkBits();
+    Options.eagerCompleteSweep = new EagerCompleteSweep();
+  }
+
+  /**
+   * The caller specifies the region of virtual memory to be used for
+   * this space.  If this region conflicts with an existing space,
+   * then the constructor will fail.
+   *
+   * @param name The name of this space (used when printing error messages etc)
+   * @param pageBudget The number of pages this space may consume
+   * before consulting the plan
+   * @param vmRequest An object describing the virtual memory requested.
+   */
+  public MarkSweepSpace(String name, int pageBudget, VMRequest vmRequest) {
+    super(name, pageBudget, 0, vmRequest);
+    if (usingStickyMarkBits) allocState = allocState.or(UNLOGGED_BIT);
+  }
+
+  /**
+   * This instance will be age-segregated using the sticky mark bits
+   * algorithm. Perform appropriate initialization
+   */
+  public void isAgeSegregatedSpace() {
+    /* we must be using sticky mark bits */
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(usingStickyMarkBits);
+    allocState = allocState.and(UNLOGGED_BIT.not()); /* clear the unlogged bit for nursery allocs */
+    isAgeSegregated = true;
+  }
+
+  /**
+   * Should SegregatedFreeListSpace manage a side bitmap to keep track of live objects?
+   */
+  @Inline
+  protected boolean maintainSideBitmap() {
+    return !HEADER_MARK_BITS;
+  }
+
+  /**
+   * Do we need to preserve free lists as we move blocks around.
+   */
+  @Inline
+  protected boolean preserveFreeList() {
+    return !LAZY_SWEEP;
+  }
+
+  /****************************************************************************
+   *
+   * Allocation
+   */
+
+  /**
+   * Prepare the next block in the free block list for use by the free
+   * list allocator.  In the case of lazy sweeping this involves
+   * sweeping the available cells.  <b>The sweeping operation must
+   * ensure that cells are pre-zeroed</b>, as this method must return
+   * pre-zeroed cells.
+   *
+   * @param block The block to be prepared for use
+   * @param sizeClass The size class of the block
+   * @return The address of the first pre-zeroed cell in the free list
+   * for this block, or zero if there are no available cells.
+   */
+  protected Address advanceToBlock(Address block, int sizeClass) {
+    if (HEADER_MARK_BITS) {
+      if (inMSCollection) markBlock(block);
+    }
+
+    if (LAZY_SWEEP) {
+      return makeFreeList(block, sizeClass);
+    } else {
+      return getFreeList(block);
+    }
+  }
+
+  /**
+   * Notify that a new block has been installed. This is to ensure that
+   * appropriate collection state can be initialized for the block
+   *
+   * @param block The new block
+   * @param sizeClass The block's sizeclass.
+   */
+  protected void notifyNewBlock(Address block, int sizeClass) {
+    if (HEADER_MARK_BITS) {
+      if (inMSCollection) markBlock(block);
+    }
+  }
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Prepare for a new collection increment.  For the mark-sweep
+   * collector we must flip the state of the mark bit between
+   * collections.
+   *
+   * @param gcWholeMS True if we are going to collect the whole marksweep space
+   */
+  public void prepare(boolean gcWholeMS) {
+    if (HEADER_MARK_BITS && Options.eagerCompleteSweep.getValue()) {
+      consumeBlocks();
+    } else {
+      flushAvailableBlocks();
+    }
+    if (HEADER_MARK_BITS) {
+      if (gcWholeMS) {
+        allocState = markState;
+        if (usingStickyMarkBits && !isAgeSegregated) /* if true, we allocate as "mature", not nursery */
+          allocState = allocState.or(UNLOGGED_BIT);
+        markState = deltaMarkState(true);
+        if (EAGER_MARK_CLEAR)
+          clearAllBlockMarks();
+      }
+    } else {
+      zeroLiveBits(start, ((FreeListPageResource) pr).getHighWater());
+    }
+    inMSCollection = true;
+  }
+
+  /**
+   * A new collection increment has completed.  For the mark-sweep
+   * collector this means we can perform the sweep phase.
+ */
+  public void release() {
+    sweepConsumedBlocks(!EAGER_MARK_CLEAR);
+    inMSCollection = false;
+  }
+
+  /**
+   * Release an allocated page or pages
+   *
+   * @param start The address of the start of the page or pages
+   */
+  @Inline
+  public void release(Address start) {
+    ((FreeListPageResource) pr).releasePages(start);
+  }
+
+  /**
+   * Should the sweep reclaim the cell containing this object. Is this object
+   * live. This is only used when maintainSideBitmap is false.
+   *
+   * @param object The object to query
+   * @return True if the cell should be reclaimed
+   */
+  @Inline
+  protected boolean isCellLive(ObjectReference object) {
+    if (!HEADER_MARK_BITS) {
+      return super.isCellLive(object);
+    }
+    return testMarkState(object, markState);
+  }
+
+  /****************************************************************************
+   *
+   * Object processing and tracing
+   */
+
+  /**
+   * Trace a reference to an object under a mark sweep collection
+   * policy.  If the object header is not already marked, mark the
+   * object in either the bitmap or by moving it off the treadmill,
+   * and enqueue the object for subsequent processing. The object is
+   * marked as (an atomic) side-effect of checking whether already
+   * marked.
+   *
+   * @param object The object to be traced.
+   * @return The object (there is no object forwarding in this
+   * collector, so we always return the same object: this could be a
+   * void method but for compliance to a more general interface).
+   */
+  @Inline
+  public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object) {
+    if (HEADER_MARK_BITS) {
+      Word markValue = Plan.NEEDS_LOG_BIT_IN_HEADER ? markState.or(Plan.UNLOGGED_BIT) : markState;
+      if (testAndMark(object, markValue)) {
+        markBlock(object);
+        trace.processNode(object);
+      }
+    } else {
+      if (testAndSetLiveBit(object)) {
+        trace.processNode(object);
+      }
+    }
+    return object;
+  }
+
+  /**
+   *
+   * @param object The object in question
+   * @return True if this object is known to be live (i.e. it is marked)
+   */
+  @Inline
+  public boolean isLive(ObjectReference object) {
+    if (HEADER_MARK_BITS) {
+      return testMarkState(object, markState);
+    } else {
+      return liveBitSet(object);
+    }
+  }
+
+  /**
+   * Get the current mark state
+   *
+   * @return The current mark state.
+   */
+  @Inline
+  public Word getMarkState() {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(markState.and(MARK_COUNT_MASK.not()).isZero());
+    return markState;
+  }
+
+  /**
+   * Get the previous mark state.
+   *
+   * @return The previous mark state.
+   */
+  @Inline
+  public Word getPreviousMarkState() {
+    return deltaMarkState(false);
+  }
+
+  /**
+   * Return the mark state incremented or decremented by one.
+   *
+   * @param increment If true, then return the incremented value else return the decremented value
+   * @return the mark state incremented or decremented by one.
+   */
+  private Word deltaMarkState(boolean increment) {
+    Word mask = Word.fromIntZeroExtend((1 << Options.markSweepMarkBits.getValue()) - 1).lsh(COUNT_BASE);
+    Word rtn = increment ? markState.plus(MARK_COUNT_INCREMENT) : markState.minus(MARK_COUNT_INCREMENT);
+    rtn = rtn.and(mask);
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(markState.and(MARK_COUNT_MASK.not()).isZero());
+    return rtn;
+  }
+
+  /****************************************************************************
+   *
+   * Header manipulation
+   */
+
+  /**
+   * Perform any required post allocation initialization
+   *
+   * @param object the object ref to the storage to be initialized
+   */
+  @Inline
+  public void postAlloc(ObjectReference object) {
+    initializeHeader(object, true);
+  }
+
+  /**
+   * Perform any required post copy (i.e. in-GC allocation) initialization.
+   * This is relevant (for example) when MS is used as the mature space in
+   * a copying GC.
+   *
+   * @param object the object ref to the storage to be initialized
+   * @param majorGC Is this copy happening during a major gc?
+   */
+  @Inline
+  public void postCopy(ObjectReference object, boolean majorGC) {
+    initializeHeader(object, false);
+    if (!HEADER_MARK_BITS) {
+      testAndSetLiveBit(object);
+    }
+  }
+
+  /**
+   * Perform any required initialization of the GC portion of the header.
+   *
+   * @param object the object ref to the storage to be initialized
+   * @param alloc is this initialization occuring due to (initial) allocation
+   * (true) or due to copying (false)?
+   */
+  @Inline
+  public void initializeHeader(ObjectReference object, boolean alloc) {
+    if (HEADER_MARK_BITS) {
+      if (alloc) {
+        writeAllocState(object);
+      } else {
+        writeMarkState(object);
+      }
+    }
+  }
+
+  /**
+   * Atomically attempt to set the mark bit of an object.  Return true
+   * if successful, false if the mark bit was already set.
+   *
+   * @param object The object whose mark bit is to be written
+   * @param value The value to which the mark bits will be set
+   */
+  @Inline
+  private static boolean testAndMark(ObjectReference object, Word value) {
+    int oldValue, markBits;
+    oldValue = VM.objectModel.readAvailableByte(object);
+    markBits = oldValue & MARK_BITS_MASK.toInt();
+    if (markBits == value.toInt()) return false;
+    VM.objectModel.writeAvailableByte(object, (byte)(oldValue & ~MARK_BITS_MASK.toInt() | value.toInt()));
+    return true;
+  }
+
+  /**
+   * Return true if the mark count for an object has the given value.
+   *
+   * @param object The object whose mark bit is to be tested
+   * @param value The value against which the mark bit will be tested
+   * @return True if the mark bit for the object has the given value.
+   */
+  @Inline
+  public static boolean testMarkState(ObjectReference object, Word value) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(value.and(MARK_COUNT_MASK.not()).isZero());
+    return VM.objectModel.readAvailableBitsWord(object).and(MARK_COUNT_MASK).EQ(value);
+  }
+
+  /**
+   * Write the allocState into the mark state fields of an object non-atomically.
+   * This is appropriate for allocation time initialization.
+   *
+   * @param object The object whose mark state is to be written
+   */
+  @Inline
+  private void writeAllocState(ObjectReference object) {
+    Word oldValue = VM.objectModel.readAvailableBitsWord(object);
+    Word newValue = oldValue.and(MARK_BITS_MASK.not()).or(allocState);
+    VM.objectModel.writeAvailableBitsWord(object, newValue);
+  }
+
+  /**
+   * Write the markState into the mark state fields of an object non-atomically.
+   * This is appropriate for collection time initialization.
+   *
+   * @param object The object whose mark state is to be written
+   */
+  @Inline
+  private void writeMarkState(ObjectReference object) {
+    Word oldValue = VM.objectModel.readAvailableBitsWord(object);
+    Word newValue = oldValue.and(MARK_BITS_MASK.not()).or(markState);
+    VM.objectModel.writeAvailableBitsWord(object, newValue);
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/RawPageSpace.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/RawPageSpace.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/policy/RawPageSpace.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/RawPageSpace.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,85 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.policy;
+
+import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.utility.heap.FreeListPageResource;
+import org.mmtk.utility.heap.VMRequest;
+import org.mmtk.utility.Constants;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * Each instance of this class corresponds to one raw page space.
+ *
+ * This class provides access to raw memory for managing internal meta
+ * data.
+ */
+ at Uninterruptible public final class RawPageSpace extends Space
+  implements Constants {
+
+  /**
+   * The caller specifies the region of virtual memory to be used for
+   * this space.  If this region conflicts with an existing space,
+   * then the constructor will fail.
+   *
+   * @param name The name of this space (used when printing error messages etc)
+   * @param pageBudget The number of pages this space may consume
+   * before consulting the plan
+   * @param vmRequest An object describing the virtual memory requested.
+   */
+  public RawPageSpace(String name, int pageBudget, VMRequest vmRequest) {
+    super(name, false, false, vmRequest);
+    if (vmRequest.isDiscontiguous()) {
+      pr = new FreeListPageResource(pageBudget, this, 0);
+    } else {
+      pr = new FreeListPageResource(pageBudget, this, start, extent);
+    }
+  }
+
+  public void prepare() { }
+  public void release() { }
+
+  /**
+   * Release a group of pages that were allocated together.
+   *
+   * @param first The first page in the group of pages that were
+   * allocated together.
+   */
+  @Inline
+  public void release(Address first) {
+    ((FreeListPageResource) pr).releasePages(first);
+  }
+
+  /**
+   * Trace an object.
+   *
+   * This makes no sense for a raw page space and should never be
+   * called.
+   *
+   * @param object The object to be traced.
+   * @return <code>zero</code>: calling this is an error.
+   */
+  @Inline
+  public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(false);
+    return ObjectReference.nullReference();
+  }
+
+  public boolean isLive(ObjectReference object) {
+    return true;
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/SegregatedFreeListSpace.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/SegregatedFreeListSpace.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/policy/SegregatedFreeListSpace.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/SegregatedFreeListSpace.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,992 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.policy;
+
+import org.mmtk.utility.alloc.BlockAllocator;
+import org.mmtk.utility.alloc.EmbeddedMetaData;
+import org.mmtk.utility.heap.FreeListPageResource;
+import org.mmtk.utility.heap.VMRequest;
+import org.mmtk.utility.Constants;
+import org.mmtk.utility.Conversions;
+import org.mmtk.utility.Memory;
+
+import org.mmtk.vm.Lock;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * Each instance of this class corresponds to one mark-sweep *space*.
+ * Each of the instance methods of this class may be called by any
+ * thread (i.e. synchronization must be explicit in any instance or
+ * class method).  This contrasts with the MarkSweepLocal, where
+ * instances correspond to *plan* instances and therefore to kernel
+ * threads.  Thus unlike this class, synchronization is not necessary
+ * in the instance methods of MarkSweepLocal.
+ */
+ at Uninterruptible
+public abstract class SegregatedFreeListSpace extends Space implements Constants {
+
+  /****************************************************************************
+  *
+  * Class variables
+  */
+  protected static final boolean LAZY_SWEEP = true;
+  private static final boolean COMPACT_SIZE_CLASSES = false;
+  protected static final int MIN_CELLS = 6;
+  protected static final int MAX_CELLS = 99; // (1<<(INUSE_BITS-1))-1;
+  protected static final int MAX_CELL_SIZE = 8<<10;
+  public static final int MAX_FREELIST_OBJECT_BYTES = MAX_CELL_SIZE;
+
+  // live bits etc
+  private static final int OBJECT_LIVE_SHIFT = LOG_MIN_ALIGNMENT; // 4 byte resolution
+  private static final int LOG_BIT_COVERAGE = OBJECT_LIVE_SHIFT;
+  private static final int LOG_LIVE_COVERAGE = LOG_BIT_COVERAGE + LOG_BITS_IN_BYTE;
+  private static final int LIVE_BYTES_PER_REGION = 1 << (EmbeddedMetaData.LOG_BYTES_IN_REGION - LOG_LIVE_COVERAGE);
+  private static final Word WORD_SHIFT_MASK = Word.one().lsh(LOG_BITS_IN_WORD).minus(Extent.one());
+  private static final int LOG_LIVE_WORD_STRIDE = LOG_LIVE_COVERAGE + LOG_BYTES_IN_WORD;
+  private static final Extent LIVE_WORD_STRIDE = Extent.fromIntSignExtend(1<<LOG_LIVE_WORD_STRIDE);
+  private static final Word LIVE_WORD_STRIDE_MASK = LIVE_WORD_STRIDE.minus(1).toWord().not();
+  private static final int NET_META_DATA_BYTES_PER_REGION = BlockAllocator.META_DATA_BYTES_PER_REGION + LIVE_BYTES_PER_REGION;
+  protected static final int META_DATA_PAGES_PER_REGION_WITH_BITMAP = Conversions.bytesToPages(Extent.fromIntSignExtend(NET_META_DATA_BYTES_PER_REGION));
+  protected static final int META_DATA_PAGES_PER_REGION_NO_BITMAP = Conversions.bytesToPages(Extent.fromIntSignExtend(BlockAllocator.META_DATA_BYTES_PER_REGION));
+  private static final Extent META_DATA_OFFSET = BlockAllocator.META_DATA_EXTENT;
+
+
+  // calculate worst case fragmentation very conservatively
+  private static final int NEW_SIZECLASS_OVERHEAD = sizeClassCount();  // one page wasted per size class
+  private static final int METADATA_OVERHEAD = META_DATA_PAGES_PER_REGION_WITH_BITMAP; // worst case scenario
+  public static final float WORST_CASE_FRAGMENTATION = 1 + ((NEW_SIZECLASS_OVERHEAD + METADATA_OVERHEAD)/(float) EmbeddedMetaData.BYTES_IN_REGION);
+
+  /****************************************************************************
+   *
+   * Instance variables
+   */
+  protected final Lock lock = VM.newLock("SegregatedFreeListGlobal");
+  protected final AddressArray consumedBlockHead = AddressArray.create(sizeClassCount());
+  protected final AddressArray flushedBlockHead = AddressArray.create(sizeClassCount());
+  protected final AddressArray availableBlockHead = AddressArray.create(sizeClassCount());
+
+  private final int[] cellSize = new int[sizeClassCount()];
+  private final byte[] blockSizeClass = new byte[sizeClassCount()];
+  private final int[] blockHeaderSize = new int[sizeClassCount()];
+
+  /**
+   * The caller specifies the region of virtual memory to be used for
+   * this space.  If this region conflicts with an existing space,
+   * then the constructor will fail.
+   *
+   * @param name The name of this space (used when printing error messages etc)
+   * @param pageBudget The number of pages this space may consume before consulting the plan
+   * @param additionalMetadata The number of meta data bytes per region for the subclass.
+   * @param vmRequest An object describing the virtual memory requested.
+   */
+  public SegregatedFreeListSpace(String name, int pageBudget, int additionalMetadata, VMRequest vmRequest) {
+    super(name, false, false, vmRequest);
+    initSizeClasses();
+    int totalMetadata = additionalMetadata;
+    if (maintainSideBitmap()) {
+      totalMetadata += META_DATA_PAGES_PER_REGION_WITH_BITMAP;
+    } else {
+      totalMetadata += META_DATA_PAGES_PER_REGION_NO_BITMAP;
+    }
+    if (vmRequest.isDiscontiguous()) {
+      pr = new FreeListPageResource(pageBudget, this, totalMetadata);
+    } else {
+      pr = new FreeListPageResource(pageBudget, this, start, extent, totalMetadata);
+    }
+  }
+
+  /**
+   * Should SegregatedFreeListSpace manage a side bitmap to keep track of live objects?
+   */
+  protected abstract boolean maintainSideBitmap();
+
+  /**
+   * Do we need to preserve free lists as we move blocks around.
+   */
+  protected abstract boolean preserveFreeList();
+
+  /****************************************************************************
+   *
+   * Allocation
+   */
+
+  /**
+   * Return a block to the global pool.
+   *
+   * @param block The block to return
+   * @param sizeClass The size class
+   */
+  public void returnConsumedBlock(Address block, int sizeClass) {
+    returnBlock(block, sizeClass, Address.zero());
+  }
+
+  /**
+   * Return a block to the global pool.
+   *
+   * @param block The block to return
+   * @param sizeClass The size class
+   * @param freeCell The first free cell in the block.
+   */
+  public void returnBlock(Address block, int sizeClass, Address freeCell) {
+    if (VM.VERIFY_ASSERTIONS) {
+      VM.assertions._assert(BlockAllocator.getNext(block).isZero());
+    }
+    if (preserveFreeList()) {
+      setFreeList(block, freeCell);
+    }
+    lock.acquire();
+    BlockAllocator.setNext(block, consumedBlockHead.get(sizeClass));
+    consumedBlockHead.set(sizeClass, block);
+    lock.release();
+  }
+
+  /**
+   * Acquire a new block from the global pool to allocate into. This method
+   * with either return a non-empty free list, or zero when allocation
+   * fails.
+   *
+   * This method will populate the passed in free list for the given size
+   * class and return the address of the block.
+   *
+   * @param sizeClass The size class to allocate into
+   * @param freeList The free list to populate
+   * @return The address of the block
+   */
+  public Address getAllocationBlock(int sizeClass, AddressArray freeList) {
+    lock.acquire();
+    Address block;
+    while(!(block = availableBlockHead.get(sizeClass)).isZero()) {
+      availableBlockHead.set(sizeClass, BlockAllocator.getNext(block));
+      lock.release();
+
+      /* This block is no longer on any list */
+      BlockAllocator.setNext(block, Address.zero());
+
+      /* Can we allocate into this block? */
+      Address cell = advanceToBlock(block, sizeClass);
+      if (!cell.isZero()) {
+        freeList.set(sizeClass, cell);
+        return block;
+      }
+
+      /* Block was full */
+      lock.acquire();
+      BlockAllocator.setNext(block, consumedBlockHead.get(sizeClass));
+      consumedBlockHead.set(sizeClass, block);
+    }
+    lock.release();
+    return expandSizeClass(sizeClass, freeList);
+  }
+
+  /**
+   * Expand a particular size class, allocating a new block, breaking
+   * the block into cells and placing those cells on a free list for
+   * that block.  The block becomes the current head for this size
+   * class and the address of the first available cell is returned.<p>
+   *
+   * <b>This is guaranteed to return pre-zeroed cells</b>
+   *
+   * @param sizeClass The size class to be expanded
+   * @param freeList The free list to populate.
+   * @return The block that was just allocated.
+   */
+  @Inline
+  private Address expandSizeClass(int sizeClass, AddressArray freeList) {
+    Address block = BlockAllocator.alloc(this, blockSizeClass[sizeClass]);
+
+    if (block.isZero()) {
+      return Address.zero();
+    }
+
+    BlockAllocator.setNext(block, Address.zero());
+    BlockAllocator.setAllClientSizeClass(block, blockSizeClass[sizeClass], (byte) sizeClass);
+
+    notifyNewBlock(block, sizeClass);
+
+    int cellExtent = cellSize[sizeClass];
+    int blockSize = BlockAllocator.blockSize(blockSizeClass[sizeClass]);
+    int useableBlockSize = blockSize - blockHeaderSize[sizeClass];
+    Address firstCell = block.plus(blockHeaderSize[sizeClass]);
+    Address sentinel = block.plus(blockSize);
+
+    /* pre-zero the block */
+    VM.memory.zero(firstCell, Extent.fromIntZeroExtend(useableBlockSize));
+
+    /* construct the free list */
+    Address nextCell;
+    Address cell = firstCell;
+    while ((nextCell = cell.plus(cellExtent)).LT(sentinel)) {
+      cell.store(nextCell);
+      cell = nextCell;
+    }
+
+    /* Populate the free list */
+    freeList.set(sizeClass, firstCell);
+    return block;
+  }
+
+  /****************************************************************************
+   *
+   * Block management
+   */
+
+  /**
+   * Initialize the size class data structures.
+   */
+  private void initSizeClasses() {
+    for (int sc = 0; sc < sizeClassCount(); sc++) {
+      cellSize[sc] = getBaseCellSize(sc);
+      for (byte blk = 0; blk < BlockAllocator.BLOCK_SIZE_CLASSES; blk++) {
+        int usableBytes = BlockAllocator.blockSize(blk);
+        int cells = usableBytes / cellSize[sc];
+        blockSizeClass[sc] = blk;
+        /* cells must start at multiple of MIN_ALIGNMENT because
+           cellSize is also supposed to be multiple, this should do
+           the trick: */
+        blockHeaderSize[sc] = BlockAllocator.blockSize(blk) - cells * cellSize[sc];
+        if (((usableBytes < BYTES_IN_PAGE) && (cells*2 > MAX_CELLS)) ||
+            ((usableBytes > (BYTES_IN_PAGE>>1)) && (cells > MIN_CELLS)))
+          break;
+      }
+    }
+  }
+
+  /**
+   * Get the size class for a given number of bytes.
+   *
+   * We use size classes based on a worst case internal fragmentation
+   * loss target of 1/8.  In fact, across sizes from 8 bytes to 512
+   * the average worst case loss is 13.3%, giving an expected loss
+   * (assuming uniform distribution) of about 7%.  We avoid using the
+   * Lea class sizes because they were so numerous and therefore
+   * liable to lead to excessive inter-class-size fragmentation.<p>
+   *
+   * This method may segregate arrays and scalars (currently it does
+   * not).<p>
+   *
+   * This method should be more intelligent and take alignment requests
+   * into consideration. The issue with this is that the block header
+   * which can be varied by subclasses can change the alignment of the
+   * cells.<p>
+   *
+   * @param bytes The number of bytes required to accommodate the object
+   * to be allocated.
+   * @return The size class capable of accommodating the allocation request.
+   */
+  @Inline
+  public final int getSizeClass(int bytes) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((bytes > 0) && (bytes <= MAX_CELL_SIZE));
+
+    int sz1 = bytes - 1;
+
+    if (BYTES_IN_ADDRESS == 4) { // 32-bit
+      if (COMPACT_SIZE_CLASSES)
+        return (
+            (sz1 <=  31) ?      (sz1 >>  2) : //    4 bytes apart
+            (sz1 <=  63) ?  4 + (sz1 >>  3) : //    8 bytes apart
+            (sz1 <=  95) ?  8 + (sz1 >>  4) : //   16 bytes apart
+            (sz1 <= 223) ? 14 + (sz1 >>  6) : //   64 bytes apart
+            (sz1 <= 734) ? 17 + (sz1 >>  8) : //  256 bytes apart
+                           20 + (sz1 >> 10)); // 1024 bytes apart
+      else
+        return (
+            (sz1 <=   63) ?      (sz1 >>  2) : //    4 bytes apart
+            (sz1 <=  127) ? 12 + (sz1 >>  4) : //   16 bytes apart
+            (sz1 <=  255) ? 16 + (sz1 >>  5) : //   32 bytes apart
+            (sz1 <=  511) ? 20 + (sz1 >>  6) : //   64 bytes apart
+            (sz1 <= 2047) ? 26 + (sz1 >>  8) : //  256 bytes apart
+                            32 + (sz1 >> 10)); // 1024 bytes apart
+    } else { // 64-bit
+      if (COMPACT_SIZE_CLASSES)
+        return (
+            (sz1 <=   95) ?      (sz1 >>  3) : //    8 bytes apart
+            (sz1 <=  127) ?  6 + (sz1 >>  4) : //   16 bytes apart
+            (sz1 <=  191) ? 10 + (sz1 >>  5) : //   32 bytes apart
+            (sz1 <=  383) ? 13 + (sz1 >>  6) : //   64 bytes apart
+            (sz1 <=  511) ? 16 + (sz1 >>  7) : //  128 bytes apart
+            (sz1 <= 1023) ? 19 + (sz1 >>  9) : //  512 bytes apart
+                            20 + (sz1 >> 10)); // 1024 bytes apart
+      else
+        return (
+            (sz1 <=  111) ?      (sz1 >>  3) : //    8 bytes apart
+            (sz1 <=  223) ?  7 + (sz1 >>  4) : //   16 bytes apart
+            (sz1 <=  319) ? 14 + (sz1 >>  5) : //   32 bytes apart
+            (sz1 <=  575) ? 19 + (sz1 >>  6) : //   64 bytes apart
+            (sz1 <= 2047) ? 26 + (sz1 >>  8) : //  256 bytes apart
+                            32 + (sz1 >> 10)); // 1024 bytes apart
+    }
+  }
+
+  /**
+   * Return the size of a basic cell (i.e. not including any cell
+   * header) for a given size class.
+   *
+   * @param sc The size class in question
+   * @return The size of a basic cell (i.e. not including any cell
+   * header).
+   */
+  @Inline
+  public final int getBaseCellSize(int sc) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((sc >= 0) && (sc < sizeClassCount()));
+
+    if (BYTES_IN_ADDRESS == 4) { // 32-bit
+      if (COMPACT_SIZE_CLASSES)
+        return ((sc <  8) ? (sc +  1) <<  2:
+                (sc < 12) ? (sc -  3) <<  3:
+                (sc < 16) ? (sc -  7) <<  4:
+                (sc < 18) ? (sc - 13) <<  6:
+                (sc < 21) ? (sc - 16) <<  8:
+                            (sc - 19) << 10);
+      else
+        return ((sc < 16) ? (sc +  1) <<  2:
+                (sc < 20) ? (sc - 11) <<  4:
+                (sc < 24) ? (sc - 15) <<  5:
+                (sc < 28) ? (sc - 19) <<  6:
+                (sc < 34) ? (sc - 25) <<  8:
+                            (sc - 31) << 10);
+    } else { // 64-bit
+      if (COMPACT_SIZE_CLASSES)
+        return ((sc < 12) ? (sc +  1) <<  3:
+                (sc < 14) ? (sc -  5) <<  4:
+                (sc < 16) ? (sc -  9) <<  5:
+                (sc < 19) ? (sc - 12) <<  6:
+                (sc < 20) ? (sc - 15) <<  7:
+                (sc < 21) ? (sc - 18) <<  9:
+                            (sc - 19) << 10);
+      else
+        return ((sc < 14) ? (sc +  1) <<  3:
+                (sc < 21) ? (sc -  6) <<  4:
+                (sc < 24) ? (sc - 13) <<  5:
+                (sc < 28) ? (sc - 18) <<  6:
+                (sc < 34) ? (sc - 25) <<  8:
+                            (sc - 31) << 10);
+    }
+  }
+
+  /**
+   * The number of distinct size classes.
+   */
+  @Inline
+  public static int sizeClassCount() {
+    return (COMPACT_SIZE_CLASSES) ? 28 : 40;
+  }
+
+  /****************************************************************************
+   *
+   * Preserving (saving & restoring) free lists
+   */
+
+  /**
+   * Prepare a block for allocation, returning a free list into the block.
+   *
+   * @param block The new block
+   * @param sizeClass The block's sizeclass.
+   */
+  protected abstract Address advanceToBlock(Address block, int sizeClass);
+
+  /**
+   * Notify that a new block has been installed.
+   *
+   * @param block The new block
+   * @param sizeClass The block's sizeclass.
+   */
+  protected void notifyNewBlock(Address block, int sizeClass) {}
+
+  /**
+   * Should the sweep reclaim the cell containing this object. Is this object
+   * live. This is only used when maintainSideBitmap is false.
+   *
+   * @param object The object to query
+   * @return True if the cell should be reclaimed
+   */
+  protected boolean reclaimCellForObject(ObjectReference object) {
+    VM.assertions.fail("Must implement reclaimCellForObject if not maintaining side bitmap");
+    return false;
+  }
+
+  /****************************************************************************
+   *
+   * Metadata manipulation
+   */
+
+  /**
+   * In the case where free lists associated with each block are
+   * preserved, get the free list for a given block.
+   *
+   * @param block The block whose free list is to be found
+   * @return The free list for this block
+   */
+  @Inline
+  protected final Address getFreeList(Address block) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(preserveFreeList());
+    return BlockAllocator.getFreeListMeta(block);
+  }
+
+  /**
+   * In the case where free lists associated with each block are
+   * preserved, set the free list for a given block.
+   *
+   * @param block The block whose free list is to be found
+   * @param cell The head of the free list (i.e. the first cell in the
+   * free list).
+   */
+  @Inline
+  protected final void setFreeList(Address block, Address cell) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(preserveFreeList());
+    BlockAllocator.setFreeListMeta(block, cell);
+  }
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Clear all block marks for this space.  This method is important when
+   * it is desirable to do partial collections, which man mean that block
+   * marks need to be explicitly cleared when necessary.
+   */
+  protected final void clearAllBlockMarks() {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!maintainSideBitmap());
+    for (int sizeClass = 0; sizeClass < sizeClassCount(); sizeClass++) {
+      Extent blockSize = Extent.fromIntSignExtend(BlockAllocator.blockSize(blockSizeClass[sizeClass]));
+      /* Flushed blocks */
+      Address block = flushedBlockHead.get(sizeClass);
+      while (!block.isZero()) {
+        Address next = BlockAllocator.getNext(block);
+        clearBlockMark(block, blockSize);
+        block = next;
+      }
+      /* Available blocks */
+      block = consumedBlockHead.get(sizeClass);
+      while (!block.isZero()) {
+        Address next = BlockAllocator.getNext(block);
+        clearBlockMark(block, blockSize);
+        block = next;
+      }
+    }
+  }
+
+  /**
+   * Sweep all blocks for free objects.
+   *
+   * @param clearMarks should we clear block mark bits as we process.
+   */
+  protected final void sweepConsumedBlocks(boolean clearMarks) {
+    for (int sizeClass = 0; sizeClass < sizeClassCount(); sizeClass++) {
+      Extent blockSize = Extent.fromIntSignExtend(BlockAllocator.blockSize(blockSizeClass[sizeClass]));
+      Address availableHead = Address.zero();
+      /* Flushed blocks */
+      Address block = flushedBlockHead.get(sizeClass);
+      flushedBlockHead.set(sizeClass, Address.zero());
+      while (!block.isZero()) {
+        Address next = BlockAllocator.getNext(block);
+        availableHead = sweepBlock(block, sizeClass, blockSize, availableHead, clearMarks);
+        block = next;
+      }
+      /* Consumed blocks */
+      block = consumedBlockHead.get(sizeClass);
+      consumedBlockHead.set(sizeClass, Address.zero());
+      while (!block.isZero()) {
+        Address next = BlockAllocator.getNext(block);
+        availableHead = sweepBlock(block, sizeClass, blockSize, availableHead, clearMarks);
+        block = next;
+      }
+      /* Make blocks available */
+      availableBlockHead.set(sizeClass, availableHead);
+    }
+  }
+
+  /**
+   * Sweep a block, freeing it and adding to the list given by availableHead
+   * if it contains no free objects.
+   *
+   * @param clearMarks should we clear block mark bits as we process.
+   */
+  protected final Address sweepBlock(Address block, int sizeClass, Extent blockSize, Address availableHead, boolean clearMarks) {
+    boolean liveBlock = containsLiveCell(block, blockSize, clearMarks);
+    if (!liveBlock) {
+      BlockAllocator.setNext(block, Address.zero());
+      BlockAllocator.free(this, block);
+    } else {
+      BlockAllocator.setNext(block, availableHead);
+      availableHead = block;
+      if (!LAZY_SWEEP) {
+        setFreeList(block, makeFreeList(block, sizeClass));
+      }
+    }
+    return availableHead;
+  }
+
+  /**
+   * Eagerly consume all remaining blocks.
+   */
+  protected final void consumeBlocks() {
+    for (int sizeClass = 0; sizeClass < sizeClassCount(); sizeClass++) {
+      while (!getAllocationBlock(sizeClass, null).isZero());
+    }
+  }
+
+  /**
+   * Flush all the allocation blocks to the consumed list.
+   */
+  protected final void flushAvailableBlocks() {
+    for (int sizeClass = 0; sizeClass < sizeClassCount(); sizeClass++) {
+      flushedBlockHead.set(sizeClass, availableBlockHead.get(sizeClass));
+      availableBlockHead.set(sizeClass, Address.zero());
+    }
+  }
+
+  /**
+   * Does this block contain any live cells.
+   *
+   * @param block The block
+   * @param blockSize The size of the block
+   * @param clearMarks should we clear block mark bits as we process.
+   * @return True if any cells in the block are live
+   */
+  @Inline
+  protected boolean containsLiveCell(Address block, Extent blockSize, boolean clearMarks) {
+    if (maintainSideBitmap()) {
+      if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(alignToLiveStride(block).EQ(block));
+      Address cursor = getLiveWordAddress(block);
+      Address sentinel = getLiveWordAddress(block.plus(blockSize.minus(1)));
+      while (cursor.LE(sentinel)) {
+        Word live = cursor.loadWord();
+        if (!live.isZero()) {
+          return true;
+        }
+        cursor = cursor.plus(BYTES_IN_WORD);
+      }
+      return false;
+    } else {
+      boolean live = false;
+      Address cursor = block;
+      while(cursor.LT(block.plus(blockSize))) {
+        live |= BlockAllocator.checkBlockMeta(cursor);
+        if (clearMarks)
+          BlockAllocator.clearBlockMeta(cursor);
+        cursor = cursor.plus(1 << BlockAllocator.LOG_MIN_BLOCK);
+      }
+      return live;
+    }
+  }
+
+
+  /**
+   * Clear block marks for a block
+   *
+   * @param block The block
+   * @param blockSize The size of the block
+   */
+  @Inline
+  protected void clearBlockMark(Address block, Extent blockSize) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!maintainSideBitmap());
+    Address cursor = block;
+    while(cursor.LT(block.plus(blockSize))) {
+      BlockAllocator.clearBlockMeta(cursor);
+      cursor = cursor.plus(1 << BlockAllocator.LOG_MIN_BLOCK);
+    }
+  }
+
+  /**
+   * In the cell containing this object live?
+   *
+   * @param object The object
+   * @return True if the cell is live
+   */
+  @Inline
+  protected boolean isCellLive(ObjectReference object) {
+    /* Must override if not using the side bitmap */
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(maintainSideBitmap());
+    return liveBitSet(object);
+  }
+
+  /**
+   * Use the live bits for a block to infer free cells and thus
+   * construct a free list for the block.
+   *
+   * @param block The block to be processed
+   * @param sizeClass The size class for the block
+   * @return The head of the new free list
+   */
+  @Inline
+  protected final Address makeFreeList(Address block, int sizeClass) {
+    Extent blockSize = Extent.fromIntSignExtend(BlockAllocator.blockSize(blockSizeClass[sizeClass]));
+    Address cursor = block.plus(blockHeaderSize[sizeClass]);
+    Address lastFree = Address.zero();
+    Address firstFree = Address.zero();
+    Address end = block.plus(blockSize);
+    Extent cellExtent = Extent.fromIntSignExtend(cellSize[sizeClass]);
+    while (cursor.LT(end)) {
+      ObjectReference current = VM.objectModel.getObjectFromStartAddress(cursor);
+      boolean free = true;
+      if (!current.isNull()) {
+        free = !isCellLive(current);
+      }
+      if (free) {
+        if (firstFree.isZero()) {
+          firstFree = cursor;
+        } else {
+          lastFree.store(cursor);
+        }
+        Memory.zeroSmall(cursor, cellExtent);
+        lastFree = cursor;
+      }
+      cursor = cursor.plus(cellExtent);
+    }
+    return firstFree;
+  }
+
+  /**
+   * Sweep all blocks for free objects.
+   */
+  public void sweepCells(Sweeper sweeper) {
+    for (int sizeClass = 0; sizeClass < sizeClassCount(); sizeClass++) {
+      Address availableHead = Address.zero();
+      /* Flushed blocks */
+      Address block = flushedBlockHead.get(sizeClass);
+      flushedBlockHead.set(sizeClass, Address.zero());
+      while (!block.isZero()) {
+        Address next = BlockAllocator.getNext(block);
+        availableHead = sweepCells(sweeper, block, sizeClass, availableHead);
+        block = next;
+      }
+      /* Consumed blocks */
+      block = consumedBlockHead.get(sizeClass);
+      consumedBlockHead.set(sizeClass, Address.zero());
+      while (!block.isZero()) {
+        Address next = BlockAllocator.getNext(block);
+        availableHead = sweepCells(sweeper, block, sizeClass, availableHead);
+        block = next;
+      }
+      /* Make blocks available */
+      availableBlockHead.set(sizeClass, availableHead);
+    }
+  }
+
+  /**
+   * Sweep a block, freeing it and adding to the list given by availableHead
+   * if it contains no free objects.
+   */
+  private Address sweepCells(Sweeper sweeper, Address block, int sizeClass, Address availableHead) {
+    boolean liveBlock = sweepCells(sweeper, block, sizeClass);
+    if (!liveBlock) {
+      BlockAllocator.setNext(block, Address.zero());
+      BlockAllocator.free(this, block);
+    } else {
+      BlockAllocator.setNext(block, availableHead);
+      availableHead = block;
+    }
+    return availableHead;
+  }
+
+  /**
+   * Sweep a block, freeing it and making it available if any live cells were found.
+   * if it contains no free objects.
+   *
+   * This is designed to be called in parallel by multiple collector threads.
+   */
+  public void parallelSweepCells(Sweeper sweeper) {
+    for (int sizeClass = 0; sizeClass < sizeClassCount(); sizeClass++) {
+      Address block;
+      while(!(block = getSweepBlock(sizeClass)).isZero()) {
+        boolean liveBlock = sweepCells(sweeper, block, sizeClass);
+        if (!liveBlock) {
+          BlockAllocator.setNext(block, Address.zero());
+          BlockAllocator.free(this, block);
+        } else {
+          lock.acquire();
+          BlockAllocator.setNext(block, availableBlockHead.get(sizeClass));
+          availableBlockHead.set(sizeClass, block);
+          lock.release();
+        }
+      }
+    }
+  }
+
+  /**
+   * Get a block for a parallel sweep.
+   *
+   * @param sizeClass The size class of the block to sweep.
+   * @return The block or zero if no blocks remain to be swept.
+   */
+  private Address getSweepBlock(int sizeClass) {
+    lock.acquire();
+    Address block;
+
+    /* Flushed blocks */
+    block = flushedBlockHead.get(sizeClass);
+    if (!block.isZero()) {
+      flushedBlockHead.set(sizeClass, BlockAllocator.getNext(block));
+      lock.release();
+      BlockAllocator.setNext(block, Address.zero());
+      return block;
+    }
+
+    /* Consumed blocks */
+    block = consumedBlockHead.get(sizeClass);
+    if (!block.isZero()) {
+      flushedBlockHead.set(sizeClass, BlockAllocator.getNext(block));
+      lock.release();
+      BlockAllocator.setNext(block, Address.zero());
+      return block;
+    }
+
+    /* All swept! */
+    lock.release();
+    return Address.zero();
+  }
+
+  /**
+   * Does this block contain any live cells?
+   */
+  @Inline
+  public boolean sweepCells(Sweeper sweeper, Address block, int sizeClass) {
+    Extent blockSize = Extent.fromIntSignExtend(BlockAllocator.blockSize(blockSizeClass[sizeClass]));
+    Address cursor = block.plus(blockHeaderSize[sizeClass]);
+    Address end = block.plus(blockSize);
+    Extent cellExtent = Extent.fromIntSignExtend(cellSize[sizeClass]);
+    boolean containsLive = false;
+    while (cursor.LT(end)) {
+      ObjectReference current = VM.objectModel.getObjectFromStartAddress(cursor);
+      boolean free = true;
+      if (!current.isNull()) {
+        free = !liveBitSet(current);
+        if (!free) {
+          free = sweeper.sweepCell(current);
+          if (free) unsyncClearLiveBit(current);
+        }
+      }
+      if (!free) {
+        containsLive = true;
+      }
+      cursor = cursor.plus(cellExtent);
+    }
+    return containsLive;
+  }
+
+  /**
+   * A callback used to perform sweeping of a free list space.
+   */
+  @Uninterruptible
+  public abstract static class Sweeper {
+    public abstract boolean sweepCell(ObjectReference object);
+  }
+
+  /****************************************************************************
+   *
+   * Live bit manipulation
+   */
+
+  /**
+   * Atomically set the live bit for a given object
+   *
+   * @param object The object whose live bit is to be set.
+   * @return True if the bit was changed to true.
+   */
+  @Inline
+  public static boolean testAndSetLiveBit(ObjectReference object) {
+    return updateLiveBit(VM.objectModel.objectStartRef(object), true, true);
+  }
+
+  /**
+   * Set the live bit for the block containing the given object
+   *
+   * @param object The object whose blocks liveness is to be set.
+   */
+  @Inline
+  protected static void markBlock(ObjectReference object) {
+    BlockAllocator.markBlockMeta(object);
+  }
+
+  /**
+   * Set the live bit for the given block.
+   *
+   * @param block The block whose liveness is to be set.
+   */
+  @Inline
+  protected static void markBlock(Address block) {
+    BlockAllocator.markBlockMeta(block);
+  }
+
+  /**
+   * Set the live bit for a given object, without using
+   * synchronization primitives---must only be used when contention
+   * for live bit is strictly not possible
+   *
+   * @param object The object whose live bit is to be set.
+   */
+  @Inline
+  public static boolean unsyncSetLiveBit(ObjectReference object) {
+    return updateLiveBit(VM.objectModel.refToAddress(object), true, false);
+  }
+
+  /**
+   * Set the live bit for a given address
+   *
+   * @param address The address whose live bit is to be set.
+   * @param set True if the bit is to be set, as opposed to cleared
+   * @param atomic True if we want to perform this operation atomically
+   */
+  @Inline
+  private static boolean updateLiveBit(Address address, boolean set, boolean atomic) {
+    Word oldValue, newValue;
+    Address liveWord = getLiveWordAddress(address);
+    Word mask = getMask(address, true);
+    if (atomic) {
+      do {
+        oldValue = liveWord.prepareWord();
+        newValue = (set) ? oldValue.or(mask) : oldValue.and(mask.not());
+      } while (!liveWord.attempt(oldValue, newValue));
+    } else {
+      oldValue = liveWord.loadWord();
+      liveWord.store(set ? oldValue.or(mask) : oldValue.and(mask.not()));
+    }
+    return oldValue.and(mask).NE(mask);
+  }
+
+  /**
+   * Test the live bit for a given object
+   *
+   * @param object The object whose live bit is to be set.
+   */
+  @Inline
+  protected static boolean liveBitSet(ObjectReference object) {
+    return liveBitSet(VM.objectModel.refToAddress(object));
+  }
+
+  /**
+   * Set the live bit for a given address
+   *
+   * @param address The address whose live bit is to be set.
+   * @return true if this operation changed the state of the live bit.
+   */
+  @Inline
+  protected static boolean liveBitSet(Address address) {
+    Address liveWord = getLiveWordAddress(address);
+    Word mask = getMask(address, true);
+    Word value = liveWord.loadWord();
+    return value.and(mask).EQ(mask);
+  }
+
+  /**
+   * Clear the live bit for a given object
+   *
+   * @param object The object whose live bit is to be cleared.
+   */
+  @Inline
+  protected static void clearLiveBit(ObjectReference object) {
+    clearLiveBit(VM.objectModel.refToAddress(object));
+  }
+
+  /**
+   * Clear the live bit for a given address
+   *
+   * @param address The address whose live bit is to be cleared.
+   */
+  @Inline
+  protected static void clearLiveBit(Address address) {
+    updateLiveBit(address, false, true);
+  }
+
+  /**
+   * Clear the live bit for a given object
+   *
+   * @param object The object whose live bit is to be cleared.
+   */
+  @Inline
+  protected static void unsyncClearLiveBit(ObjectReference object) {
+    unsyncClearLiveBit(VM.objectModel.refToAddress(object));
+  }
+
+  /**
+   * Clear the live bit for a given address
+   *
+   * @param address The address whose live bit is to be cleared.
+   */
+  @Inline
+  protected static void unsyncClearLiveBit(Address address) {
+    updateLiveBit(address, false, false);
+  }
+
+  /**
+   * Clear all live bits for a block
+   */
+  protected void clearLiveBits(Address block, int sizeClass) {
+    int blockSize = BlockAllocator.blockSize(blockSizeClass[sizeClass]);
+    Address cursor = getLiveWordAddress(block);
+    Address sentinel = getLiveWordAddress(block.plus(blockSize - 1));
+    while (cursor.LE(sentinel)) {
+      cursor.store(Word.zero());
+      cursor = cursor.plus(BYTES_IN_WORD);
+    }
+  }
+
+  /**
+   * Clear all live bits
+   */
+  protected static void zeroLiveBits(Address start, Address end) {
+    Extent bytes = Extent.fromIntSignExtend(EmbeddedMetaData.BYTES_IN_REGION>>LOG_LIVE_COVERAGE);
+    while (start.LT(end)) {
+      Address metadata = EmbeddedMetaData.getMetaDataBase(start).plus(META_DATA_OFFSET);
+      VM.memory.zero(metadata, bytes);
+      start = start.plus(EmbeddedMetaData.BYTES_IN_REGION);
+    }
+  }
+
+  /**
+   * Align an address so that it corresponds to a live word boundary.
+   * In other words, if the live bit for the given address is not the
+   * zeroth bit of a live word, round the address down such that it
+   * does.
+   *
+   * @param address The address to be aligned to a live word
+   * @return The given address, aligned down so that it corresponds to
+   * an address on a live word boundary.
+   */
+  private static Address alignToLiveStride(Address address) {
+    return address.toWord().and(LIVE_WORD_STRIDE_MASK).toAddress();
+  }
+
+  /**
+   * Given an address, produce a bit mask for the live table
+   *
+   * @param address The address whose live bit mask is to be established
+   * @param set True if we want the mask for <i>setting</i> the bit,
+   * false if we want the mask for <i>clearing</i> the bit.
+   * @return The appropriate bit mask for object for the live table for.
+   */
+  @Inline
+  private static Word getMask(Address address, boolean set) {
+    int shift = address.toWord().rshl(OBJECT_LIVE_SHIFT).and(WORD_SHIFT_MASK).toInt();
+    Word rtn = Word.one().lsh(shift);
+    return (set) ? rtn : rtn.not();
+  }
+
+  /**
+   * Given an address, return the address of the live word for
+   * that address.
+   *
+   * @param address The address whose live word address is to be returned
+   * @return The address of the live word for this object
+   */
+  @Inline
+  private static Address getLiveWordAddress(Address address) {
+    Address rtn = EmbeddedMetaData.getMetaDataBase(address);
+    return rtn.plus(META_DATA_OFFSET).plus(EmbeddedMetaData.getMetaDataOffset(address, LOG_LIVE_COVERAGE, LOG_BYTES_IN_WORD));
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/Space.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/Space.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/policy/Space.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/Space.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,704 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.policy;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.utility.heap.Map;
+import org.mmtk.utility.heap.Mmapper;
+import org.mmtk.utility.heap.PageResource;
+import org.mmtk.utility.heap.SpaceDescriptor;
+import org.mmtk.utility.heap.VMRequest;
+import org.mmtk.utility.options.Options;
+import org.mmtk.utility.Log;
+import org.mmtk.utility.Constants;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class defines and manages spaces.  Each policy is an instance
+ * of a space.  A space is a region of virtual memory (contiguous or
+ * discontigous) which is subject to the same memory management
+ * regime.  Multiple spaces (instances of this class or its
+ * descendants) may have the same policy (eg there could be numerous
+ * instances of CopySpace, each with different roles). Spaces are
+ * defined in terms of a unique region of virtual memory, so no two
+ * space instances ever share any virtual memory.<p>
+ *
+ * In addition to tracking virtual memory use and the mapping to
+ * policy, spaces also manage memory consumption (<i>used</i> virtual
+ * memory).<p>
+ *
+ */
+ at Uninterruptible
+public abstract class Space implements Constants {
+
+  /****************************************************************************
+   *
+   * Class variables
+   */
+
+  private static boolean DEBUG = false;
+
+  // the following is somewhat arbitrary for the 64 bit system at this stage
+  public static final int LOG_ADDRESS_SPACE = (BYTES_IN_ADDRESS == 4) ? 32 : 40;
+  public static final int LOG_BYTES_IN_CHUNK = 22;
+  public static final int BYTES_IN_CHUNK = 1 << LOG_BYTES_IN_CHUNK;
+  public static final int PAGES_IN_CHUNK = 1 << (LOG_BYTES_IN_CHUNK - LOG_BYTES_IN_PAGE);
+  private static final int LOG_MAX_CHUNKS = LOG_ADDRESS_SPACE - LOG_BYTES_IN_CHUNK;
+  public static final int MAX_CHUNKS = 1 << LOG_MAX_CHUNKS;
+  public static final int MAX_SPACES = 20; // quite arbitrary
+
+  public static final Address HEAP_START = chunkAlign(VM.HEAP_START, true);
+  public static final Address AVAILABLE_START = chunkAlign(VM.AVAILABLE_START, false);
+  public static final Address AVAILABLE_END = chunkAlign(VM.AVAILABLE_END, true);
+  public static final Extent AVAILABLE_BYTES = AVAILABLE_END.toWord().minus(AVAILABLE_START.toWord()).toExtent();
+  public static final int AVAILABLE_PAGES = AVAILABLE_BYTES.toWord().rshl(LOG_BYTES_IN_PAGE).toInt();
+  public static final Address HEAP_END = chunkAlign(VM.HEAP_END, false);
+
+  private static final boolean FORCE_SLOW_MAP_LOOKUP = false;
+
+  private static final int PAGES = 0;
+  private static final int MB = 1;
+  private static final int PAGES_MB = 2;
+  private static final int MB_PAGES = 3;
+
+  private static int spaceCount = 0;
+  private static Space[] spaces = new Space[MAX_SPACES];
+  private static Address heapCursor = HEAP_START;
+  private static Address heapLimit = HEAP_END;
+
+  /****************************************************************************
+   *
+   * Instance variables
+   */
+  private final String name;
+  private final int nameLength;
+  protected final int descriptor;
+  private final int index;
+  private final VMRequest vmRequest;
+
+  protected final boolean immortal;
+  protected final boolean movable;
+  protected final boolean contiguous;
+
+  protected PageResource pr;
+  protected final Address start;
+  protected final Extent extent;
+  protected Address lastDiscontiguousRegion;
+
+  private boolean allocationFailed;
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(PAGES_IN_CHUNK > 1);
+  }
+
+  /**
+   * This is the base constructor for <i>all</i> spaces.<p>
+   *
+   * @param name The name of this space (used when printing error messages etc)
+   * @param movable Are objects in this space movable?
+   * @param immortal Are objects in this space immortal (uncollected)?
+   * @param vmRequest An object describing the virtual memory requested.
+   */
+  protected Space(String name, boolean movable, boolean immortal, VMRequest vmRequest) {
+    this.name = name;
+    this.nameLength = name.length();  // necessary to avoid calling length() in uninterruptible code
+    this.movable = movable;
+    this.immortal = immortal;
+    this.vmRequest = vmRequest;
+    this.index = spaceCount++;
+    spaces[index] = this;
+
+    if (vmRequest.type == VMRequest.REQUEST_DISCONTIGUOUS) {
+      this.contiguous = false;
+      this.descriptor = SpaceDescriptor.createDescriptor();
+      this.start = Address.zero();
+      this.extent = Extent.zero();
+      this.lastDiscontiguousRegion = Address.zero();
+      VM.memory.setHeapRange(index, HEAP_START, HEAP_END); // this should really be refined!  Once we have a code space, we can be a lot more specific about what is a valid code heap area
+      return;
+    }
+
+    Address start;
+    Extent extent;
+
+    if (vmRequest.type == VMRequest.REQUEST_FRACTION) {
+      extent = getFracAvailable(vmRequest.frac);
+    } else {
+      extent = vmRequest.extent;
+    }
+
+    if (extent.NE(chunkAlign(extent, false))) {
+      VM.assertions.fail(name + " requested non-aligned extent: " + extent.toLong() + " bytes");
+    }
+
+    if (vmRequest.type == VMRequest.REQUEST_FIXED) {
+      start = vmRequest.start;
+      if (start.NE(chunkAlign(start, false))) {
+        VM.assertions.fail(name + " starting on non-aligned boundary: " + start.toLong() + " bytes");
+      }
+    } else if (vmRequest.top) {
+      heapLimit = heapLimit.minus(extent);
+      start = heapLimit;
+    } else {
+      start = heapCursor;
+      heapCursor = heapCursor.plus(extent);
+    }
+
+    if (heapCursor.GT(heapLimit)) {
+      Log.write("Out of virtual address space allocating \"");
+      Log.write(name); Log.write("\" at ");
+      Log.write(heapCursor.minus(extent)); Log.write(" (");
+      Log.write(heapCursor); Log.write(" > ");
+      Log.write(heapLimit); Log.writeln(")");
+      VM.assertions.fail("exiting");
+    }
+
+    this.contiguous = true;
+    this.start = start;
+    this.extent = extent;
+    this.descriptor = SpaceDescriptor.createDescriptor(start, start.plus(extent));
+
+    VM.memory.setHeapRange(index, start, start.plus(extent));
+    Map.insert(start, extent, descriptor, this);
+
+    if (DEBUG) {
+      Log.write(name); Log.write(" ");
+      Log.write(start); Log.write(" ");
+      Log.write(start.plus(extent)); Log.write(" ");
+      Log.writeln(extent.toWord());
+    }
+  }
+
+  /****************************************************************************
+   *
+   * Accessor methods
+   */
+
+  /** Start of discontig getter @return The start of the discontiguous space */
+  public static Address getDiscontigStart() { return heapCursor; }
+
+  /** End of discontig getter @return The end of the discontiguous space */
+  public static Address getDiscontigEnd() { return heapLimit.minus(1); }
+
+  /** Name getter @return The name of this space */
+  public final String getName() { return name; }
+
+  /** Start getter @return The start address of this space */
+  public final Address getStart() { return start; }
+
+  /** Extent getter @return The size (extent) of this space */
+  public final Extent getExtent() { return extent; }
+
+  /** Descriptor method @return The integer descriptor for this space */
+  public final int getDescriptor() { return descriptor; }
+
+  /** Index getter @return The index (ordinal number) of this space */
+  public final int getIndex() { return index; }
+
+  /** Immortal getter @return True if this space is never collected */
+  public final boolean isImmortal() { return immortal; }
+
+  /** Movable getter @return True if objects in this space may move */
+  public final boolean isMovable() { return movable; }
+
+  /** Allocationfailed getter @return true if an allocation has failed since GC */
+  public final boolean allocationFailed() { return allocationFailed; }
+
+  /** Clear Allocationfailed flag */
+  public final void clearAllocationFailed() { allocationFailed = false; }
+
+  /** ReservedPages getter @return The number of reserved pages */
+  public final int reservedPages() { return pr.reservedPages(); }
+
+  /** CommittedPages getter @return The number of committed pages */
+  public final int committedPages() { return pr.committedPages(); }
+
+  /** RequiredPages getter @return The number of required pages */
+  public final int requiredPages() { return pr.requiredPages(); }
+
+  /** AvailablePages getter @return The number of pages available for allocation */
+  public final int availablePhysicalPages() { return pr.getAvailablePhysicalPages(); }
+
+  /** Cumulative committed pages getter @return Cumulative committed pages. */
+  public static long cumulativeCommittedPages() {
+    return PageResource.cumulativeCommittedPages();
+  }
+
+  /****************************************************************************
+   *
+   * Object and address tests / accessors
+   */
+
+  /**
+   * Return true if the given object is in an immortal (uncollected) space.
+   *
+   * @param object The object in question
+   * @return True if the given object is in an immortal (uncollected) space.
+   */
+  public static boolean isImmortal(ObjectReference object) {
+    Space space = getSpaceForObject(object);
+    if (space == null)
+      return true;
+    else
+      return space.isImmortal();
+  }
+
+  /**
+   * Return true if the given object is in space that moves objects.
+   *
+   * @param object The object in question
+   * @return True if the given object is in space that moves objects.
+   */
+  @Inline
+  public static boolean isMovable(ObjectReference object) {
+    Space space = getSpaceForObject(object);
+    if (space == null)
+      return true;
+    else
+      return space.isMovable();
+  }
+
+  /**
+   * Return true if the given object is in a space managed by MMTk.
+   *
+   * @param object The object in question
+   * @return True if the given object is in a space managed by MMTk.
+   */
+  @Inline
+  public static boolean isMappedObject(ObjectReference object) {
+    return !object.isNull() && (getSpaceForObject(object) != null) && Mmapper.objectIsMapped(object);
+  }
+
+  /**
+   * Return true if the given address is in a space managed by MMTk.
+   *
+   * @param address The address in question
+   * @return True if the given address is in a space managed by MMTk.
+   */
+  @Inline
+  public static boolean isMappedAddress(Address address) {
+    return Map.getSpaceForAddress(address) != null && Mmapper.addressIsMapped(address);
+  }
+
+  /**
+   * Return true if the given object is the space associated with the
+   * given descriptor.
+   *
+   * @param descriptor The descriptor for a space
+   * @param object The object in question
+   * @return True if the given object is in the space associated with
+   * the descriptor.
+   */
+  @Inline
+  public static boolean isInSpace(int descriptor, ObjectReference object) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!object.isNull());
+    return isInSpace(descriptor, VM.objectModel.refToAddress(object));
+  }
+
+  /**
+   * Return true if the given address is the space associated with the
+   * given descriptor.
+   *
+   * @param descriptor The descriptor for a space
+   * @param address The address in question.
+   * @return True if the given address is in the space associated with
+   * the descriptor.
+   */
+  @Inline
+  public static boolean isInSpace(int descriptor, Address address) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!address.isZero());
+    if (FORCE_SLOW_MAP_LOOKUP || !SpaceDescriptor.isContiguous(descriptor)) {
+      return Map.getDescriptorForAddress(address) == descriptor;
+    } else {
+      Address start = SpaceDescriptor.getStart(descriptor);
+      if (!VM.VERIFY_ASSERTIONS &&
+          SpaceDescriptor.isContiguousHi(descriptor))
+        return address.GE(start);
+      else {
+        Extent size = Word.fromIntSignExtend(SpaceDescriptor.getChunks(descriptor)).lsh(LOG_BYTES_IN_CHUNK).toExtent();
+        Address end = start.plus(size);
+        return address.GE(start) && address.LT(end);
+      }
+    }
+  }
+
+  /**
+   * Return the space for a given object
+   *
+   * @param object The object in question
+   * @return The space containing the object
+   */
+  @Inline
+  public static Space getSpaceForObject(ObjectReference object) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!object.isNull());
+    return Map.getSpaceForAddress(VM.objectModel.refToAddress(object));
+  }
+
+  /****************************************************************************
+   *
+   * Page management
+   */
+
+  /**
+   * Acquire a number of pages from the page resource, returning
+   * either the address of the first page, or zero on failure.<p>
+   *
+   * This may trigger a GC if necessary.<p>
+   *
+   * First the page budget is checked to see whether polling the GC is
+   * necessary.  If so, the GC is polled.  If a GC is required then the
+   * request fails and zero is returned.<p>
+   *
+   * If the check of the page budget does not lead to GC being
+   * triggered, then a request is made for specific pages in virtual
+   * memory.  If the page manager cannot satisify this request, then
+   * the request fails, a GC is forced, and zero is returned.
+   * Otherwise the address of the first page is returned.<p>
+   *
+   * @param pages The number of pages requested
+   * @return The start of the first page if successful, zero on
+   * failure.
+   */
+  public final Address acquire(int pages) {
+    boolean allowPoll = !Plan.gcInProgress() && Plan.isInitialized() && !VM.collection.isEmergencyAllocation();
+
+    /* First check page budget and poll if necessary */
+    if (!pr.reservePages(pages)) {
+      /* Need to poll, either fixing budget or requiring GC */
+      if (allowPoll && VM.activePlan.global().poll(false, this)) {
+        pr.clearRequest(pages);
+        return Address.zero(); // GC required, return failure
+      }
+    }
+
+    /* Page budget is ok, try to acquire virtual memory */
+    Address rtn = pr.getNewPages(pages);
+    if (rtn.isZero()) {
+      /* Failed, so force a GC */
+      if (VM.collection.isEmergencyAllocation()) {
+        pr.clearRequest(pages);
+        VM.assertions.fail("Failed emergency allocation");
+      }
+      if (!allowPoll) VM.assertions.fail("Physical allocation failed during special (collection/emergency) allocation!");
+      allocationFailed = true;
+      VM.collection.reportPhysicalAllocationFailed();
+      VM.activePlan.global().poll(true, this);
+      pr.clearRequest(pages);
+      return Address.zero();
+    }
+
+    if (allowPoll) VM.collection.reportAllocationSuccess();
+    return rtn;
+  }
+
+  /**
+   * Extend the virtual memory associated with a particular discontiguous
+   * space.  This simply involves requesting a suitable number of chunks
+   * from the pool of chunks available to discontiguous spaces.
+   *
+   * @param chunks The number of chunks by which the space needs to be extended
+   * @return The address of the new discontiguous space.
+   */
+  public Address growDiscontiguousSpace(int chunks) {
+    this.lastDiscontiguousRegion = Map.allocateContiguousChunks(descriptor, this, chunks, lastDiscontiguousRegion);
+    return lastDiscontiguousRegion;
+  }
+
+  /**
+   * Return the number of chunks required to satisfy a request for a certain number of pages
+   *
+   * @param pages The number of pages desired
+   * @return The number of chunks needed to satisfy the request
+   */
+  public static int requiredChunks(int pages) {
+    Extent extent = chunkAlign(Extent.fromIntZeroExtend(pages<<LOG_BYTES_IN_PAGE), false);
+    return extent.toWord().rshl(LOG_BYTES_IN_CHUNK).toInt();
+  }
+
+  /**
+   * This hook is called by page resources each time a space grows.  The space may
+   * tap into the hook to monitor heap growth.  The call is made from within the
+   * page resources' critical region, immediately before yielding the lock.
+   *
+   * @param start The start of the newly allocated space
+   * @param bytes The size of the newly allocated space
+   * @param newChunk True if the new space encroached upon or started a new chunk or chunks.
+   */
+  public void growSpace(Address start, Extent bytes, boolean newChunk) {}
+
+  /**
+   * Release one or more contiguous chunks associated with a discontiguous
+   * space.
+   *
+   * @param chunk THe address of the start of the contiguous chunk or chunks
+   * @return The number of chunks freed
+   */
+  public int releaseDiscontiguousChunks(Address chunk) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(chunk.EQ(chunkAlign(chunk, true)));
+    if (chunk.EQ(lastDiscontiguousRegion)) {
+      lastDiscontiguousRegion = Map.getNextContiguousRegion(chunk);
+    }
+    return Map.freeContiguousChunks(chunk);
+  }
+
+  /**
+   * Release a unit of allocation (a page or pages)
+   *
+   * @param start The address of the start of the region to be released
+   */
+  public abstract void release(Address start);
+
+  /**
+   * Clear the allocation failed flag for all spaces.
+   *
+   */
+  public static void clearAllAllocationFailed() {
+    for (int i = 0; i < spaceCount; i++) {
+      spaces[i].clearAllocationFailed();
+    }
+  }
+
+  /**
+   * Get the total number of pages reserved by all of the spaces
+   *
+   * @return the total number of pages reserved by all of the spaces
+   */
+  private static int getPagesReserved() {
+    int pages = 0;
+    for (int i = 0; i < spaceCount; i++) {
+      pages += spaces[i].reservedPages();
+    }
+    return pages;
+  }
+
+  /****************************************************************************
+   *
+   * Debugging / printing
+   */
+
+  /**
+   * Print out the memory used by all spaces, in megabytes
+   */
+  public static void printUsageMB() { printUsage(MB); }
+
+  /**
+   * Print out the memory used by all spaces, in megabytes
+   */
+  public static void printUsagePages() { printUsage(PAGES); }
+
+  /**
+   * Print out a map of virtual memory useage by all spaces
+   */
+  public static void printVMMap() {
+    Log.writeln("Key: (I)mmortal (N)onmoving (D)iscontiguous (E)xtent (F)raction");
+    Log.write("     HEAP_START "); Log.writeln(HEAP_START);
+    Log.write("AVAILABLE_START "); Log.writeln(AVAILABLE_START);
+    for (int i = 0; i < spaceCount; i++) {
+      Space space = spaces[i];
+
+      for (int s = 0; s < 11 - space.nameLength; s++)
+        Log.write(" ");
+      Log.write(space.name); Log.write(" ");
+      Log.write(space.immortal ? "I" : " ");
+      Log.write(space.movable ? " " : "N");
+
+      if (space.contiguous) {
+        Log.write("  ");
+        Log.write(space.start); Log.write("->");
+        Log.write(space.start.plus(space.extent.minus(1)));
+        if (space.vmRequest.type == VMRequest.REQUEST_EXTENT) {
+          Log.write(" E "); Log.write(space.vmRequest.extent);
+        } else if (space.vmRequest.type == VMRequest.REQUEST_FRACTION) {
+          Log.write(" F "); Log.write(space.vmRequest.frac);
+        }
+        Log.writeln();
+      } else {
+        Log.write("D [");
+        for(Address a = space.lastDiscontiguousRegion; !a.isZero(); a = Map.getNextContiguousRegion(a)) {
+          Log.write(a); Log.write("->");
+          Log.write(a.plus(Map.getContiguousRegionSize(a).minus(1)));
+          if (Map.getNextContiguousRegion(a) != Address.zero())
+            Log.write(", ");
+        }
+        Log.writeln("]");
+      }
+    }
+    Log.write("  AVAILABLE_END "); Log.writeln(AVAILABLE_END);
+    Log.write("       HEAP_END "); Log.writeln(HEAP_END);
+  }
+
+  /**
+   * Interface to use to implement the Visitor Pattern for Spaces.
+   */
+  public static interface SpaceVisitor {
+    void visit(Space s);
+  }
+
+  /**
+   * Implement the Visitor Pattern for Spaces.
+   * @param v The visitor to perform on each Space instance
+   */
+  @Interruptible
+  public static void visitSpaces(SpaceVisitor v) {
+    for (int i = 0; i < spaceCount; i++) {
+      v.visit(spaces[i]);
+    }
+  }
+
+
+  /**
+   * Ensure that all MMTk spaces (all spaces aside from the VM space)
+   * are mapped. Demand zero map all of them if they are not already
+   * mapped.
+   */
+  @Interruptible
+  public static void eagerlyMmapMMTkSpaces() {
+    for (int i = 0; i < spaceCount; i++) {
+      Space space = spaces[i];
+      if (space != VM.memory.getVMSpace()) {
+        if (Options.verbose.getValue() > 2) {
+          Log.write("Mapping ");
+          Log.write(space.name);
+          Log.write(" ");
+          Log.write(space.start);
+          Log.write("->");
+          Log.writeln(space.start.plus(space.extent.minus(1)));
+        }
+        Mmapper.ensureMapped(space.start, space.extent.toInt()>>LOG_BYTES_IN_PAGE);
+      }
+    }
+  }
+
+  /**
+   * Print out the memory used by all spaces in either megabytes or
+   * pages.
+   *
+   * @param mode An enumeration type that specifies the format for the
+   * prining (PAGES, MB, PAGES_MB, or MB_PAGES).
+   */
+  private static void printUsage(int mode) {
+    Log.write("used = ");
+    printPages(getPagesReserved(), mode);
+    boolean first = true;
+    for (int i = 0; i < spaceCount; i++) {
+      Space space = spaces[i];
+      Log.write(first ? " = " : " + ");
+      first = false;
+      Log.write(space.name); Log.write(" ");
+      printPages(space.reservedPages(), mode);
+    }
+    Log.writeln();
+  }
+
+  /**
+   * Print out the number of pages and or megabytes, depending on the mode.
+   *
+   * @param pages The number of pages
+   * @param mode An enumeration type that specifies the format for the
+   * prining (PAGES, MB, PAGES_MB, or MB_PAGES).
+   */
+  private static void printPages(int pages, int mode) {
+    double mb = (double) (pages << LOG_BYTES_IN_PAGE) / (double) (1 << 20);
+    switch (mode) {
+    case PAGES: Log.write(pages); Log.write(" pgs"); break;
+    case MB:    Log.write(mb); Log.write(" Mb"); break;
+    case PAGES_MB: Log.write(pages); Log.write(" pgs ("); Log.write(mb); Log.write(" Mb)"); break;
+    case MB_PAGES: Log.write(mb); Log.write(" Mb ("); Log.write(pages); Log.write(" pgs)"); break;
+      default: VM.assertions.fail("writePages passed illegal printing mode");
+    }
+  }
+
+  /****************************************************************************
+   *
+   * Miscellaneous
+   */
+
+  /**
+   * Trace an object as part of a collection and return the object,
+   * which may have been forwarded (if a copying collector).
+   *
+   * @param trace The trace being conducted.
+   * @param object The object to trace
+   * @return The object, forwarded, if appropriate
+   */
+  public abstract ObjectReference traceObject(TransitiveClosure trace, ObjectReference object);
+
+
+  /**
+   * Has the object in this space been reached during the current collection.
+   * This is used for GC Tracing.
+   *
+   * @param object The object reference.
+   * @return True if the object is reachable.
+   */
+  public boolean isReachable(ObjectReference object) {
+    return isLive(object);
+  }
+
+
+  /**
+   * Is the object in this space alive?
+   *
+   * @param object The object reference.
+   * @return True if the object is live.
+   */
+  public abstract boolean isLive(ObjectReference object);
+
+  /**
+   * Align an address to a space chunk
+   *
+   * @param addr The address to be aligned
+   * @param down If true the address will be rounded down, otherwise
+   * it will rounded up.
+   */
+  public static Address chunkAlign(Address addr, boolean down) {
+    if (!down) addr = addr.plus(BYTES_IN_CHUNK - 1);
+    return addr.toWord().rshl(LOG_BYTES_IN_CHUNK).lsh(LOG_BYTES_IN_CHUNK).toAddress();
+  }
+
+  /**
+   * Align an extent to a space chunk
+   *
+   * @param bytes The extent to be aligned
+   * @param down If true the address will be rounded down, otherwise
+   * it will rounded up.
+   */
+  public static Extent chunkAlign(Extent bytes, boolean down) {
+    if (!down) bytes = bytes.plus(BYTES_IN_CHUNK - 1);
+    return bytes.toWord().rshl(LOG_BYTES_IN_CHUNK).lsh(LOG_BYTES_IN_CHUNK).toExtent();
+  }
+
+  /**
+   * Convert a fraction into a number of bytes according to the
+   * fraction of available bytes.
+   *
+   * @param frac The fraction of avialable virtual memory desired
+   * @return The corresponding number of bytes, chunk-aligned.
+   */
+  private static Extent getFracAvailable(float frac) {
+    long bytes = (long) (frac * AVAILABLE_BYTES.toLong());
+    Word mb = Word.fromIntSignExtend((int) (bytes >> LOG_BYTES_IN_MBYTE));
+    Extent rtn = mb.lsh(LOG_BYTES_IN_MBYTE).toExtent();
+    return chunkAlign(rtn, false);
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Block.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Block.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Block.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Block.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,203 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.policy.immix;
+
+import static org.mmtk.policy.immix.ImmixConstants.*;
+
+import org.mmtk.utility.Constants;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.unboxed.Address;
+import org.vmmagic.unboxed.Extent;
+import org.vmmagic.unboxed.Offset;
+
+/**
+ * This class defines operations over block-granularity meta-data
+ *
+ */
+ at Uninterruptible
+public class Block implements Constants {
+
+  static Address align(final Address ptr) {
+    return ptr.toWord().and(BLOCK_MASK.not()).toAddress();
+  }
+
+  public static boolean isAligned(final Address address) {
+    return address.EQ(align(address));
+  }
+
+  private static int getChunkIndex(final Address block) {
+    return block.toWord().and(CHUNK_MASK).rshl(LOG_BYTES_IN_BLOCK).toInt();
+  }
+
+  /***************************************************************************
+   * Block marking
+   */
+  public static boolean isUnused(final Address address) {
+    return getBlockMarkState(address) == UNALLOCATED_BLOCK_STATE;
+  }
+
+  static boolean isUnusedState(Address cursor) {
+    return cursor.loadShort() == UNALLOCATED_BLOCK_STATE;
+  }
+
+  static short getMarkState(Address cursor) {
+    return cursor.loadShort();
+  }
+
+  static void setState(Address cursor, short value) {
+    cursor.store(value);
+  }
+
+  public static short getBlockMarkState(Address address) {
+    return getBlockMarkStateAddress(address).loadShort();
+  }
+
+  static void setBlockAsInUse(Address address) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isUnused(address));
+    setBlockState(address, UNMARKED_BLOCK_STATE);
+  }
+
+  public static void setBlockAsReused(Address address) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!isUnused(address));
+    setBlockState(address, REUSED_BLOCK_STATE);
+  }
+
+  static void setBlockAsUnallocated(Address address) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!isUnused(address));
+    getBlockMarkStateAddress(address).store(UNALLOCATED_BLOCK_STATE);
+  }
+
+  private static void setBlockState(Address address, short value) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(value != UNALLOCATED_BLOCK_STATE);
+    getBlockMarkStateAddress(address).store(value);
+  }
+
+  static Address getBlockMarkStateAddress(Address address) {
+    Address chunk = Chunk.align(address);
+    int index = getChunkIndex(address);
+    Address rtn = chunk.plus(Chunk.BLOCK_STATE_TABLE_OFFSET).plus(index<<LOG_BYTES_IN_BLOCK_STATE_ENTRY);
+    if (VM.VERIFY_ASSERTIONS) {
+      Address block = chunk.plus(index<<LOG_BYTES_IN_BLOCK);
+      VM.assertions._assert(isAligned(block));
+      boolean valid = rtn.GE(chunk.plus(Chunk.BLOCK_STATE_TABLE_OFFSET)) && rtn.LT(chunk.plus(Chunk.BLOCK_STATE_TABLE_OFFSET+BLOCK_STATE_TABLE_BYTES));
+      VM.assertions._assert(valid);
+    }
+    return rtn;
+  }
+
+  /***************************************************************************
+   * Sweeping
+   */
+  static short sweepOneBlock(Address block, int[] markHistogram, final byte markState, final boolean resetMarkState) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isAligned(block));
+
+    final boolean unused = isUnused(block);
+    if (unused && !SANITY_CHECK_LINE_MARKS)
+      return 0;
+
+    Address markTable = Line.getBlockMarkTable(block);
+
+    short markCount = 0;
+    short conservativeSpillCount = 0;
+    byte mark, lastMark = 0;
+    for (int offset = 0; offset < (LINES_IN_BLOCK<<Line.LOG_BYTES_IN_LINE_STATUS); offset += Line.BYTES_IN_LINE_STATUS) {
+       if (VM.VERIFY_ASSERTIONS) {
+        VM.assertions._assert(markTable.plus(offset).GE(Chunk.align(block).plus(Chunk.LINE_MARK_TABLE_OFFSET)));
+        VM.assertions._assert(markTable.plus(offset).LT(Chunk.align(block).plus(Chunk.LINE_MARK_TABLE_OFFSET+Line.LINE_MARK_TABLE_BYTES)));
+      }
+      mark = markTable.loadByte(Offset.fromIntZeroExtend(offset));
+      if (resetMarkState)
+        markTable.store((byte) (mark == markState ? RESET_LINE_MARK_STATE : 0), Offset.fromIntZeroExtend(offset));
+
+      if (mark == markState)
+        markCount++;
+      else if (lastMark == markState)
+        conservativeSpillCount++;
+      else if (SANITY_CHECK_LINE_MARKS && lastMark != markState) {
+        VM.memory.zero(block.plus(offset<<(LOG_BYTES_IN_LINE-Line.LOG_BYTES_IN_LINE_STATUS)),Extent.fromIntZeroExtend(BYTES_IN_LINE));
+      }
+
+      lastMark = mark;
+    }
+    if (VM.VERIFY_ASSERTIONS) {
+      VM.assertions._assert(markCount <= LINES_IN_BLOCK);
+      VM.assertions._assert(markCount + conservativeSpillCount <= LINES_IN_BLOCK);
+      VM.assertions._assert(markCount == 0 || !isUnused(block));
+    }
+
+    getDefragStateAddress(block).store(conservativeSpillCount);
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(markCount >= conservativeSpillCount);
+    markHistogram[conservativeSpillCount] += markCount;
+
+    markCount = (short) (markCount + conservativeSpillCount);
+
+    return markCount;
+  }
+
+  /****************************************************************************
+   * Block defrag state
+   */
+  public static boolean isDefragSource(Address address) {
+    return getDefragStateAddress(address).loadShort() == BLOCK_IS_DEFRAG_SOURCE;
+  }
+
+  static void clearConservativeSpillCount(Address address) {
+    getDefragStateAddress(address).store((short) 0);
+  }
+
+  static short getConservativeSpillCount(Address address) {
+    return getDefragStateAddress(address).loadShort();
+  }
+
+  static Address getDefragStateAddress(Address address) {
+    Address chunk = Chunk.align(address);
+    int index = getChunkIndex(address);
+    Address rtn = chunk.plus(Chunk.BLOCK_DEFRAG_STATE_TABLE_OFFSET).plus(index<<LOG_BYTES_IN_BLOCK_DEFRAG_STATE_ENTRY);
+    if (VM.VERIFY_ASSERTIONS) {
+      Address block = chunk.plus(index<<LOG_BYTES_IN_BLOCK);
+      VM.assertions._assert(isAligned(block));
+      boolean valid = rtn.GE(chunk.plus(Chunk.BLOCK_DEFRAG_STATE_TABLE_OFFSET)) && rtn.LT(chunk.plus(Chunk.BLOCK_DEFRAG_STATE_TABLE_OFFSET+BLOCK_DEFRAG_STATE_TABLE_BYTES));
+      VM.assertions._assert(valid);
+    }
+    return rtn;
+  }
+
+  static void resetLineMarksAndDefragStateTable(short threshold, Address markStateBase, Address defragStateBase,
+      Address lineMarkBase, int block) {
+    Offset csOffset = Offset.fromIntZeroExtend(block<<LOG_BYTES_IN_BLOCK_DEFRAG_STATE_ENTRY);
+    short state = defragStateBase.loadShort(csOffset);
+    short defragState = BLOCK_IS_NOT_DEFRAG_SOURCE;
+    if (state >= threshold) defragState = BLOCK_IS_DEFRAG_SOURCE;
+    defragStateBase.store(defragState, csOffset);
+  }
+
+  private static final short UNALLOCATED_BLOCK_STATE = 0;
+  private static final short UNMARKED_BLOCK_STATE = (short) (MAX_BLOCK_MARK_STATE + 1);
+  private static final short REUSED_BLOCK_STATE = (short) (MAX_BLOCK_MARK_STATE + 2);
+
+  private static final short BLOCK_IS_NOT_DEFRAG_SOURCE = 0;
+  private static final short BLOCK_IS_DEFRAG_SOURCE = 1;
+
+  /* block states */
+  static final int LOG_BYTES_IN_BLOCK_STATE_ENTRY = LOG_BYTES_IN_SHORT; // use a short for now
+  static final int BYTES_IN_BLOCK_STATE_ENTRY = 1<<LOG_BYTES_IN_BLOCK_STATE_ENTRY;
+  static final int BLOCK_STATE_TABLE_BYTES = BLOCKS_IN_CHUNK<<LOG_BYTES_IN_BLOCK_STATE_ENTRY;
+
+  /* per-block defrag state */
+  static final int LOG_BYTES_IN_BLOCK_DEFRAG_STATE_ENTRY = LOG_BYTES_IN_SHORT;
+  static final int BYTES_IN_BLOCK_DEFRAG_STATE_ENTRY = 1<<LOG_BYTES_IN_BLOCK_DEFRAG_STATE_ENTRY;
+
+  static final int BLOCK_DEFRAG_STATE_TABLE_BYTES = BLOCKS_IN_CHUNK<<LOG_BYTES_IN_BLOCK_DEFRAG_STATE_ENTRY;
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Chunk.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Chunk.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Chunk.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Chunk.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,166 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.policy.immix;
+
+import static org.mmtk.policy.Space.BYTES_IN_CHUNK;
+import static org.mmtk.policy.immix.ImmixConstants.*;
+
+import org.mmtk.utility.Constants;
+import org.mmtk.utility.Conversions;
+import org.mmtk.utility.heap.Mmapper;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.unboxed.Address;
+import org.vmmagic.unboxed.Extent;
+
+ at Uninterruptible
+public class Chunk implements Constants {
+
+  public static Address align(Address ptr) {
+    return ptr.toWord().and(CHUNK_MASK.not()).toAddress();
+  }
+
+  static boolean isAligned(Address ptr) {
+    return ptr.EQ(align(ptr));
+  }
+
+  static int getByteOffset(Address ptr) {
+    return ptr.toWord().and(CHUNK_MASK).toInt();
+  }
+
+  /**
+   * Return the number of pages of metadata required per chunk.
+   */
+  static int getRequiredMetaDataPages() {
+    Extent bytes = Extent.fromIntZeroExtend(ROUNDED_METADATA_BYTES_PER_CHUNK);
+    return Conversions.bytesToPagesUp(bytes);
+  }
+
+  static void sweep(Address chunk, Address end, ImmixSpace space, int[] markHistogram, final byte markValue, final boolean resetMarks) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isAligned(chunk));
+    Address start = getFirstUsableBlock(chunk);
+    Address cursor = Block.getBlockMarkStateAddress(start);
+    for (int index = FIRST_USABLE_BLOCK_INDEX; index < BLOCKS_IN_CHUNK; index++) {
+      Address block = chunk.plus(index<<LOG_BYTES_IN_BLOCK);
+      if (block.GT(end)) break;
+      final boolean defragSource = space.inImmixDefragCollection() && Block.isDefragSource(block);
+      short marked = Block.sweepOneBlock(block, markHistogram, markValue, resetMarks);
+      if (marked == 0) {
+        if (!Block.isUnusedState(cursor)) {
+          space.release(block);
+          if (defragSource) Defrag.defragBytesFreed.inc(BYTES_IN_BLOCK);
+        }
+        if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Block.isUnused(block));
+      } else {
+        if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(marked > 0 && marked <= LINES_IN_BLOCK);
+        Block.setState(cursor, marked);
+        if (defragSource) Defrag.defragBytesNotFreed.inc(BYTES_IN_BLOCK);
+      }
+      if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Block.isUnused(block) || (Block.getBlockMarkState(block) == marked && marked > 0 && marked <= MAX_BLOCK_MARK_STATE));
+      cursor = cursor.plus(Block.BYTES_IN_BLOCK_STATE_ENTRY);
+    }
+  }
+
+  static void clearMetaData(Address chunk) {
+    if (VM.VERIFY_ASSERTIONS) {
+      VM.assertions._assert(isAligned(chunk));
+      VM.assertions._assert(Conversions.isPageAligned(chunk));
+      VM.assertions._assert(Conversions.isPageAligned(ROUNDED_METADATA_BYTES_PER_CHUNK));
+    }
+    Mmapper.ensureMapped(chunk, ROUNDED_METADATA_PAGES_PER_CHUNK);
+    VM.memory.zero(chunk, Extent.fromIntZeroExtend(ROUNDED_METADATA_BYTES_PER_CHUNK));
+    if (VM.VERIFY_ASSERTIONS) checkMetaDataCleared(chunk, chunk);
+  }
+
+  private static void checkMetaDataCleared(Address chunk, Address value) {
+    VM.assertions._assert(isAligned(chunk));
+    Address block = Chunk.getHighWater(chunk);
+    if (value.EQ(chunk)) {
+      VM.assertions._assert(block.isZero());
+      block = chunk.plus(Chunk.ROUNDED_METADATA_BYTES_PER_CHUNK);
+    } else {
+      block = block.plus(BYTES_IN_BLOCK); // start at first block after highwater
+      VM.assertions._assert(Block.align(block).EQ(block));
+    }
+    while (block.LT(chunk.plus(BYTES_IN_CHUNK))) {
+      VM.assertions._assert(Chunk.align(block).EQ(chunk));
+      VM.assertions._assert(Block.isUnused(block));
+      block = block.plus(BYTES_IN_BLOCK);
+    }
+  }
+
+  static void updateHighWater(Address value) {
+    Address chunk = align(value);
+    if (getHighWater(chunk).LT(value)) {
+      setHighWater(chunk, value);
+    }
+  }
+
+  private static void setHighWater(Address chunk, Address value) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isAligned(chunk));
+    chunk.plus(HIGHWATER_OFFSET).store(value);
+  }
+
+  public static Address getHighWater(Address chunk) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isAligned(chunk));
+    return chunk.plus(HIGHWATER_OFFSET).loadAddress();
+  }
+
+  static void setMap(Address chunk, int value) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isAligned(chunk));
+    chunk.plus(MAP_OFFSET).store(value);
+  }
+
+  static int getMap(Address chunk) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isAligned(chunk));
+    int rtn = chunk.plus(MAP_OFFSET).loadInt();
+    return (rtn < 0) ? -rtn : rtn;
+  }
+
+  static void resetLineMarksAndDefragStateTable(Address chunk, short threshold) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isAligned(chunk));
+    Address markStateBase = Block.getBlockMarkStateAddress(chunk);
+    Address defragStateBase = Block.getDefragStateAddress(chunk);
+    Address lineMarkBase = Line.getChunkMarkTable(chunk);
+    for (int b = FIRST_USABLE_BLOCK_INDEX; b < BLOCKS_IN_CHUNK; b++) {
+      Block.resetLineMarksAndDefragStateTable(threshold, markStateBase, defragStateBase, lineMarkBase, b);
+    }
+  }
+
+  static Address getFirstUsableBlock(Address chunk) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isAligned(chunk));
+    Address rtn = chunk.plus(ROUNDED_METADATA_BYTES_PER_CHUNK);
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(rtn.EQ(Block.align(rtn)));
+    return rtn;
+  }
+
+  private static final int LOG_BYTES_IN_HIGHWATER_ENTRY = LOG_BYTES_IN_ADDRESS;
+  private static final int HIGHWATER_BYTES = 1<<LOG_BYTES_IN_HIGHWATER_ENTRY;
+  private static final int LOG_BYTES_IN_MAP_ENTRY = LOG_BYTES_IN_INT;
+  private static final int MAP_BYTES = 1<<LOG_BYTES_IN_MAP_ENTRY;
+
+  /* byte offsets for each type of metadata */
+  static final int LINE_MARK_TABLE_OFFSET = 0;
+  static final int BLOCK_STATE_TABLE_OFFSET = LINE_MARK_TABLE_OFFSET + Line.LINE_MARK_TABLE_BYTES;
+  static final int BLOCK_DEFRAG_STATE_TABLE_OFFSET = BLOCK_STATE_TABLE_OFFSET + Block.BLOCK_STATE_TABLE_BYTES;
+  static final int HIGHWATER_OFFSET = BLOCK_DEFRAG_STATE_TABLE_OFFSET + Block.BLOCK_DEFRAG_STATE_TABLE_BYTES;
+  static final int MAP_OFFSET = HIGHWATER_OFFSET + HIGHWATER_BYTES;
+  static final int METADATA_BYTES_PER_CHUNK = MAP_OFFSET + MAP_BYTES;
+
+  /* FIXME we round the metadata up to block sizes just to ensure the underlying allocator gives us aligned requests */
+  private static final int BLOCK_MASK = (1<<LOG_BYTES_IN_BLOCK) - 1;
+  static final int ROUNDED_METADATA_BYTES_PER_CHUNK = (METADATA_BYTES_PER_CHUNK + BLOCK_MASK) & ~BLOCK_MASK;
+  static final int ROUNDED_METADATA_PAGES_PER_CHUNK = ROUNDED_METADATA_BYTES_PER_CHUNK>>LOG_BYTES_IN_PAGE;
+  public static final int FIRST_USABLE_BLOCK_INDEX = ROUNDED_METADATA_BYTES_PER_CHUNK>>LOG_BYTES_IN_BLOCK;
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ChunkList.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ChunkList.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ChunkList.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ChunkList.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,183 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.policy.immix;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.Constants;
+import org.mmtk.vm.VM;
+import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.unboxed.Address;
+import org.vmmagic.unboxed.AddressArray;
+
+ at Uninterruptible
+public final class ChunkList implements Constants {
+  private static final int LOG_PAGES_IN_CHUNK_MAP_BLOCK = 0;
+  private static final int ENTRIES_IN_CHUNK_MAP_BLOCK = (BYTES_IN_PAGE<<LOG_PAGES_IN_CHUNK_MAP_BLOCK)>>LOG_BYTES_IN_ADDRESS;
+  private static final int CHUNK_MAP_BLOCKS = 1<<4;
+  private static final int MAX_ENTRIES_IN_CHUNK_MAP = ENTRIES_IN_CHUNK_MAP_BLOCK * CHUNK_MAP_BLOCKS;
+  private AddressArray chunkMap =  AddressArray.create(CHUNK_MAP_BLOCKS);
+  private int chunkMapLimit = -1;
+  private int chunkMapCursor = -1;
+
+  void reset() {
+    chunkMapLimit = chunkMapCursor;
+  }
+
+  public Address getHeadChunk() {
+    if (chunkMapLimit < 0)
+      return Address.zero();
+    else
+      return getMapAddress(0).loadAddress();
+  }
+
+  public Address getTailChunk() {
+    if (chunkMapLimit < 0)
+      return Address.zero();
+    else
+      return getMapAddress(chunkMapLimit).loadAddress();
+  }
+
+  void addNewChunkToMap(Address chunk) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Chunk.isAligned(chunk));
+    if (chunkMapCursor == MAX_ENTRIES_IN_CHUNK_MAP - 1)
+      consolidateMap();
+    chunkMapCursor++;
+    int index = getChunkIndex(chunkMapCursor);
+    int map = getChunkMap(chunkMapCursor);
+    if (map >= CHUNK_MAP_BLOCKS) {
+      Space.printUsageMB();
+      VM.assertions.fail("Overflow of chunk map!");
+    }
+    if (chunkMap.get(map).isZero()) {
+      Address tmp = Plan.metaDataSpace.acquire(1<<LOG_PAGES_IN_CHUNK_MAP_BLOCK);
+      if (tmp.isZero()) {
+        Space.printUsageMB();
+        VM.assertions.fail("Failed to allocate space for chunk map.  Is metadata virtual memory exhausted?");
+      }
+      chunkMap.set(map, tmp);
+    }
+    Address entry = chunkMap.get(map).plus(index<<LOG_BYTES_IN_ADDRESS);
+    entry.store(chunk);
+    Chunk.setMap(chunk, chunkMapCursor);
+    if (VM.VERIFY_ASSERTIONS) checkMap();
+  }
+
+  void removeChunkFromMap(Address chunk) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Chunk.isAligned(chunk));
+    int entry = Chunk.getMap(chunk);
+    getMapAddress(entry).store(Address.zero());  // zero it it
+    Chunk.setMap(chunk, -entry);
+    if (VM.VERIFY_ASSERTIONS) checkMap();
+  }
+
+  private int getChunkIndex(int entry) { return entry & (ENTRIES_IN_CHUNK_MAP_BLOCK - 1);}
+  private int getChunkMap(int entry) {return entry & ~(ENTRIES_IN_CHUNK_MAP_BLOCK - 1);}
+
+  private Address getMapAddress(int entry) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(entry >= 0);
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(entry <= chunkMapCursor);
+    int index = getChunkIndex(entry);
+    int map = getChunkMap(entry);
+    return chunkMap.get(map).plus(index<<LOG_BYTES_IN_ADDRESS);
+  }
+
+  /**
+   * A chunk iterator.  Return the next chunk in sequence, or null if the
+   * next chunk is the same chunk (ie there is only one chunk in the iterator).
+   *
+   * @param chunk The chunk
+   * @return The next chunk in the sequence, or null if next is chunk.
+   */
+  public Address nextChunk(Address chunk) {
+    return nextChunk(chunk, chunk);
+  }
+
+  /**
+   * A chunk iterator.  Return the next chunk in sequence, or null if the
+   * next chunk is limit.
+   *
+   * @param chunk The chunk
+   * @param limit The starting point (if next is equal to this, we're done)
+   * @return The next chunk in the sequence, or null if next is limit.
+   */
+  private Address nextChunk(final Address chunk, final Address limit) {
+    return nextChunk(chunk, Chunk.getMap(limit), 1);
+  }
+
+  /**
+   * A chunk iterator.  Return the next chunk in sequence, strided
+   * by stride steps, or null if the next chunk is start.
+   *
+   * @param chunk The chunk
+   * @param start The point where this iterator started, which defines its end-point
+   * @param stride The stride by which the iterator should be stepped
+   * @return The next chunk in the sequence, or null if next is start.
+   */
+  public Address nextChunk(final Address chunk, final int start, final int stride) {
+    if (VM.VERIFY_ASSERTIONS) checkMap();
+    return nextChunk(Chunk.getMap(chunk), start, stride);
+  }
+
+  /**
+   * A chunk iterator.  Return the next chunk in sequence, strided
+   * by stride steps, or null if the next chunk is start.
+   *
+   * @param entry The entry we're currently up to
+   * @param start The point where this iterator started, which defines its end-point
+   * @param stride The stride by which the iterator should be stepped
+   * @return The next chunk in the sequence, or null if next is start.
+   */
+  private Address nextChunk(int entry, final int start, final int stride) {
+    if (VM.VERIFY_ASSERTIONS) checkMap();
+    Address chunk;
+    do {
+      entry += stride;
+      if (entry > chunkMapLimit) { entry = entry % stride; }
+      chunk = getMapAddress(entry).loadAddress();
+    } while (chunk.isZero() && entry != start);
+    return entry == start ? Address.zero() : chunk;
+  }
+
+  public Address firstChunk(int ordinal, int stride) {
+    if (ordinal > chunkMapCursor) return Address.zero();
+    if (VM.VERIFY_ASSERTIONS) checkMap();
+    Address chunk = getMapAddress(ordinal).loadAddress();
+    return chunk.isZero() ? nextChunk(ordinal, ordinal, stride) : chunk;
+  }
+
+  private void checkMap() {
+    VM.assertions._assert(chunkMapLimit <= chunkMapCursor);
+    for (int entry = 0; entry <= chunkMapCursor; entry++) {
+      Address chunk = getMapAddress(entry).loadAddress();
+      if (!chunk.isZero())
+        VM.assertions._assert(Chunk.getMap(chunk) == entry);
+    }
+  }
+
+  public void consolidateMap() {
+    int oldCursor = 0;
+    int newCursor = -1;
+    while (oldCursor <= chunkMapCursor) {
+      Address chunk = getMapAddress(oldCursor).loadAddress();
+      if (!chunk.isZero()) {
+        getMapAddress(++newCursor).store(chunk);
+        Chunk.setMap(chunk, newCursor);
+      }
+      oldCursor++;
+    }
+    chunkMapCursor = newCursor;
+    chunkMapLimit = newCursor;
+    if (VM.VERIFY_ASSERTIONS) checkMap();
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/CollectorLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/CollectorLocal.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/CollectorLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/CollectorLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,114 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.policy.immix;
+
+import static org.mmtk.policy.immix.ImmixConstants.*;
+
+import org.mmtk.utility.Constants;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.Address;
+
+/**
+ * This class implements unsynchronized (local) elements of an
+ * immix collector.  Marking is done using both a bit in
+ * each header's object word, and a mark byte.  Sweeping is
+ * performed lazily.<p>
+ *
+ */
+ at Uninterruptible
+public final class CollectorLocal implements Constants {
+
+  /****************************************************************************
+   *
+   * Class variables
+   */
+
+
+  /****************************************************************************
+   *
+   * Instance variables
+   */
+  private final ImmixSpace immixSpace;
+  private final ChunkList chunkMap;
+  private final Defrag defrag;
+
+
+  /****************************************************************************
+   *
+   * Initialization
+   */
+
+  /**
+   * Constructor
+   *
+   * @param space The mark-sweep space to which this allocator
+   * instances is bound.
+   */
+  public CollectorLocal(ImmixSpace space) {
+    immixSpace = space;
+    chunkMap = immixSpace.getChunkMap();
+    defrag = immixSpace.getDefrag();
+  }
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Prepare for a collection. If paranoid, perform a sanity check.
+   */
+  public void prepare(boolean majorGC) {
+    int ordinal = VM.collection.activeGCThreadOrdinal();
+    if (majorGC) {
+      if (immixSpace.inImmixDefragCollection()) {
+        short threshold = Defrag.defragSpillThreshold;
+        resetLineMarksAndDefragStateTable(ordinal, threshold);
+      }
+    }
+  }
+
+  private void resetLineMarksAndDefragStateTable(int ordinal, final short threshold) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(immixSpace.inImmixDefragCollection());
+    int stride = VM.collection.activeGCThreads();
+    Address chunk = chunkMap.firstChunk(ordinal, stride);
+    while (!chunk.isZero()) {
+      Chunk.resetLineMarksAndDefragStateTable(chunk, threshold);
+      chunk = chunkMap.nextChunk(chunk, ordinal, stride);
+    }
+  }
+
+  /**
+   * Finish up after a collection.
+   *
+   * We help sweeping all the blocks in parallel.
+   */
+  public void release(boolean majorGC) {
+    sweepAllBlocks(majorGC);
+  }
+
+  private void sweepAllBlocks(boolean majorGC) {
+    int stride = VM.collection.activeGCThreads();
+    int ordinal = VM.collection.activeGCThreadOrdinal();
+    int[] markSpillHisto = defrag.getAndZeroSpillMarkHistogram(ordinal);
+    Address chunk = chunkMap.firstChunk(ordinal, stride);
+    final byte markValue = immixSpace.lineMarkState;
+    final boolean resetMarks = majorGC && markValue == MAX_LINE_MARK_STATE;
+    while (!chunk.isZero()) {
+      Chunk.sweep(chunk, Chunk.getHighWater(chunk), immixSpace, markSpillHisto, markValue, resetMarks);
+      chunk = chunkMap.nextChunk(chunk, ordinal, stride);
+    }
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Defrag.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Defrag.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Defrag.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Defrag.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,189 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+
+package org.mmtk.policy.immix;
+
+import static org.mmtk.policy.immix.ImmixConstants.*;
+
+
+import org.mmtk.utility.Constants;
+import org.mmtk.utility.Log;
+import org.mmtk.utility.heap.FreeListPageResource;
+import org.mmtk.utility.options.DefragFreeHeadroom;
+import org.mmtk.utility.options.DefragFreeHeadroomFraction;
+import org.mmtk.utility.options.DefragHeadroom;
+import org.mmtk.utility.options.DefragHeadroomFraction;
+import org.mmtk.utility.options.DefragLineReuseRatio;
+import org.mmtk.utility.options.DefragSimpleSpillThreshold;
+import org.mmtk.utility.options.DefragStress;
+import org.mmtk.utility.options.Options;
+import org.mmtk.utility.statistics.EventCounter;
+import org.mmtk.utility.statistics.SizeCounter;
+import org.mmtk.vm.Collection;
+import org.mmtk.vm.VM;
+import org.vmmagic.pragma.Uninterruptible;
+
+ at Uninterruptible
+public class Defrag  implements Constants {
+
+
+  private int defragHeadroomPages = 0;
+  private int defragFreeHeadroomPages = 0;
+  private boolean inDefragCollection = false;
+  private int debugBytesDefraged = 0;
+  private int availableCleanPagesForDefrag;
+  private boolean defragSpaceExhausted = true;
+  private int[][] spillMarkHistograms = new int[MAX_COLLECTORS][SPILL_HISTOGRAM_BUCKETS];
+  private int[] spillAvailHistogram = new int[SPILL_HISTOGRAM_BUCKETS];
+  public static SizeCounter defragCleanBytesUsed = new SizeCounter("cleanUsed");
+  /* verbose stats (used only on stats runs since they induce overhead when gathred) */
+  public static SizeCounter defragBytesNotFreed = new SizeCounter("bytesNotFreed");
+  public static SizeCounter defragBytesFreed = new SizeCounter("bytesFreed");
+  public static SizeCounter defragCleanBytesAvailable = new SizeCounter("cleanAvail");
+
+  private final FreeListPageResource pr;
+  private boolean debugCollectionTypeDetermined = false;
+  static short defragSpillThreshold = 0;
+  static short defragReusableMarkStateThreshold = 0;
+  public static EventCounter defrags = new EventCounter("defrags");
+
+  static {
+    Options.defragLineReuseRatio = new DefragLineReuseRatio();
+    Options.defragHeadroom = new DefragHeadroom();
+    Options.defragHeadroomFraction = new DefragHeadroomFraction();
+    Options.defragFreeHeadroom = new DefragFreeHeadroom();
+    Options.defragFreeHeadroomFraction = new DefragFreeHeadroomFraction();
+    Options.defragSimpleSpillThreshold = new DefragSimpleSpillThreshold();
+    Options.defragStress = new DefragStress();
+    defragReusableMarkStateThreshold = (short) (Options.defragLineReuseRatio.getValue() * MAX_BLOCK_MARK_STATE);
+  }
+
+  Defrag(FreeListPageResource pr) {
+    this.pr = pr;
+  }
+
+  boolean inDefrag() { return inDefragCollection; }
+
+  void prepare(ChunkList chunkMap, ImmixSpace space) {
+    if (defragHeadroomPages > 0)
+      pr.unconditionallyReleasePages(defragHeadroomPages);
+
+    availableCleanPagesForDefrag = VM.activePlan.global().getTotalPages() - VM.activePlan.global().getPagesReserved();
+    if (availableCleanPagesForDefrag < 0) availableCleanPagesForDefrag = 0;
+    defragSpaceExhausted = false;
+    availableCleanPagesForDefrag += defragFreeHeadroomPages;
+    if (inDefragCollection) {
+      if (Options.verbose.getValue() > 0) {
+        Log.write("[Defrag]");
+      }
+      chunkMap.consolidateMap();
+      establishDefragSpillThreshold(chunkMap, space);
+      defrags.inc();
+      defragCleanBytesAvailable.inc(availableCleanPagesForDefrag<<LOG_BYTES_IN_PAGE);
+    }
+    availableCleanPagesForDefrag += VM.activePlan.global().getCollectionReserve();
+  }
+
+  void globalRelease() {
+    if (Options.defragHeadroom.getPages() > 0)
+      defragHeadroomPages = Options.defragHeadroom.getPages();
+    else if (Options.defragHeadroomFraction.getValue() > 0)
+      defragHeadroomPages = (int) (pr.reservedPages() * Options.defragHeadroomFraction.getValue());
+    else
+      defragHeadroomPages = 0;
+    if (Options.defragFreeHeadroom.getPages() > 0)
+      defragFreeHeadroomPages = Options.defragFreeHeadroom.getPages();
+    else if (Options.defragFreeHeadroomFraction.getValue() > 0)
+      defragFreeHeadroomPages = (int) (pr.reservedPages() * Options.defragFreeHeadroomFraction.getValue());
+    else
+      defragFreeHeadroomPages = 0;
+
+    if (defragHeadroomPages > 0)
+      pr.unconditionallyReservePages(defragHeadroomPages);
+
+    if (inDefragCollection && Options.verbose.getValue() > 2) {
+      Log.write("(Defrag summary: cu: "); defragCleanBytesUsed.printCurrentVolume();
+      Log.write(" nf: "); defragBytesNotFreed.printCurrentVolume();
+      Log.write(" fr: "); defragBytesFreed.printCurrentVolume();
+      Log.write(" av: "); defragCleanBytesAvailable.printCurrentVolume();
+      Log.write(")");
+    }
+
+    inDefragCollection = false;
+    debugCollectionTypeDetermined = false;
+  }
+
+  void decideWhetherToDefrag(boolean emergencyCollection, boolean collectWholeHeap, int collectionAttempt, int collectionTrigger, boolean exhaustedReusableSpace) {
+    boolean userTriggered = collectionTrigger == Collection.EXTERNAL_GC_TRIGGER && Options.fullHeapSystemGC.getValue();
+    inDefragCollection =  (collectionAttempt > 1) ||
+        emergencyCollection ||
+        collectWholeHeap && (Options.defragStress.getValue() || userTriggered);
+    if (inDefragCollection) {
+      debugBytesDefraged = 0;
+    }
+    debugCollectionTypeDetermined = true;
+  }
+
+  boolean determined(boolean inDefrag) { return debugCollectionTypeDetermined && !(inDefrag ^ inDefragCollection); }
+
+  void getBlock() {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!inDefragCollection || !defragSpaceExhausted);
+    if (availableCleanPagesForDefrag <= 0)
+      defragSpaceExhausted = true;
+    availableCleanPagesForDefrag -= PAGES_IN_BLOCK;
+    debugBytesDefraged += BYTES_IN_BLOCK;
+    Defrag.defragCleanBytesUsed.inc(BYTES_IN_BLOCK);
+  }
+
+  private void establishDefragSpillThreshold(ChunkList chunkMap, ImmixSpace space) {
+    int cleanLines = space.getAvailableLines(spillAvailHistogram);
+    int availableLines = cleanLines + availableCleanPagesForDefrag<<(LOG_BYTES_IN_PAGE - LOG_BYTES_IN_LINE);
+
+    int requiredLines = 0;
+    short threshold = (short) MAX_CONSV_SPILL_COUNT;
+    int limit = (int) (availableLines / Options.defragLineReuseRatio.getValue());
+    if (VM.VERIFY_ASSERTIONS && Options.verbose.getValue() > 2) {
+      Log.write("[threshold: "); Log.write("cl: "); Log.write(cleanLines);
+      Log.write(" al: "); Log.write(availableLines);
+      Log.write(" lm: "); Log.write(limit);
+    }
+    int collectors = VM.activePlan.collectorCount();
+    for (short index = MAX_CONSV_SPILL_COUNT; index >= TMP_MIN_SPILL_THRESHOLD && limit > requiredLines; index--) {
+      threshold = (short) index;
+      int thisBucketMark = 0;
+      int thisBucketAvail = 0;
+      for (int c = 0; c < collectors; c++) thisBucketMark += spillMarkHistograms[c][threshold];
+
+      thisBucketAvail = spillAvailHistogram[threshold];
+      limit -= thisBucketAvail;
+      requiredLines += thisBucketMark;
+      if (VM.VERIFY_ASSERTIONS && Options.verbose.getValue() > 2) {
+        Log.write(" ("); Log.write(index); Log.write(" "); Log.write(limit); Log.write(","); Log.write(requiredLines); Log.write(")");
+      }
+    }
+    if (VM.VERIFY_ASSERTIONS && Options.verbose.getValue() > 2) {
+      Log.write(" threshold: "); Log.write(threshold); Log.write("]");
+    }
+    defragSpillThreshold = threshold;
+  }
+
+
+  boolean spaceExhausted() { return defragSpaceExhausted; }
+
+  int[] getAndZeroSpillMarkHistogram(int ordinal) {
+    int[] rtn = spillMarkHistograms[ordinal];
+    for (int i = 0; i < SPILL_HISTOGRAM_BUCKETS; i++)
+      rtn[i] = 0;
+    return rtn;
+  }
+}

Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ImmixConstants.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ImmixConstants.java?rev=75904&view=auto

==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ImmixConstants.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ImmixConstants.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,78 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Eclipse Public License (EPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package org.mmtk.policy.immix;
+
+import static org.mmtk.policy.Space.BYTES_IN_CHUNK;
+import static org.mmtk.policy.Space.LOG_BYTES_IN_CHUNK;
+import static org.mmtk.utility.Constants.LOG_BYTES_IN_PAGE;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.vm.VM;
+import org.vmmagic.unboxed.Word;
+
+public class ImmixConstants {
+  public static final boolean BUILD_FOR_STICKYIMMIX = Plan.NEEDS_LOG_BIT_IN_HEADER;
+
+  /* start temporary experimental constants --- should not be allowed to lurk longer than necessary */
+  public static final int TMP_MIN_SPILL_THRESHOLD = 2;
+  public static final boolean TMP_PREFER_COPY_ON_NURSERY_GC = true;
+  /* end temporary experimental constants */
+
+  static final byte MAX_LINE_MARK_STATE = 127;
+  static final byte RESET_LINE_MARK_STATE = 1;
+
+  public static final boolean MARK_LINE_AT_SCAN_TIME = true; // else do it at mark time
+
+  public static final boolean SANITY_CHECK_LINE_MARKS = false && VM.VERIFY_ASSERTIONS;
+
+  public static final float DEFAULT_LINE_REUSE_RATIO = (float) 0.99;
+  public static final float DEFAULT_DEFRAG_LINE_REUSE_RATIO = (float) 0.99;
+  public static final float DEFAULT_SIMPLE_SPILL_THRESHOLD = (float) 0.25;
+  public static final int DEFAULT_DEFRAG_HEADROOM = 0; // number of pages.
+  public static final float DEFAULT_DEFRAG_HEADROOM_FRACTION = (float) 0.020;
+  public static final int DEFAULT_DEFRAG_FREE_HEADROOM = 0; // number of pages.  This should only deviate from zero for analytical purposes.  Otherwise the defragmenter is cheating!
+  public static final float DEFAULT_DEFRAG_FREE_HEADROOM_FRACTION = (float) 0.0;
+  /* sizes etc */
+  static final int LOG_BYTES_IN_BLOCK = (LOG_BYTES_IN_PAGE > 15 ? LOG_BYTES_IN_PAGE : 15);
+  public static final int BYTES_IN_BLOCK = 1<<LOG_BYTES_IN_BLOCK;
+  static final int LOG_PAGES_IN_BLOCK = LOG_BYTES_IN_BLOCK - LOG_BYTES_IN_PAGE;
+  static final int PAGES_IN_BLOCK = 1<<LOG_PAGES_IN_BLOCK;
+  static final int LOG_BLOCKS_IN_CHUNK = LOG_BYTES_IN_CHUNK-LOG_BYTES_IN_BLOCK;
+  static final int BLOCKS_IN_CHUNK = 1<<LOG_BLOCKS_IN_CHUNK;
+
+  public static final int LOG_BYTES_IN_LINE = 8;
+  static final int LOG_LINES_IN_BLOCK = LOG_BYTES_IN_BLOCK - LOG_BYTES_IN_LINE;
+  public static final short LINES_IN_BLOCK = (short) (1<<LOG_LINES_IN_BLOCK);
+  static final int LOG_LINES_IN_CHUNK = LOG_BYTES_IN_CHUNK - LOG_BYTES_IN_LINE;
+  static final int LINES_IN_CHUNK = 1<<LOG_LINES_IN_CHUNK;
+
+  public static final int BYTES_IN_LINE = 1<<LOG_BYTES_IN_LINE;
+
+  public static final int MAX_IMMIX_OBJECT_BYTES = BYTES_IN_BLOCK>>1;
+
+  private static final int LOG_BLOCKS_IN_RECYCLE_ALLOC_CHUNK = 4; // 3 + 15 -> 19 (512KB)
+  private static final int LOG_BYTES_IN_RECYCLE_ALLOC_CHUNK = LOG_BLOCKS_IN_RECYCLE_ALLOC_CHUNK + LOG_BYTES_IN_BLOCK;
+  static final int BYTES_IN_RECYCLE_ALLOC_CHUNK = 1<<LOG_BYTES_IN_RECYCLE_ALLOC_CHUNK;
+
+  public static final short MAX_BLOCK_MARK_STATE = LINES_IN_BLOCK;
+         static final short MAX_CONSV_SPILL_COUNT = (short) (LINES_IN_BLOCK/2);
+  public static final short SPILL_HISTOGRAM_BUCKETS = (short) (MAX_CONSV_SPILL_COUNT + 1);
+  public static final short MARK_HISTOGRAM_BUCKETS = (short) (LINES_IN_BLOCK + 1);
+         static final short MAX_COLLECTORS = 16; // nothing special here---we can increase this at the cost of a few hundred bites at build time.
+
+  public static final Word RECYCLE_ALLOC_CHUNK_MASK = Word.fromIntZeroExtend(BYTES_IN_RECYCLE_ALLOC_CHUNK - 1);
+  protected static final Word CHUNK_MASK = Word.fromIntZeroExtend(BYTES_IN_CHUNK - 1);
+  public static final Word BLOCK_MASK = Word.fromIntZeroExtend(BYTES_IN_BLOCK - 1);
+  protected static final Word LINE_MASK = Word.fromIntZeroExtend(BYTES_IN_LINE - 1);
+
+}





More information about the vmkit-commits mailing list