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 }