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.semispace;
014
015import org.mmtk.policy.CopySpace;
016import org.mmtk.policy.Space;
017import org.mmtk.plan.*;
018import org.mmtk.utility.heap.VMRequest;
019
020import org.vmmagic.pragma.*;
021import org.vmmagic.unboxed.*;
022
023/**
024 * This class implements a simple semi-space collector. See the Jones
025 * & Lins GC book, section 2.2 for an overview of the basic
026 * algorithm. This implementation also includes a large object space
027 * (LOS), and an uncollected "immortal" space.<p>
028 *
029 * All plans make a clear distinction between <i>global</i> and
030 * <i>thread-local</i> activities.  Global activities must be
031 * synchronized, whereas no synchronization is required for
032 * thread-local activities.  Instances of Plan map 1:1 to "kernel
033 * threads" (aka CPUs).  Thus instance
034 * methods allow fast, unsychronized access to Plan utilities such as
035 * allocation and collection.  Each instance rests on static resources
036 * (such as memory and virtual memory resources) which are "global"
037 * and therefore "static" members of Plan.  This mapping of threads to
038 * instances is crucial to understanding the correctness and
039 * performance properties of this plan.
040 */
041@Uninterruptible
042public class SS extends StopTheWorld {
043
044  /****************************************************************************
045   *
046   * Class variables
047   */
048
049  /** {@code true} if allocating into the "higher" semispace */
050  public static boolean hi = false;
051
052  /** One of the two semi spaces that alternate roles at each collection */
053  public static final CopySpace copySpace0 = new CopySpace("ss0", false, VMRequest.discontiguous());
054  public static final int SS0 = copySpace0.getDescriptor();
055
056  /** One of the two semi spaces that alternate roles at each collection */
057  public static final CopySpace copySpace1 = new CopySpace("ss1", true, VMRequest.discontiguous());
058  public static final int SS1 = copySpace1.getDescriptor();
059
060  public final Trace ssTrace;
061
062  /****************************************************************************
063   *
064   * Initialization
065   */
066
067  /**
068   * Class variables
069   */
070
071  /**
072   *
073   */
074  public static final int ALLOC_SS = Plan.ALLOC_DEFAULT;
075
076  public static final int SCAN_SS = 0;
077
078  /**
079   * Constructor
080   */
081  public SS() {
082    ssTrace = new Trace(metaDataSpace);
083  }
084
085  /**
086   * @return The to space for the current collection.
087   */
088  @Inline
089  public static CopySpace toSpace() {
090    return hi ? copySpace1 : copySpace0;
091  }
092
093  /**
094   * @return The from space for the current collection.
095   */
096  @Inline
097  public static CopySpace fromSpace() {
098    return hi ? copySpace0 : copySpace1;
099  }
100
101
102  /****************************************************************************
103   *
104   * Collection
105   */
106
107  /**
108   * {@inheritDoc}
109   */
110  @Override
111  @Inline
112  public void collectionPhase(short phaseId) {
113    if (phaseId == SS.PREPARE) {
114      hi = !hi; // flip the semi-spaces
115      // prepare each of the collected regions
116      copySpace0.prepare(hi);
117      copySpace1.prepare(!hi);
118      ssTrace.prepare();
119      super.collectionPhase(phaseId);
120      return;
121    }
122    if (phaseId == CLOSURE) {
123      ssTrace.prepare();
124      return;
125    }
126    if (phaseId == SS.RELEASE) {
127      // release the collected region
128      fromSpace().release();
129
130      super.collectionPhase(phaseId);
131      return;
132    }
133
134    super.collectionPhase(phaseId);
135  }
136
137  /****************************************************************************
138   *
139   * Accounting
140   */
141
142  /**
143   * Return the number of pages reserved for copying.
144   */
145  @Override
146  public final int getCollectionReserve() {
147    // we must account for the number of pages required for copying,
148    // which equals the number of semi-space pages reserved
149    return toSpace().reservedPages() + super.getCollectionReserve();
150  }
151
152  /**
153   * Return the number of pages reserved for use given the pending
154   * allocation.  This is <i>exclusive of</i> space reserved for
155   * copying.
156   */
157  @Override
158  public int getPagesUsed() {
159    return super.getPagesUsed() + toSpace().reservedPages();
160  }
161
162  /**
163   * Return the number of pages available for allocation, <i>assuming
164   * all future allocation is to the semi-space</i>.
165   *
166   * @return The number of pages available for allocation, <i>assuming
167   * all future allocation is to the semi-space</i>.
168   */
169  @Override
170  public final int getPagesAvail() {
171    return(super.getPagesAvail()) >> 1;
172  }
173
174  @Override
175  public boolean willNeverMove(ObjectReference object) {
176    if (Space.isInSpace(SS0, object) || Space.isInSpace(SS1, object))
177      return false;
178    return super.willNeverMove(object);
179  }
180
181  @Override
182  @Interruptible
183  protected void registerSpecializedMethods() {
184    TransitiveClosure.registerSpecializedScan(SCAN_SS, SSTraceLocal.class);
185    super.registerSpecializedMethods();
186  }
187}