[vmkit-commits] [vmkit] r75904 [2/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
Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ImmixSpace.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ImmixSpace.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ImmixSpace.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ImmixSpace.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,756 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.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.plan.Plan;
+import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.heap.*;
+import org.mmtk.utility.options.LineReuseRatio;
+import org.mmtk.utility.options.Options;
+import org.mmtk.utility.Constants;
+import org.mmtk.utility.Log;
+
+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 immix *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 SquishLocal, where
+ * instances correspond to *plan* instances and therefore to kernel
+ * threads. Thus unlike this class, synchronization is not necessary
+ * in the instance methods of SquishLocal.
+ *
+ */
+ at Uninterruptible
+public final class ImmixSpace extends Space implements Constants {
+
+ /****************************************************************************
+ *
+ * Class variables
+ */
+ private static short reusableMarkStateThreshold = 0;
+
+ /****************************************************************************
+ *
+ * Instance variables
+ */
+ private Word markState = ObjectHeader.MARK_BASE_VALUE;
+ byte lineMarkState = RESET_LINE_MARK_STATE;
+ private byte lineUnavailState = RESET_LINE_MARK_STATE;
+ private boolean inCollection;
+ private int linesConsumed = 0;
+
+ private Lock mutatorLock = VM.newLock(getName()+"mutator");
+ private Lock gcLock = VM.newLock(getName()+"gc");
+
+ private Address allocBlockCursor = Address.zero();
+ private Address allocBlockSentinel = Address.zero();
+ private boolean exhaustedReusableSpace = true;
+
+ private final ChunkList chunkMap = new ChunkList();
+ private final Defrag defrag;
+
+ /****************************************************************************
+ *
+ * Initialization
+ */
+
+ static {
+ Options.lineReuseRatio = new LineReuseRatio();
+ reusableMarkStateThreshold = (short) (Options.lineReuseRatio.getValue() * MAX_BLOCK_MARK_STATE);
+ }
+
+ /**
+ * 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 The virtual memory request
+ */
+ public ImmixSpace(String name, int pageBudget, VMRequest vmRequest) {
+ super(name, false, false, vmRequest);
+ if (vmRequest.isDiscontiguous())
+ pr = new FreeListPageResource(pageBudget, this, Chunk.getRequiredMetaDataPages());
+ else
+ pr = new FreeListPageResource(pageBudget, this, start, extent, Chunk.getRequiredMetaDataPages());
+ defrag = new Defrag((FreeListPageResource) pr);
+ }
+
+ /****************************************************************************
+ *
+ * Global prepare and release
+ */
+
+ /**
+ * Prepare for a new collection increment.
+ */
+ public void prepare(boolean majorGC) {
+ if (majorGC) {
+ markState = ObjectHeader.deltaMarkState(markState, true);
+ lineMarkState++;
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(lineMarkState <= MAX_LINE_MARK_STATE);
+ }
+ chunkMap.reset();
+ defrag.prepare(chunkMap, this);
+ inCollection = true;
+
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(VM.activePlan.collectorCount() <= MAX_COLLECTORS);
+ }
+
+ /**
+ * A new collection increment has completed. Release global resources.
+ * @param majorGC TODO
+ */
+ public boolean release(boolean majorGC) {
+ boolean didDefrag = defrag.inDefrag();
+ if (majorGC) {
+ if (lineMarkState == MAX_LINE_MARK_STATE)
+ lineMarkState = RESET_LINE_MARK_STATE;
+ lineUnavailState = lineMarkState;
+ }
+ chunkMap.reset();
+ defrag.globalRelease();
+ inCollection = false;
+
+ /* set up reusable space */
+ if (allocBlockCursor.isZero()) allocBlockCursor = chunkMap.getHeadChunk();
+ allocBlockSentinel = allocBlockCursor;
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isRecycleAllocChunkAligned(allocBlockSentinel));
+ exhaustedReusableSpace = false;
+ if (VM.VERIFY_ASSERTIONS && Options.verbose.getValue() >= 9) {
+ Log.write("gr[allocBlockCursor: "); Log.write(allocBlockCursor); Log.write(" allocBlockSentinel: "); Log.write(allocBlockSentinel); Log.writeln("]");
+ }
+
+ /* really just want this to happen once after options are booted, but no harm in re-doing it */
+ reusableMarkStateThreshold = (short) (Options.lineReuseRatio.getValue() * MAX_BLOCK_MARK_STATE);
+ Defrag.defragReusableMarkStateThreshold = (short) (Options.defragLineReuseRatio.getValue() * MAX_BLOCK_MARK_STATE);
+
+ linesConsumed = 0;
+ return didDefrag;
+ }
+
+ /**
+ * Determine the collection kind.
+ *
+ * @param emergencyCollection Is this collection an emergency (last did not yield enough)?
+ * @param collectWholeHeap Is this a whole heap collection?
+ * @param collectionAttempt Which attempt is this to collect?
+ * @param collectionTrigger What is triggering the collection?
+ */
+ public void decideWhetherToDefrag(boolean emergencyCollection, boolean collectWholeHeap, int collectionAttempt, int collectionTrigger) {
+ defrag.decideWhetherToDefrag(emergencyCollection, collectWholeHeap, collectionAttempt, collectionTrigger, exhaustedReusableSpace);
+ }
+
+ /****************************************************************************
+ *
+ * Collection state access methods
+ */
+
+ /**
+ * Return true if this space is currently being collected.
+ *
+ * @return True if this space is currently being collected.
+ */
+ @Inline
+ public boolean inImmixCollection() {
+ return inCollection;
+ }
+
+ /**
+ * Return true if this space is currently being defraged.
+ *
+ * @return True if this space is currently being defraged.
+ */
+ @Inline
+ public boolean inImmixDefragCollection() {
+ return inCollection && defrag.inDefrag();
+ }
+
+ /**
+ * Return the number of pages allocated since the last collection
+ *
+ * @return The number of pages allocated since the last collection
+ */
+ public int getPagesAllocated() {
+ return linesConsumed>>(LOG_BYTES_IN_PAGE-LOG_BYTES_IN_LINE);
+ }
+
+ /**
+ * Return the reusable mark state threshold, which determines how
+ * eagerly lines should be recycled (by default these values are
+ * set so that all lines are recycled).
+ *
+ * @param forDefrag The query is the context of a defragmenting collection
+ * @return The reusable mark state threshold
+ */
+ @Inline
+ public static short getReusuableMarkStateThreshold(boolean forDefrag) {
+ return forDefrag ? Defrag.defragReusableMarkStateThreshold : reusableMarkStateThreshold;
+ }
+
+ /****************************************************************************
+ *
+ * Allocation
+ */
+
+ /**
+ * Return a pointer to a set of new usable blocks, or null if none are available.
+ * Use different block selection heuristics depending on whether the allocation
+ * request is "hot" or "cold".
+ *
+ * @param hot True if the requesting context is for hot allocations (used for
+ * allocations from high allocation volume sites).
+ * @return The pointer into the alloc table containing usable blocks.
+ */
+ public Address getSpace(boolean hot, boolean copy, int lineUseCount) {
+ Address rtn;
+ if (copy)
+ defrag.getBlock();
+
+ linesConsumed += lineUseCount;
+
+ rtn = acquire(PAGES_IN_BLOCK);
+
+ if (VM.VERIFY_ASSERTIONS) {
+ VM.assertions._assert(Block.isAligned(rtn));
+ VM.assertions._assert(!(copy && Block.isDefragSource(rtn)));
+ }
+
+ if (!rtn.isZero()) {
+ Block.setBlockAsInUse(rtn);
+ Chunk.updateHighWater(rtn);
+ if (VM.VERIFY_ASSERTIONS && Options.verbose.getValue() >= 9) {
+ Log.write("gs["); Log.write(rtn); Log.write(" -> "); Log.write(rtn.plus(BYTES_IN_BLOCK-1)); Log.write(" copy: "); Log.write(copy); Log.writeln("]");
+ }
+ }
+
+ return rtn;
+ }
+
+ /**
+ * 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.
+ */
+ @Override
+ public void growSpace(Address start, Extent bytes, boolean newChunk) {
+ super.growSpace(start, bytes, newChunk);
+ if (newChunk) {
+ Address chunk = chunkAlign(start.plus(bytes), true);
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(chunkAlign(start.plus(bytes), true).EQ(chunk));
+ Chunk.clearMetaData(chunk);
+ chunkMap.addNewChunkToMap(chunk);
+ }
+ }
+
+ public Address acquireReusableBlocks() {
+ if (VM.VERIFY_ASSERTIONS) {
+ VM.assertions._assert(isRecycleAllocChunkAligned(allocBlockCursor));
+ VM.assertions._assert(isRecycleAllocChunkAligned(allocBlockSentinel));
+ }
+ Address rtn;
+
+ lock();
+ if (exhaustedReusableSpace)
+ rtn = Address.zero();
+ else {
+ rtn = allocBlockCursor;
+ Address lastAllocChunk = chunkAlign(allocBlockCursor, true);
+ allocBlockCursor = allocBlockCursor.plus(BYTES_IN_RECYCLE_ALLOC_CHUNK);
+ if (allocBlockCursor.GT(Chunk.getHighWater(lastAllocChunk)))
+ allocBlockCursor = chunkMap.nextChunk(lastAllocChunk);
+ if (VM.VERIFY_ASSERTIONS && Options.verbose.getValue() >= 9) {
+ Log.write("arb[ rtn: "); Log.write(rtn); Log.write(" allocBlockCursor: "); Log.write(allocBlockCursor); Log.write(" allocBlockSentinel: "); Log.write(allocBlockSentinel); Log.writeln("]");
+ }
+
+ if (allocBlockCursor.isZero() || allocBlockCursor.EQ(allocBlockSentinel)) {
+ exhaustedReusableSpace = true;
+ if (VM.VERIFY_ASSERTIONS && Options.verbose.getValue() >= 9) {
+ Log.writeln("[Reusable space exhausted]");
+ }
+ }
+ }
+ unlock();
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isRecycleAllocChunkAligned(rtn));
+ return rtn;
+ }
+
+ /**
+ * Release a block. A block is free, so call the underlying page allocator
+ * to release the associated storage.
+ *
+ * @param block The address of the block to be released
+ */
+ @Inline
+ public void release(Address block) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Block.isAligned(block));
+ Block.setBlockAsUnallocated(block);
+ ((FreeListPageResource) pr).releasePages(block);
+ }
+
+ /**
+ * Release one or more contiguous chunks associated with a discontiguous
+ * space. This hook is called by the page level allocators whenever a
+ * complete discontiguous chunk is released.
+ *
+ * @param chunk THe address of the start of the contiguous chunk or chunks
+ * @return The number of chunks freed
+ */
+ @Override
+ public int releaseDiscontiguousChunks(Address chunk) {
+ chunkMap.removeChunkFromMap(chunk);
+ return super.releaseDiscontiguousChunks(chunk);
+ }
+
+ /****************************************************************************
+ *
+ * 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, int bytes) {
+ if (bytes > BYTES_IN_LINE)
+ ObjectHeader.markAsStraddling(object);
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(ObjectHeader.isNewObject(object));
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!ObjectHeader.isForwardedOrBeingForwarded(object));
+ }
+
+ /**
+ * Perform any required post copy (i.e. in-GC allocation) initialization.
+ * This is relevant (for example) when Squish 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, int bytes, boolean majorGC) {
+ ObjectHeader.writeMarkState(object, markState, bytes > BYTES_IN_LINE);
+ if (!MARK_LINE_AT_SCAN_TIME && majorGC) markLines(object);
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!ObjectHeader.isForwardedOrBeingForwarded(object));
+ if (VM.VERIFY_ASSERTIONS && Plan.NEEDS_LOG_BIT_IN_HEADER) VM.assertions._assert(ObjectHeader.isUnloggedObject(object));
+ }
+
+ /****************************************************************************
+ *
+ * Object tracing
+ */
+
+ /**
+ * Trace a reference to an object. If the object header is not already
+ * marked, mark the object and enqueue it for subsequent processing.
+ *
+ * @param trace The trace performing the transitive closure
+ * @param object The object to be traced.
+ * @param allocator The allocator to which any copying should be directed
+ * @return The object, which may have been moved.
+ */
+ @Inline
+ public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object, int allocator) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(defrag.determined(true));
+
+ ObjectReference rtn = object;
+ if (isDefragSource(object))
+ rtn = traceObjectWithOpportunisticCopy(trace, object, allocator, false);
+ else
+ traceObjectWithoutMoving(trace, object);
+
+ if (VM.VERIFY_ASSERTIONS) {
+ VM.assertions._assert(!rtn.isNull());
+ VM.assertions._assert(defrag.spaceExhausted() || !isDefragSource(rtn) || (ObjectHeader.isPinnedObject(rtn)));
+ }
+ return rtn;
+ }
+
+ /**
+ * Trace a reference to an object in the context of a non-moving collection. This
+ * call is optimized for the simpler non-moving case.
+ *
+ * @param trace The trace performing the transitive closure
+ * @param object The object to be traced.
+ * @return The object (there is no object forwarding in this
+ * trace method, so we always return the same object: this could be a
+ * void method but for compliance to a more general interface).
+ */
+ @Inline
+ public ObjectReference fastTraceObject(TransitiveClosure trace, ObjectReference object) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(defrag.determined(false));
+ traceObjectWithoutMoving(trace, object);
+ return object;
+ }
+
+ /**
+ * Trace a reference to an object during a nursery collection for
+ * a sticky mark bits implementation of immix. If the object header
+ * is not already marked, mark the object and enqueue it for subsequent
+ * processing.
+ *
+ * @param trace The trace performing the transitive closure
+ * @param object The object to be traced.
+ * @param allocator The allocator to which any copying should be directed
+ * @return Either the object or a forwarded object, depending on
+ * the policy in place.
+ */
+ @Inline
+ public ObjectReference nurseryTraceObject(TransitiveClosure trace, ObjectReference object, int allocator) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!defrag.inDefrag());
+ if (TMP_PREFER_COPY_ON_NURSERY_GC)
+ return traceObjectWithOpportunisticCopy(trace, object, allocator, true);
+ else
+ return fastTraceObject(trace, object);
+ }
+
+ /**
+ * Trace a reference to an object. This interface is not supported by immix, since
+ * we require the allocator to be identified except for the special case of the fast
+ * trace.
+ *
+ * @param trace The trace performing the transitive closure
+ * @param object The object to be traced.
+ * @return null and fail.
+ */
+ public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object) {
+ VM.assertions.fail("unsupported interface");
+ return null;
+ }
+
+ /**
+ * Trace a reference to an object in the context of a non-moving collection. This
+ * call is optimized for the simpler non-moving case.
+ *
+ * @param trace The trace performing the transitive closure
+ * @param object The object to be traced.
+ */
+ @Inline
+ private void traceObjectWithoutMoving(TransitiveClosure trace, ObjectReference object) {
+ Word markValue = Plan.NEEDS_LOG_BIT_IN_HEADER ? markState.or(ObjectHeader.UNLOGGED_BIT) : markState;
+ Word oldMarkState = ObjectHeader.testAndMark(object, markValue);
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!defrag.inDefrag() || defrag.spaceExhausted() || !isDefragSource(object));
+ if (oldMarkState != markValue) {
+ if (!MARK_LINE_AT_SCAN_TIME)
+ markLines(object);
+ trace.processNode(object);
+ }
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!ObjectHeader.isForwardedOrBeingForwarded(object));
+ if (VM.VERIFY_ASSERTIONS && Plan.NEEDS_LOG_BIT_IN_HEADER) VM.assertions._assert(ObjectHeader.isUnloggedObject(object));
+ }
+
+ /**
+ * Trace a reference to an object, forwarding the object if appropriate
+ * If the object is not already marked, mark the object and enqueue it
+ * for subsequent processing.
+ *
+ * @param trace The trace performing the transitive closure
+ * @param object The object to be traced.
+ * @param allocator The allocator to which any copying should be directed
+ * @return Either the object or a forwarded object, if it was forwarded.
+ */
+ @Inline
+ private ObjectReference traceObjectWithOpportunisticCopy(TransitiveClosure trace, ObjectReference object, int allocator, boolean nurseryCollection) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(nurseryCollection || (defrag.determined(true) && isDefragSource(object)));
+
+ /* now race to be the (potential) forwarder */
+ Word priorForwardingWord = ObjectHeader.attemptToBeForwarder(object);
+ if (ObjectHeader.isForwardedOrBeingForwarded(priorForwardingWord)) {
+ /* We lost the race; the object is either forwarded or being forwarded by another thread. */
+ /* Note that the concurrent attempt to forward the object may fail, so the object may remain in-place */
+ ObjectReference rtn = ObjectHeader.spinAndGetForwardedObject(object, priorForwardingWord);
+ if (VM.VERIFY_ASSERTIONS && rtn == object) VM.assertions._assert((nurseryCollection && ObjectHeader.testMarkState(object, markState)) || defrag.spaceExhausted() || ObjectHeader.isPinnedObject(object));
+ if (VM.VERIFY_ASSERTIONS && rtn != object) VM.assertions._assert(nurseryCollection || !isDefragSource(rtn));
+ if (VM.VERIFY_ASSERTIONS && Plan.NEEDS_LOG_BIT_IN_HEADER) VM.assertions._assert(ObjectHeader.isUnloggedObject(rtn));
+ return rtn;
+ } else {
+ /* the object is unforwarded, either because this is the first thread to reach it, or because the object can't be forwarded */
+ if (ObjectHeader.testMarkState(priorForwardingWord, markState)) {
+ /* the object has not been forwarded, but has the correct mark state; unlock and return unmoved object */
+ /* Note that in a sticky mark bits collector, the mark state does not change at each GC, so correct mark state does not imply another thread got there first */
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(nurseryCollection || defrag.spaceExhausted() || ObjectHeader.isPinnedObject(object));
+ ObjectHeader.setForwardingWordAndEnsureUnlogged(object, priorForwardingWord); // return to uncontested state
+ if (VM.VERIFY_ASSERTIONS && Plan.NEEDS_LOG_BIT_IN_HEADER) VM.assertions._assert(ObjectHeader.isUnloggedObject(object));
+ return object;
+ } else {
+ /* we are the first to reach the object; either mark in place or forward it */
+ ObjectReference newObject;
+ if (ObjectHeader.isPinnedObject(object) || defrag.spaceExhausted()) {
+ /* mark in place */
+ ObjectHeader.setMarkStateUnlogAndUnlock(object, priorForwardingWord, markState);
+ newObject = object;
+ if (VM.VERIFY_ASSERTIONS && Plan.NEEDS_LOG_BIT_IN_HEADER) VM.assertions._assert(ObjectHeader.isUnloggedObject(newObject));
+ } else {
+ /* forward */
+ newObject = ObjectHeader.forwardObject(object, allocator);
+ if (VM.VERIFY_ASSERTIONS && Plan.NEEDS_LOG_BIT_IN_HEADER) VM.assertions._assert(ObjectHeader.isUnloggedObject(newObject));
+ }
+ 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("]");
+ }
+ if (!MARK_LINE_AT_SCAN_TIME)
+ markLines(newObject);
+ trace.processNode(newObject);
+ if (VM.VERIFY_ASSERTIONS) {
+ if (!((getSpaceForObject(newObject) != this) ||
+ (newObject == object) ||
+ (nurseryCollection && willNotMoveThisNurseryGC(newObject)) ||
+ (defrag.inDefrag() && willNotMoveThisGC(newObject))
+ )) {
+ Log.write(" object: "); Log.writeln(object);
+ Log.write("newObject: "); Log.writeln(newObject);
+ Log.write(" space: "); Log.writeln(getName());
+ Log.write(" nursery?: "); Log.writeln(nurseryCollection);
+ Log.write(" mature?: "); Log.writeln(ObjectHeader.isMatureObject(object));
+ Log.write(" wnmngc?: "); Log.writeln(willNotMoveThisNurseryGC(newObject));
+ Log.write(" pinned?: "); Log.writeln(ObjectHeader.isPinnedObject(object));
+ Space otherSpace = getSpaceForObject(newObject);
+ Log.write(" space(o): "); Log.writeln(otherSpace == null ? "<NULL>" : otherSpace.getName());
+ VM.assertions._assert(false);
+ }
+ }
+ return newObject;
+ }
+ }
+ }
+
+ /**
+ * Mark the line/s associated with a given object. This is distinct from the
+ * above tracing code because line marks are stored separately from the
+ * object headers (thus both must be set), and also because we found empirically
+ * that it was more efficient to perform the line mark of the object during
+ * the scan phase (which occurs after the trace phase), presumably because
+ * the latency of the associated memory operations was better hidden in the
+ * context of that code
+ *
+ * @param object The object which is live and for which the associated lines
+ * must be marked.
+ */
+ public void markLines(ObjectReference object) {
+ Address address = VM.objectModel.objectStartRef(object);
+ Line.mark(address, lineMarkState);
+ if (ObjectHeader.isStraddlingObject(object))
+ Line.markMultiLine(address, object, lineMarkState);
+ }
+
+ public int getNextUnavailableLine(Address baseLineAvailAddress, int line) {
+ return Line.getNextUnavailable(baseLineAvailAddress, line, lineUnavailState);
+ }
+
+ public int getNextAvailableLine(Address baseLineAvailAddress, int line) {
+ return Line.getNextAvailable(baseLineAvailAddress, line, lineUnavailState);
+ }
+
+ /****************************************************************************
+ *
+ * Establish available lines
+ */
+
+ /**
+ * Establish the number of recyclable lines lines available for allocation
+ * during defragmentation, populating the spillAvailHistogram, which buckets
+ * available lines according to the number of holes on the block on which
+ * the available lines reside.
+ *
+ * @param spillAvailHistogram A histogram of availability to be populated
+ * @return The number of available recyclable lines
+ */
+ int getAvailableLines(int[] spillAvailHistogram) {
+ int availableLines;
+ if (allocBlockCursor.isZero() || exhaustedReusableSpace) {
+ availableLines = 0;
+ } else {
+ if (allocBlockCursor.EQ(allocBlockSentinel)) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!exhaustedReusableSpace);
+ allocBlockCursor = chunkMap.getHeadChunk();
+ allocBlockSentinel = allocBlockCursor;
+ }
+ availableLines = getUsableLinesInRegion(allocBlockCursor, allocBlockSentinel, spillAvailHistogram);
+ }
+ return availableLines;
+ }
+
+ /**
+ * Return the number of lines usable for allocation during defragmentation in the
+ * address range specified by start and end. Populate a histogram to indicate where
+ * the usable lines reside as a function of block hole count.
+ *
+ * @param start The start of the region to be checked for availability
+ * @param end The end of the region to be checked for availability
+ * @param spillAvailHistogram The histogram which will be populated
+ * @return The number of usable lines
+ */
+ private int getUsableLinesInRegion(Address start, Address end, int[] spillAvailHistogram) {
+ int usableLines = 0;
+ Address blockCursor = Chunk.isAligned(start) ? start.plus(Chunk.FIRST_USABLE_BLOCK_INDEX<<LOG_BYTES_IN_BLOCK) : start;
+ Address blockStateCursor = Block.getBlockMarkStateAddress(blockCursor);
+ Address chunkCursor = Chunk.align(blockCursor);
+ if (Chunk.getByteOffset(end) < Chunk.FIRST_USABLE_BLOCK_INDEX<<LOG_BYTES_IN_BLOCK)
+ end = Chunk.align(end).plus(Chunk.FIRST_USABLE_BLOCK_INDEX<<LOG_BYTES_IN_BLOCK);
+
+ for (int i = 0; i <= MAX_CONSV_SPILL_COUNT; i++) spillAvailHistogram[i] = 0;
+
+ Address highwater = Chunk.getHighWater(chunkCursor);
+ do {
+ short markState = blockStateCursor.loadShort();
+ if (markState != 0 && markState <= reusableMarkStateThreshold) {
+ int usable = LINES_IN_BLOCK - markState;
+ short bucket = (short) Block.getConservativeSpillCount(blockCursor);
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(bucket >= 0 && bucket <= MAX_CONSV_SPILL_COUNT);
+ spillAvailHistogram[bucket] += usable;
+ usableLines += usable;
+ }
+ blockCursor = blockCursor.plus(BYTES_IN_BLOCK);
+ if (blockCursor.GT(highwater)) {
+ chunkCursor = chunkMap.nextChunk(chunkCursor);
+ if (chunkCursor.isZero()) break;
+ blockCursor = chunkCursor.plus(Chunk.FIRST_USABLE_BLOCK_INDEX<<LOG_BYTES_IN_BLOCK);
+ blockStateCursor = Block.getBlockMarkStateAddress(blockCursor);
+ highwater = Chunk.getHighWater(chunkCursor);
+ } else
+ blockStateCursor = blockStateCursor.plus(Block.BYTES_IN_BLOCK_STATE_ENTRY);
+ } while (blockCursor.NE(end));
+
+ return usableLines;
+ }
+
+ /****************************************************************************
+ *
+ * Object state
+ */
+
+ /**
+ * Generic test of the liveness of an 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 (defrag.inDefrag() && isDefragSource(object))
+ return ObjectHeader.isForwardedOrBeingForwarded(object) || ObjectHeader.testMarkState(object, markState);
+ else
+ return ObjectHeader.testMarkState(object, markState);
+ }
+
+ /**
+ * Test the liveness of an object during copying sticky mark bits collection
+ *
+ * @param object The object in question
+ * @return True if this object is known to be live (i.e. it is marked)
+ */
+ @Inline
+ public boolean copyNurseryIsLive(ObjectReference object) {
+ return ObjectHeader.isForwardedOrBeingForwarded(object) || ObjectHeader.testMarkState(object, markState);
+ }
+
+ /**
+ * Test the liveness of an object during defragmentation
+ *
+ * @param object The object in question
+ * @return True if this object is known to be live (i.e. it is marked)
+ */
+ @Inline
+ public boolean fastIsLive(ObjectReference object) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!defrag.inDefrag());
+ return ObjectHeader.testMarkState(object, markState);
+ }
+
+ @Inline
+ public boolean willNotMoveThisGC(ObjectReference object) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(getSpaceForObject(object) == this && defrag.inDefrag());
+ return ObjectHeader.isPinnedObject(object) || willNotMoveThisGC(VM.objectModel.refToAddress(object));
+ }
+
+ @Inline
+ public boolean willNotMoveThisNurseryGC(ObjectReference object) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(getSpaceForObject(object) == this);
+ return ObjectHeader.isMatureObject(object);
+ }
+
+ @Inline
+ private boolean isDefragSource(ObjectReference object) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(getSpaceForObject(object) == this);
+ return isDefragSource(VM.objectModel.refToAddress(object));
+ }
+
+ @Inline
+ public boolean willNotMoveThisGC(Address address) {
+ return !defrag.inDefrag() || defrag.spaceExhausted() || !isDefragSource(address);
+ }
+
+ @Inline
+ public boolean isDefragSource(Address address) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(getSpaceForObject(address.toObjectReference()) == this);
+ return Block.isDefragSource(address);
+ }
+
+
+ /****************************************************************************
+ *
+ * Locks
+ */
+
+ /**
+ * Acquire the appropriate lock depending on whether the context is
+ * GC or mutator.
+ */
+ private void lock() {
+ if (inCollection)
+ gcLock.acquire();
+ else
+ mutatorLock.acquire();
+ }
+
+ /**
+ * Release the appropriate lock depending on whether the context is
+ * GC or mutator.
+ */
+ private void unlock() {
+ if (inCollection)
+ gcLock.release();
+ else
+ mutatorLock.release();
+ }
+
+
+ /****************************************************************************
+ *
+ * Misc
+ */
+ public static boolean isRecycleAllocChunkAligned(Address ptr) {
+ return ptr.toWord().and(RECYCLE_ALLOC_CHUNK_MASK).EQ(Word.zero());
+ }
+
+ ChunkList getChunkMap() { return chunkMap; }
+ Defrag getDefrag() { return defrag; }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Line.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Line.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Line.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/Line.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.policy.immix;
+
+import static org.mmtk.policy.immix.ImmixConstants.*;
+
+import org.mmtk.utility.Constants;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.Inline;
+import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.unboxed.Address;
+import org.vmmagic.unboxed.ObjectReference;
+import org.vmmagic.unboxed.Offset;
+
+ at Uninterruptible
+public class Line implements Constants {
+
+ public static Address align(Address ptr) {
+ return ptr.toWord().and(LINE_MASK.not()).toAddress();
+ }
+
+ public static boolean isAligned(Address address) {
+ return address.EQ(align(address));
+ }
+
+ static int getChunkIndex(Address line) {
+ return line.toWord().and(CHUNK_MASK).rshl(LOG_BYTES_IN_LINE).toInt();
+ }
+
+ /***************************************************************************
+ * Line marking
+ */
+ static void mark(Address address, final byte markValue) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!Block.isUnused(Block.align(address)));
+ getMarkAddress(address).store(markValue);
+ }
+
+ static void markMultiLine(Address start, ObjectReference object, final byte markValue) {
+ /* endLine is the address of the last (highest) line touched by this object */
+ Address endLine = Line.align(VM.objectModel.getObjectEndAddress(object).minus(1));
+ Address line = Line.align(start.plus(BYTES_IN_LINE));
+ while (line.LT(endLine)) {
+ if (VM.VERIFY_ASSERTIONS)
+ VM.assertions._assert(Block.align(start) == Block.align(line));
+ mark(line, markValue);
+ line = line.plus(BYTES_IN_LINE);
+ }
+ }
+
+ /***************************************************************************
+ * Scanning through avail lines
+ */
+ public static Address getChunkMarkTable(Address chunk) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Chunk.isAligned(chunk));
+ return getMarkAddress(chunk);
+ }
+
+ public static Address getBlockMarkTable(Address block) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Block.isAligned(block));
+ return getMarkAddress(block);
+ }
+
+ @Inline
+ public static int getNextUnavailable(Address baseLineAvailAddress, int line, final byte unavailableState) {
+ while (line < LINES_IN_BLOCK &&
+ baseLineAvailAddress.loadByte(Offset.fromIntZeroExtend(line<<Line.LOG_BYTES_IN_LINE_STATUS)) < unavailableState)
+ line++;
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(line >= 0 && line <= LINES_IN_BLOCK);
+ return line;
+ }
+
+ @Inline
+ public static int getNextAvailable(Address baseLineAvailAddress, int line, final byte unavailableState) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(line >= 0 && line < LINES_IN_BLOCK);
+ byte last = baseLineAvailAddress.loadByte(Offset.fromIntZeroExtend(line<<Line.LOG_BYTES_IN_LINE_STATUS));
+ byte thisline;
+ line++;
+ while (line < LINES_IN_BLOCK) {
+ thisline = baseLineAvailAddress.loadByte(Offset.fromIntZeroExtend(line<<Line.LOG_BYTES_IN_LINE_STATUS));
+ if (thisline < unavailableState && last < unavailableState)
+ break;
+ last = thisline;
+ line++;
+ }
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(line >= 0 && line <= LINES_IN_BLOCK);
+ return line;
+ }
+
+ private static Address getMetaAddress(Address address, final int tableOffset) {
+ Address chunk = Chunk.align(address);
+ int index = getChunkIndex(address);
+ Address rtn = chunk.plus(tableOffset + (index<<LOG_BYTES_IN_LINE_STATUS));
+ if (VM.VERIFY_ASSERTIONS) {
+ Address line = chunk.plus(index<<LOG_BYTES_IN_LINE);
+ VM.assertions._assert(isAligned(line));
+ VM.assertions._assert(align(address).EQ(line));
+ boolean valid = rtn.GE(chunk.plus(tableOffset)) && rtn.LT(chunk.plus(tableOffset + LINE_MARK_TABLE_BYTES));
+ VM.assertions._assert(valid);
+ }
+ return rtn;
+ }
+
+ private static Address getMarkAddress(Address address) {
+ return getMetaAddress(address, Chunk.LINE_MARK_TABLE_OFFSET);
+ }
+
+ /* per-line mark bytes */
+ static final int LOG_BYTES_IN_LINE_STATUS = 0;
+ static final int BYTES_IN_LINE_STATUS = 1<<LOG_BYTES_IN_LINE_STATUS;
+
+ static final int LINE_MARK_TABLE_BYTES = LINES_IN_CHUNK<<LOG_BYTES_IN_LINE_STATUS;
+ static final int LOG_LINE_MARK_BYTES_PER_BLOCK = LOG_LINES_IN_BLOCK+LOG_BYTES_IN_LINE_STATUS;
+ static final int LINE_MARK_BYTES_PER_BLOCK = (1<<LOG_LINE_MARK_BYTES_PER_BLOCK);
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/MutatorLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/MutatorLocal.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/MutatorLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/MutatorLocal.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.policy.immix;
+
+import org.mmtk.utility.alloc.ImmixAllocator;
+import org.mmtk.utility.Constants;
+
+import org.vmmagic.pragma.*;
+
+/**
+ *
+ */
+ at Uninterruptible
+public final class MutatorLocal extends ImmixAllocator
+ implements Constants {
+ /**
+ * Constructor
+ *
+ * @param space The mark-sweep space to which this allocator
+ * instances is bound.
+ * @param hot TODO
+ */
+ public MutatorLocal(ImmixSpace space, boolean hot) {
+ super(space, hot, false);
+ }
+
+ /****************************************************************************
+ *
+ * Collection
+ */
+
+ /**
+ * Prepare for a collection. If paranoid, perform a sanity check.
+ */
+ public void prepare() {
+ reset();
+ }
+
+ /**
+ * Finish up after a collection.
+ */
+ public void release() {
+ reset();
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ObjectHeader.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ObjectHeader.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ObjectHeader.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/policy/immix/ObjectHeader.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,257 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.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.vm.VM;
+import org.vmmagic.pragma.Inline;
+import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.unboxed.ObjectReference;
+import org.vmmagic.unboxed.Word;
+
+ at Uninterruptible
+public class ObjectHeader {
+ /** number of header bits we may use */
+ static final int MAX_BITS = 8;
+
+ /* 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;
+
+ /* stolen bits */
+ static final Word NEW_OBJECT_MARK = Word.fromIntZeroExtend(0); // using zero means no need for explicit initialization on allocation
+ private static final Word BEING_FORWARDED = Word.fromIntZeroExtend(2); // second bit indicates an object is in the process of being forwarded
+ private static final Word FORWARDED = Word.fromIntZeroExtend(3); // second bit indicates an object is in the process of being forwarded
+ private static final Word FORWARDING_MASK = Word.fromIntZeroExtend(3);
+
+ private static final int UNLOGGED_BIT_NUMBER = 3;
+ public static final Word UNLOGGED_BIT = Word.one().lsh(UNLOGGED_BIT_NUMBER);
+ public static final Word LOG_SET_MASK = UNLOGGED_BIT;
+
+ private static final int STOLEN_LO_BITS = UNLOGGED_BIT_NUMBER + 1; // both used for forwarding, also the all zero state is used to represent new objects
+ private static final int STOLEN_HI_BITS = 2;
+
+ static final int MAX_MARKCOUNT_BITS = MAX_BITS-(STOLEN_LO_BITS+STOLEN_HI_BITS);
+ private static final int FIRST_STOLEN_HI_BIT_NUMBER = STOLEN_LO_BITS + MAX_MARKCOUNT_BITS;
+
+ public static final int PINNED_BIT_NUMBER = FIRST_STOLEN_HI_BIT_NUMBER;
+ public static final Word PINNED_BIT = Word.one().lsh(PINNED_BIT_NUMBER);
+
+ private static final int STRADDLE_BIT_NUMBER = PINNED_BIT_NUMBER + 1;
+ public static final Word STRADDLE_BIT = Word.one().lsh(STRADDLE_BIT_NUMBER);
+
+ /* mark bits */
+ private static final int MARK_BASE = STOLEN_LO_BITS;
+ private static final Word MARK_INCREMENT = Word.one().lsh(MARK_BASE);
+ public static final Word MARK_MASK = Word.one().lsh(MAX_MARKCOUNT_BITS).minus(Word.one()).lsh(MARK_BASE);
+ public static final Word MARK_AND_LOG_BITS_MASK = Word.one().lsh(MAX_BITS-STOLEN_HI_BITS).minus(Word.one());
+ public static final Word MARK_BITS_MASK = MARK_AND_LOG_BITS_MASK.xor(UNLOGGED_BIT);
+
+ public static final Word MARK_BASE_VALUE = MARK_INCREMENT;
+
+
+
+ /****************************************************************************
+ *
+ * Marking
+ */
+
+ /**
+ * Non-atomically test and 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 markState The value to which the mark bits will be set
+ */
+ static Word testAndMark(ObjectReference object, Word markState) {
+ int oldValue, newValue, oldMarkState;
+
+ oldValue = VM.objectModel.readAvailableByte(object);
+ oldMarkState = oldValue & MARK_AND_LOG_BITS_MASK.toInt();
+ if (oldMarkState != markState.toInt()) {
+ newValue = (oldValue & ~MARK_AND_LOG_BITS_MASK.toInt()) | markState.toInt();
+ VM.objectModel.writeAvailableByte(object, (byte) newValue);
+ }
+ return Word.fromIntZeroExtend(oldMarkState);
+ }
+
+ static void setMarkStateUnlogAndUnlock(ObjectReference object, Word originalForwardingWord, Word markState) {
+ Word markValue = Plan.NEEDS_LOG_BIT_IN_HEADER ? markState.or(ObjectHeader.UNLOGGED_BIT) : markState;
+ int oldValue = originalForwardingWord.toInt();
+ int newValue = (oldValue & (MARK_AND_LOG_BITS_MASK.or(FORWARDING_MASK)).not().toInt()) | markValue.toInt();
+ VM.objectModel.writeAvailableByte(object, (byte) newValue);
+ if (VM.VERIFY_ASSERTIONS)
+ VM.assertions._assert((oldValue & MARK_AND_LOG_BITS_MASK.toInt()) != markValue.toInt());
+ }
+
+ /**
+ * 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.
+ */
+ static boolean testMarkState(ObjectReference object, Word value) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(value.and(MARK_MASK).EQ(value));
+ return testMarkState(VM.objectModel.readAvailableBitsWord(object), value);
+ }
+
+ static boolean testMarkState(Word forwardingWord, Word value) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(value.and(MARK_MASK).EQ(value));
+ return forwardingWord.and(MARK_MASK).EQ(value);
+ }
+
+ static boolean isNewObject(ObjectReference object) {
+ Word markBits = VM.objectModel.readAvailableBitsWord(object).and(MARK_AND_LOG_BITS_MASK);
+ return markBits.EQ(NEW_OBJECT_MARK);
+ }
+
+ static boolean isMatureObject(ObjectReference object) {
+ Word markBits = VM.objectModel.readAvailableBitsWord(object).and(MARK_AND_LOG_BITS_MASK);
+ boolean unforwarded = markBits.and(FORWARDING_MASK).isZero();
+ boolean newObj = markBits.EQ(NEW_OBJECT_MARK);
+ return unforwarded && !newObj;
+ }
+
+ @Inline
+ static void markAsStraddling(ObjectReference object) {
+ Word old = VM.objectModel.readAvailableBitsWord(object);
+ VM.objectModel.writeAvailableBitsWord(object, old.or(STRADDLE_BIT));
+ }
+
+ @Inline
+ static boolean isStraddlingObject(ObjectReference object) {
+ return isStraddleBitSet(VM.objectModel.readAvailableBitsWord(object));
+ }
+
+ @Inline
+ private static boolean isStraddleBitSet(Word header) {
+ return header.and(STRADDLE_BIT).EQ(STRADDLE_BIT);
+ }
+
+ @Inline
+ static boolean isUnloggedObject(ObjectReference object) {
+ return isUnloggedBitSet(VM.objectModel.readAvailableBitsWord(object));
+ }
+
+ @Inline
+ static boolean isUnloggedBitSet(Word header) {
+ return header.and(UNLOGGED_BIT).EQ(UNLOGGED_BIT);
+ }
+
+ @Inline
+ public static void pinObject(ObjectReference object) {
+ byte header = VM.objectModel.readAvailableByte(object);
+ VM.objectModel.writeAvailableByte(object, (byte)(header | PINNED_BIT.toInt()));
+ }
+
+ @Inline
+ static boolean isPinnedObject(ObjectReference object) {
+ return isPinnedBitSet(VM.objectModel.readAvailableBitsWord(object));
+ }
+
+ @Inline
+ private static boolean isPinnedBitSet(Word header) {
+ return header.and(PINNED_BIT).EQ(PINNED_BIT);
+ }
+
+ /**
+ * Write the allocState 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
+ * @param markState TODO: what am I?
+ * @param straddle TODO: what am I?
+ */
+ static void writeMarkState(ObjectReference object, Word markState, boolean straddle) {
+ Word oldValue = VM.objectModel.readAvailableBitsWord(object);
+ Word markValue = Plan.NEEDS_LOG_BIT_IN_HEADER ? markState.or(ObjectHeader.UNLOGGED_BIT) : markState;
+ Word newValue = oldValue.and(MARK_AND_LOG_BITS_MASK.not()).or(markValue);
+ if (straddle)
+ newValue = newValue.or(STRADDLE_BIT);
+ VM.objectModel.writeAvailableBitsWord(object, newValue);
+ }
+
+ /****************************************************************************
+ *
+ * Forwarding
+ */
+
+ /**
+ * 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.
+ */
+ static Word attemptToBeForwarder(ObjectReference object) {
+ Word oldValue;
+ do {
+ oldValue = VM.objectModel.prepareAvailableBits(object);
+ if (oldValue.and(FORWARDING_MASK).EQ(FORWARDED))
+ return oldValue;
+ } while (!VM.objectModel.attemptAvailableBits(object, oldValue, oldValue.or(BEING_FORWARDED)));
+ return oldValue;
+ }
+
+ static ObjectReference forwardObject(ObjectReference object, int allocator) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!isPinnedObject(object));
+ ObjectReference newObject = VM.objectModel.copy(object, allocator);
+ VM.objectModel.writeAvailableBitsWord(object, newObject.toAddress().toWord().or(FORWARDED));
+ return newObject;
+ }
+
+ static void setForwardingWordAndEnsureUnlogged(ObjectReference object, Word forwardingWord) {
+ if (Plan.NEEDS_LOG_BIT_IN_HEADER) forwardingWord = forwardingWord.or(UNLOGGED_BIT);
+ VM.objectModel.writeAvailableBitsWord(object, forwardingWord);
+ }
+
+ static boolean isForwardedOrBeingForwarded(ObjectReference object) {
+ return isForwardedOrBeingForwarded(VM.objectModel.readAvailableBitsWord(object));
+ }
+
+ static boolean isForwardedOrBeingForwarded(Word forwardingWord) {
+ return !forwardingWord.and(FORWARDING_MASK).isZero();
+ }
+
+ static ObjectReference spinAndGetForwardedObject(ObjectReference object, Word forwardingWord) {
+ /* We must wait (spin) if the object is not yet fully forwarded */
+ while (forwardingWord.and(FORWARDING_MASK).EQ(BEING_FORWARDED))
+ forwardingWord = VM.objectModel.readAvailableBitsWord(object);
+
+ /* Now extract the object reference from the forwarding word and return it */
+ if (forwardingWord.and(FORWARDING_MASK).EQ(FORWARDED))
+ return forwardingWord.and(FORWARDING_MASK.not()).toAddress().toObjectReference();
+ else
+ return object;
+ }
+
+ /**
+ * 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.
+ */
+ static Word deltaMarkState(Word state, boolean increment) {
+ Word rtn = state;
+ do {
+ rtn = increment ? rtn.plus(MARK_INCREMENT) : rtn.minus(MARK_INCREMENT);
+ rtn = rtn.and(MARK_MASK);
+ } while (rtn.LT(MARK_BASE_VALUE));
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(rtn.NE(state));
+ return rtn;
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/BaseGenericFreeList.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/BaseGenericFreeList.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/BaseGenericFreeList.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/BaseGenericFreeList.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,366 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This is a very simple, generic malloc-free allocator. It works
+ * abstractly, in "units", which the user may associate with some
+ * other allocatable resource (e.g. heap blocks). The user issues
+ * requests for N units and the allocator returns the index of the
+ * first of a contiguous set of N units or fails, returning -1. The
+ * user frees the block of N units by calling <code>free()</code> with
+ * the index of the first unit as the argument.<p>
+ *
+ * Properties/Constraints:<ul>
+ * <li> The allocator consumes one word per allocatable unit (plus
+ * a fixed overhead of about 128 words).</li>
+ * <li> The allocator can only deal with MAX_UNITS units (see below for
+ * the value).</li>
+ * </ul>
+ *
+ * The basic data structure used by the algorithm is a large table,
+ * with one word per allocatable unit. Each word is used in a
+ * number of different ways, some combination of "undefined" (32),
+ * "free/used" (1), "multi/single" (1), "prev" (15), "next" (15) &
+ * "size" (15) where field sizes in bits are in parenthesis.
+ * <pre>
+ * +-+-+-----------+-----------+
+ * |f|m| prev | next/size |
+ * +-+-+-----------+-----------+
+ *
+ * - single free unit: "free", "single", "prev", "next"
+ * - single used unit: "used", "single"
+ * - contiguous free units
+ * . first unit: "free", "multi", "prev", "next"
+ * . second unit: "free", "multi", "size"
+ * . last unit: "free", "multi", "size"
+ * - contiguous used units
+ * . first unit: "used", "multi", "prev", "next"
+ * . second unit: "used", "multi", "size"
+ * . last unit: "used", "multi", "size"
+ * - any other unit: undefined
+ *
+ * +-+-+-----------+-----------+
+ * top sentinel |0|0| tail | head | [-1]
+ * +-+-+-----------+-----------+
+ * ....
+ * /-------- +-+-+-----------+-----------+
+ * | |1|1| prev | next | [j]
+ * | +-+-+-----------+-----------+
+ * | |1|1| | size | [j+1]
+ * free multi +-+-+-----------+-----------+
+ * unit block | ... | ...
+ * | +-+-+-----------+-----------+
+ * | |1|1| | size |
+ * >-------- +-+-+-----------+-----------+
+ * single free unit |1|0| prev | next |
+ * >-------- +-+-+-----------+-----------+
+ * single used unit |0|0| |
+ * >-------- +-+-+-----------------------+
+ * | |0|1| |
+ * | +-+-+-----------+-----------+
+ * | |0|1| | size |
+ * used multi +-+-+-----------+-----------+
+ * unit block | ... |
+ * | +-+-+-----------+-----------+
+ * | |0|1| | size |
+ * \-------- +-+-+-----------+-----------+
+ * ....
+ * +-+-+-----------------------+
+ * bottom sentinel |0|0| | [N]
+ * +-+-+-----------------------+
+ * </pre>
+ * The sentinels serve as guards against out of range coalescing
+ * because they both appear as "used" blocks and so will never
+ * coalesce. The top sentinel also serves as the head and tail of
+ * the doubly linked list of free blocks.
+ */
+ at Uninterruptible abstract class BaseGenericFreeList implements Constants {
+
+ /****************************************************************************
+ *
+ * Public instance methods
+ */
+
+ /**
+ * Allocate <code>size</code> units. Return the unit ID
+ *
+ * @param size The number of units to be allocated
+ * @return The index of the first of the <code>size</code>
+ * contiguous units, or -1 if the request can't be satisfied
+ */
+ public final int alloc(int size) {
+ // Note: -1 is both the default return value *and* the start sentinel index
+ int unit = head; // HEAD = -1
+ int s = 0;
+ while (((unit = getNext(unit)) != head) && ((s = getSize(unit)) < size));
+
+ return (unit == head) ? FAILURE : alloc(size, unit, s);
+ }
+
+ /**
+ * Would an allocation of <code>size</code> units succeed?
+ *
+ * @param size The number of units to test for
+ * @return True if such a request could be satisfied.
+ */
+ public final boolean couldAlloc(int size) {
+ // Note: -1 is both the default return value *and* the start sentinel index
+ int unit = head; // HEAD = -1
+ while (((unit = getNext(unit)) != head) && (getSize(unit) < size));
+
+ return (unit != head);
+ }
+
+ /**
+ * Allocate <code>size</code> units. Return the unit ID
+ *
+ * @param size The number of units to be allocated
+ * @return The index of the first of the <code>size</code>
+ * contiguous units, or -1 if the request can't be satisfied
+ */
+ public final int alloc(int size, int unit) {
+ int s = 0;
+
+ if (getFree(unit) && (s = getSize(unit)) >= size)
+ return alloc(size, unit, s);
+ else
+ return FAILURE;
+ }
+
+ /**
+ * Allocate <code>size</code> units. Return the unit ID
+ *
+ * @param size The number of units to be allocated
+ * @return The index of the first of the <code>size</code>
+ * contiguous units, or -1 if the request can't be satisfied
+ */
+ private int alloc(int size, int unit, int unitSize) {
+ if (unitSize >= size) {
+ if (unitSize > size)
+ split(unit, size);
+ removeFromFree(unit);
+ setFree(unit, false);
+ }
+
+ if (DEBUG) dbgPrintFree();
+
+ return unit;
+ }
+
+ /**
+ * Free a previously allocated contiguous lump of units.
+ *
+ * @param unit The index of the first unit.
+ * @return return the size of the unit which was freed.
+ */
+ public final int free(int unit) {
+ return free(unit, false);
+ }
+
+ /**
+ * Free a previously allocated contiguous lump of units.
+ *
+ * @param unit The index of the first unit.
+ * @param returnCoalescedSize if true, return the coalesced size
+ * @return The number of units freed. if returnCoalescedSize is
+ * false, return the size of the unit which was freed. Otherwise
+ * return the size of the unit now available (the coalesced size)
+ */
+ public final int free(int unit, boolean returnCoalescedSize) {
+ int freed = getSize(unit);
+ int left = getLeft(unit);
+ int start = isCoalescable(unit) && getFree(left) ? left : unit;
+ int right = getRight(unit);
+ int end = isCoalescable(right) && getFree(right) ? right : unit;
+ if (start != end)
+ coalesce(start, end);
+
+ if (returnCoalescedSize)
+ freed = getSize(start);
+ addToFree(start);
+
+ if (DEBUG) dbgPrintFree();
+ return freed;
+ }
+
+ /**
+ * Return the size of the specified lump of units
+ *
+ * @param unit The index of the first unit in the lump.
+ * @return The size of the lump, in units.
+ */
+ public final int size(int unit) {
+ return getSize(unit);
+ }
+
+ /****************************************************************************
+ *
+ * Private fields and methods
+ */
+
+ /**
+ * Initialize a new heap. Fabricate a free list entry containing
+ * everything
+ *
+ * @param units The number of units in the heap
+ */
+ protected final void initializeHeap(int units) {
+ initializeHeap(units, units);
+ }
+
+ /**
+ * Initialize a new heap. Fabricate a free list entry containing
+ * everything
+ *
+ * @param units The number of units in the heap
+ */
+ protected final void initializeHeap(int units, int grain) {
+ // Initialize the sentinels
+ for (int i = 1; i <= heads; i++)
+ setSentinel(-i);
+ setSentinel(units);
+
+ // create the free list item
+ int offset = units % grain;
+ int cursor = units - offset;
+ if (offset > 0) {
+ setSize(cursor, offset);
+ addToFree(cursor);
+ }
+ cursor -= grain;
+ while (cursor >= 0) {
+ setSize(cursor, grain);
+ addToFree(cursor);
+ cursor -= grain;
+ }
+ if (DEBUG) dbgPrintFree();
+ }
+
+ /**
+ * Reduce a lump of units to size, freeing any excess.
+ *
+ * @param unit The index of the first unit
+ * @param size The size of the first part
+ */
+ private void split(int unit, int size) {
+ int basesize = getSize(unit);
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(basesize > size);
+ setSize(unit, size);
+ setSize(unit + size, basesize - size);
+ addToFree(unit + size);
+ if (DEBUG) dbgPrintFree();
+ }
+
+ /**
+ * Coalesce two or three contiguous lumps of units, removing start
+ * and end lumps from the free list as necessary.
+ * @param start The index of the start of the first lump
+ * @param end The index of the start of the last lump
+ */
+ private void coalesce(int start, int end) {
+ if (getFree(end))
+ removeFromFree(end);
+ if (getFree(start))
+ removeFromFree(start);
+
+ setSize(start, end - start + getSize(end));
+ }
+
+ /**
+ * Add a lump of units to the free list
+ *
+ * @param unit The first unit in the lump of units to be added
+ */
+ private void addToFree(int unit) {
+ setFree(unit, true);
+ int next = getNext(head);
+ setNext(unit, next);
+ setNext(head, unit);
+ setPrev(unit, head);
+ setPrev(next, unit);
+ }
+
+ /**
+ * Remove a lump of units from the free list
+ *
+ * @param unit The first unit in the lump of units to be removed
+ */
+ private void removeFromFree(int unit) {
+ int next = getNext(unit);
+ int prev = getPrev(unit);
+ setNext(prev, next);
+ setPrev(next, prev);
+ if (DEBUG) dbgPrintFree();
+ }
+
+ /**
+ * Get the lump to the "right" of the current lump (i.e. "below" it)
+ *
+ * @param unit The index of the first unit in the lump in question
+ * @return The index of the first unit in the lump to the
+ * "right"/"below" the lump in question.
+ */
+ private int getRight(int unit) {
+ return unit + getSize(unit);
+ }
+
+
+ /**
+ * Print the free list (for debugging purposes)
+ */
+ void dbgPrintFree() {
+ if (DEBUG) {
+ Log.write("FL[");
+ int i = head;
+ while ((i = getNext(i)) != head) {
+ boolean f = getFree(i);
+ int s = getSize(i);
+ if (!f)
+ Log.write("->");
+ Log.write(i);
+ if (!f)
+ Log.write("<-");
+ Log.write("(");
+ Log.write(s);
+ Log.write(")");
+ Log.write(" ");
+ Log.flush();
+ }
+ Log.writeln("]FL");
+ }
+ }
+
+ abstract void setSentinel(int unit);
+ abstract int getSize(int unit);
+ abstract void setSize(int unit, int size);
+ abstract boolean getFree(int unit);
+ abstract void setFree(int unit, boolean isFree);
+ abstract int getNext(int unit);
+ abstract void setNext(int unit, int next);
+ abstract int getPrev(int unit);
+ abstract void setPrev(int unit, int prev);
+ abstract int getLeft(int unit);
+ abstract boolean isCoalescable(int unit);
+
+ protected static final boolean DEBUG = false;
+ public static final int FAILURE = -1;
+ protected static final int MAX_HEADS = 128; // somewhat arbitrary
+
+ protected int heads = 1;
+ protected int head = -heads;
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/CallSite.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/CallSite.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/CallSite.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/CallSite.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,18 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility;
+
+/*
+ */
+public class CallSite {
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/Constants.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/Constants.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/Constants.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/Constants.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,145 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility;
+
+import org.mmtk.utility.alloc.EmbeddedMetaData;
+import org.mmtk.vm.VM;
+
+/**
+ * MMTk follows the pattern set by Jikes RVM for defining sizes of
+ * primitive types thus:
+ *
+ * <pre>
+ * static final int LOG_BYTES_IN_INT = 2;
+ * static final int BYTES_IN_INT = 1<<LOG_BYTES_IN_INT;
+ * static final int LOG_BITS_IN_INT = LOG_BITS_IN_BYTE + LOG_BYTES_IN_INT;
+ * static final int BITS_IN_INT = 1<<LOG_BITS_IN_INT;
+ * </pre>
+ */
+public interface Constants {
+
+ /****************************************************************************
+ *
+ * MMTk constants
+ */
+ int PUTFIELD_WRITE_BARRIER = 0;
+ int GETFIELD_READ_BARRIER = 0;
+ int PUTSTATIC_WRITE_BARRIER = 1;
+ int GETSTATIC_READ_BARRIER = 1;
+ int AASTORE_WRITE_BARRIER = 2;
+ int AALOAD_READ_BARRIER = 2;
+
+
+ /****************************************************************************
+ *
+ * Generic sizes
+ */
+ byte LOG_BYTES_IN_BYTE = 0;
+ int BYTES_IN_BYTE = 1;
+ byte LOG_BITS_IN_BYTE = 3;
+ int BITS_IN_BYTE = 1 << LOG_BITS_IN_BYTE;
+
+ byte LOG_BYTES_IN_MBYTE = 20;
+ int BYTES_IN_MBYTE = 1 << LOG_BYTES_IN_MBYTE;
+
+ byte LOG_BYTES_IN_KBYTE = 10;
+ int BYTES_IN_KBYTE = 1 << LOG_BYTES_IN_KBYTE;
+
+ /****************************************************************************
+ *
+ * Card scanning
+ */
+ boolean SUPPORT_CARD_SCANNING = false;
+ int LOG_CARD_META_SIZE = 2;// each card consumes four bytes of metadata
+ int LOG_CARD_UNITS = 10; // number of units tracked per card
+ int LOG_CARD_GRAIN = 0; // track at byte grain, save shifting
+ int LOG_CARD_BYTES = LOG_CARD_UNITS + LOG_CARD_GRAIN;
+ int LOG_CARD_META_BYTES = EmbeddedMetaData.LOG_BYTES_IN_REGION - LOG_CARD_BYTES + LOG_CARD_META_SIZE;
+ int LOG_CARD_META_PAGES = LOG_CARD_META_BYTES - VM.LOG_BYTES_IN_PAGE;
+ int CARD_META_PAGES_PER_REGION = SUPPORT_CARD_SCANNING ? (1<<LOG_CARD_META_PAGES) : 0;
+ int CARD_MASK = (1<<LOG_CARD_BYTES) - 1;
+
+
+ /****************************************************************************
+ *
+ * Java-specific sizes currently required by MMTk
+ *
+ * TODO MMTk should really become independent of these Java types
+ */
+ byte LOG_BYTES_IN_SHORT = 1;
+ int BYTES_IN_SHORT = 1 << LOG_BYTES_IN_SHORT;
+ byte LOG_BITS_IN_SHORT = LOG_BITS_IN_BYTE + LOG_BYTES_IN_SHORT;
+ int BITS_IN_SHORT = 1 << LOG_BITS_IN_SHORT;
+
+ byte LOG_BYTES_IN_INT = 2;
+ int BYTES_IN_INT = 1 << LOG_BYTES_IN_INT;
+ byte LOG_BITS_IN_INT = LOG_BITS_IN_BYTE + LOG_BYTES_IN_INT;
+ int BITS_IN_INT = 1 << LOG_BITS_IN_INT;
+
+ int MAX_INT = 0x7fffffff;
+ int MIN_INT = 0x80000000;
+
+ /****************************************************************************
+ *
+ * VM-Specific sizes
+ */
+ byte LOG_BYTES_IN_ADDRESS = VM.LOG_BYTES_IN_ADDRESS;
+ 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;
+
+ // Note that in MMTk we currently define WORD & ADDRESS to be the same size
+ byte LOG_BYTES_IN_WORD = LOG_BYTES_IN_ADDRESS;
+ 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;
+
+ byte LOG_BYTES_IN_PAGE = VM.LOG_BYTES_IN_PAGE;
+ 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;
+
+ /* Assume byte-addressability */
+ byte LOG_BYTES_IN_ADDRESS_SPACE = (byte) BITS_IN_ADDRESS;
+
+ /**
+ * This value specifies the <i>minimum</i> allocation alignment
+ * requirement of the VM. When making allocation requests, both
+ * <code>align</code> and <code>offset</code> must be multiples of
+ * <code>MIN_ALIGNMENT</code>.
+ *
+ * This value is required to be a power of 2.
+ */
+ byte LOG_MIN_ALIGNMENT = VM.LOG_MIN_ALIGNMENT;
+ int MIN_ALIGNMENT = 1 << LOG_MIN_ALIGNMENT;
+
+ /**
+ * The maximum alignment request the vm will make. This must be a
+ * power of two multiple of the minimum alignment.
+ */
+ int MAX_ALIGNMENT = MIN_ALIGNMENT<<VM.MAX_ALIGNMENT_SHIFT;
+
+ /**
+ * The VM will add at most this value minus BYTES_IN_INT bytes of
+ * padding to the front of an object that it places in a region of
+ * memory. This value must be a power of 2.
+ */
+ int MAX_BYTES_PADDING = VM.MAX_BYTES_PADDING;
+
+ /**
+ * The VM will add at most this value minus BYTES_IN_INT bytes of
+ * padding to the front of an object that it places in a region of
+ * memory. This value must be a power of 2.
+ */
+ int ALIGNMENT_VALUE = VM.ALIGNMENT_VALUE;
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/Conversions.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/Conversions.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/Conversions.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/Conversions.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.utility;
+
+import org.mmtk.utility.heap.*;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/*
+ import org.jikesrvm.Offset;
+ * Conversions between different units.
+ */
+ at Uninterruptible public class Conversions implements Constants {
+
+ // public static Address roundDownVM(Address addr) {
+ // return roundDown(addr.toWord(), VMResource.LOG_BYTES_IN_REGION).toAddress();
+ // }
+
+ // public static Extent roundDownVM(Extent bytes) {
+ // return roundDown(bytes.toWord(), VMResource.LOG_BYTES_IN_REGION).toExtent();
+ // }
+
+ public static Address roundDownMB(Address addr) {
+ return roundDown(addr.toWord(), LOG_BYTES_IN_MBYTE).toAddress();
+ }
+
+ public static Extent roundDownMB(Extent bytes) {
+ return roundDown(bytes.toWord(), LOG_BYTES_IN_MBYTE).toExtent();
+ }
+
+ private static Word roundDown(Word value, int logBase) {
+ Word mask = Word.one().lsh(logBase).minus(Word.one()).not();
+ return value.and(mask);
+ }
+
+ public static int roundDown(int value, int alignment) {
+ return value & ~(alignment - 1);
+ }
+
+ // Round up (if necessary)
+ //
+ public static int MBToPages(int megs) {
+ if (LOG_BYTES_IN_PAGE <= LOG_BYTES_IN_MBYTE)
+ return (megs << (LOG_BYTES_IN_MBYTE - LOG_BYTES_IN_PAGE));
+ else
+ return (megs + ((BYTES_IN_PAGE >>> LOG_BYTES_IN_MBYTE) - 1)) >>> (LOG_BYTES_IN_PAGE - LOG_BYTES_IN_MBYTE);
+ }
+
+ public static int bytesToMmapChunksUp(Extent bytes) {
+ return bytes.plus(Mmapper.MMAP_CHUNK_BYTES - 1).toWord().rshl(Mmapper.LOG_MMAP_CHUNK_BYTES).toInt();
+ }
+
+ public static int pagesToMmapChunksUp(int pages) {
+ return bytesToMmapChunksUp(pagesToBytes(pages));
+ }
+
+ public static int addressToMmapChunksDown(Address addr) {
+ Word chunk = addr.toWord().rshl(Mmapper.LOG_MMAP_CHUNK_BYTES);
+ return chunk.toInt();
+ }
+
+ public static int addressToPagesDown(Address addr) {
+ Word chunk = addr.toWord().rshl(LOG_BYTES_IN_PAGE);
+ return chunk.toInt();
+ }
+
+ public static int addressToPages(Address addr) {
+ int page = addressToPagesDown(addr);
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(pagesToAddress(page).EQ(addr));
+ return page;
+ }
+
+ public static Address pagesToAddress(int pages) {
+ return Word.fromIntZeroExtend(pages).lsh(LOG_BYTES_IN_PAGE).toAddress();
+ }
+
+ public static int addressToMmapChunksUp(Address addr) {
+ Word chunk = addr.plus(Mmapper.MMAP_CHUNK_BYTES - 1).toWord().rshl(Mmapper.LOG_MMAP_CHUNK_BYTES);
+ return chunk.toInt();
+ }
+
+ public static Extent pagesToBytes(int pages) {
+ return Word.fromIntZeroExtend(pages).lsh(LOG_BYTES_IN_PAGE).toExtent();
+ }
+
+ public static int pagesToMBytes(int pages) {
+ return pages >> (LOG_BYTES_IN_MBYTE - LOG_BYTES_IN_PAGE);
+ }
+
+ public static int pagesToKBytes(int pages) {
+ return pages << (LOG_BYTES_IN_PAGE - LOG_BYTES_IN_KBYTE);
+ }
+
+ /**
+ @deprecated : use int bytesToPagesUp(Extent bytes) if possible
+ */
+ @Deprecated
+ public static int bytesToPagesUp(int bytes) {
+ return bytesToPagesUp(Extent.fromIntZeroExtend(bytes));
+ }
+
+ /**
+ @deprecated : use int bytesToPagesUp(Extent bytes) if possible
+ */
+ @Deprecated
+ public static int bytesToPages(int bytes) {
+ return bytesToPages(Extent.fromIntZeroExtend(bytes));
+ }
+
+ public static int bytesToPagesUp(Extent bytes) {
+ return bytes.plus(BYTES_IN_PAGE-1).toWord().rshl(LOG_BYTES_IN_PAGE).toInt();
+ }
+
+ public static int bytesToPages(Extent bytes) {
+ int pages = bytesToPagesUp(bytes);
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(pagesToAddress(pages).toWord().toExtent().EQ(bytes));
+ return pages;
+ }
+
+ public static int bytesToPages(Offset bytes) {
+ if (VM.VERIFY_ASSERTIONS) {
+ long val = bytes.toLong();
+ VM.assertions._assert(val >= MIN_INT && val <= MAX_INT);
+ }
+ if (bytes.sGE(Offset.zero()))
+ return bytesToPagesUp(Extent.fromIntSignExtend(bytes.toInt()));
+ else
+ return -bytesToPagesUp(Extent.fromIntSignExtend(-bytes.toInt()));
+ }
+
+ public static Address mmapChunksToAddress(int chunk) {
+ return Word.fromIntZeroExtend(chunk).lsh(Mmapper.LOG_MMAP_CHUNK_BYTES).toAddress();
+ }
+
+ public static Address pageAlign(Address address) {
+ return address.toWord().rshl(LOG_BYTES_IN_PAGE).lsh(LOG_BYTES_IN_PAGE).toAddress();
+ }
+
+ public static int pageAlign(int value) {
+ return (value>>LOG_BYTES_IN_PAGE)<<LOG_BYTES_IN_PAGE;
+ }
+
+ public static boolean isPageAligned(Address address) {
+ return pageAlign(address).EQ(address);
+ }
+
+ public static boolean isPageAligned(int value) {
+ return pageAlign(value) == value;
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/CycleDetector.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/CycleDetector.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/CycleDetector.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/CycleDetector.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.utility;
+
+import org.mmtk.utility.options.*;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/*
+ */
+ at Uninterruptible abstract class CycleDetector {
+
+ static {
+ Options.cycleFilterThreshold = new CycleFilterThreshold();
+ Options.cycleMetaDataLimit = new CycleMetaDataLimit();
+ Options.cycleTriggerThreshold = new CycleTriggerThreshold();
+ }
+
+ abstract boolean collectCycles(boolean primary, boolean time);
+ abstract void possibleCycleRoot(ObjectReference object);
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/DoublyLinkedList.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/DoublyLinkedList.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/DoublyLinkedList.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/DoublyLinkedList.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.utility;
+
+import org.mmtk.utility.gcspy.drivers.AbstractDriver;
+
+import org.mmtk.vm.Lock;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * FIXME This class must be re-written as it makes the assumption that
+ * the implementation language (Java) and the language being
+ * implemented are the same. This is true in the case of Jikes RVM,
+ * but it is not true for any VM implementing a language other than
+ * Java.
+ *
+ *
+ * Each instance of this class is a doubly-linked list, in which
+ * each item or node is a piece of memory. The first two words of each node
+ * contains the forward and backward links. The third word contains
+ * the treadmill. The remaining portion is the payload.
+ *
+ * The treadmill object itself must not be moved.
+ *
+ * Access to the instances may be synchronized depending on the
+ * constructor argument.
+ */
+ at Uninterruptible public final class DoublyLinkedList implements Constants {
+
+ /****************************************************************************
+ *
+ * Class variables
+ */
+
+ /****************************************************************************
+ *
+ * Instance variables
+ */
+ private Address head;
+ private final Lock lock;
+ private final int logGranularity; // Each node on the treadmill is guaranteed to be a multiple of granularity.
+
+ /****************************************************************************
+ *
+ * Instance Methods
+ */
+
+ /**
+ * Constructor
+ */
+ public DoublyLinkedList(int logGranularity, boolean shared) {
+ head = Address.zero();
+ lock = shared ? VM.newLock("DoublyLinkedList") : null;
+ this.logGranularity = logGranularity;
+
+ // ensure that granularity is big enough for midPayloadToNode to work
+ Word tmp = Word.one().lsh(logGranularity);
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(tmp.and(nodeMask).EQ(tmp));
+ }
+
+ // Offsets are relative to the node (not the payload)
+ //
+ private static final Offset PREV_OFFSET = Offset.fromIntSignExtend(0 * BYTES_IN_ADDRESS);
+ private static Offset NEXT_OFFSET = Offset.fromIntSignExtend(1 * BYTES_IN_ADDRESS);
+ private static Offset HEADER_SIZE = Offset.fromIntSignExtend(2 * BYTES_IN_ADDRESS);
+
+ private static final Word nodeMask;
+ static {
+ Word mask = Word.one();
+ while (mask.LE(HEADER_SIZE.plus(MAX_BYTES_PADDING).toWord())) mask = mask.lsh(1);
+ nodeMask = mask.minus(Word.one()).not();
+ }
+
+ @Inline
+ public static int headerSize() {
+ return HEADER_SIZE.toInt();
+ }
+
+ public boolean isNode(Address node) {
+ return node.toWord().rshl(logGranularity).lsh(logGranularity).EQ(node.toWord());
+ }
+
+ @Inline
+ public static Address nodeToPayload(Address node) {
+ return node.plus(HEADER_SIZE);
+ }
+
+ @Inline
+ public static Address midPayloadToNode(Address payload) {
+ // This method words as long as you are less than MAX_BYTES_PADDING into the payload.
+ return payload.toWord().and(nodeMask).toAddress();
+ }
+
+ @Inline
+ public void add(Address node) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isNode(node));
+ if (lock != null) lock.acquire();
+ node.store(Address.zero(), PREV_OFFSET);
+ node.store(head, NEXT_OFFSET);
+ if (!head.isZero())
+ head.store(node, PREV_OFFSET);
+ head = node;
+ if (lock != null) lock.release();
+ }
+
+ @Inline
+ public void remove(Address node) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isNode(node));
+ if (lock != null) lock.acquire();
+ Address prev = node.loadAddress(PREV_OFFSET);
+ Address next = node.loadAddress(NEXT_OFFSET);
+ // Splice the node out of the list
+ if (!next.isZero())
+ next.store(prev, PREV_OFFSET);
+ if (prev.isZero())
+ head = next;
+ else
+ prev.store(next, NEXT_OFFSET);
+ // Null out node's reference to the list
+ node.store(Address.zero(), PREV_OFFSET);
+ node.store(Address.zero(), NEXT_OFFSET);
+ if (lock != null) lock.release();
+ }
+
+ @Inline
+ public Address getHead() {
+ return head;
+ }
+
+ @Inline
+ public Address getNext(Address node) {
+ return node.loadAddress(NEXT_OFFSET);
+ }
+
+ @Inline
+ public Address pop() {
+ Address first = head;
+ if (!first.isZero())
+ remove(first);
+ return first;
+ }
+
+ @Inline
+ public boolean isEmpty() {
+ return head.isZero();
+ }
+
+ /**
+ * Return true if a cell is on a given treadmill
+ *
+ * @param node The cell being searched for
+ * @return True if the cell is found on the treadmill
+ */
+ public boolean isMember(Address node) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isNode(node));
+ boolean result = false;
+ if (lock != null) lock.acquire();
+ Address cur = head;
+ while (!cur.isZero()) {
+ if (cur.EQ(node)) {
+ result = true;
+ break;
+ }
+ cur = cur.loadAddress(NEXT_OFFSET);
+ }
+ if (lock != null) lock.release();
+ return result;
+ }
+
+ public void show() {
+ if (lock != null) lock.acquire();
+ Address cur = head;
+ Log.write(cur);
+ while (!cur.isZero()) {
+ cur = cur.loadAddress(NEXT_OFFSET);
+ Log.write(" -> "); Log.write(cur);
+ }
+ Log.writeln();
+ if (lock != null) lock.release();
+ }
+
+
+ /**
+ * Gather data for GCSpy
+ * @param driver the GCSpy space driver
+ */
+ void gcspyGatherData(AbstractDriver driver) {
+ // GCSpy doesn't need a lock (in its stop the world config)
+ Address cur = head;
+ while (!cur.isZero()) {
+ driver.scan(cur);
+ cur = cur.loadAddress(NEXT_OFFSET);
+ }
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/GenericFreeList.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/GenericFreeList.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/GenericFreeList.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/GenericFreeList.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,383 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This is a very simple, generic malloc-free allocator. It works
+ * abstractly, in "units", which the user may associate with some
+ * other allocatable resource (e.g. heap blocks). The user issues
+ * requests for N units and the allocator returns the index of the
+ * first of a contiguous set of N units or fails, returning -1. The
+ * user frees the block of N units by calling <code>free()</code> with
+ * the index of the first unit as the argument.<p>
+ *
+ * Properties/Constraints:<ul>
+ * <li> The allocator consumes one word per allocatable unit (plus
+ * a fixed overhead of about 128 words).</li>
+ * <li> The allocator can only deal with MAX_UNITS units (see below for
+ * the value).</li>
+ * </ul>
+ *
+ * The basic data structure used by the algorithm is a large table,
+ * with one word per allocatable unit. Each word is used in a
+ * number of different ways, some combination of "undefined" (32),
+ * "free/used" (1), "multi/single" (1), "prev" (15), "next" (15) &
+ * "size" (15) where field sizes in bits are in parenthesis.
+ * <pre>
+ * +-+-+-----------+-----------+
+ * |f|m| prev | next/size |
+ * +-+-+-----------+-----------+
+ *
+ * - single free unit: "free", "single", "prev", "next"
+ * - single used unit: "used", "single"
+ * - contiguous free units
+ * . first unit: "free", "multi", "prev", "next"
+ * . second unit: "free", "multi", "size"
+ * . last unit: "free", "multi", "size"
+ * - contiguous used units
+ * . first unit: "used", "multi", "prev", "next"
+ * . second unit: "used", "multi", "size"
+ * . last unit: "used", "multi", "size"
+ * - any other unit: undefined
+ *
+ * +-+-+-----------+-----------+
+ * top sentinel |0|0| tail | head | [-1]
+ * +-+-+-----------+-----------+
+ * ....
+ * /-------- +-+-+-----------+-----------+
+ * | |1|1| prev | next | [j]
+ * | +-+-+-----------+-----------+
+ * | |1|1| | size | [j+1]
+ * free multi +-+-+-----------+-----------+
+ * unit block | ... | ...
+ * | +-+-+-----------+-----------+
+ * | |1|1| | size |
+ * >-------- +-+-+-----------+-----------+
+ * single free unit |1|0| prev | next |
+ * >-------- +-+-+-----------+-----------+
+ * single used unit |0|0| |
+ * >-------- +-+-+-----------------------+
+ * | |0|1| |
+ * | +-+-+-----------+-----------+
+ * | |0|1| | size |
+ * used multi +-+-+-----------+-----------+
+ * unit block | ... |
+ * | +-+-+-----------+-----------+
+ * | |0|1| | size |
+ * \-------- +-+-+-----------+-----------+
+ * ....
+ * +-+-+-----------------------+
+ * bottom sentinel |0|0| | [N]
+ * +-+-+-----------------------+
+ * </pre>
+ * The sentinels serve as guards against out of range coalescing
+ * because they both appear as "used" blocks and so will never
+ * coalesce. The top sentinel also serves as the head and tail of
+ * the doubly linked list of free blocks.
+ */
+ at Uninterruptible
+public final class GenericFreeList extends BaseGenericFreeList implements Constants {
+
+ /****************************************************************************
+ *
+ * Public instance methods
+ */
+
+ /**
+ * Constructor
+ *
+ * @param units The number of allocatable units for this free list
+ */
+ public GenericFreeList(int units) {
+ this(units, units);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param units The number of allocatable units for this free list
+ * @param grain Units are allocated such that they will never cross this granularity boundary
+ */
+ public GenericFreeList(int units, int grain) {
+ this(units, grain, 1);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param units The number of allocatable units for this free list
+ * @param grain Units are allocated such that they will never cross this granularity boundary
+ * @param heads The number of free lists which will share this instance
+ */
+ public GenericFreeList(int units, int grain, int heads) {
+ this.parent = null;
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(units <= MAX_UNITS && heads <= MAX_HEADS);
+ this.heads = heads;
+ head = -1;
+
+ // allocate the data structure, including space for top & bottom sentinels
+ table = new int[(units + 1 + heads) << 1];
+ initializeHeap(units, grain);
+ }
+
+ /**
+ * Resize the free list for a parent free list.
+ * This must not be called dynamically (ie not after bootstrap).
+ *
+ * @param units The number of allocatable units for this free list
+ * @param grain Units are allocated such that they will never cross this granularity boundary
+ */
+ @Interruptible
+ public void resizeFreeList(int units, int grain) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(parent == null && !Plan.isInitialized());
+ table = new int[(units + 1 + heads) << 1];
+ initializeHeap(units, grain);
+ }
+
+ /**
+ * Resize the free list for a child free list.
+ * This must not be called dynamically (ie not after bootstrap).
+ */
+ @Interruptible
+ public void resizeFreeList() {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(parent != null && !Plan.isInitialized());
+ table = parent.getTable();
+ }
+
+ /**
+ * Constructor
+ *
+ * @param parent The parent, owning the data structures this instance will share
+ * @param ordinal The ordinal number of this child
+ */
+ public GenericFreeList(GenericFreeList parent, int ordinal) {
+ this.parent = parent;
+ this.table = parent.getTable();
+ this.heads = parent.getHeads();
+ this.head = -(1 + ordinal);
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(-this.head <= this.heads);
+ }
+
+ /** Getter */
+ int[] getTable() { return table; }
+ int getHeads() { return heads; }
+
+ /**
+ * Initialize a unit as a sentinel
+ *
+ * @param unit The unit to be initialized
+ */
+ protected void setSentinel(int unit) {
+ setLoEntry(unit, NEXT_MASK & unit);
+ setHiEntry(unit, PREV_MASK & unit);
+ }
+
+ /**
+ * Get the size of a lump of units
+ *
+ * @param unit The first unit in the lump of units
+ * @return The size of the lump of units
+ */
+ protected int getSize(int unit) {
+ if ((getHiEntry(unit) & MULTI_MASK) == MULTI_MASK)
+ return (getHiEntry(unit + 1) & SIZE_MASK);
+ else
+ return 1;
+ }
+
+ /**
+ * Set the size of lump of units
+ *
+ * @param unit The first unit in the lump of units
+ * @param size The size of the lump of units
+ */
+ protected void setSize(int unit, int size) {
+ if (size > 1) {
+ setHiEntry(unit, getHiEntry(unit) | MULTI_MASK);
+ setHiEntry(unit + 1, MULTI_MASK | size);
+ setHiEntry(unit + size - 1, MULTI_MASK | size);
+ } else
+ setHiEntry(unit, getHiEntry(unit) & ~MULTI_MASK);
+ }
+
+ /**
+ * Establish whether a lump of units is free
+ *
+ * @param unit The first or last unit in the lump
+ * @return True if the lump is free
+ */
+ protected boolean getFree(int unit) {
+ return ((getLoEntry(unit) & FREE_MASK) == FREE_MASK);
+ }
+
+ /**
+ * Set the "free" flag for a lump of units (both the first and last
+ * units in the lump are set.
+ *
+ * @param unit The first unit in the lump
+ * @param isFree True if the lump is to be marked as free
+ */
+ protected void setFree(int unit, boolean isFree) {
+ int size;
+ if (isFree) {
+ setLoEntry(unit, getLoEntry(unit) | FREE_MASK);
+ if ((size = getSize(unit)) > 1)
+ setLoEntry(unit + size - 1, getLoEntry(unit + size - 1) | FREE_MASK);
+ } else {
+ setLoEntry(unit, getLoEntry(unit) & ~FREE_MASK);
+ if ((size = getSize(unit)) > 1)
+ setLoEntry(unit + size - 1, getLoEntry(unit + size - 1) & ~FREE_MASK);
+ }
+ }
+
+ /**
+ * Get the next lump in the doubly linked free list
+ *
+ * @param unit The index of the first unit in the current lump
+ * @return The index of the first unit of the next lump of units in the list
+ */
+ protected int getNext(int unit) {
+ int next = getHiEntry(unit) & NEXT_MASK;
+ return (next <= MAX_UNITS) ? next : head;
+ }
+
+ /**
+ * Set the next lump in the doubly linked free list
+ *
+ * @param unit The index of the first unit in the lump to be set
+ * @param next The value to be set.
+ */
+ protected void setNext(int unit, int next) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((next >= -heads) && (next <= MAX_UNITS));
+ int oldValue = getHiEntry(unit);
+ int newValue = (oldValue & ~NEXT_MASK) | (next & NEXT_MASK);
+ setHiEntry(unit, newValue);
+ }
+
+ /**
+ * Get the previous lump in the doubly linked free list
+ *
+ * @param unit The index of the first unit in the current lump
+ * @return The index of the first unit of the previous lump of units
+ * in the list
+ */
+ protected int getPrev(int unit) {
+ int prev = getLoEntry(unit) & PREV_MASK;
+ return (prev <= MAX_UNITS) ? prev : head;
+ }
+
+ /**
+ * Set the previous lump in the doubly linked free list
+ *
+ * @param unit The index of the first unit in the lump to be set
+ * @param prev The value to be set.
+ */
+ protected void setPrev(int unit, int prev) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((prev >= -heads) && (prev <= MAX_UNITS));
+ int oldValue = getLoEntry(unit);
+ int newValue = (oldValue & ~PREV_MASK) | (prev & PREV_MASK);
+ setLoEntry(unit, newValue);
+ }
+
+ /**
+ * Set the uncoalescable bit associated with this unit.
+ * This ensures this unit cannot be coalesced with units below
+ * it.
+ *
+ * @param unit The unit whose uncoalescable bit is to be set
+ */
+ public void setUncoalescable(int unit) {
+ setLoEntry(unit, getLoEntry(unit) | COALESC_MASK);
+ }
+
+ /**
+ * Clear the uncoalescable bit associated with this unit.
+ * This allows this unit to be coalesced with units below
+ * it.
+ *
+ * @param unit The unit whose uncoalescable bit is to be cleared
+ */
+ public void clearUncoalescable(int unit) {
+ setLoEntry(unit, getLoEntry(unit) & ~COALESC_MASK);
+ }
+
+ /**
+ * Return true if this unit may be coalesced with the unit below it.
+ *
+ * @param unit The unit in question
+ * @return True if this unit may be coalesced with the unit below it.
+ */
+ @Override
+ public boolean isCoalescable(int unit) {
+ return (getLoEntry(unit) & COALESC_MASK) == 0;
+ }
+
+ /**
+ * Get the lump to the "left" of the current lump (i.e. "above" it)
+ *
+ * @param unit The index of the first unit in the lump in question
+ * @return The index of the first unit in the lump to the
+ * "left"/"above" the lump in question.
+ */
+ protected int getLeft(int unit) {
+ if ((getHiEntry(unit - 1) & MULTI_MASK) == MULTI_MASK)
+ return unit - (getHiEntry(unit - 1) & SIZE_MASK);
+ else
+ return unit - 1;
+ }
+
+
+ /**
+ * Get the contents of an entry
+ *
+ * @param unit The index of the unit
+ * @return The contents of the unit
+ */
+ private int getLoEntry(int unit) {
+ return table[(unit + heads) << 1];
+ }
+ private int getHiEntry(int unit) {
+ return table[((unit + heads) << 1) + 1];
+ }
+
+ /**
+ * Set the contents of an entry
+ *
+ * @param unit The index of the unit
+ * @param value The contents of the unit
+ */
+ private void setLoEntry(int unit, int value) {
+ table[(unit + heads) << 1] = value;
+ }
+ private void setHiEntry(int unit, int value) {
+ table[((unit + heads) << 1) + 1] = value;
+ }
+
+ private static final int TOTAL_BITS = 32;
+ private static final int UNIT_BITS = (TOTAL_BITS - 2);
+ public static final int MAX_UNITS = (int) (((((long) 1) << UNIT_BITS) - 1) - MAX_HEADS - 1);
+ private static final int NEXT_MASK = (int) ((((long) 1) << UNIT_BITS) - 1);
+ private static final int PREV_MASK = (int) ((((long) 1) << UNIT_BITS) - 1);
+ private static final int FREE_MASK = 1 << (TOTAL_BITS - 1);
+ private static final int MULTI_MASK = 1 << (TOTAL_BITS - 1);
+ private static final int COALESC_MASK = 1 << (TOTAL_BITS - 2);
+ private static final int SIZE_MASK = (int) ((((long) 1) << UNIT_BITS) - 1);
+
+ private int[] table;
+ private final GenericFreeList parent;
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/Log.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/Log.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/Log.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/Log.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,842 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * Error and trace logging.
+ */
+ at Uninterruptible
+public class Log implements Constants {
+
+ /****************************************************************************
+ *
+ * Class variables
+ */
+
+ /**
+ * characters in the write buffer for the caller's message. This
+ * does not include characters reserved for the overflow message.
+ *
+ * This needs to be large because Jikes RVM's implementation of Lock.java
+ * logs a lot of information when there is potential GC deadlock.
+ */
+ private static final int MESSAGE_BUFFER_SIZE = 3000;
+
+ /** message added when the write buffer has overflown */
+ private static final String OVERFLOW_MESSAGE = "... WARNING: Text truncated.\n";
+
+ private static final char OVERFLOW_MESSAGE_FIRST_CHAR = OVERFLOW_MESSAGE.charAt(0);
+
+ /** characters in the overflow message, including the (optional) final
+ * newline */
+ private static final int OVERFLOW_SIZE = OVERFLOW_MESSAGE.length();
+
+ /**
+ * characters in buffer for building string representations of
+ * longs. A long is a signed 64-bit integer in the range -2^63 to
+ * 2^63+1. The number of digits in the decimal representation of
+ * 2^63 is ceiling(log10(2^63)) == ceiling(63 * log10(2)) == 19. An
+ * extra character may be required for a minus sign (-). So the
+ * maximum number of characters is 20.
+ */
+ private static final int TEMP_BUFFER_SIZE = 20;
+
+ /** string that prefixes numbers logged in hexadecimal */
+ private static final String HEX_PREFIX = "0x";
+
+ /**
+ * log2 of number of bits represented by a single hexidemimal digit
+ */
+ private static final int LOG_BITS_IN_HEX_DIGIT = 2;
+
+ /**
+ * log2 of number of digits in the unsigned hexadecimal
+ * representation of a byte
+ */
+ private static final int LOG_HEX_DIGITS_IN_BYTE = LOG_BITS_IN_BYTE - LOG_BITS_IN_HEX_DIGIT;
+
+ /**
+ * map of hexadecimal digit values to their character representations
+ */
+ private static final char [] hexDigitCharacter =
+ { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+
+ /** new line character. Emitted by writeln methods. */
+ private static final char NEW_LINE_CHAR = '\n';
+
+ /** log instance used at build time. */
+ private static Log log = new Log();
+
+ /****************************************************************************
+ *
+ * Instance variables
+ */
+
+ /** buffer to store written message until flushing */
+ private char [] buffer = new char[MESSAGE_BUFFER_SIZE + OVERFLOW_SIZE];
+
+ /** location of next character to be written */
+ private int bufferIndex = 0;
+
+ /** <code>true</code> if the buffer has overflown */
+ private boolean overflow = false;
+
+ /** The last character that was written by #addToBuffer(char). This is
+ used to check whether we want to newline-terminate the text. */
+ private char overflowLastChar = '\0';
+
+ /** <code>true</code> if a thread id will be prepended */
+ private boolean threadIdFlag = false;
+
+ /** buffer for building string representations of longs */
+ private char[] tempBuffer = new char[TEMP_BUFFER_SIZE];
+
+ /** constructor */
+ public Log() {
+ for (int i = 0; i < OVERFLOW_SIZE; i++) {
+ buffer[MESSAGE_BUFFER_SIZE + i] = OVERFLOW_MESSAGE.charAt(i);
+ }
+ }
+
+ /**
+ * writes a boolean. Either "true" or "false" is logged.
+ *
+ * @param b boolean value to be logged.
+ */
+ public static void write(boolean b) {
+ write(b ? "true" : "false");
+ }
+
+ /**
+ * writes a character
+ *
+ * @param c character to be logged
+ */
+ public static void write(char c) {
+ add(c);
+ }
+
+ /**
+ * writes a long, in decimal. The value is not padded and no
+ * thousands seperator is logged. If the value is negative a
+ * leading minus sign (-) is logged.
+ *
+ *
+ * @param l long value to be logged
+ */
+ public static void write(long l) {
+ boolean negative = l < 0;
+ int nextDigit;
+ char nextChar;
+ int index = TEMP_BUFFER_SIZE - 1;
+ char[] intBuffer = getIntBuffer();
+
+ nextDigit = (int) (l % 10);
+ nextChar = hexDigitCharacter[negative ? - nextDigit : nextDigit];
+ intBuffer[index--] = nextChar;
+ l = l / 10;
+
+ while (l != 0) {
+ nextDigit = (int) (l % 10);
+ nextChar = hexDigitCharacter[negative ? - nextDigit : nextDigit];
+ intBuffer[index--] = nextChar;
+ l = l / 10;
+ }
+
+ if (negative) {
+ intBuffer[index--] = '-';
+ }
+
+ for (index++; index < TEMP_BUFFER_SIZE; index++) {
+ add(intBuffer[index]);
+ }
+ }
+
+ /**
+ * writes a <code>double</code>. Two digits after the decimal point
+ * are always logged. The value is not padded and no thousands
+ * seperator is used. If the value is negative a leading
+ * hyphen-minus (-) is logged. The decimal point is a full stop
+ * (.).
+ *
+ * @param d the double to be logged
+ */
+ public static void write(double d) { write(d, 2); }
+
+ /**
+ * writes a <code>double</code>. The number of digits after the
+ * decimal point is determined by <code>postDecimalDigits</code>.
+ * The value is not padded and not thousands seperator is used. If
+ * the value is negative a leading hyphen-minus (-) is logged. The
+ * decimal point is a full stop (.) and is logged even if
+ * <postDecimcalDigits</code> is zero. If <code>d</code> is greater
+ * than the largest representable value of type <code>int</code>, it
+ * is logged as "TooBig". Similarly, if it is less than
+ * the negative of the largest representable value, it is logged as
+ * "TooSmall". If <code>d</code> is NaN is is logged as "NaN".
+ *
+ * @param d the double to be logged
+ * @param postDecimalDigits the number of digits to be logged after
+ * the decimal point. If less than or equal to zero no digits are
+ * logged, but the decimal point is.
+ */
+ public static void write(double d, int postDecimalDigits) {
+ if (d != d) {
+ write("NaN");
+ return;
+ }
+ if (d > Integer.MAX_VALUE) {
+ write("TooBig");
+ return;
+ }
+ if (d < -Integer.MAX_VALUE) {
+ write("TooSmall");
+ return;
+ }
+
+ boolean negative = (d < 0.0);
+ d = negative ? (-d) : d; // Take absolute value
+ int ones = (int) d;
+ int multiplier = 1;
+ while (postDecimalDigits-- > 0)
+ multiplier *= 10;
+ int remainder = (int) (multiplier * (d - ones));
+ if (remainder < 0) remainder = 0;
+ if (negative) write('-');
+ write(ones);
+ write('.');
+ while (multiplier > 1) {
+ multiplier /= 10;
+ write(remainder / multiplier);
+ remainder %= multiplier;
+ }
+ }
+
+ /**
+ * writes an array of characters
+ *
+ * @param c the array of characters to be logged
+ */
+ public static void write(char[] c) {
+ write(c, c.length);
+ }
+
+ /**
+ * writes the start of an array of characters
+ *
+ * @param c the array of characters
+ * @param len the number of characters to be logged, starting with
+ * the first character
+ */
+ public static void write(char[] c, int len) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(len <= c.length);
+ for (int i = 0; i < len; i++) {
+ add(c[i]);
+ }
+ }
+
+ /**
+ * writes an array of bytes. The bytes are interpretted
+ * as characters.
+ *
+ * @param b the array of bytes to be logged
+ */
+ public static void write(byte[] b) {
+ for (int i = 0; i < b.length; i++) {
+ add((char)b[i]);
+ }
+ }
+
+ /**
+ * writes a string
+ *
+ * @param s the string to be logged
+ */
+ public static void write(String s) {
+ add(s);
+ }
+
+ /**
+ * writes a word, in hexadecimal. It is zero-padded to the size of
+ * an address.
+ *
+ * @param w the word to be logged
+ */
+ public static void write(Word w) {
+ writeHex(w, BYTES_IN_ADDRESS);
+ }
+
+ /**
+ * writes a word, in decimal.
+ *
+ * @param w the word to be logged
+ */
+ public static void writeDec(Word w) {
+ if (BYTES_IN_ADDRESS == 4) {
+ write(w.toInt());
+ } else {
+ write(w.toLong());
+ }
+ }
+
+ /**
+ * writes an address, in hexademical. It is zero-padded.
+ *
+ * @param a the address to be logged
+ */
+ public static void write(Address a) {
+ writeHex(a.toWord(), BYTES_IN_ADDRESS);
+ }
+
+ /**
+ * writes a string followed by an address, in hexademical.
+ * @see #write(String)
+ * @see #write(Address)
+ *
+ * @param s the string to be logged
+ * @param a the address to be logged
+ */
+ public static void write(String s, Address a) {
+ write(s);
+ write(a);
+ }
+
+ /**
+ * Write a string followed by a long
+ * @see #write(String)
+ * @see #write(long)
+ *
+ * @param s the string to be logged
+ * @param l the long to be logged
+ */
+ public static void write(String s, long l) {
+ write(s);
+ write(l);
+ }
+
+ /**
+ * writes an object reference, in hexademical. It is zero-padded.
+ *
+ * @param o the object reference to be logged
+ */
+ public static void write(ObjectReference o) {
+ writeHex(o.toAddress().toWord(), BYTES_IN_ADDRESS);
+ }
+
+ /**
+ * writes an offset, in hexademical. It is zero-padded.
+ *
+ * @param o the offset to be logged
+ */
+ public static void write(Offset o) {
+ writeHex(o.toWord(), BYTES_IN_ADDRESS);
+ }
+
+ /**
+ * writes an extent, in hexademical. It is zero-padded.
+ *
+ * @param e the extent to be logged
+ */
+ public static void write(Extent e) {
+ writeHex(e.toWord(), BYTES_IN_ADDRESS);
+ }
+
+ /**
+ * write a new-line and flushes the buffer
+ */
+ public static void writeln() {
+ writelnWithFlush(true);
+ }
+
+ /**
+ * writes a boolean and a new-line, then flushes the buffer.
+ * @see #write(boolean)
+ *
+ * @param b boolean value to be logged.
+ */
+ public static void writeln(boolean b) { writeln(b, true); }
+
+ /**
+ * writes a character and a new-line, then flushes the buffer.
+ * @see #write(char)
+ *
+ * @param c character to be logged
+ */
+ public static void writeln(char c) { writeln(c, true); }
+
+ /**
+ * writes a long, in decimal, and a new-line, then flushes the buffer.
+ * @see #write(long)
+ *
+ * @param l long value to be logged
+ */
+ public static void writeln(long l) { writeln(l, true); }
+
+ /**
+ * writes a <code>double</code> and a new-line, then flushes the buffer.
+ * @see #write(double)
+ *
+ * @param d the double to be logged
+ */
+ public static void writeln(double d) { writeln(d, true); }
+
+ /**
+ * writes a <code>double</code> and a new-line, then flushes the buffer.
+ * @see #write(double, int)
+ *
+ * @param d the double to be logged
+ */
+ public static void writeln(double d, int postDecimalDigits) {
+ writeln(d, postDecimalDigits, true); }
+
+ /**
+ * writes an array of characters and a new-line, then flushes the buffer.
+ * @see #write(char [])
+ *
+ * @param ca the array of characters to be logged
+ */
+ public static void writeln(char [] ca) { writeln(ca, true); }
+
+ /**
+ * writes the start of an array of characters and a new-line, then
+ * flushes the buffer.
+ * @see #write(char[], int)
+ *
+ * @param ca the array of characters
+ * @param len the number of characters to be logged, starting with
+ * the first character
+ */
+ public static void writeln(char [] ca, int len) { writeln(ca, len, true); }
+
+ /**
+ * writes an array of bytes and a new-line, then
+ * flushes the buffer.
+ * @see #write(byte[])
+ *
+ * @param b the array of bytes to be logged
+ */
+ public static void writeln(byte [] b) { writeln(b, true); }
+
+ /**
+ * writes a string and a new-line, then flushes the buffer.
+ *
+ * @param s the string to be logged
+ */
+ public static void writeln(String s) { writeln(s, true); }
+
+ /**
+ * writes a word, in hexadecimal, and a new-line, then flushes the buffer.
+ * @see #write(Word)
+ *
+ * @param w the word to be logged
+ */
+ public static void writeln(Word w) { writeln(w, true); }
+
+ /**
+ * writes an address, in hexademical, and a new-line, then flushes
+ * the buffer.
+ * @see #write(Address)
+ *
+ * @param a the address to be logged
+ */
+ public static void writeln(Address a) { writeln(a, true); }
+
+ /**
+ * writes an object reference, in hexademical, and a new-line, then
+ * flushes the buffer.
+ * @see #write(ObjectReference)
+ *
+ * @param o the object reference to be logged
+ */
+ public static void writeln(ObjectReference o) { writeln(o, true); }
+
+ /**
+ * writes an offset, in hexademical, and a new-line, then flushes the buffer.
+ * @see #write(Offset)
+ *
+ * @param o the offset to be logged
+ */
+ public static void writeln(Offset o) { writeln(o, true); }
+
+ /**
+ * writes an extent, in hexademical, and a new-line, then flushes the buffer.
+ * @see #write(Extent)
+ *
+ * @param e the extent to be logged
+ */
+ public static void writeln(Extent e) { writeln(e, true); }
+
+ /**
+ * writes a new-line without flushing the buffer
+ */
+ public static void writelnNoFlush() {
+ writelnWithFlush(false);
+ }
+
+ /**
+ * writes a boolean and a new-line, then optionally flushes the buffer.
+ * @see #write(boolean)
+ *
+ * @param b boolean value to be logged.
+ * @param flush if <code>true</code> then flushes the buffer
+ */
+ public static void writeln(boolean b, boolean flush) {
+ write(b);
+ writelnWithFlush(flush);
+ }
+
+ /**
+ * writes a character and a new-line, then optionally flushes the
+ * buffer.
+ * @see #write(char)
+ *
+ * @param c character to be logged
+ * @param flush if <code>true</code> then flushes the buffer
+ */
+ public static void writeln(char c, boolean flush) {
+ write(c);
+ writelnWithFlush(flush);
+ }
+
+ /**
+ * writes a long, in decimal, and a new-line, then optionally flushes
+ * the buffer.
+ * @see #write(long)
+ *
+ * @param l long value to be logged
+ * @param flush if <code>true</code> then flushes the buffer
+ */
+ public static void writeln(long l, boolean flush) {
+ write(l);
+ writelnWithFlush(flush);
+ }
+
+ /**
+ * writes a <code>double</code> and a new-line, then optionally flushes
+ * the buffer.
+ * @see #write(double)
+ *
+ * @param d the double to be logged
+ * @param flush if <code>true</code> then flush the buffer
+ */
+ public static void writeln(double d, boolean flush) {
+ write(d);
+ writelnWithFlush(flush);
+ }
+
+ /**
+ * writes a <code>double</code> and a new-line, then optionally flushes
+ * the buffer.
+ * @see #write(double, int)
+ *
+ * @param d the double to be logged
+ * @param flush if <code>true</code> then flushes the buffer
+ */
+ public static void writeln(double d, int postDecimalDigits, boolean flush) {
+ write(d, postDecimalDigits);
+ writelnWithFlush(flush);
+ }
+
+
+ /**
+ * writes an array of characters and a new-line, then optionally
+ * flushes the buffer.
+ * @see #write(char [])
+ *
+ * @param ca the array of characters to be logged
+ * @param flush if <code>true</code> then flushes the buffer
+ */
+ public static void writeln(char[] ca, boolean flush) {
+ write(ca);
+ writelnWithFlush(flush);
+ }
+
+ /**
+ * writes the start of an array of characters and a new-line, then
+ * optionally flushes the buffer.
+ * @see #write(char[], int)
+ *
+ * @param ca the array of characters
+ * @param len the number of characters to be logged, starting with
+ * the first character
+ * @param flush if <code>true</code> then flushes the buffer
+ */
+ public static void writeln(char[] ca, int len, boolean flush) {
+ write(ca, len);
+ writelnWithFlush(flush);
+ }
+
+ /**
+ * writes an array of bytes and a new-line, then optionally flushes the
+ * buffer.
+ * @see #write(byte[])
+ *
+ * @param b the array of bytes to be logged
+ * @param flush if <code>true</code> then flushes the buffer
+ */
+ public static void writeln(byte[] b, boolean flush) {
+ write(b);
+ writelnWithFlush(flush);
+ }
+
+ /**
+ * writes a string and a new-line, then optionally flushes the buffer.
+ *
+ * @param s the string to be logged
+ * @param flush if <code>true</code> then flushes the buffer
+ */
+ public static void writeln(String s, boolean flush) {
+ write(s);
+ writelnWithFlush(flush);
+ }
+
+ public static void writeln(String s, long l) {
+ write(s);
+ writeln(l);
+ }
+
+
+ /**
+ * writes a word, in hexadecimal, and a new-line, then optionally
+ * flushes the buffer.
+ * @see #write(Word)
+ *
+ * @param w the word to be logged
+ * @param flush if <code>true</code> then flushes the buffer
+ */
+ public static void writeln(Word w, boolean flush) {
+ write(w);
+ writelnWithFlush(flush);
+ }
+
+
+ /**
+ * writes an address, in hexademical, and a new-line, then optionally
+ * flushes the buffer.
+ * @see #write(Address)
+ *
+ * @param a the address to be logged
+ * @param flush if <code>true</code> then flushes the buffer
+ */
+ public static void writeln(Address a, boolean flush) {
+ write(a);
+ writelnWithFlush(flush);
+ }
+
+ /**
+ * writes an object reference, in hexademical, and a new-line, then
+ * optionally flushes the buffer.
+ * @see #write(ObjectReference)
+ *
+ * @param o the object reference to be logged
+ * @param flush if <code>true</code> then flushes the buffer
+ */
+ public static void writeln(ObjectReference o, boolean flush) {
+ write(o);
+ writelnWithFlush(flush);
+ }
+
+ /**
+ * writes an offset, in hexademical, and a new-line, then optionally
+ * flushes the buffer.
+ * @see #write(Offset)
+ *
+ * @param o the offset to be logged
+ * @param flush if <code>true</code> then flushes the buffer
+ */
+ public static void writeln(Offset o, boolean flush) {
+ write(o);
+ writelnWithFlush(flush);
+ }
+
+ /**
+ * writes an extent, in hexademical, and a new-line, then optionally
+ * flushes the buffer.
+ * @see #write(Extent)
+ *
+ * @param e the extent to be logged
+ * @param flush if <code>true</code> then flushes the buffer
+ */
+ public static void writeln(Extent e, boolean flush) {
+ write(e);
+ writelnWithFlush(flush);
+ }
+
+ /**
+ * writes a string followed by a Address
+ * @see #write(String)
+ * @see #write(Address)
+ *
+ * @param s the string to be logged
+ * @param a the Address to be logged
+ */
+ public static void writeln(String s, Address a) {
+ write(s);
+ writeln(a);
+ }
+
+ /**
+ * Log a thread identifier at the start of the next message flushed.
+ */
+ public static void prependThreadId() {
+ getLog().setThreadIdFlag();
+ }
+
+ /**
+ * flushes the buffer. The buffered effected of writes since the last
+ * flush will be logged in one block without output from other
+ * thread's logging interleaving.
+ */
+ public static void flush() {
+ getLog().flushBuffer();
+ }
+
+ /**
+ * writes a new-line and optionally flushes the buffer
+ *
+ * @param flush if <code>true</code> the buffer is flushed
+ */
+ private static void writelnWithFlush(boolean flush) {
+ add(NEW_LINE_CHAR);
+ if (flush) {
+ flush();
+ }
+ }
+
+ /**
+ * writes a <code>long</code> in hexadecimal
+ *
+ * @param w the Word to be logged
+ * @param bytes the number of bytes from the long to be logged. If
+ * less than 8 then the least significant bytes are logged and some
+ * of the most significant bytes are ignored.
+ */
+ private static void writeHex(Word w, int bytes) {
+ int hexDigits = bytes * (1 << LOG_HEX_DIGITS_IN_BYTE);
+ int nextDigit;
+
+ write(HEX_PREFIX);
+
+ for (int digitNumber = hexDigits - 1; digitNumber >= 0; digitNumber--) {
+ nextDigit = w.rshl(digitNumber << LOG_BITS_IN_HEX_DIGIT).toInt() & 0xf;
+ char nextChar = hexDigitCharacter[nextDigit];
+ add(nextChar);
+ }
+ }
+
+ /**
+ * adds a character to the buffer
+ *
+ * @param c the character to add
+ */
+ private static void add(char c) {
+ getLog().addToBuffer(c);
+ }
+
+ /**
+ * adds a string to the buffer
+ *
+ * @param s the string to add
+ */
+ private static void add(String s) {
+ getLog().addToBuffer(s);
+ }
+
+ private static Log getLog() {
+ if (VM.assertions.runningVM()) {
+ return VM.activePlan.log();
+ } else {
+ return log;
+ }
+ }
+
+ /**
+ * adds a character to the buffer
+ *
+ * @param c the character to add
+ */
+ private void addToBuffer(char c) {
+ if (bufferIndex < MESSAGE_BUFFER_SIZE) {
+ buffer[bufferIndex++] = c;
+ } else {
+ overflow = true;
+ overflowLastChar = c;
+ }
+ }
+
+ /**
+ * adds a string to the buffer
+ *
+ * @param s the string to add
+ */
+ private void addToBuffer(String s) {
+ if (bufferIndex < MESSAGE_BUFFER_SIZE) {
+ bufferIndex += VM.strings.copyStringToChars(s, buffer, bufferIndex, MESSAGE_BUFFER_SIZE + 1);
+ if (bufferIndex == MESSAGE_BUFFER_SIZE + 1) {
+ overflow = true;
+ // We don't bother setting OVERFLOW_LAST_CHAR, since we don't have an
+ // MMTk method that lets us peek into a string. Anyway, it's just a
+ // convenience to get the newline right.
+ buffer[MESSAGE_BUFFER_SIZE] = OVERFLOW_MESSAGE_FIRST_CHAR;
+ bufferIndex--;
+ }
+ } else {
+ overflow = true;
+ }
+ }
+
+ /**
+ * flushes the buffer
+ */
+ private void flushBuffer() {
+ int newlineAdjust = overflowLastChar == NEW_LINE_CHAR ? 0 : -1;
+ int totalMessageSize = overflow ? (MESSAGE_BUFFER_SIZE + OVERFLOW_SIZE + newlineAdjust) : bufferIndex;
+ if (threadIdFlag) {
+ VM.strings.writeThreadId(buffer, totalMessageSize);
+ } else {
+ VM.strings.write(buffer, totalMessageSize);
+ }
+ threadIdFlag = false;
+ overflow = false;
+ overflowLastChar = '\0';
+ bufferIndex = 0;
+ }
+
+ /**
+ * sets the flag so that a thread identifier will be included before
+ * the logged message
+ */
+ private void setThreadIdFlag() {
+ threadIdFlag = true;
+ }
+
+ /**
+ * gets the buffer for building string representations of integers.
+ * There is one of these buffers for each Log instance.
+ */
+ private static char[] getIntBuffer() {
+ return getLog().getTempBuffer();
+ }
+
+ /**
+ * gets the buffer for building string representations of integers.
+ */
+ private char[] getTempBuffer() {
+ return tempBuffer;
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/Memory.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/Memory.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/Memory.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/Memory.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,216 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements basic memory copying, setting and clearing
+ * operations.
+ *
+ * NOTE: Most of the operations in this class are performed at teh
+ * granularity of a Java integer (ie 4-byte units)
+ *
+ * FIXME: Why can't these operations be performed at word-granularity?
+ */
+ at Uninterruptible
+public class Memory implements Constants {
+
+ /****************************************************************************
+ *
+ * Class variables
+ */
+
+ /** zero operations greater than this size are done using the
+ * underlying OS implementation of zero() */
+ private static final int SMALL_REGION_THRESHOLD = 1<<8; // empirically chosen
+
+
+ /****************************************************************************
+ *
+ * Basic memory setting and zeroing operations
+ */
+
+ /**
+ * Zero a region of memory
+ *
+ * @param start The start of the region to be zeroed (must be 4-byte aligned)
+ * @param bytes The number of bytes to be zeroed (must be 4-byte aligned)
+ */
+ @Inline
+ public static void zero(Address start, Extent bytes) {
+ if (VM.VERIFY_ASSERTIONS) {
+ assertAligned(start);
+ assertAligned(bytes);
+ }
+ if (bytes.GT(Extent.fromIntZeroExtend(SMALL_REGION_THRESHOLD)))
+ VM.memory.zero(start, bytes);
+ else
+ zeroSmall(start, bytes);
+ }
+
+ /**
+ * Zero a small region of memory
+ *
+ * @param start The start of the region to be zeroed (must be 4-byte aligned)
+ * @param bytes The number of bytes to be zeroed (must be 4-byte aligned)
+ */
+ @Inline
+ public static void zeroSmall(Address start, Extent bytes) {
+ if (VM.VERIFY_ASSERTIONS) {
+ assertAligned(start);
+ assertAligned(bytes);
+ }
+ Address end = start.plus(bytes);
+ for (Address addr = start; addr.LT(end); addr = addr.plus(BYTES_IN_INT))
+ addr.store(0);
+ }
+
+ /**
+ * Set a region of memory
+ *
+ * @param start The start of the region to be zeroed (must be 4-byte aligned)
+ * @param bytes The number of bytes to be zeroed (must be 4-byte aligned)
+ * @param value The value to which the integers in the region should be set
+ */
+ @Inline
+ public static void set(Address start, int bytes, int value) {
+ if (VM.VERIFY_ASSERTIONS) {
+ assertAligned(start);
+ assertAligned(bytes);
+ }
+ Address end = start.plus(bytes);
+ for (Address addr = start; addr.LT(end); addr = addr.plus(BYTES_IN_INT))
+ addr.store(value);
+ }
+
+
+ /****************************************************************************
+ *
+ * Helper methods
+ */
+
+ /**
+ * Check that a memory range is zeroed
+ *
+ * @param start The start address of the range to be checked
+ * @param bytes The size of the region to be checked, in bytes
+ * @return True if the region is zeroed
+ */
+ @Inline
+ public static boolean IsZeroed(Address start, int bytes) {
+ return isSet(start, bytes, false, 0);
+ }
+
+ /**
+ * Assert that a memory range is zeroed. An assertion failure will
+ * occur if the region is not zeroed.
+ *
+ * this is in the inline allocation sequence when
+ * VM.VERIFY_ASSERTIONS is true, it is carefully written to
+ * reduce the impact on code space.
+ *
+ * @param start The start address of the range to be checked
+ * @param bytes The size of the region to be checked, in bytes
+ */
+ @NoInline
+ public static void assertIsZeroed(Address start, int bytes) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isSet(start, bytes, true, 0));
+ }
+
+ /**
+ * Verbosely check and return true if a memory range is set to some
+ * integer value
+ *
+ * @param start The start address of the range to be checked
+ * @param bytes The size of the region to be checked, in bytes
+ * @param value The value to which this region should be set
+ * @return True if the region has been correctly set
+ */
+ @Inline
+ public static boolean isSet(Address start, int bytes, int value) {
+ return isSet(start, bytes, true, value);
+ }
+
+ /**
+ * Assert appropriate alignment, triggering an assertion failure if
+ * the value does not satisify the alignment requirement of the
+ * memory operations.
+ *
+ * @param value The value to be tested
+ */
+ private static void assertAligned(int value) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((value & (BYTES_IN_INT - 1)) == 0);
+ }
+
+ private static void assertAligned(Word value) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(value.and(Word.fromIntSignExtend(BYTES_IN_INT-1)).isZero());
+ }
+
+ private static void assertAligned(Extent value) {
+ assertAligned(value.toWord());
+ }
+
+ private static void assertAligned(Address value) {
+ assertAligned(value.toWord());
+ }
+
+ /**
+ * Test whether a memory range is set to a given integer value
+ *
+ * @param start The address to start checking at
+ * @param bytes The size of the region to check, in bytes
+ * @param verbose If true, produce verbose output
+ * @param value The value to which the memory should be set
+ */
+ @NoInline
+ private static boolean isSet(Address start, int bytes, boolean verbose,
+ int value)
+ /* Inlining this loop into the uninterruptible code can
+ * cause/encourage the GCP into moving a get_obj_tib into the
+ * interruptible region where the tib is being installed via an
+ * int_store
+ */ {
+ if (VM.VERIFY_ASSERTIONS) assertAligned(bytes);
+ for (int i = 0; i < bytes; i += BYTES_IN_INT)
+ if (start.loadInt(Offset.fromIntSignExtend(i)) != value) {
+ if (verbose) {
+ Log.prependThreadId();
+ Log.write("VM range does not contain only value ");
+ Log.writeln(value);
+ Log.write("Non-zero range: "); Log.write(start);
+ Log.write(" .. "); Log.writeln(start.plus(bytes));
+ Log.write("First bad value at "); Log.writeln(start.plus(i));
+ dumpMemory(start, 0, bytes);
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Dump the contents of memory around a given address
+ *
+ * @param addr The address around which the memory should be dumped
+ * @param beforeBytes The number of bytes before the address to be
+ * included in the dump
+ * @param afterBytes The number of bytes after the address to be
+ * included in the dump
+ */
+ public static void dumpMemory(Address addr, int beforeBytes, int afterBytes) {
+ VM.memory.dumpMemory(addr, beforeBytes, afterBytes);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/SimpleHashtable.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/SimpleHashtable.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/SimpleHashtable.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/SimpleHashtable.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.utility;
+
+import org.mmtk.policy.RawPageSpace;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements a simple hashtable. It is intended for use
+ * in sanity checking or debugging, not high-performance algorithms.<p>
+ *
+ * This class is not thread safe.
+ */
+ at Uninterruptible public abstract class SimpleHashtable implements Constants {
+ /** The number of low order bits to ignore */
+ private static final int HASH_SHIFT = 3;
+
+ /** Offset to the key */
+ private static final Offset KEY_OFFSET = Offset.zero();
+
+ /** Offset to the data */
+ private static final Offset DATA_OFFSET = Offset.fromIntSignExtend(BYTES_IN_WORD);
+
+ /** The size of each entry in the table */
+ private final Extent entrySize;
+
+ /** The mask to use to get the hash code */
+ private final Word mask;
+
+ /** The start address of the data table */
+ private Address base;
+
+ /** The full size of the table */
+ private final Extent size;
+
+ /** The space to use for allocating the data structure */
+ private final RawPageSpace space;
+
+ /** Is this table valid (created) */
+ private boolean valid;
+
+ /**
+ * Create a new data table of a specified size.
+ *
+ * @param rps The space to acquire the data structure from.
+ * @param logSize The log of the number of table entries.
+ * @param es The size of each entry.
+ */
+ protected SimpleHashtable(RawPageSpace rps, int logSize, Extent es) {
+ mask = Word.fromIntZeroExtend((1 << logSize) - 1);
+ entrySize = es.plus(BYTES_IN_WORD);
+ size = Extent.fromIntZeroExtend((1 << logSize) * entrySize.toInt());
+ base = Address.zero();
+ space = rps;
+ valid = false;
+ }
+
+ /**
+ * Create a (zeroed) table.
+ */
+ public final void acquireTable() {
+ base = space.acquire(Conversions.bytesToPages(size));
+ VM.memory.zero(base, size);
+ valid = true;
+ }
+
+ /**
+ * Drop the table (after collection).
+ */
+ public final void releaseTable() {
+ space.release(base);
+ valid = false;
+ }
+
+ /**
+ * @return True if this table has backing data and is ready for use.
+ */
+ public final boolean isValid() {
+ return valid;
+ }
+
+ /**
+ * Retrieve a pointer to the entry for the given object, or zero if one
+ * does not exist, unless create is passed.<p>
+ *
+ * If create is true, the return is guaranteed to be non-null.
+ *
+ * @param key The key used to lookup.
+ * @param create Create a new entry if not found.
+ * @return A pointer to the reference or null.
+ */
+ @Inline
+ public final Address getEntry(Word key, boolean create) {
+ int startIndex = computeHash(key);
+ int index = startIndex;
+ Word curAddress;
+ Address entry;
+ do {
+ entry = getEntry(index);
+ curAddress = entry.loadWord(KEY_OFFSET);
+ index = (index + 1) & mask.toInt();
+ } while(curAddress.NE(key) &&
+ !curAddress.isZero() &&
+ index != startIndex);
+
+ if (index == startIndex) {
+ VM.assertions.fail("No room left in table!");
+ }
+
+ if (curAddress.isZero()) {
+ if (!create) return Address.zero();
+ entry.store(key, KEY_OFFSET);
+ }
+
+ return entry;
+ }
+
+ /**
+ * Compute the hashtable index for a given object.
+ *
+ * @param key The key.
+ * @return The index.
+ */
+ @Inline
+ private int computeHash(Word key) {
+ return key.rshl(HASH_SHIFT).and(mask).toInt();
+ }
+
+ /**
+ * Return the address of a specified entry in the table.
+ *
+ * @param index The index of the entry.
+ * @return An address to the entry.
+ */
+ @Inline
+ private Address getEntry(int index) {
+ return base.plus(Extent.fromIntZeroExtend(index * entrySize.toInt()));
+ }
+
+ /**
+ * Does the passed object have an entry in the table?
+ *
+ * @param key The key to find an entry for
+ * @return True if there is an entry for that object.
+ */
+ public final boolean contains(Word key) {
+ return !getEntry(key, false).isZero();
+ }
+
+ /**
+ * @return The first non-zero element in the table, or null if
+ * the table is empty.
+ */
+ public final Address getFirst() {
+ return getNext(base.minus(entrySize));
+ }
+
+ /**
+ * The next element in the table after the passed entry, or
+ * null if it is the last entry.
+ *
+ * @param curr The object to look for the next entry from.
+ * @return The next entry or null.
+ */
+ public final Address getNext(Address curr) {
+ Address entry = curr.plus(entrySize);
+ while (entry.LT(base.plus(size))) {
+ if (!entry.loadWord().isZero()) return entry;
+ entry = entry.plus(entrySize);
+ }
+ return Address.zero();
+ }
+
+ /**
+ * Given an address of an entry, return a pointer to the payload.
+ *
+ * @param entry The entry
+ * @return The object reference.
+ */
+ public static Address getPayloadAddress(Address entry) {
+ return entry.plus(DATA_OFFSET);
+ }
+
+ /**
+ * Given a key, return a pointer to the payload.
+ *
+ * @param key The key
+ * @return The object reference.
+ */
+ public final Address getPayloadAddress(Word key) {
+ Address entry = getEntry(key, false);
+ if (entry.isZero()) return Address.zero();
+
+ return entry.plus(DATA_OFFSET);
+ }
+
+
+ /**
+ * Return the key for a given entry.
+ *
+ * @param entry The entry.
+ * @return The key.
+ */
+ public static Word getKey(Address entry) {
+ return entry.loadWord(KEY_OFFSET);
+ }
+
+ /**
+ * Update the key for a given entry. This operation is not
+ * safe without rehashing
+ *
+ * @param entry The entry to update.
+ * @param key The new key.
+ */
+ public static void replaceKey(Address entry, Word key) {
+ entry.store(key, KEY_OFFSET);
+ }
+
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/Synchronize.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/Synchronize.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/Synchronize.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/Synchronize.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.utility;
+
+import org.vmmagic.pragma.*;
+
+/*
+ */
+ at Uninterruptible public class Synchronize{
+
+
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/TraceGenerator.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/TraceGenerator.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/TraceGenerator.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/TraceGenerator.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,410 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.plan.semispace.gctrace.GCTrace;
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.deque.*;
+import org.mmtk.utility.options.Options;
+import org.mmtk.utility.options.TraceRate;
+
+import org.mmtk.vm.VM;
+import org.mmtk.vm.Collection;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * Class that supports scanning Objects and Arrays for references
+ * during tracing, handling those references, and computing death times
+ */
+ at Uninterruptible public final class TraceGenerator
+ implements Constants, TracingConstants {
+
+
+ /***********************************************************************
+ *
+ * Class variables
+ */
+
+ /* Type of lifetime analysis to be used */
+ public static final boolean MERLIN_ANALYSIS = true;
+
+ /* include the notion of build-time allocation to our list of allocators */
+ private static final int ALLOC_BOOT = GCTrace.ALLOCATORS;
+ private static final int ALLOCATORS = ALLOC_BOOT + 1;
+
+ /* Fields for tracing */
+ private static SortTODSharedDeque tracePool; // Buffers to hold raw trace
+ private static TraceBuffer trace;
+ private static boolean traceBusy; // If we are building the trace
+ private static Word lastGC; // Last time GC was performed
+ private static ObjectReferenceArray objectLinks; // Lists of active objs
+
+ /* Fields needed for Merlin lifetime analysis */
+ private static SortTODSharedDeque workListPool; // Holds objs to process
+ private static SortTODObjectReferenceStack worklist; // Objs to process
+ private static Word agePropagate; // Death time propagating
+
+ static {
+ traceBusy = false;
+ lastGC = Word.fromIntZeroExtend(4);
+ Options.traceRate = new TraceRate();
+ }
+
+
+ /***********************************************************************
+ *
+ * Public analysis methods
+ */
+
+ /**
+ * This is called at "build-time" and passes the necessary build image
+ * objects to the trace processor.
+ *
+ * @param worklist_ The dequeue that serves as the worklist for
+ * death time propagation
+ * @param trace_ The dequeue used to store and then output the trace
+ */
+ @Interruptible
+ public static void init(SortTODSharedDeque worklist_,
+ SortTODSharedDeque trace_) {
+ /* Objects are only needed for merlin tracing */
+ if (MERLIN_ANALYSIS) {
+ workListPool = worklist_;
+ worklist = new SortTODObjectReferenceStack(workListPool);
+ }
+
+ /* Trace objects */
+ tracePool = trace_;
+ trace = new TraceBuffer(tracePool);
+ objectLinks = ObjectReferenceArray.create(Space.MAX_SPACES);
+ }
+
+ /**
+ * This is called immediately before Jikes terminates. It will perform
+ * any death time processing that the analysis requires and then output
+ * any remaining information in the trace buffer.
+ *
+ * @param value The integer value for the reason Jikes is terminating
+ */
+ public static void notifyExit(int value) {
+ if (MERLIN_ANALYSIS)
+ findDeaths();
+ trace.process();
+ }
+
+ /**
+ * Add a newly allocated object into the linked list of objects in a region.
+ * This is typically called after each object allocation.
+ *
+ * @param ref The address of the object to be added to the linked list
+ * @param linkSpace The region to which the object should be added
+ */
+ public static void addTraceObject(ObjectReference ref, int linkSpace) {
+ VM.traceInterface.setLink(ref, objectLinks.get(linkSpace));
+ objectLinks.set(linkSpace, ref);
+ }
+
+ /**
+ * Do the work necessary following each garbage collection. This HAS to be
+ * called after EACH collection.
+ */
+ public static void postCollection() {
+ /* Find and output the object deaths */
+ traceBusy = true;
+ findDeaths();
+ traceBusy = false;
+ trace.process();
+ }
+
+
+ /***********************************************************************
+ *
+ * Trace generation code
+ */
+
+ /**
+ * Add the information in the bootImage to the trace. This should be
+ * called before any allocations and pointer updates have occured.
+ *
+ * @param bootStart The address at which the bootimage starts
+ */
+ public static void boot(Address bootStart) {
+ Word nextOID = VM.traceInterface.getOID();
+ ObjectReference trav = VM.traceInterface.getBootImageLink().plus(bootStart.toWord().toOffset()).toObjectReference();
+ objectLinks.set(ALLOC_BOOT, trav);
+ /* Loop through all the objects within boot image */
+ while (!trav.isNull()) {
+ ObjectReference next = VM.traceInterface.getLink(trav);
+ Word thisOID = VM.traceInterface.getOID(trav);
+ /* Add the boot image object to the trace. */
+ trace.push(TRACE_BOOT_ALLOC);
+ trace.push(thisOID);
+ trace.push(nextOID.minus(thisOID).lsh(LOG_BYTES_IN_ADDRESS));
+ nextOID = thisOID;
+ /* Move to the next object & adjust for starting address of
+ the bootImage */
+ if (!next.isNull()) {
+ next = next.toAddress().plus(bootStart.toWord().toOffset()).toObjectReference();
+ VM.traceInterface.setLink(trav, next);
+ }
+ trav = next;
+ }
+ }
+
+ /**
+ * Do any tracing work required at each a pointer store operation. This
+ * will add the pointer store to the trace buffer and, when Merlin lifetime
+ * analysis is being used, performs the necessary timestamping.
+ *
+ * @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
+ * <code>tgt</code> will be stored
+ * @param tgt The target of the pointer store
+ */
+ @NoInline
+ public static void processPointerUpdate(boolean isScalar,
+ ObjectReference src,
+ Address slot, ObjectReference tgt) {
+ // The trace can be busy only if this is a pointer update as a result of
+ // the garbage collection needed by tracing. For the moment, we will
+ // not report these updates.
+ if (!traceBusy) {
+ /* Process the old target potentially becoming unreachable when needed. */
+ if (MERLIN_ANALYSIS) {
+ ObjectReference oldTgt = slot.loadObjectReference();
+ if (!oldTgt.isNull())
+ VM.traceInterface.updateDeathTime(oldTgt);
+ }
+
+ traceBusy = true;
+ /* Add the pointer store to the trace */
+ Offset traceOffset = VM.traceInterface.adjustSlotOffset(isScalar, src, slot);
+ if (isScalar)
+ trace.push(TRACE_FIELD_SET);
+ else
+ trace.push(TRACE_ARRAY_SET);
+ trace.push(VM.traceInterface.getOID(src));
+ trace.push(traceOffset.toWord());
+ if (tgt.isNull())
+ trace.push(Word.zero());
+ else
+ trace.push(VM.traceInterface.getOID(tgt));
+ traceBusy = false;
+ }
+ }
+
+ /**
+ * Do any tracing work required at each object allocation. This will add the
+ * object allocation to the trace buffer, triggers the necessary collection
+ * work at exact allocations, and output the data in the trace buffer.
+ *
+ * @param ref The address of the object just allocated.
+ * @param typeRef the type reference for the instance being created
+ * @param bytes The size of the object being allocated
+ */
+ @LogicallyUninterruptible
+ @NoInline
+ public static void traceAlloc(boolean isImmortal, ObjectReference ref,
+ ObjectReference typeRef, int bytes) {
+ boolean gcAllowed = VM.traceInterface.gcEnabled() && Plan.isInitialized() && !Plan.gcInProgress();
+ /* Test if it is time/possible for an exact allocation. */
+ Word oid = VM.traceInterface.getOID(ref);
+ Word allocType;
+ if (gcAllowed && (oid.GE(lastGC.plus(Word.fromIntZeroExtend(Options.traceRate.getValue())))))
+ allocType = TRACE_EXACT_ALLOC;
+ else {
+ allocType = TRACE_ALLOC;
+ }
+ /* Add the allocation into the trace. */
+ traceBusy = true;
+ /* When legally permissible, add the record to the trace buffer */
+ if (MERLIN_ANALYSIS) {
+ Address fp = (TraceBuffer.OMIT_ALLOCS) ? Address.zero() : VM.traceInterface.skipOwnFramesAndDump(typeRef);
+
+ if (isImmortal && allocType.EQ(TRACE_EXACT_ALLOC))
+ trace.push(TRACE_EXACT_IMMORTAL_ALLOC);
+ else if (isImmortal)
+ trace.push(TRACE_IMMORTAL_ALLOC);
+ else
+ trace.push(allocType);
+ trace.push(VM.traceInterface.getOID(ref));
+ trace.push(Word.fromIntZeroExtend(bytes - VM.traceInterface.getHeaderSize()));
+ trace.push(fp.toWord());
+ trace.push(Word.zero()); /* Magic.getThreadId() */
+ trace.push(TRACE_TIB_SET);
+ trace.push(VM.traceInterface.getOID(ref));
+ trace.push(VM.traceInterface.getOID(typeRef));
+ }
+ /* Perform the necessary work for death times. */
+ if (allocType.EQ(TRACE_EXACT_ALLOC)) {
+ if (MERLIN_ANALYSIS) {
+ lastGC = VM.traceInterface.getOID(ref);
+ VM.traceInterface.updateTime(lastGC);
+ VM.collection.triggerCollection(Collection.INTERNAL_GC_TRIGGER);
+ } else {
+ VM.collection.triggerCollection(Collection.RESOURCE_GC_TRIGGER);
+ lastGC = VM.traceInterface.getOID(ref);
+ }
+ }
+ /* Add the allocation record to the buffer if we have not yet done so. */
+ if (!MERLIN_ANALYSIS) {
+ Address fp = (TraceBuffer.OMIT_ALLOCS) ? Address.zero() : VM.traceInterface.skipOwnFramesAndDump(typeRef);
+ if (isImmortal && allocType.EQ(TRACE_EXACT_ALLOC))
+ trace.push(TRACE_EXACT_IMMORTAL_ALLOC);
+ else if (isImmortal)
+ trace.push(TRACE_IMMORTAL_ALLOC);
+ else
+ trace.push(allocType);
+ trace.push(VM.traceInterface.getOID(ref));
+ trace.push(Word.fromIntZeroExtend(bytes - VM.traceInterface.getHeaderSize()));
+ trace.push(fp.toWord());
+ trace.push(Word.zero()); /* Magic.getThreadId() */
+ trace.push(TRACE_TIB_SET);
+ trace.push(VM.traceInterface.getOID(ref));
+ trace.push(VM.traceInterface.getOID(typeRef));
+ }
+ trace.process();
+ traceBusy = false;
+ }
+
+ /***********************************************************************
+ *
+ * Merlin lifetime analysis methods
+ */
+
+ /**
+ * This computes and adds to the trace buffer the unreachable time for
+ * all of the objects that are _provably_ unreachable. This method
+ * should be called after garbage collection (but before the space has
+ * been reclaimed) and at program termination.
+ */
+ private static void findDeaths() {
+ /* Only the merlin analysis needs to compute death times */
+ if (MERLIN_ANALYSIS) {
+ /* Start with an empty stack. */
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(worklist.isEmpty());
+ /* Scan the linked list of objects within each region */
+ for (int allocator = 0; allocator < ALLOCATORS; allocator++) {
+ ObjectReference thisRef = objectLinks.get(allocator);
+ /* Start at the top of each linked list */
+ while (!thisRef.isNull()) {
+ /* Add the unreachable objects onto the worklist. */
+ if (!getTraceLocal().isReachable(thisRef))
+ worklist.push(thisRef);
+ thisRef = VM.traceInterface.getLink(thisRef);
+ }
+ }
+ /* Sort the objects on the worklist by their timestamp */
+ if (!worklist.isEmpty())
+ worklist.sort();
+ /* Now compute the death times. */
+ computeTransitiveClosure();
+ }
+ /* Output the death times for each object */
+ for (int allocator = 0; allocator < ALLOCATORS; allocator++) {
+ ObjectReference thisRef = objectLinks.get(allocator);
+ ObjectReference prevRef = ObjectReference.nullReference(); // the last live object seen
+ while (!thisRef.isNull()) {
+ ObjectReference nextRef = VM.traceInterface.getLink(thisRef);
+ /* Maintain reachable objects on the linked list of allocated objects */
+ if (getTraceLocal().isReachable(thisRef)) {
+ thisRef = getTraceLocal().getForwardedReference(thisRef);
+ VM.traceInterface.setLink(thisRef, prevRef);
+ prevRef = thisRef;
+ } else {
+ /* For brute force lifetime analysis, objects become
+ unreachable "now" */
+ Word deadTime;
+ if (MERLIN_ANALYSIS)
+ deadTime = VM.traceInterface.getDeathTime(thisRef);
+ else
+ deadTime = lastGC;
+ /* Add the death record to the trace for unreachable objects. */
+ trace.push(TRACE_DEATH);
+ trace.push(VM.traceInterface.getOID(thisRef));
+ trace.push(deadTime);
+ }
+ thisRef = nextRef;
+ }
+ /* Purge the list of unreachable objects... */
+ objectLinks.set(allocator, prevRef);
+ }
+ }
+
+ /**
+ * This method is called for each root-referenced object at every Merlin
+ * root enumeration. The method will update the death time of the parameter
+ * to the current trace time.
+ *
+ * @param obj The root-referenced object
+ */
+ public static void rootEnumerate(ObjectReference obj) {
+ VM.traceInterface.updateDeathTime(obj);
+ }
+
+ /**
+ * This propagates the death time being computed to the object passed as an
+ * address. If we find the unreachable time for the parameter, it will be
+ * pushed on to the processing stack.
+ *
+ * @param ref The address of the object to examine
+ */
+ public static void propagateDeathTime(ObjectReference ref) {
+ /* If this death time is more accurate, set it. */
+ if (VM.traceInterface.getDeathTime(ref).LT(agePropagate)) {
+ /* If we should add the object for further processing. */
+ if (!getTraceLocal().isReachable(ref)) {
+ VM.traceInterface.setDeathTime(ref, agePropagate);
+ worklist.push(ref);
+ } else {
+ VM.traceInterface.setDeathTime(getTraceLocal().getForwardedReference(ref), agePropagate);
+ }
+ }
+ }
+
+ /**
+ * This finds all object death times by computing the (limited)
+ * transitive closure of the dead objects. Death times are computed
+ * as the latest reaching death time to an object.
+ */
+ private static void computeTransitiveClosure() {
+ if (!worklist.isEmpty()) {
+ /* The latest time an object can die. */
+ agePropagate = Word.max();
+ /* Process through the entire buffer. */
+ ObjectReference ref = worklist.pop();
+ while (!ref.isNull()) {
+ Word currentAge = VM.traceInterface.getDeathTime(ref);
+ /* This is a cheap and simple test to process objects only once. */
+ if (currentAge.LE(agePropagate)) {
+ /* Set the "new" dead age. */
+ agePropagate = currentAge;
+ /* Scan the object, pushing the survivors */
+ VM.scanning.scanObject(getTraceLocal(), ref);
+ }
+ /* Get the next object to process */
+ ref = worklist.pop();
+ }
+ }
+ }
+
+ private static TraceLocal getTraceLocal() {
+ return VM.activePlan.collector().getCurrentTrace();
+ }
+
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/TracingConstants.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/TracingConstants.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/TracingConstants.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/TracingConstants.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.utility;
+
+import org.vmmagic.unboxed.*;
+
+/**
+ * The constants needed when storing events and then generating the trace.
+ */
+public interface TracingConstants {
+ Word TRACE_EXACT_ALLOC = Word.zero();
+ Word TRACE_BOOT_ALLOC = Word.one().lsh(0);
+ Word TRACE_ALLOC = Word.one().lsh(1);
+ Word TRACE_DEATH = Word.one().lsh(2);
+ Word TRACE_FIELD_SET = Word.one().lsh(3);
+ Word TRACE_ARRAY_SET = Word.one().lsh(4);
+ Word TRACE_TIB_SET = Word.one().lsh(5);
+ Word TRACE_STATIC_SET = Word.one().lsh(6);
+ Word TRACE_BOOTSTART = Word.one().lsh(7);
+ Word TRACE_BOOTEND = Word.one().lsh(8);
+ Word TRACE_GCSTART = Word.one().lsh(9);
+ Word TRACE_GCEND = Word.one().lsh(10);
+ Word TRACE_GCROOT = Word.one().lsh(11);
+ Word TRACE_GCBAR = Word.one().lsh(12);
+ Word TRACE_THREAD_SWITCH = Word.one().lsh(13);
+ Word TRACE_STACKDELTA = Word.one().lsh(14);
+ Word TRACE_ROOTPTR = Word.one().lsh(15);
+ Word TRACE_EXACT_IMMORTAL_ALLOC = Word.one().lsh(16);
+ Word TRACE_IMMORTAL_ALLOC = Word.one().lsh(17);
+}
+
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/Treadmill.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/Treadmill.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/Treadmill.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/Treadmill.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,187 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility;
+
+import org.mmtk.utility.gcspy.drivers.TreadmillDriver;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * FIXME The DoublyLinkedList class, upon which this depends, must be
+ * re-written as it makes the assumption that the implementation
+ * language (Java) and the language being implemented are the same.
+ * This is true in the case of Jikes RVM, but it is not true for any
+ * VM implementing a language other than Java.
+ *
+ * Each instance of this class is a doubly-linked list, in which
+ * each item or node is a piece of memory. The first two words of each node
+ * contains the forward and backward links. The third word contains
+ * the treadmill. The remaining portion is the payload.
+ *
+ * The treadmill object itself must not be moved.
+ *
+ * Access to the instances may be synchronized depending on the constructor argument.
+ */
+ at Uninterruptible
+public final class Treadmill implements Constants {
+
+ /****************************************************************************
+ *
+ * Instance variables
+ */
+ private DoublyLinkedList fromSpace;
+ private DoublyLinkedList toSpace;
+ private DoublyLinkedList collectNursery;
+ private DoublyLinkedList allocNursery;
+
+ /****************************************************************************
+ *
+ * Initialization
+ */
+
+ /**
+ * Constructor
+ */
+ public Treadmill(int granularity, boolean shared) {
+ fromSpace = new DoublyLinkedList(granularity, shared);
+ toSpace = new DoublyLinkedList(granularity, shared);
+ allocNursery = new DoublyLinkedList(granularity, shared);
+ collectNursery = new DoublyLinkedList(granularity, shared);
+ }
+
+ /**
+ * Add a node to the treadmill. This is usually performed on allocation.
+ */
+ @Inline
+ public void addToTreadmill(Address node, boolean nursery) {
+ if (nursery)
+ allocNursery.add(node);
+ else
+ toSpace.add(node);
+ }
+
+ /**
+ * Remove a node from the nursery list.
+ */
+ @Inline
+ public Address popNursery() {
+ return collectNursery.pop();
+ }
+
+ /**
+ * Remove a node from the mature list.
+ */
+ @Inline
+ public Address pop() {
+ return fromSpace.pop();
+ }
+
+ /**
+ * Copy a node (during gc tracing).
+ */
+ @Inline
+ public void copy(Address node, boolean isInNursery) {
+ if (isInNursery) {
+ collectNursery.remove(node);
+ } else {
+ fromSpace.remove(node);
+ }
+ toSpace.add(node);
+ }
+
+ /**
+ * Is the to-space empty?
+ */
+ @Inline
+ public boolean toSpaceEmpty() {
+ return toSpace.isEmpty();
+ }
+
+ /**
+ * Is the from-space empty?
+ */
+ @Inline
+ public boolean fromSpaceEmpty() {
+ return fromSpace.isEmpty();
+ }
+
+ /**
+ * Is the nursery empty?
+ */
+ @Inline
+ public boolean nurseryEmpty() {
+ return collectNursery.isEmpty();
+ }
+
+ /**
+ * Flip the roles of the spaces in preparation for a collection.
+ */
+ public void flip(boolean fullHeap) {
+ DoublyLinkedList tmp = allocNursery;
+ allocNursery = collectNursery;
+ collectNursery = tmp;
+ if (fullHeap) {
+ tmp = fromSpace;
+ fromSpace = toSpace;
+ toSpace = tmp;
+ }
+ }
+
+ /****************************************************************************
+ *
+ * Misc header manipulation
+ */
+
+ @Inline
+ public static int headerSize() {
+ return DoublyLinkedList.headerSize();
+ }
+
+ @Inline
+ public static Address nodeToPayload(Address payload) {
+ return DoublyLinkedList.nodeToPayload(payload);
+ }
+
+ @Inline
+ public static Address midPayloadToNode(Address payload) {
+ return DoublyLinkedList.midPayloadToNode(payload);
+ }
+
+ /****************************************************************************
+ *
+ * GCSpy
+ */
+
+ /**
+ * Gather data for GCSpy from the nursery
+ * @param event the gc event
+ * @param tmDriver the GCSpy space driver
+ */
+ public void gcspyGatherData(int event, TreadmillDriver tmDriver) {
+ this.allocNursery.gcspyGatherData(tmDriver);
+ }
+
+ /**
+ * Gather data for GCSpy
+ * @param event the gc event
+ * @param tmDriver the GCSpy space driver
+ * @param tospace gather from tospace?
+ */
+ public void gcspyGatherData(int event, TreadmillDriver tmDriver, boolean tospace) {
+ if (tospace)
+ toSpace.gcspyGatherData(tmDriver);
+ else
+ fromSpace.gcspyGatherData(tmDriver);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/Allocator.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/Allocator.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/Allocator.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/Allocator.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,263 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.alloc;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.*;
+import org.mmtk.utility.statistics.*;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This abstract base class provides the basis for processor-local
+ * allocation. The key functionality provided is the retry mechanism
+ * that is necessary to correctly handle the fact that a "slow-path"
+ * allocation can cause a GC which violate the uninterruptability assumption.
+ * This results in the thread being moved to a different processor so that
+ * the allocator object it is using is not actually the one for the processor
+ * it is running on.
+ *
+ * This class also includes functionality to assist allocators with
+ * ensuring that requests are aligned according to requests.
+ *
+ * Failing to handle this properly will lead to very hard to trace bugs
+ * where the allocation that caused a GC or allocations immediately following
+ * GC are run incorrectly.
+ */
+ at Uninterruptible public abstract class Allocator implements Constants {
+
+ /**
+ * Return the space this allocator is currently bound to.
+ *
+ * @return The Space.
+ */
+ protected abstract Space getSpace();
+
+ /**
+ * Aligns up an allocation request. The allocation request accepts a
+ * region, that must be at least particle aligned, an alignment
+ * request (some power of two number of particles) and an offset (a
+ * number of particles). There is also a knownAlignment parameter to
+ * allow a more optimised check when the particular allocator in use
+ * always aligns at a coarser grain than individual particles, such
+ * as some free lists.
+ *
+ * @param region The region to align up.
+ * @param alignment The requested alignment
+ * @param offset The offset from the alignment
+ * @param knownAlignment The statically known minimum alignment.
+ * @return The aligned up address.
+ */
+ @Inline
+ public static Address alignAllocation(Address region, int alignment, int offset, int knownAlignment, boolean fillAlignmentGap) {
+ if (VM.VERIFY_ASSERTIONS) {
+ VM.assertions._assert(knownAlignment >= MIN_ALIGNMENT);
+ VM.assertions._assert(MIN_ALIGNMENT >= BYTES_IN_INT);
+ VM.assertions._assert(!(fillAlignmentGap && region.isZero()));
+ VM.assertions._assert(alignment <= MAX_ALIGNMENT);
+ VM.assertions._assert(offset >= 0);
+ VM.assertions._assert(region.toWord().and(Word.fromIntSignExtend(MIN_ALIGNMENT-1)).isZero());
+ VM.assertions._assert((alignment & (MIN_ALIGNMENT - 1)) == 0);
+ VM.assertions._assert((offset & (MIN_ALIGNMENT - 1)) == 0);
+ }
+
+ // No alignment ever required.
+ if (alignment <= knownAlignment || MAX_ALIGNMENT <= MIN_ALIGNMENT)
+ return region;
+
+ // May require an alignment
+ Word mask = Word.fromIntSignExtend(alignment - 1);
+ Word negOff = Word.fromIntSignExtend(-offset);
+ Offset delta = negOff.minus(region.toWord()).and(mask).toOffset();
+
+ if (fillAlignmentGap && ALIGNMENT_VALUE != 0) {
+ if ((MAX_ALIGNMENT - MIN_ALIGNMENT) == BYTES_IN_WORD) {
+ // At most a single hole
+ if (delta.toInt() == (BYTES_IN_WORD)) {
+ region.store(Word.fromIntSignExtend(ALIGNMENT_VALUE));
+ region = region.plus(delta);
+ return region;
+ }
+ } else {
+ while (delta.toInt() >= (BYTES_IN_WORD)) {
+ region.store(Word.fromIntSignExtend(ALIGNMENT_VALUE));
+ region = region.plus(BYTES_IN_WORD);
+ delta = delta.minus(BYTES_IN_WORD);
+ }
+ }
+ }
+
+ return region.plus(delta);
+ }
+
+ /**
+ * Fill the specified region with the alignment value.
+ *
+ * @param start The start of the region.
+ * @param end A pointer past the end of the region.
+ */
+ @Inline
+ public static void fillAlignmentGap(Address start, Address end) {
+ if ((MAX_ALIGNMENT - MIN_ALIGNMENT) == BYTES_IN_INT) {
+ // At most a single hole
+ if (!end.diff(start).isZero()) {
+ start.store(ALIGNMENT_VALUE);
+ }
+ } else {
+ while (start.LT(end)) {
+ start.store(ALIGNMENT_VALUE);
+ start = start.plus(BYTES_IN_INT);
+ }
+ }
+ }
+
+ /**
+ * Aligns up an allocation request. The allocation request accepts a
+ * region, that must be at least particle aligned, an alignment
+ * request (some power of two number of particles) and an offset (a
+ * number of particles).
+ *
+ * @param region The region to align up.
+ * @param alignment The requested alignment
+ * @param offset The offset from the alignment
+ * @return The aligned up address.
+ */
+ @Inline
+ public static Address alignAllocation(Address region, int alignment, int offset) {
+ return alignAllocation(region, alignment, offset, MIN_ALIGNMENT, true);
+ }
+
+ /**
+ * Aligns up an allocation request. The allocation request accepts a
+ * region, that must be at least particle aligned, an alignment
+ * request (some power of two number of particles) and an offset (a
+ * number of particles).
+ *
+ * @param region The region to align up.
+ * @param alignment The requested alignment
+ * @param offset The offset from the alignment
+ * @return The aligned up address.
+ */
+ @Inline
+ public static Address alignAllocationNoFill(Address region, int alignment, int offset) {
+ return alignAllocation(region, alignment, offset, MIN_ALIGNMENT, false);
+ }
+
+ /**
+ * This method calculates the minimum size that will guarantee the allocation
+ * of a specified number of bytes at the specified alignment.
+ *
+ * @param size The number of bytes (not aligned).
+ * @param alignment The requested alignment (some factor of 2).
+ */
+ @Inline
+ public static int getMaximumAlignedSize(int size, int alignment) {
+ return getMaximumAlignedSize(size, alignment, MIN_ALIGNMENT);
+ }
+
+ /**
+ * This method calculates the minimum size that will guarantee the allocation
+ * of a specified number of bytes at the specified alignment.
+ *
+ * @param size The number of bytes (not aligned).
+ * @param alignment The requested alignment (some factor of 2).
+ * @param knownAlignment The known minimum alignment. Specifically for use in
+ * allocators that enforce greater than particle alignment. It is a <b>precondition</b>
+ * that size is aligned to knownAlignment, and that knownAlignment >= MIN_ALGINMENT.
+ */
+ @Inline
+ public static int getMaximumAlignedSize(int size, int alignment, int knownAlignment) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(size == Conversions.roundDown(size, knownAlignment));
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(knownAlignment >= MIN_ALIGNMENT);
+
+ if (MAX_ALIGNMENT <= MIN_ALIGNMENT || alignment <= knownAlignment) {
+ return size;
+ } else {
+ return size + alignment - knownAlignment;
+ }
+ }
+
+ /**
+ * Single slow path allocation attempt. This is called by allocSlow.
+ *
+ * @param bytes The size of the allocation request
+ * @param alignment The required alignment
+ * @param offset The alignment offset
+ * @return The start address of the region, or zero if allocation fails
+ */
+ protected abstract Address allocSlowOnce(int bytes, int alignment, int offset);
+
+ /**
+ * <b>Out-of-line</b> slow path allocation. This method forces slow path
+ * allocation to be out of line (typically desirable, but not when the
+ * calling context is already explicitly out-of-line).
+ *
+ * @param bytes The size of the allocation request
+ * @param alignment The required alignment
+ * @param offset The alignment offset
+ * @return The start address of the region, or zero if allocation fails
+ */
+ @NoInline
+ public final Address allocSlow(int bytes, int alignment, int offset) {
+ return allocSlowInline(bytes, alignment, offset);
+ }
+
+ /**
+ * <b>Inline</b> slow path allocation. This method attempts allocSlowOnce
+ * several times, and allows collection to occur, and ensures that execution
+ * safely resumes by taking care of potential thread/mutator context affinity
+ * changes. All allocators should use this as the trampoline for slow
+ * path allocation.
+ *
+ * @param bytes The size of the allocation request
+ * @param alignment The required alignment
+ * @param offset The alignment offset
+ * @return The start address of the region, or zero if allocation fails
+ */
+ @Inline
+ public final Address allocSlowInline(int bytes, int alignment, int offset) {
+ int gcCountStart = Stats.gcCount();
+ Allocator current = this;
+ Space space = current.getSpace();
+ for (int i = 0; i < Plan.MAX_COLLECTION_ATTEMPTS; i++) {
+ Address result = current.allocSlowOnce(bytes, alignment, offset);
+ if (!result.isZero()) {
+ return result;
+ }
+ if (!Plan.gcInProgress()) {
+ /* This is in case a GC occurs, and our mutator context is stale.
+ * In some VMs the scheduler can change the affinity between the
+ * current thread and the mutator context. This is possible for
+ * VMs that dynamically multiplex Java threads onto multiple mutator
+ * contexts, */
+ current = VM.activePlan.mutator().getAllocatorFromSpace(space);
+ }
+ }
+ Log.write("GC Error: Allocator.allocSlow failed on request of ");
+ Log.write(bytes);
+ Log.write(" on space ");
+ Log.writeln(space.getName());
+ Log.write("gcCountStart = ");
+ Log.writeln(gcCountStart);
+ Log.write("gcCount (now) = ");
+ Log.writeln(Stats.gcCount());
+ Space.printUsageMB();
+ VM.assertions.fail("Allocation Failed!");
+ /* NOTREACHED */
+ return Address.zero();
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/BlockAllocator.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/BlockAllocator.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/BlockAllocator.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/BlockAllocator.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.utility.alloc;
+
+import org.mmtk.policy.Space;
+import org.mmtk.utility.*;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements "block" data structures of various sizes.<p>
+ *
+ * Blocks are a non-shared (thread-local) coarse-grained unit of
+ * storage. Blocks are available in power-of-two sizes.
+ *
+ * Virtual memory space is taken from a VM resource, and pages
+ * consumed by blocks are accounted for by a memory resource.
+ */
+ at Uninterruptible
+public final class BlockAllocator implements Constants {
+ /****************************************************************************
+ *
+ * Class variables
+ */
+
+ // block freelist
+ public static final int LOG_MIN_BLOCK = 12; // 4K bytes
+ public static final int LOG_MAX_BLOCK = 15; // 32K bytes
+ public static final byte MAX_BLOCK_SIZE_CLASS = LOG_MAX_BLOCK - LOG_MIN_BLOCK;
+ public static final int BLOCK_SIZE_CLASSES = MAX_BLOCK_SIZE_CLASS + 1;
+
+ // metadata
+ private static final Offset NEXT_OFFSET = Offset.zero();
+ private static final Offset BMD_OFFSET = NEXT_OFFSET.plus(BYTES_IN_ADDRESS);
+ private static final Offset CSC_OFFSET = BMD_OFFSET.plus(1);
+ private static final Offset IU_OFFSET = CSC_OFFSET.plus(1);
+ private static final Offset FL_META_OFFSET = IU_OFFSET.plus(BYTES_IN_SHORT);
+ private static final byte BLOCK_SC_MASK = 0xf; // lower 4 bits
+ private static final int BLOCK_PAGE_OFFSET_SHIFT = 4; // higher 4 bits
+ private static final int MAX_BLOCK_PAGE_OFFSET = (1<<4)-1; // 4 bits
+ private static final int LOG_BYTES_IN_BLOCK_META = LOG_BYTES_IN_ADDRESS + 2;
+ private static final int LOG_BYTE_COVERAGE = LOG_MIN_BLOCK - LOG_BYTES_IN_BLOCK_META;
+
+ public static final int META_DATA_BYTES_PER_REGION = 1 << (EmbeddedMetaData.LOG_BYTES_IN_REGION - LOG_BYTE_COVERAGE);
+ public static final Extent META_DATA_EXTENT = Extent.fromIntSignExtend(META_DATA_BYTES_PER_REGION);
+
+ /****************************************************************************
+ *
+ * Allocation & freeing
+ */
+
+ /**
+ * Allocate a block, returning the address of the first usable byte
+ * in the block.
+ *
+ * @param blockSizeClass The size class for the block to be allocated.
+ * @return The address of the first usable byte in the block, or
+ * zero on failure.
+ */
+ public static Address alloc(Space space, int blockSizeClass) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((blockSizeClass >= 0) && (blockSizeClass <= MAX_BLOCK_SIZE_CLASS));
+ int pages = pagesForSizeClass(blockSizeClass);
+ Address result = space.acquire(pages);
+ if (!result.isZero()) {
+ setBlkSizeMetaData(result, (byte) blockSizeClass);
+ }
+ return result;
+ }
+
+ /**
+ * Free a block. If the block is a sub-page block and the page is
+ * not completely free, then the block is added to the free list.
+ * Otherwise the block is returned to the virtual memory resource.
+ *
+ * @param block The address of the block to be freed
+ */
+ public static void free(Space space, Address block) {
+ space.release(block);
+ }
+
+ /**
+ * Return the size in bytes of a block of a given size class
+ *
+ * @param blockSizeClass The size class in question
+ * @return The size in bytes of a block of this size class
+ */
+ @Inline
+ public static int blockSize(int blockSizeClass) {
+ return 1 << (LOG_MIN_BLOCK + blockSizeClass);
+ }
+
+ /**
+ * Return the number of pages required when allocating space for
+ * this size class.
+ *
+ * @param blockSizeClass The size class in question
+ * @return The number of pages required when allocating a block (or
+ * blocks) of this size class.
+ */
+ @Inline
+ private static int pagesForSizeClass(int blockSizeClass) {
+ return 1 << (LOG_MIN_BLOCK + blockSizeClass - LOG_BYTES_IN_PAGE);
+ }
+
+ /****************************************************************************
+ *
+ * Block meta-data manipulation
+ */
+
+ /**
+ * Set the <i>block size class</i> meta data field for a given
+ * address (all blocks on a given page are homogeneous with respect
+ * to block size class).
+ *
+ * @param block The address of interest
+ * @param sc The value to which this field is to be set
+ */
+ @Inline
+ private static void setBlkSizeMetaData(Address block, byte sc) {
+ if (VM.VERIFY_ASSERTIONS) {
+ VM.assertions._assert(block.EQ(Conversions.pageAlign(block)));
+ VM.assertions._assert(pagesForSizeClass(sc) - 1 <= MAX_BLOCK_PAGE_OFFSET);
+ }
+ Address address = block;
+ for (int i = 0; i < pagesForSizeClass(sc); i++) {
+ byte value = (byte) ((i << BLOCK_PAGE_OFFSET_SHIFT) | sc);
+ getMetaAddress(address).store(value, BMD_OFFSET);
+ if (VM.VERIFY_ASSERTIONS) {
+ VM.assertions._assert(getBlkStart(address).EQ(block));
+ VM.assertions._assert(getBlkSizeClass(address) == sc);
+ }
+ address = address.plus(1<<VM.LOG_BYTES_IN_PAGE);
+ }
+ }
+
+ /**
+ * Get the <i>block size class</i> meta data field for a given page
+ * (all blocks on a given page are homogeneous with respect to block
+ * size class).
+ *
+ * @param address The address of interest
+ * @return The size class field for the block containing the given address
+ */
+ @Inline
+ private static byte getBlkSizeClass(Address address) {
+ address = Conversions.pageAlign(address);
+ byte rtn = (byte) (getMetaAddress(address).loadByte(BMD_OFFSET) & BLOCK_SC_MASK);
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(rtn >= 0 && rtn <= MAX_BLOCK_SIZE_CLASS);
+ return rtn;
+ }
+
+ /**
+ * Get the <i>address of the start of a block size class</i> a given page
+ * within the block.
+ *
+ * @param address The address of interest
+ * @return The address of the block containing the address
+ */
+ @Inline
+ public static Address getBlkStart(Address address) {
+ address = Conversions.pageAlign(address);
+ byte offset = (byte) (getMetaAddress(address).loadByte(BMD_OFFSET) >>> BLOCK_PAGE_OFFSET_SHIFT);
+ return address.minus(offset<<LOG_BYTES_IN_PAGE);
+ }
+
+ /**
+ * Set the <i>client size class</i> meta data field for a given
+ * address (all blocks on a given page are homogeneous with respect
+ * to block size class).
+ *
+ * @param block The address of interest
+ * @param sc The value to which this field is to be set
+ */
+ @Inline
+ public static void setAllClientSizeClass(Address block, int blocksc, byte sc) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(block.EQ(Conversions.pageAlign(block)));
+ Address address = block;
+ for (int i = 0; i < pagesForSizeClass(blocksc); i++) {
+ getMetaAddress(address).store(sc, CSC_OFFSET);
+ address = address.plus(1<<VM.LOG_BYTES_IN_PAGE);
+ }
+ }
+
+ /**
+ * Get the <i>client size class</i> meta data field for a given page
+ * (all blocks on a given page are homogeneous with respect to block
+ * size class).
+ *
+ * @param address The address of interest
+ * @return The size class field for the block containing the given address
+ */
+ @Inline
+ public static byte getClientSizeClass(Address address) {
+ address = Conversions.pageAlign(address);
+ byte rtn = getMetaAddress(address).loadByte(CSC_OFFSET);
+ return rtn;
+ }
+
+ /**
+ * Set the free list meta data field for a given address (this is
+ * per-block meta data that is stored along with the block metadata
+ * but not used by the block allocator).
+ *
+ * @param address The address of interest
+ * @param value The value to which this field is to be set
+ */
+ @Inline
+ public static void setFreeListMeta(Address address, Address value) {
+ getMetaAddress(address).plus(FL_META_OFFSET).store(value);
+ }
+
+ /**
+ * Get the free list meta data field for a given address (this is
+ * per-block meta data that is stored along with the block metadata
+ * but not used by the block allocator).
+ *
+ * @param address The address of interest
+ * @return The free list meta data field for the block containing
+ * the given address
+ */
+ @Inline
+ public static Address getFreeListMeta(Address address) {
+ return getMetaAddress(address).plus(FL_META_OFFSET).loadAddress();
+ }
+
+ /**
+ * Set the <i>prev</i> meta data field for a given address
+ *
+ * @param address The address of interest
+ * @param prev The value to which this field is to be set
+ */
+ @Inline
+ public static void setNext(Address address, Address prev) {
+ getMetaAddress(address, NEXT_OFFSET).store(prev);
+ }
+
+ /**
+ * Get the <i>prev</i> meta data field for a given address
+ *
+ * @param address The address of interest
+ * @return The prev field for the block containing the given address
+ */
+ @Inline
+ public static Address getNext(Address address) {
+ return getMetaAddress(address, NEXT_OFFSET).loadAddress();
+ }
+
+ /**
+ * Get the address of some metadata given the address for which the
+ * metadata is required and the offset into the metadata that is of
+ * interest.
+ *
+ * @param address The address for which the metadata is required
+ * @return The address of the specified meta data
+ */
+ @Inline
+ private static Address getMetaAddress(Address address) {
+ return getMetaAddress(address, Offset.zero());
+ }
+
+ /**
+ * Get the address of some metadata given the address for which the
+ * metadata is required and the offset into the metadata that is of
+ * interest.
+ *
+ * @param address The address for which the metadata is required
+ * @param offset The offset (in bytes) into the metadata block (eg
+ * for the prev pointer, or next pointer)
+ * @return The address of the specified meta data
+ */
+ @Inline
+ private static Address getMetaAddress(Address address, Offset offset) {
+ return EmbeddedMetaData.getMetaDataBase(address).plus(
+ EmbeddedMetaData.getMetaDataOffset(address, LOG_BYTE_COVERAGE, LOG_BYTES_IN_BLOCK_META)).plus(offset);
+ }
+
+ /****************************************************************************
+ *
+ * Block marking
+ */
+
+ /**
+ * Mark the metadata for this block.
+ *
+ * @param ref
+ */
+ @Inline
+ public static void markBlockMeta(ObjectReference ref) {
+ getMetaAddress(VM.objectModel.refToAddress(ref)).plus(FL_META_OFFSET).store(Word.one());
+ }
+
+ /**
+ * Mark the metadata for this block.
+ *
+ * @param block The block address
+ */
+ @Inline
+ public static void markBlockMeta(Address block) {
+ getMetaAddress(block).plus(FL_META_OFFSET).store(Word.one());
+ }
+
+ /**
+ * Return true if the metadata for this block was set.
+ *
+ * @param block The block address
+ * @return value of the meta data.
+ */
+ @Inline
+ public static boolean checkBlockMeta(Address block) {
+ return getMetaAddress(block).plus(FL_META_OFFSET).loadWord().EQ(Word.one());
+ }
+
+ /**
+ * Clear the metadata for this block
+ *
+ * @param block The block address
+ */
+ @Inline
+ public static void clearBlockMeta(Address block) {
+ getMetaAddress(block).plus(FL_META_OFFSET).store(Word.zero());
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/BumpPointer.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/BumpPointer.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/BumpPointer.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/BumpPointer.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,459 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.alloc;
+
+import org.mmtk.policy.Space;
+import org.mmtk.utility.*;
+import org.mmtk.utility.gcspy.drivers.LinearSpaceDriver;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements a bump pointer allocator that allows linearly
+ * scanning through the allocated objects. In order to achieve this in the
+ * face of parallelism it maintains a header at a region (1 or more blocks)
+ * granularity.
+ *
+ * Intra-block allocation is fast, requiring only a load, addition comparison
+ * and store. If a block boundary is encountered the allocator will
+ * request more memory (virtual and actual).
+ *
+ * In the current implementation the scanned objects maintain affinity
+ * with the thread that allocated the objects in the region. In the future
+ * it is anticipated that subclasses should be allowed to choose to improve
+ * load balancing during the parallel scan.
+ *
+ * Each region is laid out as follows:
+ *
+ * +-------------+-------------+-------------+---------------
+ * | Region End | Next Region | Data End | Data -->
+ * +-------------+-------------+-------------+---------------
+ *
+ * The minimum region size is 32768 bytes, so the 3 or 4 word overhead is
+ * less than 0.05% of all space.
+ *
+ * An intended enhancement is to facilitate a reallocation operation
+ * where a second cursor is maintained over earlier regions (and at the
+ * limit a lower location in the same region). This would be accompianied
+ * with an alternative slow path that would allow reuse of empty regions.
+ *
+ * This class relies on the supporting virtual machine implementing the
+ * getNextObject and related operations.
+ */
+ at Uninterruptible public class BumpPointer extends Allocator
+ implements Constants {
+
+ /****************************************************************************
+ *
+ * Class variables
+ */
+
+ // Block size defines slow path periodicity.
+ private static final int LOG_DEFAULT_STEP_SIZE = 30; // 1G: let the external slow path dominate
+ private static final int STEP_SIZE = 1<<(SUPPORT_CARD_SCANNING ? LOG_CARD_BYTES : LOG_DEFAULT_STEP_SIZE);
+ protected static final int LOG_BLOCK_SIZE = LOG_BYTES_IN_PAGE + 3;
+ protected static final Word BLOCK_MASK = Word.one().lsh(LOG_BLOCK_SIZE).minus(Word.one());
+
+ // Offsets into header
+ protected static final Offset REGION_LIMIT_OFFSET = Offset.zero();
+ protected static final Offset NEXT_REGION_OFFSET = REGION_LIMIT_OFFSET.plus(BYTES_IN_ADDRESS);
+ protected static final Offset DATA_END_OFFSET = NEXT_REGION_OFFSET.plus(BYTES_IN_ADDRESS);
+
+ // Data must start particle-aligned.
+ protected static final Offset DATA_START_OFFSET = alignAllocationNoFill(
+ Address.zero().plus(DATA_END_OFFSET.plus(BYTES_IN_ADDRESS)),
+ MIN_ALIGNMENT, 0).toWord().toOffset();
+ protected static final Offset MAX_DATA_START_OFFSET = alignAllocationNoFill(
+ Address.zero().plus(DATA_END_OFFSET.plus(BYTES_IN_ADDRESS)),
+ MAX_ALIGNMENT, 0).toWord().toOffset();
+
+ /****************************************************************************
+ *
+ * Instance variables
+ */
+ protected Address cursor; // insertion point
+ private Address internalLimit; // current internal slow-path sentinal for bump pointer
+ private Address limit; // current external slow-path sentinal for bump pointer
+ protected Space space; // space this bump pointer is associated with
+ protected Address initialRegion; // first contiguous region
+ protected final boolean allowScanning; // linear scanning is permitted if true
+ protected Address region; // current contiguous region
+
+
+ /**
+ * Constructor.
+ *
+ * @param space The space to bump point into.
+ * @param allowScanning Allow linear scanning of this region of memory.
+ */
+ protected BumpPointer(Space space, boolean allowScanning) {
+ this.space = space;
+ this.allowScanning = allowScanning;
+ reset();
+ }
+
+ /**
+ * Reset the allocator. Note that this does not reset the space.
+ * This is must be done by the caller.
+ */
+ public final void reset() {
+ cursor = Address.zero();
+ limit = Address.zero();
+ internalLimit = Address.zero();
+ initialRegion = Address.zero();
+ region = Address.zero();
+ }
+
+ /**
+ * Re-associate this bump pointer with a different space. Also
+ * reset the bump pointer so that it will use the new space
+ * on the next call to <code>alloc</code>.
+ *
+ * @param space The space to associate the bump pointer with.
+ */
+ public final void rebind(Space space) {
+ reset();
+ this.space = space;
+ }
+
+ /**
+ * Allocate space for a new object. This is frequently executed code and
+ * the coding is deliberaetly sensitive to the optimizing compiler.
+ * After changing this, always check the IR/MC that is generated.
+ *
+ * @param bytes The number of bytes allocated
+ * @param align The requested alignment
+ * @param offset The offset from the alignment
+ * @return The address of the first byte of the allocated region
+ */
+ @Inline
+ public final Address alloc(int bytes, int align, int offset) {
+ Address start = alignAllocationNoFill(cursor, align, offset);
+ Address end = start.plus(bytes);
+ if (end.GT(internalLimit))
+ return allocSlow(start, end, align, offset);
+ fillAlignmentGap(cursor, start);
+ cursor = end;
+ return start;
+ }
+
+ /**
+ * Internal allocation slow path. This is called whenever the bump
+ * pointer reaches the internal limit. The code is forced out of
+ * line. If required we perform an external slow path take, which
+ * we inline into this method since this is already out of line.
+ *
+ * @param start The start address for the pending allocation
+ * @param end The end address for the pending allocation
+ * @param align The requested alignment
+ * @param offset The offset from the alignment
+ * @return The address of the first byte of the allocated region
+ */
+ @NoInline
+ private Address allocSlow(Address start, Address end, int align,
+ int offset) {
+ Address rtn = null;
+ Address card = null;
+ if (SUPPORT_CARD_SCANNING)
+ card = getCard(start.plus(CARD_MASK)); // round up
+ if (end.GT(limit)) { /* external slow path */
+ rtn = allocSlowInline(end.diff(start).toInt(), align, offset);
+ if (SUPPORT_CARD_SCANNING && card.NE(getCard(rtn.plus(CARD_MASK))))
+ card = getCard(rtn); // round down
+ } else { /* internal slow path */
+ while (internalLimit.LE(end))
+ internalLimit = internalLimit.plus(STEP_SIZE);
+ if (internalLimit.GT(limit))
+ internalLimit = limit;
+ fillAlignmentGap(cursor, start);
+ cursor = end;
+ rtn = start;
+ }
+ if (SUPPORT_CARD_SCANNING && !rtn.isZero())
+ createCardAnchor(card, rtn, end.diff(start).toInt());
+ return rtn;
+ }
+
+ /**
+ * Given an allocation which starts a new card, create a record of
+ * where the start of the object is relative to the start of the
+ * card.
+ *
+ * @param card An address that lies within the card to be marked
+ * @param start The address of an object which creates a new card.
+ * @param bytes The size of the pending allocation in bytes (used for debugging)
+ */
+ private void createCardAnchor(Address card, Address start, int bytes) {
+ if (VM.VERIFY_ASSERTIONS) {
+ VM.assertions._assert(allowScanning);
+ VM.assertions._assert(card.EQ(getCard(card)));
+ VM.assertions._assert(start.diff(card).sLE(MAX_DATA_START_OFFSET));
+ VM.assertions._assert(start.diff(card).toInt() >= -CARD_MASK);
+ }
+ while (bytes > 0) {
+ int offset = start.diff(card).toInt();
+ getCardMetaData(card).store(offset);
+ card = card.plus(1 << LOG_CARD_BYTES);
+ bytes -= (1 << LOG_CARD_BYTES);
+ }
+ }
+
+ /**
+ * Return the start of the card corresponding to a given address.
+ *
+ * @param address The address for which the card start is required
+ * @return The start of the card containing the address
+ */
+ private static Address getCard(Address address) {
+ return address.toWord().and(Word.fromIntSignExtend(CARD_MASK).not()).toAddress();
+ }
+
+ /**
+ * Return the address of the metadata for a card, given the address of the card.
+ * @param card The address of some card
+ * @return The address of the metadata associated with that card
+ */
+ private static Address getCardMetaData(Address card) {
+ Address metadata = EmbeddedMetaData.getMetaDataBase(card);
+ return metadata.plus(EmbeddedMetaData.getMetaDataOffset(card, LOG_CARD_BYTES-LOG_CARD_META_SIZE, LOG_CARD_META_SIZE));
+ }
+
+ /**
+ * External allocation slow path (called by superclass when slow path is
+ * actually taken. This is necessary (rather than a direct call
+ * from the fast path) because of the possibility of a thread switch
+ * and corresponding re-association of bump pointers to kernel
+ * threads.
+ *
+ * @param bytes The number of bytes allocated
+ * @param offset The offset from the alignment
+ * @param align The requested alignment
+ * @return The address of the first byte of the allocated region or
+ * zero on failure
+ */
+ protected final Address allocSlowOnce(int bytes, int align, int offset) {
+ /* Check we have been bound to a space */
+ if (space == null) {
+ VM.assertions.fail("Allocation on unbound bump pointer.");
+ }
+
+ /* Check if we already have a block to use */
+ if (allowScanning && !region.isZero()) {
+ Address nextRegion = region.loadAddress(NEXT_REGION_OFFSET);
+ if (!nextRegion.isZero()) {
+ return consumeNextRegion(nextRegion, bytes, align, offset);
+ }
+ }
+
+ /* Acquire space, block aligned, that can accommodate the request */
+ Extent blockSize = Word.fromIntZeroExtend(bytes).plus(BLOCK_MASK)
+ .and(BLOCK_MASK.not()).toExtent();
+ Address start = space.acquire(Conversions.bytesToPages(blockSize));
+
+ if (start.isZero()) return start; // failed allocation
+
+ if (!allowScanning) { // simple allocator
+ if (start.NE(limit)) cursor = start; // discontiguous
+ updateLimit(start.plus(blockSize), start, bytes);
+ } else // scannable allocator
+ updateMetaData(start, blockSize, bytes);
+ return alloc(bytes, align, offset);
+ }
+
+ /**
+ * Update the limit pointer. As a side effect update the internal limit
+ * pointer appropriately.
+ *
+ * @param newLimit The new value for the limit pointer
+ * @param start The start of the region to be allocated into
+ * @param bytes The size of the pending allocation (if any).
+ */
+ @Inline
+ protected final void updateLimit(Address newLimit, Address start, int bytes) {
+ limit = newLimit;
+ internalLimit = start.plus(STEP_SIZE);
+ if (internalLimit.GT(limit))
+ internalLimit = limit;
+ else {
+ while (internalLimit.LT(cursor.plus(bytes)))
+ internalLimit = internalLimit.plus(STEP_SIZE);
+ if (VM.VERIFY_ASSERTIONS)
+ VM.assertions._assert(internalLimit.LE(limit));
+ }
+ }
+
+ /**
+ * A bump pointer chuck/region has been consumed but the contiguous region
+ * is available, so consume it and then return the address of the start
+ * of a memory region satisfying the outstanding allocation request. This
+ * is relevant when re-using memory, as in a mark-compact collector.
+ *
+ * @param nextRegion The region to be consumed
+ * @param bytes The number of bytes allocated
+ * @param align The requested alignment
+ * @param offset The offset from the alignment
+ * @return The address of the first byte of the allocated region or
+ * zero on failure
+ */
+ private Address consumeNextRegion(Address nextRegion, int bytes, int align,
+ int offset) {
+ region.plus(DATA_END_OFFSET).store(cursor);
+ region = nextRegion;
+ cursor = nextRegion.plus(DATA_START_OFFSET);
+ updateLimit(nextRegion.loadAddress(REGION_LIMIT_OFFSET), nextRegion, bytes);
+ nextRegion.store(Address.zero(), DATA_END_OFFSET);
+ VM.memory.zero(cursor, limit.diff(cursor).toWord().toExtent());
+ reusePages(Conversions.bytesToPages(limit.diff(region)));
+
+ return alloc(bytes, align, offset);
+ }
+
+ /**
+ * Update the metadata to reflect the addition of a new region.
+ *
+ * @param start The start of the new region
+ * @param size The size of the new region (rounded up to block-alignment)
+ */
+ @Inline
+ private void updateMetaData(Address start, Extent size, int bytes) {
+ if (initialRegion.isZero()) {
+ /* this is the first allocation */
+ initialRegion = start;
+ region = start;
+ cursor = region.plus(DATA_START_OFFSET);
+ } else if (limit.NE(start) ||
+ region.diff(start.plus(size)).toWord().toExtent().GT(maximumRegionSize())) {
+ /* non contiguous or over-size, initialize new region */
+ region.plus(NEXT_REGION_OFFSET).store(start);
+ region.plus(DATA_END_OFFSET).store(cursor);
+ region = start;
+ cursor = start.plus(DATA_START_OFFSET);
+ }
+ updateLimit(start.plus(size), start, bytes);
+ region.plus(REGION_LIMIT_OFFSET).store(limit);
+ }
+
+ /**
+ * Gather data for GCspy. <p>
+ * This method calls the drivers linear scanner to scan through
+ * the objects allocated by this bump pointer.
+ *
+ * @param driver The GCspy driver for this space.
+ */
+ public void gcspyGatherData(LinearSpaceDriver driver) {
+ //driver.setRange(space.getStart(), cursor);
+ driver.setRange(space.getStart(), limit);
+ this.linearScan(driver.getScanner());
+ }
+
+ /**
+ * Gather data for GCspy. <p>
+ * This method calls the drivers linear scanner to scan through
+ * the objects allocated by this bump pointer.
+ *
+ * @param driver The GCspy driver for this space.
+ * @param scanSpace The space to scan
+ */
+ public void gcspyGatherData(LinearSpaceDriver driver, Space scanSpace) {
+ //TODO can scanSpace ever be different to this.space?
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(scanSpace == space, "scanSpace != space");
+
+ //driver.setRange(scanSpace.getStart(), cursor);
+ Address start = scanSpace.getStart();
+ driver.setRange(start, limit);
+
+ if (false) {
+ Log.write("\nBumpPointer.gcspyGatherData set Range "); Log.write(scanSpace.getStart());
+ Log.write(" to "); Log.writeln(limit);
+ Log.write("BumpPointergcspyGatherData scan from "); Log.writeln(initialRegion);
+ }
+
+ linearScan(driver.getScanner());
+ }
+
+
+ /**
+ * Perform a linear scan through the objects allocated by this bump pointer.
+ *
+ * @param scanner The scan object to delegate scanning to.
+ */
+ @Inline
+ public final void linearScan(LinearScan scanner) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(allowScanning);
+ /* Has this allocator ever allocated anything? */
+ if (initialRegion.isZero()) return;
+
+ /* Loop through active regions or until the last region */
+ Address start = initialRegion;
+ while (!start.isZero()) {
+ scanRegion(scanner, start); // Scan this region
+ start = start.plus(NEXT_REGION_OFFSET).loadAddress(); // Move on to next
+ }
+ }
+
+ /**
+ * Perform a linear scan through a single contiguous region
+ *
+ * @param scanner The scan object to delegate to.
+ * @param start The start of this region
+ */
+ @Inline
+ private void scanRegion(LinearScan scanner, Address start) {
+ /* 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);
+ scanner.scan(current); // Scan this object.
+ current = 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) {
+ VM.assertions.fail("Subclasses that reuse regions must override this method.");
+ }
+
+ /**
+ * 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.max(); }
+
+ /** @return the current cursor value */
+ public final Address getCursor() { return cursor; }
+ /** @return the space associated with this bump pointer */
+ public final Space getSpace() { return space; }
+
+ /**
+ * Print out the status of the allocator (for debugging)
+ */
+ public final void show() {
+ Log.write("cursor = "); Log.write(cursor);
+ if (allowScanning) {
+ Log.write(" region = "); Log.write(region);
+ }
+ Log.write(" limit = "); Log.writeln(limit);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/DumpLinearScan.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/DumpLinearScan.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/DumpLinearScan.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/DumpLinearScan.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.utility.alloc;
+
+import org.mmtk.vm.VM;
+import org.mmtk.utility.Log;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * Simple linear scan to dump object information.
+ */
+ at Uninterruptible
+public final class DumpLinearScan extends LinearScan {
+ /**
+ * Scan an object.
+ *
+ * @param object The object to scan
+ */
+ @Inline
+ public void scan(ObjectReference object) {
+ Log.write("[");
+ Log.write(object.toAddress());
+ Log.write("], SIZE = ");
+ Log.writeln(VM.objectModel.getCurrentSize(object));
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/EmbeddedMetaData.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/EmbeddedMetaData.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/EmbeddedMetaData.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/EmbeddedMetaData.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,74 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.alloc;
+
+import org.mmtk.utility.Constants;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This plan implements constants and access methods for meta data
+ * that is embeded in allocation spaces (rather than kept on the
+ * side). The basic idea is that meta data be embeded at a very
+ * coarse power of two granularity for fast access, minimal wastage
+ * and by making the regions coarse, the contiguous meta-data will be
+ * relatively large and thus the probability of L1 conflict misses
+ * will be reduced (as compared with embedding meta-data at the start
+ * of each page which will cause those few cache lines corresponding
+ * to the start of each page to be heavily conflicted).
+ */
+ at Uninterruptible public final class EmbeddedMetaData implements Constants {
+
+ /* The (log of the) size of each region of meta data management */
+ public static final int LOG_BYTES_IN_REGION = 22;
+ public static final int BYTES_IN_REGION = 1 << LOG_BYTES_IN_REGION;
+ private static final Word REGION_MASK = Word.fromIntSignExtend(BYTES_IN_REGION - 1);
+ public static final int LOG_PAGES_IN_REGION = LOG_BYTES_IN_REGION - LOG_BYTES_IN_PAGE;
+ public static final int PAGES_IN_REGION = 1 << LOG_PAGES_IN_REGION;
+
+ /**
+ * Given an address, return the begining of the meta data for the
+ * region containing the address. This is a fast operation because
+ * it only involves masking out low order bits.
+ *
+ * @param address The address whose meta data is sought.
+ * @return The address of the start of the meta data for the meta
+ * region in which the address is located.
+ */
+ @Inline
+ public static Address getMetaDataBase(Address address) {
+ return address.toWord().and(REGION_MASK.not()).toAddress();
+ }
+
+ /**
+ * Given an address, the density (coverage) of a meta data type, and
+ * the granularity (alignment) of the meta data, return the offset
+ * into the meta data the address.
+ *
+ * @param address The address whose meta data offset is sought.
+ * @param logCoverage The log base two of the coverage of the meta
+ * data in question. For example, a value of 4 would indicate a
+ * coverage of 16; one metadata byte for every 16 bytes of data.
+ * @param logAlign The log base two of the aligment or granularity
+ * of the meta-data (it may be arranged in bytes, words, double
+ * words etc).
+ * @return The offset into the meta-data for this region, given the
+ * specified address and coverage and aligment requirements.
+ */
+ public static Extent getMetaDataOffset(Address address,
+ int logCoverage,
+ int logAlign) {
+ return address.toWord().and(REGION_MASK).rshl(logCoverage+logAlign).lsh(logAlign).toExtent();
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/ImmixAllocator.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/ImmixAllocator.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/ImmixAllocator.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/ImmixAllocator.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,331 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+
+package org.mmtk.utility.alloc;
+
+import org.mmtk.policy.Space;
+import org.mmtk.policy.immix.Block;
+import org.mmtk.policy.immix.Chunk;
+import org.mmtk.policy.immix.Line;
+import org.mmtk.policy.immix.ImmixSpace;
+import static org.mmtk.policy.immix.ImmixConstants.*;
+
+import org.mmtk.utility.Constants;
+import org.mmtk.utility.Log;
+import org.mmtk.utility.options.Options;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ *
+ */
+ at Uninterruptible
+public class ImmixAllocator extends Allocator implements Constants {
+
+ /****************************************************************************
+ *
+ * Instance variables
+ */
+ protected final ImmixSpace space; /* space this allocator is associated with */
+ private final boolean hot;
+ private final boolean copy;
+
+ private Address cursor; /* bump pointer */
+ private Address limit; /* limit for bump pointer */
+ private Address largeCursor; /* bump pointer for large objects */
+ private Address largeLimit; /* limit for bump pointer for large objects */
+ private boolean requestForLarge; /* is the current request for large or small? */
+ private boolean straddle; /* did the last allocation straddle a line? */
+ private int lineUseCount; /* approximation to bytes allocated (measured at 99% accurate) 07/10/30 */
+ private Address markTable;
+ private Address recyclableBlock;
+ private int line;
+ private boolean recyclableExhausted;
+
+ /**
+ * Constructor.
+ *
+ * @param space The space to bump point into.
+ * @param hot TODO
+ * @param copy TODO
+ */
+ public ImmixAllocator(ImmixSpace space, boolean hot, boolean copy) {
+ this.space = space;
+ this.hot = hot;
+ this.copy = copy;
+ reset();
+ }
+
+ /**
+ * Reset the allocator. Note that this does not reset the space.
+ */
+ public void reset() {
+ cursor = Address.zero();
+ limit = Address.zero();
+ largeCursor = Address.zero();
+ largeLimit = Address.zero();
+ markTable = Address.zero();
+ recyclableBlock = Address.zero();
+ requestForLarge = false;
+ recyclableExhausted = false;
+ line = LINES_IN_BLOCK;
+ lineUseCount = 0;
+ }
+
+ /*****************************************************************************
+ *
+ * Public interface
+ */
+
+ /**
+ * Allocate space for a new object. This is frequently executed code and
+ * the coding is deliberaetly sensitive to the optimizing compiler.
+ * After changing this, always check the IR/MC that is generated.
+ *
+ * @param bytes The number of bytes allocated
+ * @param align The requested alignment
+ * @param offset The offset from the alignment
+ * @return The address of the first byte of the allocated region
+ */
+ @Inline
+ public final Address alloc(int bytes, int align, int offset) {
+ /* establish how much we need */
+ Address start = alignAllocationNoFill(cursor, align, offset);
+ Address end = start.plus(bytes);
+
+ /* check whether we've exceeded the limit */
+ if (end.GT(limit)) {
+ if (bytes > BYTES_IN_LINE)
+ return overflowAlloc(bytes, align, offset);
+ else
+ return allocSlowHot(bytes, align, offset);
+ }
+
+ /* sufficient memory is available, so we can finish performing the allocation */
+ fillAlignmentGap(cursor, start);
+ cursor = end;
+
+ return start;
+ }
+
+ /**
+ * Allocate space for a new object. This is frequently executed code and
+ * the coding is deliberaetly sensitive to the optimizing compiler.
+ * After changing this, always check the IR/MC that is generated.
+ *
+ * @param bytes The number of bytes allocated
+ * @param align The requested alignment
+ * @param offset The offset from the alignment
+ * @return The address of the first byte of the allocated region
+ */
+ public final Address overflowAlloc(int bytes, int align, int offset) {
+ /* establish how much we need */
+ Address start = alignAllocationNoFill(largeCursor, align, offset);
+ Address end = start.plus(bytes);
+
+ /* check whether we've exceeded the limit */
+ if (end.GT(largeLimit)) {
+ requestForLarge = true;
+ Address rtn = allocSlowInline(bytes, align, offset);
+ requestForLarge = false;
+ return rtn;
+ }
+
+ /* sufficient memory is available, so we can finish performing the allocation */
+ fillAlignmentGap(largeCursor, start);
+ largeCursor = end;
+
+ return start;
+ }
+
+ @Inline
+ public final boolean getLastAllocLineStraddle() {
+ return straddle;
+ }
+
+ /**
+ * External allocation slow path (called by superclass when slow path is
+ * actually taken. This is necessary (rather than a direct call
+ * from the fast path) because of the possibility of a thread switch
+ * and corresponding re-association of bump pointers to kernel
+ * threads.
+ *
+ * @param bytes The number of bytes allocated
+ * @param align The requested alignment
+ * @param offset The offset from the alignment
+ * @return The address of the first byte of the allocated region or
+ * zero on failure
+ */
+ protected final Address allocSlowOnce(int bytes, int align, int offset) {
+ boolean success = false;
+ while (!success) {
+ Address ptr = space.getSpace(hot, copy, lineUseCount);
+
+ if (ptr.isZero()) {
+ lineUseCount = 0;
+ return ptr; // failed allocation --- we will need to GC
+ }
+
+ /* we have been given a clean block */
+ success = true;
+ lineUseCount = LINES_IN_BLOCK;
+ if (VM.VERIFY_ASSERTIONS)
+ VM.assertions._assert(Block.isAligned(ptr));
+ zeroBlock(ptr);
+ if (requestForLarge) {
+ largeCursor = ptr;
+ largeLimit = ptr.plus(BYTES_IN_BLOCK);
+ } else {
+ cursor = ptr;
+ limit = ptr.plus(BYTES_IN_BLOCK);
+ }
+ }
+ return alloc(bytes, align, offset);
+ }
+
+ /****************************************************************************
+ *
+ * Bump allocation
+ */
+
+ /**
+ * Internal allocation slow path. This is called whenever the bump
+ * pointer reaches the internal limit. The code is forced out of
+ * line. If required we perform an external slow path take, which
+ * we inline into this method since this is already out of line.
+ *
+ * @param bytes The number of bytes allocated
+ * @param align The requested alignment
+ * @param offset The offset from the alignment
+ * @return The address of the first byte of the allocated region
+ */
+ @NoInline
+ private Address allocSlowHot(int bytes, int align, int offset) {
+ if (acquireRecyclableLines(bytes, align, offset))
+ return alloc(bytes, align, offset);
+ else
+ return allocSlowInline(bytes, align, offset);
+ }
+
+ private boolean acquireRecyclableLines(int bytes, int align, int offset) {
+ while (line < LINES_IN_BLOCK || acquireRecyclableBlock()) {
+ line = space.getNextAvailableLine(markTable, line);
+ if (line < LINES_IN_BLOCK) {
+ int endLine = space.getNextUnavailableLine(markTable, line);
+ cursor = recyclableBlock.plus(Extent.fromIntSignExtend(line<<LOG_BYTES_IN_LINE));
+ limit = recyclableBlock.plus(Extent.fromIntSignExtend(endLine<<LOG_BYTES_IN_LINE));
+ if (SANITY_CHECK_LINE_MARKS) {
+ Address tmp = cursor;
+ while (tmp.LT(limit)) {
+ if (tmp.loadByte() != (byte) 0) {
+ Log.write("cursor: "); Log.writeln(cursor);
+ Log.write(" limit: "); Log.writeln(limit);
+ Log.write("current: "); Log.write(tmp);
+ Log.write(" value: "); Log.write(tmp.loadByte());
+ Log.write(" line: "); Log.write(line);
+ Log.write("endline: "); Log.write(endLine);
+ Log.write(" chunk: "); Log.write(Chunk.align(cursor));
+ Log.write(" hw: "); Log.write(Chunk.getHighWater(Chunk.align(cursor)));
+ Log.writeln(" values: ");
+ Address tmp2 = cursor;
+ while(tmp2.LT(limit)) { Log.write(tmp2.loadByte()); Log.write(" ");}
+ Log.writeln();
+ }
+ VM.assertions._assert(tmp.loadByte() == (byte) 0);
+ tmp = tmp.plus(1);
+ }
+ }
+ if (VM.VERIFY_ASSERTIONS && bytes <= BYTES_IN_LINE) {
+ Address start = alignAllocationNoFill(cursor, align, offset);
+ Address end = start.plus(bytes);
+ VM.assertions._assert(end.LE(limit));
+ }
+ VM.memory.zero(cursor, limit.diff(cursor).toWord().toExtent());
+ if (VM.VERIFY_ASSERTIONS && Options.verbose.getValue() >= 9) {
+ Log.write("Z["); Log.write(cursor); Log.write("->"); Log.write(limit); Log.writeln("]");
+ }
+
+ line = endLine;
+ if (VM.VERIFY_ASSERTIONS && copy) VM.assertions._assert(!Block.isDefragSource(cursor));
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean acquireRecyclableBlock() {
+ boolean rtn;
+ rtn = acquireRecyclableBlockAddressOrder();
+ if (rtn) {
+ markTable = Line.getBlockMarkTable(recyclableBlock);
+ line = 0;
+ }
+ return rtn;
+ }
+
+ @Inline
+ private boolean acquireRecyclableBlockAddressOrder() {
+ if (recyclableExhausted) {
+ if (VM.VERIFY_ASSERTIONS && Options.verbose.getValue() >= 9) {
+ Log.writeln("[no recyclable available]");
+ }
+ return false;
+ }
+ int markState = 0;
+ boolean usable = false;
+ while (!usable) {
+ Address next = recyclableBlock.plus(BYTES_IN_BLOCK);
+ if (recyclableBlock.isZero() || ImmixSpace.isRecycleAllocChunkAligned(next)) {
+ recyclableBlock = space.acquireReusableBlocks();
+ if (recyclableBlock.isZero()) {
+ recyclableExhausted = true;
+ if (VM.VERIFY_ASSERTIONS && Options.verbose.getValue() >= 9) {
+ Log.writeln("[recyclable exhausted]");
+ }
+ line = LINES_IN_BLOCK;
+ return false;
+ }
+ } else {
+ recyclableBlock = next;
+ }
+ markState = Block.getBlockMarkState(recyclableBlock);
+ usable = (markState > 0 && markState <= ImmixSpace.getReusuableMarkStateThreshold(copy));
+ if (copy && Block.isDefragSource(recyclableBlock))
+ usable = false;
+ }
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!Block.isUnused(recyclableBlock));
+ Block.setBlockAsReused(recyclableBlock);
+
+ lineUseCount += (LINES_IN_BLOCK-markState);
+ return true; // found something good
+ }
+
+ private void zeroBlock(Address block) {
+ // FIXME: efficiency check here!
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(block.toWord().and(Word.fromIntSignExtend(BYTES_IN_BLOCK-1)).isZero());
+ VM.memory.zero(block, Extent.fromIntZeroExtend(BYTES_IN_BLOCK));
+ }
+
+ /** @return the space associated with this squish allocator */
+ public final Space getSpace() { return space; }
+
+ /**
+ * Print out the status of the allocator (for debugging)
+ */
+ public final void show() {
+ Log.write("cursor = "); Log.write(cursor);
+ Log.write(" limit = "); Log.writeln(limit);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/LargeObjectAllocator.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/LargeObjectAllocator.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/LargeObjectAllocator.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/LargeObjectAllocator.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.utility.alloc;
+
+import org.mmtk.policy.BaseLargeObjectSpace;
+import org.mmtk.utility.Constants;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This abstract class implements core functionality for a generic
+ * large object allocator. 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. Subclasses may require finer grained
+ * synchronization during a marking phase, for example.<p>
+ *
+ * This is a first cut implementation, with plenty of room for
+ * improvement...
+ */
+ at Uninterruptible
+public abstract class LargeObjectAllocator extends Allocator implements Constants {
+
+ /****************************************************************************
+ *
+ * Instance variables
+ */
+ protected final BaseLargeObjectSpace space;
+
+ /****************************************************************************
+ *
+ * Initialization
+ */
+
+ /**
+ * Constructor
+ *
+ * @param space The space with which this large object allocator
+ * will be associated.
+ */
+ public LargeObjectAllocator(BaseLargeObjectSpace space) {
+ this.space = space;
+ }
+
+ /**
+ * Return the space this allocator is currently bound to.
+ *
+ * @return The Space.
+ */
+ protected final BaseLargeObjectSpace getSpace() {
+ return this.space;
+ }
+
+ /****************************************************************************
+ *
+ * Allocation
+ */
+
+ /**
+ * Allocate space for an object
+ *
+ * @param bytes The number of bytes allocated
+ * @param align The requested alignment.
+ * @param offset The alignment offset.
+ * @return The address of the first byte of the allocated cell Will
+ * not return zero.
+ */
+ @NoInline
+ public final Address alloc(int bytes, int align, int offset) {
+ Address cell = allocSlow(bytes, align, offset);
+ return alignAllocation(cell, align, offset);
+ }
+
+ /**
+ * Allocate a large object. Large objects are directly allocted and
+ * freed in page-grained units via the vm resource. This routine
+ * returned zeroed memory.
+ *
+ * @param bytes The required size of this space in bytes.
+ * @param offset The alignment offset.
+ * @param align The requested alignment.
+ * @return The address of the start of the newly allocated region at
+ * least <code>bytes</code> bytes in size.
+ */
+ protected final Address allocSlowOnce(int bytes, int align, int offset) {
+ int header = space.getHeaderSize();
+ int maxbytes = getMaximumAlignedSize(bytes + header, align);
+ int pages = (maxbytes + BYTES_IN_PAGE - 1) >> LOG_BYTES_IN_PAGE;
+ Address sp = space.acquire(pages);
+ if (sp.isZero()) return sp;
+ Address cell = sp.plus(header);
+ return cell;
+ }
+
+ /****************************************************************************
+ *
+ * Miscellaneous
+ */
+ public void show() {
+ }
+}
+
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/LinearScan.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/LinearScan.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/LinearScan.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/LinearScan.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.utility.alloc;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * Callbacks from BumpPointer during a linear scan are dispatched through
+ * a subclass of this object.
+ */
+ at Uninterruptible
+public abstract class LinearScan {
+ /**
+ * Scan an object.
+ *
+ * @param object The object to scan
+ */
+ public abstract void scan(ObjectReference object);
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/SegregatedFreeList.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/SegregatedFreeList.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/SegregatedFreeList.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/SegregatedFreeList.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,119 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.alloc;
+
+import org.mmtk.policy.SegregatedFreeListSpace;
+import org.mmtk.utility.*;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This abstract class implements the fast past for a segregated free list.
+ */
+ at Uninterruptible
+public abstract class SegregatedFreeList<S extends SegregatedFreeListSpace> extends Allocator implements Constants {
+
+ /****************************************************************************
+ *
+ * Instance variables
+ */
+
+ /** The space */
+ protected final S space;
+
+ /** The current free lists for the size classes */
+ protected final AddressArray freeList;
+
+ /****************************************************************************
+ *
+ * Initialization
+ */
+
+ /**
+ * Constructor
+ *
+ * @param space The space with which this allocator will be associated
+ */
+ public SegregatedFreeList(S space) {
+ this.space = space;
+ this.freeList = AddressArray.create(sizeClassCount());
+ }
+
+ /**
+ * Return the space this allocator is currently bound to.
+ *
+ * @return The Space.
+ */
+ protected final S getSpace() {
+ return this.space;
+ }
+
+ /****************************************************************************
+ *
+ * Allocation
+ */
+
+ /**
+ * Allocate <code>bytes</code> contiguous bytes of zeroed memory.<p>
+ *
+ * This code implements the fast path, and on failure delegates to the slow path.
+ *
+ * @param bytes The size of the object to occupy this space, in bytes.
+ * @param align The requested alignment.
+ * @param offset The alignment offset.
+ * @return The address of the first word or zero on failure
+ */
+ @Inline
+ public final Address alloc(int bytes, int align, int offset) {
+ int alignedBytes = getMaximumAlignedSize(bytes, align);
+ int sizeClass = getSizeClass(alignedBytes);
+ Address cell = freeList.get(sizeClass);
+ if (!cell.isZero()) {
+ freeList.set(sizeClass, cell.loadAddress());
+ /* Clear the free list link */
+ cell.store(Address.zero());
+ if (alignedBytes != bytes) {
+ /* Ensure aligned as requested. */
+ cell = alignAllocation(cell, align, offset);
+ }
+ return cell;
+ }
+ return allocSlow(bytes, align, offset);
+ }
+
+ /**
+ * The number of distinct size classes.
+ *
+ * NOTE: For optimal performance this call must be implemented in a way
+ * it can be inlined and optimized within the allocation sequence.
+ */
+ @Inline
+ private int sizeClassCount() {
+ return SegregatedFreeListSpace.sizeClassCount();
+ }
+
+ /**
+ * Get the size class for a given number of bytes.
+ *
+ * NOTE: For optimal performance this call must be implemented in a way
+ * it can be inlined and optimized within the allocation sequence.
+ *
+ * @param bytes The number of bytes required to accommodate the object
+ * @return The size class capable of accommodating the allocation request.
+ */
+ @Inline
+ private int getSizeClass(int bytes) {
+ return space.getSizeClass(bytes);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/SegregatedFreeListLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/SegregatedFreeListLocal.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/SegregatedFreeListLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/alloc/SegregatedFreeListLocal.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,162 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.alloc;
+
+import org.mmtk.policy.SegregatedFreeListSpace;
+import org.mmtk.utility.*;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This abstract class implements a simple segregated free list.<p>
+ *
+ * See: Wilson, Johnstone, Neely and Boles "Dynamic Storage
+ * Allocation: A Survey and Critical Review", IWMM 1995, for an
+ * overview of free list allocation and the various implementation
+ * strategies, including segregated free lists.<p>
+ *
+ * We maintain a number of size classes, each size class having a free
+ * list of available objects of that size (the list may be empty). We
+ * call the storage elements "cells". Cells reside within chunks of
+ * memory called "blocks". All cells in a given block are of the same
+ * size (i.e. blocks are homogeneous with respect to size class).
+ * Each block maintains its own free list (free cells within that
+ * block). For each size class a list of blocks is maintained, one of
+ * which will serve the role of the current free list. When the free
+ * list on the current block is exhausted, the next block for that
+ * size class becomes the current block and its free list is used. If
+ * there are no more blocks the a new block is allocated.<p>
+ */
+ at Uninterruptible
+public abstract class SegregatedFreeListLocal<S extends SegregatedFreeListSpace> extends SegregatedFreeList<S>
+ implements Constants {
+
+ /****************************************************************************
+ *
+ * Class variables
+ */
+
+ /****************************************************************************
+ *
+ * Instance variables
+ */
+ protected final AddressArray currentBlock;
+
+ /****************************************************************************
+ *
+ * Initialization
+ */
+
+ /**
+ * Constructor
+ *
+ * @param space The space with which this allocator will be associated
+ */
+ public SegregatedFreeListLocal(S space) {
+ super(space);
+ this.currentBlock = AddressArray.create(space.sizeClassCount());
+ }
+
+ /****************************************************************************
+ *
+ * Allocation
+ */
+
+ /**
+ * Allocate <code>bytes</code> contiguous bytes of non-zeroed
+ * memory. First check if the fast path works. This is needed
+ * since this method may be called in the context when the fast
+ * version was NOT just called. If this fails, it will try finding
+ * another block with a non-empty free list, or allocating a new
+ * block.<p>
+ *
+ * This code should be relatively infrequently executed, so it is
+ * forced out of line to reduce pressure on the compilation of the
+ * core alloc routine.<p>
+ *
+ * Precondition: None
+ *
+ * Postconditions: A new cell has been allocated (not zeroed), and
+ * the block containing the cell has been placed on the appropriate
+ * free list data structures. The free list itself is not updated
+ * (the caller must do so).<p>
+ *
+ * @param bytes The size of the object to occupy this space, in bytes.
+ * @param offset The alignment offset.
+ * @param align The requested alignment.
+ * @return The address of the first word or zero on failure.
+ */
+ @NoInline
+ public final Address allocSlowOnce(int bytes, int align, int offset) {
+ // Did a collection occur and provide a free cell?
+ bytes = getMaximumAlignedSize(bytes, align);
+ int sizeClass = space.getSizeClass(bytes);
+ Address cell = freeList.get(sizeClass);
+
+ if (cell.isZero()) {
+ Address block = currentBlock.get(sizeClass);
+ if (!block.isZero()) {
+ // Return the block if we currently own one
+ space.returnConsumedBlock(block, sizeClass);
+ currentBlock.set(sizeClass, Address.zero());
+ }
+
+ // Get a new block for allocation, if returned, it is guaranteed to have a free cell
+ block = space.getAllocationBlock(sizeClass, freeList);
+
+ if (!block.isZero()) {
+ // We have a new current block and free list.
+ currentBlock.set(sizeClass, block);
+ cell = freeList.get(sizeClass);
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!cell.isZero());
+ } else {
+ // Allocation Failure
+ return Address.zero();
+ }
+ }
+
+ freeList.set(sizeClass, cell.loadAddress());
+ /* Clear the free list link */
+ cell.store(Address.zero());
+ return alignAllocation(cell, align, offset);
+ }
+
+ /****************************************************************************
+ *
+ * Preserving (saving & restoring) free lists
+ */
+
+ /**
+ * Zero all of the current free list pointers, and refresh the
+ * <code>currentBlock</code> values, so instead of the free list
+ * pointing to free cells, it points to the block containing the
+ * free cells. Then the free lists for each cell can be
+ * reestablished during GC. If the free lists are being preserved
+ * on a per-block basis (eager mark-sweep and reference counting),
+ * then free lists are remembered for each block.
+ */
+ public final void flush() {
+ for (int sizeClass = 0; sizeClass < space.sizeClassCount(); sizeClass++) {
+ Address block = currentBlock.get(sizeClass);
+ if (!block.isZero()) {
+ Address cell = freeList.get(sizeClass);
+ space.returnBlock(block, sizeClass, cell);
+ currentBlock.set(sizeClass, Address.zero());
+ freeList.set(sizeClass, Address.zero());
+ }
+ }
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressDeque.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressDeque.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressDeque.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressDeque.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,120 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.deque;
+
+import org.mmtk.utility.Constants;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This supports <i>unsynchronized</i> enqueuing and dequeuing of addresses
+ */
+ at Uninterruptible public class AddressDeque extends LocalDeque
+ implements Constants {
+
+ /****************************************************************************
+ *
+ * Public instance methods
+ */
+ public final String name;
+
+ /**
+ * Constructor
+ *
+ * @param queue The shared queue to which this queue will append
+ * its buffers (when full or flushed) and from which it will aquire new
+ * buffers when it has exhausted its own.
+ */
+ public AddressDeque(String n, SharedDeque queue) {
+ super(queue);
+ name = n;
+ }
+
+ /**
+ * Insert an address into the address queue.
+ *
+ * @param addr the address to be inserted into the address queue
+ */
+ @Inline
+ public final void insert(Address addr) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr.isZero());
+ checkTailInsert(1);
+ uncheckedTailInsert(addr);
+ }
+
+ /**
+ * Insert an address into the address queue, force this out of line
+ * ("OOL"), in some circumstnaces it is too expensive to have the
+ * insert inlined, so this call is made.
+ *
+ * @param addr the address to be inserted into the address queue
+ */
+ @NoInline
+ public final void insertOOL(Address addr) {
+ insert(addr);
+ }
+
+ /**
+ * Push an address onto the address queue.
+ *
+ * @param addr the address to be pushed onto the address queue
+ */
+ @Inline
+ public final void push(Address addr) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr.isZero());
+ checkHeadInsert(1);
+ uncheckedHeadInsert(addr);
+ }
+
+ /**
+ * Push an address onto the address queue, force this out of line
+ * ("OOL"), in some circumstnaces it is too expensive to have the
+ * push inlined, so this call is made.
+ *
+ * @param addr the address to be pushed onto the address queue
+ */
+ @NoInline
+ public final void pushOOL(Address addr) {
+ push(addr);
+ }
+
+ /**
+ * Pop an address from the address queue, return zero if the queue
+ * is empty.
+ *
+ * @return The next address in the address queue, or zero if the
+ * queue is empty
+ */
+ @Inline
+ public final Address pop() {
+ if (checkDequeue(1)) {
+ return uncheckedDequeue();
+ } else {
+ return Address.zero();
+ }
+ }
+
+ @Inline
+ public final boolean isEmpty() {
+ return !checkDequeue(1);
+ }
+
+ @Inline
+ public final boolean isNonEmpty() {
+ return checkDequeue(1);
+ }
+
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressPairDeque.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressPairDeque.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressPairDeque.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressPairDeque.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,98 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.deque;
+
+import org.mmtk.utility.Constants;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This supports <i>unsynchronized</i> enqueuing and dequeuing of
+ * address pairs
+ */
+ at Uninterruptible public class AddressPairDeque extends LocalDeque implements Constants {
+
+ /****************************************************************************
+ *
+ * Public instance methods
+ */
+
+ /**
+ * Constructor
+ *
+ * @param queue The shared queue to which this queue will append
+ * its buffers (when full or flushed) and from which it will aquire new
+ * buffers when it has exhausted its own.
+ */
+ public AddressPairDeque(SharedDeque queue) {
+ super(queue);
+ }
+
+ /**
+ * Insert an address pair into the address queue.
+ *
+ * @param addr1 the first address to be inserted into the address queue
+ * @param addr2 the second address to be inserted into the address queue
+ */
+ public final void insert(Address addr1, Address addr2) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr1.isZero());
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr2.isZero());
+ checkTailInsert(2);
+ uncheckedTailInsert(addr1);
+ uncheckedTailInsert(addr2);
+ }
+
+ /**
+ * Push an address pair onto the address queue.
+ *
+ * @param addr1 the first value to be pushed onto the address queue
+ * @param addr2 the second value to be pushed onto the address queue
+ */
+ public final void push(Address addr1, Address addr2) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr1.isZero());
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr2.isZero());
+ checkHeadInsert(2);
+ uncheckedHeadInsert(addr2);
+ uncheckedHeadInsert(addr1);
+ }
+
+ /**
+ * Pop the first address in a pair from the address queue, return
+ * zero if the queue is empty.
+ *
+ * @return The next address in the address queue, or zero if the
+ * queue is empty
+ */
+ public final Address pop1() {
+ if (checkDequeue(2))
+ return uncheckedDequeue();
+ else
+ return Address.zero();
+ }
+
+ /**
+ * Pop the second address in a pair from the address queue.
+ *
+ * @return The next address in the address queue
+ */
+ public final Address pop2() {
+ return uncheckedDequeue();
+ }
+
+ public final boolean isEmpty() {
+ return !checkDequeue(2);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressTripleDeque.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressTripleDeque.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressTripleDeque.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/AddressTripleDeque.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.utility.deque;
+
+import org.mmtk.utility.Constants;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.Uninterruptible;
+
+
+/**
+ * This supports <i>unsynchronized</i> enqueuing and dequeuing of
+ * address triples
+ */
+ at Uninterruptible public class AddressTripleDeque extends LocalDeque implements Constants {
+
+ /****************************************************************************
+ *
+ * Public instance methods
+ */
+
+ /**
+ * Constructor
+ *
+ * @param queue The shared queue to which this queue will append its
+ * buffers (when full or flushed) and from which it will aquire new
+ * buffers when it has exhausted its own.
+ */
+ AddressTripleDeque(SharedDeque queue) {
+ super(queue);
+ }
+
+ /**
+ * Insert an address triple into the address queue.
+ *
+ * @param addr1 the first address to be inserted into the address queue
+ * @param addr2 the second address to be inserted into the address queue
+ * @param addr3 the third address to be inserted into the address queue
+ */
+ public final void insert(Address addr1, Address addr2,
+ Address addr3) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr1.isZero());
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr2.isZero());
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr3.isZero());
+ checkTailInsert(3);
+ uncheckedTailInsert(addr1);
+ uncheckedTailInsert(addr2);
+ uncheckedTailInsert(addr3);
+ }
+ /**
+ * Push an address pair onto the address queue.
+ *
+ * @param addr1 the first value to be pushed onto the address queue
+ * @param addr2 the second value to be pushed onto the address queue
+ * @param addr3 the third address to be pushed onto the address queue
+ */
+ public final void push(Address addr1, Address addr2, Address addr3) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr1.isZero());
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr2.isZero());
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr3.isZero());
+ checkHeadInsert(3);
+ uncheckedHeadInsert(addr3);
+ uncheckedHeadInsert(addr2);
+ uncheckedHeadInsert(addr1);
+ }
+
+ /**
+ * Pop the first address in a triple from the address queue, return
+ * zero if the queue is empty.
+ *
+ * @return The next address in the address queue, or zero if the
+ * queue is empty
+ */
+ public final Address pop1() {
+ if (checkDequeue(3))
+ return uncheckedDequeue();
+ else
+ return Address.zero();
+ }
+
+ /**
+ * Pop the second address in a triple from the address queue.
+ *
+ * @return The next address in the address queue
+ */
+ public final Address pop2() {
+ return uncheckedDequeue();
+ }
+
+
+ /**
+ * Pop the third address in a triple from the address queue.
+ *
+ * @return The next address in the address queue
+ */
+ public final Address pop3() {
+ return uncheckedDequeue();
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/Deque.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/Deque.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/Deque.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/Deque.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,79 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.deque;
+
+import org.mmtk.utility.Constants;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * Class that defines a doubly-linked double-ended queue (deque). The
+ * double-linking increases the space demands slightly, but makes it far
+ * more efficient to dequeue buffers and, for example, enables sorting of
+ * its contents.
+ */
+ at Uninterruptible class Deque implements Constants {
+
+ /****************************************************************************
+ *
+ * Protected instance methods
+ *
+ * protected int enqueued;
+ */
+
+ @Inline
+ protected final Offset bufferOffset(Address buf) {
+ return buf.toWord().and(BUFFER_MASK).toOffset();
+ }
+ @Inline
+ protected final Address bufferStart(Address buf) {
+ return buf.toWord().and(BUFFER_MASK.not()).toAddress();
+ }
+ @Inline
+ protected final Address bufferEnd(Address buf) {
+ return bufferStart(buf).plus(USABLE_BUFFER_BYTES);
+ }
+ @Inline
+ protected final Address bufferFirst(Address buf) {
+ return bufferStart(buf);
+ }
+ @Inline
+ protected final Address bufferLast(Address buf, int arity) {
+ return bufferStart(buf).plus(bufferLastOffset(arity));
+ }
+ @Inline
+ protected final Address bufferLast(Address buf) {
+ return bufferLast(buf, 1);
+ }
+ @Inline
+ protected final Offset bufferLastOffset(int arity) {
+ return Offset.fromIntZeroExtend(USABLE_BUFFER_BYTES - BYTES_IN_ADDRESS -
+ (USABLE_BUFFER_BYTES % (arity << LOG_BYTES_IN_ADDRESS)));
+ }
+
+ /****************************************************************************
+ *
+ * Private and protected static final fields (aka constants)
+ */
+ protected static final int LOG_PAGES_PER_BUFFER = 0;
+ protected static final int PAGES_PER_BUFFER = 1 << LOG_PAGES_PER_BUFFER;
+ private static final int LOG_BUFFER_SIZE = (LOG_BYTES_IN_PAGE + LOG_PAGES_PER_BUFFER);
+ protected static final int BUFFER_SIZE = 1 << LOG_BUFFER_SIZE;
+ protected static final Word BUFFER_MASK = Word.one().lsh(LOG_BUFFER_SIZE).minus(Word.one());
+ protected static final int NEXT_FIELD_OFFSET = BYTES_IN_ADDRESS;
+ protected static final int META_DATA_SIZE = 2 * BYTES_IN_ADDRESS;
+ protected static final int USABLE_BUFFER_BYTES = BUFFER_SIZE - META_DATA_SIZE;
+ protected static final Address TAIL_INITIAL_VALUE = Address.zero();
+ protected static final Address HEAD_INITIAL_VALUE = Address.zero();
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalDeque.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalDeque.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalDeque.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalDeque.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,158 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.deque;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.utility.Constants;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * Note this may perform poorly when being used as a FIFO structure with
+ * insertHead and pop operations operating on the same buffer. This
+ * only uses the fields inherited from <code>LocalQueue</code>, but adds
+ * the ability for entries to be added to the head of the deque and popped
+ * from the rear.
+ */
+ at Uninterruptible public class LocalDeque extends LocalQueue
+ implements Constants {
+
+ /****************************************************************************
+ *
+ * Public instance methods
+ */
+
+ /**
+ * Constructor
+ *
+ * @param queue The shared deque to which this local deque will append
+ * its buffers (when full or flushed).
+ */
+ LocalDeque(SharedDeque queue) {
+ super(queue);
+ }
+
+ /**
+ * Flush the buffer to the shared deque (this will make any entries
+ * in the buffer visible to any other consumer associated with the
+ * shared deque).
+ */
+ @Override
+ public final void flushLocal() {
+ super.flushLocal();
+ if (head.NE(Deque.HEAD_INITIAL_VALUE)) {
+ closeAndInsertHead(queue.getArity());
+ head = Deque.HEAD_INITIAL_VALUE;
+ }
+ }
+
+ /****************************************************************************
+ *
+ * Protected instance methods
+ */
+
+ /**
+ * Check whether there is space in the buffer for a pending insert.
+ * If there is not sufficient space, allocate a new buffer
+ * (dispatching the full buffer to the shared deque if not null).
+ *
+ * @param arity The arity of the values stored in this deque: the
+ * buffer must contain enough space for this many words.
+ */
+ @Inline
+ protected final void checkHeadInsert(int arity) {
+ if (bufferOffset(head).EQ(bufferSentinel(arity)) ||
+ head.EQ(HEAD_INITIAL_VALUE))
+ headOverflow(arity);
+ else if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(bufferOffset(head).sLE(bufferLastOffset(arity)));
+ }
+
+ /**
+ * Insert a value at the front of the deque (and buffer). This is
+ * <i>unchecked</i>. The caller must first call
+ * <code>checkHeadInsert()</code> to ensure the buffer can accommodate
+ * the insertion.
+ *
+ * @param value the value to be inserted.
+ */
+ @Inline
+ protected final void uncheckedHeadInsert(Address value) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(bufferOffset(head).sLT(bufferSentinel(queue.getArity())));
+ head.store(value);
+ head = head.plus(BYTES_IN_ADDRESS);
+ // if (Interface.VerifyAssertions) enqueued++;
+ }
+
+ /****************************************************************************
+ *
+ * Private instance methods and fields
+ */
+
+ /**
+ * Buffer space has been exhausted, allocate a new buffer and enqueue
+ * the existing buffer (if any).
+ *
+ * @param arity The arity of this buffer (used for sanity test only).
+ */
+ private void headOverflow(int arity) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(arity == queue.getArity());
+ if (head.NE(Deque.HEAD_INITIAL_VALUE))
+ closeAndInsertHead(arity);
+
+ head = queue.alloc();
+ Plan.checkForAsyncCollection(); // possible side-effect of alloc()
+ }
+
+ /**
+ * Close the head buffer and enqueue it at the front of the
+ * shared buffer deque.
+ *
+ * @param arity The arity of this buffer.
+ */
+ @Inline
+ private void closeAndInsertHead(int arity) {
+ queue.enqueue(head, arity, false);
+ }
+
+ /**
+ * The tail is empty (or null), and the shared deque has no buffers
+ * available. If the head has sufficient entries, consume the head.
+ * Otherwise try wait on the shared deque until either all other
+ * clients of the reach exhaustion or a buffer becomes
+ * available.
+ *
+ * @param arity The arity of this buffer
+ * @return True if the consumer has eaten all of the entries
+ */
+ @SuppressWarnings("unused")
+ private boolean tailStarved(int arity) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(arity == queue.getArity());
+ // entries in tail, so consume tail
+ if (!bufferOffset(head).isZero()) {
+ tailBufferEnd = head;
+ tail = bufferStart(tailBufferEnd);
+ head = Deque.HEAD_INITIAL_VALUE;
+ return false;
+ }
+
+ // Wait for another entry to materialize...
+ tailBufferEnd = queue.dequeueAndWait(arity, true);
+ tail = bufferStart(tail);
+
+ // return true if a) there is not a tail buffer or b) it is empty
+ return (tail.EQ(Deque.TAIL_INITIAL_VALUE) || tail.EQ(tailBufferEnd));
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalQueue.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalQueue.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalQueue.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalQueue.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,158 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.deque;
+
+import org.mmtk.utility.Constants;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements a local (<i>unsynchronized</i>) queue.
+ * A queue is strictly FIFO.<p>
+ *
+ * Each instance stores word-sized values into a local buffer. When
+ * the buffer is full, or if the <code>flushLocal()</code> method is
+ * called, the buffer enqueued at the tail of a
+ * <code>SharedDeque</code>.
+ *
+ * The implementation is intended to be as efficient as possible, in
+ * time and space, and is the basis for the <code>TraceBuffer</code> used by
+ * heap trace generation. Each instance adds a single field to those inherited
+ * from the SSB: a bump pointer.
+ *
+ * Preconditions: Buffers are always aligned on buffer-size address
+ * boundaries.<p>
+ *
+ * Invariants: Buffers are filled such that tuples (of the specified
+ * arity) are packed to the low end of the buffer. Thus buffer
+ * underflows will always arise when then cursor is buffer-size aligned.
+ */
+ at Uninterruptible class LocalQueue extends LocalSSB implements Constants {
+
+ /**
+ * Constructor
+ *
+ * @param queue The shared queue to which this local ssb will append
+ * its buffers (when full or flushed).
+ */
+ LocalQueue(SharedDeque queue) {
+ super(queue);
+ }
+
+ /****************************************************************************
+ *
+ * Protected instance methods and fields
+ */
+ @Entrypoint
+ protected Address head; // the start of the buffer
+
+ /**
+ * Reset the local buffer (throwing away any local entries).
+ */
+ public void resetLocal() {
+ super.resetLocal();
+ head = Deque.HEAD_INITIAL_VALUE;
+ }
+
+ /**
+ * Check whether there are values in the buffer for a pending dequeue.
+ * If there is not data, grab the first buffer on the shared queue
+ * (after freeing the buffer).
+ *
+ * @param arity The arity of the values stored in this queue: the
+ * buffer must contain enough space for this many words.
+ */
+ @Inline
+ protected final boolean checkDequeue(int arity) {
+ if (bufferOffset(head).isZero()) {
+ return dequeueUnderflow(arity);
+ } else {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(bufferOffset(head).sGE(Word.fromIntZeroExtend(arity).lsh(LOG_BYTES_IN_ADDRESS).toOffset()));
+ return true;
+ }
+ }
+
+ /**
+ * Dequeue a value from the buffer. This is <i>unchecked</i>. The
+ * caller must first call <code>checkDequeue()</code> to ensure the
+ * buffer has and entry to be removed.
+ *
+ * @return The first entry on the queue.
+ */
+ @Inline
+ protected final Address uncheckedDequeue(){
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(bufferOffset(head).sGE(Offset.fromIntZeroExtend(BYTES_IN_ADDRESS)));
+ head = head.minus(BYTES_IN_ADDRESS);
+ return head.loadAddress();
+ }
+
+ /**
+ * The head is empty (or null), and the shared queue has no buffers
+ * available. If the tail has sufficient entries, consume the tail.
+ * Otherwise try wait on the global queue until either all other
+ * clients of the queue reach exhaustion or a buffer becomes
+ * available.
+ *
+ * @param arity The arity of this buffer
+ * @return True if the consumer has eaten all the entries
+ */
+ protected final boolean headStarved(int arity) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(arity == queue.getArity());
+
+ // If the tail has entries...
+ if (tail.NE(tailBufferEnd)) {
+ head = normalizeTail(arity).plus(BYTES_IN_ADDRESS);
+ tail = Deque.TAIL_INITIAL_VALUE;
+ tailBufferEnd = Deque.TAIL_INITIAL_VALUE;
+ // Return that we acquired more entries
+ return false;
+ }
+ // Wait for another entry to materialize...
+ head = queue.dequeueAndWait(arity);
+ // return true if a) there is a head buffer, and b) it is non-empty
+ return (head.EQ(Deque.HEAD_INITIAL_VALUE) || bufferOffset(head).isZero());
+ }
+
+ /****************************************************************************
+ *
+ * Private instance methods
+ */
+
+ /**
+ * There are not sufficient entries in the head buffer for a pending
+ * dequeue. Acquire a new head buffer. If the shared queue has no
+ * buffers available, consume the tail if necessary. Return false
+ * if entries cannot be acquired.
+ *
+ * @param arity The arity of this buffer (used for sanity test only).
+ * @return True if there the head buffer has been successfully
+ * replenished.
+ */
+ @NoInline
+ private boolean dequeueUnderflow(int arity) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(arity == queue.getArity());
+ do {
+ if (head.NE(Deque.HEAD_INITIAL_VALUE))
+ queue.free(head);
+ head = queue.dequeue(arity);
+ } while (head.NE(Deque.HEAD_INITIAL_VALUE) && bufferOffset(head).isZero());
+
+ if (head.EQ(Deque.HEAD_INITIAL_VALUE))
+ return !headStarved(arity);
+
+ return true;
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalSSB.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalSSB.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalSSB.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/LocalSSB.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,214 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.deque;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.utility.Constants;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements a local (<i>unsynchronized</i>) sequential
+ * store buffer. An SSB is strictly FIFO (although this class does
+ * not implement dequeuing).<p>
+ *
+ * Each instance stores word-sized values into a local buffer. When
+ * the buffer is full, or if the <code>flushLocal()</code> method is
+ * called, the buffer enqueued at the tail of a
+ * <code>SharedDeque</code>. This class provides no mechanism for
+ * dequeing.<p>
+ *
+ * The implementation is intended to be as efficient as possible, in
+ * time and space, as it is used in critical code such as the GC work
+ * queue and the write buffer used by many "remembering"
+ * collectors. Each instance has just two fields: a bump pointer and a
+ * pointer to the <code>SharedDeque</code><p>
+ *
+ * Preconditions: Buffers are always aligned on buffer-size address
+ * boundaries.<p>
+ *
+ * Invariants: Buffers are filled such that tuples (of the specified
+ * arity) are packed to the low end of the buffer. Thus buffer
+ * overflows on inserts and pops (underflow actually) will always arise
+ * when then cursor is buffer-size aligned.
+ */
+ at Uninterruptible class LocalSSB extends Deque implements Constants {
+
+ /****************************************************************************
+ *
+ * Public instance methods
+ */
+
+ /**
+ * Constructor
+ *
+ * @param queue The shared queue to which this local ssb will append
+ * its buffers (when full or flushed).
+ */
+ LocalSSB(SharedDeque queue) {
+ this.queue = queue;
+ resetLocal();
+ }
+
+ /**
+ * Flush the buffer and add it to the shared queue (this will
+ * make any entries in the buffer visible to any consumer associated
+ * with the shared queue).
+ */
+ public void flushLocal() {
+ if (tail.NE(Deque.TAIL_INITIAL_VALUE)) {
+ closeAndEnqueueTail(queue.getArity());
+ tail = Deque.TAIL_INITIAL_VALUE;
+ tailBufferEnd = Deque.TAIL_INITIAL_VALUE;
+ }
+ }
+
+ public void reset() {
+ resetLocal();
+ }
+
+ /****************************************************************************
+ *
+ * Protected instance methods and fields
+ */
+ @Entrypoint
+ protected Address tail; // the location in the buffer
+ protected Address tailBufferEnd; // the end of the buffer
+ protected final SharedDeque queue; // the shared queue
+
+ /**
+ * Reset the local buffer (throwing away any local entries).
+ */
+ public void resetLocal() {
+ tail = Deque.TAIL_INITIAL_VALUE;
+ tailBufferEnd = Deque.TAIL_INITIAL_VALUE;
+ }
+
+ /**
+ * Check whether there is space in the buffer for a pending insert.
+ * If there is not sufficient space, allocate a new buffer
+ * (dispatching the full buffer to the shared queue if not null).
+ *
+ * @param arity The arity of the values stored in this SSB: the
+ * buffer must contain enough space for this many words.
+ */
+ @Inline(value=Inline.When.AssertionsDisabled)
+ protected final void checkTailInsert(int arity) {
+ if (bufferOffset(tail).isZero())
+ tailOverflow(arity);
+ else if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(bufferOffset(tail).sGE(Word.fromIntZeroExtend(arity).lsh(LOG_BYTES_IN_ADDRESS).toOffset()));
+ }
+
+ /**
+ * Insert a value into the buffer. This is <i>unchecked</i>. The
+ * caller must first call <code>checkInsert()</code> to ensure the
+ * buffer can accommodate the insertion.
+ *
+ * @param value the value to be inserted.
+ */
+ @Inline(value=Inline.When.AssertionsDisabled)
+ protected final void uncheckedTailInsert(Address value) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(bufferOffset(tail).sGE(Offset.fromIntZeroExtend(BYTES_IN_ADDRESS)));
+ tail = tail.minus(BYTES_IN_ADDRESS);
+ tail.store(value);
+ // if (Interface.VerifyAssertions) enqueued++;
+ }
+
+ /**
+ * In the case where a buffer must be flushed before being
+ * filled (either to the queue or to the head), the entries must be
+ * slid to the base of the buffer in order to preserve the invariant
+ * that all non-tail buffers will have entries starting at the base
+ * (which allows a simple test against the base to be used when
+ * popping entries). This is <i>expensive</i>, so should be
+ * avoided.
+ *
+ * @param arity The arity of the buffer in question
+ * @return The last slot in the normalized buffer that contains an entry
+ */
+ protected final Address normalizeTail(int arity) {
+ Address src = tail;
+ Address tgt = bufferFirst(tail);
+ Address last = tgt.plus(bufferLastOffset(arity).minus(bufferOffset(tail)));
+ while (tgt.LE(last)) {
+ tgt.store(src.loadAddress());
+ src = src.plus(BYTES_IN_ADDRESS);
+ tgt = tgt.plus(BYTES_IN_ADDRESS);
+ }
+ return last;
+ }
+
+ /**
+ * Return the sentinel offset for a buffer of a given arity. This is used
+ * both to compute the address at the end of the buffer.
+ *
+ * @param arity The arity of this buffer
+ * @return The sentinel offset value for a buffer of the given arity.
+ */
+ @Inline
+ protected final Offset bufferSentinel(int arity) {
+ return bufferLastOffset(arity).plus(BYTES_IN_ADDRESS);
+ }
+
+ /****************************************************************************
+ *
+ * Private instance methods
+ */
+
+ /**
+ * Buffer space has been exhausted, allocate a new buffer and enqueue
+ * the existing buffer (if any).
+ *
+ * @param arity The arity of this buffer (used for sanity test only).
+ */
+ private void tailOverflow(int arity) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(arity == queue.getArity());
+ if (tail.NE(Deque.TAIL_INITIAL_VALUE)) {
+ closeAndEnqueueTail(arity);
+ }
+ tail = queue.alloc().plus(bufferSentinel(arity));
+ tailBufferEnd = tail;
+ Plan.checkForAsyncCollection(); // possible side-effect of alloc()
+ }
+
+ /**
+ * Close the tail buffer (normalizing if necessary), and enqueue it
+ * at the tail of the shared buffer queue.
+ *
+ * @param arity The arity of this buffer.
+ */
+ @NoInline
+ private void closeAndEnqueueTail(int arity) {
+ Address last;
+ if (!bufferOffset(tail).isZero()) {
+ // prematurely closed
+ last = normalizeTail(arity);
+ } else {
+ // a full tail buffer
+ last = tailBufferEnd.minus(BYTES_IN_ADDRESS);
+ }
+ queue.enqueue(last.plus(BYTES_IN_ADDRESS), arity, true);
+ }
+
+ /**
+ * Return true if this SSB is locally empty
+ *
+ * @return true if this SSB is locally empty
+ */
+ public final boolean isFlushed() {
+ return tail.EQ(Deque.TAIL_INITIAL_VALUE);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/ObjectReferenceBuffer.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/ObjectReferenceBuffer.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/ObjectReferenceBuffer.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/ObjectReferenceBuffer.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.utility.deque;
+
+import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.utility.Constants;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class is a combination of a Deque and a TraceStep, designed to include
+ * intelligent processing of child references as objects are scanned.
+ *
+ * @see org.mmtk.plan.TransitiveClosure
+ */
+ at Uninterruptible
+public abstract class ObjectReferenceBuffer extends TransitiveClosure implements Constants {
+ /****************************************************************************
+ *
+ * Instance variables
+ */
+ private final ObjectReferenceDeque values;
+
+ /****************************************************************************
+ *
+ * Initialization
+ */
+
+ /**
+ * Constructor
+ *
+ * @param name The name of the underlying deque.
+ * @param queue The shared deque that is used.
+ */
+ public ObjectReferenceBuffer(String name, SharedDeque queue) {
+ values = new ObjectReferenceDeque(name, queue);
+ }
+
+ /**
+ * Trace an edge during GC.
+ *
+ * @param source The source of the reference.
+ * @param slot The location containing the object reference.
+ */
+ @Inline
+ public final void processEdge(ObjectReference source, Address slot) {
+ ObjectReference object = VM.activePlan.global().loadObjectReference(slot);
+ process(object);
+ }
+
+ /**
+ * This is the method that ensures
+ *
+ * @param object The object to process.
+ */
+ protected abstract void process(ObjectReference object);
+
+ /**
+ * Process each of the child objects for the passed object.
+ *
+ * @param object The object to process the children of.
+ */
+ @Inline
+ public final void processChildren(ObjectReference object) {
+ VM.scanning.scanObject(this, object);
+ }
+
+ /**
+ * Pushes an object onto the queue, forcing an inlined sequence.
+ *
+ * @param object The object to push.
+ */
+ @Inline
+ public final void push(ObjectReference object) {
+ values.push(object);
+ }
+
+ /**
+ * Pushes an object onto the queue, forcing an out of line sequence.
+ *
+ * @param object The object to push.
+ */
+ @Inline
+ public final void pushOOL(ObjectReference object) {
+ values.pushOOL(object);
+ }
+
+ /**
+ * Retrives an object.
+ *
+ * @return The object retrieved.
+ */
+ @Inline
+ public final ObjectReference pop() {
+ return values.pop();
+ }
+
+ @Inline
+ public final boolean isEmpty() {
+ return values.isEmpty();
+ }
+
+ /**
+ * Flushes all local state back to the shared queue.
+ */
+ public final void flushLocal() {
+ values.flushLocal();
+ }
+
+ /**
+ * Return true if this buffer is locally empty
+ */
+ public final boolean isFlushed() {
+ return values.isFlushed();
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/ObjectReferenceDeque.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/ObjectReferenceDeque.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/ObjectReferenceDeque.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/ObjectReferenceDeque.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,109 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.deque;
+
+import org.mmtk.utility.Constants;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This supports <i>unsynchronized</i> enqueuing and dequeuing of
+ * object references
+ */
+ at Uninterruptible public class ObjectReferenceDeque extends LocalDeque
+ implements Constants {
+
+ /****************************************************************************
+ *
+ * Public instance methods
+ */
+ public final String name;
+
+ /**
+ * Constructor
+ *
+ * @param queue The shared queue to which this queue will append
+ * its buffers (when full or flushed) and from which it will aquire new
+ * buffers when it has exhausted its own.
+ */
+ public ObjectReferenceDeque(String n, SharedDeque queue) {
+ super(queue);
+ name = n;
+ }
+
+ /**
+ * Insert an object into the object queue.
+ *
+ * @param object the object to be inserted into the object queue
+ */
+ @Inline
+ public final void insert(ObjectReference object) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!object.isNull());
+ checkTailInsert(1);
+ uncheckedTailInsert(object.toAddress());
+ }
+
+ /**
+ * Push an object onto the object queue.
+ *
+ * @param object the object to be pushed onto the object queue
+ */
+ @Inline
+ public final void push(ObjectReference object) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!object.isNull());
+ checkHeadInsert(1);
+ uncheckedHeadInsert(object.toAddress());
+ }
+
+ /**
+ * Push an object onto the object queue, force this out of line
+ * ("OOL"), in some circumstnaces it is too expensive to have the
+ * push inlined, so this call is made.
+ *
+ * @param object the object to be pushed onto the object queue
+ */
+ @NoInline
+ public final void pushOOL(ObjectReference object) {
+ push(object);
+ }
+
+ /**
+ * Pop an object from the object queue, return zero if the queue
+ * is empty.
+ *
+ * @return The next object in the object queue, or zero if the
+ * queue is empty
+ */
+ @Inline
+ public final ObjectReference pop() {
+ if (checkDequeue(1)) {
+ return uncheckedDequeue().toObjectReference();
+ } else {
+ return ObjectReference.nullReference();
+ }
+ }
+
+ @Inline
+ public final boolean isEmpty() {
+ return !checkDequeue(1);
+ }
+
+ @Inline
+ public final boolean isNonEmpty() {
+ return checkDequeue(1);
+ }
+
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SharedDeque.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SharedDeque.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SharedDeque.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SharedDeque.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,497 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.deque;
+
+import org.mmtk.policy.RawPageSpace;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.Constants;
+import org.mmtk.utility.Log;
+import org.mmtk.vm.Lock;
+import org.mmtk.vm.VM;
+import org.vmmagic.pragma.Entrypoint;
+import org.vmmagic.pragma.Inline;
+import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.unboxed.Address;
+import org.vmmagic.unboxed.Offset;
+
+/**
+ * This supports <i>unsynchronized</i> enqueuing and dequeuing of buffers
+ * for shared use. The data can be added to and removed from either end
+ * of the deque.
+ */
+ at Uninterruptible
+public class SharedDeque extends Deque implements Constants {
+ private static final boolean DISABLE_WAITING = true;
+ private static final Offset NEXT_OFFSET = Offset.zero();
+ private static final Offset PREV_OFFSET = Offset.fromIntSignExtend(BYTES_IN_ADDRESS);
+
+ private static final boolean TRACE = false;
+ private static final boolean TRACE_DETAIL = false;
+ private static final boolean TRACE_BLOCKERS = false;
+
+ /****************************************************************************
+ *
+ * Public instance methods
+ */
+
+ /**
+ * Constructor
+ */
+ public SharedDeque(String name, RawPageSpace rps, int arity) {
+ this.rps = rps;
+ this.arity = arity;
+ this.name = name;
+ lock = VM.newLock("SharedDeque");
+ clearCompletionFlag();
+ head = HEAD_INITIAL_VALUE;
+ tail = TAIL_INITIAL_VALUE;
+ }
+
+ /** Get the arity (words per entry) of this queue */
+ @Inline
+ final int getArity() { return arity; }
+
+ /**
+ * Enqueue a block on the head or tail of the shared queue
+ *
+ * @param buf
+ * @param arity
+ * @param toTail
+ */
+ final void enqueue(Address buf, int arity, boolean toTail) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(arity == this.arity);
+ lock();
+ if (toTail) {
+ // Add to the tail of the queue
+ setNext(buf, Address.zero());
+ if (tail.EQ(TAIL_INITIAL_VALUE))
+ head = buf;
+ else
+ setNext(tail, buf);
+ setPrev(buf, tail);
+ tail = buf;
+ } else {
+ // Add to the head of the queue
+ setPrev(buf, Address.zero());
+ if (head.EQ(HEAD_INITIAL_VALUE))
+ tail = buf;
+ else
+ setPrev(head, buf);
+ setNext(buf, head);
+ head = buf;
+ }
+ bufsenqueued++;
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(checkDequeLength(bufsenqueued));
+ unlock();
+ }
+
+ public final void clearDeque(int arity) {
+ Address buf = dequeue(arity);
+ while (!buf.isZero()) {
+ free(bufferStart(buf));
+ buf = dequeue(arity);
+ }
+ setCompletionFlag();
+ }
+
+ @Inline
+ final Address dequeue(int arity) {
+ return dequeue(arity, false);
+ }
+
+ final Address dequeue(int arity, boolean fromTail) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(arity == this.arity);
+ return dequeue(false, fromTail);
+ }
+
+ @Inline
+ final Address dequeueAndWait(int arity) {
+ return dequeueAndWait(arity, false);
+ }
+
+ final Address dequeueAndWait(int arity, boolean fromTail) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(arity == this.arity);
+ Address buf = dequeue(false, fromTail);
+ if (buf.isZero() && (!complete())) {
+ buf = dequeue(true, fromTail); // Wait inside dequeue
+ }
+ return buf;
+ }
+
+ /**
+ * Prepare for parallel processing. All active GC threads will
+ * participate, and pop operations will block until all work
+ * is complete.
+ */
+ public final void prepare() {
+ if (DISABLE_WAITING) {
+ prepareNonBlocking();
+ } else {
+ /* This should be the normal mode of operation once performance is fixed */
+ prepare(VM.collection.activeGCThreads());
+ }
+ }
+
+ /**
+ * Prepare for processing where pop operations on the deques
+ * will never block.
+ */
+ public final void prepareNonBlocking() {
+ prepare(1);
+ }
+
+ /**
+ * Prepare for parallel processing where a specific number
+ * of threads take part.
+ *
+ * @param consumers # threads taking part.
+ */
+ private void prepare(int consumers) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(numConsumersWaiting == 0);
+ setNumConsumers(consumers);
+ clearCompletionFlag();
+ }
+
+ public final void reset() {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(numConsumersWaiting == 0);
+ clearCompletionFlag();
+ setNumConsumersWaiting(0);
+ assertExhausted();
+ }
+
+ public final void assertExhausted() {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(head.isZero() && tail.isZero());
+ }
+
+ @Inline
+ final Address alloc() {
+ Address rtn = rps.acquire(PAGES_PER_BUFFER);
+ if (rtn.isZero()) {
+ Space.printUsageMB();
+ VM.assertions.fail("Failed to allocate space for queue. Is metadata virtual memory exhausted?");
+ }
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(rtn.EQ(bufferStart(rtn)));
+ return rtn;
+ }
+
+ @Inline
+ final void free(Address buf) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(buf.EQ(bufferStart(buf)) && !buf.isZero());
+ rps.release(buf);
+ }
+
+ @Inline
+ public final int enqueuedPages() {
+ return (int) (bufsenqueued * PAGES_PER_BUFFER);
+ }
+
+ /****************************************************************************
+ *
+ * Private instance methods and fields
+ */
+
+ /** The name of this shared deque - for diagnostics */
+ private final String name;
+
+ /** Raw page space from which to allocate */
+ private RawPageSpace rps;
+
+ /** Number of words per entry */
+ private final int arity;
+
+ /** Completion flag - set when all consumers have arrived at the barrier */
+ @Entrypoint
+ private volatile int completionFlag;
+
+ /** # active threads - processing is complete when # waiting == this */
+ @Entrypoint
+ private volatile int numConsumers;
+
+ /** # threads waiting */
+ @Entrypoint
+ private volatile int numConsumersWaiting;
+
+ /** Head of the shared deque */
+ @Entrypoint
+ protected volatile Address head;
+
+ /** Tail of the shared deque */
+ @Entrypoint
+ protected volatile Address tail;
+ @Entrypoint
+ private volatile int bufsenqueued;
+ private Lock lock;
+
+ private static final long WARN_PERIOD = (long)(2*1E9);
+ private static final long TIMEOUT_PERIOD = 10 * WARN_PERIOD;
+
+ /**
+ * Dequeue a block from the shared pool. If 'waiting' is true, and the
+ * queue is empty, wait for either a new block to show up or all the
+ * other consumers to join us.
+ *
+ * @param waiting
+ * @param fromTail
+ * @return the Address of the block
+ */
+ private Address dequeue(boolean waiting, boolean fromTail) {
+ lock();
+ Address rtn = ((fromTail) ? tail : head);
+ if (rtn.isZero()) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(tail.isZero() && head.isZero());
+ // no buffers available
+ if (waiting) {
+ int ordinal = TRACE ? 0 : VM.activePlan.collector().getId();
+ setNumConsumersWaiting(numConsumersWaiting + 1);
+ while (rtn.isZero()) {
+ if (numConsumersWaiting == numConsumers)
+ setCompletionFlag();
+ if (TRACE) {
+ Log.write("-- ("); Log.write(ordinal);
+ Log.write(") joining wait queue of SharedDeque(");
+ Log.write(name); Log.write(") ");
+ Log.write(numConsumersWaiting); Log.write("/");
+ Log.write(numConsumers);
+ Log.write(" consumers waiting");
+ if (complete()) Log.write(" WAIT COMPLETE");
+ Log.writeln();
+ if (TRACE_BLOCKERS)
+ VM.assertions.dumpStack();
+ }
+ unlock();
+ // Spin and wait
+ spinWait(fromTail);
+
+ if (complete()) {
+ if (TRACE) {
+ Log.write("-- ("); Log.write(ordinal); Log.writeln(") EXITING");
+ }
+ lock();
+ setNumConsumersWaiting(numConsumersWaiting - 1);
+ unlock();
+ return Address.zero();
+ }
+ lock();
+ // Re-get the list head/tail while holding the lock
+ rtn = ((fromTail) ? tail : head);
+ }
+ setNumConsumersWaiting(numConsumersWaiting - 1);
+ if (TRACE) {
+ Log.write("-- ("); Log.write(ordinal); Log.write(") resuming work ");
+ Log.write(" n="); Log.writeln(numConsumersWaiting);
+ }
+ } else {
+ unlock();
+ return Address.zero();
+ }
+ }
+ if (fromTail) {
+ // dequeue the tail buffer
+ setTail(getPrev(tail));
+ if (head.EQ(rtn)) {
+ setHead(Address.zero());
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(tail.isZero());
+ } else {
+ setNext(tail, Address.zero());
+ }
+ } else {
+ // dequeue the head buffer
+ setHead(getNext(head));
+ if (tail.EQ(rtn)) {
+ setTail(Address.zero());
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(head.isZero());
+ } else {
+ setPrev(head, Address.zero());
+ }
+ }
+ bufsenqueued--;
+ unlock();
+ return rtn;
+ }
+
+ /**
+ * Spinwait for GC work to arrive
+ *
+ * @param fromTail Check the head or the tail ?
+ */
+ private void spinWait(boolean fromTail) {
+ long startNano = 0;
+ long lastElapsedNano = 0;
+ while (true) {
+ long startCycles = VM.statistics.cycles();
+ long endCycles = startCycles + ((long) 1e9); // a few hundred milliseconds more or less.
+ long nowCycles;
+ do {
+ VM.memory.isync();
+ Address rtn = ((fromTail) ? tail : head);
+ if (!rtn.isZero() || complete()) return;
+ nowCycles = VM.statistics.cycles();
+ } while (startCycles < nowCycles && nowCycles < endCycles); /* check against both ends to guard against CPU migration */
+
+ /*
+ * According to the cycle counter, we've been spinning for a while.
+ * Time to check nanoTime and see if we should print a warning and/or fail.
+ * We lock the deque while doing this to avoid interleaved messages from multiple threads.
+ */
+ lock();
+ if (startNano == 0) {
+ startNano = VM.statistics.nanoTime();
+ } else {
+ long nowNano = VM.statistics.nanoTime();
+ long elapsedNano = nowNano - startNano;
+ if (elapsedNano - lastElapsedNano > WARN_PERIOD) {
+ Log.write("GC Warning: SharedDeque("); Log.write(name);
+ Log.write(") wait has reached "); Log.write(VM.statistics.nanosToSecs(elapsedNano));
+ Log.write(", "); Log.write(numConsumersWaiting); Log.write("/");
+ Log.write(numConsumers); Log.writeln(" threads waiting");
+ lastElapsedNano = elapsedNano;
+ }
+ if (elapsedNano > TIMEOUT_PERIOD) {
+ unlock(); // To allow other GC threads to die in turn
+ VM.assertions.fail("GC Error: SharedDeque Timeout");
+ }
+ }
+ unlock();
+ }
+ }
+
+ /**
+ * Set the "next" pointer in a buffer forming the linked buffer chain.
+ *
+ * @param buf The buffer whose next field is to be set.
+ * @param next The reference to which next should point.
+ */
+ private static void setNext(Address buf, Address next) {
+ buf.store(next, NEXT_OFFSET);
+ }
+
+ /**
+ * Get the "next" pointer in a buffer forming the linked buffer chain.
+ *
+ * @param buf The buffer whose next field is to be returned.
+ * @return The next field for this buffer.
+ */
+ protected final Address getNext(Address buf) {
+ return buf.loadAddress(NEXT_OFFSET);
+ }
+
+ /**
+ * Set the "prev" pointer in a buffer forming the linked buffer chain.
+ *
+ * @param buf The buffer whose next field is to be set.
+ * @param prev The reference to which prev should point.
+ */
+ private void setPrev(Address buf, Address prev) {
+ buf.store(prev, PREV_OFFSET);
+ }
+
+ /**
+ * Get the "next" pointer in a buffer forming the linked buffer chain.
+ *
+ * @param buf The buffer whose next field is to be returned.
+ * @return The next field for this buffer.
+ */
+ protected final Address getPrev(Address buf) {
+ return buf.loadAddress(PREV_OFFSET);
+ }
+
+ /**
+ * Check the number of buffers in the work queue (for debugging
+ * purposes).
+ *
+ * @param length The number of buffers believed to be in the queue.
+ * @return True if the length of the queue matches length.
+ */
+ private boolean checkDequeLength(int length) {
+ Address top = head;
+ int l = 0;
+ while (!top.isZero() && l <= length) {
+ top = getNext(top);
+ l++;
+ }
+ return l == length;
+ }
+
+ /**
+ * Lock this shared queue. We use one simple low-level lock to
+ * synchronize access to the shared queue of buffers.
+ */
+ private void lock() {
+ lock.acquire();
+ }
+
+ /**
+ * Release the lock. We use one simple low-level lock to synchronize
+ * access to the shared queue of buffers.
+ */
+ private void unlock() {
+ lock.release();
+ }
+
+ /**
+ * Is the current round of processing complete ?
+ */
+ private boolean complete() {
+ return completionFlag == 1;
+ }
+
+ /**
+ * Set the completion flag.
+ */
+ @Inline
+ private void setCompletionFlag() {
+ if (TRACE_DETAIL) {
+ Log.writeln("# setCompletionFlag: ");
+ }
+ completionFlag = 1;
+ }
+
+ /**
+ * Clear the completion flag.
+ */
+ @Inline
+ private void clearCompletionFlag() {
+ if (TRACE_DETAIL) {
+ Log.writeln("# clearCompletionFlag: ");
+ }
+ completionFlag = 0;
+ }
+
+ @Inline
+ private void setNumConsumers(int newNumConsumers) {
+ if (TRACE_DETAIL) {
+ Log.write("# Num consumers "); Log.writeln(newNumConsumers);
+ }
+ numConsumers = newNumConsumers;
+ }
+
+ @Inline
+ private void setNumConsumersWaiting(int newNCW) {
+ if (TRACE_DETAIL) {
+ Log.write("# Num consumers waiting "); Log.writeln(newNCW);
+ }
+ numConsumersWaiting = newNCW;
+ }
+
+ @Inline
+ private void setHead(Address newHead) {
+ head = newHead;
+ VM.memory.sync();
+ }
+
+ @Inline
+ private void setTail(Address newTail) {
+ tail = newTail;
+ VM.memory.sync();
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortSharedDeque.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortSharedDeque.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortSharedDeque.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortSharedDeque.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,372 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.deque;
+
+import org.mmtk.policy.RawPageSpace;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This supports <i>unsynchronized</i> enqueuing and dequeuing of buffers
+ * for shared use. The data can be added to and removed from either end
+ * of the deque. This class is based upon the SharedQueue class. The sorting
+ * routines were modified from code written by Narendran Sachindran and
+ * Matthew Hertz for GCTk.
+ */
+ at Uninterruptible public abstract class SortSharedDeque extends SharedDeque {
+
+
+ private static final int BYTES_PUSHED = BYTES_IN_ADDRESS * 5;
+ private static final int MAX_STACK_SIZE = BYTES_PUSHED * 64;
+ private static final Offset INSERTION_SORT_LIMIT = Offset.fromIntSignExtend(80);
+
+ /***********************************************************************
+ *
+ * Class variables
+ */
+
+ /**
+ * Constructor
+ *
+ * @param rps The space from which the instance should obtain buffers.
+ */
+ public SortSharedDeque(String name, RawPageSpace rps, int arity) {
+ super(name, rps, arity);
+ stackBase = AddressArray.create(MAX_STACK_SIZE);
+ stackLoc = 0;
+ }
+
+ /***********************************************************************
+ *
+ * Sorting methods, utilities, and instance variables
+ */
+
+
+ /**
+ * Return the sorting key for the object passed as a parameter.
+ *
+ * @param obj The address of the object whose key is wanted
+ * @return The value of the sorting key for this object
+ */
+ protected abstract Word getKey(Address obj);
+
+ private static final Word mask16 = Word.fromIntZeroExtend(0xffff0000);
+ private static final Word mask8 = Word.fromIntZeroExtend(0x0000ff00);
+ private static final Word mask4 = Word.fromIntZeroExtend(0x000000f0);
+ private static final Word mask2 = Word.fromIntZeroExtend(0x0000000c);
+ private static final Word mask1 = Word.fromIntZeroExtend(0x00000002);
+
+ /**
+ * Find the highest bit that is set in a longword and return a mask
+ * with only that bit set.
+ *
+ * @param addr Value for which the mask needs to be found
+ * @return The highest bit set in the parameter
+ */
+ private static Word getBitMask(Word addr) {
+ int shift = 0;
+ if (!addr.and(mask16).isZero()) {
+ addr = addr.rshl(16);
+ shift += 16;
+ }
+ if (!addr.and(mask8).isZero()) {
+ addr = addr.rshl(8);
+ shift += 8;
+ }
+ if (!addr.and(mask4).isZero()) {
+ addr = addr.rshl(4);
+ shift += 4;
+ }
+ if (!addr.and(mask2).isZero()) {
+ addr = addr.rshl(2);
+ shift += 2;
+ }
+ if (!addr.and(mask1).isZero()) {
+ shift += 1;
+ }
+ return (Word.one().lsh(shift));
+ }
+
+ /**
+ * Perform insertion sort within an intra-block address range.
+ *
+ * @param begin Start address of the range to be sorted
+ * @param end End address of the range to be sorted
+ */
+ private void insertionSort(Address begin, Address end) {
+ Address rPtr = begin.minus(BYTES_IN_ADDRESS);
+ Address lPtr;
+
+ while (rPtr.GE(end)) {
+ Address rSlot = rPtr.loadAddress();
+ Word rKey = getKey(rSlot);
+ lPtr = rPtr.plus(BYTES_IN_ADDRESS);
+ while (lPtr.LE(begin)) {
+ Address lSlot = lPtr.loadAddress();
+ Word lKey = getKey(lSlot);
+ if (lKey.GT(rKey)) {
+ lPtr.minus(BYTES_IN_ADDRESS).store(lSlot);
+ lPtr = lPtr.plus(BYTES_IN_ADDRESS);
+ } else {
+ break;
+ }
+ }
+ lPtr.minus(BYTES_IN_ADDRESS).store(rSlot);
+ rPtr = rPtr.minus(BYTES_IN_ADDRESS);
+ }
+ }
+
+ /**
+ * Sort objects using radix exchange sort. An explicit stack is
+ * maintained to avoid using recursion.
+ */
+ public void sort() {
+ Address startPtr, startLink, endPtr, endLink;
+ Word bitMask;
+ if (!head.EQ(HEAD_INITIAL_VALUE)) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(tail.NE(TAIL_INITIAL_VALUE));
+ /* Obtain the bitmask for the first iteration and save the start &
+ end pointers and the bitmask on the stack */
+ initStack();
+ startPtr = popStack();
+ while (!startPtr.isZero()) {
+ startLink = popStack();
+ endPtr = popStack();
+ endLink = popStack();
+ bitMask = (popStack()).toWord();
+ if (startLink.NE(endLink)) {
+ partition(startPtr, startLink, endPtr, endLink, bitMask);
+ } else if (startPtr.GT(endPtr)) {
+ /* Use insertionSort for a limited number of objects within
+ a single block */
+ if (startPtr.diff(endPtr).sLT(INSERTION_SORT_LIMIT)) {
+ insertionSort(startPtr, endPtr);
+ } else {
+ partition(startPtr, startLink, endPtr, endLink, bitMask);
+ }
+ }
+ // Get the next set of data to sort
+ startPtr = popStack();
+ }
+ }
+ checkIfSorted();
+ }
+
+ /**
+ * Partition the slots in an address range based on the value in
+ * a particular bit. Place the start & end addresses of the two
+ * partitions & a bitmask per partition (which indicates the highest
+ * bit position at which the max & min of a partition differ) on the
+ * stack. This works just like the partition in quick sort, except
+ * that a bit value is being compared here
+ *
+ * @param startAddr The start address of the range to be sorted
+ * @param startLinkAddr The address where the start block has its next field
+ * @param endAddr The end address of the range to be sorted
+ * @param endLinkAddr The address where the end block has its next field
+ * @param bitMask The mask in which the bit to be commpared is set
+ */
+ private void partition(Address startAddr, Address startLinkAddr,
+ Address endAddr, Address endLinkAddr,
+ Word bitMask) {
+ Address travPtr = endAddr;
+ Address travLink = endLinkAddr;
+ Address stopPtr = startAddr;
+ Address stopLink = startLinkAddr;
+ Address travSlot, stopSlot;
+ Word travKey, stopKey;
+ Word lmax = Word.zero(), rmax = Word.zero();
+ Word lmin = Word.max(), rmin = Word.max();
+
+ while (true) {
+ /* Compute the address range within the current block to compute. */
+ Address endOfBlock = travLink;
+
+ /* Move the left pointer until the right pointer is reached
+ or an address with a 0 value in the bit position is found. */
+ while (true) {
+ travSlot = travPtr.loadAddress();
+ travKey = getKey(travSlot);
+
+ /* If we reach the end. */
+ if (travPtr.EQ(stopPtr))
+ break;
+ /* If we found a 0 in bit position, break. */
+ if (travKey.and(bitMask).isZero())
+ break;
+ if (travKey.GT(rmax))
+ rmax = travKey;
+ if (travKey.LT(rmin))
+ rmin = travKey;
+ /* Move to the next entry. */
+ travPtr = travPtr.plus(BYTES_IN_ADDRESS);
+ /* If at end of remset block, move to next block */
+ if (travPtr.EQ(endOfBlock)) {
+ travLink = getPrev(travPtr);
+ endOfBlock = travLink;
+ travPtr = bufferStart(endOfBlock);
+ }
+ }
+
+ /* Store the end of the block. */
+ endOfBlock = bufferStart(stopPtr);
+ /* Move the right pointer until the left pointer is reached
+ or an address with a 1 value in the bit position is found. */
+ while (true) {
+ stopSlot = stopPtr.loadAddress();
+ stopKey = getKey(stopSlot);
+ /* Found a 1 in bit position, break. */
+ if (!stopKey.and(bitMask).isZero())
+ break;
+ if (stopKey.GT(lmax))
+ lmax = stopKey;
+ if (stopKey.LT(lmin))
+ lmin = stopKey;
+ if (stopPtr.EQ(travPtr))
+ break;
+ /* Move to the next entry, which may be in the next block. */
+ if (stopPtr.EQ(endOfBlock)) {
+ stopLink = getNext(stopLink);
+ stopPtr = stopLink;
+ endOfBlock = bufferStart(stopPtr);
+ }
+ stopPtr = stopPtr.minus(BYTES_IN_ADDRESS);
+ }
+ if (stopPtr.EQ(travPtr))
+ break;
+ /* interchange the values pointed to by the left and right pointers */
+ travPtr.store(stopSlot);
+ stopPtr.store(travSlot);
+ }
+
+ /* If max value is not equal to the min value in the right partition,
+ (not all slots are identical) push the right partition on to the stack */
+ if (rmax.GT(rmin)) {
+ if (travPtr.EQ(bufferStart(travPtr))) {
+ stopLink = getNext(travLink);
+ stopPtr = stopLink;
+ } else {
+ stopLink = travLink;
+ stopPtr = travPtr;
+ }
+ pushOnStack(getBitMask(rmax.xor(rmin)).toAddress());
+ pushOnStack(endLinkAddr);
+ pushOnStack(endAddr);
+ pushOnStack(stopLink);
+ pushOnStack(stopPtr.minus(BYTES_IN_ADDRESS));
+ }
+ /* if max value is not equal to the min value in the left partition,
+ (not all slots are identical) push the left partition on to the stack */
+ if (lmax.GT(lmin)) {
+ pushOnStack(getBitMask(lmax.xor(lmin)).toAddress());
+ pushOnStack(travLink);
+ pushOnStack(travPtr);
+ pushOnStack(startLinkAddr);
+ pushOnStack(startAddr);
+ }
+ }
+
+ /*************************************************************************
+ *
+ * Sorting Stack management routines
+ */
+ private int stackLoc;
+ private AddressArray stackBase;
+
+ /*
+ * Allocate memory for the stack and intialize it with the first range
+ * to partition
+ */
+ private void initStack() {
+ stackLoc = 0;
+
+ Address endOfBlock = tail;
+ Address startPtr = bufferStart(endOfBlock);
+ Word min = Word.max();
+ Word max = Word.zero();
+ // Find the max. and min addresses in the object buffer
+ while (endOfBlock.NE(HEAD_INITIAL_VALUE)) {
+ startPtr = bufferStart(endOfBlock);
+ while (startPtr.LT(endOfBlock)) {
+ Address startSlot = startPtr.loadAddress();
+ Word startKey = getKey(startSlot);
+ if (startKey.GT(max))
+ max = startKey;
+ if (startKey.LT(min))
+ min = startKey;
+ startPtr = startPtr.plus(BYTES_IN_ADDRESS);
+ }
+ endOfBlock = getPrev(startPtr);
+ }
+
+ // If max and min are different (not all elements are equal), push the
+ // start, end and bitmask values on the stack
+ if (max.GT(min)) {
+ pushOnStack(getBitMask(max.xor(min)).toAddress());
+ pushOnStack(tail);
+ pushOnStack(bufferStart(tail));
+ pushOnStack(startPtr);
+ pushOnStack(startPtr.minus(BYTES_IN_ADDRESS));
+ }
+ }
+
+ /**
+ * Push an address on to the stack
+ *
+ * @param val The address to be pushed
+ */
+ private void pushOnStack(Address val) {
+ stackBase.set(stackLoc, val);
+ stackLoc++;
+ }
+
+ /**
+ * Pop an address from the stack
+ *
+ * @return The address at the top of the stack, or 0 if stack is empty
+ */
+ private Address popStack() {
+ if (stackLoc == 0)
+ return Address.zero();
+ stackLoc--;
+ return stackBase.get(stackLoc);
+ }
+
+ /**
+ * Debug routine, used to check if the object buffer is sorted correctly in
+ * decreasing final reference deletion time
+ */
+ private void checkIfSorted() {
+ if (VM.VERIFY_ASSERTIONS) {
+ Address buf, end;
+ Word prevKey = Word.max();
+ end = tail;
+ buf = bufferStart(end);
+ while (buf.NE(HEAD_INITIAL_VALUE)) {
+ // iterate through the block
+ while (buf.LT(end)) {
+ Address slot = buf.loadAddress();
+ Word key = getKey(slot);
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(key.LE(prevKey));
+ prevKey = key;
+ buf = buf.plus(BYTES_IN_ADDRESS);
+ }
+ end = getPrev(end);
+ buf = bufferStart(end);
+ }
+ }
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODAddressStack.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODAddressStack.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODAddressStack.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODAddressStack.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,91 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.deque;
+
+import org.mmtk.utility.Constants;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This supports <i>unsynchronized</i> pushing and popping of addresses.
+ * In addition, this can sort the entries currently on the shared stack.
+ */
+ at Uninterruptible public class SortTODAddressStack extends LocalDeque
+ implements Constants {
+
+ /****************************************************************************
+ *
+ * Public instance methods
+ */
+
+ /**
+ * Constructor
+ *
+ * @param queue The shared stack to which this stack will append
+ * its buffers (when full or flushed) and from which it will aquire new
+ * buffers when it has exhausted its own.
+ */
+ public SortTODAddressStack(SortTODSharedDeque queue) {
+ super(queue);
+ }
+
+ /**
+ * Sort the address on the shared stack.
+ */
+ public final void sort() {
+ flushLocal();
+ ((SortTODSharedDeque) queue).sort();
+ }
+
+ /**
+ * Push an address onto the address stack.
+ *
+ * @param addr the address to be pushed onto the address queue
+ */
+ @Inline
+ public final void push(Address addr) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr.isZero());
+ checkHeadInsert(1);
+ uncheckedHeadInsert(addr);
+ }
+
+ /**
+ * Pop an address from the address stack, return zero if the stack
+ * is empty.
+ *
+ * @return The next address in the address stack, or zero if the
+ * stack is empty
+ */
+ @Inline
+ public final Address pop() {
+ if (checkDequeue(1)) {
+ return uncheckedDequeue();
+ } else {
+ return Address.zero();
+ }
+ }
+
+ /**
+ * Check if the (local and shared) stacks are empty.
+ *
+ * @return True if there are no more entries on the local & shared stack,
+ * false otherwise.
+ */
+ @Inline
+ public final boolean isEmpty() {
+ return !checkDequeue(1);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODObjectReferenceStack.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODObjectReferenceStack.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODObjectReferenceStack.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODObjectReferenceStack.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,93 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.deque;
+
+import org.mmtk.utility.Constants;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This supports <i>unsynchronized</i> pushing and popping of object
+ * references. In addition, this can sort the entries currently on
+ * the shared stack.
+ */
+ at Uninterruptible public class SortTODObjectReferenceStack extends LocalDeque
+ implements Constants {
+
+ /****************************************************************************
+ *
+ * Public instance methods
+ */
+
+ /**
+ * Constructor
+ *
+ * @param queue The shared stack to which this stack will append
+ * its buffers (when full or flushed) and from which it will aquire new
+ * buffers when it has exhausted its own.
+ */
+ public SortTODObjectReferenceStack(SortTODSharedDeque queue) {
+ super(queue);
+ }
+
+ /**
+ * Sort the address on the shared stack.
+ */
+ public final void sort() {
+ flushLocal();
+ ((SortTODSharedDeque) queue).sort();
+ }
+
+ /**
+ * Push an address onto the address stack.
+ *
+ * @param object the object to be pushed onto the object queue
+ */
+ @Inline
+ public final void push(ObjectReference object) {
+ Address addr = object.toAddress();
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!addr.isZero());
+ checkHeadInsert(1);
+ uncheckedHeadInsert(addr);
+ }
+
+ /**
+ * Pop an address from the address stack, return zero if the stack
+ * is empty.
+ *
+ * @return The next address in the address stack, or zero if the
+ * stack is empty
+ */
+ @Inline
+ public final ObjectReference pop() {
+ if (checkDequeue(1)) {
+ return uncheckedDequeue().toObjectReference();
+ } else {
+ return ObjectReference.nullReference();
+ }
+ }
+
+ /**
+ * Check if the (local and shared) stacks are empty.
+ *
+ * @return True if there are no more entries on the local & shared stack,
+ * false otherwise.
+ */
+ @Inline
+ public final boolean isEmpty() {
+ return !checkDequeue(1);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODSharedDeque.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODSharedDeque.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODSharedDeque.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/SortTODSharedDeque.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.deque;
+
+import org.mmtk.policy.RawPageSpace;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This class specializes SortSharedQueue to sort objects according to
+ * their time of death (TOD).
+ */
+ at Uninterruptible
+public final class SortTODSharedDeque extends SortSharedDeque {
+
+ /**
+ * Constructor
+ *
+ * @param rps The space from which the instance should obtain buffers.
+ * @param arity The arity of the data to be enqueued
+ */
+ public SortTODSharedDeque(String name, RawPageSpace rps, int arity) {
+ super(name, rps, arity);
+ }
+
+ /**
+ * Return the sorting key for the object passed as a parameter.
+ *
+ * @param obj The address of the object whose key is wanted
+ * @return The value of the sorting key for this object
+ */
+ protected Word getKey(Address obj) {
+ return VM.traceInterface.getDeathTime(obj.toObjectReference());
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/TraceBuffer.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/TraceBuffer.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/TraceBuffer.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/TraceBuffer.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,235 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.deque;
+
+import org.mmtk.utility.Log;
+import org.mmtk.utility.TracingConstants;
+import org.mmtk.vm.VM;
+import org.mmtk.utility.Constants;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This supports <i>unsynchronized</i> enqueuing and dequeuing of tracing data
+ * and bulk processing of the buffer.
+ */
+ at Uninterruptible public class TraceBuffer extends LocalQueue
+ implements Constants, TracingConstants {
+
+ /***********************************************************************
+ *
+ * Class based constants
+ */
+ private static final Word TRACE_NEW_RECORD = Word.fromIntSignExtend(3);
+ private static final Word TRACE_ALLOC_SIZE = Word.fromIntSignExtend(5);
+// private static final Word TRACE_ALLOC_NAME = Word.fromIntSignExtend(6);
+ private static final Word TRACE_ALLOC_FP = Word.fromIntSignExtend(7);
+ private static final Word TRACE_ALLOC_THREAD = Word.fromIntSignExtend(9);
+ private static final Word TRACE_TIB_VALUE = Word.fromIntSignExtend(10);
+ private static final Word TRACE_DEATH_TIME = Word.fromIntSignExtend(11);
+ private static final Word TRACE_FIELD_TARGET = Word.fromIntSignExtend(12);
+ private static final Word TRACE_ARRAY_TARGET = Word.fromIntSignExtend(13);
+ private static final Word TRACE_FIELD_SLOT = Word.fromIntSignExtend(14);
+ private static final Word TRACE_ARRAY_ELEMENT = Word.fromIntSignExtend(15);
+ private static final Word TRACE_STATIC_TARGET = Word.fromIntSignExtend(17);
+ private static final Word TRACE_BOOT_ALLOC_SIZE = Word.fromIntSignExtend(18);
+
+ /*
+ * Debugging and trace reducing constants
+ */
+ public static final boolean OMIT_ALLOCS=false;
+ public static final boolean OMIT_UPDATES=false;
+ public static final boolean OMIT_BOOTALLOCS=false;
+ public static final boolean OMIT_UNREACHABLES=false;
+ public static final boolean OMIT_OTHERS=false;
+ public static final boolean OMIT_OUTPUT=OMIT_ALLOCS && OMIT_UPDATES &&
+ OMIT_OTHERS;
+
+
+ /***********************************************************************
+ *
+ * Public methods
+ */
+
+ /**
+ * Constructor
+ *
+ * @param pool The shared queue to which this queue will append its
+ * buffers (when full or flushed) and from which it will aquire new
+ * buffers when it has exhausted its own.
+ */
+ public TraceBuffer(SharedDeque pool) {
+ super(pool);
+ }
+
+ /**
+ * Push word onto the tracing queue.
+ *
+ * @param i The data to be pushed onto the tracing queue
+ */
+ @Inline
+ public final void push(Word i) {
+ checkTailInsert(1);
+ uncheckedTailInsert(i.toAddress());
+ }
+
+ /**
+ * Process the data in the tracing buffer, output information as needed.
+ */
+ public final void process() {
+ Word traceState = TRACE_NEW_RECORD;
+ int entriesNotFlushed = 0;
+ boolean loggedRecord = false;
+ /* First we must flush any remaining data */
+ if (!OMIT_OUTPUT) Log.writeln();
+
+ /* Process through the entire buffer. */
+ while (checkDequeue(1)) {
+ /* For speed and efficiency, we will actually process the data buffer by
+ buffer and not by dequeue-ing each entry. */
+ while (!bufferOffset(head).isZero()) {
+ head = head.minus(BYTES_IN_ADDRESS);
+ Word val = head.loadWord();
+ if (traceState.EQ(TRACE_NEW_RECORD)) {
+ loggedRecord = false;
+ if (val.EQ(TRACE_GCSTART)) {
+ if (!OMIT_OTHERS) {
+ Log.write('G');
+ Log.write('C');
+ Log.writeln('B', true);
+ }
+ } else if (val.EQ(TRACE_GCEND)) {
+ if (!OMIT_OTHERS) {
+ Log.write('G');
+ Log.write('C');
+ Log.writeln('E', true);
+ }
+ } else {
+ traceState = val;
+ }
+ } else {
+ if (traceState.EQ(TRACE_EXACT_ALLOC) ||
+ traceState.EQ(TRACE_ALLOC)) {
+ if (!OMIT_ALLOCS) {
+ Log.write((traceState.EQ(TRACE_EXACT_ALLOC)) ? 'A' : 'a');
+ Log.write(' ');
+ Log.write(val);
+ loggedRecord = true;
+ }
+ traceState = TRACE_ALLOC_SIZE;
+ } else if (traceState.EQ(TRACE_EXACT_IMMORTAL_ALLOC) ||
+ traceState.EQ(TRACE_IMMORTAL_ALLOC)) {
+ if (!OMIT_ALLOCS) {
+ Log.write((traceState.EQ(TRACE_EXACT_IMMORTAL_ALLOC)) ? 'I' : 'i');
+ Log.write(' ');
+ Log.write(val);
+ loggedRecord = true;
+ }
+ traceState = TRACE_ALLOC_SIZE;
+ } else if (traceState.EQ(TRACE_BOOT_ALLOC)) {
+ if (!OMIT_BOOTALLOCS) {
+ Log.write('B');
+ Log.write(' ');
+ Log.write(val);
+ loggedRecord = true;
+ }
+ traceState = TRACE_BOOT_ALLOC_SIZE;
+ } else if (traceState.EQ(TRACE_DEATH)) {
+ if (!OMIT_UNREACHABLES) {
+ Log.write('D');
+ Log.write(' ');
+ Log.write(val);
+ loggedRecord = true;
+ }
+ traceState = TRACE_DEATH_TIME;
+ } else if (traceState.EQ(TRACE_BOOT_ALLOC_SIZE)) {
+ if (!OMIT_BOOTALLOCS)
+ Log.write(val);
+ traceState = TRACE_NEW_RECORD;
+ } else if (traceState.EQ(TRACE_ALLOC_SIZE)) {
+ if (!OMIT_ALLOCS)
+ Log.write(val);
+ traceState = TRACE_ALLOC_FP;
+ } else if (traceState.EQ(TRACE_ALLOC_FP)) {
+ if (!OMIT_ALLOCS)
+ Log.write(val);
+ traceState = TRACE_ALLOC_THREAD;
+ } else if (traceState.EQ(TRACE_ALLOC_THREAD)) {
+ if (!OMIT_ALLOCS)
+ Log.write(val);
+ traceState = TRACE_NEW_RECORD;
+ } else if (traceState.EQ(TRACE_TIB_SET)) {
+ if (!OMIT_UPDATES) {
+ Log.write('T');
+ Log.write(' ');
+ Log.write(val);
+ loggedRecord = true;
+ }
+ traceState = TRACE_TIB_VALUE;
+ } else if (traceState.EQ(TRACE_STATIC_SET)) {
+ if (!OMIT_UPDATES) {
+ Log.write('S');
+ Log.write(' ');
+ Log.write(val);
+ loggedRecord = true;
+ }
+ traceState = TRACE_STATIC_TARGET;
+ } else if (traceState.EQ(TRACE_TIB_VALUE) ||
+ traceState.EQ(TRACE_STATIC_TARGET)) {
+ if (!OMIT_UPDATES)
+ Log.write(val);
+ traceState = TRACE_NEW_RECORD;
+ } else if (traceState.EQ(TRACE_DEATH_TIME)) {
+ if (!OMIT_UNREACHABLES)
+ Log.write(val);
+ traceState = TRACE_NEW_RECORD;
+ } else if (traceState.EQ(TRACE_FIELD_SET) ||
+ traceState.EQ(TRACE_ARRAY_SET)) {
+ if (!OMIT_UPDATES) {
+ Log.write('U');
+ Log.write(' ');
+ Log.write(val);
+ loggedRecord = true;
+ }
+ traceState = TRACE_FIELD_SLOT;
+ } else if (traceState.EQ(TRACE_FIELD_TARGET) ||
+ traceState.EQ(TRACE_ARRAY_TARGET)) {
+ if (!OMIT_UPDATES)
+ Log.write(val);
+ traceState = TRACE_NEW_RECORD;
+ } else if (traceState.EQ(TRACE_FIELD_SLOT) ||
+ traceState.EQ(TRACE_ARRAY_ELEMENT)) {
+ if (!OMIT_UPDATES)
+ Log.write(val);
+ traceState = TRACE_FIELD_TARGET;
+ } else {
+ VM.assertions.fail("Cannot understand directive!\n");
+ }
+ if (traceState.EQ(TRACE_NEW_RECORD) && loggedRecord) {
+ entriesNotFlushed++;
+ Log.writeln();
+ } else if (loggedRecord) {
+ Log.write(' ');
+ }
+ }
+ if (entriesNotFlushed == 10) {
+ if (!OMIT_OUTPUT)
+ Log.flush();
+ entriesNotFlushed = 0;
+ }
+ }
+ }
+ resetLocal();
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/WriteBuffer.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/WriteBuffer.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/WriteBuffer.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/deque/WriteBuffer.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.utility.deque;
+
+import org.mmtk.utility.Constants;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This supports <i>unsynchronized</i> insertion of write buffer values.
+ */
+ at Uninterruptible public class WriteBuffer extends LocalSSB
+ implements Constants {
+
+ /****************************************************************************
+ *
+ * Public instance methods
+ */
+
+ /**
+ * Constructor
+ *
+ * @param queue The shared queue to which this local ssb will append
+ * its buffers (when full or flushed).
+ */
+ public WriteBuffer(SharedDeque queue) {
+ super(queue);
+ }
+
+ /**
+ * Insert a value to be remembered into the write buffer.
+ *
+ * @param addr the value to be inserted into the write buffer
+ */
+ @NoInline
+ public final void insert(Address addr) {
+ checkTailInsert(1);
+ uncheckedTailInsert(addr);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/Color.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/Color.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/Color.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/Color.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.utility.gcspy;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * Color.java
+ *
+ * Cut-down implementation of java.awt.Color sufficient to provide
+ * the server side (Stream) with colours
+ */
+ at Uninterruptible public class Color {
+
+ /**
+ * Some gcspy standard colours (taken from gcspy_color_db.c).
+ */
+ public static final Color Black = new Color(0, 0, 0);
+ public static final Color Blue = new Color(0, 0, 255);
+ public static final Color Cyan = new Color(0, 255, 255);
+ public static final Color DarkGray = new Color(64, 64, 64);
+ public static final Color Gray = new Color(128, 128, 128);
+ public static final Color Green = new Color(0, 255, 0);
+ public static final Color LightGray = new Color(192, 192, 192);
+ public static final Color Magenta = new Color(255, 0, 255);
+ public static final Color MidGray = new Color(160, 160, 160);
+ public static final Color NavyBlue = new Color(0, 0, 150);
+ public static final Color OffWhite = new Color(230, 230, 230);
+ public static final Color Orange = new Color(255, 200, 0);
+ public static final Color Pink = new Color(255, 175, 175);
+ public static final Color Red = new Color(255, 0, 0);
+ public static final Color White = new Color(255, 255, 255);
+ public static final Color Yellow = new Color(255, 255, 0);
+
+ private short r; // red component
+ private short g; // green component
+ private short b; // blue component
+
+ /**
+ * Constructor for a simple RGB colour model.
+ *
+ * @param r red component
+ * @param g green component
+ * @param b blue component
+ */
+ public Color(short r, short g, short b) {
+ if (VM.VERIFY_ASSERTIONS)
+ VM.assertions._assert((0 <= r) && (r <= 255) &&
+ (0 <= g) && (g <= 255) &&
+ (0 <= b) && (b <= 255));
+ this.r = r;
+ this.g = g;
+ this.b = b;
+ }
+
+ /**
+ * Constructor for a simple RGB colour model.
+ *
+ * @param r red component
+ * @param g green component
+ * @param b blue component
+ */
+ private Color(int r, int g, int b) {
+ this((short) r, (short) g, (short) b);
+ }
+
+
+ /**
+ * Red component
+ *
+ * @return the red component
+ */
+ public short getRed() { return r; }
+
+ /**
+ * Green component
+ *
+ * @return the green component
+ */
+ public short getGreen() { return g; }
+
+ /**
+ * Blue component
+ *
+ * @return the blue component
+ */
+ public short getBlue() { return b; }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/GCspy.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/GCspy.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/GCspy.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/GCspy.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.utility.gcspy;
+
+import org.mmtk.utility.Log;
+import org.mmtk.utility.options.*;
+import org.mmtk.vm.VM;
+import org.mmtk.vm.gcspy.ServerInterpreter;
+import org.mmtk.vm.gcspy.Util;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements collector-independent GCspy functionality to start
+ * the GCspy server. It handles command-line parameters for port number,
+ * whether the VM should wait for a GCspy client to connect, and tile size.
+ * Most importantly, it calls the Plan's startGCspyServer method which
+ * creates a new ServerInterpreter, and adds events and space drivers.
+ */
+ at Uninterruptible public class GCspy {
+
+ /****************************************************************************
+ *
+ * Class variables
+ */
+
+ public static final Util util = VM.newGCspyUtil();
+ public static final ServerInterpreter server = VM.newGCspyServerInterpreter();
+
+ /****************************************************************************
+ *
+ * Initialization
+ */
+
+ @Interruptible
+ public static void createOptions() {
+ Options.gcspyPort = new GCspyPort();
+ Options.gcspyWait = new GCspyWait();
+ Options.gcspyTileSize = new GCspyTileSize();
+ }
+
+ /**
+ * The boot 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.
+ */
+ public static void postBoot() { }
+
+ /**
+ * Get the number of the port that GCspy communicates on
+ *
+ * @return the GCspy port number
+ */
+ public static int getGCspyPort() {
+ return Options.gcspyPort.getValue();
+ }
+
+ /**
+ * Should the VM wait for GCspy to connect?
+ *
+ * @return whether the VM should wait for the visualiser to connect
+ */
+ public static boolean getGCspyWait() {
+ return Options.gcspyWait.getValue();
+ }
+
+ /**
+ * Start the GCspy server.
+ * WARNING: allocates memory indirectly
+ */
+ @Interruptible
+ public static void startGCspyServer() {
+ int port = getGCspyPort();
+ Log.write("GCspy.startGCspyServer, port="); Log.write(port);
+ Log.write(", wait=");
+ Log.writeln(getGCspyWait());
+ if (port > 0) {
+ VM.activePlan.global().startGCspyServer(port, getGCspyWait());
+ //Log.writeln("gcspy thread booted");
+ }
+ }
+}
+
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/LinearScan.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/LinearScan.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/LinearScan.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/LinearScan.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.gcspy;
+
+import org.mmtk.utility.gcspy.drivers.AbstractDriver;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This class is only necessary because we cannot implement
+ * org.mmtk.utility.alloc.LinearScan as an interface since the invokeinterface
+ * bytecode is forbidden in uninterruptible code.
+ */
+ at Uninterruptible public class LinearScan extends org.mmtk.utility.alloc.LinearScan {
+
+ private final AbstractDriver driver;
+
+ /**
+ * Create a new scanner.
+ * @param d The GCspy driver that provides the callback.
+ */
+ public LinearScan(AbstractDriver d) { driver = d; }
+
+ /**
+ * Scan an object. The object reference is passed to the scan method of the
+ * GCspy driver registered with this scanner.
+ * @param obj The object to scan.
+ */
+ public void scan(ObjectReference obj) { driver.scan(obj); }
+}
+
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/StreamConstants.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/StreamConstants.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/StreamConstants.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/StreamConstants.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.utility.gcspy;
+
+/**
+ * This interface provides constants used by the GCspy framweork.
+ * These must correspond with values in gcspy_stream.h
+ * Presentation
+ * <table>
+ <tr><td>PRESENTATION_PLAIN</td> <td>presented as is</td>
+ <tr><td>PRESENTATION_PLUS</td> <td>as max+ if value exceeds max else as is</td>
+ <tr><td>PRESENTATION_MAX_VAR</td> <td>ditto but takes max value from a specified stream</td>
+ <tr><td>PRESENTATION_PERCENT</td> <td>as value (percent)</td>
+ <tr><td>PRESENTATION_PERCENT_VAR</td><td>ditto but takes max value from a specified stream</td>
+ <tr><td>PRESENTATION_ENUM </td> <td>chooses from an enumeration</td>
+ </table>
+ Paint style
+ <table>
+ <tr><td>PAINT_STYLE_PLAIN</td> <td>Paints as is</td>
+ <tr><td>PAINT_STYLE_ZERO</td> <td>ditto but treats zero values specially</td>
+ </table>
+ Data types
+ <table>
+ <tr><td>BYTE_TYPE</td> <td>stream of bytes</td>
+ <tr><td>SHORT_TYPE</td> <td>stream of shorts</td>
+ <tr><td>INT_TYPE</td> <td>stream of ints</td>
+ </table>
+ * StreamConstants
+ */
+
+public interface StreamConstants {
+
+ int NAME_LEN = 40;
+ int PRESENTATION_PLAIN = 0;
+ int PRESENTATION_PLUS = 1;
+ int PRESENTATION_MAX_VAR = 2;
+ int PRESENTATION_PERCENT = 3;
+ int PRESENTATION_PERCENT_VAR = 4;
+ int PRESENTATION_ENUM = 5;
+
+ int PAINT_STYLE_PLAIN = 0;
+ int PAINT_STYLE_ZERO = 1;
+
+ int BYTE_TYPE = 0;
+ int SHORT_TYPE = 1;
+ int INT_TYPE = 2;
+
+ int ENUM_MAX_LEN = 20;
+ int ENUM_MAX_NUM = 5;
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/Subspace.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/Subspace.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/Subspace.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/Subspace.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,236 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.gcspy;
+
+import org.mmtk.utility.Log;
+import org.mmtk.vm.gcspy.Util;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+
+
+/**
+ * This class is an abstraction of a contiguous region of a Space. For
+ * example, a semispace collector might choose to model the heap as a
+ * single Space, but within that Space it could model each semispace by
+ * a Subspace.<p>
+ * Subspace provides a number of useful facilities to many drivers, and
+ * is useful even if the Space comprises just a single contiguous region.<p>
+ *
+ * A subspace keeps track of the start and end address of the region,
+ * the index of its first block, the size of the blocks in this space,
+ * and the number of blocks in this subspace.
+ */
+ at Uninterruptible public class Subspace {
+
+ private Address start_; // The Subspace spans the address range [start_, end_)
+ private Address end_;
+ private int firstIndex_; // The index of the block in which start_ lies
+ private int blockSize_; // The block size
+ private int blockNum_; // The number of blocks in this space
+
+ private static final boolean DEBUG = false;
+
+ /**
+ * Create a new subspace
+ *
+ * @param start The address of the start of the subspace
+ * @param end The address of the end of the subspace
+ * @param firstIndex The index of the first block of the subspace
+ * @param blockSize The size of blocks in this space
+ * @param blockNum The number of blocks in this subspace
+ */
+ public Subspace(Address start,
+ Address end,
+ int firstIndex,
+ int blockSize,
+ int blockNum) {
+ reset(start, end, firstIndex, blockSize, blockNum);
+ }
+
+
+ //------------------Methods to reset a subspace----------------------
+
+ /**
+ * Reset a subspace.
+ *
+ * @param start The address of the start of the subspace
+ * @param end The address of the end of the subspace
+ * @param firstIndex The index of the first block of the subspace
+ * @param blockSize The size of blocks in this subspace
+ * @param blockNum The number of blocks in this subspace
+ */
+ private void reset(Address start,
+ Address end,
+ int firstIndex,
+ int blockSize,
+ int blockNum) {
+ //TODO sanity check on addresses and block size and number
+ reset(start, end, firstIndex, blockNum);
+ blockSize_ = blockSize;
+
+ if (DEBUG) dump();
+ }
+
+ /**
+ * Reset a new subspace
+ *
+ * @param start The address of the start of the subspace
+ * @param end The address of the end of the subspace
+ * @param firstIndex The index of the first block of the subspace
+ * @param blockNum The number of blocks in this subspace
+ */
+ public void reset(Address start,
+ Address end,
+ int firstIndex,
+ int blockNum) {
+ start_ = start;
+ end_ = end;
+ firstIndex_ = firstIndex;
+ blockNum_ = blockNum;
+ }
+
+ /**
+ * Reset a new subspace.
+ *
+ * @param start The address of the start of the subspace
+ * @param end The address of the end of the subspace
+ * @param blockNum The number of blocks in this subspace
+ */
+ public void reset(Address start, Address end, int blockNum) {
+ start_ = start;
+ end_ = end;
+ blockNum_ = blockNum;
+ }
+
+ /**
+ * Reset a new subspace.
+ *
+ * @param firstIndex The index of the first block of the subspace
+ * @param blockNum The number of blocks in this subspace
+ */
+ public void reset(int firstIndex, int blockNum) {
+ firstIndex_ = firstIndex;
+ blockNum_ = blockNum;
+ }
+
+
+ //----------------Facilities to query a subspace-----------------
+
+ /**
+ * Is an index in the range of this subspace?
+ *
+ * @param index The index of the block
+ * @return true if this block lies in this subspace
+ */
+ public boolean indexInRange(int index) {
+ return index >= firstIndex_ &&
+ index < firstIndex_ + blockNum_;
+ }
+
+ /**
+ * Is address in the range of this subspace?
+ *
+ * @param addr An address
+ * @return true if this address is in a block in this subspace
+ */
+ public boolean addressInRange(Address addr) {
+ return addr.GE(start_) && addr.LT(end_);
+ }
+
+
+ /**
+ * Get the block index from an address
+ *
+ * @param addr The address
+ * @return The index of the block holding this address
+ */
+ public int getIndex(Address addr) {
+ if (DEBUG) {
+ Log.write("start_ ", start_);
+ Log.write(" end_ ", end_);
+ Log.write(" blockSize_ ", blockSize_);
+ Log.write(" firstIndex_ ", firstIndex_);
+ Log.write(" + ", addr.diff(start_).toInt() / blockSize_);
+ Log.writeln(" addr ", addr);
+ }
+ return firstIndex_ + addr.diff(start_).toInt() / blockSize_;
+ }
+
+ /**
+ * Get the address of start of block from its index
+ *
+ * @param index The index of the block
+ * @return The address of the start of the block
+ */
+ public Address getAddress(int index) {
+ return start_.plus(index - firstIndex_ * blockSize_);
+ }
+
+ //--------------Accessors-------------------------
+
+ /**
+ * Get the start of the subspace
+ * @return The start of this subspace
+ */
+ public Address getStart() { return start_; }
+
+ /**
+ * Get the end of this subspace
+ * @return The address of the end of this subspace
+ */
+ public Address getEnd() { return end_; }
+
+ /**
+ * Get the first index of subspace
+ * @return the firstIndex of this subspace
+ */
+ public int getFirstIndex() { return firstIndex_; }
+
+ /**
+ * Get the blocksize for this subspace
+ * @return The size of a tile
+ */
+ public int getBlockSize() { return blockSize_; }
+
+ /**
+ * Get the number of tiles in this subspace
+ * @return The number of tiles in this subspace
+ */
+ public int getBlockNum() { return blockNum_; }
+
+ /**
+ * Calculate the space remaining in a block after this address
+ *
+ * @param addr the Address
+ * @return the remainder
+ */
+ public int spaceRemaining(Address addr) {
+ int nextIndex = getIndex(addr) + 1;
+ Address nextTile = start_.plus(blockSize_ * (nextIndex - firstIndex_));
+ return nextTile.diff(addr).toInt();
+ }
+
+ /**
+ * Dump a representation of the subspace
+ */
+ private void dump() {
+ Log.write("GCspy Subspace: ");
+ Util.dumpRange(start_, end_);
+ Log.writeln("\n -- firstIndex=", firstIndex_);
+ Log.writeln(" -- blockNum=", blockNum_);
+ }
+}
+
+
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/AbstractDriver.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/AbstractDriver.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/AbstractDriver.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/AbstractDriver.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,502 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.gcspy.drivers;
+
+import org.mmtk.policy.Space;
+import org.mmtk.utility.Log;
+import org.mmtk.utility.gcspy.GCspy;
+import org.mmtk.utility.gcspy.Subspace;
+import org.mmtk.vm.gcspy.ServerSpace;
+import org.mmtk.vm.gcspy.ServerInterpreter;
+import org.mmtk.vm.gcspy.Stream;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * Abstract GCspy driver for MMTk collectors.
+ *
+ * This class implements for the MMTk a base driver for a GCspy space.
+ * All drivers for GCspy spaces should inherit from this class.
+ */
+ at Uninterruptible
+public abstract class AbstractDriver {
+
+ /****************************************************************************
+ *
+ * Class variables
+ */
+
+ // Controls used for tile presentation
+ /** The tile is used */
+ protected static final byte CONTROL_USED = 1;
+ /** The tile is a background tile */
+ protected static final byte CONTROL_BACKGROUND = 2;
+ /** The tile is unused */
+ protected static final byte CONTROL_UNUSED = 4;
+ /** The tile is a separator */
+ protected static final byte CONTROL_SEPARATOR = 8;
+ /** The tile is a link */
+ protected static final byte CONTROL_LINK = 16;
+
+
+ private static final int MAX_STREAMS = 64; // Max number of streams
+
+ private static final boolean DEBUG = false;
+ protected String myClass; // used in debugging messages
+
+
+ /****************************************************************************
+ *
+ * Instance variables
+ */
+
+ /** The owning GCspy server */
+ protected final ServerInterpreter server;
+ /** The name of the GCspy space driver */
+ protected final String name;
+ /** The GCspy space abstraction */
+ protected final ServerSpace serverSpace;
+ /** The MMTK space */
+ protected final Space mmtkSpace;
+ /** The GCspy space's block size */
+ protected int blockSize;
+ /** The maximum number of tiles in this GCspy space */
+ protected int maxTileNum;
+ /** This space's streams */
+ protected Stream[] streams;
+ /** control values for tiles in this space */
+ protected byte[] control;
+ /** Has this space changed? */
+ protected boolean changed = true;
+
+
+ /**
+ * Create a new driver for this collector.
+ *
+ * @param server The ServerInterpreter that owns this GCspy space.
+ * @param name The name of this driver.
+ * @param mmtkSpace The MMTk space represented by this driver.
+ * @param blockSize The tile size.
+ * @param mainSpace Is this the main space?
+ */
+ public AbstractDriver(ServerInterpreter server,
+ String name,
+ Space mmtkSpace,
+ int blockSize,
+ boolean mainSpace) {
+ this.server = server;
+ this.name = name;
+ this.mmtkSpace = mmtkSpace;
+ this.blockSize = blockSize;
+ myClass = getClass().getName();
+ maxTileNum = countTileNum(mmtkSpace.getExtent(), blockSize);
+ control = (byte[])GCspy.util.createDataArray(new byte[0], maxTileNum);
+ // to avoid allocation during GC we preallocate the streams array
+ streams = new Stream[MAX_STREAMS];
+ serverSpace = createServerSpace(server, name, maxTileNum, mainSpace);
+ }
+
+ /**
+ * Create a subspace for this space.
+ * Subspace provide useful facilities for contiguous spaces, even if
+ * a space contains only one.
+ * @param mmtkSpace The MMTk space
+ */
+ @Interruptible
+ protected Subspace createSubspace(Space mmtkSpace) {
+ Address start = mmtkSpace.getStart();
+ return new Subspace(start, start, 0, blockSize, 0);
+ }
+
+ /**
+ * Create a new GCspy ServerSpace and add it to the ServerInterpreter.
+ * @param server the GCspy ServerInterpreter.
+ * @param spaceName The name of this driver.
+ * @param maxTileNum the maximum number of tiles in this space.
+ * @param mainSpace Is this the main space?
+ */
+ @Interruptible
+ protected ServerSpace createServerSpace(ServerInterpreter server,
+ String spaceName,
+ int maxTileNum,
+ boolean mainSpace) {
+ // Set the block label
+ String tmp = "Block Size: " + ((blockSize < 1024) ?
+ blockSize + " bytes\n":
+ (blockSize / 1024) + " Kbytes\n");
+
+ // Create a single GCspy Space
+ return VM.newGCspyServerSpace(server, // the server
+ spaceName, // space name
+ getDriverName(), // driver (space) name
+ "Block ", // space title
+ tmp, // block info
+ maxTileNum, // number of tiles
+ "UNUSED", // the label for unused blocks
+ mainSpace); // main space
+ }
+
+ /**
+ * Get the name of this driver type.
+ * @return The name of this driver.
+ */
+ protected abstract String getDriverName();
+
+ /**
+ * Get the maximum number of tiles in this space.
+ * @return the maximum number of tiles in the space.
+ */
+ public int getMaxTileNum() {
+ return maxTileNum;
+ }
+
+ /**
+ * The GCspy space managed by this driver.
+ * @return the GCspy server space.
+ */
+ public ServerSpace getServerSpace() { return serverSpace; }
+
+ /**
+ * Add a stream to the driver. This also sets the stream's id
+ * (unique for this space).
+ * @param stream The stream
+ * @exception IndexOutOfBoundsException if more than MAX_STREAMS are added
+ */
+ @Interruptible
+ public void addStream(Stream stream) {
+ int id = 0;
+ while (id < MAX_STREAMS) {
+ if (streams[id] == null) {
+ streams[id] = stream;
+ if (DEBUG) { Log.write("Adding stream with id="); Log.writeln(id); }
+ Address stream_ = serverSpace.addStream(id);
+ stream.setStream(id, stream_);
+ return;
+ }
+ id++;
+ }
+ throw new IndexOutOfBoundsException("Too many streams added to driver "+name);
+ }
+
+ /**
+ * Count number of tiles in an address range.
+ * @param start The start of the range.
+ * @param end The end of the range.
+ * @param tileSize The size of each tile.
+ * @return The number of tiles in this range.
+ */
+ protected int countTileNum(Address start, Address end, int tileSize) {
+ if (end.LE(start)) return 0;
+ int diff = end.diff(start).toInt();
+ return countTileNum(diff, tileSize);
+ }
+
+ /**
+ * Count number of tiles in an address range.
+ * @param extent The extent of the range.
+ * @param tileSize The size of each tile.
+ * @return The number of tiles in this range.
+ */
+ protected int countTileNum(Extent extent, int tileSize) {
+ int diff = extent.toInt();
+ return countTileNum(diff, tileSize);
+ }
+
+ private int countTileNum(int diff, int tileSize) {
+ int tiles = diff / tileSize;
+ if ((diff % tileSize) != 0)
+ ++tiles;
+ return tiles;
+ }
+
+ /**
+ * Indicate the limits of a space.
+ *
+ * @param start the Address of the start of the space.
+ * @param end the Address of the end of the space.
+ */
+ public void setRange(Address start, Address end) {}
+
+ /**
+ * Indicate the limits of a space.
+ *
+ * @param start the Address of the start of the space.
+ * @param extent the extent of the space.
+ */
+ public void setRange(Address start, Extent extent) {
+ setRange(start, start.plus(extent));
+ }
+
+ /**
+ * Setup the tile names in a subspace. Tile names are typically
+ * address ranges but may be anything (e.g. a size class if the
+ * space is a segregated free-list manager, or a class name if the
+ * space represents the class instances loaded).
+ *
+ * @param subspace the Subspace
+ * @param numTiles the number of tiles to name
+ */
+ protected void setTilenames(Subspace subspace, int numTiles) {
+ Address start = subspace.getStart();
+ int first = subspace.getFirstIndex();
+ int bs = subspace.getBlockSize();
+
+ for (int i = 0; i < numTiles; ++i) {
+ if (subspace.indexInRange(i))
+ serverSpace.setTilename(i, start.plus((i - first) * bs),
+ start.plus((i + 1 - first) * bs));
+ }
+ }
+
+ /**
+ * The "typical" maximum number of objects in each tile.
+ * @param blockSize The size of a tile
+ * @return The maximum number of objects in a tile
+ */
+ public int maxObjectsPerBlock(int blockSize) {
+ // Maybe a misuse of ServerInterpreter but it's a convenient
+ // VM-dependent class
+ return blockSize / GCspy.server.computeHeaderSize();
+ }
+
+ /**
+ * Is the server connected to a GCspy client?
+ * @param event The current event
+ */
+ public boolean isConnected(int event) {
+ return server.isConnected(event);
+ }
+
+ /**
+ * Reset the statistics for a space.
+ * In this base driver, we simply note that the data has changed.
+ */
+ protected void resetData() { changed = true; }
+
+ /**
+ * Scan an object found at a location.
+ * Collectors typically call this method to update GCspy statistics.
+ * The driver may or may not accumulate values found, depending on
+ * the value of total.
+ * @param obj the reference to the object found
+ * @param total Whether to total the statistics
+ */
+ public void scan(ObjectReference obj, boolean total) {}
+
+ /**
+ * Scan an object found at a location.
+ * Collectors typically call this method to update GCspy statistics
+ * The driver will accumulate values found.
+ * @param obj the reference to the object found
+ */
+ public void scan(ObjectReference obj) { scan(obj, true); }
+
+ /**
+ * Scan an object found at a location.
+ * Collectors typically call this method to update GCspy statistics.
+ * The driver may or may not accumulate values found, depending on
+ * the value of total.
+ * @param obj the reference to the object found
+ * @param total Whether to total the statistics
+ */
+ public void scan(Address obj, boolean total) {}
+
+ /**
+ * Scan an object found at a location.
+ * Collectors typically call this method to update GCspy statistics
+ * The driver will accumulate values found.
+ * @param obj the reference to the object found
+ */
+ public void scan(Address obj) {}
+
+ /**
+ * Handle a direct reference from the immortal space.<p>
+ * This is an empty implementation. Subclasses may override this method
+ * to increment their <code>refFromImmortal</code> Stream.
+ *
+ * @param addr The Address
+ * @return true if the given Address is in this subspace. Always false here.
+ */
+ public boolean handleReferenceFromImmortalSpace(Address addr) {
+ return false;
+ }
+
+ /**
+ * Set space info.
+ * This simply reports the size of the current space.
+ * Drivers that want to send something more complex than
+ * "Current Size: size\n"
+ * must override this method.
+ *
+ * @param size the size of the space
+ */
+ protected void setSpaceInfo(Offset size) {
+ // - sprintf(tmp, "Current Size: %s\n", gcspy_formatSize(size));
+ Address tmp = GCspy.util.formatSize("Current Size: %s\n", 128, size.toInt());
+ serverSpace.spaceInfo(tmp);
+ GCspy.util.free(tmp);
+ }
+
+
+ /****************************************************************************
+ *
+ * Control values
+ */
+
+ /**
+ * Is a tile used?
+ * @param val the control value.
+ * @return true if the tile is used
+ */
+ protected static boolean controlIsUsed(byte val) {
+ return (val & CONTROL_USED) != 0;
+ }
+
+ /**
+ * Is a tile a background pseudo-tile?
+ * @param val the control value.
+ * @return true if the tile is a background tile
+ */
+ protected static boolean controlIsBackground(byte val) {
+ return (val & CONTROL_BACKGROUND) != 0;
+ }
+
+ /**
+ * Is a tile unused?
+ * @param val the control value.
+ * @return true if the tile is unused
+ */
+ protected static boolean controlIsUnused(byte val) {
+ return (val & CONTROL_UNUSED) != 0;
+ }
+
+ /**
+ * Is this a separator?
+ * @param val the control value.
+ * @return true if this is a separator
+ */
+ protected static boolean controlIsSeparator(byte val) {
+ return (val & CONTROL_SEPARATOR) != 0;
+ }
+
+ /**
+ * Initialise the value of a control.
+ * @param index The index of the tile.
+ * @param value The new value of the control
+ */
+ protected void initControl(int index, byte value) {
+ control[index] = value;
+ }
+
+ /**
+ * Add a control to the tile
+ * @param index The index of the tile.
+ * @param value The control to add.
+ */
+ protected void addControl(int index, byte value) {
+ control[index] |= value;
+ }
+
+ /** Set the control
+ * @param value The value to set
+ */
+ protected void setControl(int index, byte value) {
+ control[index] &= value;
+ }
+
+ /**
+ * Get the controls for a tile.
+ * @param index The index of the tile.
+ * @return The value of the controls
+ */
+ public byte getControl(int index) {
+ return control[index];
+ }
+
+ /**
+ * Initialise control values in all tiles
+ */
+ protected void initControls() {
+ for (int index = 0; index < control.length; ++index) {
+ initControl(index, CONTROL_USED);
+ }
+ }
+
+ /**
+ * Set the control value in each tile in a region.
+ * @param tag The control tag.
+ * @param start The start index of the region.
+ * @param len The number of tiles in the region.
+ */
+ protected void controlValues(byte tag, int start, int len) {
+ if (DEBUG) {
+ Log.write("AbstractDriver.controlValues for space ");
+ Log.write(name);
+ Log.write(", control length=", control.length);
+ Log.write(" writing controls from ", start);
+ Log.writeln(" to ", start + len);
+ }
+ changed = true;
+ for (int i = start; i < (start+len); ++i) {
+ // Cannot be both USED and UNUSED or BACKGROUND
+ if (controlIsBackground(tag) || controlIsUnused(tag))
+ setControl(i, (byte)~CONTROL_USED);
+ else if (controlIsUsed(tag))
+ setControl(i, (byte)~CONTROL_UNUSED);
+ addControl(i, tag);
+ }
+ }
+
+ /**
+ * Transmit the streams for this space. A driver will typically
+ * <ol>
+ * <li> Determine whether a GCspy client is connected and interested in
+ * this event, e.g.
+ * <pre>server.isConnected(event)</pre>
+ * <li> Setup the summaries for each stream, e.g.
+ * <pre>stream.setSummary(values...);</pre>
+ * <li> Setup the control information for each tile. e.g.
+ * <pre>controlValues(CONTROL_USED, start, numBlocks);</pre>
+ * <pre>controlValues(CONTROL_UNUSED, end, remainingBlocks);</pre>
+ * <li> Set up the space information, e.g.
+ * <pre>setSpace(info);</pre>
+ * <li> Send the data for all streams, e.g.
+ * <pre>send(event, numTiles);</pre>
+ * Note that AbstractDriver.send takes care of sending the information
+ * for all streams (including control data).
+ *
+ * @param event The event
+ */
+ public abstract void transmit(int event);
+
+ /**
+ * Send all the streams for this space if it has changed.
+ * Assume that the data has been gathered and that summary info
+ * and control values have been set before this is called.
+ *
+ * @param event the event
+ * @param numTiles the number of blocks in this space
+ */
+ protected void send(int event, int numTiles) {
+ if (changed) {
+ serverSpace.startCommunication();
+ for (int i = 0; i < MAX_STREAMS; i++)
+ if (streams[i] != null)
+ streams[i].send(event, numTiles);
+ serverSpace.sendControls(this, numTiles);
+ serverSpace.endCommunication();
+ }
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/GenImmortalSpaceDriver.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/GenImmortalSpaceDriver.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/GenImmortalSpaceDriver.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/GenImmortalSpaceDriver.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,144 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.gcspy.drivers;
+
+import org.mmtk.policy.Space;
+
+import org.mmtk.utility.gcspy.Color;
+import org.mmtk.utility.gcspy.StreamConstants;
+import org.mmtk.vm.VM;
+import org.mmtk.vm.gcspy.ShortStream;
+
+import org.mmtk.utility.Log;
+import org.mmtk.vm.gcspy.ServerInterpreter;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * GCspy driver for the MMTk generational immortal space.
+ * Additional Stream for remset references.
+ * This class extends ImmortalSpaceDriver, a simple driver for
+ * the contiguous MMTk ImmortalSpace.
+ */
+ at Uninterruptible public class GenImmortalSpaceDriver extends ImmortalSpaceDriver {
+
+ private static final boolean DEBUG = false;
+
+ // The Stream for newly promoted objects
+ protected ShortStream remsetStream;
+ // Statistics for remset references
+ protected int totalRemset = 0;
+
+
+ /**
+ * Create a new driver for a generational immortal space.
+ *
+ * @param server The GCspy ServerInterpreter
+ * @param spaceName The name of this GCspy space
+ * @param mmtkSpace The MMTk space
+ * @param blockSize The tile size
+ * @param mainSpace Is this the main space?
+ */
+ public GenImmortalSpaceDriver(
+ ServerInterpreter server,
+ String spaceName,
+ Space mmtkSpace,
+ int blockSize,
+ boolean mainSpace) {
+
+ super(server, spaceName, mmtkSpace, blockSize, mainSpace);
+
+ // create additional stream
+ remsetStream = createRemsetStream();
+
+ if (DEBUG) {
+ Log.write("GenImmortalSpaceDriver for "); Log.write(spaceName);
+ Log.write(", blocksize="); Log.write(blockSize);
+ Log.write(", start="); Log.write(mmtkSpace.getStart());
+ Log.write(", extent="); Log.write(mmtkSpace.getExtent());
+ Log.write(", maxTileNum="); Log.writeln(maxTileNum);
+ }
+
+ resetData();
+ }
+
+ /**
+ * Get the name of this driver type.
+ * @return The name, "MMTk GenImmortalSpaceDriver" for this driver.
+ */
+ protected String getDriverName() {
+ return "MMTk GenImmortalSpaceDriver";
+ }
+
+ /**
+ * Heelper methods to create the additional streams
+ */
+ @Interruptible
+ private ShortStream createRemsetStream() {
+ return VM.newGCspyShortStream(
+ this,
+ "Remembered set stream",
+ (short)0,
+ // Say, typical size = 4 * typical scalar size?
+ (short)(maxObjectsPerBlock(blockSize)/8),
+ (short)0,
+ (short)0,
+ "Remset references: ",
+ " references",
+ StreamConstants.PRESENTATION_PLUS,
+ StreamConstants.PAINT_STYLE_ZERO,
+ 0,
+ Color.Cyan,
+ true);
+ }
+
+ /**
+ * Setup summaries part of the <code>transmit</code> method.<p>
+ * Overrides method in superclass to handle additional Stream.
+ */
+ protected void setupSummaries() {
+ super.setupSummaries();
+ remsetStream.setSummary(totalRemset);
+ }
+
+ /**
+ * Handle a remset address
+ *
+ * @param addr Remset Address
+ * @return true if the given Address is in this subspace.
+ */
+ public boolean handleRemsetAddress(Address addr) {
+ if(subspace.addressInRange(addr)) {
+ // increment tile
+ int index = subspace.getIndex(addr);
+ remsetStream.increment(index, (short)1);
+ // increment summary
+ totalRemset++;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Reset the remset Stream
+ * The remset Stream has to be reset seperately because we do not
+ * gather data in the usual way using scan().
+ */
+ public void resetRemsetStream() {
+ remsetStream.resetData();
+ totalRemset = 0;
+ }
+
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/GenLOSDriver.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/GenLOSDriver.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/GenLOSDriver.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/GenLOSDriver.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,132 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.gcspy.drivers;
+
+import org.mmtk.utility.gcspy.Color;
+import org.mmtk.utility.gcspy.StreamConstants;
+import org.mmtk.vm.VM;
+import org.mmtk.vm.gcspy.ShortStream;
+import org.mmtk.vm.gcspy.ServerInterpreter;
+
+import org.mmtk.policy.LargeObjectSpace;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+
+/**
+ * This class extends a simple driver for the MMTk LargeObjectSpace
+ * for Generational Collectors.
+ */
+ at Uninterruptible public class GenLOSDriver extends TreadmillDriver {
+
+ private static final boolean DEBUG = false;
+
+ // The additional remset stream
+ protected ShortStream remsetStream;
+ // Additional overall statistic
+ protected int totalRemset = 0; // total of remset Addresses
+
+
+ /**
+ * Create a new driver for this collector
+ *
+ * @param server The name of the GCspy server that owns this space
+ * @param spaceName The name of this driver
+ * @param lospace the large object space for this allocator
+ * @param blockSize The tile size
+ * @param threshold the size threshold of the LOS
+ * @param mainSpace Is this the main space?
+ */
+ public GenLOSDriver(ServerInterpreter server,
+ String spaceName,
+ LargeObjectSpace lospace,
+ int blockSize,
+ int threshold,
+ boolean mainSpace) {
+ //TODO blocksize should be a multiple of treadmill granularity
+ super(server, spaceName, lospace, blockSize, threshold, mainSpace);
+ // create remset stream
+ remsetStream = createRemsetStream();
+ // Initialise the statistics
+ resetData();
+ }
+
+ /**
+ * Get the name of this driver type.
+ * @return The name, "MMTk GenLOSDriver" for this driver.
+ */
+ protected String getDriverName() {
+ return "MMTk GenLOSDriver";
+ }
+
+ // private creator methods for the streams
+ @Interruptible
+ private ShortStream createRemsetStream() {
+ return VM.newGCspyShortStream(
+ this,
+ "Remembered set stream",
+ (short)0,
+ // Say, typical size = 4 * typical scalar size?
+ (short)(maxObjectsPerBlock(blockSize)/8),
+ (short)0,
+ (short)0,
+ "Remset references: ",
+ " references",
+ StreamConstants.PRESENTATION_PLUS,
+ StreamConstants.PAINT_STYLE_ZERO,
+ 0,
+ Color.Cyan,
+ true);
+ }
+
+ /**
+ * Setup summaries part of the <code>transmit</code> method.<p>
+ * Overrides <code>transmitSetupSummaries </code> of superclass to
+ * handle additional streams.
+ */
+ protected void setupSummaries() {
+ super.setupSummaries();
+ remsetStream.setSummary(totalRemset);
+ }
+
+ /**
+ * Handle a remset address.
+ *
+ * @param addr Remset Address
+ * @return true if the given Address is in this subspace.
+ */
+ public boolean handleRemsetAddress(Address addr) {
+ if(subspace.addressInRange(addr)) {
+ // increment tile
+ int index = subspace.getIndex(addr);
+ remsetStream.increment(index, (short)1);
+ // increment summary
+ this.totalRemset++;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Reset the remset Stream. <p>
+ * The remset Stream has to be reset seperately because we do not
+ * gather data in the usual way using <code>scan()</code>.
+ */
+ public void resetRemsetStream() {
+ remsetStream.resetData();
+ totalRemset = 0;
+ }
+
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/ImmortalSpaceDriver.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/ImmortalSpaceDriver.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/ImmortalSpaceDriver.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/ImmortalSpaceDriver.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.utility.gcspy.drivers;
+
+import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.Log;
+import org.mmtk.vm.gcspy.ServerInterpreter;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * GCspy driver for the contiguous MMTk ImmortalSpace.
+ * Adds features for the Immortal space.
+ * <p>
+ *
+ * This class extends LinearSpaceDriver, a simple driver for contiguous MMTk spaces
+ * such as CopySpace and ImmortalSpace.
+ */
+ at Uninterruptible public class ImmortalSpaceDriver extends LinearSpaceDriver {
+
+ private static final boolean DEBUG = false;
+
+ // Instance variables
+ private AbstractDriver[] registeredDrivers;
+ private ImmortalSpaceDriver.Closure closure;
+
+ /**
+ * Create a new driver for an immortal Contiguous MMTk space.
+ *
+ * @param server The GCspy ServerInterpreter
+ * @param spaceName The name of this GCspy space
+ * @param mmtkSpace The MMTk space
+ * @param blockSize The tile size
+ * @param mainSpace Is this the main space?
+ */
+ public ImmortalSpaceDriver(
+ ServerInterpreter server,
+ String spaceName,
+ Space mmtkSpace,
+ int blockSize,
+ boolean mainSpace) {
+
+ super(server, spaceName, mmtkSpace, blockSize, mainSpace);
+
+ if (DEBUG) {
+ Log.write("ImmortalSpaceDriver for "); Log.write(spaceName);
+ Log.write(", blocksize="); Log.write(blockSize);
+ Log.write(", start="); Log.write(mmtkSpace.getStart());
+ Log.write(", extent="); Log.write(mmtkSpace.getExtent());
+ Log.write(", maxTileNum="); Log.writeln(maxTileNum);
+ }
+
+ // initially no registered drivers for reference notification
+ registeredDrivers = new AbstractDriver[0];
+
+ closure = new ImmortalSpaceDriver.Closure();
+ }
+
+ /**
+ * Get the name of this driver type.
+ * @return The name, "MMTk ImmortalSpaceDriver" for this driver.
+ */
+ protected String getDriverName() {
+ return "MMTk ImmortalSpaceDriver";
+ }
+
+ /**
+ * Update the tile statistics. <br>
+ * This method overrides <code> scan </code> iin its superclass to
+ * add immortal space features.
+ *
+ * @param object The current object
+ * @param total Whether to accumulate the values
+ */
+ public void scan(ObjectReference object, boolean total) {
+ Address addr = object.toAddress();
+
+ if (subspace.addressInRange(addr)) {
+ VM.scanning.scanObject(closure, object);
+ super.scan(object, total);
+ }
+ }
+
+ /**
+ * Register a set of AbstractDriver instances to be notified about direct references.
+ *
+ * @param drivers The array of driver objects.
+ */
+ public void registerDriversForReferenceNotification(AbstractDriver[] drivers) {
+ this.registeredDrivers = drivers;
+ }
+
+ /**
+ * Used to visit the edges in the immortal object.
+ */
+ @Uninterruptible
+ private class Closure extends TransitiveClosure {
+ /**
+ * Process an edge.
+ */
+ public void processEdge(ObjectReference source, Address slot) {
+ // Address in Range, locate references
+ Address target = slot.loadAddress();
+ // notify registered drivers
+ for (int j = 0; j < registeredDrivers.length; j++) {
+ registeredDrivers[j].handleReferenceFromImmortalSpace(target);
+ }
+ }
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/LinearSpaceDriver.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/LinearSpaceDriver.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/LinearSpaceDriver.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/LinearSpaceDriver.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,508 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.gcspy.drivers;
+
+import org.mmtk.policy.Space;
+import org.mmtk.utility.gcspy.Color;
+import org.mmtk.utility.gcspy.LinearScan;
+import org.mmtk.utility.gcspy.StreamConstants;
+import org.mmtk.utility.gcspy.Subspace;
+import org.mmtk.vm.gcspy.IntStream;
+import org.mmtk.vm.gcspy.ShortStream;
+
+import org.mmtk.utility.Log;
+import org.mmtk.vm.gcspy.ServerInterpreter;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * GCspy driver for the MMTk ContigousSpace.
+ *
+ * This class implements a simple driver for contiguous MMTk spaces
+ * such as CopySpace and ImmortalSpace.
+ */
+ at Uninterruptible public class LinearSpaceDriver extends AbstractDriver {
+
+ // The GCspy streams
+ protected IntStream scalarUsedSpaceStream;
+ protected IntStream arrayUsedSpaceStream;
+ protected ShortStream scalarObjectsStream;
+ protected ShortStream arrayObjectsStream;
+ protected ShortStream arrayPrimitiveStream;
+ protected ShortStream rootsStream;
+ protected ShortStream refFromImmortalStream;
+
+ protected Subspace subspace; // A subspace for all of this space
+ protected int allTileNum; // total number of tiles
+
+ // Overall statistics
+ protected int totalScalarObjects = 0; // total number of objects allocated
+ protected int totalArrayObjects = 0;
+ protected int totalPrimitives = 0;
+ protected int totalScalarUsedSpace = 0; // total space used
+ protected int totalArrayUsedSpace = 0;
+ protected int totalRoots = 0;
+ protected int totalRefFromImmortal = 0;
+
+ private final LinearScan scanner; // A scanner to trace objects
+
+ // Debugging
+ protected Address lastAddress = Address.zero();
+ protected int lastSize = 0;
+ private static final boolean DEBUG = false;
+
+
+ /**
+ * Create a new driver for a contiguous MMTk space.
+ *
+ * @param server The GCspy ServerInterpreter
+ * @param spaceName The name of this GCspy space
+ * @param mmtkSpace The MMTk space
+ * @param blockSize The tile size
+ * @param mainSpace Is this the main space?
+ */
+ public LinearSpaceDriver(ServerInterpreter server,
+ String spaceName,
+ Space mmtkSpace,
+ int blockSize,
+ boolean mainSpace) {
+
+ super(server, spaceName, mmtkSpace, blockSize, mainSpace);
+
+ if (DEBUG) {
+ Log.write("LinearSpaceDriver for "); Log.write(spaceName);
+ Log.write(", blocksize="); Log.write(blockSize);
+ Log.write(", start="); Log.write(mmtkSpace.getStart());
+ Log.write(", extent="); Log.write(mmtkSpace.getExtent());
+ Log.write(", maxTileNum="); Log.writeln(maxTileNum);
+ }
+
+ // Initialise a subspace and 4 Streams
+ subspace = createSubspace(mmtkSpace);
+ allTileNum = 0;
+ scalarUsedSpaceStream = createScalarUsedSpaceStream();
+ arrayUsedSpaceStream = createArrayUsedSpaceStream();
+ scalarObjectsStream = createScalarObjectsStream();
+ arrayPrimitiveStream = createArrayPrimitiveStream();
+ arrayObjectsStream = createArrayObjectsStream();
+ rootsStream = createRootsStream();
+ refFromImmortalStream = createRefFromImmortalStream();
+ serverSpace.resize(0); // the collector must call resize() before gathering data
+
+ // Initialise the statistics
+ resetData();
+ scanner = new LinearScan(this);
+ }
+
+ /**
+ * Get the name of this driver type.
+ * @return The name of this driver.
+ */
+ protected String getDriverName() { return "MMTk LinearSpaceDriver"; }
+
+ /**
+ * Private creator methods to create the Streams.
+ */
+ @Interruptible
+ private IntStream createScalarUsedSpaceStream() {
+ return VM.newGCspyIntStream(
+ this,
+ "Scalar Used Space stream", // stream name
+ 0, // min. data value
+ blockSize, // max. data value
+ 0, // zero value
+ 0, // default value
+ "Scalars and primitive arrays: ", // value prefix
+ " bytes", // value suffix
+ StreamConstants.PRESENTATION_PERCENT, // presentation style
+ StreamConstants.PAINT_STYLE_ZERO, // paint style
+ 0, // index of max stream (only needed if the presentation is *_VAR)
+ Color.Red, // tile colour
+ true); // summary enabled
+ }
+
+ @Interruptible
+ private IntStream createArrayUsedSpaceStream() {
+ return VM.newGCspyIntStream(
+ this,
+ "Array Used Space stream",
+ 0,
+ blockSize,
+ 0,
+ 0,
+ "Reference arrays: ",
+ " bytes",
+ StreamConstants.PRESENTATION_PERCENT,
+ StreamConstants.PAINT_STYLE_ZERO,
+ 0,
+ Color.Blue,
+ true);
+ }
+
+ @Interruptible
+ private ShortStream createScalarObjectsStream() {
+ return VM.newGCspyShortStream(
+ this,
+ "Scalar Objects stream",
+ (short)0,
+ // Say, max value = 50% of max possible
+ (short)(maxObjectsPerBlock(blockSize)/2),
+ (short)0,
+ (short)0,
+ "Scalars: ",
+ " objects",
+ StreamConstants.PRESENTATION_PLUS,
+ StreamConstants.PAINT_STYLE_ZERO,
+ 0,
+ Color.Green,
+ true);
+ }
+
+ @Interruptible
+ private ShortStream createArrayPrimitiveStream() {
+ return VM.newGCspyShortStream(
+ this,
+ "Array Primitive stream",
+ (short)0,
+ // Say, typical primitive array size = 4 * typical scalar size?
+ (short)(maxObjectsPerBlock(blockSize)/8),
+ (short)0,
+ (short)0,
+ "Primitive arrays: ",
+ " objects",
+ StreamConstants.PRESENTATION_PLUS,
+ StreamConstants.PAINT_STYLE_ZERO,
+ 0,
+ Color.Yellow,
+ true);
+ }
+
+ @Interruptible
+ private ShortStream createArrayObjectsStream() {
+ return VM.newGCspyShortStream(
+ this,
+ "Array Objects stream",
+ (short)0,
+ // Say, typical ref array size = 4 * typical scalar size?
+ (short)(maxObjectsPerBlock(blockSize)/8),
+ (short)0,
+ (short)0,
+ "Reference arrays: ",
+ " objects",
+ StreamConstants.PRESENTATION_PLUS,
+ StreamConstants.PAINT_STYLE_ZERO,
+ 0,
+ Color.Cyan,
+ true);
+ }
+
+ @Interruptible
+ private ShortStream createRootsStream() {
+ return VM.newGCspyShortStream(
+ this,
+ "Roots stream",
+ (short)0,
+ // Say, typical size = 4 * typical scalar size?
+ (short)(maxObjectsPerBlock(blockSize)/8),
+ (short)0,
+ (short)0,
+ "Roots: ",
+ " objects",
+ StreamConstants.PRESENTATION_PLUS,
+ StreamConstants.PAINT_STYLE_ZERO,
+ 0,
+ Color.Blue,
+ true);
+ }
+
+ @Interruptible
+ private ShortStream createRefFromImmortalStream() {
+ return VM.newGCspyShortStream(
+ this,
+ "References from immortal stream",
+ (short)0,
+ // Say, typical size = 4 * typical scalar size?
+ (short)(maxObjectsPerBlock(blockSize)/8),
+ (short)0,
+ (short)0,
+ "References from immortal space: ",
+ " references",
+ StreamConstants.PRESENTATION_PLUS,
+ StreamConstants.PAINT_STYLE_ZERO,
+ 0,
+ Color.Blue,
+ true);
+ }
+
+ /**
+ * Reset the statistics for all the streams, including totals used for summaries
+ */
+ public void resetData() {
+ super.resetData();
+
+ // Reset all the streams
+ scalarUsedSpaceStream.resetData();
+ arrayUsedSpaceStream.resetData();
+ scalarObjectsStream.resetData();
+ arrayObjectsStream.resetData();
+ arrayPrimitiveStream.resetData();
+ refFromImmortalStream.resetData();
+
+ // Reset the summary counts
+ totalScalarObjects = 0;
+ totalArrayObjects = 0;
+ totalPrimitives = 0;
+ totalScalarUsedSpace = 0;
+ totalArrayUsedSpace = 0;
+ totalRefFromImmortal = 0;
+ }
+
+ /**
+ * BumpPointer.linearScan needs a LinearScan object, which we provide here.
+ * @return the scanner for this driver
+ */
+ public LinearScan getScanner() { return scanner; }
+
+ /**
+ * Set the current address range of a contiguous space
+ * @param start the start of the contiguous space
+ * @param end the end of the contiguous space
+ */
+ public void setRange(Address start, Address end) {
+ int current = subspace.getBlockNum();
+ int required = countTileNum(start, end, subspace.getBlockSize());
+
+ // Reset the subspace
+ if(required != current)
+ subspace.reset(start, end, 0, required);
+
+ if (DEBUG) {
+ Log.write("\nContiguousSpaceDriver.setRange for contiguous space: ");
+ Log.write(subspace.getFirstIndex()); Log.write("-", subspace.getBlockNum());
+ Log.write(" (", start); Log.write("-", end); Log.write(")");
+ }
+
+ // Reset the driver
+ // Note release() only resets a CopySpace's cursor (and optionally zeroes
+ // or mprotects the pages); it doesn't make the pages available to other
+ // spaces. If pages were to be released, change the test here to
+ // if (allTileNum != required) {
+ if (allTileNum < required) {
+ if (DEBUG) { Log.write(", resize from ", allTileNum); Log.write(" to ", required); }
+ allTileNum = required;
+ serverSpace.resize(allTileNum);
+ setTilenames(subspace, allTileNum);
+ }
+ if (DEBUG) Log.writeln();
+ }
+
+
+ /**
+ * Update the tile statistics
+ * @param obj The current object
+ */
+ public void scan(ObjectReference obj) {
+ scan(obj, true);
+ }
+
+ /**
+ * Update the tile statistics
+ * @param obj The current object
+ * @param total Whether to accumulate the values
+ */
+ public void scan(ObjectReference obj, boolean total) {
+ boolean isArray = VM.objectModel.isArray(obj);
+ int length = VM.objectModel.getCurrentSize(obj);
+ Address addr = obj.toAddress();
+
+ if (VM.VERIFY_ASSERTIONS) {
+ if(addr.LT(lastAddress.plus(lastSize))) {
+ Log.write("\nContiguousSpaceDriver finds addresses going backwards: ");
+ Log.write("last="); Log.write(lastAddress);
+ Log.write(" last size="); Log.write(lastSize);
+ Log.writeln(" current=", addr);
+ }
+ lastAddress = addr;
+ lastSize = length;
+ }
+
+ // Update the stats
+ if (subspace.addressInRange(addr)) {
+ int index = subspace.getIndex(addr);
+ int remainder = subspace.spaceRemaining(addr);
+ if (isArray) {
+ arrayObjectsStream.increment(index, (short)1);
+ arrayUsedSpaceStream.distribute(index, remainder, blockSize, length);
+ if (total) {
+ totalArrayObjects++;
+ totalArrayUsedSpace += length;
+ }
+ } else {
+ if(!this.scanCheckPrimitiveArray(obj, index, total, length)) {
+ // real object
+ scalarObjectsStream.increment(index, (short)1);
+ if (total) {
+ totalScalarObjects++;
+ totalScalarUsedSpace += length;
+ }
+ }
+ scalarUsedSpaceStream.distribute(index, remainder, blockSize, length);
+ }
+ }
+ }
+
+ /**
+ * Check if this Object is an array of primitives.<br>
+ * Part of the public scan() method.
+ *
+ * @param obj The Object to check
+ * @param index Index of the tile
+ * @param total Increment summary
+ * @param length Current size of the Object, will be added to array space summary.
+ * @return True if this Object is an array of primitives.
+ */
+ protected boolean scanCheckPrimitiveArray(ObjectReference obj, int index, boolean total, int length) {
+ if(VM.objectModel.isPrimitiveArray(obj)) {
+ arrayPrimitiveStream.increment(index, (short)1);
+ if (total) {
+ totalPrimitives++;
+ totalScalarUsedSpace += length;
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Transmit the data if this event is of interest to the client.<p>
+ * Implemented using the algorithm pattern, subclasses can override parts of it.
+ * @param event The event, defined in the Plan
+ */
+ public void transmit(int event) {
+ if (!server.isConnected(event))
+ return;
+
+ if (DEBUG) {
+ Log.write("CONNECTED\n");
+ Log.write(myClass);
+ Log.write(".send: numTiles=", allTileNum);
+ //Log.write("LinearSpaceDriver.transmit: numTiles=", allTileNum);
+ Log.writeln(", control.length=", control.length);
+ Log.flush();
+ }
+
+ // Setup the summaries
+ setupSummaries();
+
+ // Setup the control info
+ setupControlInfo();
+
+ // Setup the space info
+ Offset size = subspace.getEnd().diff(subspace.getStart());
+ setSpaceInfo(size);
+
+ // Send the all streams
+ send(event, allTileNum);
+
+ // Debugging
+ if (VM.VERIFY_ASSERTIONS) {
+ lastAddress = Address.zero();
+ lastSize = 0;
+ }
+ }
+
+ /**
+ * Setup summaries part of the <code>transmit</code> method.<p>
+ * Override this method to setup summaries of additional streams in subclasses.
+ */
+ protected void setupSummaries() {
+ scalarUsedSpaceStream.setSummary(totalScalarUsedSpace,
+ subspace.getEnd().diff(subspace.getStart()).toInt());
+ arrayUsedSpaceStream.setSummary(totalArrayUsedSpace,
+ subspace.getEnd().diff(subspace.getStart()).toInt());
+ scalarObjectsStream.setSummary(totalScalarObjects);
+ arrayObjectsStream.setSummary(totalArrayObjects);
+ arrayPrimitiveStream.setSummary(totalPrimitives);
+ rootsStream.setSummary(totalRoots);
+ refFromImmortalStream.setSummary(totalRefFromImmortal);
+ }
+
+ /**
+ * Setup control info part of the <code>transmit</code> method.<p>
+ * Override this method to change the controls for your own driver subclass.
+ */
+ protected void setupControlInfo() {
+ int numBlocks = subspace.getBlockNum();
+ controlValues(CONTROL_USED, subspace.getFirstIndex(), numBlocks);
+ if (DEBUG) {
+ Log.write("LinearSpaceDriver.transmitSetupControlInfo: allTileNum=", allTileNum);
+ Log.writeln(", numBlocks=", numBlocks);
+ }
+ if (numBlocks < allTileNum)
+ controlValues(CONTROL_UNUSED,
+ subspace.getFirstIndex() + numBlocks,
+ allTileNum - numBlocks);
+ }
+
+ /**
+ * Handle a root address
+ *
+ * @param addr Root Address
+ * @return true if the given Address is in this subspace.
+ */
+ public boolean handleRoot(Address addr) {
+ if(subspace.addressInRange(addr)) {
+ // increment tile
+ int index = subspace.getIndex(addr);
+ rootsStream.increment(index, (short)1);
+ // increment summary
+ this.totalRoots++;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Reset the roots Stream
+ * The roots Stream has to be reset seperately because we do not
+ * gather data in the usual way using <code>scan()</code>.
+ */
+ public void resetRootsStream() {
+ rootsStream.resetData();
+ totalRoots = 0;
+ }
+
+ /**
+ * Handle a direct reference from the immortal space.
+ *
+ * @param addr The Address
+ * @return true if the given Address is in this subspace.
+ */
+ public boolean handleReferenceFromImmortalSpace(Address addr) {
+ if(subspace.addressInRange(addr)) {
+ // increment tile
+ int index = subspace.getIndex(addr);
+ refFromImmortalStream.increment(index, (short)1);
+ // increment summary
+ this.totalRefFromImmortal++;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/TreadmillDriver.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/TreadmillDriver.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/TreadmillDriver.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/gcspy/drivers/TreadmillDriver.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,326 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.gcspy.drivers;
+
+import org.mmtk.policy.LargeObjectSpace;
+import org.mmtk.utility.gcspy.Color;
+import org.mmtk.utility.gcspy.StreamConstants;
+import org.mmtk.utility.gcspy.Subspace;
+import org.mmtk.vm.gcspy.IntStream;
+import org.mmtk.vm.gcspy.ShortStream;
+import org.mmtk.vm.gcspy.ServerInterpreter;
+import org.mmtk.utility.Conversions;
+import org.mmtk.utility.Log;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+
+/**
+ * This class implements a simple driver for the MMTk LargeObjectSpace.
+ */
+ at Uninterruptible public class TreadmillDriver extends AbstractDriver {
+
+ private static final boolean DEBUG = false;
+
+ // The streams
+ protected IntStream usedSpaceStream;
+ protected ShortStream objectsStream;
+ protected ShortStream rootsStream;
+ protected ShortStream refFromImmortalStream;
+
+ protected Subspace subspace; // A single subspace for this space
+ protected int allTileNum; // total number of tiles
+
+ // Overall statistics
+ protected int totalObjects = 0; // total number of objects allocated
+ protected int totalUsedSpace = 0; // total space used
+ protected int totalRoots = 0; // total of roots
+ protected int totalRefFromImmortal = 0; // total direct references from the immortal space
+ protected Address maxAddr; // the largest address seen
+ protected int threshold;
+
+
+ /**
+ * Create a new driver for this collector
+ *
+ * @param server The name of the GCspy server that owns this space
+ * @param spaceName The name of this driver
+ * @param lospace the large object space for this allocator
+ * @param blockSize The tile size
+ * @param threshold the size threshold of the LOS
+ * @param mainSpace Is this the main space?
+ */
+ public TreadmillDriver(
+ ServerInterpreter server,
+ String spaceName,
+ LargeObjectSpace lospace,
+ int blockSize,
+ int threshold,
+ boolean mainSpace) {
+ //TODO blocksize should be a multiple of treadmill granularity
+ super(server, spaceName, lospace, blockSize, mainSpace);
+
+ if (DEBUG) {
+ Log.write("TreadmillDriver for "); Log.write(spaceName);
+ Log.write(", blocksize="); Log.write(blockSize);
+ Log.write(", start="); Log.write(lospace.getStart());
+ Log.write(", extent="); Log.write(lospace.getExtent());
+ Log.write(", maxTileNum="); Log.writeln(maxTileNum);
+ }
+
+ this.threshold = threshold;
+
+ // Initialise a subspace and 2 Streams
+ subspace = createSubspace(lospace);
+ allTileNum = 0;
+ maxAddr = lospace.getStart();
+ usedSpaceStream = createUsedSpaceStream();
+ objectsStream = createObjectsStream();
+ rootsStream = createRootsStream();
+ refFromImmortalStream = createRefFromImmortalStream();
+ serverSpace.resize(0); // the collector must call resize() before gathering data
+
+ // Initialise the statistics
+ resetData();
+ }
+
+ /**
+ * Get the name of this driver type.
+ * @return The name, "MMTk TreadmillDriver" for this driver.
+ */
+ protected String getDriverName() {
+ return "MMTk TreadmillDriver";
+ }
+
+ // private creator methods for the streams
+ @Interruptible
+ private IntStream createUsedSpaceStream() {
+ return VM.newGCspyIntStream(
+ this,
+ "Used Space stream", // stream name
+ 0, // min. data value
+ blockSize, // max. data value
+ 0, // zero value
+ 0, // default value
+ "Space used: ", // value prefix
+ " bytes", // value suffix
+ StreamConstants.PRESENTATION_PERCENT, // presentation style
+ StreamConstants.PAINT_STYLE_ZERO, // paint style
+ 0, // index of the max stream (only needed if presentation is *_VAR)
+ Color.Red, // tile colour
+ true); // summary enabled
+ }
+
+ @Interruptible
+ private ShortStream createObjectsStream() {
+ return VM.newGCspyShortStream(
+ this,
+ "Objects stream",
+ (short)0,
+ (short)(blockSize/threshold),
+ (short)0,
+ (short)0,
+ "No. of objects = ",
+ " objects",
+ StreamConstants.PRESENTATION_PLUS,
+ StreamConstants.PAINT_STYLE_ZERO,
+ 0,
+ Color.Green,
+ true);
+ }
+
+ @Interruptible
+ private ShortStream createRootsStream() {
+ return VM.newGCspyShortStream(
+ this,
+ "Roots stream",
+ (short)0,
+ // Say, typical size = 4 * typical scalar size?
+ (short)(maxObjectsPerBlock(blockSize)/8),
+ (short)0,
+ (short)0,
+ "Roots: ",
+ " objects",
+ StreamConstants.PRESENTATION_PLUS,
+ StreamConstants.PAINT_STYLE_ZERO,
+ 0,
+ Color.Blue,
+ true);
+ }
+
+ @Interruptible
+ private ShortStream createRefFromImmortalStream() {
+ return VM.newGCspyShortStream(
+ this,
+ "References from Immortal stream",
+ (short)0,
+ // Say, typical size = 4 * typical scalar size?
+ (short)(maxObjectsPerBlock(blockSize)/8),
+ (short)0,
+ (short)0,
+ "References from immortal space: ",
+ " references",
+ StreamConstants.PRESENTATION_PLUS,
+ StreamConstants.PAINT_STYLE_ZERO,
+ 0,
+ Color.Blue,
+ true);
+ }
+
+ /**
+ * Reset the tile stats for all streams, including values used for summaries
+ */
+ public void resetData() {
+ super.resetData();
+
+ // Reset all the streams
+ usedSpaceStream.resetData();
+ objectsStream.resetData();
+ refFromImmortalStream.resetData();
+
+ // Reset the summary counts
+ totalUsedSpace = 0;
+ totalObjects = 0;
+ totalRefFromImmortal = 0;
+ }
+
+ /**
+ * Update the tile statistics
+ * In this case, we are accounting for super-page objects, rather than
+ * simply for the objects they contain.
+ *
+ * @param addr The address of the superpage
+ */
+ public void scan(Address addr) {
+
+ int index = subspace.getIndex(addr);
+ int length = ((LargeObjectSpace)mmtkSpace).getSize(addr).toInt();
+
+ if (DEBUG) {
+ Log.write("TreadmillDriver: super=", addr);
+ Log.write(", index=", index);
+ Log.write(", pages=", length);
+ Log.write(", bytes=", Conversions.pagesToBytes(length).toInt());
+ Log.writeln(", max=", usedSpaceStream.getMaxValue());
+ }
+
+ totalObjects++;
+ totalUsedSpace += length;
+ objectsStream.increment(index, (short)1);
+ int remainder = subspace.spaceRemaining(addr);
+ usedSpaceStream.distribute(index, remainder, blockSize, length);
+
+ Address tmp = addr.plus(length);
+ if (tmp.GT(maxAddr)) maxAddr = tmp;
+ }
+
+ /**
+ * Transmit the data if this event is of interest to the client
+ * @param event The event, either BEFORE_COLLECTION, SEMISPACE_COPIED
+ * or AFTER_COLLECTION
+ */
+ public void transmit(int event) {
+ if (!isConnected(event))
+ return;
+
+ // At this point, we've filled the tiles with data,
+ // however, we don't know the size of the space
+ // Calculate the highest indexed tile used so far, and update the subspace
+ Address start = subspace.getStart();
+ int required = countTileNum(start, maxAddr, blockSize);
+ int current = subspace.getBlockNum();
+ if (required > current || maxAddr != subspace.getEnd()) {
+ subspace.reset(start, maxAddr, 0, required);
+ allTileNum = required;
+ serverSpace.resize(allTileNum);
+ setTilenames(subspace, allTileNum);
+ }
+
+ // Set the summaries
+ setupSummaries();
+
+ // set the control info: all of space is USED
+ controlValues(CONTROL_USED,
+ subspace.getFirstIndex(), subspace.getBlockNum());
+
+ // send the space info
+ Offset size = subspace.getEnd().diff(subspace.getStart());
+ setSpaceInfo(size);
+
+ // Send the streams
+ send(event, allTileNum);
+ }
+
+ /**
+ * Setup summaries part of the <code>transmit</code> method.<p>
+ * Override this method to setup summaries of additional streams in subclasses.
+ */
+ protected void setupSummaries() {
+ usedSpaceStream.setSummary(totalUsedSpace,
+ subspace.getEnd().diff(subspace.getStart()).toInt());
+ objectsStream.setSummary(totalObjects);
+ rootsStream.setSummary(totalRoots);
+ refFromImmortalStream.setSummary(totalRefFromImmortal);
+ }
+
+
+ /**
+ * Handle a root address
+ *
+ * @param addr Root Address
+ * @return true if the given Address is in this subspace.
+ */
+ public boolean handleRoot(Address addr) {
+ if(subspace.addressInRange(addr)) {
+ // increment tile
+ int index = subspace.getIndex(addr);
+ rootsStream.increment(index, (short)1);
+ // increment summary
+ this.totalRoots++;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Reset the roots Stream. <br>
+ * The roots Stream has to be reset seperately because we do not
+ * gather data in the usual way using <code>scan()</code>.
+ */
+ public void resetRootsStream() {
+ rootsStream.resetData();
+ totalRoots = 0;
+ }
+
+ /**
+ * Handle a direct reference from the immortal space.
+ *
+ * @param addr The Address
+ * @return true if the given Address is in this subspace.
+ */
+ public boolean handleReferenceFromImmortalSpace(Address addr) {
+ if(subspace.addressInRange(addr)) {
+ // increment tile
+ int index = subspace.getIndex(addr);
+ refFromImmortalStream.increment(index, (short)1);
+ // increment summary
+ this.totalRefFromImmortal++;
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/FreeListPageResource.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/FreeListPageResource.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/FreeListPageResource.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/FreeListPageResource.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,382 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.heap;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.policy.Space;
+import static org.mmtk.policy.Space.PAGES_IN_CHUNK;
+import org.mmtk.utility.alloc.EmbeddedMetaData;
+import org.mmtk.utility.Conversions;
+import org.mmtk.utility.GenericFreeList;
+import org.mmtk.vm.VM;
+import org.mmtk.utility.Constants;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This class manages the allocation of pages for a space. When a
+ * page is requested by the space both a page budget and the use of
+ * virtual address space are checked. If the request for space can't
+ * be satisfied (for either reason) a GC may be triggered.<p>
+ */
+ at Uninterruptible
+public final class FreeListPageResource extends PageResource implements Constants {
+
+ private final GenericFreeList freeList;
+ private int highWaterMark = 0;
+ private final int metaDataPagesPerRegion;
+ private int pagesCurrentlyOnFreeList = 0;
+
+ /**
+ * Constructor
+ *
+ * Contiguous free list resource. The address range is pre-defined at
+ * initialization time and is immutable.
+ *
+ * @param pageBudget The budget of pages available to this memory
+ * manager before it must poll the collector.
+ * @param space The space to which this resource is attached
+ * @param start The start of the address range allocated to this resource
+ * @param bytes The size of the address rage allocated to this resource
+ */
+ public FreeListPageResource(int pageBudget, Space space, Address start,
+ Extent bytes) {
+ super(pageBudget, space, start);
+ int pages = Conversions.bytesToPages(bytes);
+ freeList = new GenericFreeList(pages);
+ pagesCurrentlyOnFreeList = pages;
+ this.metaDataPagesPerRegion = 0;
+ }
+
+ /**
+ * Constructor
+ *
+ * Contiguous free list resource. The address range is pre-defined at
+ * initialization time and is immutable.
+ *
+ * @param pageBudget The budget of pages available to this memory
+ * manager before it must poll the collector.
+ * @param space The space to which this resource is attached
+ * @param start The start of the address range allocated to this resource
+ * @param bytes The size of the address rage allocated to this resource
+ * @param metaDataPagesPerRegion The number of pages of meta data
+ * that are embedded in each region.
+ */
+ public FreeListPageResource(int pageBudget, Space space, Address start,
+ Extent bytes, int metaDataPagesPerRegion) {
+ super(pageBudget, space, start);
+ this.metaDataPagesPerRegion = metaDataPagesPerRegion;
+ int pages = Conversions.bytesToPages(bytes);
+ freeList = new GenericFreeList(pages, EmbeddedMetaData.PAGES_IN_REGION);
+ pagesCurrentlyOnFreeList = pages;
+ reserveMetaData(space.getExtent());
+ }
+
+ /**
+ * Constructor
+ *
+ * Discontiguous monotone resource. The address range is <i>not</i>
+ * pre-defined at initialization time and is dynamically defined to
+ * be some set of pages, according to demand and availability.
+ *
+ * @param pageBudget The budget of pages available to this memory
+ * manager before it must poll the collector.
+ * @param space The space to which this resource is attached
+ */
+ public FreeListPageResource(int pageBudget, Space space, int metaDataPagesPerRegion) {
+ super(pageBudget, space);
+ this.metaDataPagesPerRegion = metaDataPagesPerRegion;
+ this.start = Space.AVAILABLE_START;
+ freeList = new GenericFreeList(Map.globalPageMap, Map.getDiscontigFreeListPROrdinal(this));
+ pagesCurrentlyOnFreeList = 0;
+ }
+
+ /**
+ * Return the number of available physical pages for this resource.
+ * This includes all pages currently free on the resource's free list.
+ * If the resource is using discontiguous space it also includes
+ * currently unassigned discontiguous space.<p>
+ *
+ * Note: This just considers physical pages (ie virtual memory pages
+ * allocated for use by this resource). This calculation is orthogonal
+ * to and does not consider any restrictions on the number of pages
+ * this resource may actually use at any time (ie the number of
+ * committed and reserved pages).<p>
+ *
+ * Note: The calculation is made on the assumption that all space that
+ * could be assigned to this resource would be assigned to this resource
+ * (ie the unused discontiguous space could just as likely be assigned
+ * to another competing resource).
+ *
+ * @return The number of available physical pages for this resource.
+ */
+ @Override
+ public int getAvailablePhysicalPages() {
+ int rtn = pagesCurrentlyOnFreeList;
+ if (!contiguous) {
+ int chunks = Map.getAvailableDiscontiguousChunks()-Map.getChunkConsumerCount();
+ if (chunks < 0) chunks = 0;
+ rtn += chunks*(Space.PAGES_IN_CHUNK-metaDataPagesPerRegion);
+ }
+ return rtn;
+ }
+
+ /**
+ * Allocate <code>pages</code> pages from this resource.<p>
+ *
+ * If the request can be satisfied, then ensure the pages are
+ * mmpapped and zeroed before returning the address of the start of
+ * the region. If the request cannot be satisfied, return zero.
+ *
+ * @param pages The number of pages to be allocated.
+ * @return The start of the first page if successful, zero on
+ * failure.
+ */
+ @Inline
+ protected Address allocPages(int pages) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(metaDataPagesPerRegion == 0 || pages <= PAGES_IN_CHUNK - metaDataPagesPerRegion);
+ lock();
+ boolean newChunk = false;
+ int pageOffset = freeList.alloc(pages);
+ if (pageOffset == GenericFreeList.FAILURE && !contiguous) {
+ pageOffset = allocateContiguousChunks(pages);
+ newChunk = true;
+ }
+ if (pageOffset == -1) {
+ unlock();
+ return Address.zero();
+ } else {
+ pagesCurrentlyOnFreeList -= pages;
+ if (pageOffset > highWaterMark) {
+ if ((pageOffset ^ highWaterMark) > EmbeddedMetaData.PAGES_IN_REGION) {
+ int regions = 1 + ((pageOffset - highWaterMark) >> EmbeddedMetaData.LOG_PAGES_IN_REGION);
+ int metapages = regions * metaDataPagesPerRegion;
+ reserved += metapages;
+ committed += metapages;
+ newChunk = true;
+ }
+ highWaterMark = pageOffset;
+ }
+ Address rtn = start.plus(Conversions.pagesToBytes(pageOffset));
+ Extent bytes = Conversions.pagesToBytes(pages);
+ commitPages(pages, pages);
+ space.growSpace(rtn, bytes, newChunk);
+ unlock();
+ Mmapper.ensureMapped(rtn, pages);
+ VM.memory.zero(rtn, bytes);
+ VM.events.tracePageAcquired(space, rtn, pages);
+ return rtn;
+ }
+ }
+
+ /**
+ * Release a group of pages, associated with this page resource,
+ * that were allocated together, optionally zeroing on release and
+ * optionally memory protecting on release.
+ *
+ * @param first The first page in the group of pages that were
+ * allocated together.
+ */
+ @Inline
+ public void releasePages(Address first) {
+ if (VM.VERIFY_ASSERTIONS)
+ VM.assertions._assert(Conversions.isPageAligned(first));
+
+ int pageOffset = Conversions.bytesToPages(first.diff(start));
+
+ int pages = freeList.size(pageOffset);
+ if (ZERO_ON_RELEASE)
+ VM.memory.zero(first, Conversions.pagesToBytes(pages));
+ /* Can't use protect here because of the chunk sizes involved!
+ if (protectOnRelease.getValue())
+ LazyMmapper.protect(first, pages);
+ */
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(pages <= committed);
+
+ lock();
+ reserved -= pages;
+ committed -= pages;
+ int freed = freeList.free(pageOffset, true);
+ pagesCurrentlyOnFreeList += pages;
+
+ if (!contiguous) // only discontiguous spaces use chunks
+ releaseFreeChunks(first, freed);
+
+ unlock();
+
+ VM.events.tracePageReleased(space, first, pages);
+ }
+
+ /**
+ * The release of a page may have freed up an entire chunk or
+ * set of chunks. We need to check whether any chunks can be
+ * freed, and if so, free them.
+ *
+ * @param freedPage The address of the page that was just freed.
+ * @param pagesFreed The number of pages made available when the page was freed.
+ */
+ private void releaseFreeChunks(Address freedPage, int pagesFreed) {
+ int pageOffset = Conversions.bytesToPages(freedPage.diff(start));
+
+ if (metaDataPagesPerRegion > 0) { // can only be a single chunk
+ if (pagesFreed == (PAGES_IN_CHUNK - metaDataPagesPerRegion)) {
+ freeContiguousChunk(Space.chunkAlign(freedPage, true));
+ }
+ } else { // may be multiple chunks
+ if (pagesFreed % PAGES_IN_CHUNK == 0) { // necessary, but not sufficient condition
+ /* grow a region of chunks, starting with the chunk containing the freed page */
+ int regionStart = pageOffset & ~(PAGES_IN_CHUNK - 1);
+ int nextRegionStart = regionStart + PAGES_IN_CHUNK;
+ /* now try to grow (end point pages are marked as non-coalescing) */
+ while (regionStart >= 0 && freeList.isCoalescable(regionStart))
+ regionStart -= PAGES_IN_CHUNK;
+ while (nextRegionStart < GenericFreeList.MAX_UNITS && freeList.isCoalescable(nextRegionStart))
+ nextRegionStart += PAGES_IN_CHUNK;
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(regionStart >= 0 && nextRegionStart < GenericFreeList.MAX_UNITS);
+ if (pagesFreed == nextRegionStart - regionStart) {
+ freeContiguousChunk(start.plus(Conversions.pagesToBytes(regionStart)));
+ }
+ }
+ }
+ }
+
+ /**
+ * Allocate sufficient contiguous chunks within a discontiguous region to
+ * satisfy the pending request. Note that this is purely about address space
+ * allocation within a discontiguous region. This method does not reserve
+ * individual pages, it merely assigns a suitably large region of virtual
+ * memory from within the discontiguous region for use by a particular space.
+ *
+ * @param pages The number of pages currently being requested
+ * @return A chunk number or GenericFreelist.FAILURE
+ */
+ private int allocateContiguousChunks(int pages) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(metaDataPagesPerRegion == 0 || pages <= PAGES_IN_CHUNK - metaDataPagesPerRegion);
+ int rtn = GenericFreeList.FAILURE;
+ int requiredChunks = Space.requiredChunks(pages);
+ Address region = space.growDiscontiguousSpace(requiredChunks);
+ if (!region.isZero()) {
+ int regionStart = Conversions.bytesToPages(region.diff(start));
+ int regionEnd = regionStart + (requiredChunks*Space.PAGES_IN_CHUNK) - 1;
+ freeList.setUncoalescable(regionStart);
+ freeList.setUncoalescable(regionEnd + 1);
+ for (int p = regionStart; p < regionEnd; p += Space.PAGES_IN_CHUNK) {
+ int liberated;
+ if (p != regionStart)
+ freeList.clearUncoalescable(p);
+ liberated = freeList.free(p, true); // add chunk to our free list
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(liberated == Space.PAGES_IN_CHUNK + (p - regionStart));
+ if (metaDataPagesPerRegion > 1)
+ freeList.alloc(metaDataPagesPerRegion, p); // carve out space for metadata
+ pagesCurrentlyOnFreeList += Space.PAGES_IN_CHUNK - metaDataPagesPerRegion;
+ }
+ rtn = freeList.alloc(pages); // re-do the request which triggered this call
+ }
+ return rtn;
+ }
+
+ /**
+ * Release a single chunk from a discontiguous region. All this does is
+ * release a chunk from the virtual address space associated with this
+ * discontiguous space.
+ *
+ * @param chunk The chunk to be freed
+ */
+ private void freeContiguousChunk(Address chunk) {
+ int numChunks = Map.getContiguousRegionChunks(chunk);
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(numChunks == 1 || metaDataPagesPerRegion == 0);
+
+ /* nail down all pages associated with the chunk, so it is no longer on our free list */
+ int chunkStart = Conversions.bytesToPages(chunk.diff(start));
+ int chunkEnd = chunkStart + (numChunks*Space.PAGES_IN_CHUNK);
+ while (chunkStart < chunkEnd) {
+ freeList.setUncoalescable(chunkStart);
+ if (metaDataPagesPerRegion > 0)
+ freeList.free(chunkStart); // first free any metadata pages
+ int tmp = freeList.alloc(Space.PAGES_IN_CHUNK, chunkStart); // then alloc the entire chunk
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(tmp == chunkStart);
+ chunkStart += Space.PAGES_IN_CHUNK;
+ pagesCurrentlyOnFreeList -= (Space.PAGES_IN_CHUNK - metaDataPagesPerRegion);
+ }
+ /* now return the address space associated with the chunk for global reuse */
+ space.releaseDiscontiguousChunks(chunk);
+ }
+
+ /**
+ * Reserve virtual address space for meta-data.
+ *
+ * @param extent The size of this space
+ */
+ private void reserveMetaData(Extent extent) {
+ highWaterMark = 0;
+ if (metaDataPagesPerRegion > 0) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(start.toWord().rshl(EmbeddedMetaData.LOG_BYTES_IN_REGION).lsh(EmbeddedMetaData.LOG_BYTES_IN_REGION).toAddress().EQ(start));
+ Extent size = extent.toWord().rshl(EmbeddedMetaData.LOG_BYTES_IN_REGION).lsh(EmbeddedMetaData.LOG_BYTES_IN_REGION).toExtent();
+ Address cursor = start.plus(size);
+ while (cursor.GT(start)) {
+ cursor = cursor.minus(EmbeddedMetaData.BYTES_IN_REGION);
+ int unit = cursor.diff(start).toWord().rshl(LOG_BYTES_IN_PAGE).toInt();
+ int tmp = freeList.alloc(metaDataPagesPerRegion, unit);
+ pagesCurrentlyOnFreeList -= metaDataPagesPerRegion;
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(tmp == unit);
+ }
+ }
+ }
+
+ /**
+ * Adjust a page request to include metadata requirements, if any. In the
+ * case of a free-list allocator, meta-data is pre-allocated, so simply
+ * return the un-adjusted request size.
+ *
+ * @param pages The size of the pending allocation in pages
+ * @return The (unadjusted) request size, since metadata is pre-allocated
+ */
+ public int adjustForMetaData(int pages) { return pages; }
+
+ public Address getHighWater() {
+ return start.plus(Extent.fromIntSignExtend(highWaterMark<<LOG_BYTES_IN_PAGE));
+ }
+
+ /**
+ * Return the size of the super page
+ *
+ * @param first the Address of the first word in the superpage
+ * @return the size in bytes
+ */
+ @Inline
+ public Extent getSize(Address first) {
+ if (VM.VERIFY_ASSERTIONS)
+ VM.assertions._assert(Conversions.isPageAligned(first));
+
+ int pageOffset = Conversions.bytesToPages(first.diff(start));
+ int pages = freeList.size(pageOffset);
+ return Conversions.pagesToBytes(pages);
+ }
+
+ /**
+ * Resize the free list associated with this resource and nail down
+ * its start address. This method is called to re-set the free list
+ * once the global free list (which it shares) is finalized and the
+ * base address is finalized. There's a circular dependency, so we
+ * need an explicit call-back to reset the free list size and start
+ *
+ * @param startAddress The final start address for the discontiguous space.
+ */
+ @Interruptible
+ public void resizeFreeList(Address startAddress) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!contiguous && !Plan.isInitialized());
+ start = startAddress;
+ freeList.resizeFreeList();
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/HeapGrowthManager.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/HeapGrowthManager.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/HeapGrowthManager.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/HeapGrowthManager.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,293 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.heap;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.utility.*;
+import org.mmtk.utility.options.Options;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class is responsible for growing and shrinking the
+ * heap size by observing heap utilization and GC load.
+ */
+ at Uninterruptible public abstract class HeapGrowthManager implements Constants {
+
+ /**
+ * The initial heap size (-Xms) in bytes
+ */
+ private static Extent initialHeapSize;
+
+ /**
+ * The maximum heap size (-Xms) in bytes
+ */
+ private static Extent maxHeapSize;
+
+ /**
+ * The current heap size in bytes
+ */
+ private static Extent currentHeapSize;
+
+
+ private static final double[][] generationalFunction = {{0.00, 0.00, 0.10, 0.30, 0.60, 0.80, 1.00},
+ { 0.00, 0.90, 0.90, 0.95, 1.00, 1.00, 1.00 },
+ { 0.01, 0.90, 0.90, 0.95, 1.00, 1.00, 1.00 },
+ { 0.02, 0.95, 0.95, 1.00, 1.00, 1.00, 1.00 },
+ { 0.07, 1.00, 1.00, 1.10, 1.15, 1.20, 1.20 },
+ { 0.15, 1.00, 1.00, 1.20, 1.25, 1.35, 1.30 },
+ { 0.40, 1.00, 1.00, 1.25, 1.30, 1.50, 1.50 },
+ { 1.00, 1.00, 1.00, 1.25, 1.30, 1.50, 1.50 } };
+
+ private static final double[][] nongenerationalFunction = {{0.00, 0.00, 0.10, 0.30, 0.60, 0.80, 1.00},
+ { 0.00, 0.90, 0.90, 0.95, 1.00, 1.00, 1.00 },
+ { 0.02, 0.90, 0.90, 0.95, 1.00, 1.00, 1.00 },
+ { 0.05, 0.95, 0.95, 1.00, 1.00, 1.00, 1.00 },
+ { 0.15, 1.00, 1.00, 1.10, 1.15, 1.20, 1.20 },
+ { 0.30, 1.00, 1.00, 1.20, 1.25, 1.35, 1.30 },
+ { 0.50, 1.00, 1.00, 1.25, 1.30, 1.50, 1.50 },
+ { 1.00, 1.00, 1.00, 1.25, 1.30, 1.50, 1.50 } };
+
+ /**
+ * An encoding of the function used to manage heap size.
+ * The xaxis represents the live ratio at the end of a major collection.
+ * The yaxis represents the GC load (GC time/total time).
+ * The interior of the matrix represents a ratio to shrink or grow
+ * the heap for a given pair of live ratio and GC load.
+ * The constraints on the matrix are:
+ * <ul>
+ * <li> function[0][0] is ignored.
+ * <li> All numbers in the first row must monotonically increase and
+ * must be in the range from 0 to 1 inclusive.</li>
+ * <li> All numbers in the first column must monotonically increase
+ * and must be in the range from 0 to 1 inclusive.</li>
+ * <li> There must be 0 and 1 values specified in both dimensions.
+ * <li> For all interior points in the matrix, the value must be
+ * greater than the liveRatio for that column.</li>
+ * </ul>
+ */
+ private static final double[][] function =
+ VM.activePlan.constraints().generational() ? generationalFunction : nongenerationalFunction;
+
+ private static long endLastMajorGC;
+ private static double accumulatedGCTime;
+
+ /**
+ * Initialize heap size parameters and the mechanisms
+ * used to adaptively change heap size.
+ */
+ public static void boot(Extent initial, Extent max) {
+ initialHeapSize = initial;
+ maxHeapSize = max;
+ if (initialHeapSize.GT(maxHeapSize))
+ maxHeapSize = initialHeapSize;
+ currentHeapSize = initialHeapSize;
+ VM.events.heapSizeChanged(currentHeapSize);
+ if (VM.VERIFY_ASSERTIONS) sanityCheck();
+ endLastMajorGC = VM.statistics.nanoTime();
+ }
+
+ /**
+ * @return the current heap size in bytes
+ */
+ public static Extent getCurrentHeapSize() {
+ return currentHeapSize;
+ }
+
+ /**
+ * Return the max heap size in bytes (as set by -Xmx).
+ *
+ * @return The max heap size in bytes (as set by -Xmx).
+ */
+ public static Extent getMaxHeapSize() {
+ return maxHeapSize;
+ }
+
+ /**
+ * Return the initial heap size in bytes (as set by -Xms).
+ *
+ * @return The initial heap size in bytes (as set by -Xms).
+ */
+ public static Extent getInitialHeapSize() {
+ return initialHeapSize;
+ }
+
+ /**
+ * Forcibly grow the heap by the given number of bytes.
+ * Used to provide headroom when handling an OutOfMemory
+ * situation.
+ * @param size number of bytes to grow the heap
+ */
+ public static void overrideGrowHeapSize(Extent size) {
+ currentHeapSize = currentHeapSize.plus(size);
+ VM.events.heapSizeChanged(currentHeapSize);
+ }
+
+ /**
+ * Record the time taken by the current GC;
+ * used to compute gc load, one of the inputs
+ * into the heap size management function
+ */
+ public static void recordGCTime(double time) {
+ accumulatedGCTime += time;
+ }
+
+ /**
+ * Reset timers used to compute gc load
+ */
+ public static void reset() {
+ endLastMajorGC = VM.statistics.nanoTime();
+ accumulatedGCTime = 0;
+ }
+
+ /**
+ * Decide how to grow/shrink the heap to respond
+ * to application's memory usage.
+ * @return true if heap size was changed, false otherwise
+ */
+ public static boolean considerHeapSize() {
+ Extent oldSize = currentHeapSize;
+ Extent reserved = Plan.reservedMemory();
+ double liveRatio = reserved.toLong() / ((double) currentHeapSize.toLong());
+ double ratio = computeHeapChangeRatio(liveRatio);
+ Extent newSize = Word.fromIntSignExtend((int)(ratio * (double) (oldSize.toLong()>>LOG_BYTES_IN_MBYTE))).lsh(LOG_BYTES_IN_MBYTE).toExtent(); // do arith in MB to avoid overflow
+ if (newSize.LT(reserved)) newSize = reserved;
+ newSize = newSize.plus(BYTES_IN_MBYTE - 1).toWord().rshl(LOG_BYTES_IN_MBYTE).lsh(LOG_BYTES_IN_MBYTE).toExtent(); // round to next megabyte
+ if (newSize.GT(maxHeapSize)) newSize = maxHeapSize;
+ if (newSize.NE(oldSize) && newSize.GT(Extent.zero())) {
+ // Heap size is going to change
+ currentHeapSize = newSize;
+ if (Options.verbose.getValue() >= 2) {
+ Log.write("GC Message: Heap changed from "); Log.writeDec(oldSize.toWord().rshl(LOG_BYTES_IN_KBYTE));
+ Log.write("KB to "); Log.writeDec(newSize.toWord().rshl(LOG_BYTES_IN_KBYTE));
+ Log.writeln("KB");
+ }
+ VM.events.heapSizeChanged(currentHeapSize);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private static double computeHeapChangeRatio(double liveRatio) {
+ // (1) compute GC load.
+ long totalNanos = VM.statistics.nanoTime() - endLastMajorGC;
+ double totalTime = VM.statistics.nanosToMillis(totalNanos);
+ double gcLoad = accumulatedGCTime / totalTime;
+
+ if (liveRatio > 1) {
+ // Perhaps indicates bad bookkeeping in MMTk?
+ Log.write("GCWarning: Live ratio greater than 1: ");
+ Log.writeln(liveRatio);
+ liveRatio = 1;
+ }
+ if (gcLoad > 1) {
+ if (gcLoad > 1.0001) {
+ Log.write("GC Error: GC load was greater than 1!! ");
+ Log.writeln(gcLoad);
+ Log.write("GC Error:\ttotal time (ms) "); Log.writeln(totalTime);
+ Log.write("GC Error:\tgc time (ms) "); Log.writeln(accumulatedGCTime);
+ }
+ gcLoad = 1;
+ }
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(liveRatio >= 0);
+ if (VM.VERIFY_ASSERTIONS && gcLoad < -0.0) {
+ Log.write("gcLoad computed to be "); Log.writeln(gcLoad);
+ Log.write("\taccumulateGCTime was (ms) "); Log.writeln(accumulatedGCTime);
+ Log.write("\ttotalTime was (ms) "); Log.writeln(totalTime);
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(false);
+ }
+
+ if (Options.verbose.getValue() > 2) {
+ Log.write("Live ratio "); Log.writeln(liveRatio);
+ Log.write("GCLoad "); Log.writeln(gcLoad);
+ }
+
+ // (2) Find the 4 points surrounding gcLoad and liveRatio
+ int liveRatioUnder = 1;
+ int liveRatioAbove = function[0].length - 1;
+ int gcLoadUnder = 1;
+ int gcLoadAbove = function.length - 1;
+ while (true) {
+ if (function[0][liveRatioUnder+1] >= liveRatio) break;
+ liveRatioUnder++;
+ }
+ while (true) {
+ if (function[0][liveRatioAbove-1] <= liveRatio) break;
+ liveRatioAbove--;
+ }
+ while (true) {
+ if (function[gcLoadUnder+1][0] >= gcLoad) break;
+ gcLoadUnder++;
+ }
+ while (true) {
+ if (function[gcLoadAbove-1][0] <= gcLoad) break;
+ gcLoadAbove--;
+ }
+
+ // (3) Compute the heap change ratio
+ double factor = function[gcLoadUnder][liveRatioUnder];
+ double liveRatioFraction =
+ (liveRatio - function[0][liveRatioUnder]) /
+ (function[0][liveRatioAbove] - function[0][liveRatioUnder]);
+ double liveRatioDelta =
+ function[gcLoadUnder][liveRatioAbove] - function[gcLoadUnder][liveRatioUnder];
+ factor += (liveRatioFraction * liveRatioDelta);
+ double gcLoadFraction =
+ (gcLoad - function[gcLoadUnder][0]) /
+ (function[gcLoadAbove][0] - function[gcLoadUnder][0]);
+ double gcLoadDelta =
+ function[gcLoadAbove][liveRatioUnder] - function[gcLoadUnder][liveRatioUnder];
+ factor += (gcLoadFraction * gcLoadDelta);
+
+ if (Options.verbose.getValue() > 2) {
+ Log.write("Heap adjustment factor is ");
+ Log.writeln(factor);
+ }
+ return factor;
+ }
+
+ /**
+ * Check that function satisfies the invariants
+ */
+ private static void sanityCheck() {
+ // Check live ratio
+ double[] liveRatio = function[0];
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(liveRatio[1] == 0);
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(liveRatio[liveRatio.length-1] == 1);
+ for (int i = 2; i < liveRatio.length; i++) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(liveRatio[i-1] < liveRatio[i]);
+ for (int j = 1; j < function.length; j++) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(function[j][i] >= 1 || function[j][i] > liveRatio[i]);
+ }
+ }
+
+ // Check GC load
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(function[1][0] == 0);
+ int len = function.length;
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(function[len-1][0] == 1);
+ for (int i = 2; i < len; i++) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(function[i-1][0] < function[i][0]);
+ }
+
+ // Check that we have a rectangular matrix
+ for (int i = 1; i < function.length; i++) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(function[i-1].length == function[i].length);
+ }
+ }
+
+
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/Map.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/Map.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/Map.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/Map.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,339 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.heap;
+
+import org.mmtk.policy.Space;
+import org.mmtk.utility.GenericFreeList;
+import org.mmtk.utility.Log;
+import org.mmtk.vm.Lock;
+import org.mmtk.vm.VM;
+import org.vmmagic.pragma.Inline;
+import org.vmmagic.pragma.Interruptible;
+import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.unboxed.Address;
+import org.vmmagic.unboxed.Extent;
+import org.vmmagic.unboxed.Word;
+
+/**
+ * This class manages the mapping of spaces to virtual memory ranges.<p>
+ *
+ */
+ at Uninterruptible
+public class Map {
+
+ /* set the map base address so that we have an unused (null) chunk at the bottome of the space for 64 bit */
+ private static final Address MAP_BASE_ADDRESS = Space.BITS_IN_ADDRESS == 32 ? Address.zero() : Space.HEAP_START.minus(Space.BYTES_IN_CHUNK);
+
+ /****************************************************************************
+ *
+ * Class variables
+ */
+ private static final int[] descriptorMap;
+ private static final int[] linkageMap;
+ private static final Space[] spaceMap;
+ private static final GenericFreeList regionMap;
+ public static final GenericFreeList globalPageMap;
+ private static int sharedDiscontigFLCount = 0;
+ private static final FreeListPageResource[] sharedFLMap;
+ private static int totalAvailableDiscontiguousChunks = 0;
+
+ private static final Lock lock = VM.newLock("Map lock");
+
+ /****************************************************************************
+ *
+ * Initialization
+ */
+
+ /**
+ * Class initializer. Create our two maps
+ */
+ static {
+ descriptorMap = new int[Space.MAX_CHUNKS];
+ linkageMap = new int[Space.MAX_CHUNKS];
+ spaceMap = new Space[Space.MAX_CHUNKS];
+ regionMap = new GenericFreeList(Space.MAX_CHUNKS);
+ globalPageMap = new GenericFreeList(1, 1, Space.MAX_SPACES);
+ sharedFLMap = new FreeListPageResource[Space.MAX_SPACES];
+ if (VM.VERIFY_ASSERTIONS)
+ VM.assertions._assert(Space.BITS_IN_ADDRESS == Space.LOG_ADDRESS_SPACE ||
+ Space.HEAP_END.diff(MAP_BASE_ADDRESS).toWord().rshl(Space.LOG_ADDRESS_SPACE).isZero());
+ }
+
+ /****************************************************************************
+ *
+ * Map accesses and insertion
+ */
+
+ /**
+ * Insert a space and its descriptor into the map, associating it
+ * with a particular address range.
+ *
+ * @param start The start address of the region to be associated
+ * with this space.
+ * @param extent The size of the region, in bytes
+ * @param descriptor The descriptor for this space
+ * @param space The space to be associated with this region
+ */
+ public static void insert(Address start, Extent extent, int descriptor,
+ Space space) {
+ Extent e = Extent.zero();
+ while (e.LT(extent)) {
+ int index = getChunkIndex(start.plus(e));
+ if (descriptorMap[index] != 0) {
+ Log.write("Conflicting virtual address request for space \"");
+ Log.write(space.getName()); Log.write("\" at ");
+ Log.writeln(start.plus(e));
+ Space.printVMMap();
+ VM.assertions.fail("exiting");
+ }
+ descriptorMap[index] = descriptor;
+ VM.barriers.setArrayNoBarrier(spaceMap, index, space);
+ e = e.plus(Space.BYTES_IN_CHUNK);
+ }
+ }
+
+ /**
+ * Allocate some number of contiguous chunks within a discontiguous region
+ *
+ * @param descriptor The descriptor for the space to which these chunks will be assigned
+ * @param space The space to which these chunks will be assigned
+ * @param chunks The number of chunks required
+ * @param previous The previous contgiuous set of chunks for this space (to create a linked list of contiguous regions for each space)
+ * @return The address of the assigned memory. This always succeeds. If the request fails we fail right here.
+ */
+ public static Address allocateContiguousChunks(int descriptor, Space space, int chunks, Address previous) {
+ lock.acquire();
+ int chunk = regionMap.alloc(chunks);
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(chunk != 0);
+ if (chunk == -1) {
+ Log.write("Unable to allocate virtual address space for space \"");
+ Log.write(space.getName()); Log.write("\" for ");
+ Log.write(chunks); Log.write(" chunks (");
+ Log.write(chunks<<Space.LOG_BYTES_IN_CHUNK); Log.writeln(" bytes)");
+ Space.printVMMap();
+ VM.assertions.fail("exiting");
+ }
+ totalAvailableDiscontiguousChunks -= chunks;
+ Address rtn = addressForChunkIndex(chunk);
+ insert(rtn, Extent.fromIntZeroExtend(chunks<<Space.LOG_BYTES_IN_CHUNK), descriptor, space);
+ linkageMap[chunk] = previous.isZero() ? 0 : getChunkIndex(previous);
+ lock.release();
+ return rtn;
+ }
+
+ /**
+ * Return the address of the next contiguous region associated with some discontiguous space by following the linked list for that space.
+ *
+ * @param start The current region (return the next region in the list)
+ * @return Return the next contiguous region after start in the linked list of regions
+ */
+ public static Address getNextContiguousRegion(Address start) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(start.EQ(Space.chunkAlign(start, true)));
+ int chunk = getChunkIndex(start);
+ return (chunk == 0) ? Address.zero() : (linkageMap[chunk] == 0) ? Address.zero() : addressForChunkIndex(linkageMap[chunk]);
+ }
+
+ /**
+ * Return the size of a contiguous region in chunks.
+ *
+ * @param start The start address of the region whose size is being requested
+ * @return The size of the region in question
+ */
+ public static int getContiguousRegionChunks(Address start) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(start.EQ(Space.chunkAlign(start, true)));
+ int chunk = getChunkIndex(start);
+ return regionMap.size(chunk);
+ }
+
+ /**
+ * Return the size of a contiguous region in bytes.
+ *
+ * @param start The start address of the region whose size is being requested
+ * @return The size of the region in question
+ */
+ public static Extent getContiguousRegionSize(Address start) {
+ return Word.fromIntSignExtend(getContiguousRegionChunks(start)).lsh(Space.LOG_BYTES_IN_CHUNK).toExtent();
+ }
+
+ /**
+ * Free all chunks in a linked list of contiguous chunks. This means starting
+ * with lastChunk and then walking the chain of contiguous regions, freeing each.
+ *
+ * @param lastChunk The last chunk in the linked list of chunks to be freed
+ */
+ public static void freeAllChunks(Address lastChunk) {
+ lock.acquire();
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(lastChunk.EQ(Space.chunkAlign(lastChunk, true)));
+ int chunk = getChunkIndex(lastChunk);
+ while (chunk != 0) {
+ int next = linkageMap[chunk];
+ freeContiguousChunks(chunk);
+ chunk = next;
+ }
+ lock.release();
+ }
+
+ /**
+ * Free some set of contiguous chunks, given the chunk address
+ *
+ * @param start The start address of the first chunk in the series
+ * @return The number of chunks which were contiguously allocated
+ */
+ public static int freeContiguousChunks(Address start) {
+ lock.acquire();
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(start.EQ(Space.chunkAlign(start, true)));
+ int rtn = freeContiguousChunks(getChunkIndex(start));
+ lock.release();
+ return rtn;
+ }
+
+ /**
+ * Free some set of contiguous chunks, given the chunk index
+ *
+ * @param chunk The chunk index of the region to be freed
+ * @return The number of chunks freed
+ */
+ private static int freeContiguousChunks(int chunk) {
+ int chunks = regionMap.free(chunk);
+ totalAvailableDiscontiguousChunks += chunks;
+ for (int offset = 0; offset < chunks; offset++) {
+ descriptorMap[chunk + offset] = 0;
+ VM.barriers.setArrayNoBarrier(spaceMap, chunk + offset, null);
+ linkageMap[chunk + offset] = 0;
+ }
+ return chunks;
+ }
+
+ /**
+ * Finalize the space map, establishing which virtual memory
+ * is nailed down, and then placing the rest into a map to
+ * be used by discontiguous spaces.
+ */
+ @Interruptible
+ public static void finalizeStaticSpaceMap() {
+ /* establish bounds of discontiguous space */
+ Address startAddress = Space.getDiscontigStart();
+ int firstChunk = getChunkIndex(startAddress);
+ int lastChunk = getChunkIndex(Space.getDiscontigEnd());
+ int unavailStartChunk = lastChunk + 1;
+ int trailingChunks = Space.MAX_CHUNKS - unavailStartChunk;
+ int pages = (1 + lastChunk - firstChunk) * Space.PAGES_IN_CHUNK;
+ globalPageMap.resizeFreeList(pages, pages);
+ for (int pr = 0; pr < sharedDiscontigFLCount; pr++)
+ sharedFLMap[pr].resizeFreeList(startAddress);
+
+ /* set up the region map free list */
+ int allocedChunk = regionMap.alloc(firstChunk); // block out entire bottom of address range
+ for (int chunkIndex = firstChunk; chunkIndex <= lastChunk; chunkIndex++)
+ allocedChunk = regionMap.alloc(1); // Tentatively allocate all usable chunks
+ allocedChunk = regionMap.alloc(trailingChunks); // block out entire top of address range
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(allocedChunk == unavailStartChunk);
+
+ /* set up the global page map and place chunks on free list */
+ int firstPage = 0;
+ for (int chunkIndex = firstChunk; chunkIndex <= lastChunk; chunkIndex++) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(spaceMap[chunkIndex] == null);
+ totalAvailableDiscontiguousChunks++;
+ regionMap.free(chunkIndex); // put this chunk on the free list
+ globalPageMap.setUncoalescable(firstPage);
+ int allocedPages = globalPageMap.alloc(Space.PAGES_IN_CHUNK); // populate the global page map
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(allocedPages == firstPage);
+ firstPage += Space.PAGES_IN_CHUNK;
+ }
+ }
+
+ /**
+ * Return the ordinal number for some free list space wishing to share a discontiguous region.
+ * @return The ordinal number for a free list space wishing to share a discontiguous region
+ */
+ @Interruptible
+ public static int getDiscontigFreeListPROrdinal(FreeListPageResource pr) {
+ sharedFLMap[sharedDiscontigFLCount] = pr;
+ sharedDiscontigFLCount++;
+ return sharedDiscontigFLCount;
+ }
+
+ /**
+ * Return the total number of chunks available (unassigned) within the
+ * range of virtual memory apportioned to discontiguous spaces.
+ *
+ * @return The number of available chunks for use by discontiguous spaces.
+ */
+ public static int getAvailableDiscontiguousChunks() {
+ return totalAvailableDiscontiguousChunks;
+ }
+
+ /**
+ * Return the total number of clients contending for chunks. This
+ * is useful when establishing conservative bounds on the number
+ * of remaining chunks.
+ *
+ * @return The total number of clients who may contend for chunks.
+ */
+ public static int getChunkConsumerCount() {
+ return sharedDiscontigFLCount;
+ }
+
+ /**
+ * Return the space in which this address resides.
+ *
+ * @param address The address in question
+ * @return The space in which the address resides
+ */
+ @Inline
+ public static Space getSpaceForAddress(Address address) {
+ int index = getChunkIndex(address);
+ return spaceMap[index];
+ }
+
+ /**
+ * Return the space descriptor for the space in which this object
+ * resides.
+ *
+ * @param object The object in question
+ * @return The space descriptor for the space in which the object
+ * resides
+ */
+ @Inline
+ public static int getDescriptorForAddress(Address object) {
+ int index = getChunkIndex(object);
+ return descriptorMap[index];
+ }
+
+ /**
+ * Hash an address to a chunk (this is simply done via bit shifting)
+ *
+ * @param address The address to be hashed
+ * @return The chunk number that this address hashes into
+ */
+ @Inline
+ private static int getChunkIndex(Address address) {
+ if (Space.BYTES_IN_ADDRESS == 8) {
+ if (address.LT(Space.HEAP_START) || address.GE(Space.HEAP_END))
+ return 0;
+ else
+ return address.diff(MAP_BASE_ADDRESS).toWord().rshl(Space.LOG_BYTES_IN_CHUNK).toInt();
+ } else
+ return address.toWord().rshl(Space.LOG_BYTES_IN_CHUNK).toInt();
+ }
+ @Inline
+ private static Address addressForChunkIndex(int chunk) {
+ if (Space.BYTES_IN_ADDRESS == 8) {
+ if (chunk == 0)
+ return Address.zero();
+ else
+ return MAP_BASE_ADDRESS.plus(Word.fromIntZeroExtend(chunk).lsh(Space.LOG_BYTES_IN_CHUNK).toExtent());
+ } else
+ return Word.fromIntZeroExtend(chunk).lsh(Space.LOG_BYTES_IN_CHUNK).toAddress();
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/Mmapper.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/Mmapper.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/Mmapper.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/Mmapper.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.utility.heap;
+
+import org.mmtk.utility.*;
+
+import org.mmtk.vm.Lock;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements mmapping and protection of virtual memory.
+ */
+ at Uninterruptible public final class Mmapper implements Constants {
+
+ /****************************************************************************
+ * Constants
+ */
+ public static final byte UNMAPPED = 0;
+ public static final byte MAPPED = 1;
+ public static final byte PROTECTED = 2; // mapped but not accessible
+ public static final int LOG_MMAP_CHUNK_BYTES = 20;
+ public static final int MMAP_CHUNK_BYTES = 1 << LOG_MMAP_CHUNK_BYTES; // the granularity VMResource operates at
+ //TODO: 64-bit: this is not OK: value does not fit in int, but should, we do not want to create such big array
+ private static final int MMAP_CHUNK_MASK = MMAP_CHUNK_BYTES - 1;
+ private static final int MMAP_NUM_CHUNKS = 1 << (Constants.LOG_BYTES_IN_ADDRESS_SPACE - LOG_MMAP_CHUNK_BYTES);
+ public static final boolean verbose = false;
+
+ /****************************************************************************
+ * Class variables
+ */
+ public static final Lock lock = VM.newLock("Mmapper");
+ private static byte[] mapped;
+
+
+ /****************************************************************************
+ * Initialization
+ */
+
+ /**
+ * Class initializer. This is executed <i>prior</i> to bootstrap
+ * (i.e. at "build" time).
+ */
+ static {
+ mapped = new byte[MMAP_NUM_CHUNKS];
+ for (int c = 0; c < MMAP_NUM_CHUNKS; c++) {
+ mapped[c] = UNMAPPED;
+ }
+ }
+
+ /****************************************************************************
+ * Generic mmap and protection functionality
+ */
+
+ /**
+ * Given an address array describing the regions of virtual memory to be used
+ * by MMTk, demand zero map all of them if they are not already mapped.
+ *
+ * @param spaceMap An address array containing a pairs of start and end
+ * addresses for each of the regions to be mappe3d
+ */
+ public static void eagerlyMmapAllSpaces(AddressArray spaceMap) {
+
+ /*for (int i = 0; i < spaceMap.length() / 2; i++) {
+ Address regionStart = spaceMap.get(i * 2);
+ Address regionEnd = spaceMap.get(i * 2 + 1);
+ Log.write(regionStart); Log.write(" "); Log.writeln(regionEnd);
+ if (regionEnd.EQ(Address.zero()) || regionStart.EQ(Address.fromIntSignExtend(-1)) ||regionEnd.EQ(Address.fromIntSignExtend(-1)))
+ break;
+ if (VM.VERIFY_ASSERTIONS) {
+ VM.assertions._assert(regionStart.EQ(chunkAlignDown(regionStart)));
+ VM.assertions._assert(regionEnd.EQ(chunkAlignDown(regionEnd)));
+ }
+ int pages = Conversions.bytesToPages(regionEnd.diff(regionStart));
+ ensureMapped(regionStart, pages);
+ }*/
+ }
+
+ /**
+ * Mark a range of pages as having (already) been mapped. This is useful
+ * where the VM has performed the mapping of the pages itself.
+ *
+ * @param start The start of the range to be marked as mapped
+ * @param bytes The size of the range, in bytes.
+ */
+ public static void markAsMapped(Address start, int bytes) {
+ int startChunk = Conversions.addressToMmapChunksDown(start);
+ int endChunk = Conversions.addressToMmapChunksUp(start.plus(bytes));
+ for (int i = startChunk; i <= endChunk; i++)
+ mapped[i] = MAPPED;
+ }
+
+ /**
+ * Ensure that a range of pages is mmapped (or equivalent). If the
+ * pages are not yet mapped, demand-zero map them. Note that mapping
+ * occurs at chunk granularity, not page granularity.<p>
+ *
+ * NOTE: There is a monotonicity assumption so that only updates require lock
+ * acquisition.
+ * TODO: Fix the above to support unmapping.
+ *
+ * @param start The start of the range to be mapped.
+ * @param pages The size of the range to be mapped, in pages
+ */
+ public static void ensureMapped(Address start, int pages) {
+ int startChunk = Conversions.addressToMmapChunksDown(start);
+ int endChunk = Conversions.addressToMmapChunksUp(start.plus(Conversions.pagesToBytes(pages)));
+ for (int chunk = startChunk; chunk < endChunk; chunk++) {
+ if (mapped[chunk] == MAPPED) continue;
+ Address mmapStart = Conversions.mmapChunksToAddress(chunk);
+ lock.acquire();
+// Log.writeln(mmapStart);
+ // might have become MAPPED here
+ if (mapped[chunk] == UNMAPPED) {
+ int errno = VM.memory.dzmmap(mmapStart, MMAP_CHUNK_BYTES);
+ if (errno != 0) {
+ lock.release();
+ Log.write("ensureMapped failed with errno "); Log.write(errno);
+ Log.write(" on address "); Log.writeln(mmapStart);
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(false);
+ } else {
+ if (verbose) {
+ Log.write("mmap succeeded at chunk "); Log.write(chunk); Log.write(" "); Log.write(mmapStart);
+ Log.write(" with len = "); Log.writeln(MMAP_CHUNK_BYTES);
+ }
+ }
+ }
+ if (mapped[chunk] == PROTECTED) {
+ if (!VM.memory.munprotect(mmapStart, MMAP_CHUNK_BYTES)) {
+ lock.release();
+ VM.assertions.fail("Mmapper.ensureMapped (unprotect) failed");
+ } else {
+ if (verbose) {
+ Log.write("munprotect succeeded at chunk "); Log.write(chunk); Log.write(" "); Log.write(mmapStart);
+ Log.write(" with len = "); Log.writeln(MMAP_CHUNK_BYTES);
+ }
+ }
+ }
+ mapped[chunk] = MAPPED;
+ lock.release();
+ }
+
+ }
+
+ /**
+ * Memory protect a range of pages (using mprotect or equivalent). Note
+ * that protection occurs at chunk granularity, not page granularity.
+ *
+ * @param start The start of the range to be protected.
+ * @param pages The size of the range to be protected, in pages
+ */
+ public static void protect(Address start, int pages) {
+ int startChunk = Conversions.addressToMmapChunksDown(start);
+ int chunks = Conversions.pagesToMmapChunksUp(pages);
+ int endChunk = startChunk + chunks;
+ lock.acquire();
+ for (int chunk = startChunk; chunk < endChunk; chunk++) {
+ if (mapped[chunk] == MAPPED) {
+ Address mmapStart = Conversions.mmapChunksToAddress(chunk);
+ if (!VM.memory.mprotect(mmapStart, MMAP_CHUNK_BYTES)) {
+ lock.release();
+ VM.assertions.fail("Mmapper.mprotect failed");
+ } else {
+ if (verbose) {
+ Log.write("mprotect succeeded at chunk "); Log.write(chunk); Log.write(" "); Log.write(mmapStart);
+ Log.write(" with len = "); Log.writeln(MMAP_CHUNK_BYTES);
+ }
+ }
+ mapped[chunk] = PROTECTED;
+ } else {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(mapped[chunk] == PROTECTED);
+ }
+ }
+ lock.release();
+ }
+
+ /****************************************************************************
+ * Utility functions
+ */
+
+ /**
+ * Return true if the given address has been mmapped
+ *
+ * @param addr The address in question.
+ * @return true if the given address has been mmapped
+ */
+ @Uninterruptible
+ public static boolean addressIsMapped(Address addr) {
+ int chunk = Conversions.addressToMmapChunksDown(addr);
+ return mapped[chunk] == MAPPED;
+ }
+
+ /**
+ * Return true if the given object has been mmapped
+ *
+ * @param object The object in question.
+ * @return true if the given object has been mmapped
+ */
+ @Uninterruptible
+ public static boolean objectIsMapped(ObjectReference object) {
+ return addressIsMapped(VM.objectModel.refToAddress(object));
+ }
+
+ /**
+ * Return a given address rounded up to an mmap chunk size
+ *
+ * @param addr The address to be aligned
+ * @return The given address rounded up to an mmap chunk size
+ */
+ @SuppressWarnings("unused") // but might be useful someday
+ private static Address chunkAlignUp(Address addr) {
+ return chunkAlignDown(addr.plus(MMAP_CHUNK_MASK));
+ }
+
+ /**
+ * Return a given address rounded down to an mmap chunk size
+ *
+ * @param addr The address to be aligned
+ * @return The given address rounded down to an mmap chunk size
+ */
+ private static Address chunkAlignDown(Address addr) {
+ return addr.toWord().and(Word.fromIntSignExtend(MMAP_CHUNK_MASK).not()).toAddress();
+ }
+}
+
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/MonotonePageResource.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/MonotonePageResource.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/MonotonePageResource.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/MonotonePageResource.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,307 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.heap;
+
+import org.mmtk.utility.alloc.EmbeddedMetaData;
+import org.mmtk.utility.options.Options;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.Conversions;
+import org.mmtk.utility.Constants;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class manages the allocation of pages for a space. When a
+ * page is requested by the space both a page budget and the use of
+ * virtual address space are checked. If the request for space can't
+ * be satisfied (for either reason) a GC may be triggered.<p>
+ */
+ at Uninterruptible
+public final class MonotonePageResource extends PageResource
+ implements Constants {
+
+ /****************************************************************************
+ *
+ * Instance variables
+ */
+ private Address cursor;
+ private Address sentinel;
+ private final int metaDataPagesPerRegion;
+ private Address currentChunk = Address.zero();
+
+ /**
+ * Constructor
+ *
+ * Contiguous monotone resource. The address range is pre-defined at
+ * initialization time and is immutable.
+ *
+ * @param pageBudget The budget of pages available to this memory
+ * manager before it must poll the collector.
+ * @param space The space to which this resource is attached
+ * @param start The start of the address range allocated to this resource
+ * @param bytes The size of the address rage allocated to this resource
+ * @param metaDataPagesPerRegion The number of pages of meta data
+ * that are embedded in each region.
+ */
+ public MonotonePageResource(int pageBudget, Space space, Address start,
+ Extent bytes, int metaDataPagesPerRegion) {
+ super(pageBudget, space, start);
+ this.cursor = start;
+ this.sentinel = start.plus(bytes);
+ this.metaDataPagesPerRegion = metaDataPagesPerRegion;
+ }
+
+ /**
+ * Constructor
+ *
+ * Discontiguous monotone resource. The address range is <i>not</i>
+ * pre-defined at initialization time and is dynamically defined to
+ * be some set of pages, according to demand and availability.
+ *
+ * CURRENTLY UNIMPLEMENTED
+ *
+ * @param pageBudget The budget of pages available to this memory
+ * manager before it must poll the collector.
+ * @param space The space to which this resource is attached
+ * @param metaDataPagesPerRegion The number of pages of meta data
+ * that are embedded in each region.
+ */
+ public MonotonePageResource(int pageBudget, Space space, int metaDataPagesPerRegion) {
+ super(pageBudget, space);
+ /* unimplemented */
+ this.start = Address.zero();
+ this.cursor = Address.zero();
+ this.sentinel = Address.zero();
+ this.metaDataPagesPerRegion = metaDataPagesPerRegion;
+ }
+
+ /**
+ * Return the number of available physical pages for this resource.
+ * This includes all pages currently unused by this resource's page
+ * cursor. If the resource is using discontiguous space it also includes
+ * currently unassigned discontiguous space.<p>
+ *
+ * Note: This just considers physical pages (ie virtual memory pages
+ * allocated for use by this resource). This calculation is orthogonal
+ * to and does not consider any restrictions on the number of pages
+ * this resource may actually use at any time (ie the number of
+ * committed and reserved pages).<p>
+ *
+ * Note: The calculation is made on the assumption that all space that
+ * could be assigned to this resource would be assigned to this resource
+ * (ie the unused discontiguous space could just as likely be assigned
+ * to another competing resource).
+ *
+ * @return The number of available physical pages for this resource.
+ */
+ @Override
+ public int getAvailablePhysicalPages() {
+ int rtn = Conversions.bytesToPages(sentinel.diff(cursor));
+ if (!contiguous)
+ rtn += Map.getAvailableDiscontiguousChunks()*Space.PAGES_IN_CHUNK;
+ return rtn;
+ }
+
+ /**
+ * Allocate <code>pages</code> pages from this resource. Simply
+ * bump the cursor, and fail if we hit the sentinel.<p>
+ *
+ * If the request can be satisfied, then ensure the pages are
+ * mmpapped and zeroed before returning the address of the start of
+ * the region. If the request cannot be satisfied, return zero.
+ *
+ * @param requestPages The number of pages to be allocated.
+ * @return The start of the first page if successful, zero on
+ * failure.
+ */
+ @Inline
+ protected Address allocPages(int requestPages) {
+ int pages = requestPages;
+ boolean newChunk = false;
+ lock();
+ Address rtn = cursor;
+ if (Space.chunkAlign(rtn, true).NE(currentChunk)) {
+ newChunk = true;
+ currentChunk = Space.chunkAlign(rtn, true);
+ }
+
+ if (metaDataPagesPerRegion != 0) {
+ /* adjust allocation for metadata */
+ Address regionStart = getRegionStart(cursor.plus(Conversions.pagesToBytes(pages)));
+ Offset regionDelta = regionStart.diff(cursor);
+ if (regionDelta.sGE(Offset.zero())) {
+ /* start new region, so adjust pages and return address accordingly */
+ pages += Conversions.bytesToPages(regionDelta) + metaDataPagesPerRegion;
+ rtn = regionStart.plus(Conversions.pagesToBytes(metaDataPagesPerRegion));
+ }
+ }
+ Extent bytes = Conversions.pagesToBytes(pages);
+ Address tmp = cursor.plus(bytes);
+
+ if (!contiguous && tmp.GT(sentinel)) {
+ /* we're out of virtual memory within our discontiguous region, so ask for more */
+ int requiredChunks = Space.requiredChunks(pages);
+ start = space.growDiscontiguousSpace(requiredChunks);
+ cursor = start;
+ sentinel = cursor.plus(start.isZero() ? 0 : requiredChunks<<Space.LOG_BYTES_IN_CHUNK);
+ rtn = cursor;
+ tmp = cursor.plus(bytes);
+ newChunk = true;
+ }
+ if (VM.VERIFY_ASSERTIONS)
+ VM.assertions._assert(rtn.GE(cursor) && rtn.LT(cursor.plus(bytes)));
+ if (tmp.GT(sentinel)) {
+ unlock();
+ return Address.zero();
+ } else {
+ Address old = cursor;
+ cursor = tmp;
+ commitPages(requestPages, pages);
+ space.growSpace(old, bytes, newChunk);
+ unlock();
+ Mmapper.ensureMapped(old, pages);
+ VM.memory.zero(old, bytes);
+ VM.events.tracePageAcquired(space, rtn, pages);
+ return rtn;
+ }
+ }
+
+ /**
+ * Adjust a page request to include metadata requirements, if any.<p>
+ *
+ * In this case we simply report the expected page cost. We can't use
+ * worst case here because we would exhaust our budget every time.
+ *
+ * @param pages The size of the pending allocation in pages
+ * @return The number of required pages, inclusive of any metadata
+ */
+ public int adjustForMetaData(int pages) {
+ return (metaDataPagesPerRegion * pages) / EmbeddedMetaData.PAGES_IN_REGION;
+ }
+
+ /**
+ * Adjust a page request to include metadata requirements, if any.<p>
+ *
+ * Note that there could be a race here, with multiple threads each
+ * adjusting their request on account of the same single metadata
+ * region. This should not be harmful, as the failing requests will
+ * just retry, and if multiple requests succeed, only one of them
+ * will actually have the metadata accounted against it, the others
+ * will simply have more space than they originally requested.
+ *
+ * @param pages The size of the pending allocation in pages
+ * @param begin The start address of the region assigned to this pending
+ * request
+ * @return The number of required pages, inclusive of any metadata
+ */
+ public int adjustForMetaData(int pages, Address begin) {
+ if (getRegionStart(begin).plus(metaDataPagesPerRegion<<LOG_BYTES_IN_PAGE).EQ(begin))
+ pages += metaDataPagesPerRegion;
+ return pages;
+ }
+
+ private static Address getRegionStart(Address addr) {
+ return addr.toWord().and(Word.fromIntSignExtend(EmbeddedMetaData.BYTES_IN_REGION - 1).not()).toAddress();
+ }
+
+ /**
+ * Reset this page resource, freeing all pages and resetting
+ * reserved and committed pages appropriately.
+ */
+ @Inline
+ public void reset() {
+ lock();
+ reserved = 0;
+ committed = 0;
+ releasePages();
+ unlock();
+ }
+
+ /**
+ * Notify that several pages are no longer in use.
+ *
+ * @param pages The number of pages
+ */
+ public void unusePages(int pages) {
+ lock();
+ reserved -= pages;
+ committed -= pages;
+ unlock();
+ }
+
+ /**
+ * Notify that previously unused pages are in use again.
+ *
+ * @param pages The number of pages
+ */
+ public void reusePages(int pages) {
+ lock();
+ reserved += pages;
+ committed += pages;
+ unlock();
+ }
+
+ /**
+ * Release all pages associated with this page resource, optionally
+ * zeroing on release and optionally memory protecting on release.
+ */
+ @Inline
+ private void releasePages() {
+ Address first = start;
+ do {
+ Extent bytes = cursor.diff(start).toWord().toExtent();
+ releasePages(start, bytes);
+ cursor = start;
+ } while (!contiguous && moveToNextChunk());
+ if (!contiguous) {
+ sentinel = Address.zero();
+ Map.freeAllChunks(first);
+ }
+ }
+
+ /**
+ * Adjust the start and cursor fields to point to the next chunk
+ * in the linked list of chunks tied down by this page resource.
+ *
+ * @return True if we moved to the next chunk; false if we hit the
+ * end of the linked list.
+ */
+ private boolean moveToNextChunk() {
+ start = Map.getNextContiguousRegion(start);
+ if (start.isZero())
+ return false;
+ else {
+ cursor = start.plus(Map.getContiguousRegionSize(start));
+ return true;
+ }
+ }
+
+ /**
+ * Release a range of pages associated with this page resource, optionally
+ * zeroing on release and optionally memory protecting on release.
+ */
+ @Inline
+ private void releasePages(Address first, Extent bytes) {
+ int pages = Conversions.bytesToPages(bytes);
+ if (VM.VERIFY_ASSERTIONS)
+ VM.assertions._assert(bytes.EQ(Conversions.pagesToBytes(pages)));
+ if (ZERO_ON_RELEASE)
+ VM.memory.zero(first, bytes);
+ if (Options.protectOnRelease.getValue())
+ Mmapper.protect(first, pages);
+ VM.events.tracePageReleased(space, first, pages);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/PageResource.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/PageResource.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/PageResource.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/PageResource.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,320 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.heap;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.Constants;
+import org.mmtk.utility.options.ProtectOnRelease;
+import org.mmtk.utility.options.Options;
+
+import org.mmtk.vm.Lock;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class manages the allocation of pages for a space. When a
+ * page is requested by the space both a page budget and the use of
+ * virtual address space are checked. If the request for space can't
+ * be satisfied (for either reason) a GC may be triggered.<p>
+ *
+ * This class is abstract, and is subclassed with monotone and
+ * freelist variants, which reflect monotonic and ad hoc space usage
+ * respectively. Monotonic use is easier to manage, but is obviously
+ * more restrictive (useful for copying collectors which allocate
+ * monotonically before freeing the entire space and starting over).
+ */
+ at Uninterruptible
+public abstract class PageResource implements Constants {
+
+ /****************************************************************************
+ *
+ * Class variables
+ */
+ protected static final boolean ZERO_ON_RELEASE = false; // debugging
+
+ private static final Lock classLock;
+ private static long cumulativeCommitted = 0;
+
+
+ /****************************************************************************
+ *
+ * Instance variables
+ */
+
+ // page budgeting
+ protected int reserved;
+ protected int committed;
+ protected int required;
+ private final int pageBudget;
+
+ protected final boolean contiguous;
+ protected final Space space;
+ protected Address start; // only for contiguous
+
+ // locking
+ private final Lock gcLock; // used during GC
+ private final Lock mutatorLock; // used by mutators
+
+ /****************************************************************************
+ *
+ * Initialization
+ */
+ static {
+ classLock = VM.newLock("PageResource");
+ Options.protectOnRelease = new ProtectOnRelease();
+ }
+
+ /**
+ * Constructor
+ *
+ * @param pageBudget The budget of pages available to this memory
+ * manager before it must poll the collector.
+ * @param space The space to which this resource is attached
+ */
+ private PageResource(int pageBudget, Space space, boolean contiguous) {
+ this.pageBudget = pageBudget;
+ this.contiguous = contiguous;
+ this.space = space;
+ gcLock = VM.newLock(space.getName() + ".gcLock");
+ mutatorLock = VM.newLock(space.getName() + ".mutatorLock");
+ }
+
+ /**
+ * Constructor for discontiguous spaces
+ *
+ * @param pageBudget The budget of pages available to this memory
+ * manager before it must poll the collector.
+ * @param space The space to which this resource is attached
+ */
+ PageResource(int pageBudget, Space space) {
+ this(pageBudget, space, false);
+ }
+
+ /**
+ * Constructor for contiguous spaces
+ *
+ * @param pageBudget The budget of pages available to this memory
+ * manager before it must poll the collector.
+ * @param space The space to which this resource is attached
+ */
+ PageResource(int pageBudget, Space space, Address start) {
+ this(pageBudget, space, true);
+ this.start = start;
+ }
+
+ /**
+ * Return the number of available physical pages for this resource.
+ *
+ * Note: This just considers physical pages (ie virtual memory pages
+ * allocated for use by this resource). This calculation is orthogonal
+ * to and does not consider any restrictions on the number of pages
+ * this resource may actually use at any time (ie the number of
+ * committed and reserved pages).<p>
+ *
+ * Note: The calculation is made on the assumption that all space that
+ * could be assigned to this resource would be assigned to this resource
+ * (ie the unused discontiguous space could just as likely be assigned
+ * to another competing resource).
+ *
+ * @return The number of available physical pages for this resource.
+ */
+ public abstract int getAvailablePhysicalPages();
+
+ /**
+ * Reserve pages.<p>
+ *
+ * The role of reserving pages is that it allows the request to be
+ * noted as pending (the difference between committed and reserved
+ * indicates pending requests). If the request would exceed the
+ * page budget then the caller must poll in case a GC is necessary.
+ *
+ * @param pages The number of pages requested
+ * @return True if the page budget could satisfy the request.
+ */
+ @Inline
+ public final boolean reservePages(int pages) {
+ lock();
+ required += adjustForMetaData(pages);
+ reserved = committed + required;
+ boolean satisfied = reserved <= pageBudget;
+ unlock();
+ return satisfied;
+ }
+
+ /**
+ * Remove a request to the space.
+ *
+ * @param pages The number of pages in the request.
+ */
+ @Inline
+ public final void clearRequest(int pages) {
+ lock();
+ required -= adjustForMetaData(pages);
+ unlock();
+ }
+
+ /**
+ * Reserve pages unconditionally.<p>
+ *
+ * An example of where this is useful is in cases where it is
+ * desirable to put some space aside as head-room. By
+ * unconditionally reserving the pages, the pages are counted
+ * against the collectors budget. When the space is actually
+ * needed, the pages can be unconditionally released, freeing
+ * the pages for other purposes.
+ *
+ * @param pages The number of pages to be unconditionally
+ * reserved.
+ */
+ public final void unconditionallyReservePages(int pages) {
+ lock();
+ committed += pages;
+ reserved += pages;
+ unlock();
+ }
+
+ /**
+ * Release pages unconditionally.<p>
+ *
+ * This call allows pages to be unconditionally removed from
+ * the collectors page budget.
+ *
+ * @see #unconditionallyReservePages
+ * @param pages The number of pages to be unconditionally
+ * released.
+ */
+ public final void unconditionallyReleasePages(int pages) {
+ lock();
+ committed -= pages;
+ reserved -= pages;
+ unlock();
+ }
+
+ abstract Address allocPages(int pages);
+
+ /**
+ * Adjust a page request to include metadata requirements for a request
+ * of the given size. This must be a pure function, that is it does not
+ * depend on the state of the PageResource.
+ *
+ * @param pages The size of the pending allocation in pages
+ * @return The number of required pages, inclusive of any metadata
+ */
+ public abstract int adjustForMetaData(int pages);
+
+ /**
+ * Allocate pages in virtual memory, returning zero on failure.<p>
+ *
+ * If the request cannot be satisfied, zero is returned and it
+ * falls to the caller to trigger the GC.
+ *
+ * Call <code>allocPages</code> (subclass) to find the pages in
+ * virtual memory. If successful then commit the pending page
+ * request and return the address of the first page.
+ *
+ * @param pages The number of pages requested
+ * @return The address of the first of <code>pages</code> pages, or
+ * zero on failure.
+ */
+ @Inline
+ public final Address getNewPages(int pages) {
+ return allocPages(pages);
+ }
+
+ /**
+ * Commit pages to the page budget. This is called after
+ * successfully determining that the request can be satisfied by
+ * both the page budget and virtual memory. This simply accounts
+ * for the descrepency between <code>committed</code> and
+ * <code>reserved</code> while the request was pending.
+ *
+ * This *MUST* be called by each PageResource during the
+ * allocPages, and the caller must hold the lock.
+ *
+ * @param requestedPages The number of pages from this request
+ * @param totalPages The number of pages
+ */
+ protected void commitPages(int requestedPages, int totalPages) {
+ int predictedPages = adjustForMetaData(requestedPages);
+ int delta = totalPages - predictedPages;
+ required -= predictedPages;
+ reserved += delta;
+ committed += totalPages;
+ if (!Plan.gcInProgress())
+ addToCommitted(totalPages); // only count mutator pages
+ }
+
+ /**
+ * Return the number of reserved pages
+ *
+ * @return The number of reserved pages.
+ */
+ public final int reservedPages() { return reserved; }
+
+ /**
+ * Return the number of committed pages
+ *
+ * @return The number of committed pages.
+ */
+ public final int committedPages() { return committed; }
+
+ /**
+ * Return the number of required pages
+ *
+ * @return The number of required pages.
+ */
+ public final int requiredPages() { return required; }
+
+ /**
+ * Return the cumulative number of committed pages
+ *
+ * @return The cumulative number of committed pages.
+ */
+ public static long cumulativeCommittedPages() { return cumulativeCommitted; }
+
+ /**
+ * Add to the total cumulative committed page count.
+ *
+ * @param pages The number of pages to be added.
+ */
+ private static void addToCommitted(int pages) {
+ classLock.acquire();
+ cumulativeCommitted += pages;
+ classLock.release();
+ }
+
+ /**
+ * Acquire the appropriate lock depending on whether the context is
+ * GC or mutator.
+ */
+ protected final void lock() {
+ if (Plan.gcInProgress())
+ gcLock.acquire();
+ else
+ mutatorLock.acquire();
+ }
+
+ /**
+ * Release the appropriate lock depending on whether the context is
+ * GC or mutator.
+ */
+ protected final void unlock() {
+ if (Plan.gcInProgress())
+ gcLock.release();
+ else
+ mutatorLock.release();
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/SpaceDescriptor.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/SpaceDescriptor.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/SpaceDescriptor.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/SpaceDescriptor.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.utility.heap;
+
+import org.mmtk.policy.Space;
+import org.mmtk.utility.Constants;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class manages the encoding and decoding of space descriptors.<p>
+ *
+ * Space descriptors are integers that encode a space's mapping into
+ * virtual memory. For discontiguous spaces, they indicate
+ * discontiguity and mapping must be done by consulting the space map.
+ * For contiguous spaces, the space's address range is encoded into
+ * the integer (using a fixed point notation).<p>
+ *
+ * The purpose of this class is to allow <code>static final int</code>
+ * space descriptors to exist for each space, which can then be used
+ * in tests to determine whether an object is in a space. A good
+ * compiler can perform this decoding at compile time and produce
+ * optimal code for the test.
+ */
+ at Uninterruptible public class SpaceDescriptor implements Constants {
+
+ /****************************************************************************
+ *
+ * Class variables
+ */
+
+ private static final int TYPE_BITS = 2;
+ private static final int TYPE_SHARED = 0;
+ private static final int TYPE_CONTIGUOUS = 1;
+ private static final int TYPE_CONTIGUOUS_HI = 3;
+ private static final int TYPE_MASK = (1 << TYPE_BITS) - 1;
+ private static final int SIZE_SHIFT = TYPE_BITS;
+ private static final int SIZE_BITS = 10;
+ private static final int SIZE_MASK = ((1 << SIZE_BITS) - 1) << SIZE_SHIFT;
+ private static final int EXPONENT_SHIFT = SIZE_SHIFT + SIZE_BITS;
+ private static final int EXPONENT_BITS = 5;
+ private static final int EXPONENT_MASK = ((1 << EXPONENT_BITS) - 1) << EXPONENT_SHIFT;
+ private static final int MANTISSA_SHIFT = EXPONENT_SHIFT + EXPONENT_BITS;
+ private static final int MANTISSA_BITS = 14;
+ private static final int BASE_EXPONENT = BITS_IN_INT - MANTISSA_BITS;
+
+ private static int discontiguousSpaceIndex = 0;
+ private static final int DISCONTIG_INDEX_INCREMENT = 1<<TYPE_BITS;
+
+ /****************************************************************************
+ *
+ * Descriptor creation
+ */
+
+ /**
+ * Create a descriptor for a <i>contiguous</i> space
+ *
+ * @param start The start address of the space
+ * @param end The end address of the space
+ * @return An integer descriptor encoding the region of virtual
+ * memory occupied by the space
+ */
+ public static int createDescriptor(Address start, Address end) {
+ int chunks = end.diff(start).toWord().rshl(Space.LOG_BYTES_IN_CHUNK).toInt();
+ if (VM.VERIFY_ASSERTIONS)
+ VM.assertions._assert(!start.isZero() && chunks > 0 && chunks < (1 << SIZE_BITS));
+ boolean top = end.EQ(Space.HEAP_END);
+ Word tmp = start.toWord();
+ tmp = tmp.rshl(BASE_EXPONENT);
+ int exponent = 0;
+ while (!tmp.isZero() && tmp.and(Word.one()).isZero()) {
+ tmp = tmp.rshl(1);
+ exponent++;
+ }
+ int mantissa = tmp.toInt();
+ if (VM.VERIFY_ASSERTIONS)
+ VM.assertions._assert(tmp.lsh(BASE_EXPONENT + exponent).EQ(start.toWord()));
+ return (mantissa<<MANTISSA_SHIFT) |
+ (exponent<<EXPONENT_SHIFT) |
+ (chunks << SIZE_SHIFT) |
+ ((top) ? TYPE_CONTIGUOUS_HI : TYPE_CONTIGUOUS);
+ }
+
+ /**
+ * Create a descriptor for a <i>dis-contiguous</i> (shared) space
+ *
+ * @return An integer descriptor reflecting the fact that this space
+ * is shared (and thus discontiguous and so must be established via
+ * maps).
+ */
+ public static int createDescriptor() {
+ discontiguousSpaceIndex += DISCONTIG_INDEX_INCREMENT;
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((discontiguousSpaceIndex & TYPE_CONTIGUOUS) != TYPE_CONTIGUOUS);
+ return discontiguousSpaceIndex;
+ }
+
+ /****************************************************************************
+ *
+ * Descriptor interrogation
+ */
+
+ /**
+ * Return true if this descriptor describes a contiguous space
+ *
+ * @param descriptor
+ * @return True if this descriptor describes a contiguous space
+ */
+ @Inline
+ public static boolean isContiguous(int descriptor) {
+ return ((descriptor & TYPE_CONTIGUOUS) == TYPE_CONTIGUOUS);
+ }
+
+ /**
+ * Return true if this descriptor describes a contiguous space that
+ * is at the top of the virtual address space
+ *
+ * @param descriptor
+ * @return True if this descriptor describes a contiguous space that
+ * is at the top of the virtual address space
+ */
+ @Inline
+ public static boolean isContiguousHi(int descriptor) {
+ return ((descriptor & TYPE_MASK) == TYPE_CONTIGUOUS_HI);
+ }
+
+ /**
+ * Return the start of this region of memory encoded in this descriptor
+ *
+ * @param descriptor
+ * @return The start of this region of memory encoded in this descriptor
+ */
+ @Inline
+ public static Address getStart(int descriptor) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isContiguous(descriptor));
+ Word mantissa = Word.fromIntSignExtend(descriptor >>> MANTISSA_SHIFT);
+ int exponent = (descriptor & EXPONENT_MASK) >>> EXPONENT_SHIFT;
+ return mantissa.lsh(BASE_EXPONENT + exponent).toAddress();
+ }
+
+ /**
+ * Return the size of the region of memory encoded in this
+ * descriptor, in chunks
+ *
+ * @param descriptor
+ * @return The size of the region of memory encoded in this
+ * descriptor, in chunks
+ */
+ @Inline
+ public static int getChunks(int descriptor) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isContiguous(descriptor));
+ return (descriptor & SIZE_MASK) >>> SIZE_SHIFT;
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/VMRequest.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/VMRequest.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/VMRequest.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/heap/VMRequest.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.utility.heap;
+
+import org.mmtk.utility.Constants;
+
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class manages the encoding and decoding of virtual memory requests.
+ *
+ * By encapsulating this aspect of the construction of a space, we greatly
+ * reduce the number of constructors required.
+ */
+public final class VMRequest implements Constants {
+
+ public static final int REQUEST_DISCONTIGUOUS = 0;
+ public static final int REQUEST_FIXED = 1;
+ public static final int REQUEST_EXTENT = 3;
+ public static final int REQUEST_FRACTION = 4;
+
+ public final int type;
+ public final Address start;
+ public final Extent extent;
+ public final float frac;
+ public final boolean top;
+
+ private VMRequest(int type, Address start, Extent bytes, float frac, boolean top) {
+ this.type = type;
+ this.start = start;
+ this.extent = bytes;
+ this.frac = frac;
+ this.top = top;
+ }
+
+ /**
+ * Is this a discontiguous space request?
+ * @return true if this is a discontiguous space request, false otherwise
+ */
+ public boolean isDiscontiguous() {
+ return type == REQUEST_DISCONTIGUOUS;
+ }
+
+ /**
+ * A request for a discontiguous region of memory
+ *
+ * @return The request object
+ */
+ public static VMRequest create() {
+ return new VMRequest(REQUEST_DISCONTIGUOUS, Address.zero(), Extent.zero(), 0f, false);
+ }
+
+ /**
+ * A request for an explicit region of memory
+ *
+ * @param start The start of the region
+ * @param extent The size of the region
+ * @return The request object
+ */
+ public static VMRequest create(Address start, Extent extent) {
+ return new VMRequest(REQUEST_FIXED, start, extent, 0f, false);
+ }
+
+ /**
+ * A request for a number of megabytes of memory
+ *
+ * @param mb The number of megabytes
+ * @return The request object
+ */
+ public static VMRequest create(int mb) {
+ return create(mb, false);
+ }
+
+ /**
+ * A request for a fraction of available memory
+ *
+ * @param frac The fraction
+ * @return The request object
+ */
+ public static VMRequest create(float frac) {
+ return create(frac, false);
+ }
+
+ /**
+ * A request for a number of megabytes of memory, optionally requesting the highest available.
+ *
+ * @param mb The number of megabytes
+ * @param top True to request high memory
+ * @return The request object
+ */
+ public static VMRequest create(int mb, boolean top) {
+ return new VMRequest(REQUEST_EXTENT, Address.zero(), Word.fromIntSignExtend(mb).lsh(LOG_BYTES_IN_MBYTE).toExtent(), 0f, top);
+ }
+
+ /**
+ * A request for a fraction of available memory, optionally requesting the highest available.
+ *
+ * @param frac The fraction
+ * @param top True to request high memory
+ * @return The request object
+ */
+ public static VMRequest create(float frac, boolean top) {
+ return new VMRequest(REQUEST_FRACTION, Address.zero(), Extent.zero(), frac, top);
+ }
+
+ /**
+ * A request for a number of bytes of memory, optionally requesting the highest available.
+ *
+ * @param extent The number of bytes
+ * @param top True to request high memory
+ * @return The request object
+ */
+ public static VMRequest create(Extent extent, boolean top) {
+ return new VMRequest(REQUEST_EXTENT, Address.zero(), extent, 0f, top);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/BoundedNursery.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/BoundedNursery.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/BoundedNursery.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/BoundedNursery.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.utility.options;
+
+import org.mmtk.plan.Plan;
+
+/**
+ * Provide an upper bound on nursery size. This option is not intended to
+ * be created directly, but via NurserySize.
+ */
+public final class BoundedNursery extends org.vmutil.options.PagesOption {
+ /**
+ * Create the option.
+ */
+ public BoundedNursery() {
+ super(Options.set, "Bounded Nursery",
+ "Bound the maximum size of the nursery to this value",
+ Plan.DEFAULT_MAX_NURSERY);
+ }
+
+ /**
+ * Nursery can not be empty.
+ */
+ protected void validate() {
+ failIf(value <= 0, "Can not have an empty nursery");
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/ConcurrentTrigger.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/ConcurrentTrigger.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/ConcurrentTrigger.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/ConcurrentTrigger.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.options;
+
+/**
+ * Concurrent trigger percentage
+ */
+public class ConcurrentTrigger extends org.vmutil.options.IntOption {
+ /**
+ * Create the option.
+ */
+ public ConcurrentTrigger() {
+ super(Options.set, "Concurrent Trigger",
+ "Concurrent trigger percentage",
+ 50);
+ }
+
+ /**
+ * Only accept values between 1 and 100 (inclusive)
+ */
+ protected void validate() {
+ failIf(this.value <= 0, "Trigger must be between 1 and 100");
+ failIf(this.value > 100, "Trigger must be between 1 and 100");
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleFilterThreshold.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleFilterThreshold.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleFilterThreshold.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleFilterThreshold.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.utility.options;
+
+/**
+ * Trigger cycle buffer filtering if the space available falls below this threshold.
+ */
+public final class CycleFilterThreshold extends org.vmutil.options.PagesOption {
+ /**
+ * Create the option.
+ */
+ public CycleFilterThreshold() {
+ super(Options.set, "Cycle Filter Threshold",
+ "Trigger cycle buffer filtering if the space available falls below this threshold",
+ 512);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleMetaDataLimit.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleMetaDataLimit.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleMetaDataLimit.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleMetaDataLimit.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.utility.options;
+
+/**
+ * Trigger cycle detection if the meta data volume grows to this limit.
+ */
+public final class CycleMetaDataLimit extends org.vmutil.options.PagesOption {
+ /**
+ * Create the option.
+ */
+ public CycleMetaDataLimit() {
+ super(Options.set, "Cycle Meta Data Limit",
+ "Trigger cycle detection if the meta data volume grows to this limit",
+ 4096);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleTriggerThreshold.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleTriggerThreshold.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleTriggerThreshold.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/CycleTriggerThreshold.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.utility.options;
+
+/**
+ * Trigger cycle detection if the space available falls below this threshold.
+ */
+public final class CycleTriggerThreshold extends org.vmutil.options.PagesOption {
+ /**
+ * Create the option.
+ */
+ public CycleTriggerThreshold() {
+ super(Options.set, "Cycle Trigger Threshold",
+ "Trigger cycle detection if the space available falls below this threshold",
+ 512);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DebugAddress.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DebugAddress.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DebugAddress.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DebugAddress.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,29 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.options;
+
+import org.vmmagic.unboxed.Address;
+
+/**
+ * Allow an address to be specified on the command line for use in debugging.
+ */
+public final class DebugAddress extends org.vmutil.options.AddressOption {
+ /**
+ * Create the option
+ */
+ public DebugAddress() {
+ super(Options.set, "Debug Address",
+ "Specify an address at runtime for use in debugging",
+ Address.zero());
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragFreeHeadroom.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragFreeHeadroom.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragFreeHeadroom.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragFreeHeadroom.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.utility.options;
+
+import static org.mmtk.policy.immix.ImmixConstants.DEFAULT_DEFRAG_FREE_HEADROOM;
+
+public class DefragFreeHeadroom extends org.vmutil.options.PagesOption {
+ /**
+ * Create the option.
+ */
+ public DefragFreeHeadroom() {
+ super(Options.set, "Defrag Free Headroom",
+ "Allow the defragmenter this amount of free headroom during defrag. For analysis purposes only!",
+ DEFAULT_DEFRAG_FREE_HEADROOM);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragFreeHeadroomFraction.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragFreeHeadroomFraction.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragFreeHeadroomFraction.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragFreeHeadroomFraction.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,33 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.options;
+
+import static org.mmtk.policy.immix.ImmixConstants.DEFAULT_DEFRAG_FREE_HEADROOM_FRACTION;
+
+public class DefragFreeHeadroomFraction extends org.vmutil.options.FloatOption {
+ /**
+ * Create the option.
+ */
+ public DefragFreeHeadroomFraction() {
+ super(Options.set, "Defrag Free Headroom Fraction",
+ "Allow the defragmenter this fraction of the heap size as free headroom during defrag. For analysis purposes only!",
+ DEFAULT_DEFRAG_FREE_HEADROOM_FRACTION);
+ }
+
+ /**
+ * Ensure the value is valid.
+ */
+ protected void validate() {
+ failIf((this.value < 0 || this.value > 1.0), "Ratio must be a float between 0 and 1");
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragHeadroom.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragHeadroom.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragHeadroom.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragHeadroom.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.utility.options;
+
+import static org.mmtk.policy.immix.ImmixConstants.DEFAULT_DEFRAG_HEADROOM;
+
+/**
+ */
+public class DefragHeadroom extends org.vmutil.options.PagesOption {
+ /**
+ * Create the option.
+ */
+ public DefragHeadroom() {
+ super(Options.set, "Defrag Headroom",
+ "Allow the defragmenter this amount of headroom during defrag.",
+ DEFAULT_DEFRAG_HEADROOM);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragHeadroomFraction.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragHeadroomFraction.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragHeadroomFraction.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragHeadroomFraction.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,33 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.options;
+
+import static org.mmtk.policy.immix.ImmixConstants.DEFAULT_DEFRAG_HEADROOM_FRACTION;
+
+public class DefragHeadroomFraction extends org.vmutil.options.FloatOption {
+ /**
+ * Create the option.
+ */
+ public DefragHeadroomFraction() {
+ super(Options.set, "Defrag Headroom Fraction",
+ "Allow the defrag this fraction of the heap as headroom during defrag.",
+ DEFAULT_DEFRAG_HEADROOM_FRACTION);
+ }
+
+ /**
+ * Ensure the value is valid.
+ */
+ protected void validate() {
+ failIf((this.value < 0 || this.value > 1.0), "Ratio must be a float between 0 and 1");
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragLineReuseRatio.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragLineReuseRatio.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragLineReuseRatio.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragLineReuseRatio.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,33 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.options;
+
+import static org.mmtk.policy.immix.ImmixConstants.DEFAULT_DEFRAG_LINE_REUSE_RATIO;
+
+public class DefragLineReuseRatio extends org.vmutil.options.FloatOption {
+ /**
+ * Create the option.
+ */
+ public DefragLineReuseRatio() {
+ super(Options.set, "Defrag Line Reuse Ratio",
+ "Blocks with this fraction marked may be reused for defrag allocation",
+ DEFAULT_DEFRAG_LINE_REUSE_RATIO);
+ }
+
+ /**
+ * Ensure the value is valid.
+ */
+ protected void validate() {
+ failIf((this.value <= 0 || this.value > 1.0), "Ratio must be a float between 0 and 1");
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragSimpleSpillThreshold.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragSimpleSpillThreshold.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragSimpleSpillThreshold.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragSimpleSpillThreshold.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,33 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.options;
+
+import static org.mmtk.policy.immix.ImmixConstants.DEFAULT_SIMPLE_SPILL_THRESHOLD;
+
+public class DefragSimpleSpillThreshold extends org.vmutil.options.FloatOption {
+ /**
+ * Create the option.
+ */
+ public DefragSimpleSpillThreshold() {
+ super(Options.set, "Defrag Simple Spill Threshold",
+ "Blocks with this fraction spilled will be defrag sources",
+ DEFAULT_SIMPLE_SPILL_THRESHOLD);
+ }
+
+ /**
+ * Ensure the value is valid.
+ */
+ protected void validate() {
+ failIf((this.value <= 0 || this.value > 1.0), "Ratio must be a float between 0 and 1");
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragStress.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragStress.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragStress.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DefragStress.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.utility.options;
+
+/**
+ * Should we force degfrag every time the immix space is collected?
+ */
+public final class DefragStress extends org.vmutil.options.BooleanOption {
+ /**
+ * Create the option.
+ */
+ public DefragStress() {
+ super(Options.set, "Defrag Stress",
+ "Should we force degfrag every time the immix space is collected?",
+ false);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DummyEnum.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DummyEnum.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DummyEnum.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/DummyEnum.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,33 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.options;
+
+/**
+ * A sample enumeration for testing.
+ */
+public final class DummyEnum extends org.vmutil.options.EnumOption {
+
+ // enumeration values.
+ public final int FOO = 0;
+ public final int BAR = 1;
+
+ /**
+ * Create the option.
+ */
+ public DummyEnum() {
+ super(Options.set, "Dummy Enum",
+ "This is a sample enumeration to test the options system",
+ new String[] {"foo", "bar"},
+ "foo");
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EagerCompleteSweep.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EagerCompleteSweep.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EagerCompleteSweep.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EagerCompleteSweep.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.utility.options;
+
+/**
+ * Should we eagerly finish sweeping at the start of a collection
+ */
+public final class EagerCompleteSweep extends org.vmutil.options.BooleanOption {
+ /**
+ * Create the option.
+ */
+ public EagerCompleteSweep() {
+ super(Options.set, "Eager Complete Sweep",
+ "Should we eagerly finish sweeping at the start of a collection",
+ false);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EagerMmapSpaces.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EagerMmapSpaces.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EagerMmapSpaces.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EagerMmapSpaces.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.utility.options;
+
+/**
+ * Should spaces be eagerly demand zero mmapped?
+ */
+public final class EagerMmapSpaces extends org.vmutil.options.BooleanOption {
+ /**
+ * Create the option.
+ */
+ public EagerMmapSpaces() {
+ super(Options.set, "Eager Mmap Spaces",
+ "If true, all spaces are eagerly demand zero mmapped at boot time",
+ false);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EchoOptions.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EchoOptions.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EchoOptions.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/EchoOptions.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.utility.options;
+
+/**
+ * Echo when options are set?
+ */
+public final class EchoOptions extends org.vmutil.options.BooleanOption {
+ /**
+ * Create the option.
+ */
+ public EchoOptions() {
+ super(Options.set, "Echo Options",
+ "Echo when options are set?",
+ false);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FixedNursery.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FixedNursery.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FixedNursery.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FixedNursery.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.utility.options;
+
+import org.mmtk.plan.Plan;
+
+/**
+ * Provide an lower and upper bound on nursery size.
+ *
+ * This option is not intended to be created directly, but via NurserySize.
+ */
+public final class FixedNursery extends org.vmutil.options.PagesOption {
+ // values
+ BoundedNursery boundedNursery;
+
+ /**
+ * Create the option
+ */
+ public FixedNursery(BoundedNursery boundedNursery) {
+ super(Options.set, "Fixed Nursery",
+ "Fix the minimum and maximum size of the nursery to this value",
+ Plan.DEFAULT_MIN_NURSERY);
+ this.boundedNursery = boundedNursery;
+ }
+
+ /**
+ * Nursery can not be empty.
+ */
+ protected void validate() {
+ failIf(value <= 0, "Can not have an empty nursery");
+ // Update upper bound.
+ boundedNursery.setBytes(this.getBytes());
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FragmentationStats.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FragmentationStats.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FragmentationStats.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FragmentationStats.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.utility.options;
+
+/**
+ * Option to print fragmentation information for the free list.
+ */
+public final class FragmentationStats extends org.vmutil.options.BooleanOption {
+ /**
+ * Create the option.
+ */
+ public FragmentationStats() {
+ super(Options.set, "Fragmentation Stats",
+ "Should we print fragmentation statistics for the free list allocator?",
+ false);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FullHeapSystemGC.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FullHeapSystemGC.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FullHeapSystemGC.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/FullHeapSystemGC.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.utility.options;
+
+/**
+ * Should a major GC be performed when a system GC is triggered?
+ */
+public final class FullHeapSystemGC extends org.vmutil.options.BooleanOption {
+ /**
+ * Create the option.
+ */
+ public FullHeapSystemGC() {
+ super(Options.set, "Full Heap System GC",
+ "Should a major GC be performed when a system GC is triggered?",
+ false);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCTimeCap.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCTimeCap.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCTimeCap.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCTimeCap.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.utility.options;
+
+/**
+ * Try to limit reference counting collections to this time cap.
+ */
+public final class GCTimeCap extends org.vmutil.options.MicrosecondsOption {
+ /**
+ * Create the option.
+ */
+ public GCTimeCap() {
+ super(Options.set, "GC Time Cap",
+ "Try to limit reference counting collections to this time cap",
+ 1000000);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyPort.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyPort.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyPort.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyPort.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.utility.options;
+
+/**
+ * Port number for GCSpy server to connect with visualiser.
+ */
+public final class GCspyPort extends org.vmutil.options.IntOption {
+ /**
+ * Create the option.
+ */
+ public GCspyPort() {
+ super(Options.set, "GCSpy Port",
+ "Port number for GCSpy server to connect with visualiser",
+ 0);
+ }
+
+ /**
+ * Ensure the port is valid.
+ */
+ protected void validate() {
+ failIf(this.value <= 0, "Unreasonable GCSpy port value");
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyTileSize.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyTileSize.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyTileSize.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyTileSize.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.utility.options;
+
+/**
+ * GCspy Tile Size.
+ */
+public final class GCspyTileSize extends org.vmutil.options.IntOption {
+ /**
+ * Create the option.
+ */
+ public GCspyTileSize() {
+ super(Options.set, "GCspy Tile Size",
+ "GCspy Tile Size",
+ 131072);
+ }
+
+ /**
+ * Ensure the tile size is positive
+ */
+ protected void validate() {
+ failIf(this.value <= 0, "Unreasonable gcspy tilesize");
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyWait.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyWait.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyWait.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GCspyWait.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.utility.options;
+
+/**
+ * Should the VM wait for the visualiser to connect?
+ */
+public final class GCspyWait extends org.vmutil.options.BooleanOption {
+ /**
+ * Create the option
+ */
+ public GCspyWait() {
+ super(Options.set, "GCSpy Wait",
+ "Should the VM wait for the visualiser to connect?",
+ false);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GenCycleDetection.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GenCycleDetection.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GenCycleDetection.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/GenCycleDetection.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.utility.options;
+
+/**
+ * Should we use a generational approach to cycle detection?
+ */
+public final class GenCycleDetection extends org.vmutil.options.BooleanOption {
+ /**
+ * Create the option.
+ */
+ public GenCycleDetection() {
+ super(Options.set, "Gen Cycle Detection",
+ "Should we use a generational approach to cycle detection?",
+ false);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/HarnessAll.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/HarnessAll.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/HarnessAll.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/HarnessAll.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.utility.options;
+
+/**
+ * Should we wrap the entire execution with a harnessBegin/harnessEnd?
+ */
+public final class HarnessAll extends org.vmutil.options.BooleanOption {
+ /**
+ * Create the option.
+ */
+ public HarnessAll() {
+ super(Options.set, "Harness All",
+ "Should we wrap the entire execution inside calls to harnessBegin and harnessEnd?",
+ false);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/IgnoreSystemGC.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/IgnoreSystemGC.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/IgnoreSystemGC.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/IgnoreSystemGC.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.utility.options;
+
+/**
+ * Should we ignore calls to java.lang.System.gc?
+ */
+public final class IgnoreSystemGC extends org.vmutil.options.BooleanOption {
+ /**
+ * Create the option.
+ */
+ public IgnoreSystemGC() {
+ super(Options.set, "Ignore System GC",
+ "Should we ignore calls to java.lang.System.gc?",
+ false);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/LineReuseRatio.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/LineReuseRatio.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/LineReuseRatio.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/LineReuseRatio.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.options;
+
+import static org.mmtk.policy.immix.ImmixConstants.DEFAULT_LINE_REUSE_RATIO;
+
+/**
+ */
+public class LineReuseRatio extends org.vmutil.options.FloatOption {
+ /**
+ * Create the option.
+ */
+ public LineReuseRatio() {
+ super(Options.set, "Line Reuse Ratio",
+ "Blocks with this fraction marked may be reused for allocation",
+ DEFAULT_LINE_REUSE_RATIO);
+ }
+
+ /**
+ * Ensure the value is valid.
+ */
+ protected void validate() {
+ failIf((this.value <= 0 || this.value > 1.0), "Ratio must be a float between 0 and 1");
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/MarkSweepMarkBits.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/MarkSweepMarkBits.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/MarkSweepMarkBits.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/MarkSweepMarkBits.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.utility.options;
+
+import org.mmtk.policy.MarkSweepSpace;
+
+/**
+ * Number of bits to use for the header cycle of mark sweep spaces.
+ */
+public final class MarkSweepMarkBits extends org.vmutil.options.IntOption {
+ /**
+ * Create the option.
+ */
+ public MarkSweepMarkBits() {
+ super(Options.set, "Mark Sweep Mark Bits",
+ "Number of bits to use for the header cycle of mark sweep spaces",
+ MarkSweepSpace.DEFAULT_MARKCOUNT_BITS);
+ }
+
+ /**
+ * Ensure the value is valid.
+ */
+ protected void validate() {
+ failIf(this.value <= 0, "Must provide at least one bit");
+ failIf(this.value > MarkSweepSpace.MAX_MARKCOUNT_BITS , "Only "+MarkSweepSpace.MAX_MARKCOUNT_BITS+" bits are reserved in MarkSweepSpace");
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/MetaDataLimit.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/MetaDataLimit.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/MetaDataLimit.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/MetaDataLimit.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.utility.options;
+
+/**
+ * Provide a bound on how much metadata is allowed before a GC is triggered.
+ */
+public final class MetaDataLimit extends org.vmutil.options.PagesOption {
+ /**
+ * Create the option.
+ */
+ public MetaDataLimit() {
+ super(Options.set, "Meta Data Limit",
+ "Trigger a GC if the meta data volume grows to this limit",
+ 4096);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NoFinalizer.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NoFinalizer.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NoFinalizer.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NoFinalizer.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.utility.options;
+
+/**
+ * Should finalization be disabled?
+ */
+public final class NoFinalizer extends org.vmutil.options.BooleanOption {
+ /**
+ * Create the option.
+ */
+ public NoFinalizer() {
+ super(Options.set, "No Finalizer",
+ "Should finalization be disabled?",
+ false);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NoReferenceTypes.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NoReferenceTypes.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NoReferenceTypes.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NoReferenceTypes.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.utility.options;
+
+/**
+ * Should reference type processing be disabled?
+ */
+public final class NoReferenceTypes extends org.vmutil.options.BooleanOption {
+ /**
+ * Create the option.
+ */
+ public NoReferenceTypes() {
+ super(Options.set, "No Reference Types",
+ "Should reference type processing be disabled?",
+ false);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NurserySize.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NurserySize.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NurserySize.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/NurserySize.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.utility.options;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * A composite option that provides a min/max interface to MMTk,
+ * and a fixed/bounded option interface to the VM/user.
+ */
+public final class NurserySize {
+ // values
+ private FixedNursery fixedNursery;
+ private BoundedNursery boundedNursery;
+
+ /**
+ * Create the options.
+ */
+ public NurserySize() {
+ boundedNursery = new BoundedNursery();
+ fixedNursery = new FixedNursery(boundedNursery);
+ }
+
+ /**
+ * Read the upper bound of the nursery size.
+ *
+ * @return maximum number of pages in the nursery.
+ */
+ @Uninterruptible
+ public int getMaxNursery() {
+ return boundedNursery.getPages();
+ }
+
+ /**
+ * Read the lower bound of the nursery size.
+ *
+ * @return minimum number of pages in the nursery.
+ */
+ @Uninterruptible
+ public int getMinNursery() {
+ return fixedNursery.getPages();
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/Options.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/Options.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/Options.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/Options.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,67 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.options;
+
+import org.vmutil.options.OptionSet;
+
+/**
+ * Repository for all option instances.
+ */
+public final class Options {
+ public static OptionSet set;
+
+ /* Other options */
+ public static BoundedNursery boundedNursery;
+ public static ConcurrentTrigger concurrentTrigger;
+ public static CycleFilterThreshold cycleFilterThreshold;
+ public static CycleMetaDataLimit cycleMetaDataLimit;
+ public static CycleTriggerThreshold cycleTriggerThreshold;
+ public static DebugAddress debugAddress;
+ public static DummyEnum dummyEnum;
+ public static DefragHeadroom defragHeadroom;
+ public static DefragHeadroomFraction defragHeadroomFraction;
+ public static DefragFreeHeadroom defragFreeHeadroom;
+ public static DefragFreeHeadroomFraction defragFreeHeadroomFraction;
+ public static DefragLineReuseRatio defragLineReuseRatio;
+ public static DefragSimpleSpillThreshold defragSimpleSpillThreshold;
+ public static DefragStress defragStress;
+ public static EagerCompleteSweep eagerCompleteSweep;
+ public static EagerMmapSpaces eagerMmapSpaces;
+ public static FixedNursery fixedNursery;
+ public static FragmentationStats fragmentationStats;
+ public static FullHeapSystemGC fullHeapSystemGC;
+ public static GCspyPort gcspyPort;
+ public static GCspyTileSize gcspyTileSize;
+ public static GCspyWait gcspyWait;
+ public static GCTimeCap gcTimeCap;
+ public static GenCycleDetection genCycleDetection;
+ public static HarnessAll harnessAll;
+ public static IgnoreSystemGC ignoreSystemGC;
+ public static LineReuseRatio lineReuseRatio;
+ public static MarkSweepMarkBits markSweepMarkBits;
+ public static MetaDataLimit metaDataLimit;
+ public static NoFinalizer noFinalizer;
+ public static NoReferenceTypes noReferenceTypes;
+ public static NurserySize nurserySize;
+ public static PerfMetric perfMetric;
+ public static PrintPhaseStats printPhaseStats;
+ public static ProtectOnRelease protectOnRelease;
+ public static SanityCheck sanityCheck;
+ public static StressFactor stressFactor;
+ public static TraceRate traceRate;
+ public static VariableSizeHeap variableSizeHeap;
+ public static VerboseFragmentationStats verboseFragmentationStats;
+ public static Verbose verbose;
+ public static VerboseTiming verboseTiming;
+ public static XmlStats xmlStats;
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/PerfMetric.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/PerfMetric.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/PerfMetric.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/PerfMetric.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.utility.options;
+
+/**
+ * Performance counter options.
+ */
+public class PerfMetric extends org.vmutil.options.EnumOption {
+ /**
+ * Create the option.
+ */
+ public PerfMetric() {
+ super(Options.set, "Perf Metric",
+ "Use this to select a performance metric to measure",
+ new String[] {"RI", "L1D_MISS", "L2_MISS", "DTLB_MISS", "ITLB_MISS", "ITLB_HIT", "BPU_TC", "TC_FLUSH", "L1I_MISS", "BRANCHES", "BRANCH_MISS"},
+ "RI");
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/PrintPhaseStats.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/PrintPhaseStats.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/PrintPhaseStats.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/PrintPhaseStats.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.utility.options;
+
+/**
+ * When printing statistics, should statistics for each
+ * gc-mutator phase be printed?
+ */
+public final class PrintPhaseStats extends org.vmutil.options.BooleanOption {
+ /**
+ * Create the option.
+ */
+ public PrintPhaseStats() {
+ super(Options.set, "Print Phase Stats",
+ "When printing statistics, should statistics for each gc-mutator phase be printed?",
+ false);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/ProtectOnRelease.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/ProtectOnRelease.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/ProtectOnRelease.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/ProtectOnRelease.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.utility.options;
+
+/**
+ * Should memory be protected on release?
+ */
+public final class ProtectOnRelease extends org.vmutil.options.BooleanOption {
+ /**
+ * Create the option.
+ */
+ public ProtectOnRelease() {
+ super(Options.set, "Protect On Release",
+ "Should memory be protected on release?",
+ false);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/SanityCheck.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/SanityCheck.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/SanityCheck.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/SanityCheck.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.utility.options;
+
+
+/**
+ * Should a major GC be performed when a system GC is triggered?
+ */
+public final class SanityCheck extends org.vmutil.options.BooleanOption {
+ /**
+ * Create the option.
+ */
+ public SanityCheck() {
+ super(Options.set, "Sanity Check",
+ "Perform sanity checks before and after each collection?",
+ false);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/StressFactor.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/StressFactor.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/StressFactor.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/StressFactor.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.utility.options;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.utility.Constants;
+
+/**
+ * Force frequent collections after amounts of allocation.
+ */
+public final class StressFactor extends org.vmutil.options.PagesOption {
+ /**
+ * Create the option, defaulting to the maximum possible value.
+ */
+ public StressFactor() {
+ super(Options.set, "Stress Factor",
+ "Force a collection after this much allocation",
+ Integer.MAX_VALUE >>> Constants.LOG_BYTES_IN_PAGE);
+ }
+
+ /**
+ * Ensure that the value is sensible.
+ */
+ public void validate() {
+ failIf(this.value < Plan.DEFAULT_POLL_FREQUENCY,
+ "Stress Factor must be at least equal to plan's poll frequency");
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/TraceRate.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/TraceRate.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/TraceRate.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/TraceRate.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.options;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * The granularity of the trace being produced.
+ */
+public final class TraceRate extends org.vmutil.options.IntOption
+ implements org.mmtk.utility.Constants {
+ /**
+ * Create the option.
+ */
+ public TraceRate() {
+ super(Options.set, "Trace Rate",
+ "The granularity of the trace being produced. By default, the trace has the maximum possible granularity.",
+ Integer.MAX_VALUE);
+ }
+
+ /**
+ * Return the appropriate value.
+ *
+ * @return the trace rate.
+ */
+ @Uninterruptible
+ public int getValue() {
+ return (this.value < BYTES_IN_ADDRESS) ? 1 : (this.value >> LOG_BYTES_IN_ADDRESS);
+ }
+
+ /**
+ * Trace rate must be positive.
+ */
+ protected void validate() {
+ failIf(value <= 0, "Can not have a negative trace rate");
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VariableSizeHeap.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VariableSizeHeap.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VariableSizeHeap.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VariableSizeHeap.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.utility.options;
+
+/**
+ * Should we shrink/grow the heap to adjust to application working set?
+ */
+public final class VariableSizeHeap extends org.vmutil.options.BooleanOption {
+ /**
+ * Create the option.
+ */
+ public VariableSizeHeap() {
+ super(Options.set, "Variable Size Heap",
+ "Should we shrink/grow the heap to adjust to application working set?",
+ true);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/Verbose.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/Verbose.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/Verbose.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/Verbose.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.utility.options;
+
+/**
+ * GC verbosity level.
+ */
+public final class Verbose extends org.vmutil.options.IntOption {
+ /**
+ * Create the option.
+ */
+ public Verbose() {
+ super(Options.set, "Verbose",
+ "GC verbosity level",
+ 0);
+ }
+
+ /**
+ * Only accept non-negative values.
+ */
+ protected void validate() {
+ failIf(this.value < 0, "Unreasonable verbosity level");
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VerboseFragmentationStats.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VerboseFragmentationStats.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VerboseFragmentationStats.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VerboseFragmentationStats.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.utility.options;
+
+/**
+ * Should we print verbose fragmentation statistics for the free list allocator?
+ */
+public final class VerboseFragmentationStats extends org.vmutil.options.BooleanOption {
+ /**
+ * Create the option.
+ */
+ public VerboseFragmentationStats() {
+ super(Options.set, "Verbose Fragmentation Stats",
+ "Should we print verbose fragmentation statistics for the free list allocator?",
+ false);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VerboseTiming.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VerboseTiming.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VerboseTiming.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/VerboseTiming.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.utility.options;
+
+/**
+ * Should we display detailed breakdown of where GC time is spent?
+ */
+public final class VerboseTiming extends org.vmutil.options.BooleanOption {
+ /**
+ * Create the option.
+ */
+ public VerboseTiming() {
+ super(Options.set, "Verbose Timing",
+ "Should we display detailed breakdown of where GC time is spent?",
+ false);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/XmlStats.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/XmlStats.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/XmlStats.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/options/XmlStats.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.utility.options;
+
+/**
+ * Display statistics and options in XML rather than himan-readable
+ * format.
+ */
+public final class XmlStats extends org.vmutil.options.BooleanOption {
+
+ /**
+ * Create the option.
+ */
+ public XmlStats() {
+ super(Options.set, "Xml Stats", "Print end-of-run statistics in XML format", false);
+ }
+
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityChecker.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityChecker.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityChecker.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityChecker.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,253 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.sanitychecker;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.plan.Trace;
+import org.mmtk.plan.Simple;
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.policy.Space;
+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 performs sanity checks for Simple collectors.
+ */
+ at Uninterruptible
+public final class SanityChecker implements Constants {
+
+ /* Counters */
+ public static long referenceCount;
+ public static long rootReferenceCount;
+ public static long danglingReferenceCount;
+ public static long nullReferenceCount;
+ public static long liveObjectCount;
+
+ public static final int DEAD = -2;
+ public static final int ALIVE = -1;
+ public static final int UNSURE = 0;
+
+ public static final int LOG_SANITY_DATA_SIZE = 24;
+
+ /* Tracing */
+ public Trace rootTrace;
+ public Trace checkTrace;
+ private final SanityDataTable sanityTable;
+ private boolean preGCSanity;
+
+ /* Local, but we only run the check trace single-threaded. */
+ final SanityTraceLocal checkTraceLocal;
+
+ /* Linear scanning */
+ private final SanityLinearScan scanner = new SanityLinearScan(this);
+
+ /****************************************************************************
+ * Constants
+ */
+ public SanityChecker() {
+ sanityTable = new SanityDataTable(Plan.sanitySpace, LOG_SANITY_DATA_SIZE);
+ checkTrace = new Trace(Plan.sanitySpace);
+ rootTrace = new Trace(Plan.sanitySpace);
+ checkTraceLocal = new SanityTraceLocal(checkTrace, this);
+ }
+
+ /**
+ * Perform any sanity checking collection phases.
+ *
+ * @param phaseId The id to proces
+ * @return True if the phase was handled.
+ */
+ @NoInline
+ public boolean collectionPhase(int phaseId) {
+ if (phaseId == Simple.SANITY_SET_PREGC) {
+ preGCSanity = true;
+ return true;
+ }
+
+ if (phaseId == Simple.SANITY_SET_POSTGC) {
+ preGCSanity = false;
+ return true;
+ }
+
+ if (phaseId == Simple.SANITY_PREPARE) {
+ Log.writeln("");
+ Log.write("============================== GC Sanity Checking ");
+ Log.writeln("==============================");
+ Log.writeln(preGCSanity ? "Performing Pre-GC Sanity Checks..." : "Performing Post-GC Sanity Checks...");
+
+ // Reset counters
+ referenceCount = 0;
+ nullReferenceCount = 0;
+ liveObjectCount = 0;
+ danglingReferenceCount = 0;
+ rootReferenceCount = 0;
+
+ // Clear data space
+ sanityTable.acquireTable();
+
+ // Root trace
+ rootTrace.prepareNonBlocking();
+
+ // Checking trace
+ checkTrace.prepareNonBlocking();
+ checkTraceLocal.prepare();
+ return true;
+ }
+
+ if (phaseId == Simple.SANITY_ROOTS) {
+ VM.scanning.resetThreadCounter();
+ return true;
+ }
+
+ if (phaseId == Simple.SANITY_BUILD_TABLE) {
+ // Trace, checking for dangling pointers
+ checkTraceLocal.completeTrace();
+ return true;
+ }
+
+ if (phaseId == Simple.SANITY_CHECK_TABLE) {
+ // Iterate over the reachable objects.
+ Address curr = sanityTable.getFirst();
+ while (!curr.isZero()) {
+ ObjectReference ref = SanityDataTable.getObjectReference(curr);
+ int normalRC = SanityDataTable.getNormalRC(curr);
+ int rootRC = SanityDataTable.getRootRC(curr);
+ if (!preGCSanity) {
+ int expectedRC = VM.activePlan.global().sanityExpectedRC(ref, rootRC);
+ switch (expectedRC) {
+ case SanityChecker.ALIVE:
+ case SanityChecker.UNSURE:
+ // Always ok.
+ break;
+ case SanityChecker.DEAD:
+ // Never ok.
+ Log.write("ERROR: SanityRC = ");
+ Log.write(normalRC);
+ Log.write(", SpaceRC = 0 ");
+ SanityChecker.dumpObjectInformation(ref);
+ break;
+ default:
+ // A mismatch in an RC space
+ if (normalRC != expectedRC && VM.activePlan.global().lastCollectionFullHeap()) {
+ Log.write("WARNING: SanityRC = ");
+ Log.write(normalRC);
+ Log.write(", SpaceRC = ");
+ Log.write(expectedRC);
+ Log.write(" ");
+ SanityChecker.dumpObjectInformation(ref);
+ break;
+ }
+ }
+ }
+ curr = sanityTable.getNext(curr);
+ }
+
+ if (!preGCSanity && VM.activePlan.global().lastCollectionFullHeap()) {
+ VM.activePlan.global().sanityLinearScan(scanner);
+ }
+ return true;
+ }
+
+ if (phaseId == Simple.SANITY_RELEASE) {
+ checkTrace.release();
+ sanityTable.releaseTable();
+ checkTraceLocal.release();
+
+ Log.writeln("roots\tobjects\trefs\tnull");
+ Log.write(rootReferenceCount);Log.write("\t");
+ Log.write(liveObjectCount);Log.write("\t");
+ Log.write(referenceCount);Log.write("\t");
+ Log.writeln(nullReferenceCount);
+
+ Log.write("========================================");
+ Log.writeln("========================================");
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Process an object during a linear scan of the heap. We have already checked
+ * all objects in the table. So we are only interested in objects that are not in
+ * the sanity table here. We are therefore only looking for leaks here.
+ *
+ * @param object The object being scanned.
+ */
+ public void scanProcessObject(ObjectReference object) {
+ if (sanityTable.getEntry(object, false).isZero()) {
+ // Is this a leak?
+ int expectedRC = VM.activePlan.global().sanityExpectedRC(object, 0);
+
+ if (expectedRC == SanityChecker.UNSURE) {
+ // Probably not.
+ return;
+ }
+
+ // Possibly
+ Log.write("WARNING: Possible leak, SpaceRC = ");
+ Log.write(expectedRC);
+ Log.write(" ");
+ SanityChecker.dumpObjectInformation(object);
+ }
+ }
+
+ /**
+ * Process an object during sanity checking, validating data,
+ * incrementing counters and enqueuing if this is the first
+ * visit to the object.
+ *
+ * @param object The object to mark.
+ * @param root True If the object is a root.
+ */
+ public void processObject(TraceLocal trace, ObjectReference object, boolean root) {
+ SanityChecker.referenceCount++;
+ if (root) SanityChecker.rootReferenceCount++;
+
+ if (object.isNull()) {
+ SanityChecker.nullReferenceCount++;
+ return;
+ }
+
+ if (Plan.SCAN_BOOT_IMAGE && Space.isInSpace(Plan.VM_SPACE, object)) {
+ return;
+ }
+
+ // Get the table entry.
+ Address tableEntry = sanityTable.getEntry(object, true);
+
+ if (SanityDataTable.incRC(tableEntry, root)) {
+ SanityChecker.liveObjectCount++;
+ trace.processNode(object);
+ }
+ }
+
+ /**
+ * Print out object information (used for warning and error messages)
+ *
+ * @param object The object to dump info for.
+ */
+ public static void dumpObjectInformation(ObjectReference object) {
+ Log.write(object);
+ Log.write(" [");
+ Log.write(Space.getSpaceForObject(object).getName());
+ Log.write("] ");
+ Log.writeln(VM.objectModel.getTypeDescriptor(object));
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityCheckerLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityCheckerLocal.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityCheckerLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityCheckerLocal.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.utility.sanitychecker;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.plan.Simple;
+import org.mmtk.utility.Constants;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class performs sanity checks for Simple collectors.
+ */
+ at Uninterruptible
+public final class SanityCheckerLocal implements Constants {
+
+ /* Trace */
+ final SanityRootTraceLocal rootTraceLocal;
+
+ /****************************************************************************
+ * Constants
+ */
+ public SanityCheckerLocal() {
+ rootTraceLocal = new SanityRootTraceLocal(Plan.sanityChecker.rootTrace);
+ }
+
+ /**
+ * Perform any sanity checking collection phases.
+ *
+ * @param phaseId The id to proces
+ * @param primary Perform local single threaded actions on this thread
+ * @return True if the phase was handled.
+ */
+ @NoInline
+ public boolean collectionPhase(int phaseId, boolean primary) {
+ if (phaseId == Simple.SANITY_PREPARE) {
+ rootTraceLocal.prepare();
+ return true;
+ }
+
+ if (phaseId == Simple.SANITY_ROOTS) {
+ VM.scanning.computeGlobalRoots(rootTraceLocal);
+ VM.scanning.computeThreadRoots(rootTraceLocal);
+ VM.scanning.computeStaticRoots(rootTraceLocal);
+ if (Plan.SCAN_BOOT_IMAGE) {
+ VM.scanning.computeBootImageRoots(rootTraceLocal);
+ }
+ rootTraceLocal.flush();
+ return true;
+ }
+
+ if (phaseId == Simple.SANITY_COPY_ROOTS) {
+ if (primary) {
+ rootTraceLocal.copyRootValuesTo(Plan.sanityChecker.checkTraceLocal);
+ }
+ return true;
+ }
+
+ if (phaseId == Simple.SANITY_RELEASE) {
+ rootTraceLocal.release();
+ return true;
+ }
+
+ return false;
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityDataTable.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityDataTable.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityDataTable.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityDataTable.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,161 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.sanitychecker;
+
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.policy.RawPageSpace;
+import org.mmtk.utility.Constants;
+import org.mmtk.utility.deque.*;
+import org.mmtk.utility.SimpleHashtable;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements a simple hashtable to store and retrieve per
+ * object information for sanity checking. <p>
+ *
+ * This class is not thread safe.
+ */
+ at Uninterruptible
+public final class SanityDataTable extends SimpleHashtable implements Constants {
+
+ /** The number of bits for the normal reference count */
+ private static final int NORMAL_RC_BITS = 25;
+
+ /** The mask for the normal reference count */
+ private static final int NORMAL_RC_MASK = (1 << 25) - 1;
+
+ /** The shift for the root reference count */
+ private static final int ROOT_RC_SHIFT = NORMAL_RC_BITS;
+
+ /** The increment to use for normal increments */
+ private static final int NORMAL_RC_INC = 1;
+
+ /** The increment to use for root increments */
+ private static final int ROOT_RC_INC = 1 << ROOT_RC_SHIFT;
+
+ /**
+ * Create a new data table of a specified size.
+ *
+ * @param rps The space to acquire the data structure from.
+ * @param logSize The log of the number of table entries.
+ */
+ public SanityDataTable(RawPageSpace rps, int logSize) {
+ super(rps, logSize, Extent.fromIntSignExtend(BYTES_IN_WORD));
+ }
+
+ /**
+ * Increment the data word for an object.
+ *
+ * @param entry The table entry.
+ * @param root True if this is a root reference.
+ * @return True if this is the first ref to that object.
+ */
+ @Inline
+ public static boolean incRC(Address entry, boolean root) {
+ Address data = SimpleHashtable.getPayloadAddress(entry);
+ int old = data.loadInt();
+ data.store(old + (root ? ROOT_RC_INC : NORMAL_RC_INC));
+ return (old == 0);
+ }
+
+ /**
+ * Push any entries that are only in this table, and not the
+ * passed table. This does not compare values.
+ *
+ * @param other The table to use for comparison.
+ * @param deque The buffer to push results onto.
+ */
+ public void pushNotInOther(SanityDataTable other,
+ ObjectReferenceDeque deque) {
+ Address entry = getFirst();
+ while (!entry.isZero()) {
+ Word key = SimpleHashtable.getKey(entry);
+ if (!other.contains(key)) {
+ deque.push(key.toAddress().toObjectReference());
+ }
+ entry = getNext(entry);
+ }
+ }
+
+
+ /**
+ * Given an address of an entry, read the reference count,
+ * excluding root references.
+ *
+ * @param entry The entry
+ * @return The reference count.
+ */
+ public static int getNormalRC(Address entry) {
+ return SimpleHashtable.getPayloadAddress(entry).loadInt() & NORMAL_RC_MASK;
+ }
+
+ /**
+ * Given an address of an entry, read the root reference count.
+ *
+ * @param entry The entry
+ * @return The root reference count.
+ */
+ public static int getRootRC(Address entry) {
+ return SimpleHashtable.getPayloadAddress(entry).loadInt() >>> ROOT_RC_SHIFT;
+ }
+
+ /**
+ * Given an address of an entry, read the total reference count.
+ *
+ * @param entry The entry
+ * @return The total reference count.
+ */
+ public static int getRC(Address entry) {
+ int val = SimpleHashtable.getPayloadAddress(entry).loadInt();
+ return (val & NORMAL_RC_MASK) + val >>> ROOT_RC_SHIFT;
+ }
+
+ /**
+ * Given an address of an entry, read the reference component.
+ *
+ * @param entry The entry
+ * @return The object reference.
+ */
+ public static ObjectReference getObjectReference(Address entry) {
+ return SimpleHashtable.getKey(entry).toAddress().toObjectReference();
+ }
+
+ /**
+ * Forward data table using the supplied trace. Note that the data is
+ * not hashed correctly, so only enumeration can be used without
+ * rehashing.
+ *
+ * @param trace The trace to use.
+ */
+ public void forwardTable(TraceLocal trace) {
+ Address entry = getFirst();
+ while (!entry.isZero()) {
+ ObjectReference obj = getObjectReference(entry);
+ SimpleHashtable.replaceKey(entry, trace.getForwardedReference(obj).toAddress().toWord());
+ entry = getNext(entry);
+ }
+ }
+
+ /**
+ * Get an entry for an object.
+ *
+ * @param object The object to find an entry for.
+ * @param create Create an entry if none exists?
+ * @return The entry address.
+ */
+ public Address getEntry(ObjectReference object, boolean create) {
+ return super.getEntry(object.toAddress().toWord(), create);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityLinearScan.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityLinearScan.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityLinearScan.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityLinearScan.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.utility.sanitychecker;
+
+import org.mmtk.utility.alloc.LinearScan;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.ObjectReference;
+
+/**
+ * This class performs sanity checks for Simple collectors.
+ */
+ at Uninterruptible
+final class SanityLinearScan extends LinearScan {
+
+ private final SanityChecker sanityChecker;
+ public SanityLinearScan(SanityChecker sanityChecker) {
+ this.sanityChecker = sanityChecker;
+ }
+
+ public void scan(ObjectReference object) {
+ sanityChecker.scanProcessObject(object);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityRootTraceLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityRootTraceLocal.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityRootTraceLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityRootTraceLocal.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.utility.sanitychecker;
+
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.plan.Trace;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements the parallel root-gathering part of a sanity check.
+ */
+ at Uninterruptible
+public final class SanityRootTraceLocal extends TraceLocal {
+
+ /**
+ * Constructor
+ */
+ public SanityRootTraceLocal(Trace trace) {
+ super(trace);
+ }
+
+ /****************************************************************************
+ *
+ * Object processing and tracing
+ */
+
+ /**
+ * Copy root values across to the 'real' single-threaded trace that will do
+ * the sanity checking.
+ */
+ @Inline
+ public void copyRootValuesTo(TraceLocal trace) {
+ while (!rootLocations.isEmpty()) {
+ ObjectReference object = rootLocations.pop().loadObjectReference();
+ if (!object.isNull()) {
+ trace.traceObject(object, true);
+ }
+ }
+ while (!values.isEmpty()) {
+ trace.traceObject(values.pop(), true);
+ }
+ }
+
+ /**
+ * Process delayed roots. This does not make sense for SanityRootTraceLocal.
+ * are empty.
+ */
+ @Inline
+ public void processRoots() {
+ VM.assertions.fail("SanityRootTraceLocal.processRoots called.");
+ }
+
+ /**
+ * Finishing processing all GC work. This does not make sense for SanityRootTraceLocal.
+ */
+ @Inline
+ public void completeTrace() {
+ VM.assertions.fail("SanityRootTraceLocal.completeTrace called.");
+ }
+
+ /**
+ * This method is the core method during the trace of the object graph.
+ * The role of this method is to:
+ *
+ * @param object The object to be traced.
+ * @param root Is this object a root?
+ * @return The new reference to the same object instance.
+ */
+ @Inline
+ public ObjectReference traceObject(ObjectReference object, boolean root) {
+ if (!root) VM.assertions.fail("SanityRootTraceLocal.traceObject called for non-root object.");
+ if (!object.isNull()) {
+ values.push(object);
+ }
+ 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) {
+ // We never move objects!
+ return true;
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityTraceLocal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityTraceLocal.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityTraceLocal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/sanitychecker/SanityTraceLocal.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.utility.sanitychecker;
+
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.plan.Trace;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.*;
+
+/**
+ * This class implements the simply sanity closure.
+ */
+ at Uninterruptible
+public final class SanityTraceLocal extends TraceLocal {
+
+ private final SanityChecker sanityChecker;
+
+ /**
+ * Constructor
+ */
+ public SanityTraceLocal(Trace trace, SanityChecker sanityChecker) {
+ super(trace);
+ this.sanityChecker = sanityChecker;
+ }
+
+ /****************************************************************************
+ *
+ * Object processing and tracing
+ */
+
+ /**
+ * This method is the core method during the trace of the object graph.
+ * The role of this method is to:
+ *
+ * @param object The object to be traced.
+ * @param root Is this object a root?
+ * @return The new reference to the same object instance.
+ */
+ @Inline
+ public ObjectReference traceObject(ObjectReference object, boolean root) {
+ sanityChecker.processObject(this, object, root);
+ 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) {
+ // We never move objects!
+ return true;
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/BooleanCounter.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/BooleanCounter.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/BooleanCounter.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/BooleanCounter.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,200 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.statistics;
+
+import org.mmtk.utility.Log;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements a simple boolean counter (counting number of
+ * phases where some boolean event is true).
+ */
+ at Uninterruptible public class BooleanCounter extends Counter {
+
+ /****************************************************************************
+ *
+ * Instance variables
+ */
+
+ private final boolean[] state;
+
+ protected int total = 0;
+ private boolean running = false;
+
+ /****************************************************************************
+ *
+ * Initialization
+ */
+
+ /**
+ * Constructor
+ *
+ * @param name The name to be associated with this counter
+ */
+ public BooleanCounter(String name) {
+ this(name, true, false);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param name The name to be associated with this counter
+ * @param start True if this counter is to be implicitly started
+ * when <code>startAll()</code> is called (otherwise the counter
+ * must be explicitly started).
+ */
+ public BooleanCounter(String name, boolean start) {
+ this(name, start, false);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param name The name to be associated with this counter
+ * @param start True if this counter is to be implicitly started
+ * when <code>startAll()</code> is called (otherwise the counter
+ * must be explicitly started).
+ * @param mergephases True if this counter does not separately
+ * report GC and Mutator phases.
+ */
+ public BooleanCounter(String name, boolean start, boolean mergephases) {
+ super(name, start, mergephases);
+ state = new boolean[Stats.MAX_PHASES];
+ for (int i = 0; i < Stats.MAX_PHASES; i++)
+ state[i] = false;
+ }
+
+ /****************************************************************************
+ *
+ * Counter-specific methods
+ */
+
+ /**
+ * Set the boolean to true for this phase, increment the total.
+ */
+ public void set() {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Stats.phase == Stats.MAX_PHASES -1 || !state[Stats.phase]);
+ state[Stats.phase] = true;
+ total++;
+ }
+
+ /****************************************************************************
+ *
+ * Generic counter control methods: start, stop, print etc
+ */
+
+ /**
+ * Start this counter
+ */
+ protected void start() {
+ if (!Stats.gatheringStats) return;
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!running);
+ running = true;
+ }
+
+ /**
+ * Stop this counter
+ */
+ protected void stop() {
+ if (!Stats.gatheringStats) return;
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(running);
+ running = false;
+ }
+
+ /**
+ * The phase has changed (from GC to mutator or mutator to GC).
+ * Take action with respect to the last phase if necessary.
+ * <b>Do nothing in this case.</b>
+ *
+ * @param oldPhase The last phase
+ */
+ void phaseChange(int oldPhase) {}
+
+ /**
+ * Print the value of this counter for the given phase. Print '0'
+ * for false, '1' for true.
+ *
+ * @param phase The phase to be printed
+ */
+ protected final void printCount(int phase) {
+ if (VM.VERIFY_ASSERTIONS && mergePhases())
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((phase | 1) == (phase + 1));
+ if (mergePhases())
+ printValue((state[phase] || state[phase + 1]) ? 1 : 0);
+ else
+ printValue((state[phase]) ? 1 : 0);
+ }
+
+ /**
+ * Print the current total number of 'true' phases for this counter
+ */
+ protected final void printTotal() {
+ int total = 0;
+ for (int p = 0; p <= Stats.phase; p++) {
+ total += (state[p]) ? 1 : 0;
+ }
+ printValue(total);
+ }
+
+ /**
+ * Print the current total number of 'true' phases for either the
+ * mutator or GC phase
+ *
+ * @param mutator True if the total for the mutator phases is to be
+ * printed (otherwise the total for the GC phases will be printed).
+ */
+ protected final void printTotal(boolean mutator) {
+ int total = 0;
+ for (int p = (mutator) ? 0 : 1; p <= Stats.phase; p += 2) {
+ total += (state[p]) ? 1 : 0;
+ }
+ printValue(total);
+ }
+
+ /**
+ * Print the current minimum value for either the mutator or GC
+ * phase. <b>Do nothing in this case.</b>
+ *
+ * @param mutator True if the minimum for the mutator phase is to be
+ * printed (otherwise the minimum for the GC phase will be printed).
+ */
+ protected final void printMin(boolean mutator) {}
+
+ /**
+ * Print the current maximum value for either the mutator or GC
+ * phase. <b>Do nothing in this case.</b>
+ *
+ * @param mutator True if the maximum for the mutator phase is to be
+ * printed (otherwise the maximum for the GC phase will be printed).
+ */
+ protected final void printMax(boolean mutator) {}
+
+ /**
+ * Print the given value
+ *
+ * @param value The value to be printed
+ */
+ void printValue(int value) {
+ Log.write(value);
+ }
+
+ /**
+ * Print statistics for the most recent phase
+ */
+ public void printLast() {
+ if (Stats.phase > 0) printCount(Stats.phase - 1);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Counter.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Counter.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Counter.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Counter.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,173 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.statistics;
+
+import org.vmmagic.pragma.*;
+
+/**
+ *
+ * This abstract class describes the interface of a generic counter.
+ */
+ at Uninterruptible public abstract class Counter {
+
+ /****************************************************************************
+ *
+ * Instance variables
+ */
+
+ private final String name;
+ private final boolean start;
+ private final boolean mergephases;
+
+ /**
+ * Allow for counters whose values are too complex to be simply printed out.
+ */
+ protected boolean complex = false;
+
+ /****************************************************************************
+ *
+ * Initialization
+ */
+
+ /**
+ * Constructor
+ *
+ * @param name The name to be associated with this counter
+ */
+ Counter(String name) {
+ this(name, true, false);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param name The name to be associated with this counter
+ * @param start True if this counter is to be implicitly started
+ * when <code>startAll()</code> is called (otherwise the counter
+ * must be explicitly started).
+ */
+ Counter(String name, boolean start) {
+ this(name, start, false);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param name The name to be associated with this counter
+ * @param start True if this counter is to be implicitly started
+ * when <code>startAll()</code> is called (otherwise the counter
+ * must be explicitly started).
+ * @param mergephases True if this counter does not separately
+ * report GC and Mutator phases.
+ */
+ Counter(String name, boolean start, boolean mergephases) {
+ this.name = name;
+ this.start = start;
+ this.mergephases = mergephases;
+ Stats.newCounter(this);
+ }
+
+ /****************************************************************************
+ *
+ * Counter control methods: start, stop, print etc
+ */
+
+ /**
+ * Start this counter
+ */
+ abstract void start();
+
+ /**
+ * Stop this counter
+ */
+ abstract void stop();
+
+ /**
+ * The phase has changed (from GC to mutator or mutator to GC).
+ * Take action with respect to the last phase if necessary.
+ *
+ * @param oldPhase The last phase
+ */
+ abstract void phaseChange(int oldPhase);
+
+ /**
+ * Print the value of this counter for the given phase
+ *
+ * @param phase The phase to be printed
+ */
+ abstract void printCount(int phase);
+
+ /**
+ * Print the current total for this counter
+ */
+ abstract void printTotal();
+
+ /**
+ * Print the current total for either the mutator or GC phase
+ *
+ * @param mutator True if the total for the mutator phases is to be
+ * printed (otherwise the total for the GC phases will be printed).
+ */
+ abstract void printTotal(boolean mutator);
+
+ /**
+ * Print the current minimum value for either the mutator or GC phase
+ *
+ * @param mutator True if the minimum for the mutator phase is to be
+ * printed (otherwise the minimum for the GC phase will be printed).
+ */
+ abstract void printMin(boolean mutator);
+
+ /**
+ * Print the current maximum value for either the mutator or GC phase
+ *
+ * @param mutator True if the maximum for the mutator phase is to be
+ * printed (otherwise the maximum for the GC phase will be printed).
+ */
+ abstract void printMax(boolean mutator);
+
+ /**
+ * Print statistics for the most recent phase
+ */
+ public void printLast() {
+ if (Stats.phase > 0) printCount(Stats.phase - 1);
+ }
+
+
+ /****************************************************************************
+ *
+ * Accessor methods
+ */
+
+ /**
+ * Return the name of this counter
+ * @return The name of this counter
+ */
+ String getName() { return name; }
+
+ /**
+ * Return true if this counter is implicitly started when
+ * <code>startAll()</code> is called.
+ * @return True if this counter is implicitly started when
+ * <code>startAll()</code> is called.
+ */
+ boolean getStart() { return start; }
+
+ /**
+ * Return true if this counter will merge stats for GC and mutator phases.
+ * @return True if this counter will merge stats for GC and mutator phases.
+ */
+ boolean mergePhases() { return mergephases; }
+
+ boolean isComplex() { return complex; }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/EventCounter.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/EventCounter.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/EventCounter.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/EventCounter.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,230 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.statistics;
+
+import org.mmtk.utility.Log;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements a simple event counter (counting number
+ * events that occur for each phase).
+ */
+ at Uninterruptible public class EventCounter extends Counter {
+
+ /****************************************************************************
+ *
+ * Instance variables
+ */
+
+ private final long[] count;
+
+ protected long totalCount = 0;
+ private boolean running = false;
+
+ /****************************************************************************
+ *
+ * Initialization
+ */
+
+ /**
+ * Constructor
+ *
+ * @param name The name to be associated with this counter
+ */
+ public EventCounter(String name) {
+ this(name, true, false);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param name The name to be associated with this counter
+ * @param start True if this counter is to be implicitly started
+ * when <code>startAll()</code> is called (otherwise the counter
+ * must be explicitly started).
+ */
+ public EventCounter(String name, boolean start) {
+ this(name, start, false);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param name The name to be associated with this counter
+ * @param start True if this counter is to be implicitly started
+ * when <code>startAll()</code> is called (otherwise the counter
+ * must be explicitly started).
+ * @param mergephases True if this counter does not separately
+ * report GC and Mutator phases.
+ */
+ public EventCounter(String name, boolean start, boolean mergephases) {
+ super(name, start, mergephases);
+ count = new long[Stats.MAX_PHASES];
+ }
+
+ /****************************************************************************
+ *
+ * Counter-specific methods
+ */
+
+ /**
+ * Increment the event counter
+ */
+ public void inc() {
+ if (running) inc(1);
+ }
+
+ /**
+ * Increment the event counter by <code>value</code>
+ *
+ * @param value The amount by which the counter should be incremented.
+ */
+ public void inc(int value) {
+ if (running) totalCount += value;
+ }
+
+ /****************************************************************************
+ *
+ * Generic counter control methods: start, stop, print etc
+ */
+
+ /**
+ * Start this counter
+ */
+ protected void start() {
+ if (!Stats.gatheringStats) return;
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!running);
+ running = true;
+ }
+
+ /**
+ * Stop this counter
+ */
+ protected void stop() {
+ if (!Stats.gatheringStats) return;
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(running);
+ running = false;
+ }
+
+ /**
+ * The phase has changed (from GC to mutator or mutator to GC).
+ * Take action with respect to the last phase if necessary.
+ * <b>Do nothing in this case.</b>
+ *
+ * @param oldPhase The last phase
+ */
+ void phaseChange(int oldPhase) {
+ if (running) {
+ count[oldPhase] = totalCount;
+ totalCount = 0;
+ }
+ }
+
+ /**
+ * Print the value of this counter for the given phase. Print '0'
+ * for false, '1' for true.
+ *
+ * @param phase The phase to be printed
+ */
+ protected final void printCount(int phase) {
+ if (VM.VERIFY_ASSERTIONS && mergePhases())
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((phase | 1) == (phase + 1));
+ if (mergePhases())
+ printValue(count[phase] + count[phase + 1]);
+ else
+ printValue(count[phase]);
+ }
+
+ /**
+ * Print the current value for this counter (mid-phase)
+ */
+ public final void printCurrent() {
+ printValue(totalCount);
+ }
+
+ /**
+ * Print the current total for this counter
+ */
+ public final void printTotal() {
+ long total = 0;
+ for (int p = 0; p <= Stats.phase; p++) {
+ total += count[p];
+ }
+ printValue(total);
+ }
+
+ /**
+ * Print the current total for either the mutator or GC phase
+ *
+ * @param mutator True if the total for the mutator phases is to be
+ * printed (otherwise the total for the GC phases will be printed).
+ */
+ protected final void printTotal(boolean mutator) {
+ long total = 0;
+ for (int p = (mutator) ? 0 : 1; p <= Stats.phase; p += 2) {
+ total += count[p];
+ }
+ printValue(total);
+ }
+
+ /**
+ * Print the current minimum value for either the mutator or GC
+ * phase.
+ *
+ * @param mutator True if the minimum for the mutator phase is to be
+ * printed (otherwise the minimum for the GC phase will be printed).
+ */
+ protected final void printMin(boolean mutator) {
+ int p = (mutator) ? 0 : 1;
+ long min = count[p];
+ for (; p < Stats.phase; p += 2) {
+ if (count[p] < min) min = count[p];
+ }
+ printValue(min);
+ }
+
+ /**
+ * Print the current maximum value for either the mutator or GC
+ * phase.
+ *
+ * @param mutator True if the maximum for the mutator phase is to be
+ * printed (otherwise the maximum for the GC phase will be printed).
+ */
+ protected final void printMax(boolean mutator) {
+ int p = (mutator) ? 0 : 1;
+ long max = count[p];
+ for (; p < Stats.phase; p += 2) {
+ if (count[p] > max) max = count[p];
+ }
+ printValue(max);
+ }
+
+ /**
+ * Print the given value
+ *
+ * @param value The value to be printed
+ */
+ void printValue(long value) {
+ Log.write(value);
+ }
+
+ /**
+ * Print statistics for the most recent phase
+ */
+ public void printLast() {
+ if (Stats.phase > 0) printCount(Stats.phase - 1);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/LongCounter.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/LongCounter.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/LongCounter.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/LongCounter.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,215 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.statistics;
+
+import org.mmtk.utility.Log;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This abstract class implements a simple counter (counting some
+ * integer (long) value for each phase).
+ */
+ at Uninterruptible public abstract class LongCounter extends Counter {
+
+ /****************************************************************************
+ *
+ * Instance variables
+ */
+
+ private final long[] count;
+
+ private long startValue = 0;
+ protected long totalCount = 0;
+ private boolean running = false;
+
+ /****************************************************************************
+ *
+ * Initialization
+ */
+
+ /**
+ * Constructor
+ *
+ * @param name The name to be associated with this counter
+ */
+ LongCounter(String name) {
+ this(name, true, false);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param name The name to be associated with this counter
+ * @param start True if this counter is to be implicitly started
+ * when <code>startAll()</code> is called (otherwise the counter
+ * must be explicitly started).
+ */
+ LongCounter(String name, boolean start) {
+ this(name, start, false);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param name The name to be associated with this counter
+ * @param start True if this counter is to be implicitly started
+ * when <code>startAll()</code> is called (otherwise the counter
+ * must be explicitly started).
+ * @param mergephases True if this counter does not separately
+ * report GC and Mutator phases.
+ */
+ LongCounter(String name, boolean start, boolean mergephases) {
+ super(name, start, mergephases);
+ count = new long[Stats.MAX_PHASES];
+ }
+
+ /****************************************************************************
+ *
+ * Counter-specific methods
+ */
+ protected abstract long getCurrentValue();
+
+ /****************************************************************************
+ *
+ * Generic counter control methods: start, stop, print etc
+ */
+
+ /**
+ * Start this counter
+ */
+ public void start() {
+ if (!Stats.gatheringStats) return;
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!running);
+ running = true;
+ startValue = getCurrentValue();
+ }
+
+ /**
+ * Stop this counter
+ */
+ public void stop() {
+ if (!Stats.gatheringStats) return;
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(running);
+ running = false;
+ long delta = getCurrentValue() - startValue;
+ count[Stats.phase] += delta;
+ totalCount += delta;
+ }
+
+ /**
+ * The phase has changed (from GC to mutator or mutator to GC).
+ * Take action with respect to the last phase if necessary.
+ * <b>Do nothing in this case.</b>
+ *
+ * @param oldPhase The last phase
+ */
+ protected void phaseChange(int oldPhase) {
+ if (running) {
+ long now = getCurrentValue();
+ long delta = now - startValue;
+ count[oldPhase] += delta;
+ totalCount += delta;
+ startValue = now;
+ }
+ }
+
+ /**
+ * Print the value of this counter for the given phase. Print '0'
+ * for false, '1' for true.
+ *
+ * @param phase The phase to be printed
+ */
+ protected final void printCount(int phase) {
+ if (VM.VERIFY_ASSERTIONS && mergePhases())
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((phase | 1) == (phase + 1));
+ if (mergePhases())
+ printValue(count[phase] + count[phase + 1]);
+ else
+ printValue(count[phase]);
+ }
+
+ /**
+ * Print the current total for this counter
+ */
+ public final void printTotal() {
+ printValue(totalCount);
+ }
+
+
+ /**
+ * Get the total as at the lasts phase
+ *
+ * @return The total as at the last phase
+ */
+ long getLastTotal() {
+ return totalCount;
+ }
+
+ /**
+ * Print the current total for either the mutator or GC phase
+ *
+ * @param mutator True if the total for the mutator phases is to be
+ * printed (otherwise the total for the GC phases will be printed).
+ */
+ protected final void printTotal(boolean mutator) {
+ long total = 0;
+ for (int p = (mutator) ? 0 : 1; p <= Stats.phase; p += 2) {
+ total += count[p];
+ }
+ printValue(total);
+ }
+
+ /**
+ * Print the current minimum value for either the mutator or GC
+ * phase.
+ *
+ * @param mutator True if the minimum for the mutator phase is to be
+ * printed (otherwise the minimum for the GC phase will be printed).
+ */
+ protected final void printMin(boolean mutator) {
+ int p = (mutator) ? 0 : 1;
+ long min = count[p];
+ for (; p < Stats.phase; p += 2) {
+ if (count[p] < min) min = count[p];
+ }
+ printValue(min);
+ }
+
+ /**
+ * Print the current maximum value for either the mutator or GC
+ * phase.
+ *
+ * @param mutator True if the maximum for the mutator phase is to be
+ * printed (otherwise the maximum for the GC phase will be printed).
+ */
+ protected final void printMax(boolean mutator) {
+ int p = (mutator) ? 0 : 1;
+ long max = count[p];
+ for (; p < Stats.phase; p += 2) {
+ if (count[p] > max) max = count[p];
+ }
+ printValue(max);
+ }
+
+ /**
+ * Print the given value
+ *
+ * @param value The value to be printed
+ */
+ void printValue(long value) {
+ Log.write(value);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/PerfCounter.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/PerfCounter.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/PerfCounter.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/PerfCounter.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.utility.statistics;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements a simple performance counter, used to gather
+ * data from hardware performance counters.
+ */
+ at Uninterruptible
+public class PerfCounter extends LongCounter {
+
+ /****************************************************************************
+ *
+ * Initialization
+ */
+
+ /**
+ * Constructor
+ *
+ * @param name The name to be associated with this counter
+ */
+ public PerfCounter(String name) {
+ this(name, true, false);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param name The name to be associated with this counter
+ * @param start True if this counter is to be implicitly started at
+ * boot time (otherwise the counter must be explicitly started).
+ */
+ public PerfCounter(String name, boolean start) {
+ this(name, start, false);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param name The name to be associated with this counter
+ * @param start True if this counter is to be implicitly started at
+ * boot time (otherwise the counter must be explicitly started).
+ * @param gconly True if this counter only pertains to (and
+ * therefore functions during) GC phases.
+ */
+ public PerfCounter(String name, boolean start, boolean gconly) {
+ super(name, start, gconly);
+ }
+
+ /****************************************************************************
+ *
+ * Counter-specific methods
+ */
+
+ /**
+ * Get the current value for this counter
+ *
+ * @return The current value for this counter
+ */
+ @Inline
+ protected final long getCurrentValue() {
+ return VM.statistics.perfCtrReadMetric();
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/SizeCounter.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/SizeCounter.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/SizeCounter.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/SizeCounter.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,138 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.statistics;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements a simple counter of events of different sizes
+ * (eg object allocations, where total number of objects and total
+ * volume of objects would be counted).
+ *
+ * The counter is trivially composed from two event counters (one for
+ * counting the number of events, the other for counting the volume).
+ */
+ at Uninterruptible public class SizeCounter {
+
+ /****************************************************************************
+ *
+ * Instance variables
+ */
+ private EventCounter units;
+ private EventCounter volume;
+
+ /****************************************************************************
+ *
+ * Initialization
+ */
+
+ /**
+ * Constructor
+ *
+ * @param name The name to be associated with this counter
+ */
+ public SizeCounter(String name) {
+ this(name, true, false);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param name The name to be associated with this counter
+ * @param start True if this counter is to be implicitly started
+ * when <code>startAll()</code> is called (otherwise the counter
+ * must be explicitly started).
+ */
+ public SizeCounter(String name, boolean start) {
+ this(name, start, false);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param name The name to be associated with this counter
+ * @param start True if this counter is to be implicitly started
+ * when <code>startAll()</code> is called (otherwise the counter
+ * must be explicitly started).
+ * @param mergephases True if this counter does not separately
+ * report GC and Mutator phases.
+ */
+ public SizeCounter(String name, boolean start, boolean mergephases) {
+ units = new EventCounter(name, start, mergephases);
+ volume = new EventCounter(name + "Volume", start, mergephases);
+ }
+
+ /****************************************************************************
+ *
+ * Counter-specific methods
+ */
+
+ /**
+ * Increment the event counter by <code>value</code>
+ *
+ * @param value The amount by which the counter should be incremented.
+ */
+ public void inc(int value) {
+ units.inc();
+ volume.inc(value);
+ }
+
+ /****************************************************************************
+ *
+ * Generic counter control methods: start, stop, print etc
+ */
+
+ /**
+ * Start this counter
+ */
+ public void start() {
+ units.start();
+ volume.start();
+ }
+
+ /**
+ * Stop this counter
+ */
+ public void stop() {
+ units.stop();
+ volume.stop();
+ }
+
+ /**
+ * Print current (mid-phase) units
+ */
+ public void printCurrentUnits() {
+ units.printCurrent();
+ }
+
+ /**
+ * Print (mid-phase) volume
+ */
+ public void printCurrentVolume() {
+ volume.printCurrent();
+ }
+
+ /**
+ * Print units
+ */
+ public void printUnits() {
+ units.printTotal();
+ }
+
+ /**
+ * Print volume
+ */
+ public void printVolume() {
+ volume.printTotal();
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Stats.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Stats.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Stats.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Stats.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,378 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.statistics;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.utility.Log;
+import org.mmtk.utility.options.Options;
+import org.mmtk.utility.options.PrintPhaseStats;
+import org.mmtk.utility.options.XmlStats;
+
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements basic statistics functionality
+ */
+ at Uninterruptible public class Stats {
+
+ /****************************************************************************
+ *
+ * Class variables
+ */
+
+ public static final boolean GATHER_MARK_CONS_STATS = false;
+
+ /** Maximum number of gc/mutator phases that can be counted */
+ static final int MAX_PHASES = 1 << 12;
+ /** Maximum number of counters that can be in operation */
+ static final int MAX_COUNTERS = 100;
+
+ private static int counters = 0;
+ private static Counter[] counter;
+ static int phase = 0;
+ private static int gcCount = 0;
+ static boolean gatheringStats = false;
+ static boolean exceededPhaseLimit = false;
+
+ /****************************************************************************
+ *
+ * Initialization
+ */
+
+ /**
+ * Class initializer. This is executed <i>prior</i> to bootstrap
+ * (i.e. at "build" time). This is where key <i>global</i>
+ * instances are allocated. These instances will be incorporated
+ * into the boot image by the build process.
+ */
+ static {
+ counter = new Counter[MAX_COUNTERS];
+ Options.printPhaseStats = new PrintPhaseStats();
+ Options.xmlStats = new XmlStats();
+ }
+
+ /**
+ * Add a new counter to the set of managed counters.
+ *
+ * @param ctr The counter to be added.
+ */
+ @Interruptible
+ static void newCounter(Counter ctr) {
+ if (counters < (MAX_COUNTERS - 1)) {
+ counter[counters++] = ctr;
+ } else {
+ Log.writeln("Warning: number of stats counters exceeds maximum");
+ }
+ }
+
+ /**
+ * Start a new GC phase. This means notifying each counter of the
+ * phase change.
+ */
+ public static void startGC() {
+ gcCount++;
+ if (!gatheringStats) return;
+ if (phase < MAX_PHASES - 1) {
+ for (int c = 0; c < counters; c++) {
+ counter[c].phaseChange(phase);
+ }
+ phase++;
+ } else if (!exceededPhaseLimit) {
+ Log.writeln("Warning: number of GC phases exceeds MAX_PHASES");
+ exceededPhaseLimit = true;
+ }
+ }
+
+ /**
+ * End a GC phase. This means notifying each counter of the phase
+ * change.
+ */
+ public static void endGC() {
+ if (!gatheringStats) return;
+ if (phase < MAX_PHASES - 1) {
+ for (int c = 0; c < counters; c++) {
+ counter[c].phaseChange(phase);
+ }
+ phase++;
+ } else if (!exceededPhaseLimit) {
+ Log.writeln("Warning: number of GC phases exceeds MAX_PHASES");
+ exceededPhaseLimit = true;
+ }
+ }
+
+ /**
+ * Start all implicitly started counters (i.e. those for whom
+ * <code>start == true</code>).
+ */
+ public static void startAll() {
+ if (gatheringStats) {
+ Log.writeln("Error: calling Stats.startAll() while stats running");
+ Log.writeln(" verbosity > 0 and the harness mechanism may be conflicitng");
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(false);
+ }
+ gatheringStats = true;
+ for (int c = 0; c < counters; c++) {
+ if (counter[c].getStart())
+ counter[c].start();
+ }
+ if (Options.xmlStats.getValue()) {
+ Xml.begin();
+ Xml.openTag("mmtk-stats");
+ Xml.end();
+ }
+ }
+
+ /**
+ * Stop all counters
+ */
+ @Interruptible
+ public static void stopAll() {
+ stopAllCounters();
+ Stats.printStats();
+ if (Options.xmlStats.getValue()) {
+ Xml.begin();
+ Xml.closeTag("mmtk-stats");
+ Xml.end();
+ }
+ }
+
+ /**
+ * Stop all counters
+ */
+ private static void stopAllCounters() {
+ for (int c = 0; c < counters; c++) {
+ if (counter[c].getStart())
+ counter[c].stop();
+ }
+ gatheringStats = false;
+ }
+
+ @Interruptible
+ public static void printStats() {
+ if (exceededPhaseLimit) {
+ Log.writeln("Warning: number of GC phases exceeds MAX_PHASES. Statistics are truncated.");
+ }
+ if (Options.xmlStats.getValue())
+ printStatsXml();
+ else
+ printStatsPlain();
+ }
+
+ /**
+ * Print out statistics
+ */
+ @Interruptible
+ public static void printStatsPlain() {
+ if (Options.printPhaseStats.getValue())
+ printPhases();
+ printTotals();
+ }
+
+ /**
+ * Print out statistics totals
+ */
+ @Interruptible
+ public static void printTotals() {
+ Log.writeln("============================ MMTk Statistics Totals ============================");
+ printColumnNames();
+ Log.write(phase/2); Log.write("\t");
+ for (int c = 0; c < counters; c++) {
+ if (counter[c].mergePhases()) {
+ counter[c].printTotal(); Log.write("\t");
+ } else {
+ counter[c].printTotal(true); Log.write("\t");
+ counter[c].printTotal(false); Log.write("\t");
+ }
+ }
+ Log.writeln();
+ Log.write("Total time: ");
+ Plan.totalTime.printTotal(); Log.writeln(" ms");
+ Log.writeln("------------------------------ End MMTk Statistics -----------------------------");
+ }
+
+ /**
+ * Print out statistics for each mutator/gc phase
+ */
+ @Interruptible
+ public static void printPhases() {
+ Log.writeln("--------------------- MMTk Statistics Per GC/Mutator Phase ---------------------");
+ printColumnNames();
+ for (int p = 0; p <= phase; p += 2) {
+ Log.write((p/2)+1); Log.write("\t");
+ for (int c = 0; c < counters; c++) {
+ if (counter[c].mergePhases()) {
+ counter[c].printCount(p); Log.write("\t");
+ } else {
+ counter[c].printCount(p); Log.write("\t");
+ counter[c].printCount(p+1); Log.write("\t");
+ }
+ }
+ Log.writeln();
+ }
+ }
+
+ /**
+ * Print out statistics column names
+ */
+ @Interruptible
+ private static void printColumnNames() {
+ Log.write("GC\t");
+ for (int c = 0; c < counters; c++) {
+ if (counter[c].mergePhases()) {
+ Log.write(counter[c].getName());
+ Log.write("\t");
+ } else {
+ Log.write(counter[c].getName());
+ Log.write(".mu\t");
+ Log.write(counter[c].getName());
+ Log.write(".gc\t");
+ }
+ }
+ Log.writeln();
+ }
+
+ /* ****************************************************************
+ *
+ * Statistics output in xml format
+ */
+
+ /**
+ * Print command-line options and statistics in XML format
+ */
+ @Interruptible
+ public static void printStatsXml() {
+ Xml.begin();
+ Options.set.logXml();
+ VM.config.printConfigXml();
+ if (Options.printPhaseStats.getValue())
+ printPhasesXml();
+ printTotalsXml();
+ Xml.end();
+ }
+
+ private static void openStatXml(String name) {
+ Xml.openMinorTag("stat");
+ Xml.attribute("name", name);
+ }
+
+ private static void closeStatXml() {
+ Xml.closeMinorTag();
+ }
+
+ enum Phase {
+ MUTATOR("mu"), GC("gc"), COMBINED("all");
+
+ private final String name;
+ Phase(String name) {
+ this.name = name;
+ }
+ public String toString() { return name; }
+ }
+
+ /**
+ * Print out statistics totals in Xml format
+ */
+ @Interruptible
+ public static void printTotalsXml() {
+ Xml.openTag("mmtk-stats-totals");
+ Xml.singleValue("gc", phase/2);
+ for (int c = 0; c < counters; c++) {
+ if (!counter[c].isComplex())
+ if (counter[c].mergePhases()) {
+ printTotalXml(counter[c],Phase.COMBINED);
+ } else {
+ printTotalXml(counter[c],Phase.MUTATOR);
+ printTotalXml(counter[c],Phase.GC);
+ }
+ }
+ Xml.singleValue("total-time",Plan.totalTime.getTotalMillis(),"ms");
+ Xml.closeTag("mmtk-stats-totals");
+ }
+
+ /**
+ * Print a single total in an xml tag
+ *
+ * @param c The counter
+ * @param phase The phase
+ */
+ @Interruptible
+ private static void printTotalXml(Counter c, Phase phase) {
+ openStatXml(c.getName());
+ Xml.openAttribute("value");
+ if (phase == Phase.COMBINED) {
+ c.printTotal();
+ } else {
+ c.printTotal(phase == Phase.MUTATOR);
+ Xml.closeAttribute();
+ Xml.openAttribute("phase");
+ Log.write(phase.toString());
+ }
+ Xml.closeAttribute();
+ closeStatXml();
+ }
+
+ /**
+ * Print a single phase counter in an xml tag
+ *
+ * @param c The counter
+ * @param p The phase number
+ * @param phase The phase (null, "mu" or "gc")
+ */
+ @Interruptible
+ private static void printPhaseStatXml(Counter c, int p, Phase phase) {
+ openStatXml(c.getName());
+ Xml.openAttribute("value");
+ if (phase == Phase.COMBINED) {
+ c.printCount(p);
+ } else {
+ c.printCount(p);
+ Xml.closeAttribute();
+ Xml.openAttribute("phase");
+ Log.write(phase.name);
+ }
+ Xml.closeAttribute();
+ closeStatXml();
+ }
+
+ /**
+ * Print out statistics for each mutator/gc phase in Xml format
+ */
+ @Interruptible
+ public static void printPhasesXml() {
+ Xml.openTag("mmtk-stats-per-gc");
+ for (int p = 0; p <= phase; p += 2) {
+ Xml.openTag("phase",false);
+ Xml.attribute("gc",(p/2)+1);
+ Xml.closeMinorTag();
+ for (int c = 0; c < counters; c++) {
+ if (!counter[c].isComplex())
+ if (counter[c].mergePhases()) {
+ printPhaseStatXml(counter[c],p,Phase.COMBINED);
+ } else {
+ printPhaseStatXml(counter[c],p,Phase.MUTATOR);
+ printPhaseStatXml(counter[c],p,Phase.GC);
+ }
+ }
+ Xml.closeTag("phase");
+ }
+ Xml.closeTag("mmtk-stats-per-gc");
+ }
+
+ /** @return The GC count (inclusive of any in-progress GC) */
+ public static int gcCount() { return gcCount; }
+
+ /** @return True if currently gathering stats */
+ public static boolean gatheringStats() { return gatheringStats; }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Timer.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Timer.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Timer.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Timer.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,145 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.statistics;
+
+import org.mmtk.utility.Log;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+
+/**
+ * This class implements a simple timer.
+ */
+ at Uninterruptible public class Timer extends LongCounter {
+
+ /****************************************************************************
+ *
+ * Initialization
+ */
+
+ /**
+ * Constructor
+ *
+ * @param name The name to be associated with this counter
+ */
+ public Timer(String name) {
+ this(name, true, false);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param name The name to be associated with this counter
+ * @param start True if this counter is to be implicitly started
+ * when <code>startAll()</code> is called (otherwise the counter
+ * must be explicitly started).
+ */
+ public Timer(String name, boolean start) {
+ this(name, start, false);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param name The name to be associated with this counter
+ * @param start True if this counter is to be implicitly started
+ * when <code>startAll()</code> is called (otherwise the counter
+ * must be explicitly started).
+ * @param mergephases True if this counter does not separately
+ * report GC and Mutator phases.
+ */
+ public Timer(String name, boolean start, boolean mergephases) {
+ super(name, start, mergephases);
+ }
+
+ /****************************************************************************
+ *
+ * Counter-specific methods
+ */
+
+ /**
+ * Get the current value for this timer
+ *
+ * @return The current value for this timer
+ */
+ @Inline
+ protected final long getCurrentValue() {
+ return VM.statistics.nanoTime();
+ }
+
+ /**
+ * Print the total in microseconds
+ */
+ final void printTotalMicro() {
+ printMicro(totalCount);
+ }
+
+ /**
+ * Print the total in milliseconds
+ */
+ public final void printTotalMillis() {
+ printMillis(totalCount);
+ }
+
+ /**
+ * Print the total in seconds
+ */
+ public final void printTotalSecs() {
+ printSecs(totalCount);
+ }
+
+ /**
+ * Print a value (in milliseconds)
+ *
+ * @param value The value to be printed
+ */
+ final void printValue(long value) {
+ printMillis(value);
+ }
+
+ /**
+ * Print a value in microseconds
+ *
+ * @param value The value to be printed
+ */
+ final void printMicro(long value) {
+ Log.write(1000 * VM.statistics.nanosToMillis(value));
+ }
+
+ /**
+ * Print a value in milliseconds
+ *
+ * @param value The value to be printed
+ */
+ final void printMillis(long value) {
+ Log.write(VM.statistics.nanosToMillis(value));
+ }
+
+ /**
+ * Print a value in seconds
+ *
+ * @param value The value to be printed
+ */
+ final void printSecs(long value) {
+ Log.write(VM.statistics.nanosToSecs(value));
+ }
+
+ /**
+ * Get the current value of the timer in milliseconds
+ */
+ final double getTotalMillis() {
+ return VM.statistics.nanosToMillis(totalCount);
+ }
+
+}
+
Added: vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Xml.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Xml.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Xml.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/utility/statistics/Xml.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,300 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.utility.statistics;
+
+import org.mmtk.utility.Log;
+import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.unboxed.Word;
+
+/**
+ * Utility class for writing statistics out in XML format.
+ */
+ at Uninterruptible
+public class Xml {
+ /**
+ * Mark the start of XML output
+ */
+ public static void begin() {
+ Log.writeln("<xml-begin/> <!-- Everything until xml-end is now valid xml -->");
+ }
+
+ /**
+ * Mark the end of XML output
+ */
+ public static void end() {
+ Log.writeln("<xml-end/> <!-- Non-xml data follows ... -->");
+ }
+
+ /**
+ * Close the innermost XML tag and pop it from the stack.
+ */
+ public static void closeTag(String name) {
+ Log.write("</"); Log.write(name); Log.writeln(">");
+ }
+
+ /**
+ * Open an XML tag.
+ *
+ * @param name Tag name
+ * @param endTag Should the tag be closed, or left open for
+ * adding additional attributes
+ */
+ static void openTag(String name, boolean endTag) {
+ openMinorTag(name);
+ if (endTag)
+ closeTag(false);
+ }
+
+ /**
+ * Open a simple XML entity.
+ *
+ * @param name Name of the entity
+ */
+ static void openTag(String name) { openTag(name,true); }
+
+ /**
+ * Output a "stat" entity, with a given name, <code>double</code>value and optionally, units.
+ *
+ * @param name Name of the entity
+ * @param value The value of the entity
+ * @param units The units, or null for no units.
+ */
+ public static void singleValue(String name, double value, String units) {
+ openMinorTag("stat");
+ attribute("name",name);
+ attribute("value",value);
+ if (units != null) attribute("units",units);
+ closeMinorTag();
+ }
+
+ /**
+ * Convenience version of singleValue where units are not specified.
+ *
+ * @param name Name of the entity
+ * @param value The value of the entity
+ */
+ public static void singleValue(String name, double value) {
+ singleValue(name,value,null);
+ }
+
+ /**
+ * Output a "config" entity, with a given name and <code>boolean</code>value.
+ *
+ * @param name Name of the entity
+ * @param value The value of the entity
+ */
+ public static void configItem(String name, boolean value) {
+ openMinorTag("conf");
+ attribute("name",name);
+ attribute("value",value);
+ closeMinorTag();
+ }
+
+ /**
+ * Output a "config" entity, with a given name and <code>String</code>value.
+ *
+ * @param name Name of the entity
+ * @param value The value of the entity
+ */
+ public static void configItem(String name, String value) {
+ openMinorTag("conf");
+ attribute("name",name);
+ attribute("value",value);
+ closeMinorTag();
+ }
+
+ /**
+ * Output a "stat" entity, with a given name, <code>long</code> value and
+ * optionally, units.
+ *
+ * @param name Name of the entity
+ * @param value The value of the entity
+ * @param units The units, or null for no units.
+ */
+ public static void singleValue(String name, long value, String units) {
+ openMinorTag("stat");
+ attribute("name",name);
+ attribute("value",value);
+ if (units != null) attribute("units",units);
+ closeMinorTag();
+ }
+
+ /**
+ * Convenience version of singleValue where units are not specified.
+ *
+ * @param name Name of the entity
+ * @param value The value of the entity
+ */
+ public static void singleValue(String name, long value) {
+ singleValue(name,value,null);
+ }
+
+ /**
+ * Add a word-valued attribute to an open XML tag.
+ *
+ * @param name Name of the entity
+ * @param value The value of the entity
+ */
+ public static void attribute(String name, Word value) {
+ openAttribute(name); Log.write(value); closeAttribute();
+ }
+
+ /**
+ * Add a byte[]-valued attribute to an open XML tag.
+ *
+ * @param name Name of the entity
+ * @param value The value of the entity
+ */
+ public static void attribute(String name, byte[] value) {
+ openAttribute(name); Log.write(value); closeAttribute();
+ }
+
+ /**
+ * Add a String-valued attribute to an open XML tag.
+ *
+ * @param name Name of the entity
+ * @param value The value of the entity
+ */
+ public static void attribute(String name, String value) {
+ openAttribute(name); Log.write(value); closeAttribute();
+ }
+
+ /**
+ * Add a boolean-valued attribute to an open XML tag.
+ *
+ * @param name Name of the entity
+ * @param value The value of the entity
+ */
+ public static void attribute(String name, boolean value) {
+ openAttribute(name); Log.write(value); closeAttribute();
+ }
+
+ /**
+ * Add a double-valued attribute to an open XML tag.
+ *
+ * @param name Name of the entity
+ * @param value The value of the entity
+ */
+ public static void attribute(String name, double value) {
+ openAttribute(name); Log.write(value); closeAttribute();
+ }
+
+ /**
+ * Add a long-valued attribute to an open XML tag.
+ *
+ * @param name Name of the entity
+ * @param value The value of the entity
+ */
+ public static void attribute(String name, long value) {
+ openAttribute(name); Log.write(value); closeAttribute();
+ }
+
+ /**
+ * Add an int-valued attribute to an open XML tag.
+ *
+ * @param name Name of the entity
+ * @param value The value of the entity
+ */
+ public static void attribute(String name, int value) {
+ openAttribute(name); Log.write(value); closeAttribute();
+ }
+
+ /**
+ * Close an attribute (actually a simple close-quote)
+ */
+ public static void closeAttribute() {
+ Log.write("\"");
+ }
+
+ /**
+ * Open an attribute (write "{name}=\")
+ *
+ * @param name Name of the entity
+ */
+ public static void openAttribute(String name) {
+ Log.write(" "); Log.write(name); Log.write("=\"");
+ }
+
+ /**
+ * Start a tag
+ */
+ public static void startTag() {
+ Log.write("<");
+ }
+
+ /**
+ * End a tag, optionally closing it (if it is a simple entity)
+ *
+ * @param close If true, close the tag with "/>" rather than ">"
+ */
+ public static void closeTag(boolean close) {
+ closeTag(close,true);
+ }
+
+ /**
+ * End a tag, optionally closing it (if it is a simple entity),
+ * and optionally printing end-of-line
+ *
+ * @param close If true, close the tag with "/>" rather than ">"
+ * @param endLine If true end the current line.
+ */
+ public static void closeTag(boolean close, boolean endLine) {
+ if (close) Log.write("/");
+ Log.write(">");
+ if (endLine) Log.writeln();
+ }
+
+ /**
+ * Close a tag with a "/>"
+ */
+ public static void closeMinorTag() {
+ closeTag(true,true);
+ }
+
+ /**
+ * Open a tag without pushing it on the tag stack - must end this
+ * with a call to closeMinorTag()
+ *
+ * @param name Name of the entity
+ */
+ public static void openMinorTag(String name) {
+ Log.write("<"); Log.write(name);
+ }
+
+ /**
+ * Open an XML comment
+ */
+ public static void openComment() {
+ Log.write("<!-- ");
+ }
+
+ /**
+ * Close an XML comment
+ */
+ public static void closeComment() {
+ Log.write(" -->");
+ }
+
+ /**
+ * Add a comment, bracketing it with open- and close-comment tags.
+ *
+ * @param comment The comment.
+ */
+ public static void comment(String comment) {
+ openComment();
+ Log.write(comment);
+ closeComment();
+ Log.writeln();
+ }
+
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/ActivePlan.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/ActivePlan.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/vm/ActivePlan.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/ActivePlan.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,59 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.vm;
+
+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.vmmagic.pragma.*;
+
+/**
+ * Stub to give access to plan local, constraint and global instances
+ */
+ at Uninterruptible public abstract class ActivePlan {
+
+ /** @return The active Plan instance. */
+ public abstract Plan global();
+
+ /** @return The active PlanConstraints instance. */
+ public abstract PlanConstraints constraints();
+
+ /** @return The active <code>CollectorContext</code> instance. */
+ public abstract CollectorContext collector();
+
+ /** @return The active <code>MutatorContext</code> instance. */
+ public abstract MutatorContext mutator();
+
+ /** @return The log for the active thread */
+ public abstract Log log();
+
+ /** @return The maximum number of collector threads that may participate in parallel GC. */
+ public abstract int collectorCount();
+
+ /** Reset the mutator iterator */
+ public abstract 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 abstract MutatorContext getNextMutator();
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/Assert.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/Assert.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/vm/Assert.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/Assert.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.vm;
+
+import org.vmmagic.pragma.Uninterruptible;
+
+ at Uninterruptible public abstract class Assert {
+ /**
+ * Logs a message and traceback, then exits.
+ *
+ * @param message the string to log
+ */
+ public abstract void fail(String message);
+
+ /**
+ * 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
+ */
+ public abstract void _assert(boolean 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
+ */
+ public abstract void _assert(boolean cond, String message);
+
+ /**
+ * Print a stack trace
+ */
+ public abstract void dumpStack();
+
+ /**
+ * Checks if the virtual machine is running. This value changes, so
+ * the call-through to the VM must be a method. In Jikes RVM, just
+ * returns VM.runningVM.
+ *
+ * @return <code>true</code> if the virtual machine is running
+ */
+ public abstract boolean runningVM();
+
+ /*
+ * NOTE: The following methods must be implemented by subclasses of this
+ * class, but are internal to the VM<->MM interface glue, so are never
+ * called by MMTk users.
+ */
+ /** @return true if assertions should be verified */
+ protected abstract boolean getVerifyAssertionsConstant();
+
+ /*
+ * NOTE: This method should not be called by anything other than the
+ * reflective mechanisms in org.mmtk.vm.VM, and is not implemented by
+ * subclasses.
+ *
+ * This hack exists only to allow us to declare getVerifyAssertions() as
+ * a protected method.
+ */
+ static boolean verifyAssertionsTrapdoor(Assert a) {
+ return a.getVerifyAssertionsConstant();
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/Barriers.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/Barriers.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/vm/Barriers.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/Barriers.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.vm;
+
+import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.unboxed.*;
+
+ at Uninterruptible
+public abstract class Barriers {
+ /**
+ * 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 abstract void setArrayNoBarrier(Object [] dst, int index, Object value);
+
+ /**
+ * 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 VM specific meta data
+ * @param metaDataB VM specific meta data
+ * @param mode The context in which the write is occuring
+ */
+ public abstract void performWriteInBarrier(ObjectReference ref, Address slot,
+ ObjectReference target, Word metaDataA,
+ Word metaDataB, int mode);
+
+ /**
+ * 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 VM specific meta data
+ * @param metaDataB VM specific meta data
+ * @param mode The context in which the write is occuring
+ */
+ public abstract void performRawWriteInBarrier(ObjectReference ref, Address slot,
+ Word rawTarget, Word metaDataA,
+ Word metaDataB, int mode);
+
+ /**
+ * 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 VM specific meta data
+ * @param metaDataB VM specific meta data
+ * @param mode The context in which the write is occuring
+ * @return the read value
+ */
+ public abstract ObjectReference performReadInBarrier(ObjectReference ref, Address slot,
+ Word metaDataA, Word metaDataB, int mode);
+
+ /**
+ * 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 VM specific meta data
+ * @param metaDataB VM specific meta data
+ * @param mode The context in which the write is occuring
+ * @return the read value
+ */
+ public abstract Word performRawReadInBarrier(ObjectReference ref, Address slot,
+ Word metaDataA, Word metaDataB, int mode);
+
+ /**
+ * 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 VM specific meta data
+ * @param metaDataB VM specific meta data
+ * @param mode The context in which the write is occuring
+ * @return The value that was replaced by the write.
+ */
+ public abstract ObjectReference performWriteInBarrierAtomic(ObjectReference ref, Address slot,
+ ObjectReference target, Word metaDataA,
+ Word metaDataB, int mode);
+
+ /**
+ * 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 rawTarget The raw value that the slot will be updated to
+ * @param metaDataA VM specific meta data
+ * @param metaDataB VM specific meta data
+ * @param mode The context in which the write is occuring
+ * @return The raw value that was replaced by the write.
+ */
+ public abstract Word performRawWriteInBarrierAtomic(ObjectReference ref, Address slot,
+ Word rawTarget, Word metaDataA,
+ Word metaDataB, int mode);
+
+ /**
+ * 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 VM specific meta data
+ * @param metaDataB VM specific meta data
+ * @param mode The context in which the write is occuring
+ * @return True if the compare and swap was successful
+ */
+ public abstract boolean tryCompareAndSwapWriteInBarrier(ObjectReference ref, Address slot,
+ ObjectReference old, ObjectReference target,
+ Word metaDataA, Word metaDataB, int mode);
+
+ /**
+ * 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 VM specific meta data
+ * @param metaDataB VM specific meta data
+ * @param mode The context in which the write is occuring
+ * @return True if the compare and swap was successful
+ */
+ public abstract boolean tryRawCompareAndSwapWriteInBarrier(ObjectReference ref, Address slot,
+ Word rawOld, Word rawTarget,
+ Word metaDataA, Word metaDataB, int mode);
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/BuildTimeConfig.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/BuildTimeConfig.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/vm/BuildTimeConfig.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/BuildTimeConfig.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.vm;
+
+/**
+ * Build-time configuration constants for MMTk.
+ */
+public abstract class BuildTimeConfig {
+
+ /**
+ * @return The name of the current MMTk plan
+ */
+ public abstract String getPlanName();
+
+ /**
+ * Return a property of type String
+ * @param name The name of the property
+ * @return The value of the property
+ */
+ public abstract String getStringProperty(String name);
+
+ /**
+ * Return a property of type String, with default.
+ * @param name The name of the property
+ * @param dflt Default value
+ * @return The value of the property
+ */
+ public abstract String getStringProperty(String name, String dflt);
+
+ /**
+ * Return a property of type int
+ * @param name The name of the property
+ * @return The value of the property
+ */
+ public abstract int getIntProperty(String name);
+
+ /**
+ * Return a property of type String, with default.
+ * @param name The name of the property
+ * @param dflt Default value
+ * @return The value of the property
+ */
+ public abstract int getIntProperty(String name, int dflt);
+
+ /**
+ * Return a property of type boolean
+ * @param name The name of the property
+ * @return The value of the property
+ */
+ public abstract boolean getBooleanProperty(String name);
+
+ /**
+ * Return a property of type boolean, with default.
+ * @param name The name of the property
+ * @param dflt Default value
+ * @return The value of the property
+ */
+ public abstract boolean getBooleanProperty(String name, boolean dflt);
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/Collection.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/Collection.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/vm/Collection.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/Collection.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,160 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.vm;
+
+import org.mmtk.plan.CollectorContext;
+import org.mmtk.plan.MutatorContext;
+
+import org.vmmagic.pragma.*;
+
+ at Uninterruptible public abstract class Collection {
+
+ /****************************************************************************
+ *
+ * Class variables
+ */
+
+ /**
+ * An unknown GC trigger reason. Signals a logic bug.
+ */
+ public static final int UNKNOWN_GC_TRIGGER = 0;
+
+ /**
+ * Concurrent collection phase trigger.
+ */
+ public static final int INTERNAL_PHASE_GC_TRIGGER = 1;
+
+ /**
+ * Externally triggered garbage collection (eg call to System.gc())
+ */
+ public static final int EXTERNAL_GC_TRIGGER = 2;
+
+ /**
+ * Resource triggered garbage collection. For example, an
+ * allocation request would take the number of pages in use beyond
+ * the number available.
+ */
+ public static final int RESOURCE_GC_TRIGGER = 3;
+
+ /**
+ * Internally triggered garbage collection. For example, the memory
+ * manager attempting another collection after the first failed to
+ * free space.
+ */
+ public static final int INTERNAL_GC_TRIGGER = 4;
+
+ /**
+ * The number of garbage collection trigger reasons.
+ */
+ public static final int TRIGGER_REASONS = 5;
+
+ /** Short descriptions of the garbage collection trigger reasons. */
+ protected static final String[] triggerReasons = {
+ "unknown",
+ "concurrent phase",
+ "external request",
+ "resource exhaustion",
+ "internal request"
+ };
+
+ /**
+ * Triggers a collection.
+ *
+ * @param why the reason why a collection was triggered. 0 to
+ * <code>TRIGGER_REASONS - 1</code>.
+ */
+ @Unpreemptible
+ public abstract void triggerCollection(int why);
+
+ /**
+ * Joins an already requested collection.
+ */
+ @Unpreemptible
+ public abstract void joinCollection();
+
+ /**
+ * Trigger an asynchronous collection, checking for memory
+ * exhaustion first.
+ *
+ * @param why the reason why a collection was triggered. 0 to
+ * <code>TRIGGER_REASONS - 1</code>.
+ */
+ public abstract void triggerAsyncCollection(int why);
+
+ /**
+ * The maximum number collection attempts across threads.
+ */
+ public abstract int maximumCollectionAttempt();
+
+ /**
+ * Report that the allocation has succeeded.
+ */
+ public abstract void reportAllocationSuccess();
+
+ /**
+ * Report that a physical allocation has failed.
+ */
+ public abstract void reportPhysicalAllocationFailed();
+
+ /**
+ * Does the VM consider this an emergency alloction, where the normal
+ * heap size rules can be ignored.
+ */
+ public abstract boolean isEmergencyAllocation();
+
+ /**
+ * 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.
+ */
+ public abstract boolean noThreadsInGC();
+
+ /**
+ * Prepare a mutator for collection.
+ *
+ * @param m the mutator to prepare
+ */
+ public abstract void prepareMutator(MutatorContext m);
+
+ /**
+ * Prepare a collector for a collection.
+ *
+ * @param c the collector to prepare
+ */
+ public abstract void prepareCollector(CollectorContext c);
+
+ /**
+ * Rendezvous with all other processors, returning the rank
+ * (that is, the order this processor arrived at the barrier).
+ */
+ public abstract int rendezvous(int where);
+
+ /** @return The number of active collector threads */
+ public abstract int activeGCThreads();
+
+ /**
+ * @return The ordinal ID of the running collector thread w.r.t.
+ * the set of active collector threads (zero based)
+ */
+ public abstract int activeGCThreadOrdinal();
+
+ /**
+ * Request each mutator flush remembered sets. This method
+ * will trigger the flush and then yield until all processors have
+ * flushed.
+ */
+ public abstract void requestMutatorFlush();
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/Config.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/Config.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/vm/Config.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/Config.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.vm;
+
+import org.mmtk.utility.Log;
+import org.mmtk.utility.statistics.Xml;
+
+public class Config {
+ /* The name of the active plan */
+ private final String ACTIVE_PLAN;
+
+ /** Mark bit in the header or on the side ? */
+ public final boolean HEADER_MARK_BITS;
+
+ Config(BuildTimeConfig config) {
+ ACTIVE_PLAN = config.getPlanName();
+ HEADER_MARK_BITS = config.getBooleanProperty("mmtk.headerMarkBit",true);
+ }
+
+ public void printConfig() {
+ Log.writeln("================ MMTk Configuration ================");
+ Log.write("plan = "); Log.writeln(ACTIVE_PLAN);
+ Log.write("HEADER_MARK_BITS = "); Log.writeln(HEADER_MARK_BITS);
+ Log.writeln("====================================================");
+ }
+
+ public void printConfigXml() {
+ Log.writeln("<config>");
+ Xml.configItem("plan",ACTIVE_PLAN);
+ Xml.configItem("header-mark-bit",HEADER_MARK_BITS);
+ Log.writeln("</config>");
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/Debug.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/Debug.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/vm/Debug.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/Debug.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,89 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.vm;
+
+import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.unboxed.Address;
+import org.vmmagic.unboxed.ObjectReference;
+
+/**
+ *
+ */
+ at Uninterruptible
+public abstract class Debug {
+ /**
+ * Global switch for debugging - if false the other methods of this
+ * class are never called.
+ * @return Whether debugging is enabled
+ */
+ public abstract boolean isEnabled();
+
+ /**
+ * A modbuf (object remembering barrier) entry has been
+ * traced during collection.
+ * @param object
+ */
+ public void modbufEntry(ObjectReference object) { }
+
+ /**
+ * A remset (slot remembering barrier) entry has been
+ * traced during collection.
+ * @param slot
+ */
+ public void remsetEntry(Address slot) { }
+
+ /**
+ * An array remset entry has been traced during collection. Implicitly
+ * the slots from start (inclusive) through to guard (non-inclusive)
+ * are traced as remset entries
+ * @param start
+ * @param guard
+ */
+ public void arrayRemsetEntry(Address start, Address guard) { }
+
+ /**
+ * A global GC collection phase
+ * @param phaseId The phase ID
+ * @param before true at the start of the phase, false at the end
+ */
+ public void globalPhase(short phaseId, boolean before) { }
+
+ /**
+ * A per-collector GC collection phase
+ * @param phaseId The phase ID
+ * @param ordinal The collector ID (within this collection)
+ * @param before true at the start of the phase, false at the end
+ */
+ public void collectorPhase(short phaseId, int ordinal, boolean before) { }
+
+ /**
+ * A per-mutator GC collection phase
+ * @param phaseId The phase ID
+ * @param ordinal The mutator ID
+ * @param before true at the start of the phase, false at the end
+ */
+ public void mutatorPhase(short phaseId, int ordinal, boolean before) { }
+
+ /*
+ * NOTE: These methods should not be called by anything other than the
+ * reflective mechanisms in org.mmtk.vm.VM, and are not implemented by
+ * subclasses.
+ *
+ * This hack exists only to allow us to declare the respective
+ * methods as protected.
+ */
+ static final boolean isEnabledTrapdoor(Debug d) {
+ return d.isEnabled();
+ }
+
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/Factory.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/Factory.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/vm/Factory.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/Factory.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,347 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.vm;
+
+import org.vmutil.options.OptionSet;
+import org.mmtk.utility.gcspy.Color;
+import org.mmtk.utility.gcspy.drivers.AbstractDriver;
+import org.mmtk.vm.gcspy.ByteStream;
+import org.mmtk.vm.gcspy.IntStream;
+import org.mmtk.vm.gcspy.ServerInterpreter;
+import org.mmtk.vm.gcspy.ServerSpace;
+import org.mmtk.vm.gcspy.ShortStream;
+import org.mmtk.vm.gcspy.Util;
+
+/**
+ * This class defines factory methods for VM-specific types which must
+ * be instantiated within MMTk. Since the concrete type is defined at
+ * build time, we leave it to a concrete vm-specific instance of this class
+ * to perform the object instantiation.
+ */
+public abstract class Factory {
+
+ /**
+ * Create or retrieve the OptionSet used for MMTk options.
+ *
+ * @return A concrete VM-specific OptionSet instance
+ */
+ public abstract OptionSet getOptionSet();
+
+ /**
+ * Create a new ActivePlan instance using the appropriate VM-specific
+ * concrete ActivePlan sub-class.
+ *
+ * @see ActivePlan
+ * @return A concrete VM-specific ActivePlan instance.
+ */
+ public abstract ActivePlan newActivePlan();
+
+ /**
+ * Create a new Assert instance using the appropriate VM-specific
+ * concrete Assert sub-class.
+ *
+ * @see Assert
+ * @return A concrete VM-specific Assert instance.
+ */
+ public abstract Assert newAssert();
+
+ /**
+ * Create a new Barriers instance using the appropriate VM-specific
+ * concrete Barriers sub-class.
+ *
+ * @see Barriers
+ * @return A concrete VM-specific Barriers instance.
+ */
+ public abstract Barriers newBarriers();
+
+ /**
+ * Create a new Collection instance using the appropriate VM-specific
+ * concrete Collection sub-class.
+ *
+ * @see Collection
+ * @return A concrete VM-specific Collection instance.
+ */
+ public abstract Collection newCollection();
+
+ /**
+ * Create a new Config instance using the appropriate VM-specific
+ * concrete Config sub-class.
+ *
+ * @see Collection
+ * @return A concrete VM-specific Collection instance.
+ */
+ public abstract BuildTimeConfig newBuildTimeConfig();
+
+ /**
+ * 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 abstract Lock newLock(String name);
+
+ /**
+ * Create a new Memory instance using the appropriate VM-specific
+ * concrete Memory sub-class.
+ *
+ * @see Memory
+ * @return A concrete VM-specific Memory instance.
+ */
+ public abstract Memory newMemory();
+
+ /**
+ * Create a new ObjectModel instance using the appropriate VM-specific
+ * concrete ObjectModel sub-class.
+ *
+ * @see ObjectModel
+ * @return A concrete VM-specific ObjectModel instance.
+ */
+ public abstract ObjectModel newObjectModel();
+
+ /**
+ * Create a new ReferenceProcessor instance using the appropriate VM-specific
+ * concrete ReferenceProcessor sub-class.
+ *
+ * @see ReferenceProcessor
+ * @return A concrete VM-specific ReferenceProcessor instance.
+ */
+ public abstract ReferenceProcessor newReferenceProcessor(ReferenceProcessor.Semantics semantics);
+
+
+ /**
+ * Create a new FinalizbleProcessor instance using the appropriate VM-specific
+ * concrete FinalizableProcessor sub-class.
+ *
+ * @see FinalizableProcessor
+ * @return A concrete VM-specific FinalizableProcessor instance.
+ */
+ public abstract FinalizableProcessor newFinalizableProcessor();
+
+ /**
+ * Create a new Scanning instance using the appropriate VM-specific
+ * concrete Scanning sub-class.
+ *
+ * @see Scanning
+ * @return A concrete VM-specific Scanning instance.
+ */
+ public abstract Scanning newScanning();
+
+ /**
+ * Create a new Statistics instance using the appropriate VM-specific
+ * concrete Statistics sub-class.
+ *
+ * @see Statistics
+ * @return A concrete VM-specific Statistics instance.
+ */
+ public abstract Statistics newStatistics();
+
+ /**
+ * Create a new Strings instance using the appropriate VM-specific
+ * concrete Strings sub-class.
+ *
+ * @see Strings
+ * @return A concrete VM-specific Strings instance.
+ */
+ public abstract Strings newStrings();
+
+ /**
+ * Create a new SynchronizedCounter instance using the appropriate
+ * VM-specific concrete SynchronizedCounter sub-class.
+ *
+ * @see SynchronizedCounter
+ *
+ * @return A concrete VM-specific SynchronizedCounter instance.
+ */
+ public abstract SynchronizedCounter newSynchronizedCounter();
+
+ /**
+ * Create a new TraceInterface instance using the appropriate VM-specific
+ * concrete TraceInterface sub-class.
+ *
+ * @see TraceInterface
+ * @return A concrete VM-specific TraceInterface instance.
+ */
+ public abstract TraceInterface newTraceInterface();
+
+ /**
+ * Create a new MMTk_Events instance using the appropriate VM-specific
+ * concrete MMTk_Events sub-class.
+ */
+ public abstract MMTk_Events newEvents();
+
+ /**
+ * Create a new debug object
+ */
+ public abstract Debug newDebug();
+
+ /**********************************************************************
+ * GCspy methods
+ */
+
+ /**
+ * Create a new Util instance using the appropriate VM-specific
+ * concrete Util sub-class.
+ *
+ * @see Util
+ * @return A concrete VM-specific Util instance.
+ */
+ public abstract Util newGCspyUtil();
+
+ /**
+ * Create a new ServerInterpreter instance using the appropriate VM-specific
+ * concrete ServerInterpreter sub-class.
+ *
+ * @see ServerInterpreter
+ * @return A concrete VM-specific ServerInterpreter instance.
+ */
+ public abstract ServerInterpreter newGCspyServerInterpreter();
+
+ /**
+ * 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 ServerSpace
+ * @return A concrete VM-specific ServerSpace instance.
+ */
+ public abstract ServerSpace newGCspyServerSpace(
+ ServerInterpreter serverInterpreter,
+ String serverName,
+ String driverName,
+ String title,
+ String blockInfo,
+ int tileNum,
+ String unused,
+ boolean mainSpace);
+
+ /**
+ * 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 IntStream
+ *
+ * @return A concrete VM-specific IntStream instance.
+ */
+ public abstract 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);
+
+ /**
+ * 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 IntStream
+ *
+ * @return A concrete VM-specific ByteStream instance.
+ */
+ public abstract 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);
+
+ /**
+ * 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 IntStream
+ *
+ * @return A concrete VM-specific ShortStream instance.
+ */
+ public abstract 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);
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/FinalizableProcessor.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/FinalizableProcessor.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/vm/FinalizableProcessor.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/FinalizableProcessor.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.vm;
+
+import org.mmtk.plan.TraceLocal;
+import org.vmmagic.pragma.Uninterruptible;
+
+/**
+ * This class manages finalizable objects.
+ */
+ at Uninterruptible
+public abstract class FinalizableProcessor {
+
+ /**
+ * Clear the contents of the table. This is called when finalization is
+ * disabled to make it easier for VMs to change this setting at runtime.
+ */
+ public abstract void clear();
+
+ /**
+ * Scan through the list of references.
+ *
+ * @param trace the thread local trace element.
+ * @param nursery true if it is safe to only scan new references.
+ */
+ public abstract void scan(TraceLocal trace, boolean nursery);
+
+ /**
+ * Iterate over and forward entries in the table.
+ */
+ public abstract void forward(TraceLocal trace, boolean nursery);
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/Lock.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/Lock.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/vm/Lock.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/Lock.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.vm;
+
+import org.vmmagic.pragma.Uninterruptible;
+
+/**
+ * Simple, fair locks with deadlock detection.
+ */
+ at Uninterruptible public abstract class Lock {
+
+ /**
+ * Set the name of this lock instance
+ *
+ * @param str The name of the lock (for error output).
+ */
+ public abstract void setName(String str);
+
+
+ /**
+ * Try to acquire a lock and spin-wait until acquired.
+ */
+ public abstract void acquire();
+
+ /**
+ * Perform sanity checks on the lock. For debugging.
+ *
+ * @param w Identifies the code location in the debugging output.
+ */
+ public abstract void check(int w);
+
+ /**
+ * Release the lock by incrementing serving counter.
+ */
+ public abstract void release();
+
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/MMTk_Events.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/MMTk_Events.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/vm/MMTk_Events.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/MMTk_Events.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.vm;
+
+import org.mmtk.policy.Space;
+import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.unboxed.Address;
+import org.vmmagic.unboxed.Extent;
+
+/**
+ * Event generation interface for MMTk.
+ */
+ at Uninterruptible
+public abstract class MMTk_Events {
+ public abstract void tracePageAcquired(Space space, Address startAddress, int numPages);
+
+ public abstract void tracePageReleased(Space space, Address startAddress, int numPages);
+
+ public abstract void heapSizeChanged(Extent heapSize);
+
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/Memory.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/Memory.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/vm/Memory.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/Memory.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,211 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.vm;
+
+import org.mmtk.policy.ImmortalSpace;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+ at Uninterruptible public abstract class Memory {
+
+ /**
+ * Allows for the VM to reserve space between HEAP_START()
+ * and AVAILABLE_START() for its own purposes. MMTk should
+ * expect to encounter objects in this range, but may not
+ * allocate in this range.
+ *
+ * MMTk expects the virtual address space between AVAILABLE_START()
+ * and AVAILABLE_END() to be contiguous and unmapped.
+ * Allows for the VM to reserve space between HEAP_END()
+ * and AVAILABLE_END() for its own purposes. MMTk should
+ * expect to encounter objects in this range, but may not
+ * allocate in this range.
+ *
+ * MMTk expects the virtual address space between AVAILABLE_START()
+ * and AVAILABLE_END() to be contiguous and unmapped.
+ *
+ * @return The high bound of the memory that MMTk can allocate.
+ */
+
+ /**
+ * Return the space associated with/reserved for the VM. In the
+ * case of Jikes RVM this is the boot image space.<p>
+ *
+ * @return The space managed by the virtual machine.
+ */
+ @Interruptible
+ public abstract ImmortalSpace getVMSpace();
+
+ /** Global preparation for a collection. */
+ public abstract void globalPrepareVMSpace();
+
+ /** Per-collector preparation for a collection. */
+ public abstract void collectorPrepareVMSpace();
+
+ /** Per-collector post-collection work. */
+ public abstract void collectorReleaseVMSpace();
+
+ /** Global post-collection work. */
+ public abstract void globalReleaseVMSpace();
+
+ /**
+ * 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 abstract 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 abstract 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 abstract 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 abstract 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 abstract 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 abstract 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 abstract void dumpMemory(Address start, int beforeBytes,
+ int afterBytes);
+
+ /**
+ * Wait for preceeding cache flush/invalidate instructions to complete
+ * on all processors. Ensures that all memory writes before this
+ * point are visible to all processors.
+ */
+ @Inline
+ public abstract void sync();
+
+ /**
+ * Wait for all preceeding instructions to complete and discard any
+ * prefetched instructions on this processor. Also prevents the
+ * compiler from performing code motion across this point.
+ */
+ @Inline
+ public abstract void isync();
+
+ /*
+ * NOTE: The following methods must be implemented by subclasses of this
+ * class, but are internal to the VM<->MM interface glue, so are never
+ * called by MMTk users.
+ */
+ /** @return The lowest address in the virtual address space known to MMTk */
+ protected abstract Address getHeapStartConstant();
+ /** @return The highest address in the virtual address space known to MMTk */
+ protected abstract Address getHeapEndConstant();
+ /** @return The lowest address in the contiguous address space available to MMTk */
+ protected abstract Address getAvailableStartConstant();
+ /** @return The highest address in the contiguous address space available to MMTk */
+ protected abstract Address getAvailableEndConstant();
+ /** @return The log base two of the size of an address */
+ protected abstract byte getLogBytesInAddressConstant();
+ /** @return The log base two of the size of a word */
+ protected abstract byte getLogBytesInWordConstant();
+ /** @return The log base two of the size of an OS page */
+ protected abstract byte getLogBytesInPageConstant();
+ /** @return The log base two of the minimum allocation alignment */
+ protected abstract byte getLogMinAlignmentConstant();
+ /** @return The log base two of (MAX_ALIGNMENT/MIN_ALIGNMENT) */
+ protected abstract byte getMaxAlignmentShiftConstant();
+ /** @return The maximum number of bytes of padding to prepend to an object */
+ protected abstract int getMaxBytesPaddingConstant();
+ /** @return The value to store in alignment holes */
+ protected abstract int getAlignmentValueConstant();
+
+ /*
+ * NOTE: These methods should not be called by anything other than the
+ * reflective mechanisms in org.mmtk.vm.VM, and are not implemented by
+ * subclasses. This hack exists only to allow us to declare the respective
+ * methods as protected.
+ */
+ static Address heapStartTrapdoor(Memory m) {
+ return m.getHeapStartConstant();
+ }
+ static Address heapEndTrapdoor(Memory m) {
+ return m.getHeapEndConstant();
+ }
+ static Address availableStartTrapdoor(Memory m) {
+ return m.getAvailableStartConstant();
+ }
+ static Address availableEndTrapdoor(Memory m) {
+ return m.getAvailableEndConstant();
+ }
+ static byte logBytesInAddressTrapdoor(Memory m) {
+ return m.getLogBytesInAddressConstant();
+ }
+ static byte logBytesInWordTrapdoor(Memory m) {
+ return m.getLogBytesInWordConstant();
+ }
+ static byte logBytesInPageTrapdoor(Memory m) {
+ return m.getLogBytesInPageConstant();
+ }
+ static byte logMinAlignmentTrapdoor(Memory m) {
+ return m.getLogMinAlignmentConstant();
+ }
+ static byte maxAlignmentShiftTrapdoor(Memory m) {
+ return m.getMaxAlignmentShiftConstant();
+ }
+ static int maxBytesPaddingTrapdoor(Memory m) {
+ return m.getMaxBytesPaddingConstant();
+ }
+ static int alignmentValueTrapdoor(Memory m) {
+ return m.getAlignmentValueConstant();
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/ObjectModel.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/ObjectModel.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/vm/ObjectModel.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/ObjectModel.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,256 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.vm;
+
+import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.unboxed.*;
+
+ at Uninterruptible public abstract class ObjectModel {
+ /**
+ * 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
+ * @param allocator The allocator to use.
+ * @return the address of the new object
+ */
+ public abstract 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 of the region that was reserved for this object
+ * @return Address The address past the end of the copied object
+ */
+ public abstract 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 abstract ObjectReference getReferenceWhenCopiedTo(ObjectReference from, Address to);
+
+
+ /**
+ * 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 abstract 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 abstract 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 abstract 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 abstract int getCurrentSize(ObjectReference object);
+
+ /**
+ * Return the next object in the heap under contiguous allocation
+ */
+ public abstract ObjectReference getNextObject(ObjectReference object);
+
+ /**
+ * Return an object reference from knowledge of the low order word
+ */
+ public abstract ObjectReference getObjectFromStartAddress(Address start);
+ /**
+ * Gets a pointer to the address just past the end of the object.
+ *
+ * @param object The objecty.
+ */
+ public abstract Address getObjectEndAddress(ObjectReference object);
+
+
+ /**
+ * Get the type descriptor for an object.
+ *
+ * @param ref address of the object
+ * @return byte array with the type descriptor
+ */
+ public abstract byte[] getTypeDescriptor(ObjectReference ref);
+
+ /**
+ * Is the passed object an array?
+ *
+ * @param object address of the object
+ */
+ public abstract boolean isArray(ObjectReference object);
+
+ /**
+ * Is the passed object a primitive array?
+ *
+ * @param object address of the object
+ */
+ public abstract boolean isPrimitiveArray(ObjectReference object);
+
+ /**
+ * Get the length of an array object.
+ *
+ * @param object address of the object
+ * @return The array length, in elements
+ */
+ public abstract int getArrayLength(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 abstract 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 abstract 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 abstract 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 abstract 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 abstract 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 abstract 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
+ */
+ public abstract 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
+ */
+ public abstract 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 abstract Address refToAddress(ObjectReference object);
+
+ /**
+ * Checks if a reference of the given type in another object is
+ * inherently acyclic. The type is given as a TIB.
+ *
+ * @return <code>true</code> if a reference of the type is
+ * inherently acyclic
+ */
+ public abstract boolean isAcyclic(ObjectReference typeRef);
+
+ /**
+ * Dump debugging information for an object.
+ *
+ * @param object The object whose information is to be dumped
+ */
+ public abstract void dumpObject(ObjectReference object);
+
+ /*
+ * NOTE: The following methods must be implemented by subclasses of this
+ * class, but are internal to the VM<->MM interface glue, so are never
+ * called by MMTk users.
+ */
+ /** @return The offset from array reference to element zero */
+ protected abstract Offset getArrayBaseOffset();
+
+ /*
+ * NOTE: These methods should not be called by anything other than the
+ * reflective mechanisms in org.mmtk.vm.VM, and are not implemented by
+ * subclasses.
+ *
+ * This hack exists only to allow us to declare the respective
+ * methods as protected.
+ */
+ static Offset arrayBaseOffsetTrapdoor(ObjectModel o) {
+ return o.getArrayBaseOffset();
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/ReferenceProcessor.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/ReferenceProcessor.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/vm/ReferenceProcessor.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/ReferenceProcessor.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.vm;
+
+import org.mmtk.plan.TraceLocal;
+import org.vmmagic.pragma.Uninterruptible;
+
+/**
+ * This class manages SoftReferences, WeakReferences, and
+ * PhantomReferences.
+ */
+ at Uninterruptible
+public abstract class ReferenceProcessor {
+
+ public enum Semantics { SOFT, WEAK, PHANTOM }
+
+ /**
+ * 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.
+ */
+ public abstract void clear();
+
+ /**
+ * Scan through the list of references.
+ *
+ * @param trace the thread local trace element.
+ * @param nursery true if it is safe to only scan new references.
+ */
+ public abstract void scan(TraceLocal trace, boolean nursery);
+
+ /**
+ * Iterate over all references and forward.
+ */
+ public abstract void forward(TraceLocal trace, boolean nursery);
+
+ /**
+ * @return the number of references objects on the queue
+ */
+ public abstract int countWaitingReferences();
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/Scanning.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/Scanning.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/vm/Scanning.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/Scanning.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,137 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.vm;
+
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.utility.Constants;
+
+import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.unboxed.*;
+
+ at Uninterruptible public abstract class Scanning implements Constants {
+ /**
+ * Delegated scanning of a object, processing each pointer field
+ * encountered.
+ *
+ * @param object The object to be scanned.
+ */
+ public abstract 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
+ */
+ public abstract void specializedScanObject(int id, TransitiveClosure trace, ObjectReference object);
+
+ /**
+ * Delegated precopying of a object's children, processing each pointer field
+ * encountered.
+ *
+ * @param trace The trace object to use for precopying.
+ * @param object The object to be scanned.
+ */
+ public abstract 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 abstract 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.
+ */
+ public abstract 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 abstract 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 abstract 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>
+ *
+ * @param trace The trace to use for computing roots.
+ */
+ public abstract 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 abstract void computeBootImageRoots(TraceLocal trace);
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/Statistics.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/Statistics.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/vm/Statistics.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/Statistics.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,79 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.vm;
+
+import org.vmmagic.pragma.Uninterruptible;
+
+
+ at Uninterruptible public abstract class Statistics {
+ /**
+ * Returns the number of collections that have occurred.
+ *
+ * @return The number of collections that have occurred.
+ */
+ public abstract int getCollectionCount();
+
+ /**
+ * Read cycle counter
+ */
+ public abstract long nanoTime();
+
+ /**
+ * Convert nanoseconds to milliseconds
+ */
+ public abstract double nanosToMillis(long c);
+
+ /**
+ * Convert nanoseconds to seconds
+ */
+ public abstract double nanosToSecs(long c);
+
+ /**
+ * Convert milliseconds to nanoseconds
+ */
+ public abstract long millisToNanos(double t);
+
+ /**
+ * Convert seconds to nanoseconds
+ */
+ public abstract long secsToNanos(double t);
+
+ /**
+ * Read the cycle counter
+ */
+ public abstract long cycles();
+
+ /**
+ * Initialize performance counters
+ *
+ * @param metric An integer identifying the metric being read
+ */
+ public abstract void perfCtrInit(int metric);
+
+ /**
+ * Read the current cycle count from the perfctr libraries
+ *
+ * @return the current cycle count from the perfctr libraries
+ */
+ public abstract 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 abstract long perfCtrReadMetric();
+
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/Strings.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/Strings.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/vm/Strings.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/Strings.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.vm;
+
+import org.vmmagic.pragma.Uninterruptible;
+
+
+ at Uninterruptible public abstract class Strings {
+ /**
+ * Log a message.
+ *
+ * @param c character array with message starting at index 0
+ * @param len number of characters in message
+ */
+ public abstract 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 abstract 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 abstract int copyStringToChars(String src, char [] dst,
+ int dstBegin, int dstEnd);
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/SynchronizedCounter.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/SynchronizedCounter.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/vm/SynchronizedCounter.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/SynchronizedCounter.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.vm;
+
+import org.vmmagic.pragma.Uninterruptible;
+
+
+/**
+ * A counter that supports atomic increment and reset.
+ */
+ at Uninterruptible public abstract class SynchronizedCounter {
+
+ /**
+ * Reset the counter to 0, returning its previous value.
+ *
+ * @return The value of the counter, prior to reset.
+ */
+ public abstract int reset();
+
+ /**
+ * Adds 1 to the counter.
+ *
+ * @return the value before the add
+ */
+ public abstract int increment();
+
+ /**
+ * Peek at the counter
+ *
+ * @return The current value of the counter.
+ */
+ public abstract int peek();
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/TraceInterface.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/TraceInterface.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/vm/TraceInterface.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/TraceInterface.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.vm;
+
+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 abstract class 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 abstract 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 abstract 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 abstract Address skipOwnFramesAndDump(ObjectReference typeRef);
+
+ /***********************************************************************
+ *
+ * Wrapper methods
+ */
+ public abstract void updateDeathTime(ObjectReference obj);
+ public abstract void setDeathTime(ObjectReference ref, Word time_);
+ public abstract void setLink(ObjectReference ref, ObjectReference link);
+ public abstract void updateTime(Word time_);
+ public abstract Word getOID(ObjectReference ref);
+ public abstract Word getDeathTime(ObjectReference ref);
+ public abstract ObjectReference getLink(ObjectReference ref);
+ public abstract Address getBootImageLink();
+ public abstract Word getOID();
+ public abstract void setOID(Word oid);
+ public abstract int getHeaderSize();
+ public abstract int getHeaderEndOffset();
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/VM.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/VM.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/vm/VM.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/VM.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,386 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.vm;
+
+import org.mmtk.utility.options.Options;
+import org.mmtk.utility.gcspy.Color;
+import org.mmtk.utility.gcspy.drivers.AbstractDriver;
+import org.mmtk.vm.gcspy.ByteStream;
+import org.mmtk.vm.gcspy.IntStream;
+import org.mmtk.vm.gcspy.ServerInterpreter;
+import org.mmtk.vm.gcspy.ServerSpace;
+import org.mmtk.vm.gcspy.ShortStream;
+import org.mmtk.vm.gcspy.Util;
+import org.vmmagic.pragma.Untraced;
+import org.vmmagic.unboxed.Address;
+import org.vmmagic.unboxed.Offset;
+
+/**
+ * This class is responsible for all VM-specific functionality required
+ * by MMTk.<p>
+ *
+ * The class has three major elements. First it defines VM-specific
+ * constants which are used throughout MMTk, second, it declares
+ * singleton instances of each of the abstract classes in this
+ * package, and third, it provides factory methods for VM-specific
+ * instances which are needed by MMTk (such as <code>Lock</code>).<p>
+ *
+ * Both the constants and the singleton instances are initialized to
+ * VM-specific values at build time using reflection and a VM-specific
+ * factory class. The system property <code>mmtk.hostjvm</code> is
+ * interrogated at build time to establish concrete instantations of
+ * the abstract classes in this package. By <b>convention</b>,
+ * <code>mmtk.hostjvm</code> will identify a VM-provided package which
+ * includes concrete instances of each of the abstract classes, with
+ * each concrete class having the same base class name (but different
+ * package name) as the abstract classes defined here. The class
+ * initializer for this class then uses the system property
+ * <code>mmtk.hostjvm</code> to load the VM-specific concrete classes
+ * and initialize the constants and singletons defined here.
+ */
+public final class VM {
+ /*
+ * VM-specific constant values
+ */
+ /** <code>true</code> if assertions should be verified */
+ public static final boolean VERIFY_ASSERTIONS;
+ /** The lowest address in virtual memory known to MMTk */
+ public static final Address HEAP_START;
+ /** The highest address in virtual memory known to MMTk */
+ public static final Address HEAP_END;
+ /** The lowest address in the contiguously available memory available to MMTk */
+ public static final Address AVAILABLE_START;
+ /** The highest address in the contiguously available memory available to MMTk */
+ public static final Address AVAILABLE_END;
+ /** The log base two of the size of an address */
+ public static final byte LOG_BYTES_IN_ADDRESS;
+ /** The log base two of the size of a word */
+ public static final byte LOG_BYTES_IN_WORD;
+ /** The log base two of the size of an OS page */
+ public static final byte LOG_BYTES_IN_PAGE;
+ /** The log base two of the minimum allocation alignment */
+ public static final byte LOG_MIN_ALIGNMENT;
+ /** The log base two of (MAX_ALIGNMENT/MIN_ALIGNMENT) */
+ public static final byte MAX_ALIGNMENT_SHIFT;
+ /** The maximum number of bytes of padding to prepend to an object */
+ public static final int MAX_BYTES_PADDING;
+ /** The value to store in alignment holes */
+ public static final int ALIGNMENT_VALUE;
+ /** The offset from an array reference to element zero */
+ public static final Offset ARRAY_BASE_OFFSET;
+ /** Global debugging switch */
+ public static final boolean DEBUG;
+
+ /*
+ * VM-specific functionality captured in a series of singleton classs
+ */
+ @Untraced
+ public static final ActivePlan activePlan;
+ @Untraced
+ public static final Assert assertions;
+ @Untraced
+ public static final Barriers barriers;
+ @Untraced
+ public static final Collection collection;
+ @Untraced
+ public static final Config config;
+ @Untraced
+ public static final Memory memory;
+ @Untraced
+ public static final ObjectModel objectModel;
+ @Untraced
+ public static final ReferenceProcessor weakReferences;
+ @Untraced
+ public static final ReferenceProcessor softReferences;
+ @Untraced
+ public static final ReferenceProcessor phantomReferences;
+ @Untraced
+ public static final FinalizableProcessor finalizableProcessor;
+ @Untraced
+ public static final Scanning scanning;
+ @Untraced
+ public static final Statistics statistics;
+ @Untraced
+ public static final Strings strings;
+ @Untraced
+ public static final TraceInterface traceInterface;
+ @Untraced
+ public static final MMTk_Events events;
+ @Untraced
+ public static final Debug debugging;
+
+ /*
+ * The remainder is does the static initialization of the
+ * above, reflectively binding to the appropriate host jvm
+ * classes.
+ */
+ private static final Factory factory;
+ private static final String vmFactory;
+
+ /**
+ * This class initializer establishes a VM-specific factory class
+ * using reflection, and then uses that to create VM-specific concrete
+ * instances of all of the vm classes, initializing the singltons in
+ * this class. Finally the constants declared in this class are
+ * initialized using the VM-specific singletons.
+ */
+ static {
+ /* Identify the VM-specific factory using reflection */
+ vmFactory = System.getProperty("mmtk.hostjvm");
+ Factory xfa = null;
+ try {
+ xfa = (Factory) Class.forName(vmFactory).newInstance();
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(-1); // we must *not* go on if the above has failed
+ }
+ factory = xfa;
+
+ /* Now instantiate the singletons using the factory */
+ activePlan = factory.newActivePlan();
+ assertions = factory.newAssert();
+ barriers = factory.newBarriers();
+ collection = factory.newCollection();
+ memory = factory.newMemory();
+ objectModel = factory.newObjectModel();
+ Options.set = factory.getOptionSet();
+ weakReferences = factory.newReferenceProcessor(ReferenceProcessor.Semantics.WEAK);
+ softReferences = factory.newReferenceProcessor(ReferenceProcessor.Semantics.SOFT);
+ phantomReferences = factory.newReferenceProcessor(ReferenceProcessor.Semantics.PHANTOM);
+ finalizableProcessor = factory.newFinalizableProcessor();
+ scanning = factory.newScanning();
+ statistics = factory.newStatistics();
+ strings = factory.newStrings();
+ traceInterface = factory.newTraceInterface();
+ events = factory.newEvents();
+ debugging = factory.newDebug();
+ config = new Config(factory.newBuildTimeConfig());
+
+ /* Now initialize the constants using the vm-specific singletons */
+ VERIFY_ASSERTIONS = Assert.verifyAssertionsTrapdoor(assertions);
+ HEAP_START = Memory.heapStartTrapdoor(memory);
+ HEAP_END = Memory.heapEndTrapdoor(memory);
+ AVAILABLE_START = Memory.availableStartTrapdoor(memory);
+ AVAILABLE_END = Memory.availableEndTrapdoor(memory);
+ LOG_BYTES_IN_ADDRESS = Memory.logBytesInAddressTrapdoor(memory);
+ LOG_BYTES_IN_WORD = Memory.logBytesInWordTrapdoor(memory);
+ LOG_BYTES_IN_PAGE = Memory.logBytesInPageTrapdoor(memory);
+ LOG_MIN_ALIGNMENT = Memory.logMinAlignmentTrapdoor(memory);
+ MAX_ALIGNMENT_SHIFT = Memory.maxAlignmentShiftTrapdoor(memory);
+ MAX_BYTES_PADDING = Memory.maxBytesPaddingTrapdoor(memory);
+ ALIGNMENT_VALUE = Memory.alignmentValueTrapdoor(memory);
+ ARRAY_BASE_OFFSET = ObjectModel.arrayBaseOffsetTrapdoor(objectModel);
+ DEBUG = Debug.isEnabledTrapdoor(debugging);
+ }
+
+ /**
+ * 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 static Lock newLock(String name) {
+ return factory.newLock(name);
+ }
+
+ /**
+ * Create a new SynchronizedCounter instance using the appropriate
+ * VM-specific concrete SynchronizedCounter sub-class.
+ *
+ * @see SynchronizedCounter
+ *
+ * @return A concrete VM-specific SynchronizedCounter instance.
+ */
+ public static SynchronizedCounter newSynchronizedCounter() {
+ return factory.newSynchronizedCounter();
+ }
+
+ /**********************************************************************
+ * GCspy methods
+ */
+
+ /**
+ * Create a new Util instance using the appropriate
+ * VM-specific concrete Util sub-class.
+ *
+ * @see Util
+ *
+ * @return A concrete VM-specific Util instance.
+ */
+ public static Util newGCspyUtil() {
+ return factory.newGCspyUtil();
+ }
+
+ /**
+ * Create a new ServerInterpreter instance using the appropriate
+ * VM-specific concrete ServerInterpreter sub-class.
+ *
+ * @see ServerInterpreter
+ *
+ * @return A concrete VM-specific ServerInterpreter instance.
+ */
+ public static ServerInterpreter newGCspyServerInterpreter() {
+ return factory.newGCspyServerInterpreter();
+ }
+
+ /**
+ * Create a new ServerInterpreter instance using the appropriate
+ * VM-specific concrete ServerInterpreter sub-class.
+ *
+ * @see ServerInterpreter
+ *
+ * @return A concrete VM-specific ServerInterpreter instance.
+ */
+ public static ServerSpace newGCspyServerSpace(
+ ServerInterpreter serverInterpreter,
+ String serverName,
+ String driverName,
+ String title,
+ String blockInfo,
+ int tileNum,
+ String unused,
+ boolean mainSpace) {
+ return factory.newGCspyServerSpace(serverInterpreter, serverName, driverName,
+ title, blockInfo, tileNum, unused,
+ mainSpace);
+ }
+
+ /**
+ * 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 IntStream
+ *
+ * @return A concrete VM-specific ByteStream instance.
+ */
+ public static 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) {
+ return factory.newGCspyByteStream(driver, name, minValue, maxValue,
+ zeroValue, defaultValue, stringPre, stringPost,
+ presentation, paintStyle, indexMaxStream,
+ colour, summary);
+ }
+
+ /**
+ * 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 IntStream
+ *
+ * @return A concrete VM-specific IntStream instance.
+ */
+ public static 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) {
+ return factory.newGCspyIntStream(driver, name, minValue, maxValue,
+ zeroValue, defaultValue, stringPre, stringPost,
+ presentation, paintStyle, indexMaxStream,
+ colour, summary);
+ }
+
+ /**
+ * 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 IntStream
+ *
+ * @return A concrete VM-specific IntStream instance.
+ */
+ public static 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) {
+ return factory.newGCspyShortStream(driver, name, minValue, maxValue,
+ zeroValue, defaultValue, stringPre, stringPost,
+ presentation, paintStyle, indexMaxStream,
+ colour, summary);
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ByteStream.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ByteStream.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ByteStream.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ByteStream.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.vm.gcspy;
+
+import org.mmtk.utility.Log;
+import org.mmtk.utility.gcspy.Color;
+import org.mmtk.utility.gcspy.GCspy;
+import org.mmtk.utility.gcspy.StreamConstants;
+import org.mmtk.utility.gcspy.drivers.AbstractDriver;
+import org.mmtk.vm.VM;
+import org.vmmagic.pragma.*;
+
+/**
+ * Set up a GCspy Stream with data type BYTE_TYPE
+ */
+
+ at Uninterruptible public abstract class ByteStream extends Stream {
+
+ /****************************************************************************
+ *
+ * Instance variables
+ */
+ private byte[] data; // The stream data
+ private byte defaultValue; // The default value for the data items
+
+
+ /****************************************************************************
+ *
+ * Initialization
+ */
+
+ /**
+ * Construct a new GCspy stream of BYTE_TYPE
+ * @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
+ */
+ public ByteStream(
+ 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) {
+
+ super(driver, StreamConstants.BYTE_TYPE, name,
+ minValue, maxValue, zeroValue, defaultValue,
+ stringPre, stringPost, presentation, paintStyle,
+ indexMaxStream, colour, summary);
+
+ data = (byte[])GCspy.util.createDataArray(new byte[0], driver.getMaxTileNum());
+ this.defaultValue = defaultValue;
+ }
+
+ /**
+ * Reset all data in this stream to default values.
+ */
+ public void resetData() {
+ for (int i = 0; i < data.length; i++)
+ data[i] = defaultValue;
+ }
+
+
+ /**
+ * Distribute a value across a sequence of tiles. This handles the case
+ * when when an object spans two or more tiles and its value is to be
+ * attributed to each tile proportionally.
+ *
+ * @param start the index of the starting tile
+ * @param remainder the value left in the starting tile
+ * @param blockSize the size of each tile
+ * @param value the value to distribute
+ */
+ public void distribute(int start, byte remainder, int blockSize, byte value) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(remainder <= blockSize);
+ if (value <= remainder) { // fits in this tile
+ data[start] += value;
+ //checkspace(start, value, "scanObject fits in first tile");
+ } else {
+ data[start] += remainder;
+ //checkspace(start, remainder, "scanObject remainder put in first tile");
+ value -= remainder;
+ start++;
+ while (value >= blockSize) {
+ data[start] += blockSize;
+ //checkspace(start, blockSize, "scanObject subsequent tile");
+ value -= blockSize;
+ start++;
+ }
+ data[start] += value;
+ //checkspace(start, value, "scanObject last tile");
+ }
+ }
+
+ /**
+ * Increment the value of a tile.
+ * @param index the index
+ * @param value the increment
+ */
+ public void increment(int index, byte value) { data[index] += value; }
+
+ /**
+ * Send the data and summary for this stream.
+ * @param event The event
+ * @param numTiles The number of tiles to send (which may be less than maxTileNum)
+ * @see #ByteStream
+ */
+ public void send(int event, int numTiles) {
+ if (DEBUG) {
+ Log.write("sending "); Log.write(numTiles); Log.writeln(" int values");
+ }
+ serverSpace.stream(streamId, numTiles);
+ for (int index = 0; index < numTiles; index++)
+ serverSpace.streamByteValue(data[index]);
+ serverSpace.streamEnd();
+ sendSummary();
+ }
+}
+
Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/IntStream.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/IntStream.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/IntStream.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/IntStream.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.vm.gcspy;
+
+import org.mmtk.utility.Log;
+import org.mmtk.utility.gcspy.Color;
+import org.mmtk.utility.gcspy.GCspy;
+import org.mmtk.utility.gcspy.StreamConstants;
+import org.mmtk.utility.gcspy.drivers.AbstractDriver;
+import org.mmtk.vm.VM;
+import org.vmmagic.pragma.*;
+
+/**
+ * Set up a GCspy Stream with data type INT_TYPE.
+ */
+ at Uninterruptible public abstract class IntStream extends Stream {
+
+ /****************************************************************************
+ *
+ * Instance variables
+ */
+ private int[] data; // The stream data
+ private int defaultValue; // The default value for the data items
+
+
+ /****************************************************************************
+ *
+ * Initialization
+ */
+
+ /**
+ * Construct a new GCspy stream of INT_TYPE
+ * @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
+ */
+ public IntStream(
+ 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) {
+
+ super(driver, StreamConstants.INT_TYPE, name,
+ minValue, maxValue, zeroValue, defaultValue,
+ stringPre, stringPost, presentation, paintStyle,
+ indexMaxStream, colour, summary);
+
+ data = (int[])GCspy.util.createDataArray(new int[0], driver.getMaxTileNum());
+ this.defaultValue = defaultValue;
+ }
+
+ /**
+ * Reset all data in this stream to default values.
+ */
+ public void resetData() {
+ for (int i = 0; i < data.length; i++)
+ data[i] = defaultValue;
+ }
+
+
+ /**
+ * Distribute a value across a sequence of tiles. This handles the case
+ * when when an object spans two or more tiles and its value is to be
+ * attributed to each tile proportionally.
+ *
+ * @param start the index of the starting tile
+ * @param remainder the value left in the starting tile
+ * @param blockSize the size of each tile
+ * @param value the value to distribute
+ */
+ public void distribute(int start, int remainder, int blockSize, int value) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(remainder <= blockSize);
+ if (value <= remainder) { // fits in this tile
+ data[start] += value;
+ //checkspace(start, value, "scanObject fits in first tile");
+ } else {
+ data[start] += remainder;
+ //checkspace(start, remainder, "scanObject remainder put in first tile");
+ value -= remainder;
+ start++;
+ while (value >= blockSize) {
+ data[start] += blockSize;
+ //checkspace(start, blockSize, "scanObject subsequent tile");
+ value -= blockSize;
+ start++;
+ }
+ data[start] += value;
+ //checkspace(start, value, "scanObject last tile");
+ }
+ }
+
+ /**
+ * Increment the value of a tile.
+ * @param index the index
+ * @param value the increment
+ */
+ public void increment(int index, int value) { data[index] += value; }
+
+ /**
+ * Send the data and summary for this stream.
+ * @param event The event
+ * @param numTiles The number of tiles to send (which may be less than maxTileNum)
+ */
+ public void send(int event, int numTiles) {
+ if (DEBUG) {
+ Log.write("sending "); Log.write(numTiles); Log.writeln(" int values");
+ }
+
+ serverSpace.stream(streamId, numTiles);
+ for (int index = 0; index < numTiles; index++)
+ serverSpace.streamIntValue(data[index]);
+ serverSpace.streamEnd();
+
+ sendSummary();
+ }
+}
+
Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ServerInterpreter.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ServerInterpreter.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ServerInterpreter.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ServerInterpreter.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.vm.gcspy;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.Address;
+
+/**
+ * Abstract class for the GCspy server interpreter
+ *
+ * Implementing classes will mostly forward calls to the C gcspy library.
+ */
+ at Uninterruptible public abstract class ServerInterpreter {
+
+ protected static final int MAX_LEN = 64 * 1024; // Buffer size
+ protected static final int MAX_SPACES = 32; // Maximum number of spaces
+ protected static boolean initialised = false;
+
+ protected ServerSpace[] spaces; // The server's spaces
+ protected Address server; // a pointer to the c server, gcspy_main_server_t server
+
+ protected static final boolean DEBUG = false;
+
+ /**
+ * Create a new ServerInterpreter singleton.
+ * @param name The name of the server
+ * @param port The number of the port on which to communicate
+ * @param verbose Whether the server is to run verbosely
+ */
+ @Interruptible
+ public abstract void init(String name, int port, boolean verbose);
+
+ /**
+ * Add an event to the ServerInterpreter.
+ * @param num the event number
+ * @param name the event name
+ */
+ public abstract void addEvent(int num, String name);
+
+ /**
+ * Set the general info for the ServerInterpreter.
+ * @param info the information
+ */
+ public abstract void setGeneralInfo(String info);
+
+ /**
+ * Get a pointer to the C server, gcspy_main_server_t.
+ * This address is used in alll calls to the server in the C library.
+ * @return the address of the server
+ */
+ public Address getServerAddress() { return server; }
+
+ /**
+ * Add a GCspy ServerSpace to the ServerInterpreter.
+ * This method returns a unique space ID for the ServerSpace
+ * (again used in calls to the C library).
+ *
+ * @param space the ServerSpace to add
+ * @return a unique id for this space
+ * @exception IndexOutOfBoundsException on attempt to add more than
+ * MAX_SPACES spaces
+ */
+ @Interruptible
+ public int addSpace(ServerSpace space) {
+ int id = 0;
+ while (id < MAX_SPACES) {
+ if (spaces[id] == null) {
+ spaces[id] = space;
+ return id;
+ }
+ id++;
+ }
+ throw new IndexOutOfBoundsException(
+ "Too many spaces to add to interpreter.\nSet MAX_SPACES to higher value in ServerInterpreter.");
+ }
+
+ /**
+ * Start the server, running its main loop in a pthread.
+ * @param wait Whether to wait for the client to connect
+ */
+ public abstract void startServer(boolean wait);
+
+ /**
+ * Are we connected to a GCspy client?
+ * @param event The current event
+ * @return true if we are connected
+ */
+ public abstract boolean isConnected(int event);
+
+ /**
+ * Start compensation timer so that time spent gathering data is
+ * not confused with the time spent in the application and the VM.
+ */
+ public abstract void startCompensationTimer();
+
+ /**
+ * Stop compensation timer so that time spent gathering data is
+ * not confused with the time spent in the application and the VM.r
+ */
+ public abstract void stopCompensationTimer();
+
+ /**
+ * Indicate that we are at a server safe point (e.g. the end of a GC).
+ * This is a point at which the server can pause, play one, etc.
+ * @param event The current event
+ */
+ public abstract void serverSafepoint(int event);
+
+ /**
+ * Discover the smallest header size for objects.
+ * @return the size in bytes
+ */
+ public abstract int computeHeaderSize();
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ServerSpace.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ServerSpace.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ServerSpace.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ServerSpace.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,160 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.vm.gcspy;
+
+import org.mmtk.utility.Log;
+import org.mmtk.utility.gcspy.drivers.AbstractDriver;
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * Abstract class for the GCspy Space abstraction.
+ *
+ * Implementing classes will largely forward calls to the gcspy C library.
+ */
+ at Uninterruptible public abstract class ServerSpace {
+
+ /****************************************************************************
+ *
+ * Class variables
+ */
+ protected static final String DEFAULT_UNUSED_STRING = "NOT USED"; // The "unused" string
+
+ /****************************************************************************
+ *
+ * Instance variables
+ */
+ protected int spaceId; // the space's ID
+ protected Address driver; // a pointer to the C driver, gcspy_gc_drivert *driver;
+ protected static final boolean DEBUG = false;
+
+
+ /**
+ * Get a pointer to the native driver
+ * @return The address of the C driver, gcspy_gc_drivert *, used in all calls
+ * to the C library.
+ */
+ Address getDriverAddress() {
+ return driver;
+ }
+
+ /**
+ * Tell the native driver the tile name.
+ * @param i the number of the tile
+ * @param start the starting address of the tile
+ * @param end the end address
+ */
+ public abstract void setTilename(int i, Address start, Address end);
+
+ /**
+ * Tell the native driver the tile name.
+ * @param i the number of the tile
+ * @param format the name of the tile, a format string
+ * @param value The value for the format string
+ */
+ public abstract void setTilename(int i, Address format, long value);
+
+ /**
+ * Tell the native driver the tile names.
+ * @param i the number of the tile
+ * @param format The name, including format tags
+ * @param value The value for the format string
+ */
+ public abstract void setTilename(int i, String format, long value);
+
+ /**
+ * Tell the C driver to resize
+ * @param size the new driver size
+ */
+ public abstract void resize(int size);
+
+ /**
+ * Start a transmission
+ */
+ public abstract void startCommunication();
+
+ /**
+ * Add a stream to the native driver
+ * @param id the stream's ID
+ * @return the address of the C gcspy_gc_stream_t
+ */
+ public abstract Address addStream(int id);
+
+ /**
+ * Start transmitting a stream.
+ * @param id The stream's ID
+ * @param len The number of items in the stream
+ */
+ public abstract void stream(int id, int len);
+
+ /**
+ * Send a byte
+ * @param value The byte
+ */
+ public abstract void streamByteValue(byte value);
+
+ /**
+ * Send a short
+ * @param value The short
+ */
+ public abstract void streamShortValue(short value);
+
+ /**
+ * Send an int
+ * @param value The int
+ */
+ public abstract void streamIntValue(int value);
+
+ /**
+ * End of this stream
+ */
+ public abstract void streamEnd();
+
+ /**
+ * Start to send a summary
+ * @param id The stream's ID
+ * @param len The number of items to be sent
+ */
+ public abstract void summary(int id, int len);
+
+ /**
+ * Send a summary value
+ * @param val The value
+ */
+ public abstract void summaryValue(int val);
+
+ /**
+ * End the summary
+ */
+ public abstract void summaryEnd();
+
+ /**
+ * Send all the control info for the space
+ * @param space The GCspy driver for this space
+ * @param tileNum The number of tiles
+ */
+ public abstract void sendControls(AbstractDriver space, int tileNum);
+
+ /**
+ * Send info for this space
+ * @param info A pointer to the information (held as C string)
+ */
+ public abstract void spaceInfo(Address info);
+
+ /**
+ * End the transmission (for this event)
+ */
+ public void endCommunication() {
+ if (DEBUG) Log.write("endComm\n");
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ShortStream.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ShortStream.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ShortStream.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/ShortStream.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,146 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.vm.gcspy;
+
+import org.mmtk.utility.Log;
+import org.mmtk.utility.gcspy.Color;
+import org.mmtk.utility.gcspy.GCspy;
+import org.mmtk.utility.gcspy.StreamConstants;
+import org.mmtk.utility.gcspy.drivers.AbstractDriver;
+import org.mmtk.vm.VM;
+import org.vmmagic.pragma.*;
+
+/**
+ * Set up a GCspy Stream with data type SHORT_TYPE.
+ */
+ at Uninterruptible public abstract class ShortStream extends Stream {
+
+ /****************************************************************************
+ *
+ * Instance variables
+ */
+ private short[] data; // The stream data
+ private short defaultValue; // The default value for the data items
+
+ /****************************************************************************
+ *
+ * Initialization
+ */
+
+ /**
+ * Construct a new GCspy stream of SHORT_TYPE
+ * @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
+ */
+ public ShortStream(
+ 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) {
+
+ super(driver, StreamConstants.SHORT_TYPE, name,
+ minValue, maxValue, zeroValue, defaultValue,
+ stringPre, stringPost, presentation, paintStyle,
+ indexMaxStream, colour, summary);
+
+ data = (short[])GCspy.util.createDataArray(new short[0], driver.getMaxTileNum());
+ this.defaultValue = defaultValue;
+ }
+
+ /**
+ * Reset all data in this stream to default values.
+ */
+ public void resetData() {
+ for (int i = 0; i < data.length; i++)
+ data[i] = defaultValue;
+ }
+
+
+ /**
+ * Distribute a value across a sequence of tiles. This handles the case
+ * when when an object spans two or more tiles and its value is to be
+ * attributed to each tile proportionally.
+ *
+ * @param start the index of the starting tile
+ * @param remainder the value left in the starting tile
+ * @param blockSize the size of each tile
+ * @param value the value to distribute
+ */
+ public void distribute(int start, short remainder, int blockSize, short value) {
+ if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(remainder <= blockSize);
+ if (value <= remainder) { // fits in this tile
+ data[start] += value;
+ //checkspace(start, value, "scanObject fits in first tile");
+ } else {
+ data[start] += remainder;
+ //checkspace(start, remainder, "scanObject remainder put in first tile");
+ value -= remainder;
+ start++;
+ while (value >= blockSize) {
+ data[start] += blockSize;
+ //checkspace(start, blockSize, "scanObject subsequent tile");
+ value -= blockSize;
+ start++;
+ }
+ data[start] += value;
+ //checkspace(start, value, "scanObject last tile");
+ }
+ }
+
+ /**
+ * Increment the value of a tile.
+ * @param index the index
+ * @param value the increment
+ */
+ public void increment(int index, short value) { data[index] += value; }
+
+ /**
+ * Send the data and summary for this stream.
+ * @param event The event
+ * @param numTiles The number of tiles to send (which may be less than maxTileNum)
+ */
+ public void send(int event, int numTiles) {
+ if (DEBUG) {
+ Log.write("sending "); Log.write(numTiles); Log.writeln(" int values");
+ }
+ serverSpace.stream(streamId, numTiles);
+ for (int index = 0; index < numTiles; index++)
+ serverSpace.streamShortValue(data[index]);
+ serverSpace.streamEnd();
+
+ // send the summary
+ sendSummary();
+ }
+}
+
Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/Stream.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/Stream.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/Stream.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/Stream.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,217 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Eclipse Public License (EPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.mmtk.vm.gcspy;
+
+import org.mmtk.utility.Log;
+import org.mmtk.utility.gcspy.Color;
+import org.mmtk.utility.gcspy.StreamConstants;
+import org.mmtk.utility.gcspy.drivers.AbstractDriver;
+import org.mmtk.vm.VM;
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.Address;
+
+/**
+ *
+ * Abstract class for a GCspy Stream.
+ * Implementing classes will mostly forward calls
+ * to the gcspy C library
+ */
+
+ at Uninterruptible public abstract class Stream {
+
+ /****************************************************************************
+ *
+ * Instance variables
+ */
+
+ /**
+ * The address of the C stream, gcspy_gc_stream_t *stream, used in all calls
+ * to the C library
+ */
+ protected Address stream;
+
+ /** The owning GCspy space */
+ protected ServerSpace serverSpace;
+
+ /** The stream's ID */
+ protected int streamId;
+
+ /**
+ * A summary has 1 or 2 values depending on presentation style
+ * (PERCENT* styles require 2 values).
+ */
+ protected int summaryLen;
+
+ /** The first summary value */
+ protected int summary0;
+
+ /** The second summary value (if any) */
+ protected int summary1;
+
+ private int min; // The minimum value for tiles
+
+ private int max; // The maximum value for tiles
+
+ /** use summaries? */
+ protected boolean summaryEnabled;
+
+ /** the presentation style */
+ protected int presentation;
+
+ protected static final boolean DEBUG = false;
+
+ /**
+ * Construct a new GCspy stream.
+ *
+ * @param driver The AbstractDriver that owns this Stream
+ * @param dataType The stream's data type, one of BYTE_TYPE, SHORT_TYPE or INT_TYPE
+ * @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 for the maximum stream if the presentation is *_VAR.
+ * @param colour The default colour for tiles of this stream
+ * @param summary Is a summary enabled?
+ */
+ protected Stream(
+ AbstractDriver driver,
+ int dataType,
+ String name,
+ int minValue,
+ int maxValue,
+ int zeroValue,
+ int defaultValue,
+ String stringPre,
+ String stringPost,
+ int presentation,
+ int paintStyle,
+ int indexMaxStream,
+ Color colour,
+ boolean summary) {
+
+ serverSpace = driver.getServerSpace();
+ summaryEnabled = summary;
+ this.presentation = presentation;
+ if (summary)
+ setupSummary(presentation);
+ min = minValue;
+ max = maxValue;
+
+ driver.addStream(this);
+ if (DEBUG) {
+ Log.write("Adding stream ");
+ Log.write(name);
+ Log.writeln(" id=", streamId);
+ }
+ }
+
+
+ /**
+ * Set the stream address and id (called by AbstractDriver.addStream).
+ * @param id the id
+ * @param str the address of the gcspy C gcspy_gc_stream_t *stream
+ */
+ public void setStream(int id, Address str) {
+ streamId = id;
+ stream = str;
+ }
+
+ /**
+ * Return the minimum value expected for this stream.
+ * @return the minimum value
+ */
+ public int getMinValue() { return min; }
+
+ /**
+ * Return the maximum value expected for this stream.
+ * @return the maximum value
+ */
+ public int getMaxValue() { return max; }
+
+ /**
+ * Setup the summary array.
+ * @param presentation the presentation style
+ */
+ @Interruptible
+ private void setupSummary(int presentation) {
+ switch (presentation) {
+ case StreamConstants.PRESENTATION_PLAIN:
+ case StreamConstants.PRESENTATION_PLUS:
+ case StreamConstants.PRESENTATION_MAX_VAR:
+ case StreamConstants.PRESENTATION_ENUM:
+ summaryLen = 1;
+ break;
+ case StreamConstants.PRESENTATION_PERCENT:
+ case StreamConstants.PRESENTATION_PERCENT_VAR:
+ summaryLen = 2;
+ break;
+ default:
+ VM.assertions._assert(false);
+ }
+ }
+
+ /**
+ * Set the summary value for presentation styles with just one value
+ * @param value0 the value
+ */
+ public void setSummary(int value0) {
+ if (VM.VERIFY_ASSERTIONS)
+ VM.assertions._assert(presentation != StreamConstants.PRESENTATION_PERCENT &&
+ presentation != StreamConstants.PRESENTATION_PERCENT_VAR);
+ summary0 = value0;
+ }
+
+ /**
+ * Set the summary values for presentation styles with two values (i.e.
+ * PRESENTATION_PERCENT and PRESENTATION_PERCENT_VAR).
+ * @param value0 the numerator value
+ * @param value1 the denominator value
+ */
+ public void setSummary(int value0, int value1) {
+ if (VM.VERIFY_ASSERTIONS)
+ VM.assertions._assert(presentation == StreamConstants.PRESENTATION_PERCENT ||
+ presentation == StreamConstants.PRESENTATION_PERCENT_VAR);
+ summary0 = value0;
+ summary1 = value1;
+ }
+
+ /**
+ * Send the data for this stream.
+ * @param event the event.
+ * @param numTiles the number of tiles to send.
+ */
+ public abstract void send(int event, int numTiles);
+
+ /**
+ * Send the summary data for this stream.
+ */
+ public void sendSummary() {
+ if (summaryEnabled) {
+ serverSpace.summary(streamId, summaryLen);
+ serverSpace.summaryValue(summary0);
+ if (summaryLen == 2)
+ serverSpace.summaryValue(summary1);
+ serverSpace.summaryEnd();
+ }
+ }
+
+}
+
+
Added: vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/Util.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/Util.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/Util.java (added)
+++ vmkit/trunk/mmtk/java/src/org/mmtk/vm/gcspy/Util.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.vm.gcspy;
+
+import org.mmtk.utility.Log;
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * Abstract class that provides generally useful
+ * methods.
+ */
+ at Uninterruptible public abstract class Util {
+
+ /**
+ * Allocate an array of bytes with malloc
+ *
+ * @param size The size to allocate
+ * @return The start address of the memory allocated in C space
+ * @see #free
+ */
+ public abstract Address malloc(int size);
+
+ /**
+ * Free an array of bytes previously allocated with malloc
+ *
+ * @param addr The address of some memory previously allocated with malloc
+ * @see #malloc
+ */
+ public abstract void free(Address addr);
+
+ /**
+ * Dump a range in format [start,end)
+ *
+ * @param start The start of the range
+ * @param end The end of the range
+ */
+ public static void dumpRange(Address start, Address end) {
+ Log.write("["); Log.write(start);
+ Log.write(","); Log.write(end);
+ Log.write(')');
+ }
+
+ /**
+ * Convert a String to a 0-terminated array of bytes
+ *
+ * @param str The string to convert
+ * @return The address of a null-terminated array in C-space
+ */
+ public abstract Address getBytes(String str);
+
+ /**
+ * Pretty print a size, converting from bytes to kilo- or mega-bytes as appropriate
+ *
+ * @param buffer The buffer (in C space) in which to place the formatted size
+ * @param size The size in bytes
+ */
+ public abstract void formatSize(Address buffer, int size);
+
+ /**
+ * Pretty print a size, converting from bytes to kilo- or mega-bytes as appropriate
+ *
+ * @param format A format string
+ * @param bufsize The size of a buffer large enough to hold the formatted result
+ * @param size The size in bytes
+ */
+ public abstract Address formatSize(String format, int bufsize, int size);
+
+// public abstract Address formatSize(String format, int bufsize, int size);
+
+ /**
+ * Place a string representation of a long in an array of bytes
+ * without incurring allocation
+ *
+ * @param buffer The byte array
+ * @param value The long to convert
+ * @return The length of the string representation of the integer
+ * -1 indicates some problem (e.g the char buffer was too small)
+ */
+ public static int numToBytes(byte[] buffer, long value) {
+ return numToBytes(buffer, value, 10);
+ }
+
+ /**
+ * Place a string representation of a long in an array of bytes
+ * without incurring allocation
+ *
+ * @param buffer The byte array
+ * @param value The long to convert
+ * @param radix the base to use for conversion
+ * @return The length of the string representation of the integer
+ * -1 indicates some problem (e.g the char buffer was too small)
+ */
+ public static int numToBytes(byte[] buffer, long value, int radix) {
+
+ if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
+ radix = 10;
+
+ if (value == 0) {
+ buffer[0] = (byte)'0';
+ return 1;
+ }
+
+ boolean negative;
+ long longValue;
+ int count;
+ if (!(negative = (value < 0))) {
+ longValue = -value;
+ count = 1;
+ } else {
+ longValue = value;
+ count = 2;
+ }
+
+ long j = longValue;
+ while ((j /= radix) != 0) count++;
+ if (count > buffer.length)
+ return -1; // overflow
+
+ int i = count;
+ do {
+ int ch = (int) -(longValue % radix);
+ if (ch > 9)
+ ch -= (10 - (int) 'a');
+ else
+ ch += (int) '0';
+ buffer [--i] = (byte) ch;
+ } while ((longValue /= radix) != 0);
+ if (negative) buffer [0] = (byte)'-';
+
+ return count;
+
+ }
+
+ /**
+ * sprintf(char *str, char *format, char* value)
+ *
+ * @param str The destination 'string' (memory in C space)
+ * @param format The format 'string' (memory in C space)
+ * @param value The value 'string' (memory in C space)
+ * @return The number of characters printed (as returned by C's sprintf
+ */
+ public abstract int sprintf(Address str, Address format, Address value);
+
+ /**
+ * Create an array of a particular type.
+ * The easiest way to use this is:
+ * Foo[] x = (Foo [])Stream.createDataArray(new Foo[0], numElements);
+ * @param templ a data array to use as a template
+ * @param numElements number of elements in new array
+ * @return the new array
+ */
+ @Interruptible
+ public abstract Object createDataArray(Object templ, int numElements);
+}
+
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/Intrinsic.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/Intrinsic.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/Intrinsic.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/Intrinsic.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+
+/**
+ * An intrinsic method is a method that is built in (that is, intrinsic) to the compiler
+ * rather than part of a class library. Intrinsic methods are an escape hatch to provide
+ * "magic" that is inexpressible int the Java programming language. A compiler intrinsic
+ * will usually generate a specific code sequence that is inlined and optimized as part
+ * by the compiler. Unless an intrinsic method is expected to be executed in a non-intrinsic
+ * aware compiler, the body of the method should be empty.
+ *
+ * <p>If the Intrinsic annotation is applied to a method then then the method is a compiler
+ * intrinsic. If the Intrinsic annotation is applied to a class then all the methods of
+ * the class AND all subclasses are intrinsic.</p>
+ *
+ * <p>NOTE: At the current time the Intrinsic annotation is only used for documentation
+ * purposes but in the near future it is expected that the semantics of the annotation will
+ * be enforced by the compiler.</p>
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.TYPE,ElementType.METHOD})
+ at Inherited
+public @interface Intrinsic { }
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/Pragma.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/Pragma.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/Pragma.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/Pragma.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+
+/**
+ * A Pragma is a mechanism for supplying information to the compiler to alter the code it
+ * generates for a method. A Pragma is similar to an {@link org.vmmagic.Intrinsic}
+ * but it does not provide any behaviour but provides information to the compiler that modifies
+ * optimizations, calling conventions and activation frame layout.
+ *
+ * <p>If the Pragma annotation is applied to a method then then the method is a handled specially
+ * by the compiler. If the Pragma annotation is applied to a class then then all the methods in that
+ * class are handled specially by the compiler.</p>
+ *
+ * <p>NOTE: At the current time the Pragma annotation is only used for documentation
+ * purposes but in the near future it is expected that the semantics of the annotation will
+ * be enforced by the compiler.</p>
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.TYPE,ElementType.METHOD})
+ at Inherited
+public @interface Pragma { }
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/Unboxed.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/Unboxed.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/Unboxed.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/Unboxed.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+
+/**
+ * The Unboxed annotation marks a type as unboxed. Besides the primitive types, all Java values
+ * are boxed types. Conceptually, they are represented by a pointer to a heap object. However,
+ * an unboxed type is represented by the value itself. All methods on an unboxed type are
+ * {@link Intrinsic}s.
+ *
+ * <p>As an unboxed type is not a regular java object there are a few constraints on the way unboxed
+ * types are handled;</p>
+ * <ul>
+ * <li>All methods are {@link Intrinsic} and thus there can be no virtual methods.</li>
+ * <li>An unboxed type can not be synchronized on.</li>
+ * <li>An unboxed type has no hashcode.</li>
+ * <li>An unboxed type MUST NOT be passed where an object is expected or when two overloaded methods
+ * can only be distinguished by by Object vs unboxed parameter type.</li>
+ * </ul>
+ *
+ * <p>NOTE: At the current time the Unboxed annotation is only used for documentation
+ * purposes but in the near future it is expected that the semantics of the annotation will
+ * be enforced by the compiler.</p>
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.TYPE)
+ at Inherited
+public @interface Unboxed { }
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/BaselineNoRegisters.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/BaselineNoRegisters.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/BaselineNoRegisters.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/BaselineNoRegisters.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.ElementType;
+import org.vmmagic.Pragma;
+
+/**
+ * Some methods shouldn't use registers for locals and stack values.
+ * E.g. CollectorThread can't relocate refs in registers of its own.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.METHOD)
+ at Pragma
+public @interface BaselineNoRegisters { }
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/BaselineSaveLSRegisters.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/BaselineSaveLSRegisters.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/BaselineSaveLSRegisters.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/BaselineSaveLSRegisters.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.ElementType;
+import org.vmmagic.Pragma;
+
+/**
+ * Methods with this pragma that are BaselineCompiled should save in its prologue, ALL registers that
+ * can be used to store local and stack registers in any BaselineCompiled method. Used by OSR.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.METHOD)
+ at Pragma
+public @interface BaselineSaveLSRegisters { }
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/DynamicBridge.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/DynamicBridge.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/DynamicBridge.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/DynamicBridge.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import org.vmmagic.Pragma;
+
+/**
+ * Methods of a class that implements this interface are treated specially
+ * by the compilers.
+ *
+ * <p>Instead of saving just the non-volatile registers used by the method into
+ * the register save area of the method's stackframe, the compiler generates
+ * code to save *all* GPR and FPR registers except GPR0, FPR0, JTOC, and FP.
+ *
+ * <p>Methods of a class that implement this interface may not return.
+ * (it is assumed that execution is resumed via a call to Magic.dynamicBridgeTo)
+ *
+ * @see org.jikesrvm.runtime.Magic#dynamicBridgeTo(org.jikesrvm.ArchitectureSpecific.CodeArray)
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.TYPE)
+ at Pragma
+public @interface DynamicBridge { }
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Entrypoint.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Entrypoint.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Entrypoint.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Entrypoint.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,29 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import org.vmmagic.Pragma;
+
+/**
+ * The entrypoint annotation indicates that the method or field is
+ * directly accessed by the compiler. We cache resolved values for
+ * these elements in Entrypoints.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.METHOD, ElementType.FIELD})
+ at Pragma
+public @interface Entrypoint { }
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Inline.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Inline.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Inline.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Inline.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,63 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.ElementType;
+import org.vmmagic.Pragma;
+
+/**
+ * This pragma indicates that a particular method should always be inlined
+ * by the optimizing compiler.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.METHOD)
+ at Pragma
+public @interface Inline {
+ /**
+ * Enumeration defining when to inline
+ */
+ public enum When {
+ /**
+ * Always inline, regardless of arguments
+ */
+ Always,
+ /**
+ * Inline when all the arguments are constants
+ */
+ AllArgumentsAreConstant,
+ /**
+ * Inline when the specified arguments are constants
+ */
+ ArgumentsAreConstant,
+ /**
+ * Inline when the VM is built without Assertions (VM.VerifyAssertions == false).
+ * Note: It would be nicer to have the more general ExpressionIsTrue annotation,
+ * but the argument expression to the annotation is restricted to be a fairly
+ * trivial constant, and that isn't enough to handle how VM.VERIFY_ASSERTIONS
+ * is defined in MMTk.
+ */
+ AssertionsDisabled
+ }
+ /**
+ * When to inline, default When.Always
+ */
+ When value() default When.Always;
+ /**
+ * Arguments that must be constant to cause inlining. NB for static methods 0
+ * is the first argument whilst for virtual methods 0 is this
+ */
+ int[] arguments() default {};
+}
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Interruptible.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Interruptible.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Interruptible.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Interruptible.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.ElementType;
+import org.vmmagic.Pragma;
+
+/**
+ * By default all Java code is interruptible, that is scheduling or garbage
+ * collection may occur at points within the code. Code can be marked as
+ * {@link Unpreemptible} or {@link Uninterruptible}, that instructs the JVM to
+ * avoid garbage collection and thread scheduling. The {@link Uninterruptible}
+ * annotation disallows any operation that may cause garbage collection or
+ * thread scheduling, for example memory allocation. The {@link Unpreemptible}
+ * annotation doesn't disallow operations that can cause garbage collection or
+ * scheduling, but instructs the JVM to avoid inserting such operations during a
+ * block of code.
+ *
+ * In the internals of a VM most code wants to be {@link Uninterruptible}.
+ * However, code involved in scheduling and locking will cause context switches,
+ * and creating exception objects may trigger garbage collection, this code is
+ * therefore {@link Unpreemptible}.
+ *
+ * This pragma is used to declare that a particular method is interruptible. It
+ * is used to override the class-wide pragma {@link Uninterruptible}.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.METHOD)
+ at Pragma
+public @interface Interruptible {
+ /**
+ * @return Explanation of why code needs to be interruptible
+ */
+ String value() default "";
+}
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/LogicallyUninterruptible.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/LogicallyUninterruptible.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/LogicallyUninterruptible.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/LogicallyUninterruptible.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.ElementType;
+import org.vmmagic.Pragma;
+
+/**
+ * A pragma that can be used to declare that a particular method is logically
+ * uninterruptible even though it contains bytecodes that are actually
+ * interruptible.
+ *
+ * The effect of this pragma is to suppress warning messages about violations of
+ * uninterruptiblity when compiling a method that throws this exception. There
+ * are two cases in which using the pragma is justified.
+ * <ul>
+ * <li> Uninterruptibility is ensured via some other mechanism. For example, the
+ * method explicitly disables threadswitching around the interruptible regions
+ * (VM.sysWrite on String). Or the interruptible regions are not reachable when
+ * the VM is running (various VM.sysWrite that check VM.runningVM).
+ * <li> The interruptible regions represent an 'error' condition that will never
+ * be executed unless the VM is already in the process of reporting an error,
+ * for example RuntimeEntrypoints.raiseClassCastException.
+ * <ul>
+ * Extreme care must be exercised when using this pragma since it suppresses the
+ * checking of uninterruptibility.
+ * <p>
+ * Use of this pragma is being phased out since it lumps together two possible
+ * special cases. Use either {@link Unpreemptible} or
+ * {@link UninterruptibleNoWarn} instead.
+ * {@link <a href="http://jira.codehaus.org/browse/RVM-115">RVM-115</a>} for more
+ * context.
+ * @deprecated
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.METHOD)
+ at Pragma
+public @interface LogicallyUninterruptible { }
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NativeBridge.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NativeBridge.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NativeBridge.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NativeBridge.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import org.vmmagic.Pragma;
+
+/**
+ * Methods of a class that implements this interface are treated specially
+ * by the compilers:
+ * -They are only called from C or C++ program
+ * -The compiler will generate the necessary prolog to insert a glue stack
+ * frame to map from the native stack/register convention to RVM's convention
+ * -It is an error to call these methods from Java
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.TYPE)
+ at Pragma
+public @interface NativeBridge { }
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoBoundsCheck.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoBoundsCheck.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoBoundsCheck.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoBoundsCheck.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.ElementType;
+import org.vmmagic.Pragma;
+
+/**
+ * This pragma indicates that a particular method should never have bounds
+ * checks generated.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.METHOD)
+ at Pragma
+public @interface NoBoundsCheck { }
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoEscapes.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoEscapes.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoEscapes.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoEscapes.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.ElementType;
+
+/**
+ * Use this annotation to mark methods that won't cause their reference arguments
+ * to escape. If we can convert the object referenced in to registers then the
+ * method marked with this annotation will be removed.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+public @interface NoEscapes { }
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoInline.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoInline.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoInline.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoInline.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.ElementType;
+import org.vmmagic.Pragma;
+
+/**
+ * This pragma indicates that a particular method should never be inlined
+ * by the optimizing compiler.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.METHOD)
+ at Pragma
+public @interface NoInline { }
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoNullCheck.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoNullCheck.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoNullCheck.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoNullCheck.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.ElementType;
+import org.vmmagic.Pragma;
+
+/**
+ * This pragma indicates that a particular method should never have null checks
+ * generated.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.METHOD)
+ at Pragma
+public @interface NoNullCheck { }
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoOptCompile.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoOptCompile.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoOptCompile.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NoOptCompile.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,29 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.ElementType;
+import org.vmmagic.Pragma;
+
+/**
+ * This pragma indicates that a particular method should never be
+ * compiled by the optimizing compiler. It also implies that the
+ * method will never be inlined by the optimizing compiler.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.TYPE, ElementType.METHOD})
+ at Pragma
+public @interface NoOptCompile { }
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NonMoving.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NonMoving.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NonMoving.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NonMoving.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.ElementType;
+
+/**
+ * Use this annotation to mark types that must never move. This is intended for
+ * a very small set of VM internal types that are accessed without knowledge of the
+ * memory manager. This includes code, that is CALLed and fields that are loaded
+ * directly (such as Untraced fields).
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.TYPE)
+public @interface NonMoving { }
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NonMovingAllocation.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NonMovingAllocation.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NonMovingAllocation.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/NonMovingAllocation.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.ElementType;
+
+/**
+ * Use this annotation to mark methods for which all allocation must never
+ * move. This is intended for a very small set of VM internal methods that
+ * specifically require these semantics.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.METHOD)
+public @interface NonMovingAllocation { }
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Preemptible.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Preemptible.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Preemptible.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Preemptible.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.ElementType;
+import org.vmmagic.Pragma;
+
+/**
+ * By default all Java code is interruptible, that is scheduling or garbage
+ * collection may occur at points within the code. Code can be marked as
+ * {@link Unpreemptible} or {@link Uninterruptible}, that instructs the JVM to
+ * avoid garbage collection and thread scheduling. The {@link Uninterruptible}
+ * annotation disallows any operation that may cause garbage collection or
+ * thread scheduling, for example memory allocation. The {@link Unpreemptible}
+ * annotation doesn't disallow operations that can cause garbage collection or
+ * scheduling, but instructs the JVM to avoid inserting such operations during a
+ * block of code.
+ *
+ * In the internals of a VM most code wants to be {@link Uninterruptible}.
+ * However, code involved in scheduling and locking will cause context switches,
+ * and creating exception objects may trigger garbage collection, this code is
+ * therefore {@link Unpreemptible}.
+ *
+ * This pragma is used to declare that a particular method is preemptible. It
+ * is used to override the class-wide pragma {@link Unpreemptible}.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.TYPE, ElementType.METHOD})
+ at Pragma
+public @interface Preemptible {
+ /**
+ * @return Explanation of why code needs to be preemptible
+ */
+ String value() default "";
+}
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Pure.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Pure.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Pure.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Pure.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.ElementType;
+import org.vmmagic.Pragma;
+
+/**
+ * This pragma is used to indicate a method has no side effects. Use this pragma
+ * with care as it can cause compile time invocation of the method it is placed
+ * on. This pragma is used to imply weak purity of a method, and as such cannot
+ * remove calls to pure methods - as they may throw exceptions.
+ * {@link <a href="http://jira.codehaus.org/browse/RVM-503">RVM-503</a>}.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.METHOD})
+ at Pragma
+public @interface Pure { /* annotation has no value */ }
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RawStorage.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RawStorage.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RawStorage.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RawStorage.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.ElementType;
+import org.vmmagic.Pragma;
+
+/**
+ * When applied to class this annotation indicates that the data component
+ * of this field consists of an intrisically managed chunk of raw memory of
+ * the specified size. This is used as the basic building block for native
+ * width types.
+ *
+ * To construct types larger than those possible with RawStorage, simply
+ * construct an type with multiple (Unboxed) fields.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.TYPE})
+ at Pragma
+public @interface RawStorage {
+ boolean lengthInWords();
+ int length();
+}
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RuntimeFinal.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RuntimeFinal.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RuntimeFinal.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RuntimeFinal.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.ElementType;
+import org.vmmagic.Pragma;
+
+/**
+ * This pragma is used to indicate a field will be final in the running VM. We
+ * can't indicate all fields are final as some are used in the boot strap
+ * process.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.FIELD})
+ at Pragma
+public @interface RuntimeFinal {
+ /** The value of the field. Currently only boolean values can be RuntimeFinal. */
+ boolean value();
+}
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RuntimePure.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RuntimePure.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RuntimePure.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/RuntimePure.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.ElementType;
+import org.vmmagic.Pragma;
+
+/**
+ * This pragma is a variant of Pure that is used to mark methods that have a
+ * special behaviour at boot image writing time and are Pure at runtime
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.METHOD})
+ at Pragma
+public @interface RuntimePure {
+ /** Enumeration of the special boot image return values */
+ public enum ReturnValue {
+ /** the return value is unavailable until runtime*/
+ Unavailable
+ }
+ /** What value should be returned */
+ ReturnValue value() default ReturnValue.Unavailable;
+}
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SaveVolatile.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SaveVolatile.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SaveVolatile.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SaveVolatile.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import org.vmmagic.Pragma;
+
+/**
+ * Methods of a class that implements this interface
+ * are treated specially by the machine code compiler:
+ * the method prologue saves all the volatile registers
+ * and the method epilogue restores all the volatile registers
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.TYPE)
+ at Pragma
+public @interface SaveVolatile { }
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SpecializedMethodInvoke.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SpecializedMethodInvoke.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SpecializedMethodInvoke.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SpecializedMethodInvoke.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.ElementType;
+import org.vmmagic.Pragma;
+
+/**
+ * This pragma indicates that a particular method is a specialized
+ * method invocation point, and could be optimized as such.
+ *
+ * All such methods must be static.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.METHOD)
+ at Pragma
+public @interface SpecializedMethodInvoke { }
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SynchronizedObject.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SynchronizedObject.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SynchronizedObject.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SynchronizedObject.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,29 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.vmmagic.Pragma;
+
+/**
+ * This interface designates an object which should always be allocated a
+ * thin lock, since it is likely to be synchronized.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.TYPE)
+ at Pragma
+public @interface SynchronizedObject {
+}
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SysCallNative.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SysCallNative.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SysCallNative.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/SysCallNative.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.ElementType;
+import org.vmmagic.Pragma;
+
+/**
+ * An annotation for static native methods to show that they should be
+ * compiled as system calls. A system call is a lightweight call to a
+ * C function that doesn't set up the JNI environment and is therefore
+ * cheaper than JNI. The first argument to the function is the address
+ * of the C function to run.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.METHOD})
+ at Pragma
+public @interface SysCallNative {
+}
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Uninterruptible.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Uninterruptible.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Uninterruptible.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Uninterruptible.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,64 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.ElementType;
+import org.vmmagic.Pragma;
+
+/**
+ * By default all Java code is interruptible, that is scheduling or garbage
+ * collection may occur at points within the code. Code can be marked as
+ * {@link Unpreemptible} or {@link Uninterruptible}, that instructs the JVM to
+ * avoid garbage collection and thread scheduling. The {@link Uninterruptible}
+ * annotation disallows any operation that may cause garbage collection or
+ * thread scheduling, for example memory allocation. The {@link Unpreemptible}
+ * annotation doesn't disallow operations that can cause garbage collection or
+ * scheduling, but instructs the JVM to avoid inserting such operations during a
+ * block of code.
+ *
+ * In the internals of a VM most code wants to be {@link Uninterruptible}.
+ * However, code involved in scheduling and locking will cause context switches,
+ * and creating exception objects may trigger garbage collection, this code is
+ * therefore {@link Unpreemptible}.
+ *
+ * Any method that is marked as uninterruptible is treated specially by the
+ * machine code compiler:
+ *
+ * (1) the normal thread switch test that would be emitted in the method
+ * prologue is omitted.
+ *
+ * (2) the stack overflow test that would be emitted in the method prologue is
+ * omitted.
+ *
+ * (3) calls to preemptible code causes warnings.
+ *
+ * (4) bytecodes that can cause interruption cause warnings.
+ *
+ * (5) uninterruptible code will be generated assuming no RuntimeExceptions are
+ * raised and without any GC maps (since by definition there can be noGC if
+ * control is not lost).
+ *
+ * This is the inverse of {@link Interruptible}.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.TYPE, ElementType.METHOD})
+ at Pragma
+public @interface Uninterruptible {
+ /**
+ * @return Explanation of why code needs to be uninterruptible
+ */
+ String value() default "";
+}
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/UninterruptibleNoWarn.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/UninterruptibleNoWarn.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/UninterruptibleNoWarn.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/UninterruptibleNoWarn.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.ElementType;
+import org.vmmagic.Pragma;
+
+/**
+ * A pragma that has the same direct effect as {@link Uninterruptible}
+ * but also suppresses checking of uninterruptibility violations for
+ * the method. This should be used with care and is only justified
+ * for code only executed when creating the boot image.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.TYPE, ElementType.METHOD})
+ at Pragma
+public @interface UninterruptibleNoWarn {
+ /**
+ * @return Explanation of why uninterruptible warnings are disabled
+ */
+ String value() default "";
+}
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Unpreemptible.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Unpreemptible.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Unpreemptible.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Unpreemptible.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,58 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.ElementType;
+import org.vmmagic.Pragma;
+
+/**
+ * By default all Java code is interruptible, that is scheduling or garbage
+ * collection may occur at points within the code. Code can be marked as
+ * {@link Unpreemptible} or {@link Uninterruptible}, that instructs the JVM to
+ * avoid garbage collection and thread scheduling. The {@link Uninterruptible}
+ * annotation disallows any operation that may cause garbage collection or
+ * thread scheduling, for example memory allocation. The {@link Unpreemptible}
+ * annotation doesn't disallow operations that can cause garbage collection or
+ * scheduling, but instructs the JVM to avoid inserting such operations during a
+ * block of code.
+ *
+ * In the internals of a VM most code wants to be {@link Uninterruptible}.
+ * However, code involved in scheduling and locking will cause context switches,
+ * and creating exception objects may trigger garbage collection, this code is
+ * therefore {@link Unpreemptible}.
+ *
+ * Any method that is marked as unpreemptible is treated specially by the
+ * machine code compiler:
+ *
+ * (1) the normal thread switch test that would be emitted in the method
+ * prologue is omitted.
+ *
+ * (2) the stack overflow test that would be emitted in the method prologue is
+ * omitted.
+ *
+ * (3) calls to preemptible code causes warnings.
+ *
+ * This is the inverse of {@link Preemptible}.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.TYPE, ElementType.METHOD})
+ at Pragma
+public @interface Unpreemptible {
+ /**
+ * @return Explanation of why code needs to be unpreemptible
+ */
+ String value() default "";
+}
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/UnpreemptibleNoWarn.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/UnpreemptibleNoWarn.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/UnpreemptibleNoWarn.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/UnpreemptibleNoWarn.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,33 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.ElementType;
+import org.vmmagic.Pragma;
+
+/**
+ * A special case of {@link Unpreemptible} where the code may call out to other
+ * interruptible routines.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.TYPE, ElementType.METHOD})
+ at Pragma
+public @interface UnpreemptibleNoWarn {
+ /**
+ * @return Explanation of why code needs to be unpreemptible
+ */
+ String value() default "";
+}
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Untraced.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Untraced.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Untraced.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/pragma/Untraced.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.pragma;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.ElementType;
+
+/**
+ * Use this annotation to mark fields that are read without the knowledge of the
+ * memory management system. This means that barriers are not triggered and
+ * the reference is also not traced by the garbage collector.
+ *
+ * As annotations are loaded at class resolution time, fields marked with this
+ * annotation must be private so that no unresolved accesses are compiled to them with
+ * barriers.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.FIELD)
+public @interface Untraced { }
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/Address.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/Address.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/Address.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/Address.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,952 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.unboxed;
+
+import org.vmmagic.Unboxed;
+import org.vmmagic.pragma.RawStorage;
+
+/**
+ * <b>Stub</b> implementation of an Address type, intended only to
+ * allow the core of MMTk to be compiled. This <b>must</b> be
+ * replaced with a concrete implementation appropriate to a specific
+ * VM.
+ *
+ * The address type is used by the runtime system and collector to
+ * denote machine addresses. We use a separate type instead of the
+ * Java int type for coding clarity, machine-portability (it can map
+ * to 32 bit and 64 bit integral types), and access to unsigned
+ * operations (Java does not have unsigned int types).
+ */
+ at Unboxed
+ at RawStorage(lengthInWords = true, length = 1)
+public final class Address {
+
+ /****************************************************************************
+ *
+ * Special values
+ */
+
+ /**
+ * Return an <code>Address</code> instance that reflects the value
+ * zero.
+ *
+ * @return An address instance that reflects the value zero.
+ */
+ public static Address zero() {
+ return null;
+ }
+
+ /**
+ * Return <code>true</code> if this instance is zero.
+ *
+ * @return <code>true</code> if this instance is zero.
+ */
+ public boolean isZero() {
+ return false;
+ }
+
+ /**
+ * Return an <code>Address</code> instance that reflects the maximum
+ * allowable <code>Address</code> value.
+ *
+ * @return An <code>Address</code> instance that reflects the
+ * maximum allowable <code>Address</code> value.
+ */
+ public static Address max() {
+ return null;
+ }
+
+ /**
+ * Return <code>true</code> if this instance is the maximum
+ * allowable <code>Address</code> value.
+ *
+ * @return <code>true</code> if this instance is the maximum
+ * allowable <code>Address</code> valu.
+ */
+ public boolean isMax() {
+ return false;
+ }
+
+ /****************************************************************************
+ *
+ * Conversions
+ */
+
+ /**
+ * Fabricate an <code>Address</code> instance from an integer, after
+ * sign extending the integer.
+ *
+ * @param address the integer from which to create an <code>Address</code>
+ * instance
+ * @return An address instance
+ */
+ public static Address fromIntSignExtend(int address) {
+ return null;
+ }
+
+ /**
+ * Fabricate an <code>Address</code> instance from an integer, after
+ * zero extending the integer.
+ *
+ * @param address the integer from which to create an <code>Address</code>
+ * instance
+ * @return An address instance
+ */
+ public static Address fromIntZeroExtend(int address) {
+ return null;
+ }
+
+ /**
+ * Fabricate an <code>Address</code> instance from an integer
+ *
+ * @param address the integer from which to create an <code>Address</code>
+ * instance
+ * @return An address instance
+ */
+ public static Address fromLong(long address) {
+ return null;
+ }
+
+ /**
+ * Fabricate an <code>ObjectReference</code> instance from an
+ * <code>Address</code> instance. It is the user's responsibility
+ * to ensure that the <code>Address</code> is suitable (i.e. it
+ * points to the object header, or satisfies any other VM-specific
+ * requirement for such a conversion).
+ *
+ * @return An <code>ObjectReference</code> instance.
+ */
+ public ObjectReference toObjectReference() {
+ return null;
+ }
+
+ /**
+ * Return an integer that reflects the value of this
+ * <code>Address</code> instance.
+ *
+ * @return An integer that reflects the value of this
+ * <code>Address</code> instance.
+ */
+ public int toInt() {
+ return 0;
+ }
+
+ /**
+ * Return an long that reflects the value of this
+ * <code>Address</code> instance.
+ *
+ * @return An long that reflects the value of this
+ * <code>Address</code> instance.
+ */
+ public long toLong() {
+ return 0;
+ }
+
+ /**
+ * Return a <code>Word</code> instance that reflects the value of
+ * this <code>Address</code> instance.
+ *
+ * @return A <code>Word</code> instance that reflects the value of
+ * this <code>Address</code> instance.
+ */
+ public Word toWord() {
+ return null;
+ }
+
+ /****************************************************************************
+ *
+ * Arithemtic operators
+ */
+
+ /**
+ * Add an integer to this <code>Address</code>, and return the sum.
+ *
+ * @param v the value to be added to this <code>Address</code>
+ * @return An <code>Address</code> instance that reflects the result
+ * of the addition.
+ */
+ public Address plus(int v) {
+ return null;
+ }
+
+ /**
+ * Add an <code>Offset</code> to this <code>Address</code>, and
+ * return the sum.
+ *
+ * @param offset the <code>Offset</code> to be added to the address
+ * @return An <code>Address</code> instance that reflects the result
+ * of the addition.
+ */
+ public Address plus(Offset offset) {
+ return null;
+ }
+
+ /**
+ * Add an <code>Extent</code> to this <code>Address</code>, and
+ * return the sum.
+ *
+ * @param extent the <code>Extent</code> to be added to this
+ * <code>Address</code>
+ * @return An <code>Address</code> instance that reflects the result
+ * of the addition.
+ */
+ public Address plus(Extent extent) {
+ return null;
+ }
+
+ /**
+ * Subtract an integer from this <code>Address</code>, and return
+ * the result.
+ *
+ * @param v the integer to be subtracted from this
+ * <code>Address</code>.
+ * @return An <code>Address</code> instance that reflects the result
+ * of the subtraction.
+ */
+ public Address minus(int v) {
+ return null;
+ }
+
+ /**
+ * Subtract an <code>Offset</code> from this <code>Address</code>, and
+ * return the result.
+ *
+ * @param offset the <code>Offset</code> to be subtracted from this
+ * <code>Address</code>.
+ * @return An <code>Address</code> instance that reflects the result
+ * of the subtraction.
+ */
+ public Address minus(Offset offset) {
+ return null;
+ }
+
+ /**
+ * Subtract an <code>Extent</code> from this <code>Address</code>, and
+ * return the result.
+ *
+ * @param extent the <code>Extent</code> to be subtracted from this
+ * <code>Address</code>.
+ * @return An <code>Address</code> instance that reflects the result
+ * of the subtraction.
+ */
+ public Address minus(Extent extent) {
+ return null;
+ }
+
+ /**
+ * Compute the difference between two <code>Address</code>es and
+ * return the result.
+ *
+ * @param addr2 the <code>Address</code> to be subtracted from this
+ * <code>Address</code>.
+ * @return An <code>Offset</code> instance that reflects the result
+ * of the subtraction.
+ */
+ public Offset diff(Address addr2) {
+ return null;
+ }
+
+ /****************************************************************************
+ *
+ * Boolean operators
+ */
+
+ /**
+ * Return true if this <code>Address</code> instance is <i>less
+ * than</i> <code>addr2</code>.
+ *
+ * @param addr2 the <code>Address</code> to be compared to this
+ * <code>Address</code>.
+ * @return true if this <code>Address</code> instance is <i>less
+ * than</i> <code>addr2</code>.
+ */
+ public boolean LT(Address addr2) {
+ return false;
+ }
+
+ /**
+ * Return true if this <code>Address</code> instance is <i>less
+ * than or equal to</i> <code>addr2</code>.
+ *
+ * @param addr2 the <code>Address</code> to be compared to this
+ * <code>Address</code>.
+ * @return true if this <code>Address</code> instance is <i>less
+ * than or equal to</i> <code>addr2</code>.
+ */
+ public boolean LE(Address addr2) {
+ return false;
+ }
+
+ /**
+ * Return true if this <code>Address</code> instance is <i>greater
+ * than</i> <code>addr2</code>.
+ *
+ * @param addr2 the <code>Address</code> to be compared to this
+ * <code>Address</code>.
+ * @return true if this <code>Address</code> instance is <i>greater
+ * than</i> <code>addr2</code>.
+ */
+ public boolean GT(Address addr2) {
+ return false;
+ }
+
+ /**
+ * Return true if this <code>Address</code> instance is <i>greater
+ * than or equal to</i> <code>addr2</code>.
+ *
+ * @param addr2 the <code>Address</code> to be compared to this
+ * <code>Address</code>.
+ * @return true if this <code>Address</code> instance is <i>greater
+ * than or equal to</i> <code>addr2</code>.
+ */
+ public boolean GE(Address addr2) {
+ return false;
+ }
+
+ /**
+ * Return true if this <code>Address</code> instance is <i>equal
+ * to</i> <code>addr2</code>.
+ *
+ * @param addr2 the <code>Address</code> to be compared to this
+ * <code>Address</code>.
+ * @return true if this <code>Address</code> instance is <i>equal
+ * to</i> <code>addr2</code>.
+ */
+ public boolean EQ(Address addr2) {
+ return false;
+ }
+
+ /**
+ * Return true if this <code>Address</code> instance is <i>not equal
+ * to</i> <code>addr2</code>.
+ *
+ * @param addr2 the <code>Address</code> to be compared to this
+ * <code>Address</code>.
+ * @return true if this <code>Address</code> instance is <i>not
+ * equal to</i> <code>addr2</code>.
+ */
+ public boolean NE(Address addr2) {
+ return false;
+ }
+
+ /****************************************************************************
+ *
+ * Software prefetch operators etc
+ */
+
+ /**
+ * Prefetch a cache-line, architecture-independent
+ */
+ public void prefetch() {
+ }
+
+ /****************************************************************************
+ *
+ * Memory access operators
+ */
+
+ /**
+ * Loads a reference from the memory location pointed to by the
+ * current instance.
+ *
+ * @return the read value
+ */
+ public ObjectReference loadObjectReference() {
+ return null;
+ }
+
+ /**
+ * Loads a reference from the memory location pointed to by the
+ * current instance.
+ *
+ * @param offset the offset to the value.
+ * @return the read value
+ */
+ public ObjectReference loadObjectReference(Offset offset) {
+ return null;
+ }
+
+ /**
+ * Loads a byte from the memory location pointed to by the
+ * current instance.
+ *
+ * @return the read value
+ */
+ public byte loadByte() {
+ return (byte) 0;
+ }
+
+ /**
+ * Loads a byte from the memory location pointed to by the
+ * current instance.
+ *
+ * @param offset the offset to the value.
+ * @return the read value
+ */
+ public byte loadByte(Offset offset) {
+ return (byte) 0;
+ }
+
+ /**
+ * Loads a char from the memory location pointed to by the
+ * current instance.
+ *
+ * @return the read value
+ */
+ public char loadChar() {
+ return (char) 0;
+ }
+
+ /**
+ * Loads a char from the memory location pointed to by the
+ * current instance.
+ *
+ * @param offset the offset to the value.
+ * @return the read value
+ */
+ public char loadChar(Offset offset) {
+ return (char) 0;
+ }
+
+ /**
+ * Loads a short from the memory location pointed to by the
+ * current instance.
+ *
+ * @return the read value
+ */
+ public short loadShort() {
+ return (short) 0;
+ }
+
+ /**
+ * Loads a short from the memory location pointed to by the
+ * current instance.
+ *
+ * @param offset the offset to the value.
+ * @return the read value
+ */
+ public short loadShort(Offset offset) {
+ return (short) 0;
+ }
+
+ /**
+ * Loads a float from the memory location pointed to by the
+ * current instance.
+ *
+ * @return the read value
+ */
+ public float loadFloat() {
+ return (float) 0;
+ }
+
+ /**
+ * Loads a float from the memory location pointed to by the
+ * current instance.
+ *
+ * @param offset the offset to the value.
+ * @return the read value
+ */
+ public float loadFloat(Offset offset) {
+ return (float) 0;
+ }
+
+ /**
+ * Loads an int from the memory location pointed to by the
+ * current instance.
+ *
+ * @return the read value
+ */
+ public int loadInt() {
+ return 0;
+ }
+
+ /**
+ * Loads an int from the memory location pointed to by the
+ * current instance.
+ *
+ * @param offset the offset to the value.
+ * @return the read value
+ */
+ public int loadInt(Offset offset) {
+ return 0;
+ }
+
+
+ /**
+ * Loads a long from the memory location pointed to by the
+ * current instance.
+ *
+ * @return the read value
+ */
+ public long loadLong() {
+ return 0L;
+ }
+
+ /**
+ * Loads a long from the memory location pointed to by the
+ * current instance.
+ *
+ * @param offset the offset to the value.
+ * @return the read value
+ */
+ public long loadLong(Offset offset) {
+ return 0L;
+ }
+
+ /**
+ * Loads a double from the memory location pointed to by the
+ * current instance.
+ *
+ * @return the read value
+ */
+ public double loadDouble() {
+ return 0;
+ }
+
+ /**
+ * Loads a double from the memory location pointed to by the
+ * current instance.
+ *
+ * @param offset the offset to the value.
+ * @return the read value
+ */
+ public double loadDouble(Offset offset) {
+ return 0;
+ }
+
+
+ /**
+ * Loads an address value from the memory location pointed to by the
+ * current instance.
+ *
+ * @return the read address value.
+ */
+ public Address loadAddress() {
+ return null;
+ }
+
+ /**
+ * Loads an address value from the memory location pointed to by the
+ * current instance.
+ *
+ * @param offset the offset to the value.
+ * @return the read address value.
+ */
+ public Address loadAddress(Offset offset) {
+ return null;
+ }
+
+ /**
+ * Loads a word value from the memory location pointed to by the
+ * current instance.
+ *
+ * @return the read word value.
+ */
+ public Word loadWord() {
+ return null;
+ }
+
+ /**
+ * Loads a word value from the memory location pointed to by the
+ * current instance.
+ *
+ * @param offset the offset to the value.
+ * @return the read word value.
+ */
+ public Word loadWord(Offset offset) {
+ return null;
+ }
+
+ /**
+ * Stores the address value in the memory location pointed to by the
+ * current instance.
+ *
+ * @param value The address value to store.
+ */
+ public void store(ObjectReference value) {
+ }
+
+ /**
+ * Stores the object reference value in the memory location pointed
+ * to by the current instance.
+ *
+ * @param value The object reference value to store.
+ * @param offset the offset to the value.
+ */
+ public void store(ObjectReference value, Offset offset) {
+ }
+
+ /**
+ * Stores the address value in the memory location pointed to by the
+ * current instance.
+ *
+ * @param value The address value to store.
+ */
+ public void store(Address value) {
+ }
+
+ /**
+ * Stores the address value in the memory location pointed to by the
+ * current instance.
+ *
+ * @param value The address value to store.
+ * @param offset the offset to the value.
+ */
+ public void store(Address value, Offset offset) {
+ }
+
+ /**
+ * Stores the float value in the memory location pointed to by the
+ * current instance.
+ *
+ * @param value The float value to store.
+ */
+ public void store(float value) {
+ }
+
+ /**
+ * Stores the float value in the memory location pointed to by the
+ * current instance.
+ *
+ * @param value The float value to store.
+ * @param offset the offset to the value.
+ */
+ public void store(float value, Offset offset) {
+ }
+
+ /**
+ * Stores the word value in the memory location pointed to by the
+ * current instance.
+ *
+ * @param value The word value to store.
+ */
+ public void store(Word value) {
+ }
+
+ /**
+ * Stores the word value in the memory location pointed to by the
+ * current instance.
+ *
+ * @param value The word value to store.
+ * @param offset the offset to the value.
+ */
+ public void store(Word value, Offset offset) {
+ }
+
+ /**
+ * Stores the byte value in the memory location pointed to by the
+ * current instance.
+ *
+ * @param value The byte value to store.
+ */
+ public void store(byte value) {
+ }
+
+ /**
+ * Stores the byte value in the memory location pointed to by the
+ * current instance.
+ *
+ * @param value The byte value to store.
+ * @param offset the offset to the value.
+ */
+ public void store(byte value, Offset offset) {
+ }
+
+
+ /**
+ * Stores an int value in memory location pointed to by the
+ * current instance.
+ *
+ * @param value The int value to store.
+ */
+ public void store(int value) {
+ }
+
+ /**
+ * Stores an int value in memory location pointed to by the
+ * current instance.
+ *
+ * @param value The int value to store.
+ * @param offset the offset to the value.
+ */
+ public void store(int value, Offset offset) {
+ }
+
+ /**
+ * Stores a double value in memory location pointed to by the
+ * current instance.
+ *
+ * @param value The double value to store.
+ */
+ public void store(double value) {
+ }
+
+ /**
+ * Stores a double value in memory location pointed to by the
+ * current instance.
+ *
+ * @param value The double value to store.
+ * @param offset the offset to the value.
+ */
+ public void store(double value, Offset offset) {
+ }
+
+
+ /**
+ * Stores a double value in memory location pointed to by the
+ * current instance.
+ *
+ * @param value The double value to store.
+ */
+ public void store(long value) {
+ }
+
+ /**
+ * Stores a double value in memory location pointed to by the
+ * current instance.
+ *
+ * @param value The double value to store.
+ * @param offset the offset to the value.
+ */
+ public void store(long value, Offset offset) {
+ }
+
+ /**
+ * Stores a char value in the memory location pointed to by the
+ * current instance.
+ *
+ * @param value the char value to store.
+ */
+ public void store(char value) {
+ }
+
+ /**
+ * Stores a char value in the memory location pointed to by the
+ * current instance.
+ *
+ * @param value the char value to store.
+ * @param offset the offset to the value.
+ */
+ public void store(char value, Offset offset) {
+ }
+
+ /**
+ * Stores a short value in the memory location pointed to by the
+ * current instance.
+ *
+ * @param value the short value to store.
+ */
+ public void store(short value) {
+ }
+
+ /**
+ * Stores a short value in the memory location pointed to by the
+ * current instance.
+ *
+ * @param value the short value to store.
+ * @param offset the offset to the value.
+ */
+ public void store(short value, Offset offset) {
+ }
+
+ /****************************************************************************
+ *
+ * Atomic memory access operators (compare and swap)
+ */
+
+ /**
+ * Prepare for an atomic store operation. This must be associated with
+ * a related call to attempt.
+ *
+ * @return the old value to be passed to an attempt call.
+ */
+ public Word prepareWord() {
+ return null;
+ }
+
+ /**
+ * Prepare for an atomic store operation. This must be associated with
+ * a related call to attempt.
+ *
+ * @param offset the offset to the value.
+ * @return the old value to be passed to an attempt call.
+ */
+ public Word prepareWord(Offset offset) {
+ return null;
+ }
+
+ /**
+ * Prepare for an atomic store operation. This must be associated with
+ * a related call to attempt.
+ *
+ * @return the old value to be passed to an attempt call.
+ */
+ public ObjectReference prepareObjectReference() {
+ return null;
+ }
+
+ /**
+ * Prepare for an atomic store operation. This must be associated with
+ * a related call to attempt.
+ *
+ * @param offset the offset to the value.
+ * @return the old value to be passed to an attempt call.
+ */
+ public ObjectReference prepareObjectReference(Offset offset) {
+ return null;
+ }
+
+ /**
+ * Prepare for an atomic store operation. This must be associated with
+ * a related call to attempt.
+ *
+ * @return the old value to be passed to an attempt call.
+ */
+ public Address prepareAddress() {
+ return null;
+ }
+
+ /**
+ * Prepare for an atomic store operation. This must be associated with
+ * a related call to attempt.
+ *
+ * @param offset the offset to the value.
+ * @return the old value to be passed to an attempt call.
+ */
+ public Address prepareAddress(Offset offset) {
+ return null;
+ }
+
+ /**
+ * Prepare for an atomic store operation. This must be associated with
+ * a related call to attempt.
+ *
+ * @return the old value to be passed to an attempt call.
+ */
+ public int prepareInt() {
+ return 0;
+ }
+
+ /**
+ * Prepare for an atomic store operation. This must be associated with
+ * a related call to attempt.
+ *
+ * @param offset the offset to the value.
+ * @return the old value to be passed to an attempt call.
+ */
+ public int prepareInt(Offset offset) {
+ return 0;
+ }
+
+ /**
+ * Attempt an atomic store operation. This must be associated with a
+ * related call to prepare.
+ *
+ * @param old the old value.
+ * @param value the new value.
+ * @return true if the attempt was successful.
+ */
+ public boolean attempt(int old, int value) {
+ return false;
+ }
+
+ /**
+ * Attempt an atomic store operation. This must be associated with a
+ * related call to prepare.
+ *
+ * @param old the old value.
+ * @param value the new value.
+ * @param offset the offset to the value.
+ * @return true if the attempt was successful.
+ */
+ public boolean attempt(int old, int value, Offset offset) {
+ return false;
+ }
+
+ /**
+ * Attempt an atomic store operation. This must be associated with a
+ * related call to prepare.
+ *
+ * @param old the old value.
+ * @param value the new value.
+ * @return true if the attempt was successful.
+ */
+ public boolean attempt(Word old, Word value) {
+ return false;
+ }
+
+ /**
+ * Attempt an atomic store operation. This must be associated with a
+ * related call to prepare.
+ *
+ * @param old the old value.
+ * @param value the new value.
+ * @param offset the offset to the value.
+ * @return true if the attempt was successful.
+ */
+ public boolean attempt(Word old, Word value, Offset offset) {
+ return false;
+ }
+
+ /**
+ * Attempt an atomic store operation. This must be associated with a
+ * related call to prepare.
+ *
+ * @param old the old value.
+ * @param value the new value.
+ * @return true if the attempt was successful.
+ */
+ public boolean attempt(ObjectReference old, ObjectReference value) {
+ return false;
+ }
+
+ /**
+ * Attempt an atomic store operation. This must be associated with a
+ * related call to prepare.
+ *
+ * @param old the old value.
+ * @param value the new value.
+ * @param offset the offset to the value.
+ * @return true if the attempt was successful.
+ */
+ public boolean attempt(ObjectReference old, ObjectReference value,
+ Offset offset) {
+ return false;
+ }
+
+ /**
+ * Attempt an atomic store operation. This must be associated with a
+ * related call to prepare.
+ *
+ * @param old the old value.
+ * @param value the new value.
+ * @return true if the attempt was successful.
+ */
+ public boolean attempt(Address old, Address value) {
+ return false;
+ }
+
+ /**
+ * Attempt an atomic store operation. This must be associated with a
+ * related call to prepare.
+ *
+ * @param old the old value.
+ * @param value the new value.
+ * @param offset the offset to the value.
+ * @return true if the attempt was successful.
+ */
+ public boolean attempt(Address old, Address value, Offset offset) {
+ return false;
+ }
+
+}
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/AddressArray.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/AddressArray.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/AddressArray.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/AddressArray.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.unboxed;
+
+public final class AddressArray {
+
+ private final Address[] data;
+
+ private AddressArray(int size) {
+ data = new Address[size];
+ Address zero = Address.zero();
+ for(int i=0; i<size;i++) {
+ data[i] = zero;
+ }
+ }
+
+ public static AddressArray create(int size) {
+ return new AddressArray(size);
+ }
+
+ public Address get(int index) {
+ return data[index];
+ }
+
+ public void set(int index, Address v) {
+ data[index] = v;
+ }
+
+ public int length() {
+ return data.length;
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/Extent.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/Extent.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/Extent.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/Extent.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,93 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.unboxed;
+
+import org.vmmagic.Unboxed;
+import org.vmmagic.pragma.RawStorage;
+
+ at Unboxed
+ at RawStorage(lengthInWords = true, length = 1)
+public final class Extent {
+ public static Extent fromIntSignExtend(int address) {
+ return null;
+ }
+
+ public static Extent fromIntZeroExtend(int address) {
+ return null;
+ }
+
+ public static Extent zero() {
+ return null;
+ }
+
+ public static Extent one() {
+ return null;
+ }
+
+ public static Extent max() {
+ return null;
+ }
+
+ public int toInt() {
+ return 0;
+ }
+
+ public long toLong() {
+ return 0L;
+ }
+
+ public Word toWord() {
+ return null;
+ }
+
+ public Extent plus(int byteSize) {
+ return null;
+ }
+
+ public Extent plus(Extent byteSize) {
+ return null;
+ }
+
+ public Extent minus(int byteSize) {
+ return null;
+ }
+
+ public Extent minus(Extent byteSize) {
+ return null;
+ }
+
+ public boolean LT(Extent extent2) {
+ return false;
+ }
+
+ public boolean LE(Extent extent2) {
+ return false;
+ }
+
+ public boolean GT(Extent extent2) {
+ return false;
+ }
+
+ public boolean GE(Extent extent2) {
+ return false;
+ }
+
+ public boolean EQ(Extent extent2) {
+ return false;
+ }
+
+ public boolean NE(Extent extent2) {
+ return false;
+ }
+}
+
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/ExtentArray.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/ExtentArray.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/ExtentArray.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/ExtentArray.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.unboxed;
+
+public final class ExtentArray {
+
+ private final Extent[] data;
+
+ private ExtentArray(int size) {
+ data = new Extent[size];
+ Extent zero = Extent.zero();
+ for(int i=0; i<size;i++) {
+ data[i] = zero;
+ }
+ }
+
+ public static ExtentArray create(int size) {
+ return new ExtentArray(size);
+ }
+
+ public Extent get(int index) {
+ return data[index];
+ }
+
+ public void set(int index, Extent v) {
+ data[index] = v;
+ }
+
+ public int length() {
+ return data.length;
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/ObjectReference.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/ObjectReference.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/ObjectReference.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/ObjectReference.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.unboxed;
+
+import org.vmmagic.Unboxed;
+
+/**
+ * The object reference type is used by the runtime system and collector to
+ * represent a type that holds a reference to a single object.
+ * We use a separate type instead of the Java Object type for coding clarity,
+ * to make a clear distinction between objects the VM is written in, and
+ * objects that the VM is managing. No operations that can not be completed in
+ * pure Java should be allowed on Object.
+ */
+ at Unboxed
+public final class ObjectReference {
+
+ /**
+ * The object field.
+ */
+ @SuppressWarnings("unused")
+ private Object data;
+
+ /**
+ * Convert from an object to a reference.
+ * @param obj The object
+ * @return The corresponding reference
+ */
+ public static ObjectReference fromObject(Object obj) {
+ return null;
+ }
+
+ /**
+ * Return a null reference
+ */
+ public static ObjectReference nullReference() {
+ return null;
+ }
+
+ /**
+ * Convert from an reference to an object. Note: this is a JikesRVM
+ * specific extension to vmmagic.
+ * @return The object
+ */
+ public Object toObject() {
+ return null;
+ }
+
+ /**
+ * Get a heap address for the object.
+ */
+ public Address toAddress() {
+ return null;
+ }
+
+ /**
+ * Is this a null reference?
+ */
+ public boolean isNull() {
+ return false;
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/ObjectReferenceArray.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/ObjectReferenceArray.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/ObjectReferenceArray.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/ObjectReferenceArray.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.unboxed;
+
+public final class ObjectReferenceArray {
+
+ private final ObjectReference[] data;
+
+ private ObjectReferenceArray(int size) {
+ data = new ObjectReference[size];
+ ObjectReference nullRef = ObjectReference.nullReference();
+ for(int i=0; i<size;i++) {
+ data[i] = nullRef;
+ }
+ }
+
+ public static ObjectReferenceArray create(int size) {
+ return new ObjectReferenceArray(size);
+ }
+
+ public ObjectReference get(int index) {
+ return data[index];
+ }
+
+ public void set(int index, ObjectReference v) {
+ data[index] = v;
+ }
+
+ public int length() {
+ return data.length;
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/Offset.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/Offset.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/Offset.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/Offset.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.unboxed;
+
+import org.vmmagic.Unboxed;
+import org.vmmagic.pragma.RawStorage;
+
+/**
+ * To be commented
+ */
+ at Unboxed
+ at RawStorage(lengthInWords = true, length = 1)
+public final class Offset {
+
+ public static Offset fromIntSignExtend(int address) {
+ return null;
+ }
+
+ public static Offset fromIntZeroExtend(int address) {
+ return null;
+ }
+
+ public static Offset zero() {
+ return null;
+ }
+
+ public static Offset max() {
+ return null;
+ }
+
+ public int toInt() {
+ return 0;
+ }
+
+ public long toLong() {
+ return 0L;
+ }
+
+ public Word toWord() {
+ return null;
+ }
+
+ public Offset plus(int byteSize) {
+ return null;
+ }
+
+ public Offset minus(int byteSize) {
+ return null;
+ }
+
+ public Offset minus(Offset off2) {
+ return null;
+ }
+
+ public boolean EQ(Offset off2) {
+ return false;
+ }
+
+ public boolean NE(Offset off2) {
+ return false;
+ }
+
+ public boolean sLT(Offset off2) {
+ return false;
+ }
+
+ public boolean sLE(Offset off2) {
+ return false;
+ }
+
+ public boolean sGT(Offset off2) {
+ return false;
+ }
+
+ public boolean sGE(Offset off2) {
+ return false;
+ }
+
+ public boolean isZero() {
+ return false;
+ }
+
+ public boolean isMax() {
+ return false;
+ }
+}
+
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/OffsetArray.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/OffsetArray.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/OffsetArray.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/OffsetArray.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.unboxed;
+
+public final class OffsetArray {
+
+ private final Offset[] data;
+
+ private OffsetArray(int size) {
+ data = new Offset[size];
+ Offset zero = Offset.zero();
+ for(int i=0; i<size;i++) {
+ data[i] = zero;
+ }
+ }
+
+ public static OffsetArray create(int size) {
+ return new OffsetArray(size);
+ }
+
+ public Offset get(int index) {
+ return data[index];
+ }
+
+ public void set(int index, Offset v) {
+ data[index] = v;
+ }
+
+ public int length() {
+ return data.length;
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/Word.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/Word.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/Word.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/Word.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,319 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.unboxed;
+
+import org.vmmagic.Unboxed;
+import org.vmmagic.pragma.RawStorage;
+
+/**
+ * (Mistakes in) comments by Robin Garner
+ * @see Address
+ */
+ at Unboxed
+ at RawStorage(lengthInWords = true, length = 1)
+public final class Word {
+
+ /**
+ * Convert an into to a word. On 64-bit machines, sign-extend the
+ * high order bit.
+ *
+ * @param val
+ * @return A word instance whose value is val, sign-extended on 64 bit machines
+ */
+ public static Word fromIntSignExtend(int val) {
+ return null;
+ }
+
+ /**
+ * Convert an int to a word. On 64-bit machines, zero-extend the
+ * high order bit.
+ *
+ * @param val
+ * @return A word instance whose value is val, zero-extended on 64 bit machines
+ */
+ public static Word fromIntZeroExtend(int val) {
+ return null;
+ }
+
+ /**
+ * Convert a long to a word. On 64-bit this is a no-op.
+ * TODO document behaviour on 32-bit. Truncate ?
+ *
+ * @param val
+ * @return A word instance whose value is val on 32 bit machine this truncates the upper 32 bits.
+ */
+ public static Word fromLong(long val) {
+ return null;
+ }
+
+ /**
+ * The Word constant 0.
+ * Equivalent to Word.fromIntSignExtend(0), but more readable.
+ *
+ * @return the Word constant 0.
+ */
+ public static Word zero() {
+ return null;
+ }
+
+ /**
+ * The Word constant 1.
+ * Equivalent to Word.fromIntSignExtend(1), but more readable.
+ *
+ * @return the Word constant 1.
+ */
+ public static Word one() {
+ return null;
+ }
+
+ /**
+ * The maximum representable Word value. Words are unsigned, so this is
+ * a word full of 1s, 32/64-bit safe.
+ *
+ * @return the maximum representable Word value
+ */
+ public static Word max() {
+ return null;
+ }
+
+ /**
+ * Type-cast to an int, truncating on 64-bit platforms.
+ *
+ * @return an int, with the same value as the word on 32 bit platforms; truncates on 64 bit platforms.
+ */
+ public int toInt() {
+ return 0;
+ }
+
+ /**
+ * Type-cast to a long, zero-extending on a 32-bit platform.
+ * @return a long, with the same value as the word (zero extends on 32 bit platforms).
+ */
+ public long toLong() {
+ return 0L;
+ }
+
+ /** Type-cast to an address. */
+ public Address toAddress() {
+ return null;
+ }
+
+ /** Type-cast to an offset */
+ public Offset toOffset() {
+ return null;
+ }
+
+ /** Type-cast to an extent */
+ public Extent toExtent() {
+ return null;
+ }
+
+ /**
+ * Add two words
+ *
+ * @param w2
+ * @return The word whose value is this+w2
+ */
+ public Word plus(Word w2) {
+ return null;
+ }
+
+ /**
+ * Add an offset to a word
+ * @param w2
+ * @return The word whose value is this+w2
+ */
+ public Word plus(Offset w2) {
+ return null;
+ }
+
+ /**
+ * Add an extent to a word
+ * @param w2
+ * @return The word whose value is this+w2
+ */
+ public Word plus(Extent w2) {
+ return null;
+ }
+
+ /**
+ * Subtract two words
+ * @param w2
+ * @return The word whose value is this-w2
+ */
+ public Word minus(Word w2) {
+ return null;
+ }
+
+ /**
+ * Subtract an offset from a word
+ * @param w2
+ * @return The word whose value is this-w2
+ */
+ public Word minus(Offset w2) {
+ return null;
+ }
+
+ /**
+ * Subtract an extent from a word.
+ * @param w2
+ * @return The word whose value is this-w2
+ */
+ public Word minus(Extent w2) {
+ return null;
+ }
+
+ /**
+ * Test for zero. Equivalent to .EQ(Word.zero())
+ * @return return true if this is equal to Word.zero(), false otherwise
+ */
+ public boolean isZero() {
+ return false;
+ }
+
+ /**
+ * Test for zero. Equivalent to .EQ(Word.max())
+ * @return true if this is equal to Word.max(), false otherwise
+ */
+ public boolean isMax() {
+ return false;
+ }
+
+ /**
+ * Less-than comparison
+ * @param addr2
+ * @return true if this <code>Word</code> instance is <i>less than</i> <code>addr2</code>
+ */
+ public boolean LT(Word addr2) {
+ return false;
+ }
+
+ /**
+ * Less-than or equal comparison
+ * @param w2
+ * @return true if this <code>Word</code> instance is <i>less than or equal to</i> <code>w2</code>
+ */
+ public boolean LE(Word w2) {
+ return false;
+ }
+
+ /**
+ * Greater-than comparison
+ * @param w2
+ * @return true if this <code>Word</code> instance is <i>greater than</i> <code>w2</code>
+ */
+ public boolean GT(Word w2) {
+ return false;
+ }
+
+ /**
+ * Greater-than or equal comparison
+ * @param w2
+ * @return true if this <code>Word</code> instance is <i>greater than or equal to</i> <code>w2</code>
+ */
+ public boolean GE(Word w2) {
+ return false;
+ }
+
+ /**
+ * Equality comparison
+ * @param w2
+ * @return true if this <code>Word</code> instance is <i>equal to</i> <code>w2</code>
+ */
+ public boolean EQ(Word w2) {
+ return false;
+ }
+
+ /**
+ * Not-equal comparison
+ * @param w2
+ * @return true if this <code>Word</code> instance is <i>not equal to</i> <code>w2</code>
+ */
+ public boolean NE(Word w2) {
+ return false;
+ }
+
+ /**
+ * Bit-wise and of two words.
+ * @param w2
+ * @return The word whose value is the bitwise and of this and w2
+ */
+ public Word and(Word w2) {
+ return null;
+ }
+
+ /**
+ * Bit-wise or of two words.
+ * @param w2
+ * @return The word whose value is the bitwise not of this and w2
+ */
+ public Word or(Word w2) {
+ return null;
+ }
+
+ /**
+ * Bit-wise complement of a word.
+ * @return the bitwise complement of this
+ */
+ public Word not() {
+ return null;
+ }
+
+ /**
+ * Bit-wise exclusive or of two words.
+ * @param w2
+ * @return The word whose value is the bitwise xor of this and w2
+ */
+ public Word xor(Word w2) {
+ return null;
+ }
+
+ /**
+ * Left-shift a word. Shifts of a size greater than the Word are undefined and
+ * have an architecture and compiler specific behaviour. On Intel the shift
+ * amount ignores the most significant bits, for example for a 32bit Word 1
+ * << 32 == 1, the result will be 0 on PowerPC. Shifts may or may not be
+ * combined by the compiler, this yields differing behaviour, for example for a
+ * 32bit Word 1 <<32 may or may not equal 1 << 16 << 16.
+ *
+ * @param amt the amount to shift by
+ * @return new Word shifted by the given amount
+ */
+ public Word lsh(int amt) {
+ return null;
+ }
+
+ /**
+ * Logical right-shift a word. Shifts of a size greater than the Word are undefined and
+ * have an architecture and compiler specific behaviour see also {@link #lsh(int)}.
+ *
+ * @param amt the amount to shift by
+ * @return new Word shifted by the given amount
+ */
+ public Word rshl(int amt) {
+ return null;
+ }
+
+ /**
+ * Arithmetic right-shift a word. Shifts of a size greater than the Word are undefined and
+ * have an architecture and compiler specific behaviour see also {@link #lsh(int)}.
+ * Arithmetic right-shift a word. Equivalent to the integer <code>>></code> operator
+ *
+ * @param amt the amount to shift by
+ * @return new Word shifted by the given amount
+ */
+ public Word rsha(int amt) {
+ return null;
+ }
+}
+
Added: vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/WordArray.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/WordArray.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/WordArray.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmmagic/unboxed/WordArray.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmmagic.unboxed;
+
+public final class WordArray {
+
+ private final Word[] data;
+
+ private WordArray(int size) {
+ data = new Word[size];
+ Word zero = Word.zero();
+ for(int i=0; i<size;i++) {
+ data[i] = zero;
+ }
+ }
+
+ public static WordArray create(int size) {
+ return new WordArray(size);
+ }
+
+ public Word get(int index) {
+ return data[index];
+ }
+
+ public void set(int index, Word v) {
+ data[index] = v;
+ }
+
+ public int length() {
+ return data.length;
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/vmutil/options/AddressOption.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmutil/options/AddressOption.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmutil/options/AddressOption.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmutil/options/AddressOption.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmutil.options;
+
+import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.unboxed.Address;
+
+/**
+ * An option with a simple integer value.
+ */
+public class AddressOption extends Option {
+ // values
+ protected Address defaultValue;
+ protected Address value;
+
+ /**
+ * Create a new int option.
+ *
+ * @param set The option set this option belongs to.
+ * @param name The space separated name for the option.
+ * @param desc The purpose of the option
+ * @param defaultValue The default value of the option.
+ */
+ protected AddressOption(OptionSet set, String name, String desc, Address defaultValue) {
+ super(set, ADDRESS_OPTION, name, desc);
+ this.value = this.defaultValue = defaultValue;
+ }
+
+ /**
+ * Read the current value of the option.
+ *
+ * @return The option value.
+ */
+ @Uninterruptible
+ public Address getValue() {
+ return this.value;
+ }
+
+ /**
+ * Read the default value of the option.
+ *
+ * @return The default value.
+ */
+ @Uninterruptible
+ public Address getDefaultValue() {
+ return this.defaultValue;
+ }
+
+ /**
+ * Update the value of the option, echoing the change if the echoOptions
+ * option is set. This method also calls the validate method to allow
+ * subclasses to perform any required validation.
+ *
+ * @param value The new value for the option.
+ */
+ public void setValue(int value) {
+ this.value = Address.fromIntZeroExtend(value);
+ validate();
+ set.logChange(this);
+ }
+
+ /**
+ * Modify the default value of the option.
+ *
+ * @param value The new default value for the option.
+ */
+ public void setDefaultValue(Address value) {
+ this.value = this.defaultValue = value;
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/vmutil/options/BooleanOption.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmutil/options/BooleanOption.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmutil/options/BooleanOption.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmutil/options/BooleanOption.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,79 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmutil.options;
+
+import org.vmmagic.pragma.Uninterruptible;
+
+/**
+ * Base class for boolean options.
+ */
+public class BooleanOption extends Option {
+ // values
+ protected boolean defaultValue;
+ protected boolean value;
+
+ /**
+ * Create a new boolean option.
+ *
+ * @param set The option set this option belongs to.
+ * @param name The space separated name for the option.
+ * @param desc The purpose of the option
+ * @param defaultValue The default value of the option.
+ */
+ protected BooleanOption(OptionSet set, String name, String desc, boolean defaultValue) {
+ super(set, BOOLEAN_OPTION, name, desc);
+ this.value = this.defaultValue = defaultValue;
+ }
+
+ /**
+ * Read the current value of the option.
+ *
+ * @return The option value.
+ */
+ @Uninterruptible
+ public boolean getValue() {
+ return this.value;
+ }
+
+ /**
+ * Read the default value of the option.
+ *
+ * @return The default value.
+ */
+ @Uninterruptible
+ public boolean getDefaultValue() {
+ return this.defaultValue;
+ }
+
+ /**
+ * Update the value of the option, echoing the change if the echoOptions
+ * option is set. This method also calls the validate method to allow
+ * subclasses to perform any required validation.
+ *
+ * @param value The new value for the option.
+ */
+ public void setValue(boolean value) {
+ this.value = value;
+ validate();
+ set.logChange(this);
+ }
+
+ /**
+ * Modify the default value of the option.
+ *
+ * @param value The new default value for the option.
+ */
+ public void setDefaultValue(boolean value) {
+ this.value = this.defaultValue = value;
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/vmutil/options/EnumOption.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmutil/options/EnumOption.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmutil/options/EnumOption.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmutil/options/EnumOption.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmutil.options;
+
+import org.vmmagic.pragma.Uninterruptible;
+
+/**
+ * An option that is a selection of several strings. The mapping
+ * between strings and integers is determined using indexes into
+ * a string array.
+ *
+ * Enumerations are case sensitive.
+ */
+public class EnumOption extends Option {
+ // values
+ protected int defaultValue;
+ protected int value;
+ protected String[] values;
+
+ /**
+ * Create a new enumeration option.
+ *
+ * @param set The option set this option belongs to.
+ * @param name The space separated name for the option.
+ * @param description The purpose of the option.
+ * @param values A mapping of int to string for the enum.
+ * @param defaultValue The default value of the option.
+ */
+ protected EnumOption(OptionSet set, String name, String description, String[] values, String defaultValue) {
+ super(set, ENUM_OPTION, name, description);
+ this.values = values;
+ this.value = this.defaultValue = findValue(defaultValue);
+ }
+
+ /**
+ * Search for a string in the enumeration.
+ *
+ * @return The index of the passed string.
+ */
+ private int findValue(String string) {
+ for (int i = 0; i < values.length; i++) {
+ if (values[i].equals(string)) {
+ return i;
+ }
+ }
+ fail("Invalid Enumeration Value");
+ return -1;
+ }
+
+ /**
+ * Read the current value of the option.
+ *
+ * @return The option value.
+ */
+ @Uninterruptible
+ public int getValue() {
+ return this.value;
+ }
+
+ /**
+ * Read the string for the current value of the option.
+ *
+ * @return The option value.
+ */
+ @Uninterruptible
+ public String getValueString() {
+ return this.values[this.value];
+ }
+
+ /**
+ * Read the default value of the option.
+ *
+ * @return The default value.
+ */
+ @Uninterruptible
+ public int getDefaultValue() {
+ return this.defaultValue;
+ }
+
+ /**
+ * Read the string for the default value of the option.
+ *
+ * @return The default value.
+ */
+ @Uninterruptible
+ public String getDefaultValueString() {
+ return this.values[this.defaultValue];
+ }
+
+ /**
+ * Update the value of the option, echoing the change if the echoOptions
+ * option is set. This method also calls the validate method to allow
+ * subclasses to perform any required validation.
+ *
+ * @param value The new value for the option.
+ */
+ public void setValue(int value) {
+ this.value = value;
+ validate();
+ set.logChange(this);
+ }
+
+ /**
+ * Look up the value for a string and update the value of the option
+ * accordingly, echoing the change if the echoOptions option is set.
+ * This method also calls the validate method to allow subclasses to
+ * perform any required validation.
+ *
+ * @param value The new value for the option.
+ */
+ public void setValue(String value) {
+ setValue(findValue(value));
+ }
+
+ /**
+ * Modify the default value of the option.
+ *
+ * @param value The new default value for the option.
+ */
+ public void setDefaultValue(String value) {
+ this.value = this.defaultValue = findValue(value);
+ }
+
+ /**
+ * Return the array of allowed enumeration values.
+ *
+ * @return The values array.
+ */
+ public String[] getValues() {
+ return this.values;
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/vmutil/options/FloatOption.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmutil/options/FloatOption.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmutil/options/FloatOption.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmutil/options/FloatOption.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,79 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmutil.options;
+
+import org.vmmagic.pragma.Uninterruptible;
+
+/**
+ * An option that has a simple single precision floating point value.
+ */
+public class FloatOption extends Option {
+ // values
+ protected float defaultValue;
+ protected float value;
+
+ /**
+ * Create a new float option.
+ *
+ * @param set The option set this option belongs to.
+ * @param name The space separated name for the option.
+ * @param desc The purpose of the option
+ * @param defaultValue The default value of the option.
+ */
+ protected FloatOption(OptionSet set, String name, String desc, float defaultValue) {
+ super(set, FLOAT_OPTION, name, desc);
+ this.value = this.defaultValue = defaultValue;
+ }
+
+ /**
+ * Read the current value of the option.
+ *
+ * @return The option value.
+ */
+ @Uninterruptible
+ public float getValue() {
+ return this.value;
+ }
+
+ /**
+ * Read the default value of the option
+ *
+ * @return The default value.
+ */
+ @Uninterruptible
+ public float getDefaultValue() {
+ return this.defaultValue;
+ }
+
+ /**
+ * Update the value of the option, echoing the change if the echoOptions
+ * option is set. This method also calls the validate method to allow
+ * subclasses to perform any required validation.
+ *
+ * @param value The new value for the option.
+ */
+ public void setValue(float value) {
+ this.value = value;
+ validate();
+ set.logChange(this);
+ }
+
+ /**
+ * Modify the default value of the option.
+ *
+ * @param value The new default value for the option.
+ */
+ public void setDefaultValue(float value) {
+ this.value = this.defaultValue = value;
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/vmutil/options/IntOption.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmutil/options/IntOption.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmutil/options/IntOption.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmutil/options/IntOption.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,79 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmutil.options;
+
+import org.vmmagic.pragma.Uninterruptible;
+
+/**
+ * An option with a simple integer value.
+ */
+public class IntOption extends Option {
+ // values
+ protected int defaultValue;
+ protected int value;
+
+ /**
+ * Create a new int option.
+ *
+ * @param set The option set this option belongs to.
+ * @param name The space separated name for the option.
+ * @param desc The purpose of the option
+ * @param defaultValue The default value of the option.
+ */
+ protected IntOption(OptionSet set, String name, String desc, int defaultValue) {
+ super(set, INT_OPTION, name, desc);
+ this.value = this.defaultValue = defaultValue;
+ }
+
+ /**
+ * Read the current value of the option.
+ *
+ * @return The option value.
+ */
+ @Uninterruptible
+ public int getValue() {
+ return this.value;
+ }
+
+ /**
+ * Read the default value of the option.
+ *
+ * @return The default value.
+ */
+ @Uninterruptible
+ public int getDefaultValue() {
+ return this.defaultValue;
+ }
+
+ /**
+ * Update the value of the option, echoing the change if the echoOptions
+ * option is set. This method also calls the validate method to allow
+ * subclasses to perform any required validation.
+ *
+ * @param value The new value for the option.
+ */
+ public void setValue(int value) {
+ this.value = value;
+ validate();
+ set.logChange(this);
+ }
+
+ /**
+ * Modify the default value of the option.
+ *
+ * @param value The new default value for the option.
+ */
+ public void setDefaultValue(int value) {
+ this.value = this.defaultValue = value;
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/vmutil/options/MicrosecondsOption.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmutil/options/MicrosecondsOption.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmutil/options/MicrosecondsOption.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmutil/options/MicrosecondsOption.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmutil.options;
+
+import org.vmmagic.pragma.Uninterruptible;
+
+/**
+ * A time option that stores values at a microsecond granularity.
+ */
+public class MicrosecondsOption extends Option {
+ // values
+ protected int defaultValue;
+ protected int value;
+
+ /**
+ * Create a new microsecond option.
+ *
+ * @param set The option set this option belongs to.
+ * @param name The space separated name for the option.
+ * @param desc The purpose of the option
+ * @param defaultUs The default value of the option (usec).
+ */
+ protected MicrosecondsOption(OptionSet set, String name, String desc, int defaultUs) {
+ super(set, MICROSECONDS_OPTION, name, desc);
+ this.value = this.defaultValue = defaultUs;
+ }
+
+ /**
+ * Read the current value of the option in microseconds.
+ *
+ * @return The option value.
+ */
+ @Uninterruptible
+ public int getMicroseconds() {
+ return this.value;
+ }
+
+ /**
+ * Read the current value of the option in milliseconds.
+ *
+ * @return The option value.
+ */
+ @Uninterruptible
+ public int getMilliseconds() {
+ return this.value / 1000;
+ }
+
+ /**
+ * Read the default value of the option in microseconds.
+ *
+ * @return The default value.
+ */
+ @Uninterruptible
+ public int getDefaultMicroseconds() {
+ return this.defaultValue;
+ }
+
+ /**
+ * Read the default value of the option in milliseconds.
+ *
+ * @return The default value.
+ */
+ @Uninterruptible
+ public int getDefaultMilliseconds() {
+ return this.defaultValue / 1000;
+ }
+
+ /**
+ * Update the value of the option, echoing the change if the echoOptions
+ * option is set. An error occurs if the value is negative, and then the
+ * validate method is called to allow subclasses to perform any additional
+ * validation.
+ *
+ * @param value The new value for the option.
+ */
+ public void setMicroseconds(int value) {
+ failIf(value < 0, "Unreasonable " + this.getName() + " value");
+ this.value = value;
+ validate();
+ set.logChange(this);
+ }
+
+ /**
+ * Modify the default value of the option.
+ *
+ * @param value The new default value for the option.
+ */
+ public void setDefaultMicrosends(int value) {
+ this.value = this.defaultValue = value;
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/vmutil/options/Option.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmutil/options/Option.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmutil/options/Option.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmutil/options/Option.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmutil.options;
+
+/**
+ * The abstract base class for all options. This class also has
+ * the static interfaces to access the options system to set
+ * option values.
+ *
+ * All options within the system should have a unique name. No
+ * two options shall have a name that is the same when a case
+ * insensitive comparison between the names with spaces removed
+ * is performed. Only basic alphanumeric characters and spaces
+ * are allowed.
+ *
+ * The VM is required to provide a one way mapping function that
+ * takes the name and creates a VM style name, such as mapping
+ * "No Finalizer" to noFinalizer. The VM may not remove any letters
+ * when performing this mapping but may remove spaces and change
+ * the case of any character.
+ */
+public abstract class Option {
+ // Option types
+ public static final int BOOLEAN_OPTION = 1;
+ public static final int STRING_OPTION = 2;
+ public static final int ENUM_OPTION = 3;
+ public static final int INT_OPTION = 4;
+ public static final int PAGES_OPTION = 6;
+ public static final int MICROSECONDS_OPTION = 7;
+ public static final int FLOAT_OPTION = 8;
+ public static final int ADDRESS_OPTION = 9;
+
+ /**
+ * The possible output formats
+ */
+ public static final int READABLE = 0;
+ public static final int RAW = 1;
+ public static final int XML = 2;
+
+ // Per option values
+ private int type;
+ private String name;
+ private String description;
+ private String key;
+ private Option next;
+
+ protected OptionSet set;
+
+ /**
+ * Construct a new option. This also calls the VM to map the option's
+ * name into a unique option key and links it onto the option list.
+ *
+ * @param set The option set this option belongs to.
+ * @param type The option type as defined in this class.
+ * @param name The unique name of the option.
+ * @param description A short description of the option and purpose.
+ */
+ protected Option(OptionSet set, int type, String name, String description) {
+ this.type = type;
+ this.name = name;
+ this.description = description;
+ this.set = set;
+ this.key = set.register(this, name);
+ }
+
+ /**
+ * Return the VM determined key for an option
+ *
+ * @return The key.
+ */
+ public String getKey() {
+ return this.key;
+ }
+
+ /**
+ * Update the next pointer in the Option chain.
+ */
+ void setNext(Option o) {
+ next = o;
+ }
+
+ /**
+ * Return the next option in the linked list.
+ *
+ * @return The next option or null if this is the last option.
+ */
+ public Option getNext() {
+ return this.next;
+ }
+
+ /**
+ * Return the name for the option.
+ *
+ * @return The option name.
+ */
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * Return the option description.
+ *
+ * @return The option description.
+ */
+ public String getDescription() {
+ return this.description;
+ }
+
+ /**
+ * Return the type of the option.
+ *
+ * @return The option type.
+ */
+ public int getType() {
+ return this.type;
+ }
+
+ /**
+ * This is a validation method that can be implemented by leaf option
+ * classes to provide additional validation. This should not be implemented
+ * at other levels within the heirarchy to avoid confusion. The validate
+ * method works against the current value of the option (post-set).
+ */
+ protected void validate() {}
+
+ /**
+ * 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 message The error message associated with the failure.
+ */
+ protected void fail(String message) {
+ set.fail(this, message);
+ }
+
+ /**
+ * Fail if a specified condition is met.
+ *
+ * @param condition The condition that indicates failure.
+ * @param message The error message associated with the failure.
+ */
+ protected void failIf(boolean condition, String message) {
+ if (condition) set.fail(this, message);
+ }
+
+ /**
+ * 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 message The message associated with the warning.
+ */
+ protected void warn(String message) {
+ set.warn(this, message);
+ }
+
+ /**
+ * Warn if a specified condition is met.
+ *
+ * @param condition The condition that indicates warning.
+ * @param message The message associated with the warning.
+ */
+ protected void warnIf(boolean condition, String message) {
+ if (condition) set.warn(this, message);
+ }
+}
+
Added: vmkit/trunk/mmtk/java/src/org/vmutil/options/OptionSet.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmutil/options/OptionSet.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmutil/options/OptionSet.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmutil/options/OptionSet.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmutil.options;
+
+import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.unboxed.*;
+
+/**
+ * The abstract base class for all option sets.
+ *
+ * Concrete instantiations of this class include logic
+ *
+ * All options within the system should have a unique name. No
+ * two options shall have a name that is the same when a case
+ * insensitive comparison between the names with spaces removed
+ * is performed. Only basic alphanumeric characters and spaces
+ * are allowed.
+ *
+ * The VM is required to provide a one way mapping function that
+ * takes the name and creates a VM style name, such as mapping
+ * "No Finalizer" to noFinalizer. The VM may not remove any letters
+ * when performing this mapping but may remove spaces and change
+ * the case of any character.
+ */
+public abstract class OptionSet {
+ private Option head;
+ private Option tail;
+ private boolean loggingChanges;
+
+ /**
+ * Initialize the option set so that options can be created.
+ */
+ protected OptionSet() {
+ head = null;
+ tail = null;
+ loggingChanges = false;
+ }
+
+ /**
+ * Register the option to this set, computing its key in the process.
+ *
+ * @param o The option to register.
+ */
+ final String register(Option o, String name) {
+ if (tail == null) {
+ tail = head = o;
+ } else {
+ tail.setNext(o);
+ tail = o;
+ }
+ return computeKey(name);
+ }
+
+ /**
+ * Using the VM determined key, look up the corresponding option,
+ * or return null if an option can not be found.
+ *
+ * @param key The (unique) option key.
+ * @return The option, or null.
+ */
+ public final Option getOption(String key) {
+ Option o = getFirst();
+ while (o != null) {
+ if (o.getKey().equals(key)) {
+ return o;
+ }
+ o = o.getNext();
+ }
+ return null;
+ }
+
+ /**
+ * Return the first option. This can be used with the getNext method to
+ * iterate through the options.
+ *
+ * @return The first option, or null if no options exist.
+ */
+ public final Option getFirst() {
+ return head;
+ }
+
+ public void logChange(Option o) {
+ if (loggingChanges) {
+ logString("Option Update: ");
+ log(o);
+ }
+ }
+
+ /**
+ * Log the option value in plain text.
+ *
+ * @param o The option to log.
+ */
+ public void log(Option o) {
+ logString("Option '");
+ logString(o.getKey());
+ logString("' = ");
+ logValue(o, false);
+ logNewLine();
+ }
+
+ /**
+ * Log the option value in Xml.
+ *
+ * @param o The option to log.
+ */
+ public void logXml(Option o) {
+ logString("<option name=\"");
+ logString(o.getKey());
+ logString("\" value=\"");
+ logValue(o, true);
+ logString("\"/>");
+ logNewLine();
+ }
+
+ /**
+ * Log the option values in Xml.
+ */
+ public void logXml() {
+ logString("<options>");
+ logNewLine();
+
+ for(Option o = getFirst(); o != null; o = o.getNext()) {
+ logXml(o);
+ }
+
+ logString("</options>");
+ logNewLine();
+ }
+
+ /**
+ * Format and log an option value.
+ *
+ * @param o The option.
+ * @param forXml Is this part of xml output?
+ */
+ protected abstract void logValue(Option o, boolean forXml);
+
+ /**
+ * Log a string.
+ */
+ protected abstract void logString(String s);
+
+ /**
+ * Print a new line.
+ */
+ protected abstract void logNewLine();
+
+ /**
+ * 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 abstract String computeKey(String name);
+
+ /**
+ * 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 abstract void warn(Option o, String 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 abstract void fail(Option o, String message);
+
+ /**
+ * Convert bytes into pages, rounding up if necessary.
+ *
+ * @param bytes The number of bytes.
+ * @return The corresponding number of pages.
+ */
+ @Uninterruptible
+ protected abstract int bytesToPages(Extent bytes);
+
+ /**
+ * Convert from pages into bytes.
+ * @param pages the number of pages.
+ * @return The corresponding number of bytes.
+ */
+ @Uninterruptible
+ protected abstract Extent pagesToBytes(int pages);
+}
+
Added: vmkit/trunk/mmtk/java/src/org/vmutil/options/PagesOption.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmutil/options/PagesOption.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmutil/options/PagesOption.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmutil/options/PagesOption.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 Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmutil.options;
+
+import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.unboxed.Extent;
+
+/**
+ * A memory option that stores values as a whole number of pages.
+ */
+public class PagesOption extends Option {
+ // values
+ protected int defaultValue;
+ protected int value;
+
+ /**
+ * Create a new pages option.
+ *
+ * @param set The option set this option belongs to.
+ * @param name The space separated name for the option.
+ * @param desc The purpose of the option
+ * @param defaultPages The default value of the option.
+ */
+ protected PagesOption(OptionSet set, String name, String desc, int defaultPages) {
+ super(set, PAGES_OPTION, name, desc);
+ this.value = this.defaultValue = defaultPages;
+ }
+
+ /**
+ * Read the current value of the option in pages.
+ *
+ * @return The option value.
+ */
+ @Uninterruptible
+ public int getPages() {
+ return this.value;
+ }
+
+ /**
+ * Read the current value of the option in bytes.
+ *
+ * @return The option value.
+ */
+ @Uninterruptible
+ public Extent getBytes() {
+ return set.pagesToBytes(this.value);
+ }
+
+ /**
+ * Read the default value of the option in bytes.
+ *
+ * @return The default value.
+ */
+ @Uninterruptible
+ public Extent getDefaultBytes() {
+ return set.pagesToBytes(this.defaultValue);
+ }
+
+ /**
+ * Read the default value of the option in pages.
+ *
+ * @return The default value.
+ */
+ @Uninterruptible
+ public int getDefaultPages() {
+ return this.defaultValue;
+ }
+
+ /**
+ * Update the value of the option, echoing the change if logChanges is set.
+ * A warning is raised if the value is not a whole multiple of pages, and
+ * then the validate method is called to allow subclasses to perform any
+ * additional validation.
+ *
+ * @param value The new value for the option.
+ */
+ public void setBytes(Extent value) {
+ int pages = set.bytesToPages(value);
+ warnIf(value.NE(set.pagesToBytes(pages)), "Value rounded up to a whole number of pages");
+ setPages(pages);
+ }
+
+ /**
+ * Update the value of the option, echoing the change if logChanges is set.
+ * The validate method is called to allow subclasses to perform any additional
+ * validation.
+ *
+ * @param pages The new value for the option.
+ */
+ public void setPages(int pages) {
+ this.value = pages;
+ validate();
+ set.logChange(this);
+ }
+
+ /**
+ * Modify the default value of the option.
+ *
+ * @param value The new default value for the option.
+ */
+ public void setDefaultPages(int value) {
+ this.value = this.defaultValue = value;
+ }
+}
Added: vmkit/trunk/mmtk/java/src/org/vmutil/options/StringOption.java
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/java/src/org/vmutil/options/StringOption.java?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/java/src/org/vmutil/options/StringOption.java (added)
+++ vmkit/trunk/mmtk/java/src/org/vmutil/options/StringOption.java Thu Jul 16 06:26:34 2009
@@ -0,0 +1,79 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.vmutil.options;
+
+import org.vmmagic.pragma.Uninterruptible;
+
+/**
+ * An option that has a simple string value.
+ */
+public class StringOption extends Option {
+ // values
+ protected String defaultValue;
+ protected String value;
+
+ /**
+ * Create a new string option.
+ *
+ * @param set The option set this option belongs to.
+ * @param name The space separated name for the option.
+ * @param desc The purpose of the option
+ * @param defaultValue The default value of the option.
+ */
+ protected StringOption(OptionSet set, String name, String desc, String defaultValue) {
+ super(set, STRING_OPTION, name, desc);
+ this.value = this.defaultValue = defaultValue;
+ }
+
+ /**
+ * Read the current value of the option.
+ *
+ * @return The option value.
+ */
+ @Uninterruptible
+ public String getValue() {
+ return this.value;
+ }
+
+ /**
+ * Read the default value of the option
+ *
+ * @return The default value.
+ */
+ @Uninterruptible
+ public String getDefaultValue() {
+ return this.defaultValue;
+ }
+
+ /**
+ * Update the value of the option, echoing the change if the echoOptions
+ * option is set. This method also calls the validate method to allow
+ * subclasses to perform any required validation.
+ *
+ * @param value The new value for the option.
+ */
+ public void setValue(String value) {
+ this.value = value;
+ validate();
+ set.logChange(this);
+ }
+
+ /**
+ * Modify the default value of the option.
+ *
+ * @param value The new default value for the option.
+ */
+ public void setDefaultValue(String value) {
+ this.value = this.defaultValue = value;
+ }
+}
Added: vmkit/trunk/mmtk/magic/LowerJavaRT.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/magic/LowerJavaRT.cpp?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/magic/LowerJavaRT.cpp (added)
+++ vmkit/trunk/mmtk/magic/LowerJavaRT.cpp Thu Jul 16 06:26:34 2009
@@ -0,0 +1,73 @@
+//===-- LowerJavaRT.cpp - Remove references to RT classes and functions --===//
+//
+// The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Constants.h"
+#include "llvm/Function.h"
+#include "llvm/Instructions.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/CallSite.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Debug.h"
+
+#include "jnjvm/JnjvmModule.h"
+
+#include <iostream>
+
+using namespace llvm;
+
+namespace {
+
+ class VISIBILITY_HIDDEN LowerJavaRT : public ModulePass {
+ public:
+ static char ID;
+ LowerJavaRT() : ModulePass((intptr_t)&ID) { }
+
+ virtual bool runOnModule(Module &M);
+ private:
+ };
+ char LowerJavaRT::ID = 0;
+ static RegisterPass<LowerJavaRT> X("LowerJavaRT",
+ "Remove references to RT");
+
+bool LowerJavaRT::runOnModule(Module& M) {
+ bool Changed = true;
+
+ for (Module::iterator I = M.begin(), E = M.end(); I != E;) {
+ GlobalValue& GV = *I;
+ ++I;
+ if (!strncmp(GV.getName().c_str(), "JnJVM_java", 10) ||
+ !strncmp(GV.getName().c_str(), "java", 4)) {
+ GV.replaceAllUsesWith(M.getContext().getNullValue(GV.getType()));
+ GV.eraseFromParent();
+ }
+ }
+
+ for (Module::global_iterator I = M.global_begin(), E = M.global_end();
+ I != E;) {
+ GlobalValue& GV = *I;
+ ++I;
+ if (!strncmp(GV.getName().c_str(), "JnJVM_java", 10) ||
+ !strncmp(GV.getName().c_str(), "java", 4)) {
+ GV.replaceAllUsesWith(M.getContext().getNullValue(GV.getType()));
+ GV.eraseFromParent();
+ }
+ }
+
+
+ return Changed;
+}
+
+
+ModulePass* createLowerJavaRT() {
+ return new LowerJavaRT();
+}
+
+}
Added: vmkit/trunk/mmtk/magic/LowerMagic.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/magic/LowerMagic.cpp?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/magic/LowerMagic.cpp (added)
+++ vmkit/trunk/mmtk/magic/LowerMagic.cpp Thu Jul 16 06:26:34 2009
@@ -0,0 +1,1132 @@
+//===----- LowerConstantCalls.cpp - Changes arrayLength calls --------------===//
+//
+// JnJVM
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Constants.h"
+#include "llvm/Function.h"
+#include "llvm/Instructions.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/CallSite.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Debug.h"
+
+#include <iostream>
+
+using namespace llvm;
+
+namespace vmmagic {
+
+ class VISIBILITY_HIDDEN LowerMagic : public FunctionPass {
+ public:
+ static char ID;
+ LowerMagic() : FunctionPass((intptr_t)&ID) { }
+
+ virtual bool runOnFunction(Function &F);
+ private:
+ };
+ char LowerMagic::ID = 0;
+ static RegisterPass<LowerMagic> X("LowerMagic",
+ "Lower magic calls");
+
+static const char* AddressClass = "JnJVM_org_vmmagic_unboxed_Address_";
+static const char* AddressZeroMethod = 0;
+static const char* AddressIsZeroMethod;
+static const char* AddressMaxMethod;
+static const char* AddressIsMaxMethod;
+static const char* AddressFromIntSignExtendMethod;
+static const char* AddressFromIntZeroExtendMethod;
+static const char* AddressFromLongMethod;
+static const char* AddressToObjectReferenceMethod;
+static const char* AddressToIntMethod;
+static const char* AddressToLongMethod;
+static const char* AddressToWordMethod;
+static const char* AddressPlusIntMethod;
+static const char* AddressPlusOffsetMethod;
+static const char* AddressPlusExtentMethod;
+static const char* AddressMinusIntMethod;
+static const char* AddressMinusOffsetMethod;
+static const char* AddressMinusExtentMethod;
+static const char* AddressDiffMethod;
+static const char* AddressLTMethod;
+static const char* AddressLEMethod;
+static const char* AddressGTMethod;
+static const char* AddressGEMethod;
+static const char* AddressEQMethod;
+static const char* AddressNEMethod;
+static const char* AddressPrefetchMethod;
+static const char* AddressLoadObjectReferenceMethod;
+static const char* AddressLoadObjectReferenceAtOffsetMethod;
+static const char* AddressLoadByteMethod;
+static const char* AddressLoadByteAtOffsetMethod;
+static const char* AddressLoadCharMethod;
+static const char* AddressLoadCharAtOffsetMethod;
+static const char* AddressLoadShortMethod;
+static const char* AddressLoadShortAtOffsetMethod;
+static const char* AddressLoadFloatMethod;
+static const char* AddressLoadFloatAtOffsetMethod;
+static const char* AddressLoadIntMethod;
+static const char* AddressLoadIntAtOffsetMethod;
+static const char* AddressLoadLongMethod;
+static const char* AddressLoadLongAtOffsetMethod;
+static const char* AddressLoadDoubleMethod;
+static const char* AddressLoadDoubleAtOffsetMethod;
+static const char* AddressLoadAddressMethod;
+static const char* AddressLoadAddressAtOffsetMethod;
+static const char* AddressLoadWordMethod;
+static const char* AddressLoadWordAtOffsetMethod;
+static const char* AddressStoreObjectReferenceMethod;
+static const char* AddressStoreObjectReferenceAtOffsetMethod;
+static const char* AddressStoreAddressMethod;
+static const char* AddressStoreAddressAtOffsetMethod;
+static const char* AddressStoreFloatMethod;
+static const char* AddressStoreFloatAtOffsetMethod;
+static const char* AddressStoreWordMethod;
+static const char* AddressStoreWordAtOffsetMethod;
+static const char* AddressStoreByteMethod;
+static const char* AddressStoreByteAtOffsetMethod;
+static const char* AddressStoreIntMethod;
+static const char* AddressStoreIntAtOffsetMethod;
+static const char* AddressStoreDoubleMethod;
+static const char* AddressStoreDoubleAtOffsetMethod;
+static const char* AddressStoreLongMethod;
+static const char* AddressStoreLongAtOffsetMethod;
+static const char* AddressStoreCharMethod;
+static const char* AddressStoreCharAtOffsetMethod;
+static const char* AddressStoreShortMethod;
+static const char* AddressStoreShortAtOffsetMethod;
+static const char* AddressPrepareWordMethod;
+static const char* AddressPrepareWordAtOffsetMethod;
+static const char* AddressPrepareObjectReferenceMethod;
+static const char* AddressPrepareObjectReferenceAtOffsetMethod;
+static const char* AddressPrepareAddressMethod;
+static const char* AddressPrepareAddressAtOffsetMethod;
+static const char* AddressPrepareIntMethod;
+static const char* AddressPrepareIntAtOffsetMethod;
+static const char* AddressAttemptIntMethod;
+static const char* AddressAttemptIntAtOffsetMethod;
+static const char* AddressAttemptWordMethod;
+static const char* AddressAttemptWordAtOffsetMethod;
+static const char* AddressAttemptObjectReferenceMethod;
+static const char* AddressAttemptObjectReferenceAtOffsetMethod;
+static const char* AddressAttemptAddressMethod;
+static const char* AddressAttemptAddressAtOffsetMethod;
+
+static const char* ExtentClass = "JnJVM_org_vmmagic_unboxed_Extent_";
+static const char* ExtentToWordMethod = 0;
+static const char* ExtentFromIntSignExtendMethod;
+static const char* ExtentFromIntZeroExtendMethod;
+static const char* ExtentZeroMethod;
+static const char* ExtentOneMethod;
+static const char* ExtentMaxMethod;
+static const char* ExtentToIntMethod;
+static const char* ExtentToLongMethod;
+static const char* ExtentPlusIntMethod;
+static const char* ExtentPlusExtentMethod;
+static const char* ExtentMinusIntMethod;
+static const char* ExtentMinusExtentMethod;
+static const char* ExtentLTMethod;
+static const char* ExtentLEMethod;
+static const char* ExtentGTMethod;
+static const char* ExtentGEMethod;
+static const char* ExtentEQMethod;
+static const char* ExtentNEMethod;
+
+static const char* ObjectReferenceClass =
+ "JnJVM_org_vmmagic_unboxed_ObjectReference_";
+static const char* ObjectReferenceFromObjectMethod = 0;
+static const char* ObjectReferenceNullReferenceMethod;
+static const char* ObjectReferenceToObjectMethod;
+static const char* ObjectReferenceToAddressMethod;
+static const char* ObjectReferenceIsNullMethod;
+
+static const char* OffsetClass = "JnJVM_org_vmmagic_unboxed_Offset_";
+static const char* OffsetFromIntSignExtendMethod = 0;
+static const char* OffsetFromIntZeroExtendMethod;
+static const char* OffsetZeroMethod;
+static const char* OffsetMaxMethod;
+static const char* OffsetToIntMethod;
+static const char* OffsetToLongMethod;
+static const char* OffsetToWordMethod;
+static const char* OffsetPlusIntMethod;
+static const char* OffsetMinusIntMethod;
+static const char* OffsetMinusOffsetMethod;
+static const char* OffsetEQMethod;
+static const char* OffsetNEMethod;
+static const char* OffsetSLTMethod;
+static const char* OffsetSLEMethod;
+static const char* OffsetSGTMethod;
+static const char* OffsetSGEMethod;
+static const char* OffsetIsZeroMethod;
+static const char* OffsetIsMaxMethod;
+
+static const char* WordClass = "JnJVM_org_vmmagic_unboxed_Word_";
+static const char* WordFromIntSignExtendMethod = 0;
+static const char* WordFromIntZeroExtendMethod;
+static const char* WordFromLongMethod;
+static const char* WordZeroMethod;
+static const char* WordOneMethod;
+static const char* WordMaxMethod;
+static const char* WordToIntMethod;
+static const char* WordToLongMethod;
+static const char* WordToAddressMethod;
+static const char* WordToOffsetMethod;
+static const char* WordToExtentMethod;
+static const char* WordPlusWordMethod;
+static const char* WordPlusOffsetMethod;
+static const char* WordPlusExtentMethod;
+static const char* WordMinusWordMethod;
+static const char* WordMinusOffsetMethod;
+static const char* WordMinusExtentMethod;
+static const char* WordIsZeroMethod;
+static const char* WordIsMaxMethod;
+static const char* WordLTMethod;
+static const char* WordLEMethod;
+static const char* WordGTMethod;
+static const char* WordGEMethod;
+static const char* WordEQMethod;
+static const char* WordNEMethod;
+static const char* WordAndMethod;
+static const char* WordOrMethod;
+static const char* WordNotMethod;
+static const char* WordXorMethod;
+static const char* WordLshMethod;
+static const char* WordRshlMethod;
+static const char* WordRshaMethod;
+
+static Function* CASPtr;
+static Function* CASInt;
+
+static void initialiseFunctions(Module* M) {
+ if (!AddressZeroMethod) {
+ AddressZeroMethod = "JnJVM_org_vmmagic_unboxed_Address_zero__";
+ AddressMaxMethod = "JnJVM_org_vmmagic_unboxed_Address_max__";
+ AddressStoreObjectReferenceMethod = "JnJVM_org_vmmagic_unboxed_Address_store__Lorg_vmmagic_unboxed_ObjectReference_2";
+ AddressLoadObjectReferenceMethod = "JnJVM_org_vmmagic_unboxed_Address_loadObjectReference__";
+ AddressLoadAddressMethod = "JnJVM_org_vmmagic_unboxed_Address_loadAddress__";
+ AddressLoadWordMethod = "JnJVM_org_vmmagic_unboxed_Address_loadWord__";
+ AddressDiffMethod = "JnJVM_org_vmmagic_unboxed_Address_diff__Lorg_vmmagic_unboxed_Address_2";
+ AddressPlusOffsetMethod = "JnJVM_org_vmmagic_unboxed_Address_plus__Lorg_vmmagic_unboxed_Offset_2";
+ AddressStoreAddressMethod = "JnJVM_org_vmmagic_unboxed_Address_store__Lorg_vmmagic_unboxed_Address_2";
+ AddressPlusIntMethod = "JnJVM_org_vmmagic_unboxed_Address_plus__I";
+ AddressLTMethod = "JnJVM_org_vmmagic_unboxed_Address_LT__Lorg_vmmagic_unboxed_Address_2";
+ AddressGEMethod = "JnJVM_org_vmmagic_unboxed_Address_GE__Lorg_vmmagic_unboxed_Address_2";
+ AddressStoreWordMethod = "JnJVM_org_vmmagic_unboxed_Address_store__Lorg_vmmagic_unboxed_Word_2";
+ AddressToObjectReferenceMethod = "JnJVM_org_vmmagic_unboxed_Address_toObjectReference__";
+ AddressToWordMethod = "JnJVM_org_vmmagic_unboxed_Address_toWord__";
+ AddressPrepareWordMethod = "JnJVM_org_vmmagic_unboxed_Address_prepareWord__";
+ AddressAttemptWordAtOffsetMethod = "JnJVM_org_vmmagic_unboxed_Address_attempt__Lorg_vmmagic_unboxed_Word_2Lorg_vmmagic_unboxed_Word_2Lorg_vmmagic_unboxed_Offset_2";
+ AddressPrepareWordAtOffsetMethod = "JnJVM_org_vmmagic_unboxed_Address_prepareWord__Lorg_vmmagic_unboxed_Offset_2";
+ AddressLoadWordAtOffsetMethod = "JnJVM_org_vmmagic_unboxed_Address_loadWord__Lorg_vmmagic_unboxed_Offset_2";
+ AddressStoreWordAtOffsetMethod = "JnJVM_org_vmmagic_unboxed_Address_store__Lorg_vmmagic_unboxed_Word_2Lorg_vmmagic_unboxed_Offset_2";
+ AddressPlusExtentMethod = "JnJVM_org_vmmagic_unboxed_Address_plus__Lorg_vmmagic_unboxed_Extent_2";
+ AddressIsZeroMethod = "JnJVM_org_vmmagic_unboxed_Address_isZero__";
+ AddressStoreAddressAtOffsetMethod = "JnJVM_org_vmmagic_unboxed_Address_store__Lorg_vmmagic_unboxed_Address_2Lorg_vmmagic_unboxed_Offset_2";
+ AddressGTMethod = "JnJVM_org_vmmagic_unboxed_Address_GT__Lorg_vmmagic_unboxed_Address_2";
+ AddressLoadAddressAtOffsetMethod = "JnJVM_org_vmmagic_unboxed_Address_loadAddress__Lorg_vmmagic_unboxed_Offset_2";
+ AddressEQMethod = "JnJVM_org_vmmagic_unboxed_Address_EQ__Lorg_vmmagic_unboxed_Address_2";
+ AddressLoadObjectReferenceAtOffsetMethod = "JnJVM_org_vmmagic_unboxed_Address_loadObjectReference__Lorg_vmmagic_unboxed_Offset_2";
+ AddressLEMethod = "JnJVM_org_vmmagic_unboxed_Address_LE__Lorg_vmmagic_unboxed_Address_2";
+ AddressAttemptWordMethod = "JnJVM_org_vmmagic_unboxed_Address_attempt__Lorg_vmmagic_unboxed_Word_2Lorg_vmmagic_unboxed_Word_2";
+ AddressNEMethod = "JnJVM_org_vmmagic_unboxed_Address_NE__Lorg_vmmagic_unboxed_Address_2";
+ AddressToLongMethod = "JnJVM_org_vmmagic_unboxed_Address_toLong__";
+ AddressMinusExtentMethod = "JnJVM_org_vmmagic_unboxed_Address_minus__Lorg_vmmagic_unboxed_Extent_2";
+ AddressLoadShortAtOffsetMethod = "JnJVM_org_vmmagic_unboxed_Address_loadShort__Lorg_vmmagic_unboxed_Offset_2";
+ AddressStoreShortAtOffsetMethod = "JnJVM_org_vmmagic_unboxed_Address_store__SLorg_vmmagic_unboxed_Offset_2";
+ AddressLoadShortMethod = "JnJVM_org_vmmagic_unboxed_Address_loadShort__";
+ AddressStoreShortMethod = "JnJVM_org_vmmagic_unboxed_Address_store__S";
+ AddressLoadByteMethod = "JnJVM_org_vmmagic_unboxed_Address_loadByte__";
+ AddressLoadIntMethod = "JnJVM_org_vmmagic_unboxed_Address_loadInt__";
+ AddressStoreIntMethod = "JnJVM_org_vmmagic_unboxed_Address_store__I";
+ AddressStoreByteMethod = "JnJVM_org_vmmagic_unboxed_Address_store__B";
+ AddressLoadByteAtOffsetMethod = "JnJVM_org_vmmagic_unboxed_Address_loadByte__Lorg_vmmagic_unboxed_Offset_2";
+ AddressMinusIntMethod = "JnJVM_org_vmmagic_unboxed_Address_minus__I";
+ AddressLoadIntAtOffsetMethod = "JnJVM_org_vmmagic_unboxed_Address_loadInt__Lorg_vmmagic_unboxed_Offset_2";
+ AddressStoreByteAtOffsetMethod = "JnJVM_org_vmmagic_unboxed_Address_store__BLorg_vmmagic_unboxed_Offset_2";
+ AddressFromIntZeroExtendMethod = "JnJVM_org_vmmagic_unboxed_Address_fromIntZeroExtend__I";
+ AddressToIntMethod = "JnJVM_org_vmmagic_unboxed_Address_toInt__";
+
+ ExtentToWordMethod = "JnJVM_org_vmmagic_unboxed_Extent_toWord__";
+ ExtentMinusExtentMethod = "JnJVM_org_vmmagic_unboxed_Extent_minus__Lorg_vmmagic_unboxed_Extent_2";
+ ExtentPlusExtentMethod = "JnJVM_org_vmmagic_unboxed_Extent_plus__Lorg_vmmagic_unboxed_Extent_2";
+ ExtentPlusIntMethod = "JnJVM_org_vmmagic_unboxed_Extent_plus__I";
+ ExtentMinusIntMethod = "JnJVM_org_vmmagic_unboxed_Extent_minus__I";
+ ExtentFromIntZeroExtendMethod = "JnJVM_org_vmmagic_unboxed_Extent_fromIntZeroExtend__I";
+ ExtentFromIntSignExtendMethod = "JnJVM_org_vmmagic_unboxed_Extent_fromIntSignExtend__I";
+ ExtentOneMethod = "JnJVM_org_vmmagic_unboxed_Extent_one__";
+ ExtentNEMethod = "JnJVM_org_vmmagic_unboxed_Extent_NE__Lorg_vmmagic_unboxed_Extent_2";
+ ExtentZeroMethod = "JnJVM_org_vmmagic_unboxed_Extent_zero__";
+ ExtentToLongMethod = "JnJVM_org_vmmagic_unboxed_Extent_toLong__";
+ ExtentToIntMethod = "JnJVM_org_vmmagic_unboxed_Extent_toInt__";
+ ExtentEQMethod = "JnJVM_org_vmmagic_unboxed_Extent_EQ__Lorg_vmmagic_unboxed_Extent_2";
+ ExtentGTMethod = "JnJVM_org_vmmagic_unboxed_Extent_GT__Lorg_vmmagic_unboxed_Extent_2";
+ ExtentLTMethod = "JnJVM_org_vmmagic_unboxed_Extent_LT__Lorg_vmmagic_unboxed_Extent_2";
+ ExtentMaxMethod = "JnJVM_org_vmmagic_unboxed_Extent_max__";
+
+ ObjectReferenceFromObjectMethod = "JnJVM_org_vmmagic_unboxed_ObjectReference_fromObject__Ljava_lang_Object_2";
+ ObjectReferenceToObjectMethod = "JnJVM_org_vmmagic_unboxed_ObjectReference_toObject__";
+ ObjectReferenceNullReferenceMethod = "JnJVM_org_vmmagic_unboxed_ObjectReference_nullReference__";
+ ObjectReferenceToAddressMethod = "JnJVM_org_vmmagic_unboxed_ObjectReference_toAddress__";
+ ObjectReferenceIsNullMethod = "JnJVM_org_vmmagic_unboxed_ObjectReference_isNull__";
+
+ WordOrMethod = "JnJVM_org_vmmagic_unboxed_Word_or__Lorg_vmmagic_unboxed_Word_2";
+ WordRshlMethod = "JnJVM_org_vmmagic_unboxed_Word_rshl__I";
+ WordToIntMethod = "JnJVM_org_vmmagic_unboxed_Word_toInt__";
+ WordNotMethod = "JnJVM_org_vmmagic_unboxed_Word_not__";
+ WordZeroMethod = "JnJVM_org_vmmagic_unboxed_Word_zero__";
+ WordOneMethod = "JnJVM_org_vmmagic_unboxed_Word_one__";
+ WordAndMethod = "JnJVM_org_vmmagic_unboxed_Word_and__Lorg_vmmagic_unboxed_Word_2";
+ WordToAddressMethod = "JnJVM_org_vmmagic_unboxed_Word_toAddress__";
+ WordLshMethod = "JnJVM_org_vmmagic_unboxed_Word_lsh__I";
+ WordMinusWordMethod = "JnJVM_org_vmmagic_unboxed_Word_minus__Lorg_vmmagic_unboxed_Word_2";
+ WordLTMethod = "JnJVM_org_vmmagic_unboxed_Word_LT__Lorg_vmmagic_unboxed_Word_2";
+ WordPlusWordMethod = "JnJVM_org_vmmagic_unboxed_Word_plus__Lorg_vmmagic_unboxed_Word_2";
+ WordLEMethod = "JnJVM_org_vmmagic_unboxed_Word_LE__Lorg_vmmagic_unboxed_Word_2";
+ WordGEMethod = "JnJVM_org_vmmagic_unboxed_Word_GE__Lorg_vmmagic_unboxed_Word_2";
+ WordEQMethod = "JnJVM_org_vmmagic_unboxed_Word_EQ__Lorg_vmmagic_unboxed_Word_2";
+ WordNEMethod = "JnJVM_org_vmmagic_unboxed_Word_NE__Lorg_vmmagic_unboxed_Word_2";
+ WordFromIntSignExtendMethod = "JnJVM_org_vmmagic_unboxed_Word_fromIntSignExtend__I";
+ WordIsZeroMethod = "JnJVM_org_vmmagic_unboxed_Word_isZero__";
+ WordXorMethod = "JnJVM_org_vmmagic_unboxed_Word_xor__Lorg_vmmagic_unboxed_Word_2";
+ WordFromIntZeroExtendMethod = "JnJVM_org_vmmagic_unboxed_Word_fromIntZeroExtend__I";
+ WordToExtentMethod = "JnJVM_org_vmmagic_unboxed_Word_toExtent__";
+ WordMinusExtentMethod = "JnJVM_org_vmmagic_unboxed_Word_minus__Lorg_vmmagic_unboxed_Extent_2";
+ WordToLongMethod = "JnJVM_org_vmmagic_unboxed_Word_toLong__";
+ WordMaxMethod = "JnJVM_org_vmmagic_unboxed_Word_max__";
+ WordToOffsetMethod = "JnJVM_org_vmmagic_unboxed_Word_toOffset__";
+ WordGTMethod = "JnJVM_org_vmmagic_unboxed_Word_GT__Lorg_vmmagic_unboxed_Word_2";
+
+
+ OffsetSLTMethod = "JnJVM_org_vmmagic_unboxed_Offset_sLT__Lorg_vmmagic_unboxed_Offset_2";
+ OffsetFromIntSignExtendMethod = "JnJVM_org_vmmagic_unboxed_Offset_fromIntSignExtend__I";
+ OffsetSGTMethod = "JnJVM_org_vmmagic_unboxed_Offset_sGT__Lorg_vmmagic_unboxed_Offset_2";
+ OffsetPlusIntMethod = "JnJVM_org_vmmagic_unboxed_Offset_plus__I";
+ OffsetZeroMethod = "JnJVM_org_vmmagic_unboxed_Offset_zero__";
+ OffsetToWordMethod = "JnJVM_org_vmmagic_unboxed_Offset_toWord__";
+ OffsetFromIntZeroExtendMethod = "JnJVM_org_vmmagic_unboxed_Offset_fromIntZeroExtend__I";
+ OffsetSGEMethod = "JnJVM_org_vmmagic_unboxed_Offset_sGE__Lorg_vmmagic_unboxed_Offset_2";
+ OffsetToIntMethod = "JnJVM_org_vmmagic_unboxed_Offset_toInt__";
+ OffsetToLongMethod = "JnJVM_org_vmmagic_unboxed_Offset_toLong__";
+ OffsetIsZeroMethod = "JnJVM_org_vmmagic_unboxed_Offset_isZero__";
+ OffsetMinusIntMethod = "JnJVM_org_vmmagic_unboxed_Offset_minus__I";
+ OffsetSLEMethod = "JnJVM_org_vmmagic_unboxed_Offset_sLE__Lorg_vmmagic_unboxed_Offset_2";
+ OffsetEQMethod = "JnJVM_org_vmmagic_unboxed_Offset_EQ__Lorg_vmmagic_unboxed_Offset_2";
+ OffsetMinusOffsetMethod = "JnJVM_org_vmmagic_unboxed_Offset_minus__Lorg_vmmagic_unboxed_Offset_2";
+ }
+}
+
+#include <iostream>
+
+static bool removePotentialNullCheck(BasicBlock* Cur, Value* Obj) {
+ BasicBlock* BB = Cur->getUniquePredecessor();
+ LLVMContext* Context = Cur->getParent()->getContext();
+ if (BB) {
+ Instruction* T = BB->getTerminator();
+ if (dyn_cast<BranchInst>(T) && T != BB->begin()) {
+ BasicBlock::iterator BIE = BB->end();
+ --BIE; // Terminator
+ --BIE; // Null test
+ if (ICmpInst* IE = dyn_cast<ICmpInst>(BIE)) {
+ if (IE->getPredicate() == ICmpInst::ICMP_EQ &&
+ IE->getOperand(0) == Obj &&
+ IE->getOperand(1) == Context->getNullValue(Obj->getType())) {
+ BIE->replaceAllUsesWith(ConstantInt::getFalse());
+ BIE->eraseFromParent();
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+bool LowerMagic::runOnFunction(Function& F) {
+ Module* globalModule = F.getParent();
+ LLVMContext& Context = globalModule->getContext();
+ bool Changed = false;
+ const llvm::Type* pointerSizeType =
+ globalModule->getPointerSize() == llvm::Module::Pointer32 ?
+ Type::Int32Ty : Type::Int64Ty;
+
+ initialiseFunctions(globalModule);
+ if (!CASPtr || CASPtr->getParent() != globalModule) {
+ if (pointerSizeType == Type::Int32Ty) {
+ CASPtr = globalModule->getFunction("llvm.atomic.cmp.swap.i32.p0i32");
+ } else {
+ CASPtr = globalModule->getFunction("llvm.atomic.cmp.swap.i64.p0i64");
+ }
+ CASInt = globalModule->getFunction("llvm.atomic.cmp.swap.i32.p0i32");
+ }
+
+ for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE; BI++) {
+ BasicBlock *Cur = BI;
+ for (BasicBlock::iterator II = Cur->begin(), IE = Cur->end(); II != IE;) {
+ Instruction *I = II;
+ II++;
+ CallSite Call = CallSite::get(I);
+ Instruction* CI = Call.getInstruction();
+ if (CI) {
+ Value* V = Call.getCalledValue();
+ if (Function* FCur = dyn_cast<Function>(V)) {
+ const char* name = FCur->getNameStart();
+ unsigned len = FCur->getNameLen();
+ if (len > strlen(AddressClass) &&
+ !memcmp(AddressClass, name, strlen(AddressClass))) {
+
+ Changed = true;
+ // Remove the null check
+ if (Call.arg_begin() != Call.arg_end()) {
+ removePotentialNullCheck(Cur, Call.getArgument(0));
+ }
+
+ if (!strcmp(FCur->getNameStart(), AddressZeroMethod)) {
+ Constant* N = Context.getNullValue(FCur->getReturnType());
+ CI->replaceAllUsesWith(N);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), AddressMaxMethod)) {
+ ConstantInt* M = Context.getConstantInt(Type::Int64Ty, (uint64_t)-1);
+ Constant* N = ConstantExpr::getIntToPtr(M, FCur->getReturnType());
+ CI->replaceAllUsesWith(N);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), AddressStoreObjectReferenceMethod) ||
+ !strcmp(FCur->getNameStart(), AddressStoreAddressMethod) ||
+ !strcmp(FCur->getNameStart(), AddressStoreShortMethod) ||
+ !strcmp(FCur->getNameStart(), AddressStoreByteMethod) ||
+ !strcmp(FCur->getNameStart(), AddressStoreIntMethod) ||
+ !strcmp(FCur->getNameStart(), AddressStoreWordMethod)) {
+ Value* Addr = Call.getArgument(0);
+ Value* Obj = Call.getArgument(1);
+ const llvm::Type* Ty = PointerType::getUnqual(Obj->getType());
+ Addr = new BitCastInst(Addr, Ty, "", CI);
+ new StoreInst(Obj, Addr, CI);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), AddressLoadObjectReferenceMethod) ||
+ !strcmp(FCur->getNameStart(), AddressLoadAddressMethod) ||
+ !strcmp(FCur->getNameStart(), AddressLoadWordMethod) ||
+ !strcmp(FCur->getNameStart(), AddressLoadShortMethod) ||
+ !strcmp(FCur->getNameStart(), AddressLoadByteMethod) ||
+ !strcmp(FCur->getNameStart(), AddressLoadIntMethod) ||
+ !strcmp(FCur->getNameStart(), AddressPrepareWordMethod)) {
+ Value* Addr = Call.getArgument(0);
+ const Type* Ty = PointerType::getUnqual(FCur->getReturnType());
+ Addr = new BitCastInst(Addr, Ty, "", CI);
+ Value* LD = new LoadInst(Addr, "", CI);
+ CI->replaceAllUsesWith(LD);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), AddressDiffMethod) ||
+ !strcmp(FCur->getNameStart(), AddressMinusExtentMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = BinaryOperator::CreateSub(Val1, Val2, "", CI);
+ res = new IntToPtrInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), AddressPlusOffsetMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = BinaryOperator::CreateAdd(Val1, Val2, "", CI);
+ res = new IntToPtrInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), AddressPlusIntMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ if (Val2->getType() != pointerSizeType)
+ Val2 = new ZExtInst(Val2, pointerSizeType, "", CI);
+ Value* res = BinaryOperator::CreateAdd(Val1, Val2, "", CI);
+ res = new IntToPtrInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), AddressMinusIntMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ if (Val2->getType() != pointerSizeType)
+ Val2 = new ZExtInst(Val2, pointerSizeType, "", CI);
+ Value* res = BinaryOperator::CreateSub(Val1, Val2, "", CI);
+ res = new IntToPtrInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), AddressLTMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = new ICmpInst(CI, ICmpInst::ICMP_ULT, Val1, Val2, "");
+ res = new ZExtInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), AddressGTMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = new ICmpInst(CI, ICmpInst::ICMP_UGT, Val1, Val2, "");
+ res = new ZExtInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), AddressEQMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = new ICmpInst(CI, ICmpInst::ICMP_EQ, Val1, Val2, "");
+ res = new ZExtInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), AddressNEMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = new ICmpInst(CI, ICmpInst::ICMP_NE, Val1, Val2, "");
+ res = new ZExtInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), AddressLEMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = new ICmpInst(CI, ICmpInst::ICMP_ULE, Val1, Val2, "");
+ res = new ZExtInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), AddressGEMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = new ICmpInst(CI, ICmpInst::ICMP_UGE, Val1, Val2, "");
+ res = new ZExtInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), AddressToObjectReferenceMethod) ||
+ !strcmp(FCur->getNameStart(), AddressToWordMethod)) {
+ Value* Val = Call.getArgument(0);
+ Val = new BitCastInst(Val, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(Val);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), AddressAttemptWordAtOffsetMethod)) {
+ Value* Ptr = Call.getArgument(0);
+ Value* Old = Call.getArgument(1);
+ Value* Val = Call.getArgument(2);
+ Value* Offset = Call.getArgument(3);
+
+ Ptr = new PtrToIntInst(Ptr, pointerSizeType, "", CI);
+ Offset = new PtrToIntInst(Offset, pointerSizeType, "", CI);
+ Ptr = BinaryOperator::CreateAdd(Ptr, Offset, "", CI);
+ const Type* Ty = PointerType::getUnqual(pointerSizeType);
+ Ptr = new IntToPtrInst(Ptr, Ty, "", CI);
+ Old = new PtrToIntInst(Old, pointerSizeType, "", CI);
+ Val = new PtrToIntInst(Val, pointerSizeType, "", CI);
+
+ Value* Args[3] = { Ptr, Old, Val };
+ Value* res = CallInst::Create(CASPtr, Args, Args + 3, "", CI);
+ res = new ICmpInst(CI, ICmpInst::ICMP_EQ, res, Old, "");
+ res = new ZExtInst(res, FCur->getReturnType(), "", CI);
+
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), AddressAttemptWordMethod)) {
+ Value* Ptr = Call.getArgument(0);
+ Value* Old = Call.getArgument(1);
+ Value* Val = Call.getArgument(2);
+
+ const Type* Ty = PointerType::getUnqual(pointerSizeType);
+ Ptr = new BitCastInst(Ptr, Ty, "", CI);
+ Old = new PtrToIntInst(Old, pointerSizeType, "", CI);
+ Val = new PtrToIntInst(Val, pointerSizeType, "", CI);
+
+ Value* Args[3] = { Ptr, Old, Val };
+ Value* res = CallInst::Create(CASPtr, Args, Args + 3, "", CI);
+ res = new ICmpInst(CI, ICmpInst::ICMP_EQ, res, Old, "");
+ res = new ZExtInst(res, FCur->getReturnType(), "", CI);
+
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), AddressPrepareWordAtOffsetMethod) ||
+ !strcmp(FCur->getNameStart(), AddressLoadWordAtOffsetMethod) ||
+ !strcmp(FCur->getNameStart(), AddressLoadAddressAtOffsetMethod) ||
+ !strcmp(FCur->getNameStart(), AddressLoadObjectReferenceAtOffsetMethod) ||
+ !strcmp(FCur->getNameStart(), AddressLoadByteAtOffsetMethod) ||
+ !strcmp(FCur->getNameStart(), AddressLoadIntAtOffsetMethod) ||
+ !strcmp(FCur->getNameStart(), AddressLoadShortAtOffsetMethod)) {
+ Value* Ptr = Call.getArgument(0);
+ Value* Offset = Call.getArgument(1);
+
+ Ptr = new PtrToIntInst(Ptr, pointerSizeType, "", CI);
+ Offset = new PtrToIntInst(Offset, pointerSizeType, "", CI);
+ Ptr = BinaryOperator::CreateAdd(Ptr, Offset, "", CI);
+ const Type* Ty = PointerType::getUnqual(FCur->getReturnType());
+ Ptr = new IntToPtrInst(Ptr, Ty, "", CI);
+ Value* res = new LoadInst(Ptr, "", CI);
+
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), AddressStoreWordAtOffsetMethod) ||
+ !strcmp(FCur->getNameStart(), AddressStoreAddressAtOffsetMethod) ||
+ !strcmp(FCur->getNameStart(), AddressStoreByteAtOffsetMethod) ||
+ !strcmp(FCur->getNameStart(), AddressStoreShortAtOffsetMethod)) {
+ Value* Ptr = Call.getArgument(0);
+ Value* Val = Call.getArgument(1);
+ Value* Offset = Call.getArgument(2);
+
+ Ptr = new PtrToIntInst(Ptr, pointerSizeType, "", CI);
+ Offset = new PtrToIntInst(Offset, pointerSizeType, "", CI);
+ Ptr = BinaryOperator::CreateAdd(Ptr, Offset, "", CI);
+ const Type* Ty = PointerType::getUnqual(Val->getType());
+ Ptr = new IntToPtrInst(Ptr, Ty, "", CI);
+ new StoreInst(Val, Ptr, CI);
+
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), AddressPlusExtentMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = BinaryOperator::CreateAdd(Val1, Val2, "", CI);
+ res = new IntToPtrInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), AddressIsZeroMethod)) {
+ Value* Val = Call.getArgument(0);
+ Constant* N = Context.getNullValue(Val->getType());
+ Value* Res = new ICmpInst(CI, ICmpInst::ICMP_EQ, Val, N, "");
+ Res = new ZExtInst(Res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(Res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), AddressToLongMethod)) {
+ Value* Val = Call.getArgument(0);
+ Val = new PtrToIntInst(Val, Type::Int64Ty, "", CI);
+ CI->replaceAllUsesWith(Val);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), AddressFromIntZeroExtendMethod)) {
+ Value* Val = Call.getArgument(0);
+ if (pointerSizeType != Type::Int32Ty)
+ Val = new ZExtInst(Val, pointerSizeType, "", CI);
+ Val = new IntToPtrInst(Val, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(Val);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), AddressToIntMethod)) {
+ Value* Val = Call.getArgument(0);
+ Val = new PtrToIntInst(Val, Type::Int32Ty, "", CI);
+ CI->replaceAllUsesWith(Val);
+ CI->eraseFromParent();
+ } else {
+ fprintf(stderr, "Implement me %s\n", name);
+ abort();
+ }
+
+ } else if (len > strlen(ExtentClass) &&
+ !memcmp(ExtentClass, name, strlen(ExtentClass))) {
+
+ Changed = true;
+ // Remove the null check
+ if (Call.arg_begin() != Call.arg_end()) {
+ removePotentialNullCheck(Cur, Call.getArgument(0));
+ }
+
+ if (!strcmp(FCur->getNameStart(), ExtentToWordMethod)) {
+ CI->replaceAllUsesWith(Call.getArgument(0));
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), ExtentMinusExtentMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = BinaryOperator::CreateSub(Val1, Val2, "", CI);
+ res = new IntToPtrInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), ExtentPlusExtentMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = BinaryOperator::CreateAdd(Val1, Val2, "", CI);
+ res = new IntToPtrInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), ExtentPlusIntMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ if (Val2->getType() != pointerSizeType)
+ Val2 = new ZExtInst(Val2, pointerSizeType, "", CI);
+ Value* res = BinaryOperator::CreateAdd(Val1, Val2, "", CI);
+ res = new IntToPtrInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), ExtentMinusIntMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ if (Val2->getType() != pointerSizeType)
+ Val2 = new ZExtInst(Val2, pointerSizeType, "", CI);
+ Value* res = BinaryOperator::CreateSub(Val1, Val2, "", CI);
+ res = new IntToPtrInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), ExtentFromIntZeroExtendMethod)) {
+ Value* Val = Call.getArgument(0);
+ if (pointerSizeType != Type::Int32Ty)
+ Val = new ZExtInst(Val, pointerSizeType, "", CI);
+ Val = new IntToPtrInst(Val, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(Val);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), ExtentFromIntSignExtendMethod)) {
+ Value* Val = Call.getArgument(0);
+ if (pointerSizeType != Type::Int32Ty)
+ Val = new SExtInst(Val, pointerSizeType, "", CI);
+ Val = new IntToPtrInst(Val, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(Val);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), ExtentOneMethod)) {
+ Constant* N = Context.getConstantInt(pointerSizeType, 1);
+ N = ConstantExpr::getIntToPtr(N, FCur->getReturnType());
+ CI->replaceAllUsesWith(N);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), ExtentNEMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = new ICmpInst(CI, ICmpInst::ICMP_NE, Val1, Val2, "");
+ res = new ZExtInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), ExtentEQMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = new ICmpInst(CI, ICmpInst::ICMP_EQ, Val1, Val2, "");
+ res = new ZExtInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), ExtentGTMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = new ICmpInst(CI, ICmpInst::ICMP_UGT, Val1, Val2, "");
+ res = new ZExtInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), ExtentLTMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = new ICmpInst(CI, ICmpInst::ICMP_ULT, Val1, Val2, "");
+ res = new ZExtInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), ExtentZeroMethod)) {
+ Constant* N = Context.getNullValue(FCur->getReturnType());
+ CI->replaceAllUsesWith(N);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), ExtentToLongMethod)) {
+ Value* Val = Call.getArgument(0);
+ Val = new PtrToIntInst(Val, Type::Int64Ty, "", CI);
+ CI->replaceAllUsesWith(Val);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), ExtentToIntMethod)) {
+ Value* Val = Call.getArgument(0);
+ Val = new PtrToIntInst(Val, Type::Int32Ty, "", CI);
+ CI->replaceAllUsesWith(Val);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), ExtentMaxMethod)) {
+ ConstantInt* M = Context.getConstantInt(Type::Int64Ty, (uint64_t)-1);
+ Constant* N = ConstantExpr::getIntToPtr(M, FCur->getReturnType());
+ CI->replaceAllUsesWith(N);
+ CI->eraseFromParent();
+ } else {
+ fprintf(stderr, "Implement me %s\n", name);
+ abort();
+ }
+ } else if (len > strlen(OffsetClass) &&
+ !memcmp(OffsetClass, name, strlen(OffsetClass))) {
+
+ Changed = true;
+ // Remove the null check
+ if (Call.arg_begin() != Call.arg_end()) {
+ removePotentialNullCheck(Cur, Call.getArgument(0));
+ }
+
+ if (!strcmp(FCur->getNameStart(), OffsetSLTMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = new ICmpInst(CI, ICmpInst::ICMP_SLT, Val1, Val2, "");
+ res = new ZExtInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), OffsetToWordMethod)) {
+ Value* Val = Call.getArgument(0);
+ Val = new BitCastInst(Val, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(Val);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), OffsetZeroMethod)) {
+ Constant* N = Context.getNullValue(FCur->getReturnType());
+ CI->replaceAllUsesWith(N);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), OffsetSGTMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = new ICmpInst(CI, ICmpInst::ICMP_SGT, Val1, Val2, "");
+ res = new ZExtInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), OffsetSGEMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = new ICmpInst(CI, ICmpInst::ICMP_SGE, Val1, Val2, "");
+ res = new ZExtInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), OffsetSLEMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = new ICmpInst(CI, ICmpInst::ICMP_SLE, Val1, Val2, "");
+ res = new ZExtInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), OffsetEQMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = new ICmpInst(CI, ICmpInst::ICMP_EQ, Val1, Val2, "");
+ res = new ZExtInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), OffsetFromIntSignExtendMethod)) {
+ Value* Val = Call.getArgument(0);
+ if (pointerSizeType != Type::Int32Ty)
+ Val = new SExtInst(Val, pointerSizeType, "", CI);
+ Val = new IntToPtrInst(Val, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(Val);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), OffsetFromIntZeroExtendMethod)) {
+ Value* Val = Call.getArgument(0);
+ if (pointerSizeType != Type::Int32Ty)
+ Val = new ZExtInst(Val, pointerSizeType, "", CI);
+ Val = new IntToPtrInst(Val, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(Val);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), OffsetPlusIntMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ if (Val2->getType() != pointerSizeType)
+ Val2 = new ZExtInst(Val2, pointerSizeType, "", CI);
+ Value* res = BinaryOperator::CreateAdd(Val1, Val2, "", CI);
+ res = new IntToPtrInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), OffsetToIntMethod)) {
+ Value* Val = Call.getArgument(0);
+ Val = new PtrToIntInst(Val, Type::Int32Ty, "", CI);
+ CI->replaceAllUsesWith(Val);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), OffsetToLongMethod)) {
+ Value* Val = Call.getArgument(0);
+ Val = new PtrToIntInst(Val, Type::Int64Ty, "", CI);
+ CI->replaceAllUsesWith(Val);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), OffsetIsZeroMethod)) {
+ Value* Val = Call.getArgument(0);
+ Constant* N = Context.getNullValue(Val->getType());
+ Value* Res = new ICmpInst(CI, ICmpInst::ICMP_EQ, Val, N, "");
+ Res = new ZExtInst(Res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(Res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), OffsetMinusIntMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ if (Val2->getType() != pointerSizeType)
+ Val2 = new ZExtInst(Val2, pointerSizeType, "", CI);
+ Value* res = BinaryOperator::CreateSub(Val1, Val2, "", CI);
+ res = new IntToPtrInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), OffsetMinusOffsetMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = BinaryOperator::CreateSub(Val1, Val2, "", CI);
+ res = new IntToPtrInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else {
+ fprintf(stderr, "Implement me %s\n", name);
+ abort();
+ }
+ } else if (len > strlen(ObjectReferenceClass) &&
+ !memcmp(ObjectReferenceClass, name, strlen(ObjectReferenceClass))) {
+
+ Changed = true;
+ // Remove the null check
+ if (Call.arg_begin() != Call.arg_end()) {
+ removePotentialNullCheck(Cur, Call.getArgument(0));
+ }
+
+ if (!strcmp(FCur->getNameStart(), ObjectReferenceNullReferenceMethod)) {
+ Constant* N = Context.getNullValue(FCur->getReturnType());
+ CI->replaceAllUsesWith(N);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), ObjectReferenceFromObjectMethod)) {
+ Value* Val = Call.getArgument(0);
+ Val = new BitCastInst(Val, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(Val);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), ObjectReferenceToAddressMethod)) {
+ Value* Val = Call.getArgument(0);
+ Val = new BitCastInst(Val, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(Val);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), ObjectReferenceToObjectMethod)) {
+ Value* Val = Call.getArgument(0);
+ Val = new BitCastInst(Val, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(Val);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), ObjectReferenceIsNullMethod)) {
+ Value* Val = Call.getArgument(0);
+ Constant* N = Context.getNullValue(Val->getType());
+ Value* Res = new ICmpInst(CI, ICmpInst::ICMP_EQ, Val, N, "");
+ Res = new ZExtInst(Res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(Res);
+ CI->eraseFromParent();
+ } else {
+ fprintf(stderr, "Implement me %s\n", name);
+ abort();
+ }
+ } else if (len > strlen(WordClass) &&
+ !memcmp(WordClass, name, strlen(WordClass))) {
+
+ Changed = true;
+ // Remove the null check
+ if (Call.arg_begin() != Call.arg_end()) {
+ removePotentialNullCheck(Cur, Call.getArgument(0));
+ }
+
+ if (!strcmp(FCur->getNameStart(), WordOrMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* Res = BinaryOperator::CreateOr(Val1, Val2, "", CI);
+ Res = new IntToPtrInst(Res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(Res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), WordAndMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* Res = BinaryOperator::CreateAnd(Val1, Val2, "", CI);
+ Res = new IntToPtrInst(Res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(Res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), WordXorMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* Res = BinaryOperator::CreateXor(Val1, Val2, "", CI);
+ Res = new IntToPtrInst(Res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(Res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), WordRshlMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ if (Val2->getType() != pointerSizeType)
+ Val2 = new ZExtInst(Val2, pointerSizeType, "", CI);
+ Value* Res = BinaryOperator::CreateLShr(Val1, Val2, "", CI);
+ Res = new IntToPtrInst(Res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(Res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), WordLshMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ if (Val2->getType() != pointerSizeType)
+ Val2 = new ZExtInst(Val2, pointerSizeType, "", CI);
+ Value* Res = BinaryOperator::CreateShl(Val1, Val2, "", CI);
+ Res = new IntToPtrInst(Res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(Res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), WordToIntMethod)) {
+ Value* Val = Call.getArgument(0);
+ Val = new PtrToIntInst(Val, Type::Int32Ty, "", CI);
+ CI->replaceAllUsesWith(Val);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), WordNotMethod)) {
+ Value* Val = Call.getArgument(0);
+ Val = new PtrToIntInst(Val, pointerSizeType, "", CI);
+ Constant* M1 = Context.getConstantInt(pointerSizeType, -1);
+ Value* Res = BinaryOperator::CreateXor(Val, M1, "", CI);
+ Res = new IntToPtrInst(Res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(Res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), WordZeroMethod)) {
+ Constant* N = Context.getNullValue(FCur->getReturnType());
+ CI->replaceAllUsesWith(N);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), WordOneMethod)) {
+ Constant* N = Context.getConstantInt(pointerSizeType, 1);
+ N = ConstantExpr::getIntToPtr(N, FCur->getReturnType());
+ CI->replaceAllUsesWith(N);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), WordToAddressMethod) ||
+ !strcmp(FCur->getNameStart(), WordToOffsetMethod) ||
+ !strcmp(FCur->getNameStart(), WordToExtentMethod)) {
+ Value* Val = Call.getArgument(0);
+ Val = new BitCastInst(Val, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(Val);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), WordMinusWordMethod) ||
+ !strcmp(FCur->getNameStart(), WordMinusExtentMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = BinaryOperator::CreateSub(Val1, Val2, "", CI);
+ res = new IntToPtrInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), WordPlusWordMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = BinaryOperator::CreateAdd(Val1, Val2, "", CI);
+ res = new IntToPtrInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), WordLTMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = new ICmpInst(CI, ICmpInst::ICMP_ULT, Val1, Val2, "");
+ res = new ZExtInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), WordLEMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = new ICmpInst(CI, ICmpInst::ICMP_ULE, Val1, Val2, "");
+ res = new ZExtInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), WordGEMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = new ICmpInst(CI, ICmpInst::ICMP_UGE, Val1, Val2, "");
+ res = new ZExtInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), WordEQMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = new ICmpInst(CI, ICmpInst::ICMP_EQ, Val1, Val2, "");
+ res = new ZExtInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), WordGTMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = new ICmpInst(CI, ICmpInst::ICMP_UGT, Val1, Val2, "");
+ res = new ZExtInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), WordNEMethod)) {
+ Value* Val1 = Call.getArgument(0);
+ Value* Val2 = Call.getArgument(1);
+ Val1 = new PtrToIntInst(Val1, pointerSizeType, "", CI);
+ Val2 = new PtrToIntInst(Val2, pointerSizeType, "", CI);
+ Value* res = new ICmpInst(CI, ICmpInst::ICMP_NE, Val1, Val2, "");
+ res = new ZExtInst(res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), WordFromIntSignExtendMethod)) {
+ Value* Val = Call.getArgument(0);
+ if (pointerSizeType != Type::Int32Ty)
+ Val = new SExtInst(Val, pointerSizeType, "", CI);
+ Val = new IntToPtrInst(Val, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(Val);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), WordFromIntZeroExtendMethod)) {
+ Value* Val = Call.getArgument(0);
+ if (pointerSizeType != Type::Int32Ty)
+ Val = new ZExtInst(Val, pointerSizeType, "", CI);
+ Val = new IntToPtrInst(Val, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(Val);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), WordIsZeroMethod)) {
+ Value* Val = Call.getArgument(0);
+ Constant* N = Context.getNullValue(Val->getType());
+ Value* Res = new ICmpInst(CI, ICmpInst::ICMP_EQ, Val, N, "");
+ Res = new ZExtInst(Res, FCur->getReturnType(), "", CI);
+ CI->replaceAllUsesWith(Res);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), WordToLongMethod)) {
+ Value* Val = Call.getArgument(0);
+ Val = new PtrToIntInst(Val, Type::Int64Ty, "", CI);
+ CI->replaceAllUsesWith(Val);
+ CI->eraseFromParent();
+ } else if (!strcmp(FCur->getNameStart(), WordMaxMethod)) {
+ ConstantInt* M = Context.getConstantInt(Type::Int64Ty, (uint64_t)-1);
+ Constant* N = ConstantExpr::getIntToPtr(M, FCur->getReturnType());
+ CI->replaceAllUsesWith(N);
+ CI->eraseFromParent();
+ } else {
+ fprintf(stderr, "Implement me %s\n", name);
+ abort();
+ }
+ }
+ }
+ }
+ }
+ }
+ return Changed;
+}
+
+
+FunctionPass* createLowerMagicPass() {
+ return new LowerMagic();
+}
+
+}
Added: vmkit/trunk/mmtk/magic/Makefile
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/magic/Makefile?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/magic/Makefile (added)
+++ vmkit/trunk/mmtk/magic/Makefile Thu Jul 16 06:26:34 2009
@@ -0,0 +1,16 @@
+##===- mmtk/magic/Makefile ---------------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+LIBRARYNAME = MMTKMagic
+LOADABLE_MODULE = 1
+USEDLIBS =
+
+include $(LEVEL)/Makefile.common
+
Added: vmkit/trunk/mmtk/mmtk-j3/ActivePlan.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/ActivePlan.cpp?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/mmtk-j3/ActivePlan.cpp (added)
+++ vmkit/trunk/mmtk/mmtk-j3/ActivePlan.cpp Thu Jul 16 06:26:34 2009
@@ -0,0 +1,22 @@
+//===------ ActivePlan.cpp - Implementation of the ActivePlan class ------===//
+//
+// The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "JavaObject.h"
+
+using namespace jnjvm;
+
+extern "C" JavaObject* Java_org_j3_mmtk_ActivePlan_getNextMutator__ (JavaObject* A) {
+ return 0;
+}
+
+extern "C" void Java_org_j3_mmtk_ActivePlan_resetMutatorIterator__ (JavaObject* A) {
+ return;
+}
+
+extern "C" void Java_org_j3_mmtk_ActivePlan_collectorCount__ () { abort(); }
Added: vmkit/trunk/mmtk/mmtk-j3/Assert.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/Assert.cpp?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/mmtk-j3/Assert.cpp (added)
+++ vmkit/trunk/mmtk/mmtk-j3/Assert.cpp Thu Jul 16 06:26:34 2009
@@ -0,0 +1,14 @@
+//===----------- Assert.cpp - Implementation of the Assert class ---------===//
+//
+// The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "JavaObject.h"
+
+using namespace jnjvm;
+
+extern "C" void Java_org_j3_mmtk_Assert_dumpStack__ () { abort(); }
Added: vmkit/trunk/mmtk/mmtk-j3/Collection.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/Collection.cpp?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/mmtk-j3/Collection.cpp (added)
+++ vmkit/trunk/mmtk/mmtk-j3/Collection.cpp Thu Jul 16 06:26:34 2009
@@ -0,0 +1,54 @@
+//===------- Collection.cpp - Implementation of the Collection class -----===//
+//
+// The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "JavaObject.h"
+
+using namespace jnjvm;
+
+extern "C" void JnJVM_org_mmtk_plan_Plan_setCollectionTriggered__();
+
+extern "C" void JnJVM_org_j3_config_Selected_00024Collector_staticCollect__();
+
+extern "C" void JnJVM_org_mmtk_plan_Plan_collectionComplete__();
+
+
+extern "C" bool Java_org_j3_mmtk_Collection_isEmergencyAllocation__ (JavaObject* C) {
+ return false;
+}
+
+extern "C" void Java_org_j3_mmtk_Collection_reportAllocationSuccess__ (JavaObject* C) {
+}
+
+
+extern "C" void Java_org_j3_mmtk_Collection_triggerCollection__I (JavaObject* C, int why) {
+ JnJVM_org_mmtk_plan_Plan_setCollectionTriggered__();
+ JnJVM_org_j3_config_Selected_00024Collector_staticCollect__();
+ JnJVM_org_mmtk_plan_Plan_collectionComplete__();
+}
+
+extern "C" int Java_org_j3_mmtk_Collection_rendezvous__I (JavaObject* C, int where) {
+ return 1;
+}
+
+extern "C" int Java_org_j3_mmtk_Collection_maximumCollectionAttempt__ (JavaObject* C) {
+ return 1;
+}
+
+extern "C" void Java_org_j3_mmtk_Collection_prepareCollector__Lorg_mmtk_plan_CollectorContext_2 (JavaObject* C, JavaObject* CC) {
+}
+
+
+extern "C" void Java_org_j3_mmtk_Collection_joinCollection__ () { abort(); }
+extern "C" void Java_org_j3_mmtk_Collection_reportPhysicalAllocationFailed__ () { abort(); }
+extern "C" void Java_org_j3_mmtk_Collection_triggerAsyncCollection__I () { abort(); }
+extern "C" void Java_org_j3_mmtk_Collection_noThreadsInGC__ () { abort(); }
+extern "C" void Java_org_j3_mmtk_Collection_prepareMutator__Lorg_mmtk_plan_MutatorContext_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_Collection_activeGCThreads__ () { abort(); }
+extern "C" void Java_org_j3_mmtk_Collection_activeGCThreadOrdinal__ () { abort(); }
+extern "C" void Java_org_j3_mmtk_Collection_requestMutatorFlush__ () { abort(); }
Added: vmkit/trunk/mmtk/mmtk-j3/FinalizableProcessor.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/FinalizableProcessor.cpp?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/mmtk-j3/FinalizableProcessor.cpp (added)
+++ vmkit/trunk/mmtk/mmtk-j3/FinalizableProcessor.cpp Thu Jul 16 06:26:34 2009
@@ -0,0 +1,26 @@
+//===- FinalizableProcessor.cpp -------------------------------------------===//
+//===- Implementation of the FinalizableProcessor class ------------------===//
+//
+// The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "JavaObject.h"
+
+using namespace jnjvm;
+
+extern "C" void Java_org_j3_mmtk_FinalizableProcessor_clear__ () {
+ abort();
+}
+
+extern "C" void
+Java_org_j3_mmtk_FinalizableProcessor_forward__Lorg_mmtk_plan_TraceLocal_2Z () {
+ abort();
+}
+
+extern "C" void
+Java_org_j3_mmtk_FinalizableProcessor_scan__Lorg_mmtk_plan_TraceLocal_2Z () {
+}
Added: vmkit/trunk/mmtk/mmtk-j3/Lock.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/Lock.cpp?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/mmtk-j3/Lock.cpp (added)
+++ vmkit/trunk/mmtk/mmtk-j3/Lock.cpp Thu Jul 16 06:26:34 2009
@@ -0,0 +1,28 @@
+//===----------- Lock.cpp - Implementation of the Lock class -------------===//
+//
+// The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "JavaObject.h"
+#include "mvm/Threads/Locks.h"
+
+using namespace jnjvm;
+
+struct Lock {
+ JavaObject base;
+ mvm::SpinLock spin;
+};
+
+
+extern "C" void Java_org_j3_mmtk_Lock_acquire__(Lock* l) {
+ l->spin.acquire();
+}
+extern "C" void Java_org_j3_mmtk_Lock_check__I () { abort(); }
+
+extern "C" void Java_org_j3_mmtk_Lock_release__(Lock* l) {
+ l->spin.release();
+}
Added: vmkit/trunk/mmtk/mmtk-j3/Makefile
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/Makefile?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/mmtk-j3/Makefile (added)
+++ vmkit/trunk/mmtk/mmtk-j3/Makefile Thu Jul 16 06:26:34 2009
@@ -0,0 +1,18 @@
+##===- mmtk/magic/Makefile ---------------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+LIBRARYNAME = MMTKRuntime
+LOADABLE_MODULE = 1
+USEDLIBS =
+
+CXX.Flags += -I$(PROJ_OBJ_DIR)/../../lib/JnJVM/VMCore
+
+include $(LEVEL)/Makefile.common
+
Added: vmkit/trunk/mmtk/mmtk-j3/Memory.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/Memory.cpp?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/mmtk-j3/Memory.cpp (added)
+++ vmkit/trunk/mmtk/mmtk-j3/Memory.cpp Thu Jul 16 06:26:34 2009
@@ -0,0 +1,76 @@
+//===------------ Memory.cpp - Implementation of the Memory class --------===//
+//
+// The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <sys/mman.h>
+
+
+#include "JavaObject.h"
+
+using namespace jnjvm;
+extern "C" uintptr_t Java_org_j3_mmtk_Memory_getHeapStartConstant__ () {
+ return (uintptr_t)0x30000000;
+}
+
+extern "C" uintptr_t Java_org_j3_mmtk_Memory_getHeapEndConstant__ () {
+ return (uintptr_t)0x80000000;
+}
+
+extern "C" uintptr_t Java_org_j3_mmtk_Memory_getAvailableStartConstant__ () {
+ return (uintptr_t)0x30000000;
+}
+
+extern "C" uintptr_t Java_org_j3_mmtk_Memory_getAvailableEndConstant__ () {
+ return (uintptr_t)0x80000000;
+}
+
+extern "C" sint32
+Java_org_j3_mmtk_Memory_dzmmap__Lorg_vmmagic_unboxed_Address_2I(JavaObject* M,
+ void* start,
+ sint32 size) {
+#if defined (__MACH__)
+ uint32 flags = MAP_PRIVATE | MAP_ANON | MAP_FIXED;
+#else
+ uint32 flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED;
+#endif
+ void* baseAddr = mmap((void*)start, size, PROT_READ | PROT_WRITE, flags,
+ -1, 0);
+ if (baseAddr == MAP_FAILED) {
+ perror("mmap");
+ abort();
+ }
+
+ return 0;
+}
+
+extern "C" void
+Java_org_j3_mmtk_Memory_mprotect__Lorg_vmmagic_unboxed_Address_2I () {
+ abort();
+}
+
+extern "C" void
+Java_org_j3_mmtk_Memory_munprotect__Lorg_vmmagic_unboxed_Address_2I () {
+ abort();
+}
+
+extern "C" void
+Java_org_j3_mmtk_Memory_zero__Lorg_vmmagic_unboxed_Address_2Lorg_vmmagic_unboxed_Extent_2(JavaObject* M,
+ void* addr,
+ uintptr_t len) {
+ memset(addr, 0, len);
+}
+
+extern "C" void
+Java_org_j3_mmtk_Memory_zeroPages__Lorg_vmmagic_unboxed_Address_2I () {
+ abort();
+}
+
+extern "C" void
+Java_org_j3_mmtk_Memory_dumpMemory__Lorg_vmmagic_unboxed_Address_2II () {
+ abort();
+}
Added: vmkit/trunk/mmtk/mmtk-j3/ObjectModel.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/ObjectModel.cpp?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/mmtk-j3/ObjectModel.cpp (added)
+++ vmkit/trunk/mmtk/mmtk-j3/ObjectModel.cpp Thu Jul 16 06:26:34 2009
@@ -0,0 +1,51 @@
+//===---- ObjectModel.cpp - Implementation of the ObjectModel class ------===//
+//
+// The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "JavaObject.h"
+
+using namespace jnjvm;
+
+extern "C" intptr_t Java_org_j3_mmtk_ObjectModel_getArrayBaseOffset__ () {
+ return sizeof(JavaObject) + sizeof(ssize_t);
+}
+
+extern "C" intptr_t Java_org_j3_mmtk_ObjectModel_GC_1HEADER_1OFFSET__ () {
+ return sizeof(void*);
+}
+
+extern "C" uintptr_t Java_org_j3_mmtk_ObjectModel_readAvailableBitsWord__Lorg_vmmagic_unboxed_ObjectReference_2 (JavaObject* OM, JavaObject* obj) {
+ return ((uintptr_t*)obj)[1];
+}
+
+extern "C" void Java_org_j3_mmtk_ObjectModel_writeAvailableBitsWord__Lorg_vmmagic_unboxed_ObjectReference_2Lorg_vmmagic_unboxed_Word_2 (JavaObject* OM, JavaObject* obj, uintptr_t val) {
+ ((uintptr_t*)obj)[1] = val;
+}
+
+extern "C" void Java_org_j3_mmtk_ObjectModel_copy__Lorg_vmmagic_unboxed_ObjectReference_2I () { abort(); }
+extern "C" void Java_org_j3_mmtk_ObjectModel_copyTo__Lorg_vmmagic_unboxed_ObjectReference_2Lorg_vmmagic_unboxed_ObjectReference_2Lorg_vmmagic_unboxed_Address_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_ObjectModel_getReferenceWhenCopiedTo__Lorg_vmmagic_unboxed_ObjectReference_2Lorg_vmmagic_unboxed_Address_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_ObjectModel_getObjectEndAddress__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_ObjectModel_getSizeWhenCopied__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_ObjectModel_getAlignWhenCopied__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_ObjectModel_getAlignOffsetWhenCopied__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_ObjectModel_getCurrentSize__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_ObjectModel_getNextObject__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_ObjectModel_getObjectFromStartAddress__Lorg_vmmagic_unboxed_Address_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_ObjectModel_getTypeDescriptor__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_ObjectModel_getArrayLength__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_ObjectModel_isArray__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_ObjectModel_isPrimitiveArray__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_ObjectModel_attemptAvailableBits__Lorg_vmmagic_unboxed_ObjectReference_2Lorg_vmmagic_unboxed_Word_2Lorg_vmmagic_unboxed_Word_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_ObjectModel_prepareAvailableBits__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_ObjectModel_writeAvailableByte__Lorg_vmmagic_unboxed_ObjectReference_2B () { abort(); }
+extern "C" void Java_org_j3_mmtk_ObjectModel_readAvailableByte__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_ObjectModel_objectStartRef__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_ObjectModel_refToAddress__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_ObjectModel_isAcyclic__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_ObjectModel_dumpObject__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); }
Added: vmkit/trunk/mmtk/mmtk-j3/ReferenceProcessor.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/ReferenceProcessor.cpp?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/mmtk-j3/ReferenceProcessor.cpp (added)
+++ vmkit/trunk/mmtk/mmtk-j3/ReferenceProcessor.cpp Thu Jul 16 06:26:34 2009
@@ -0,0 +1,20 @@
+//===-------- ReferenceProcessor.cpp --------------------------------------===//
+//===-------- Implementation of the Selected class -----------------------===//
+//
+// The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "JavaObject.h"
+
+using namespace jnjvm;
+
+extern "C" void Java_org_j3_mmtk_ReferenceProcessor_scan__Lorg_mmtk_plan_TraceLocal_2Z () {
+}
+
+extern "C" void Java_org_j3_mmtk_ReferenceProcessor_forward__Lorg_mmtk_plan_TraceLocal_2Z () { abort(); }
+extern "C" void Java_org_j3_mmtk_ReferenceProcessor_clear__ () { abort(); }
+extern "C" void Java_org_j3_mmtk_ReferenceProcessor_countWaitingReferences__ () { abort(); }
Added: vmkit/trunk/mmtk/mmtk-j3/Scanning.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/Scanning.cpp?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/mmtk-j3/Scanning.cpp (added)
+++ vmkit/trunk/mmtk/mmtk-j3/Scanning.cpp Thu Jul 16 06:26:34 2009
@@ -0,0 +1,29 @@
+//===-------- Scanning.cpp - Implementation of the Scanning class --------===//
+//
+// The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "JavaObject.h"
+
+using namespace jnjvm;
+
+extern "C" void Java_org_j3_mmtk_Scanning_computeThreadRoots__Lorg_mmtk_plan_TraceLocal_2 () {
+}
+
+extern "C" void Java_org_j3_mmtk_Scanning_computeGlobalRoots__Lorg_mmtk_plan_TraceLocal_2 () {
+}
+
+extern "C" void Java_org_j3_mmtk_Scanning_computeStaticRoots__Lorg_mmtk_plan_TraceLocal_2 () {
+}
+
+extern "C" void Java_org_j3_mmtk_Scanning_resetThreadCounter__ () {
+}
+
+extern "C" void Java_org_j3_mmtk_Scanning_scanObject__Lorg_mmtk_plan_TransitiveClosure_2Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_Scanning_specializedScanObject__ILorg_mmtk_plan_TransitiveClosure_2Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_Scanning_precopyChildren__Lorg_mmtk_plan_TraceLocal_2Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_Scanning_preCopyGCInstances__Lorg_mmtk_plan_TraceLocal_2 () { abort(); }
Added: vmkit/trunk/mmtk/mmtk-j3/Selected.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/Selected.cpp?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/mmtk-j3/Selected.cpp (added)
+++ vmkit/trunk/mmtk/mmtk-j3/Selected.cpp Thu Jul 16 06:26:34 2009
@@ -0,0 +1,42 @@
+//===-------- Selected.cpp - Implementation of the Selected class --------===//
+//
+// The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "JavaArray.h"
+#include "JavaClass.h"
+#include "JavaObject.h"
+#include "JavaThread.h"
+
+using namespace jnjvm;
+
+#if 1
+
+extern "C" JavaObject* org_j3_config_Selected_4Mutator_static;
+extern "C" JavaObject* org_j3_config_Selected_4Collector_static;
+
+
+extern "C" JavaObject* Java_org_j3_config_Selected_00024Collector_get__() {
+ JavaObject* obj = org_j3_config_Selected_4Collector_static;
+ return obj;
+}
+
+extern "C" JavaObject* Java_org_j3_config_Selected_00024Mutator_get__() {
+ JavaObject* obj = org_j3_config_Selected_4Mutator_static;
+ return obj;
+}
+
+
+#else
+extern "C" JavaObject* Java_org_j3_config_Selected_00024Collector_get__() {
+ return 0;
+}
+
+extern "C" JavaObject* Java_org_j3_config_Selected_00024Mutator_get__() {
+ return 0;
+}
+#endif
Added: vmkit/trunk/mmtk/mmtk-j3/Statistics.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/Statistics.cpp?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/mmtk-j3/Statistics.cpp (added)
+++ vmkit/trunk/mmtk/mmtk-j3/Statistics.cpp Thu Jul 16 06:26:34 2009
@@ -0,0 +1,25 @@
+//===----- Statistics.cpp - Implementation of the Statistics class -------===//
+//
+// The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "JavaObject.h"
+
+using namespace jnjvm;
+
+extern "C" void Java_org_j3_mmtk_Statistics_perfCtrInit__I (JavaObject* S) {
+ // Implement me
+}
+
+extern "C" int64_t Java_org_j3_mmtk_Statistics_cycles__ () {
+ return 0;
+}
+
+extern "C" void Java_org_j3_mmtk_Statistics_getCollectionCount__ () { abort(); }
+extern "C" void Java_org_j3_mmtk_Statistics_nanoTime__ () { abort(); }
+extern "C" void Java_org_j3_mmtk_Statistics_perfCtrReadCycles__ () { abort(); }
+extern "C" void Java_org_j3_mmtk_Statistics_perfCtrReadMetric__ () { abort(); }
Added: vmkit/trunk/mmtk/mmtk-j3/Strings.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/Strings.cpp?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/mmtk-j3/Strings.cpp (added)
+++ vmkit/trunk/mmtk/mmtk-j3/Strings.cpp Thu Jul 16 06:26:34 2009
@@ -0,0 +1,50 @@
+//===--------- Strings.cpp - Implementation of the Strings class ---------===//
+//
+// The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "JavaArray.h"
+#include "JavaObject.h"
+#include "JavaString.h"
+#include "JavaThread.h"
+
+using namespace jnjvm;
+
+extern "C" void Java_org_j3_mmtk_Strings_write___3CI(JavaObject* str,
+ ArrayUInt16* msg,
+ sint32 len) {
+ for (sint32 i = 0; i < len; ++i)
+ fprintf(stderr, "%c", msg->elements[i]);
+}
+
+extern "C" void Java_org_j3_mmtk_Strings_writeThreadId___3CI(JavaObject*str,
+ ArrayUInt16* msg,
+ sint32 len) {
+
+ fprintf(stderr, "[%p] ", (void*)JavaThread::get());
+
+ for (sint32 i = 0; i < len; ++i)
+ fprintf(stderr, "%c", msg->elements[i]);
+}
+
+
+extern "C" sint32
+Java_org_j3_mmtk_Strings_copyStringToChars__Ljava_lang_String_2_3CII(
+ JavaObject* obj, JavaString* str, ArrayUInt16* dst, uint32 dstBegin,
+ uint32 dstEnd) {
+
+ sint32 len = str->count;
+ sint32 n = (dstBegin + len <= dstEnd) ? len : (dstEnd - dstBegin);
+
+ for (sint32 i = 0; i < n; i++) {
+ dst->elements[dstBegin + i] = str->value->elements[str->offset + i];
+ }
+
+ return n;
+
+}
+
Added: vmkit/trunk/mmtk/mmtk-j3/SynchronizedCounter.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/SynchronizedCounter.cpp?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/mmtk-j3/SynchronizedCounter.cpp (added)
+++ vmkit/trunk/mmtk/mmtk-j3/SynchronizedCounter.cpp Thu Jul 16 06:26:34 2009
@@ -0,0 +1,17 @@
+//===-------- SynchronizedCounter.cpp -------------------------------------===//
+//===-------- Implementation of the SynchronizedCounter class ------------===//
+//
+// The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "JavaObject.h"
+
+using namespace jnjvm;
+
+extern "C" void Java_org_j3_mmtk_SynchronizedCounter_reset__ () { abort(); }
+extern "C" void Java_org_j3_mmtk_SynchronizedCounter_increment__ () { abort(); }
+
Added: vmkit/trunk/mmtk/mmtk-j3/TraceInterface.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/TraceInterface.cpp?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/mmtk-j3/TraceInterface.cpp (added)
+++ vmkit/trunk/mmtk/mmtk-j3/TraceInterface.cpp Thu Jul 16 06:26:34 2009
@@ -0,0 +1,29 @@
+//===-- TraceInterface.cpp - Implementation of the TraceInterface class --===//
+//
+// The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "JavaObject.h"
+
+using namespace jnjvm;
+
+extern "C" void Java_org_j3_mmtk_TraceInterface_gcEnabled__ () { abort(); }
+extern "C" void Java_org_j3_mmtk_TraceInterface_adjustSlotOffset__ZLorg_vmmagic_unboxed_ObjectReference_2Lorg_vmmagic_unboxed_Address_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_TraceInterface_skipOwnFramesAndDump__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_TraceInterface_updateDeathTime__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_TraceInterface_setDeathTime__Lorg_vmmagic_unboxed_ObjectReference_2Lorg_vmmagic_unboxed_Word_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_TraceInterface_setLink__Lorg_vmmagic_unboxed_ObjectReference_2Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_TraceInterface_updateTime__Lorg_vmmagic_unboxed_Word_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_TraceInterface_getOID__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_TraceInterface_getDeathTime__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_TraceInterface_getLink__Lorg_vmmagic_unboxed_ObjectReference_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_TraceInterface_getBootImageLink__ () { abort(); }
+extern "C" void Java_org_j3_mmtk_TraceInterface_getOID__ () { abort(); }
+extern "C" void Java_org_j3_mmtk_TraceInterface_setOID__Lorg_vmmagic_unboxed_Word_2 () { abort(); }
+extern "C" void Java_org_j3_mmtk_TraceInterface_getHeaderSize__ () { abort(); }
+extern "C" void Java_org_j3_mmtk_TraceInterface_getHeaderEndOffset__ () { abort(); }
+
Added: vmkit/trunk/mmtk/mmtk-j3/VM.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/mmtk/mmtk-j3/VM.cpp?rev=75904&view=auto
==============================================================================
--- vmkit/trunk/mmtk/mmtk-j3/VM.cpp (added)
+++ vmkit/trunk/mmtk/mmtk-j3/VM.cpp Thu Jul 16 06:26:34 2009
@@ -0,0 +1,42 @@
+//===-------------- VM.cpp - Implementation of the VM class --------------===//
+//
+// The VMKit project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "JavaObject.h"
+#include "JavaThread.h"
+
+using namespace jnjvm;
+
+extern "C" void Java_org_j3_runtime_VM_sysWrite__Lorg_vmmagic_unboxed_Extent_2 () { abort(); }
+extern "C" void Java_org_j3_runtime_VM_sysWrite__Lorg_vmmagic_unboxed_Address_2 () { abort(); }
+extern "C" void Java_org_j3_runtime_VM_sysWrite__F () { abort(); }
+extern "C" void Java_org_j3_runtime_VM_sysWrite__I () { abort(); }
+extern "C" void Java_org_j3_runtime_VM_sysWrite__Ljava_lang_String_2 () { abort(); }
+extern "C" void Java_org_j3_runtime_VM_sysWriteln__ () { abort(); }
+extern "C" void Java_org_j3_runtime_VM_sysWriteln__Ljava_lang_String_2 () { abort(); }
+extern "C" void Java_org_j3_runtime_VM__1assert__ZLjava_lang_String_2 () { abort(); }
+extern "C" void Java_org_j3_runtime_VM_sysExit__I () { abort(); }
+extern "C" void Java_org_j3_runtime_VM_sysFail__Ljava_lang_String_2 () { abort(); }
+
+extern "C" void Java_org_j3_runtime_VM__1assert__Z (bool cond) {
+
+ assert(cond);
+}
+
+extern "C" bool Java_org_j3_runtime_VM_buildFor64Addr__ () {
+ return false;
+}
+
+extern "C" bool Java_org_j3_runtime_VM_buildForIA32__ () {
+ return true;
+}
+
+extern "C" bool Java_org_j3_runtime_VM_verifyAssertions__ () {
+ return true;
+}
+
More information about the vmkit-commits
mailing list