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.
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
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.
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      public static final ImmixSpace immixSpace = new ImmixSpace("immix", DEFAULT_POLL_FREQUENCY, VMRequest.create());
056      public static final int IMMIX = immixSpace.getDescriptor();
057    
058      public static final int SCAN_IMMIX = 0;
059      public static final int SCAN_DEFRAG = 1;
060    
061      /****************************************************************************
062       * Instance variables
063       */
064    
065      public final Trace immixTrace = new Trace(metaDataSpace);
066      /** will the next collection collect the whole heap? */
067      public boolean nextGCWholeHeap = true;
068      /** will this collection collect the whole heap */
069      public boolean collectWholeHeap = nextGCWholeHeap;
070      protected boolean lastGCWasDefrag = false;
071    
072      /**
073       * Constructor.
074       *
075       */
076      public Immix() {
077      }
078    
079      /*****************************************************************************
080       *
081       * Collection
082       */
083    
084      /**
085       * Perform a (global) collection phase.
086       *
087       * @param phaseId Collection phase to execute.
088       */
089      @Inline
090      public void collectionPhase(short phaseId) {
091        if (phaseId == SET_COLLECTION_KIND) {
092          super.collectionPhase(phaseId);
093          immixSpace.decideWhetherToDefrag(emergencyCollection, collectWholeHeap, collectionAttempt, collectionTrigger);
094          return;
095        }
096    
097        if (phaseId == PREPARE) {
098          super.collectionPhase(phaseId);
099          immixTrace.prepare();
100          immixSpace.prepare(true);
101          return;
102        }
103    
104        if (phaseId == CLOSURE) {
105          immixTrace.prepare();
106          return;
107        }
108    
109        if (phaseId == RELEASE) {
110          immixTrace.release();
111          lastGCWasDefrag = immixSpace.release(true);
112          super.collectionPhase(phaseId);
113          return;
114        }
115    
116        super.collectionPhase(phaseId);
117      }
118    
119      /**
120       * @return Whether last GC was an exhaustive attempt to collect the heap.  For many collectors this is the same as asking whether the last GC was a full heap collection.
121       */
122      @Override
123      public boolean lastCollectionWasExhaustive() {
124        return lastGCWasDefrag;
125      }
126    
127      /*****************************************************************************
128       *
129       * Accounting
130       */
131    
132      /**
133       * Return the number of pages reserved for use given the pending
134       * allocation.  The superclass accounts for its spaces, we just
135       * augment this with the mark-sweep space's contribution.
136       *
137       * @return The number of pages reserved given the pending
138       * allocation, excluding space reserved for copying.
139       */
140      public int getPagesUsed() {
141        return immixSpace.reservedPages() + super.getPagesUsed();
142      }
143    
144      /**
145       * Calculate the number of pages a collection is required to free to satisfy
146       * outstanding allocation requests.
147       *
148       * @return the number of pages a collection is required to free to satisfy
149       * outstanding allocation requests.
150       */
151      public int getPagesRequired() {
152        return super.getPagesRequired() + immixSpace.requiredPages();
153      }
154    
155      /**
156       * @see org.mmtk.plan.Plan#willNeverMove
157       *
158       * @param object Object in question
159       * @return True if the object will never move
160       */
161      @Override
162      public boolean willNeverMove(ObjectReference object) {
163        if (Space.isInSpace(IMMIX, object)) {
164          ObjectHeader.pinObject(object);
165          return true;
166        } else
167          return super.willNeverMove(object);
168      }
169    
170      /**
171       * Register specialized methods.
172       */
173      @Interruptible
174      protected void registerSpecializedMethods() {
175        TransitiveClosure.registerSpecializedScan(SCAN_IMMIX, ImmixTraceLocal.class);
176        TransitiveClosure.registerSpecializedScan(SCAN_DEFRAG, ImmixDefragTraceLocal.class);
177        super.registerSpecializedMethods();
178      }
179    }