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;
014
015import org.mmtk.utility.statistics.Timer;
016import org.mmtk.utility.Log;
017import org.mmtk.vm.VM;
018
019import org.vmmagic.pragma.*;
020
021/**
022 * Phases of a garbage collection.<p>
023 *
024 * A complex phase is a sequence of phases.
025 *
026 */
027@Uninterruptible
028public final class ComplexPhase extends Phase {
029
030  /****************************************************************************
031   * Instance fields
032   */
033
034  /**
035   * The phases that comprise this phase.
036   */
037  private final int[] scheduledSubPhases;
038
039  /**
040   * Construct a complex phase from an array of phase IDs.
041   *
042   * @param name The name of the phase.
043   * @param scheduledSubPhases The sub phases
044   */
045  protected ComplexPhase(String name, int[] scheduledSubPhases) {
046    super(name);
047    this.scheduledSubPhases = scheduledSubPhases;
048    checkPhases();
049  }
050
051  /**
052   * Construct a complex phase from an array of phase IDs, but using
053   * the specified timer rather than creating one.
054   *
055   * @param name The name of the phase.
056   * @param timer The timer for this phase to contribute to.
057   * @param scheduledSubPhases The sub phases
058   */
059  protected ComplexPhase(String name, Timer timer, int[] scheduledSubPhases) {
060    super(name, timer);
061    this.scheduledSubPhases = scheduledSubPhases;
062    checkPhases();
063  }
064
065  /**
066   * Validate the scheduled sub phases.
067   */
068  private void checkPhases() {
069    if (VM.VERIFY_ASSERTIONS) {
070      VM.assertions._assert(scheduledSubPhases.length > 0);
071      for (int scheduledPhase: scheduledSubPhases) {
072        VM.assertions._assert(getSchedule(scheduledPhase) > 0);
073        VM.assertions._assert(getPhaseId(scheduledPhase) > 0);
074      }
075    }
076  }
077
078  /**
079   * @return the number of scheduled sub phases.
080   */
081  protected int count() {
082    return scheduledSubPhases.length;
083  }
084
085  /**
086   * Return an individual scheduled sub phase.
087   *
088   * @param index The index
089   * @return The scheduled phase.
090   */
091  protected int get(int index) {
092    return scheduledSubPhases[index];
093  }
094
095  @Override
096  protected void logPhase() {
097    Log.write("ComplexPhase(");
098    Log.write(name);
099    Log.write(", < ");
100    for (int subPhase : scheduledSubPhases) {
101      short ordering = getSchedule(subPhase);
102      short phaseId = getPhaseId(subPhase);
103      Log.write(getScheduleName(ordering));
104      Log.write("(");
105      Log.write(getName(phaseId));
106      Log.write(") ");
107    }
108    Log.write(">)");
109  }
110
111  /**
112   * Replace a scheduled phase. Used for example to replace a placeholder.
113   *
114   * @param oldScheduledPhase The scheduled phase to replace.
115   * @param newScheduledPhase The new scheduled phase.
116   */
117  public void replacePhase(int oldScheduledPhase, int newScheduledPhase) {
118    for (int i = 0; i < scheduledSubPhases.length; i++) {
119      int scheduledPhase = scheduledSubPhases[i];
120      if (scheduledPhase == oldScheduledPhase) {
121        /* Replace */
122        scheduledSubPhases[i] = newScheduledPhase;
123      } else if (getSchedule(scheduledPhase) == SCHEDULE_COMPLEX) {
124        /* Recurse */
125        ComplexPhase p = (ComplexPhase)getPhase(getPhaseId(scheduledPhase));
126        p.replacePhase(oldScheduledPhase, newScheduledPhase);
127      }
128    }
129  }
130}