use of com.jopdesign.common.MethodCode 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.MethodCode 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.MethodCode 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 com.jopdesign.common.MethodCode in project jop by jop-devel.
the class SimpleInliner method performSimpleInline.
/**
* Try to inline a simple getter, wrapper or stub method.
* <p>
* If the inlined code is again an invoke, the InvokeSite does not change because
* the InstructionHandle of the invoker's invoke is kept.</p>
*
* @param invokeSite the invoke to replace.
* @param invokee the method to inline.
* @param inlineData the parameters of the invokee and the code to inline.
* @return true if inlining has been performed.
*/
private InvokeSite performSimpleInline(InvokeSite invokeSite, MethodInfo invokee, InlineData inlineData) {
MethodInfo invoker = invokeSite.getInvoker();
MethodCode invokerCode = invoker.getCode();
if (logger.isDebugEnabled()) {
logger.debug("Inlining at " + invokeSite + " using " + invokee);
}
// Prepare code for the actual inlining
helper.prepareInlining(invoker, invokee);
InstructionHandle invoke = invokeSite.getInstructionHandle();
// Perform inlining: update the prologue
if (inlineData.getOldPrologueLength() > 0) {
InstructionHandle start = invoke;
for (int i = 0; i < inlineData.getOldPrologueLength(); i++) {
start = start.getPrev();
}
// invokeSite is not a target in this case, no need to worry about targets here
invokerCode.replace(start, inlineData.getOldPrologueLength(), inlineData.getPrologue(), false);
} else if (inlineData.getPrologue().getLength() > 0) {
// old-prologue is empty, invokeSite may be a target.. Need to update the targets to the new prologue
if (invoke.hasTargeters()) {
invokerCode.retarget(invoke, inlineData.getPrologue().getStart());
}
InstructionList il = invokerCode.getInstructionList();
il.insert(invoke, inlineData.getPrologue());
}
// Replace the invoke
MethodCode invokeeCode = invokee.getCode();
InstructionList il = invokeeCode.getInstructionList();
InstructionHandle start = invokeeCode.getInstructionHandle(inlineData.getInlineStart());
int cnt = il.getLength() - inlineData.getInlineStart();
if (il.getEnd().getInstruction() instanceof ReturnInstruction) {
// do not inline the return
cnt--;
}
InstructionHandle end = invokerCode.replace(invoke, 1, invokee, start, cnt, true);
// the invokee
if (cnt > 0) {
InstructionHandle ih = end;
for (int i = 0; i < cnt; i++) {
ih = ih.getPrev();
}
invokerCode.setLineNumber(ih, invokeeCode.getSourceClassInfo(start), invokeeCode.getLineNumber(start));
}
// insert epilogue
invokerCode.getInstructionList().insert(end, inlineData.getEpilogue());
// If we inlined another invokesite, find the new invokesite and return it
if (inlineData.getInvokeSite() != null) {
end = end.getPrev();
// search backwards from last inlined instruction
while (end != null) {
if (invokerCode.isInvokeSite(end)) {
return invokerCode.getInvokeSite(end);
}
end = end.getPrev();
}
}
return null;
}
use of com.jopdesign.common.MethodCode in project jop by jop-devel.
the class DFATool method runLocalAnalysis.
public <K, V> Map runLocalAnalysis(Analysis<K, V> localAnalysis, ExecutionContext scope) {
Interpreter<K, V> interpreter = new Interpreter<K, V>(localAnalysis, this);
if (scope == null)
throw new AssertionError("No such method: " + scope);
Context context = new Context();
MethodCode entryCode = scope.getMethodInfo().getCode();
context.stackPtr = entryCode.getMaxLocals();
context.setMethodInfo(scope.getMethodInfo());
context.setCallString(scope.getCallString());
localAnalysis.initialize(scope.getMethodInfo(), context);
/* Here used to be a extremely-hard-to-trackdown bug!
* Without the boolean parameters, getInstructionList() will dispose
* the CFG, a very bad idea during WCET analysis which relies on
* pointer equality for CFG edges :(
*/
InstructionHandle entry = entryCode.getInstructionList(false, false).getStart();
interpreter.interpret(context, entry, new LinkedHashMap<InstructionHandle, ContextMap<K, V>>(), true);
return localAnalysis.getResult();
}
Aggregations