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.immix;
014    
015    import org.mmtk.plan.*;
016    import org.mmtk.policy.Space;
017    import org.mmtk.policy.immix.ImmixSpace;
018    import org.mmtk.policy.immix.ObjectHeader;
019    import org.mmtk.utility.heap.VMRequest;
020    
021    import org.vmmagic.pragma.*;
022    import org.vmmagic.unboxed.*;
023    
024    /**
025     * This class implements the global state of an immix collector.<p>
026     *
027     * See the PLDI'08 paper by Blackburn and McKinley for a description
028     * of the algorithm: http://doi.acm.org/10.1145/1375581.1375586<p>
029     *
030     * All plans make a clear distinction between <i>global</i> and
031     * <i>thread-local</i> activities, and divides global and local state
032     * into separate class hierarchies.  Global activities must be
033     * synchronized, whereas no synchronization is required for
034     * thread-local activities.  There is a single instance of Plan (or the
035     * appropriate sub-class), and a 1:1 mapping of PlanLocal to "kernel
036     * threads" (aka CPUs or in Jikes RVM, Processors).  Thus instance
037     * methods of PlanLocal allow fast, unsychronized access to functions such as
038     * allocation and collection.<p>
039     *
040     * The global instance defines and manages static resources
041     * (such as memory and virtual memory resources).  This mapping of threads to
042     * instances is crucial to understanding the correctness and
043     * performance properties of MMTk plans.
044     */
045    @Uninterruptible
046    public class Immix extends StopTheWorld {
047    
048      /****************************************************************************
049       * Constants
050       */
051    
052      /****************************************************************************
053       * Class variables
054       */
055    
056      /**
057       *
058       */
059      public static final ImmixSpace immixSpace = new ImmixSpace("immix", VMRequest.create());
060      public static final int IMMIX = immixSpace.getDescriptor();
061    
062      public static final int SCAN_IMMIX = 0;
063      public static final int SCAN_DEFRAG = 1;
064    
065      /****************************************************************************
066       * Instance variables
067       */
068    
069      /**
070       *
071       */
072      public final Trace immixTrace = new Trace(metaDataSpace);
073      /** will the next collection collect the whole heap? */
074      public boolean nextGCWholeHeap = true;
075      /** will this collection collect the whole heap */
076      public boolean collectWholeHeap = nextGCWholeHeap;
077      protected boolean lastGCWasDefrag = false;
078    
079      /**
080       * Constructor.
081       *
082       */
083      public Immix() {
084      }
085    
086      /*****************************************************************************
087       *
088       * Collection
089       */
090    
091      /**
092       * {@inheritDoc}
093       */
094      @Override
095      @Inline
096      public void collectionPhase(short phaseId) {
097        if (phaseId == SET_COLLECTION_KIND) {
098          super.collectionPhase(phaseId);
099          immixSpace.decideWhetherToDefrag(emergencyCollection, collectWholeHeap, collectionAttempt, userTriggeredCollection);
100          return;
101        }
102    
103        if (phaseId == PREPARE) {
104          super.collectionPhase(phaseId);
105          immixTrace.prepare();
106          immixSpace.prepare(true);
107          return;
108        }
109    
110        if (phaseId == CLOSURE) {
111          immixTrace.prepare();
112          return;
113        }
114    
115        if (phaseId == RELEASE) {
116          immixTrace.release();
117          lastGCWasDefrag = immixSpace.release(true);
118          super.collectionPhase(phaseId);
119          return;
120        }
121    
122        super.collectionPhase(phaseId);
123      }
124    
125      @Override
126      public boolean lastCollectionWasExhaustive() {
127        return lastGCWasDefrag;
128      }
129    
130      /*****************************************************************************
131       *
132       * Accounting
133       */
134    
135      /**
136       * Return the number of pages reserved for use given the pending
137       * allocation.  The superclass accounts for its spaces, we just
138       * augment this with the mark-sweep space's contribution.
139       */
140      @Override
141      public int getPagesUsed() {
142        return immixSpace.reservedPages() + super.getPagesUsed();
143      }
144    
145      /**
146       * Return the number of pages reserved for collection.
147       */
148      @Override
149      public int getCollectionReserve() {
150        return super.getCollectionReserve() + immixSpace.defragHeadroomPages();
151      }
152    
153      @Override
154      public boolean willNeverMove(ObjectReference object) {
155        if (Space.isInSpace(IMMIX, object)) {
156          ObjectHeader.pinObject(object);
157          return true;
158        } else
159          return super.willNeverMove(object);
160      }
161    
162      @Override
163      @Interruptible
164      protected void registerSpecializedMethods() {
165        TransitiveClosure.registerSpecializedScan(SCAN_IMMIX, ImmixTraceLocal.class);
166        TransitiveClosure.registerSpecializedScan(SCAN_DEFRAG, ImmixDefragTraceLocal.class);
167        super.registerSpecializedMethods();
168      }
169    }