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.immix;
014
015import org.mmtk.plan.*;
016import org.mmtk.policy.Space;
017import org.mmtk.policy.immix.ImmixSpace;
018import org.mmtk.policy.immix.ObjectHeader;
019import org.mmtk.utility.heap.VMRequest;
020
021import org.vmmagic.pragma.*;
022import org.vmmagic.unboxed.*;
023
024/**
025 * This class implements the global state of an immix collector.<p>
026 *
027 * See the PLDI'08 paper by Blackburn and McKinley for a description
028 * of the algorithm: http://doi.acm.org/10.1145/1375581.1375586<p>
029 *
030 * All plans make a clear distinction between <i>global</i> and
031 * <i>thread-local</i> activities, and divides global and local state
032 * into separate class hierarchies.  Global activities must be
033 * synchronized, whereas no synchronization is required for
034 * thread-local activities.  There is a single instance of Plan (or the
035 * appropriate sub-class), and a 1:1 mapping of PlanLocal to "kernel
036 * threads" (aka CPUs or in Jikes RVM, Processors).  Thus instance
037 * methods of PlanLocal allow fast, unsychronized access to functions such as
038 * allocation and collection.<p>
039 *
040 * The global instance defines and manages static resources
041 * (such as memory and virtual memory resources).  This mapping of threads to
042 * instances is crucial to understanding the correctness and
043 * performance properties of MMTk plans.
044 */
045@Uninterruptible
046public class Immix extends StopTheWorld {
047
048  /****************************************************************************
049   * Constants
050   */
051
052  /****************************************************************************
053   * Class variables
054   */
055
056  /**
057   *
058   */
059  public static final ImmixSpace immixSpace = new ImmixSpace("immix", VMRequest.discontiguous());
060  public static final int IMMIX = immixSpace.getDescriptor();
061
062  public static final int SCAN_IMMIX = 0;
063  public static final int SCAN_DEFRAG = 1;
064
065  /****************************************************************************
066   * Instance variables
067   */
068
069  /**
070   *
071   */
072  public final Trace immixTrace = new Trace(metaDataSpace);
073  /** will the next collection collect the whole heap? */
074  public boolean nextGCWholeHeap = true;
075  /** will this collection collect the whole heap */
076  public boolean collectWholeHeap = nextGCWholeHeap;
077  protected boolean lastGCWasDefrag = false;
078
079  /**
080   * Constructor.
081   *
082   */
083  public Immix() {
084  }
085
086  /*****************************************************************************
087   *
088   * Collection
089   */
090
091  /**
092   * {@inheritDoc}
093   */
094  @Override
095  @Inline
096  public void collectionPhase(short phaseId) {
097    if (phaseId == SET_COLLECTION_KIND) {
098      super.collectionPhase(phaseId);
099      immixSpace.decideWhetherToDefrag(emergencyCollection, collectWholeHeap, collectionAttempt, userTriggeredCollection);
100      return;
101    }
102
103    if (phaseId == PREPARE) {
104      super.collectionPhase(phaseId);
105      immixTrace.prepare();
106      immixSpace.prepare(true);
107      return;
108    }
109
110    if (phaseId == CLOSURE) {
111      immixTrace.prepare();
112      return;
113    }
114
115    if (phaseId == RELEASE) {
116      immixTrace.release();
117      lastGCWasDefrag = immixSpace.release(true);
118      super.collectionPhase(phaseId);
119      return;
120    }
121
122    super.collectionPhase(phaseId);
123  }
124
125  @Override
126  public boolean lastCollectionWasExhaustive() {
127    return lastGCWasDefrag;
128  }
129
130  /*****************************************************************************
131   *
132   * Accounting
133   */
134
135  /**
136   * Return the number of pages reserved for use given the pending
137   * allocation.  The superclass accounts for its spaces, we just
138   * augment this with the mark-sweep space's contribution.
139   */
140  @Override
141  public int getPagesUsed() {
142    return immixSpace.reservedPages() + super.getPagesUsed();
143  }
144
145  /**
146   * Return the number of pages reserved for collection.
147   */
148  @Override
149  public int getCollectionReserve() {
150    return super.getCollectionReserve() + immixSpace.defragHeadroomPages();
151  }
152
153  @Override
154  public boolean willNeverMove(ObjectReference object) {
155    if (Space.isInSpace(IMMIX, object)) {
156      ObjectHeader.pinObject(object);
157      return true;
158    } else
159      return super.willNeverMove(object);
160  }
161
162  @Override
163  @Interruptible
164  protected void registerSpecializedMethods() {
165    TransitiveClosure.registerSpecializedScan(SCAN_IMMIX, ImmixTraceLocal.class);
166    TransitiveClosure.registerSpecializedScan(SCAN_DEFRAG, ImmixDefragTraceLocal.class);
167    super.registerSpecializedMethods();
168  }
169
170  @Override
171  @Interruptible
172  public void preCollectorSpawn() {
173    immixSpace.initializeDefrag();
174  }
175}