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.concurrent;
014    
015    import org.mmtk.plan.Phase;
016    import org.mmtk.plan.Simple;
017    import org.mmtk.utility.Log;
018    import org.mmtk.utility.options.ConcurrentTrigger;
019    import org.mmtk.utility.options.Options;
020    
021    import org.vmmagic.pragma.*;
022    
023    /**
024     * This class implements the global state of a concurrent collector.
025     */
026    @Uninterruptible
027    public abstract class Concurrent extends Simple {
028    
029      /****************************************************************************
030       * Constants
031       */
032    
033      /****************************************************************************
034       * Class variables
035       */
036    
037      /**
038       *
039       */
040      public static final short FLUSH_MUTATOR               = Phase.createSimple("flush-mutator", null);
041      public static final short SET_BARRIER_ACTIVE          = Phase.createSimple("set-barrier", null);
042      public static final short FLUSH_COLLECTOR             = Phase.createSimple("flush-collector", null);
043      public static final short CLEAR_BARRIER_ACTIVE        = Phase.createSimple("clear-barrier", null);
044    
045      // CHECKSTYLE:OFF
046    
047      /**
048       * When we preempt a concurrent marking phase we must flush mutators and then continue the closure.
049       */
050      protected static final short preemptConcurrentClosure = Phase.createComplex("preeempt-concurrent-trace", null,
051          Phase.scheduleMutator  (FLUSH_MUTATOR),
052          Phase.scheduleCollector(CLOSURE));
053    
054      public static final short CONCURRENT_CLOSURE = Phase.createConcurrent("concurrent-closure",
055                                                                            Phase.scheduleComplex(preemptConcurrentClosure));
056    
057      /**
058       * Perform the initial determination of liveness from the roots.
059       */
060      protected static final short concurrentClosure = Phase.createComplex("concurrent-mark", null,
061          Phase.scheduleGlobal    (SET_BARRIER_ACTIVE),
062          Phase.scheduleMutator   (SET_BARRIER_ACTIVE),
063          Phase.scheduleCollector (FLUSH_COLLECTOR),
064          Phase.scheduleConcurrent(CONCURRENT_CLOSURE),
065          Phase.scheduleGlobal    (CLEAR_BARRIER_ACTIVE),
066          Phase.scheduleMutator   (CLEAR_BARRIER_ACTIVE));
067    
068      /** Build, validate and then build another sanity table */
069      protected static final short preSanityPhase = Phase.createComplex("sanity", null,
070          Phase.scheduleComplex    (sanityBuildPhase),
071          Phase.scheduleGlobal     (SANITY_SET_PREGC),
072          Phase.scheduleComplex    (sanityCheckPhase),
073          Phase.scheduleComplex    (sanityBuildPhase));
074    
075      /** Validate, build and validate the second sanity table */
076      protected static final short postSanityPhase = Phase.createComplex("sanity", null,
077          Phase.scheduleGlobal     (SANITY_SET_POSTGC),
078          Phase.scheduleComplex    (sanityCheckPhase),
079          Phase.scheduleComplex    (sanityBuildPhase),
080          Phase.scheduleGlobal     (SANITY_SET_PREGC),
081          Phase.scheduleComplex    (sanityCheckPhase));
082    
083      // CHECKSTYLE:OFF
084    
085      /****************************************************************************
086       * Instance variables
087       */
088    
089      /****************************************************************************
090       * Constructor.
091       */
092      public Concurrent() {
093        Options.concurrentTrigger = new ConcurrentTrigger();
094      }
095    
096      /*****************************************************************************
097       *
098       * Collection
099       */
100    
101      /**
102       * {@inheritDoc}
103       */
104      @Override
105      @Interruptible
106      public void processOptions() {
107        super.processOptions();
108    
109        /* Set up the concurrent marking phase */
110        replacePhase(Phase.scheduleCollector(CLOSURE), Phase.scheduleComplex(concurrentClosure));
111    
112        if (Options.sanityCheck.getValue()) {
113          Log.writeln("Collection sanity checking enabled.");
114          replacePhase(Phase.schedulePlaceholder(PRE_SANITY_PLACEHOLDER), Phase.scheduleComplex(preSanityPhase));
115          replacePhase(Phase.schedulePlaceholder(POST_SANITY_PLACEHOLDER), Phase.scheduleComplex(postSanityPhase));
116        }
117      }
118    
119      /****************************************************************************
120       *
121       * Collection
122       */
123    
124      /**
125       *
126       */
127      private boolean inConcurrentCollection = false;
128    
129      @Override
130      @Inline
131      public void collectionPhase(short phaseId) {
132        if (phaseId == SET_BARRIER_ACTIVE) {
133          ConcurrentMutator.newMutatorBarrierActive = true;
134          return;
135        }
136        if (phaseId == CLEAR_BARRIER_ACTIVE) {
137          ConcurrentMutator.newMutatorBarrierActive = false;
138          return;
139        }
140        if (phaseId == CLOSURE) {
141          return;
142        }
143        if (phaseId == PREPARE) {
144          inConcurrentCollection = true;
145        }
146        if (phaseId == RELEASE) {
147          inConcurrentCollection = false;
148        }
149        super.collectionPhase(phaseId);
150      }
151    
152      @Override
153      protected boolean concurrentCollectionRequired() {
154        return !Phase.concurrentPhaseActive() &&
155          ((getPagesReserved() * 100) / getTotalPages()) > Options.concurrentTrigger.getValue();
156      }
157    
158      @Override
159      public boolean lastCollectionFullHeap() {
160        // TODO: Why this?
161        return !inConcurrentCollection;
162      }
163    
164      /*****************************************************************************
165       *
166       * Accounting
167       */
168    }