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