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.Enumeration; 016 017import org.jikesrvm.VM; 018import org.jikesrvm.adaptive.controller.Controller; 019import org.jikesrvm.adaptive.database.AOSDatabase; 020import org.jikesrvm.adaptive.measurements.instrumentation.Instrumentation; 021import org.jikesrvm.adaptive.measurements.instrumentation.YieldpointCounterData; 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 org.jikesrvm.compilers.opt.ir.Operator; 028import static org.jikesrvm.compilers.opt.ir.Operators.YIELDPOINT_BACKEDGE; 029import static org.jikesrvm.compilers.opt.ir.Operators.YIELDPOINT_EPILOGUE; 030import 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 */ 038public 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() { 060 return "InsertYieldpointCounters"; 061 } 062 063 /** 064 * counters after all yieldpoint instructions 065 * 066 * @param ir the governing IR 067 */ 068 @Override 069 public final void perform(IR ir) { 070 071 // Don't insert counters in uninterruptible methods, 072 // the boot image, or when instrumentation is disabled 073 if (!ir.method.isInterruptible() || 074 ir.method.getDeclaringClass().isInBootImage() || 075 !Instrumentation.instrumentationEnabled()) { 076 return; 077 } 078 079 YieldpointCounterData data = AOSDatabase.yieldpointCounterData; 080 081 if (InsertYieldpointCounters.DEBUG) { 082 VM.sysWrite("InsertYieldpointCounters.perform() " + ir.method + "\n"); 083 } 084 // For each yieldpoint, insert a counter. 085 for (Enumeration<BasicBlock> bbe = ir.getBasicBlocks(); bbe.hasMoreElements();) { 086 BasicBlock bb = bbe.nextElement(); 087 088 if (InsertYieldpointCounters.DEBUG) { 089 VM.sysWrite("Considering basic block " + bb.toString() + "\n"); 090 bb.printExtended(); 091 } 092 093 Instruction i = bb.firstInstruction(); 094 while (i != null && i != bb.lastInstruction()) { 095 096 if (i.operator() == YIELDPOINT_PROLOGUE || 097 i.operator() == YIELDPOINT_EPILOGUE || 098 i.operator() == YIELDPOINT_BACKEDGE) { 099 String prefix = yieldpointPrefix(i.operator()); 100 double incrementValue = 1.0; 101 102 if (i.operator() == YIELDPOINT_EPILOGUE) { 103 prefix = "METHOD ENTRY "; 104 } else if (i.operator() == YIELDPOINT_PROLOGUE) { 105 prefix = "METHOD EXIT "; 106 } else { 107 prefix = "BACKEDGE "; 108 incrementValue = 1.0; 109 } 110 111 // Create an instruction to increment the counter for this 112 // method. By appending the prefix and method name, it 113 // maintains a separate counter for each method, and 114 // separates between method entry and backedges. 115 Instruction counterInst = data. 116 getCounterInstructionForEvent(prefix + ir.method.toString(), incrementValue); 117 118 // Insert the new instruction into the code order 119 i.insertAfter(counterInst); 120 } 121 122 i = i.nextInstructionInCodeOrder(); 123 } 124 } 125 } 126 127 /** 128 * Return a string based version of the passed yieldpoint operator 129 * @param op the yieldpoint operator 130 * @return a string based on the type of yieldpoint operator 131 */ 132 private static String yieldpointPrefix(Operator op) { 133 if (op == YIELDPOINT_PROLOGUE) return "Prologue"; 134 if (op == YIELDPOINT_EPILOGUE) return "Epilogue"; 135 if (op == YIELDPOINT_BACKEDGE) return "Backedge"; 136 return "ERROR"; 137 } 138} 139