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.jikesrvm.compilers.opt.driver;
014
015import org.jikesrvm.VM;
016import org.jikesrvm.compilers.opt.OptOptions;
017import org.jikesrvm.compilers.opt.OptimizingCompilerException;
018import org.jikesrvm.compilers.opt.ir.IR;
019
020/**
021 * An element in the opt compiler's optimization plan
022 * that aggregates together other OptimizationPlan elements.
023 * <p>
024 * NOTE: Instances of subclasses of this class are
025 *       held in OptimizationPlanner.masterPlan
026 *       and thus represent global state.
027 *       It is therefore incorrect for any per-compilation
028 *       state to be stored in an instance field of
029 *       one of these objects.
030 */
031public class OptimizationPlanCompositeElement extends OptimizationPlanElement {
032  /**
033   * Name of this element.
034   */
035  private final String myName;
036  /**
037   * Ordered list of elements that together comprise this element.
038   */
039  private final OptimizationPlanElement[] myElements;
040
041  /**
042   * Compose together the argument elements into a composite element
043   * of an optimization plan.
044   *
045   * @param   n     The name for this phase
046   * @param   e     The elements to compose
047   */
048  public OptimizationPlanCompositeElement(String n, OptimizationPlanElement[] e) {
049    myName = n;
050    myElements = e;
051  }
052
053  /**
054   * Compose together the argument elements into a composite element
055   * of an optimization plan.
056   *
057   * @param   n     The name for this phase
058   * @param   e     The elements to compose
059   */
060  public OptimizationPlanCompositeElement(String n, Object[] e) {
061    myName = n;
062    myElements = new OptimizationPlanElement[e.length];
063    for (int i = 0; i < e.length; i++) {
064      if (e[i] instanceof OptimizationPlanElement) {
065        myElements[i] = (OptimizationPlanElement) (e[i]);
066      } else if (e[i] instanceof CompilerPhase) {
067        myElements[i] = new OptimizationPlanAtomicElement((CompilerPhase) e[i]);
068      } else {
069        throw new OptimizingCompilerException("Unsupported plan element " + e[i]);
070      }
071    }
072  }
073
074  @Override
075  public void initializeForMeasureCompilation() {
076    // initialize each composite object
077    for (OptimizationPlanElement myElement : myElements) {
078      myElement.initializeForMeasureCompilation();
079    }
080  }
081
082  /**
083   * Compose together the argument elements into a composite element
084   * of an optimization plan.
085   *
086   * @param name The name associated with this composite.
087   * @param elems An Object[] of CompilerPhases or
088   *              OptimizationPlanElements to be composed
089   * @return an OptimizationPlanCompositeElement that
090   *         represents the composition.
091   */
092  public static OptimizationPlanCompositeElement compose(String name, Object[] elems) {
093    return new OptimizationPlanCompositeElement(name, elems);
094  }
095
096  @Override
097  public boolean shouldPerform(OptOptions options) {
098    for (OptimizationPlanElement myElement : myElements) {
099      if (myElement.shouldPerform(options)) {
100        return true;
101      }
102    }
103    return false;
104  }
105
106  /**
107   * Returns true if the phase wants the IR dumped before and/or after it runs.
108   * By default, printing is not enabled.
109   * Subclasses should overide this method if they want to provide IR dumping.
110   *
111   * @param options the compiler options for the compilation
112   * @param before true when invoked before perform, false otherwise.
113   * @return {@code true} if the IR should be printed, {@code false} otherwise.
114   */
115  public boolean printingEnabled(OptOptions options, boolean before) {
116    return false;
117  }
118
119  @Override
120  public final void perform(IR ir) {
121    if (printingEnabled(ir.options, true)) {
122      if (!ir.options.hasMETHOD_TO_PRINT() || ir.options.fuzzyMatchMETHOD_TO_PRINT(ir.method.toString())) {
123        CompilerPhase.dumpIR(ir, "Before " + getName());
124      }
125    }
126
127    for (OptimizationPlanElement myElement : myElements) {
128      if (myElement.shouldPerform(ir.options)) {
129        myElement.perform(ir);
130      }
131    }
132
133    if (printingEnabled(ir.options, false)) {
134      if (!ir.options.hasMETHOD_TO_PRINT() || ir.options.fuzzyMatchMETHOD_TO_PRINT(ir.method.toString())) {
135        CompilerPhase.dumpIR(ir, "After " + getName());
136      }
137    }
138  }
139
140  @Override
141  public String getName() {
142    return myName;
143  }
144
145  @Override
146  public final void reportStats(int indent, int timeCol, double totalTime) {
147    double myTime = elapsedTime();
148    if (myTime < 0.000001) {
149      return;
150    }
151    // (1) Print header.
152    int curCol = 0;
153    for (curCol = 0; curCol < indent; curCol++) {
154      VM.sysWrite(" ");
155    }
156    int myNamePtr = 0;
157    while (curCol < timeCol && myNamePtr < myName.length()) {
158      VM.sysWrite(myName.charAt(myNamePtr));
159      myNamePtr++;
160      curCol++;
161    }
162    VM.sysWrite("\n");
163    // (2) print elements
164    for (OptimizationPlanElement myElement : myElements) {
165      myElement.reportStats(indent + 4, timeCol, totalTime);
166    }
167    // (3) print total
168    curCol = 0;
169    for (curCol = 0; curCol < indent + 4; curCol++) {
170      VM.sysWrite(" ");
171    }
172    VM.sysWrite("TOTAL ");
173    curCol += 6;
174    while (curCol < timeCol) {
175      VM.sysWrite(" ");
176      curCol++;
177    }
178    prettyPrintTime(myTime, totalTime);
179    VM.sysWriteln();
180  }
181
182  @Override
183  public double elapsedTime() {
184    double total = 0.0;
185    for (OptimizationPlanElement myElement : myElements) {
186      total += myElement.elapsedTime();
187    }
188    return total;
189  }
190}