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