use of com.jopdesign.common.code.InvokeSite in project jop by jop-devel.
the class InlineHelper method checkCode.
/**
* check the code of the invoked method if it contains instructions which prevent inlining.
*
* @param invoker the method into which the invokee will be inlined.
* @param invokee the invoked method.
* @return true if the code can be inlined and {@link #prepareInlining(MethodInfo, MethodInfo)} will succeed.
*/
private boolean checkCode(MethodInfo invoker, MethodInfo invokee) {
MethodCode code = invokee.getCode();
// Go through code, check for access to fields and invocations
for (InstructionHandle ih : code.getInstructionList(true, false).getInstructionHandles()) {
Instruction instr = ih.getInstruction();
if (instr instanceof InvokeInstruction) {
InvokeSite invokeSite = code.getInvokeSite(ih);
MethodRef ref = invokeSite.getInvokeeRef();
MethodInfo method = ref.getMethodInfo();
if (method == null) {
// TODO perform basic check on classnames if invoked method must already be public?
return false;
}
// invokespecial is somewhat, well, special..
if (invokeSite.isInvokeSpecial()) {
if (checkInvokeSpecial(invoker, invokee, invokeSite, ref.getClassInfo(), method) == CheckResult.SKIP) {
return false;
}
} else {
// check if fields need to be set to public
if (checkNeedsPublic(invoker, invokee, ref.getClassInfo(), method) == CheckResult.SKIP) {
return false;
}
}
} else if (instr instanceof FieldInstruction) {
FieldRef ref = code.getFieldRef(ih);
FieldInfo field = ref.getFieldInfo();
if (field == null) {
// TODO perform basic check on classnames if field is already public?
return false;
}
// check if fields need to be set to public
if (checkNeedsPublic(invoker, invokee, ref.getClassInfo(), field) == CheckResult.SKIP) {
return false;
}
}
}
return true;
}
use of com.jopdesign.common.code.InvokeSite in project jop by jop-devel.
the class InlineHelper method prepareInlining.
/**
* Prepare the invokee for inlining into the invokesite, by widening access restrictions or renaming
* methods to prevent incorrect method resolving.
* <p>
* This may change the code of the invokee, so this needs to be done before inlining the code.
* The CFG of the invokee will be removed.
* </p><p>
* This code assumes that {@link #canInline(CallString, InvokeSite, MethodInfo)} returned true for this invoke.
* </p>
*
* @param invoker the method where the code will be inlined to.
* @param invokee the method to inline.
*/
public void prepareInlining(MethodInfo invoker, MethodInfo invokee) {
MethodCode code = invokee.getCode();
InstructionList il = code.getInstructionList();
for (InstructionHandle ih : il.getInstructionHandles()) {
Instruction instr = ih.getInstruction();
if (instr instanceof InvokeInstruction) {
InvokeSite invokeSite = code.getInvokeSite(ih);
MethodRef ref = invokeSite.getInvokeeRef();
MethodInfo method = ref.getMethodInfo();
// we already checked that everything can be resolved
// nothing special to do for invokespecial here (checkInvokeSpecial only skips, no special return codes)
// check what we need to do
CheckResult rs = checkNeedsPublic(invoker, invokee, ref.getClassInfo(), method);
if (rs == CheckResult.NEEDS_PUBLIC) {
makePublic(method);
}
if (rs == CheckResult.NEEDS_PUBLIC_RENAME) {
if (method.isPrivate()) {
// TODO check the class for invokers, change to invokevirtual
} else {
// if the method is package visible, we need to rename all overriding methods
// too (but not methods from subclasses in different packages which do not override this)
// TODO update overriding methods
// TODO need to update all possible call sites
}
makePublic(method);
throw new AppInfoError("Implement me!");
}
} else if (instr instanceof FieldInstruction) {
FieldRef ref = code.getFieldRef(ih);
FieldInfo field = ref.getFieldInfo();
// we already checked that everything can be resolved
// check if fields need to be set to public
CheckResult rs = checkNeedsPublic(invoker, invokee, ref.getClassInfo(), field);
if (rs == CheckResult.NEEDS_PUBLIC) {
makePublic(field);
}
if (rs == CheckResult.NEEDS_PUBLIC_RENAME) {
throw new AppInfoError("Invalid returncode: renaming of fields not required");
}
}
}
}
use of com.jopdesign.common.code.InvokeSite in project jop by jop-devel.
the class InlineHelper method needsNullpointerCheck.
/**
* Check if an exception must be generated if the 'this' reference is null.
* This test can return false if
* <ul><li>There is no 'this' reference</li>
* <li>The DFA analysis showed that the reference is never null</li>
* <li>The inlined code will always generate an exception anyway</li>
* <li>Generating checks has been disabled by configuration</li>
* </ul>
* <p>
* The callstring does not need to start or to end at the method to optimize. However since the callstring is
* used to check the DFA results if available, the callstring must match what the DFA expects, i.e. if
* the DFA-results and -callstrings are updated during inlining, this callstring must not include inlined
* invokes. Contrariwise if the DFA results are not updated during inline, the callstring must contain already
* inlined invokes.
* </p>
*
* @param callString The callstring including the invokesite of the invokee. The top invokesite does not need to
* refer to an invoke instruction, and the referenced invoker method does not need to
* be the method containing the invoke to inline (e.g. if the invoke to inline has
* been inlined itself). However the callstring needs to match what the DFA expects.
* @param invokee the devirtualized invokee.
* @param analyzeCode if false, skip checking the code of the invokee.
* @return true if a nullpointer check code should be generated.
*/
public boolean needsNullpointerCheck(CallString callString, MethodInfo invokee, boolean analyzeCode) {
if (inlineConfig.skipNullpointerChecks())
return false;
InvokeSite invokeSite = callString.top();
// check if we have a 'this' reference anyway
if (invokeSite.isInvokeStatic() || invokeSite.isJVMCall()) {
return false;
}
// TODO check the DFA results if available
if (jcopter.useDFA()) {
} else if ("<init>".equals(invokee.getShortName())) {
// the NP check in this case (and hope that compilers for languages other than Java do the same..)
return false;
}
if (!analyzeCode) {
return true;
}
// check if the code will always throw an exception anyway (without producing any side effects before throwing)
ValueMapAnalysis analysis = new ValueMapAnalysis(invokee);
analysis.loadParameters();
InstructionList list = invokee.getCode().getInstructionList(true, false);
for (InstructionHandle ih : list.getInstructionHandles()) {
Instruction instr = ih.getInstruction();
if (instr instanceof ConstantPushInstruction || instr instanceof LocalVariableInstruction) {
analysis.transfer(instr);
} else if (instr instanceof GETFIELD || instr instanceof PUTFIELD || instr instanceof INVOKEVIRTUAL || instr instanceof INVOKEINTERFACE || instr instanceof INVOKESPECIAL) {
int down = instr.consumeStack(invokee.getConstantPoolGen());
ValueInfo value = analysis.getValueTable().top(down);
// the same way as the inlined invoke
if (value.isThisReference()) {
return false;
}
break;
} else {
// we ignore all other instructions (for now..)
break;
}
}
return true;
}
use of com.jopdesign.common.code.InvokeSite in project jop by jop-devel.
the class SimpleInliner method optimizeMethod.
@Override
public void optimizeMethod(MethodInfo method) {
InlineData inlineData = new InlineData();
List<InvokeSite> invokes = new ArrayList<InvokeSite>(method.getCode().getInvokeSites());
// we iterate over the invoke sites in a sorted order for the single reason that the DFA cache hack works
// (else the order of the entries in the constantpool can differ)
Collections.sort(invokes, new Comparator<InvokeSite>() {
@Override
public int compare(InvokeSite o1, InvokeSite o2) {
return o1.getInstructionHandle().getPosition() - o2.getInstructionHandle().getPosition();
}
});
for (InvokeSite invoke : invokes) {
// The callstring contains 'original' invokesites from the unmodified callgraph,
// 'invoke' refers to the new invokesite in the modified code
CallString cs = new CallString(invoke);
while (invoke != null) {
countInvokeSites++;
MethodInfo invokee = helper.devirtualize(cs);
if (invokee == null)
break;
countDevirtualized++;
// Preliminary checks
if (checkInvoke(invoke, cs, invokee, inlineData)) {
invoke = performSimpleInline(invoke, invokee, inlineData);
inlineCounter++;
if (inlineData.getInvokeSite() != null) {
cs.push(inlineData.getInvokeSite());
} else {
break;
}
} else {
break;
}
}
}
// update callgraph (?) If we update the callgraph, the callstrings become invalid!
// -> update callgraph only after we finished inlining of a toplevel invokesite;
// collect all invokesites to collapse into toplevel invokesite;
// replace old invokesite with invokesites from inlined code, add edges to not inlined methods
// We could collect all nodes to merge and call callgraph.merge(), but this is not yet implemented.
// Instead we simply rebuild the whole callgraph and all results which use callstrings.
}
use of com.jopdesign.common.code.InvokeSite in project jop by jop-devel.
the class ExecFrequencyProvider method getExecCount.
public long getExecCount(ExecutionContext context) {
CallString cs = context.getCallString();
if (cs.isEmpty()) {
return getExecCount(context.getMethodInfo());
}
// if we have a callstring, we need to start at the beginning of the callstring, then multiply the
// frequencies up to the invoked method along the callstring
long count = getExecCount(cs.first().getInvoker());
for (int i = 0; i < cs.length(); i++) {
InvokeSite is = cs.get(i);
MethodInfo invokee = i + 1 < cs.length() ? cs.get(i + 1).getInvoker() : context.getMethodInfo();
count *= getExecFrequency(is, invokee);
}
return count;
}
Aggregations