[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