/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* 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/eclipse-1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package org.jikesrvm.compilers.opt.inlining;
import org.jikesrvm.classloader.RVMMethod;
import org.jikesrvm.compilers.opt.OptOptions;
/**
* Instances of this class represent decisions to inline.
*/
public final class InlineDecision {
private enum Code {
/**
* Symbolic constant coding internal state.
*/
DECIDE_NO,
/**
* Symbolic constant coding internal state.
*/
DECIDE_YES,
/**
* Symbolic constant coding internal state.
*/
GUARDED_YES
}
/**
* Rationale for this decision
*/
private final String rationale;
/**
* Holds characterization of this decision.
*/
private final Code code;
/**
* The set of methods to inline.
*/
private final RVMMethod[] targets;
/**
* The set of guards to use (only valid when code == GUARDED_YES)
*/
private final byte[] guards;
/**
* Should the test-failed block be replaced with an OSR point?
*/
private boolean testFailedOSR = false;
/**
* @param targets The methods to inline
* @param code the decision code
* @param reason a string rationale
*/
private InlineDecision(RVMMethod[] targets, byte[] guards, Code code, String reason) {
this.code = code;
this.rationale = reason;
this.targets = targets;
this.guards = guards;
}
/**
* Return a decision NOT to inline.
*
* @param target the method that is not being inlined.
* @param reason a rationale for not inlining
* @return a decision NOT to inline
*/
public static InlineDecision NO(RVMMethod target, String reason) {
RVMMethod[] targets = new RVMMethod[1];
targets[0] = target;
return new InlineDecision(targets, null, Code.DECIDE_NO, reason);
}
/**
* Return a decision NOT to inline.
*
* @param reason a rationale for not inlining
* @return a decision NOT to inline
*/
public static InlineDecision NO(String reason) {
return new InlineDecision(null, null, Code.DECIDE_NO, reason);
}
/**
* Return a decision to inline without a guard.
* @param target the method to inline
* @param reason a rationale for inlining
* @return a decision YES to inline
*/
public static InlineDecision YES(RVMMethod target, String reason) {
RVMMethod[] targets = new RVMMethod[1];
targets[0] = target;
return new InlineDecision(targets, null, Code.DECIDE_YES, reason);
}
/**
* Return a decision YES to do a guarded inline.
*
* @param target the method to inline
* @param guard the type of guard to use
* @param reason a rationale for inlining
* @return a decision YES to inline, but it is not always safe.
*/
public static InlineDecision guardedYES(RVMMethod target, byte guard, String reason) {
RVMMethod[] targets = new RVMMethod[1];
byte[] guards = new byte[1];
targets[0] = target;
guards[0] = guard;
return new InlineDecision(targets, guards, Code.GUARDED_YES, reason);
}
/**
* Return a decision YES to do a guarded inline.
*
* @param targets The methods to inline
* @param guards the types of guard to use
* @param reason A rationale for inlining
* @return a decision YES to inline, but it is not always safe.
*/
public static InlineDecision guardedYES(RVMMethod[] targets, byte[] guards, String reason) {
return new InlineDecision(targets, guards, Code.GUARDED_YES, reason);
}
/**
* Is this inline decision a YES?
*/
public boolean isYES() {
return !isNO();
}
/**
* Is this inline decision a NO?
*/
public boolean isNO() {
return (code == Code.DECIDE_NO);
}
/**
* Does this inline site need a guard?
*/
public boolean needsGuard() {
return (code == Code.GUARDED_YES);
}
/**
* Return the methods to inline according to this decision.
*/
public RVMMethod[] getTargets() {
return targets;
}
/**
* Return the guards to use according to this decision.
*/
public byte[] getGuards() {
return guards;
}
/**
* Return the number methods to inline.
*/
public int getNumberOfTargets() {
if (targets == null) {
return 0;
}
return targets.length;
}
public void setOSRTestFailed() { testFailedOSR = true; }
public boolean OSRTestFailed() { return testFailedOSR; }
public String toString() {
String s = code.toString();
if (testFailedOSR) {
s += "(OSR off-branch)";
}
s += ":" + rationale;
if (targets != null) {
for (int i = 0; i < targets.length; i++) {
s += " " + targets[i];
if (guards != null) {
switch (guards[i]) {
case OptOptions.INLINE_GUARD_METHOD_TEST:
s += " (method test)";
break;
case OptOptions.INLINE_GUARD_CLASS_TEST:
s += " (class test)";
break;
case OptOptions.INLINE_GUARD_CODE_PATCH:
s += " (code patch)";
break;
}
}
}
}
return s;
}
}