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.jikesrvm.compilers.opt.driver;
014    
015    import org.jikesrvm.VM;
016    import org.jikesrvm.compilers.opt.OptOptions;
017    import org.jikesrvm.compilers.opt.OptimizingCompilerException;
018    import 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     */
031    public 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    }