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