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 properties of this plan.
054     */
055    @Uninterruptible public class GenCopy extends Gen {
056    
057      /****************************************************************************
058       *
059       * Class variables
060       */
061    
062      // GC state
063    
064      /**
065       * <code>true</code> if copying to "higher" semispace
066       */
067      static boolean hi = false;
068    
069      /**
070       * The low half of the copying mature space.  We allocate into this space
071       * when <code>hi</code> is <code>false</code>.
072       */
073      static CopySpace matureSpace0 = new CopySpace("ss0", false, VMRequest.create());
074      static final int MS0 = matureSpace0.getDescriptor();
075    
076      /**
077       * The high half of the copying mature space. We allocate into this space
078       * when <code>hi</code> is <code>true</code>.
079       */
080      static CopySpace matureSpace1 = new CopySpace("ss1", true, VMRequest.create());
081      static final int MS1 = matureSpace1.getDescriptor();
082    
083    
084      /****************************************************************************
085       *
086       * Instance fields
087       */
088    
089      /**
090       *
091       */
092      final Trace matureTrace;
093    
094      /**
095       * Constructor
096       */
097      public GenCopy() {
098        super();
099        if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!IGNORE_REMSETS); // Not supported for GenCopy
100        matureTrace = new Trace(metaDataSpace);
101      }
102    
103      @Override
104      protected boolean copyMature() {
105        return true;
106      }
107    
108      /**
109       * @return The semispace we are currently allocating into
110       */
111      static CopySpace toSpace() {
112        return hi ? matureSpace1 : matureSpace0;
113      }
114    
115      /**
116       * @return Space descriptor for to-space.
117       */
118      static int toSpaceDesc() { return hi ? MS1 : MS0; }
119    
120      /**
121       * @return The semispace we are currently copying from
122       * (or copied from at last major GC)
123       */
124      static CopySpace fromSpace() {
125        return hi ? matureSpace0 : matureSpace1;
126      }
127    
128      /**
129       * @return Space descriptor for from-space
130       */
131      static int fromSpaceDesc() { return hi ? MS0 : MS1; }
132    
133      /****************************************************************************
134       *
135       * Collection
136       */
137    
138      /**
139       * {@inheritDoc}
140       */
141      @Override
142      @Inline
143      public void collectionPhase(short phaseId) {
144        if (traceFullHeap()) {
145          if (phaseId == PREPARE) {
146            super.collectionPhase(phaseId);
147            hi = !hi; // flip the semi-spaces
148            matureSpace0.prepare(hi);
149            matureSpace1.prepare(!hi);
150            matureTrace.prepare();
151            return;
152          }
153          if (phaseId == CLOSURE) {
154            matureTrace.prepare();
155            return;
156          }
157          if (phaseId == RELEASE) {
158            matureTrace.release();
159            fromSpace().release();
160            super.collectionPhase(phaseId);
161            return;
162          }
163        }
164        super.collectionPhase(phaseId);
165      }
166    
167      /*****************************************************************************
168       *
169       * Accounting
170       */
171    
172      /**
173       * Return the number of pages reserved for use given the pending
174       * allocation.
175       */
176      @Override
177      @Inline
178      public int getPagesUsed() {
179        return toSpace().reservedPages() + super.getPagesUsed();
180      }
181    
182      /**
183       * Return the number of pages reserved for copying.
184       *
185       * @return the number of pages reserved for copying.
186       */
187      @Override
188      public final int getCollectionReserve() {
189        // we must account for the number of pages required for copying,
190        // which equals the number of semi-space pages reserved
191        return toSpace().reservedPages() + super.getCollectionReserve();
192      }
193    
194      @Override
195      public int getMaturePhysicalPagesAvail() {
196        return toSpace().availablePhysicalPages() >> 1;
197      }
198    
199      /**************************************************************************
200       * Miscellaneous methods
201       */
202    
203      /**
204       * @return The mature space we are currently allocating into
205       */
206      @Override
207      @Inline
208      public Space activeMatureSpace() {
209        return toSpace();
210      }
211    
212      @Override
213      @Interruptible
214      protected void registerSpecializedMethods() {
215        TransitiveClosure.registerSpecializedScan(SCAN_MATURE, GenCopyMatureTraceLocal.class);
216        super.registerSpecializedMethods();
217      }
218    }