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 */
013package org.mmtk.plan.concurrent;
014
015import org.mmtk.plan.Phase;
016import org.mmtk.plan.Simple;
017import org.mmtk.utility.Log;
018import org.mmtk.utility.options.ConcurrentTrigger;
019import org.mmtk.utility.options.Options;
020
021import org.vmmagic.pragma.*;
022
023/**
024 * This class implements the global state of a concurrent collector.
025 */
026@Uninterruptible
027public 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}