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 */
013 package org.mmtk.plan.generational.copying;
014
015 import org.mmtk.policy.CopySpace;
016 import org.mmtk.policy.Space;
017 import org.mmtk.plan.generational.*;
018 import org.mmtk.plan.Trace;
019 import org.mmtk.plan.TransitiveClosure;
020 import org.mmtk.utility.heap.VMRequest;
021 import org.mmtk.vm.VM;
022
023 import org.vmmagic.pragma.*;
024
025 /**
026 * This class implements the functionality of a standard
027 * two-generation copying collector. Nursery collections occur when
028 * either the heap is full or the nursery is full. The nursery size
029 * is determined by an optional command line argument. If undefined,
030 * the nursery size is "infinite", so nursery collections only occur
031 * when the heap is full (this is known as a flexible-sized nursery
032 * collector). Thus both fixed and flexible nursery sizes are
033 * supported. Full heap collections occur when the nursery size has
034 * dropped to a statically defined threshold,
035 * <code>NURSERY_THRESHOLD</code><p>
036 *
037 * See the Jones & Lins GC book, chapter 7 for a detailed discussion
038 * of generational collection and section 7.3 for an overview of the
039 * flexible nursery behavior ("The Standard ML of New Jersey
040 * collector"), or go to Appel's paper "Simple generational garbage
041 * collection and fast allocation." SP&E 19(2):171--183, 1989.<p>
042 *
043 * All plans make a clear distinction between <i>global</i> and
044 * <i>thread-local</i> activities. Global activities must be
045 * synchronized, whereas no synchronization is required for
046 * thread-local activities. Instances of Plan map 1:1 to "kernel
047 * threads" (aka CPUs). Thus instance
048 * methods allow fast, unsychronized access to Plan utilities such as
049 * allocation and collection. Each instance rests on static resources
050 * (such as memory and virtual memory resources) which are "global"
051 * and therefore "static" members of Plan. This mapping of threads to
052 * instances is crucial to understanding the correctness and
053 * performance proprties of this plan.
054 */
055 @Uninterruptible public class GenCopy extends Gen {
056
057 /****************************************************************************
058 *
059 * Class variables
060 */
061
062 // GC state
063 static boolean hi = false; // True if copying to "higher" semispace
064
065 /**
066 * The low half of the copying mature space. We allocate into this space
067 * when <code>hi</code> is <code>false</code>.
068 */
069 static CopySpace matureSpace0 = new CopySpace("ss0", DEFAULT_POLL_FREQUENCY, false, VMRequest.create());
070 static final int MS0 = matureSpace0.getDescriptor();
071
072 /**
073 * The high half of the copying mature space. We allocate into this space
074 * when <code>hi</code> is <code>true</code>.
075 */
076 static CopySpace matureSpace1 = new CopySpace("ss1", DEFAULT_POLL_FREQUENCY, true, VMRequest.create());
077 static final int MS1 = matureSpace1.getDescriptor();
078
079
080 /****************************************************************************
081 *
082 * Instance fields
083 */
084 final Trace matureTrace;
085
086 /**
087 * Constructor
088 */
089 public GenCopy() {
090 super();
091 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!IGNORE_REMSETS); // Not supported for GenCopy
092 matureTrace = new Trace(metaDataSpace);
093 }
094
095 /**
096 * @return Does the mature space do copying ?
097 */
098 protected boolean copyMature() {
099 return true;
100 }
101
102 /**
103 * @return The semispace we are currently allocating into
104 */
105 static CopySpace toSpace() {
106 return hi ? matureSpace1 : matureSpace0;
107 }
108
109 /**
110 * @return Space descriptor for to-space.
111 */
112 static int toSpaceDesc() { return hi ? MS1 : MS0; }
113
114 /**
115 * @return The semispace we are currently copying from
116 * (or copied from at last major GC)
117 */
118 static CopySpace fromSpace() {
119 return hi ? matureSpace0 : matureSpace1;
120 }
121
122 /**
123 * @return Space descriptor for from-space
124 */
125 static int fromSpaceDesc() { return hi ? MS0 : MS1; }
126
127 /****************************************************************************
128 *
129 * Collection
130 */
131
132 /**
133 * Perform a phase of the currently active collection.
134 *
135 * @param phaseId Collection phase to process
136 */
137 @Inline
138 public void collectionPhase(short phaseId) {
139 if (traceFullHeap()) {
140 if (phaseId == PREPARE) {
141 super.collectionPhase(phaseId);
142 hi = !hi; // flip the semi-spaces
143 matureSpace0.prepare(hi);
144 matureSpace1.prepare(!hi);
145 matureTrace.prepare();
146 return;
147 }
148 if (phaseId == CLOSURE) {
149 matureTrace.prepare();
150 return;
151 }
152 if (phaseId == RELEASE) {
153 matureTrace.release();
154 fromSpace().release();
155 super.collectionPhase(phaseId);
156 return;
157 }
158 }
159 super.collectionPhase(phaseId);
160 }
161
162 /*****************************************************************************
163 *
164 * Accounting
165 */
166
167 /**
168 * Return the number of pages reserved for use given the pending
169 * allocation.
170 *
171 * @return The number of pages reserved given the pending
172 * allocation, excluding space reserved for copying.
173 */
174 @Inline
175 public int getPagesUsed() {
176 return toSpace().reservedPages() + super.getPagesUsed();
177 }
178
179 /**
180 * Return the number of pages reserved for copying.
181 *
182 * @return the number of pages reserved for copying.
183 */
184 public final int getCollectionReserve() {
185 // we must account for the number of pages required for copying,
186 // which equals the number of semi-space pages reserved
187 return toSpace().reservedPages() + super.getCollectionReserve();
188 }
189
190 /**
191 * Calculate the number of pages a collection is required to free to satisfy
192 * outstanding allocation requests.
193 *
194 * @return the number of pages a collection is required to free to satisfy
195 * outstanding allocation requests.
196 */
197 public int getPagesRequired() {
198 return super.getPagesRequired() + (toSpace().requiredPages() << 1);
199 }
200
201 /**
202 * Return the number of pages available for allocation into the mature
203 * space.
204 *
205 * @return The number of pages available for allocation into the mature
206 * space.
207 */
208 public int getMaturePhysicalPagesAvail() {
209 return toSpace().availablePhysicalPages() >> 1;
210 }
211
212 /**************************************************************************
213 * Miscellaneous methods
214 */
215
216 /**
217 * @return The mature space we are currently allocating into
218 */
219 @Inline
220 public Space activeMatureSpace() {
221 return toSpace();
222 }
223
224 /**
225 * Register specialized methods.
226 */
227 @Interruptible
228 protected void registerSpecializedMethods() {
229 TransitiveClosure.registerSpecializedScan(SCAN_MATURE, GenCopyMatureTraceLocal.class);
230 super.registerSpecializedMethods();
231 }
232 }