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    }