/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Common Public License (CPL);
* You may not use this file except in compliance with the License. You
* may obtain a copy of the License at
*
* http://www.opensource.org/licenses/cpl1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package org.jikesrvm.adaptive.recompilation.instrumentation;
import org.jikesrvm.VM;
import org.jikesrvm.adaptive.controller.VM_Controller;
import org.jikesrvm.adaptive.database.VM_AOSDatabase;
import org.jikesrvm.adaptive.measurements.instrumentation.VM_Instrumentation;
import org.jikesrvm.adaptive.measurements.instrumentation.VM_YieldpointCounterData;
import org.jikesrvm.compilers.opt.OPT_CompilerPhase;
import org.jikesrvm.compilers.opt.OPT_Options;
import org.jikesrvm.compilers.opt.ir.OPT_BasicBlock;
import org.jikesrvm.compilers.opt.ir.OPT_BasicBlockEnumeration;
import org.jikesrvm.compilers.opt.ir.OPT_IR;
import org.jikesrvm.compilers.opt.ir.OPT_Instruction;
import org.jikesrvm.compilers.opt.ir.OPT_Operator;
import static org.jikesrvm.compilers.opt.ir.OPT_Operators.YIELDPOINT_BACKEDGE;
import static org.jikesrvm.compilers.opt.ir.OPT_Operators.YIELDPOINT_EPILOGUE;
import static org.jikesrvm.compilers.opt.ir.OPT_Operators.YIELDPOINT_PROLOGUE;
/**
* An opt compiler phase that inserts yieldpoint counters. Searches
* for all yieldpoint instructions and inserts an increment after
* them, using the VM_CounterArrayManager counter manager to implement
* the counters.
*/
public class OPT_InsertYieldpointCounters extends OPT_CompilerPhase {
static final boolean DEBUG = false;
/**
* Return this instance of this phase. This phase contains no
* per-compilation instance fields.
* @param ir not used
* @return this
*/
public OPT_CompilerPhase newExecution(OPT_IR ir) {
return this;
}
public final boolean shouldPerform(OPT_Options options) {
return VM_Controller.options.INSERT_YIELDPOINT_COUNTERS;
}
public final String getName() { return "InsertYieldpointCounters"; }
/**
* counters after all yieldpoint instructions
*
* @param ir the governing IR
*/
public final void perform(OPT_IR ir) {
// Don't insert counters in uninterruptible methods,
// the boot image, or when instrumentation is disabled
if (!ir.method.isInterruptible() ||
ir.method.getDeclaringClass().isInBootImage() ||
!VM_Instrumentation.instrumentationEnabled()) {
return;
}
VM_YieldpointCounterData data = VM_AOSDatabase.yieldpointCounterData;
if (OPT_InsertYieldpointCounters.DEBUG) {
VM.sysWrite("OPT_InsertYieldpointCounters.perform() " + ir.method + "\n");
}
// For each yieldpoint, insert a counter.
for (OPT_BasicBlockEnumeration bbe = ir.getBasicBlocks(); bbe.hasMoreElements();) {
OPT_BasicBlock bb = bbe.next();
if (OPT_InsertYieldpointCounters.DEBUG) {
VM.sysWrite("Considering basic block " + bb.toString() + "\n");
bb.printExtended();
}
OPT_Instruction i = bb.firstInstruction();
while (i != null && i != bb.lastInstruction()) {
if (i.operator() == YIELDPOINT_PROLOGUE ||
i.operator() == YIELDPOINT_EPILOGUE ||
i.operator() == YIELDPOINT_BACKEDGE) {
String prefix = yieldpointPrefix(i.operator());
double incrementValue = 1.0;
if (i.operator() == YIELDPOINT_EPILOGUE) {
prefix = "METHOD ENTRY ";
} else if (i.operator() == YIELDPOINT_PROLOGUE) {
prefix = "METHOD EXIT ";
} else {
prefix = "BACKEDGE ";
incrementValue = 1.0;
}
// Create an instruction to increment the counter for this
// method. By appending the prefix and method name, it
// maintains a separate counter for each method, and
// separates between method entry and backedges.
OPT_Instruction counterInst = data.
getCounterInstructionForEvent(prefix + ir.method.toString(), incrementValue);
// Insert the new instruction into the code order
i.insertAfter(counterInst);
}
i = i.nextInstructionInCodeOrder();
}
}
}
/**
* Return a string based version of the passed yieldpoint operator
* @param op the yieldpoint operator
* @return a string based on the type of yieldpoint operator
*/
private static String yieldpointPrefix(OPT_Operator op) {
if (op == YIELDPOINT_PROLOGUE) return "Prologue";
if (op == YIELDPOINT_EPILOGUE) return "Epilogue";
if (op == YIELDPOINT_BACKEDGE) return "Backedge";
return "ERROR";
}
}