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.adaptive.recompilation.instrumentation;
014
015import java.util.ArrayList;
016import java.util.Enumeration;
017
018import org.jikesrvm.adaptive.controller.Controller;
019import org.jikesrvm.adaptive.measurements.instrumentation.Instrumentation;
020import org.jikesrvm.adaptive.util.AOSOptions;
021import org.jikesrvm.compilers.opt.InstrumentedEventCounterManager;
022import org.jikesrvm.compilers.opt.OptOptions;
023import org.jikesrvm.compilers.opt.driver.CompilerPhase;
024import org.jikesrvm.compilers.opt.ir.BasicBlock;
025import org.jikesrvm.compilers.opt.ir.IR;
026import org.jikesrvm.compilers.opt.ir.Instruction;
027import 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 */
035public 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() {
065    return "LowerInstrumentation";
066  }
067
068  /**
069   * Finds all instrumented instructions and calls the appropriate code to
070   * convert it into the real sequence of instrumentation instructions.
071   *
072   * @param ir the governing IR
073   */
074  @Override
075  public final void perform(IR ir) {
076    // Convert all instrumentation instructions into actual counter code
077    lowerInstrumentation(ir);
078
079    // TODO: For efficiency, should probably call Simple, or
080    // branch optimizations or something.
081  }
082
083  /**
084   * Actually perform the lowering
085   *
086   * @param ir the governing IR
087   */
088  static void lowerInstrumentation(IR ir) {
089    /*
090    for (Enumeration<BasicBlock> bbe = ir.getBasicBlocks();
091         bbe.hasMoreElements(); ) {
092      BasicBlock bb = bbe.nextElement();
093      bb.printExtended();
094    }
095    */
096
097    ArrayList<Instruction> instrumentedInstructions = new ArrayList<Instruction>();
098
099    // Go through all instructions and find the instrumented ones.  We
100    // put them in instrumentedInstructions and expand them later
101    // because if we expanded them on the fly we mess up the
102    // enumeration.
103    for (Enumeration<BasicBlock> bbe = ir.getBasicBlocks(); bbe.hasMoreElements();) {
104      BasicBlock bb = bbe.nextElement();
105
106      Instruction i = bb.firstInstruction();
107      while (i != null && i != bb.lastInstruction()) {
108
109        if (i.operator() == INSTRUMENTED_EVENT_COUNTER) {
110          instrumentedInstructions.add(i);
111        }
112        i = i.nextInstructionInCodeOrder();
113      }
114    }
115
116    // Now go through the instructions and "lower" them by calling
117    // the counter manager to convert them into real instructions
118    for (final Instruction i : instrumentedInstructions) {
119      // Have the counter manager for this data convert this into the
120      // actual counting code.  For now, we'll hard code the counter
121      // manager.  Ideally it should be stored in the instruction,
122      // (to allow multiple counter managers.  It would also make this
123      // code independent of the adaptive system..)
124      InstrumentedEventCounterManager counterManager = Instrumentation.eventCounterManager;
125
126      counterManager.mutateOptEventCounterInstruction(i, ir);
127    }
128
129    /*
130    for (Enumeration<BasicBlock> bbe = ir.getBasicBlocks();
131         bbe.hasMoreElements(); ) {
132      BasicBlock bb = bbe.nextElement();
133      bb.printExtended();
134    }
135    */
136  } // end of lowerInstrumentation
137
138}