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.copyms;
014
015import org.mmtk.plan.*;
016import org.mmtk.policy.CopySpace;
017import org.mmtk.policy.MarkSweepSpace;
018import org.mmtk.policy.Space;
019import org.mmtk.utility.heap.VMRequest;
020import org.mmtk.utility.options.Options;
021import org.mmtk.utility.sanitychecker.SanityChecker;
022
023import org.vmmagic.pragma.*;
024import org.vmmagic.unboxed.ObjectReference;
025
026/**
027 * This class implements the global state of a full-heap collector
028 * with a copying nursery and mark-sweep mature space.  Unlike a full
029 * generational collector, there is no write barrier, no remembered set, and
030 * every collection is full-heap.<p>
031 *
032 * All plans make a clear distinction between <i>global</i> and
033 * <i>thread-local</i> activities, and divides global and local state
034 * into separate class hierarchies.  Global activities must be
035 * synchronized, whereas no synchronization is required for
036 * thread-local activities.  There is a single instance of Plan (or the
037 * appropriate sub-class), and a 1:1 mapping of PlanLocal to "kernel
038 * threads" (aka CPUs).  Thus instance
039 * methods of PlanLocal allow fast, unsychronized access to functions such as
040 * allocation and collection.<p>
041 *
042 * The global instance defines and manages static resources
043 * (such as memory and virtual memory resources).  This mapping of threads to
044 * instances is crucial to understanding the correctness and
045 * performance properties of MMTk plans.
046 */
047@Uninterruptible
048public class CopyMS extends StopTheWorld {
049
050  /****************************************************************************
051   * Constants
052   */
053
054  /****************************************************************************
055   * Class variables
056   */
057
058  /**
059   *
060   */
061  public static final CopySpace nurserySpace = new CopySpace("nursery", false, VMRequest.highFraction(0.15f));
062  public static final MarkSweepSpace msSpace = new MarkSweepSpace("ms", VMRequest.discontiguous());
063
064  public static final int NURSERY = nurserySpace.getDescriptor();
065  public static final int MARK_SWEEP = msSpace.getDescriptor();
066
067  public static final int ALLOC_NURSERY = ALLOC_DEFAULT;
068  public static final int ALLOC_MS = StopTheWorld.ALLOCATORS + 1;
069
070  public static final int SCAN_COPYMS = 0;
071
072  /****************************************************************************
073   * Instance variables
074   */
075
076  /**
077   *
078   */
079  public final Trace trace;
080
081  /**
082   * Constructor.
083 */
084  public CopyMS() {
085    trace = new Trace(metaDataSpace);
086  }
087
088
089  /*****************************************************************************
090   * Collection
091   */
092
093  /**
094   * {@inheritDoc}
095   */
096  @Override
097  @Inline
098  public final void collectionPhase(short phaseId) {
099    if (phaseId == PREPARE) {
100      super.collectionPhase(phaseId);
101      trace.prepare();
102      msSpace.prepare(true);
103      nurserySpace.prepare(true);
104      return;
105    }
106    if (phaseId == CLOSURE) {
107      trace.prepare();
108      return;
109    }
110    if (phaseId == RELEASE) {
111      trace.release();
112      msSpace.release();
113      nurserySpace.release();
114      switchNurseryZeroingApproach(nurserySpace);
115      super.collectionPhase(phaseId);
116      return;
117    }
118
119    super.collectionPhase(phaseId);
120  }
121
122  @Override
123  public final boolean collectionRequired(boolean spaceFull, Space space) {
124    boolean nurseryFull = nurserySpace.reservedPages() > Options.nurserySize.getMaxNursery();
125
126    return super.collectionRequired(spaceFull, space) || nurseryFull;
127  }
128
129  /*****************************************************************************
130   *
131   * Accounting
132   */
133
134  /**
135   * {@inheritDoc}
136   */
137  @Override
138  public int getPagesUsed() {
139    return super.getPagesUsed() +
140      msSpace.reservedPages() +
141      nurserySpace.reservedPages();
142  }
143
144  /**
145   * Return the number of pages reserved for collection.
146   * For mark sweep this is a fixed fraction of total pages.
147   */
148  @Override
149  public int getCollectionReserve() {
150    return nurserySpace.reservedPages() + super.getCollectionReserve();
151  }
152
153  /**
154   * @return The number of pages available for allocation, <i>assuming
155   * all future allocation is to the nursery</i>.
156   */
157  @Override
158  public final int getPagesAvail() {
159    return (getTotalPages() - getPagesReserved()) >> 1;
160  }
161
162  @Override
163  public int sanityExpectedRC(ObjectReference object, int sanityRootRC) {
164    Space space = Space.getSpaceForObject(object);
165
166    // Nursery
167    if (space == CopyMS.nurserySpace) {
168      return SanityChecker.DEAD;
169    }
170
171    return space.isReachable(object) ? SanityChecker.ALIVE : SanityChecker.DEAD;
172  }
173
174  @Override
175  @Interruptible
176  protected void registerSpecializedMethods() {
177    TransitiveClosure.registerSpecializedScan(SCAN_COPYMS, CopyMSTraceLocal.class);
178    super.registerSpecializedMethods();
179  }
180
181  @Interruptible
182  @Override
183  public void fullyBooted() {
184    super.fullyBooted();
185    nurserySpace.setZeroingApproach(Options.nurseryZeroing.getNonTemporal(), Options.nurseryZeroing.getConcurrent());
186  }
187}