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.adaptive.recompilation.instrumentation;
014    
015    import java.util.Enumeration;
016    
017    import org.jikesrvm.VM;
018    import org.jikesrvm.adaptive.controller.Controller;
019    import org.jikesrvm.adaptive.database.AOSDatabase;
020    import org.jikesrvm.adaptive.measurements.instrumentation.Instrumentation;
021    import org.jikesrvm.adaptive.measurements.instrumentation.YieldpointCounterData;
022    import org.jikesrvm.compilers.opt.OptOptions;
023    import org.jikesrvm.compilers.opt.driver.CompilerPhase;
024    import org.jikesrvm.compilers.opt.ir.BasicBlock;
025    import org.jikesrvm.compilers.opt.ir.IR;
026    import org.jikesrvm.compilers.opt.ir.Instruction;
027    import org.jikesrvm.compilers.opt.ir.Operator;
028    import static org.jikesrvm.compilers.opt.ir.Operators.YIELDPOINT_BACKEDGE;
029    import static org.jikesrvm.compilers.opt.ir.Operators.YIELDPOINT_EPILOGUE;
030    import static org.jikesrvm.compilers.opt.ir.Operators.YIELDPOINT_PROLOGUE;
031    
032    /**
033     * An opt compiler phase that inserts yieldpoint counters.  Searches
034     * for all yieldpoint instructions and inserts an increment after
035     * them, using the CounterArrayManager counter manager to implement
036     * the counters.
037     */
038    public class InsertYieldpointCounters extends CompilerPhase {
039    
040      static final boolean DEBUG = false;
041    
042      /**
043       * Return this instance of this phase. This phase contains no
044       * per-compilation instance fields.
045       * @param ir not used
046       * @return this
047       */
048      @Override
049      public CompilerPhase newExecution(IR ir) {
050        return this;
051      }
052    
053      @Override
054      public final boolean shouldPerform(OptOptions options) {
055        return Controller.options.INSERT_YIELDPOINT_COUNTERS;
056      }
057    
058      @Override
059      public final String getName() { return "InsertYieldpointCounters"; }
060    
061      /**
062       * counters after all yieldpoint instructions
063       *
064       * @param ir the governing IR
065       */
066      @Override
067      public final void perform(IR ir) {
068    
069        // Don't insert counters in uninterruptible methods,
070        // the boot image, or when instrumentation is disabled
071        if (!ir.method.isInterruptible() ||
072            ir.method.getDeclaringClass().isInBootImage() ||
073            !Instrumentation.instrumentationEnabled()) {
074          return;
075        }
076    
077        YieldpointCounterData data = AOSDatabase.yieldpointCounterData;
078    
079        if (InsertYieldpointCounters.DEBUG) {
080          VM.sysWrite("InsertYieldpointCounters.perform() " + ir.method + "\n");
081        }
082        // For each yieldpoint, insert a counter.
083        for (Enumeration<BasicBlock> bbe = ir.getBasicBlocks(); bbe.hasMoreElements();) {
084          BasicBlock bb = bbe.nextElement();
085    
086          if (InsertYieldpointCounters.DEBUG) {
087            VM.sysWrite("Considering basic block " + bb.toString() + "\n");
088            bb.printExtended();
089          }
090    
091          Instruction i = bb.firstInstruction();
092          while (i != null && i != bb.lastInstruction()) {
093    
094            if (i.operator() == YIELDPOINT_PROLOGUE ||
095                i.operator() == YIELDPOINT_EPILOGUE ||
096                i.operator() == YIELDPOINT_BACKEDGE) {
097              String prefix = yieldpointPrefix(i.operator());
098              double incrementValue = 1.0;
099    
100              if (i.operator() == YIELDPOINT_EPILOGUE) {
101                prefix = "METHOD ENTRY ";
102              } else if (i.operator() == YIELDPOINT_PROLOGUE) {
103                prefix = "METHOD EXIT ";
104              } else {
105                prefix = "BACKEDGE ";
106                incrementValue = 1.0;
107              }
108    
109              // Create an instruction to increment the counter for this
110              // method.  By appending the prefix and method name, it
111              // maintains a separate counter for each method, and
112              // separates between method entry and backedges.
113              Instruction counterInst = data.
114                  getCounterInstructionForEvent(prefix + ir.method.toString(), incrementValue);
115    
116              // Insert the new instruction into the code order
117              i.insertAfter(counterInst);
118            }
119    
120            i = i.nextInstructionInCodeOrder();
121          }
122        }
123      }
124    
125      /**
126       * Return a string based version of the passed yieldpoint operator
127       * @param op the yieldpoint operator
128       * @return a string based on the type of yieldpoint operator
129       */
130      private static String yieldpointPrefix(Operator op) {
131        if (op == YIELDPOINT_PROLOGUE) return "Prologue";
132        if (op == YIELDPOINT_EPILOGUE) return "Epilogue";
133        if (op == YIELDPOINT_BACKEDGE) return "Backedge";
134        return "ERROR";
135      }
136    }
137