001/*
002 *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 *  This file is licensed to You under the Eclipse Public License (EPL);
005 *  You may not use this file except in compliance with the License. You
006 *  may obtain a copy of the License at
007 *
008 *      http://www.opensource.org/licenses/eclipse-1.0.php
009 *
010 *  See the COPYRIGHT.txt file distributed with this work for information
011 *  regarding copyright ownership.
012 */
013package org.mmtk.plan.generational.immix;
014
015import org.mmtk.plan.generational.Gen;
016import org.mmtk.plan.Trace;
017import org.mmtk.plan.TransitiveClosure;
018import org.mmtk.policy.immix.ImmixSpace;
019import org.mmtk.policy.immix.ObjectHeader;
020import org.mmtk.policy.Space;
021import org.mmtk.utility.heap.VMRequest;
022import org.vmmagic.pragma.*;
023import org.vmmagic.unboxed.*;
024
025/**
026 * This class implements the functionality of a two-generation copying
027 * collector where <b>the higher generation is an immix space</b>.
028 *
029 * Nursery collections occur when either the heap is full or the nursery
030 * is full.  The nursery size is determined by an optional command line
031 * argument. If undefined, the nursery size is "infinite", so nursery
032 * collections only occur when the heap is full (this is known as a
033 * flexible-sized nursery collector).  Thus both fixed and flexible
034 * nursery sizes are supported.  Full heap collections occur when the
035 * nursery size has dropped to a statically defined threshold,
036 * <code>NURSERY_THRESHOLD</code><p>
037 *
038 * See the PLDI'08 paper by Blackburn and McKinley for a description
039 * of the algorithm: http://doi.acm.org/10.1145/1375581.1375586<p>
040 *
041 * See the Jones &amp; Lins GC book, chapter 7 for a detailed discussion
042 * of generational collection and section 7.3 for an overview of the
043 * flexible nursery behavior ("The Standard ML of New Jersey
044 * collector"), or go to Appel's paper "Simple generational garbage
045 * collection and fast allocation." SP&amp;E 19(2):171--183, 1989.<p>
046 *
047 *
048 * For general comments about the global/local distinction among classes refer
049 * to Plan.java and PlanLocal.java.
050 */
051@Uninterruptible
052public class GenImmix extends Gen {
053
054  /*****************************************************************************
055   *
056   * Class fields
057   */
058
059  /** The mature space, which for GenImmix uses a mark sweep collection policy. */
060  public static final ImmixSpace immixSpace = new ImmixSpace("immix", false, VMRequest.discontiguous());
061
062  public static final int IMMIX = immixSpace.getDescriptor();
063
064  /** Specialized scanning method identifier */
065  public static final int SCAN_IMMIX = 1;
066
067  /****************************************************************************
068   *
069   * Instance fields
070   */
071
072  /** The trace class for a full-heap collection */
073  public final Trace matureTrace = new Trace(metaDataSpace);
074  private boolean lastGCWasDefrag = false;
075
076  /*****************************************************************************
077   *
078   * Collection
079   */
080
081  /**
082   * {@inheritDoc}
083   */
084  @Inline
085  @Override
086  public final void collectionPhase(short phaseId) {
087    if (phaseId == SET_COLLECTION_KIND) {
088      super.collectionPhase(phaseId);
089      if (gcFullHeap) {
090        immixSpace.decideWhetherToDefrag(emergencyCollection, true, collectionAttempt, userTriggeredCollection);
091      }
092      return;
093    }
094
095    if (traceFullHeap()) {
096      if (phaseId == PREPARE) {
097        super.collectionPhase(phaseId);
098        matureTrace.prepare();
099        immixSpace.prepare(true);
100        return;
101      }
102
103      if (phaseId == CLOSURE) {
104        matureTrace.prepare();
105        return;
106      }
107
108      if (phaseId == RELEASE) {
109        matureTrace.release();
110        lastGCWasDefrag = immixSpace.release(true);
111        super.collectionPhase(phaseId);
112        return;
113      }
114    } else
115      lastGCWasDefrag = false;
116
117    super.collectionPhase(phaseId);
118  }
119
120  @Override
121  public boolean lastCollectionWasExhaustive() {
122    return lastGCWasDefrag;
123  }
124
125  /*****************************************************************************
126   *
127   * Accounting
128   */
129
130  /**
131   * Return the number of pages reserved for use given the pending
132   * allocation.
133   */
134  @Inline
135  @Override
136  public int getPagesUsed() {
137    return immixSpace.reservedPages() + super.getPagesUsed();
138  }
139
140  @Override
141  public int getMaturePhysicalPagesAvail() {
142    return immixSpace.availablePhysicalPages();
143  }
144
145  @Override
146  public int getCollectionReserve() {
147    return super.getCollectionReserve() + immixSpace.defragHeadroomPages();
148  }
149
150  /*****************************************************************************
151   *
152   * Miscellaneous
153   */
154
155  /**
156   * @return The active mature space
157   */
158  @Override
159  @Inline
160  protected final Space activeMatureSpace() {
161    return immixSpace;
162  }
163
164  @Override
165  public boolean willNeverMove(ObjectReference object) {
166    if (Space.isInSpace(IMMIX, object)) {
167      ObjectHeader.pinObject(object);
168      return true;
169    } else
170      return super.willNeverMove(object);
171  }
172
173  @Override
174  @Interruptible
175  protected void registerSpecializedMethods() {
176    TransitiveClosure.registerSpecializedScan(SCAN_IMMIX, GenImmixMatureTraceLocal.class);
177//    TransitiveClosure.registerSpecializedScan(SCAN_DEFRAG, GenImmixMatureDefragTraceLocal.class);
178    super.registerSpecializedMethods();
179  }
180
181  @Override
182  @Interruptible
183  public void preCollectorSpawn() {
184    immixSpace.initializeDefrag();
185  }
186}