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.ArrayList;
016    import java.util.Enumeration;
017    
018    import org.jikesrvm.adaptive.controller.Controller;
019    import org.jikesrvm.adaptive.measurements.instrumentation.Instrumentation;
020    import org.jikesrvm.adaptive.util.AOSOptions;
021    import org.jikesrvm.compilers.opt.InstrumentedEventCounterManager;
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 static org.jikesrvm.compilers.opt.ir.Operators.INSTRUMENTED_EVENT_COUNTER;
028    
029    /**
030     *  This phase takes converts "instrumentation instructions" that were
031     *  inserted by previous instrumentation phases and "lowers" them,
032     *  converting them to the actual instructions that perform the
033     *  instrumentation.
034     */
035    public class LowerInstrumentation extends CompilerPhase {
036    
037      static final boolean DEBUG = false;
038    
039      /**
040       * Return this instance of this phase. This phase contains no
041       * per-compilation instance fields.
042       * @param ir not used
043       * @return this
044       */
045      @Override
046      public CompilerPhase newExecution(IR ir) {
047        return this;
048      }
049    
050      @Override
051      public final boolean shouldPerform(OptOptions options) {
052        AOSOptions opts = Controller.options;
053        return opts
054            .INSERT_INSTRUCTION_COUNTERS ||
055                                         opts
056                                             .INSERT_METHOD_COUNTERS_OPT ||
057                                                                         opts
058                                                                             .INSERT_DEBUGGING_COUNTERS ||
059                                                                                                        opts
060                                                                                                            .INSERT_YIELDPOINT_COUNTERS;
061      }
062    
063      @Override
064      public final String getName() { return "LowerInstrumentation"; }
065    
066      /**
067       * Finds all instrumented instructions and calls the appropriate code to
068       * convert it into the real sequence of instrumentation instructions.
069       *
070       * @param ir the governing IR
071       */
072      @Override
073      public final void perform(IR ir) {
074        // Convert all instrumentation instructions into actual counter code
075        lowerInstrumentation(ir);
076    
077        // TODO: For efficiency, should probably call Simple, or
078        // branch optimizations or something.
079      }
080    
081      /**
082       * Actually perform the lowering
083       *
084       * @param ir the governing IR
085       */
086      static void lowerInstrumentation(IR ir) {
087        /*
088        for (Enumeration<BasicBlock> bbe = ir.getBasicBlocks();
089             bbe.hasMoreElements(); ) {
090          BasicBlock bb = bbe.nextElement();
091          bb.printExtended();
092        }
093        */
094    
095        ArrayList<Instruction> instrumentedInstructions = new ArrayList<Instruction>();
096    
097        // Go through all instructions and find the instrumented ones.  We
098        // put them in instrumentedInstructions and expand them later
099        // because if we expanded them on the fly we mess up the
100        // enumeration.
101        for (Enumeration<BasicBlock> bbe = ir.getBasicBlocks(); bbe.hasMoreElements();) {
102          BasicBlock bb = bbe.nextElement();
103    
104          Instruction i = bb.firstInstruction();
105          while (i != null && i != bb.lastInstruction()) {
106    
107            if (i.operator() == INSTRUMENTED_EVENT_COUNTER) {
108              instrumentedInstructions.add(i);
109            }
110            i = i.nextInstructionInCodeOrder();
111          }
112        }
113    
114        // Now go through the instructions and "lower" them by calling
115        // the counter manager to convert them into real instructions
116        for (final Instruction i : instrumentedInstructions) {
117          // Have the counter manager for this data convert this into the
118          // actual counting code.  For now, we'll hard code the counter
119          // manager.  Ideally it should be stored in the instruction,
120          // (to allow multiple counter managers.  It would also make this
121          // code independent of the adaptive system..)
122          InstrumentedEventCounterManager counterManager = Instrumentation.eventCounterManager;
123    
124          counterManager.mutateOptEventCounterInstruction(i, ir);
125        }
126    
127        /*
128        for (Enumeration<BasicBlock> bbe = ir.getBasicBlocks();
129             bbe.hasMoreElements(); ) {
130          BasicBlock bb = bbe.nextElement();
131          bb.printExtended();
132        }
133        */
134      } // end of lowerInstrumentation
135    
136    }