use of org.apache.bcel.generic.InstructionHandle 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 org.apache.bcel.generic.InstructionHandle 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 org.apache.bcel.generic.InstructionHandle 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 org.apache.bcel.generic.InstructionHandle in project jop by jop-devel.
the class WCAInvoker method updateWCEP.
private void updateWCEP() {
if (!provideWCAExecCount)
return;
execCounts.clear();
for (MethodInfo root : getWcaTargets()) {
execCounts.put(root, 1L);
}
NodeVisitor<ExecutionContext> visitor = new NodeVisitor<ExecutionContext>() {
@Override
public boolean visitNode(ExecutionContext context) {
MethodInfo method = context.getMethodInfo();
MethodCode code = method.getCode();
long ec = getExecCount(method);
// skip methods which are not on the WCET path.. we can ship iterating over the childs too..
if (ec == 0)
return false;
// iterate over all blocks in the CFG, find all invokes and add block execution counts to invokees
ControlFlowGraph cfg = method.getCode().getControlFlowGraph(false);
for (CFGNode node : cfg.getGraph().vertexSet()) {
if (node instanceof InvokeNode) {
InvokeNode inv = (InvokeNode) node;
long ef = getExecFrequency(method, node);
for (MethodInfo invokee : inv.getImplementingMethods()) {
addExecCount(invokee, ec * ef);
}
} else if (node instanceof BasicBlockNode) {
// check if we have a JVM invoke here (or an invoke not in a dedicated node..)
for (InstructionHandle ih : node.getBasicBlock().getInstructions()) {
if (!code.isInvokeSite(ih))
continue;
long ef = getExecFrequency(method, node);
for (MethodInfo invokee : method.getAppInfo().findImplementations(code.getInvokeSite(ih))) {
addExecCount(invokee, ec * ef);
}
}
}
}
return true;
}
};
TopologicalTraverser<ExecutionContext, ContextEdge> topOrder = new TopologicalTraverser<ExecutionContext, ContextEdge>(wcetTool.getCallGraph().getGraph(), visitor);
topOrder.traverse();
}
use of org.apache.bcel.generic.InstructionHandle in project jop by jop-devel.
the class SimpleInliner method analyzeCodeSize.
/**
* Check if the resulting code will not be larger than the older code.
* @param invokeSite the invokesite to inline.
* @param invokee the invoked method.
* @param inlineData the map to store the analyzer results
* @return true if the new code will not violate any size constrains
*/
private boolean analyzeCodeSize(InvokeSite invokeSite, MethodInfo invokee, InlineData inlineData) {
ProcessorModel pm = AppInfo.getSingleton().getProcessorModel();
MethodInfo invoker = invokeSite.getInvoker();
// delta = new prologue + inlined code + epilogue - old prologue - invokesite
int delta = 0;
InstructionHandle[] il = invokee.getCode().getInstructionList().getInstructionHandles();
InstructionHandle ih = il[inlineData.getInlineStart()];
while (ih != null) {
Instruction instr = ih.getInstruction();
if (instr instanceof ReturnInstruction) {
break;
}
delta += pm.getNumberOfBytes(invokee, instr);
ih = ih.getNext();
}
for (InstructionHandle instr : inlineData.getPrologue().getInstructionHandles()) {
delta += pm.getNumberOfBytes(invoker, instr.getInstruction());
}
for (InstructionHandle instr : inlineData.getEpilogue().getInstructionHandles()) {
delta += pm.getNumberOfBytes(invoker, instr.getInstruction());
}
ih = invokeSite.getInstructionHandle();
for (int i = 0; i <= inlineData.getOldPrologueLength(); i++) {
Instruction instr = ih.getInstruction();
delta -= pm.getNumberOfBytes(invoker, instr);
ih = ih.getPrev();
}
// TODO we could allow for some slack, especially if we decreased the codesize before..
return delta <= 0;
}
Aggregations