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