Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

...

 

Code Block
titleMS.java
themeConfluence
linenumberstrue
languagejava
public static final MarkSweepSpace msSpace = new MarkSweepSpace("ms", VMRequest.create());
public static final int MARK_SWEEP = msSpace.getDescriptor();

In this code fragment, we see the MS plan defined.  Note that we generally also define a static final space descriptor.  This is an optimization that allows some rapid operations on spaces.

Space is a global object, shared among multiple mutator threads.  Each policy will also have one or more thread-local classes which provide unsynchronized allocation.  These classes are subclasses of org.mmtk.utility.alloc.Allocator, and in the case of MarkSweep, it is called MarkSweepLocal.  Instances of MarkSweepLocal are created as part of a mutator context, like this

Code Block
titleMSMutator.java
linenumberstrue
languagejava
protected MarkSweepLocal ms = new MarkSweepLocal(MS.msSpace);

The design pattern is that the local Allocator will allocate space from a thread-local buffer, and when that is exhausted it will allocate a new buffer from the global Space, performing appropriate locking.  The constructor of the MarkSweepLocal specifies the space from which the allocator will allocate global memory.

...

Code Block
titleMSMutator.java
linenumberstrue
languagejava
public Address alloc(int bytes, int align, int offset, int allocator, int site) {
  if (allocator == MS.ALLOC_DEFAULT) {
    return ms.alloc(bytes, align, offset);
  }
  return super.alloc(bytes, align, offset, allocator, site);
}

...

 

Code Block
titleAllocator.java (simplified)
linenumberstrue
languagejava
public final Address allocSlowInline(int bytes, int alignment, int offset) {
  boolean emergencyCollection = false;
  while (true) {
    Address result = allocSlowOnce(bytes, alignment, offset);
    if (!result.isZero()) {
      return result;
    }
    if (emergencyCollection) {
      VM.collection.outOfMemory();
    }
    emergencyCollection = Plan.isEmergencyCollection();
  }
}

This code fragment shows the retry logic in the allocator.  We try allocating using allocSlowOnce, which may recycle partially-used blocks and eventually call Space.acquire.  If a GC occurred, we try again.  Eventually the plan will request an emergency collection which will (for example) cause soft references to be dropped.  If this fails we throw an OutOfMemoryError.

...

Code Block
titleParallelCollector
linenumberstrue
languagejava
public void run() {
  while(true) {
    park();
    collect();
  }
}

...

Code Block
titleStopTheWorldCollector
linenumberstrue
languagejava
public void collect() {
  Phase.beginNewPhaseStack(Phase.scheduleComplex(global().collection));
}

...

Code Block
titleSimple.java
linenumberstrue
languagejava
public static final short SET_COLLECTION_KIND = Phase.createSimple("set-collection-kind", null);
public static final short INITIATE            = Phase.createSimple("initiate", null);
public static final short PREPARE             = Phase.createSimple("prepare");
...

...

Code Block
titleSimple.java
linenumberstrue
languagejava
/** Ensure stacks are ready to be scanned */
protected static final short prepareStacks = Phase.createComplex("prepare-stacks", null,
    Phase.scheduleMutator    (PREPARE_STACKS),
    Phase.scheduleGlobal     (PREPARE_STACKS));

...

The actual work of a collection phase is done (as mentioned above) in the collectionPhase method of the major Plan classes.

Code Block
titleMS.java
linenumberstrue
languagejava
@Inline
@Override
public void collectionPhase(short phaseId) {
  if (phaseId == PREPARE) {
    super.collectionPhase(phaseId);
    msTrace.prepare();
    msSpace.prepare(true);
    return;
  }
  if (phaseId == CLOSURE) {
    msTrace.prepare();
    return;
  }
  if (phaseId == RELEASE) {
    msTrace.release();
    msSpace.release();
    super.collectionPhase(phaseId);
    return;
  }
  super.collectionPhase(phaseId);
}

...

Code Block
titleMSCollector.java
linenumberstrue
languagejava
public void collectionPhase(short phaseId, boolean primary) {
  ...
  if (phaseId == MS.CLOSURE) {
    fullTrace.completeTrace();
    return;
  }
  ...
}

...