use of com.jopdesign.common.MethodInfo 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.MethodInfo 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.MethodInfo in project jop by jop-devel.
the class DFACallgraphBuilder method getInvokedMethods.
@Override
protected Set<MethodInfo> getInvokedMethods(ExecutionContext context, InvokeSite invokeSite) {
// to avoid problems we only use the DFA for virtual calls, all other can be uniquely resolved anyway.
if (!invokeSite.isVirtual()) {
return Collections.singleton(invokeSite.getInvokeeRef().getMethodInfo());
}
Set<String> receivers = dfaTool.getReceivers(invokeSite.getInstructionHandle(), context.getCallString());
if (receivers == null) {
// This can happen e.g. because we have all Runnable.run() methods as roots, regardless if they are used
logger.debug("No receivers for " + invokeSite.getInvokeeRef() + " at " + invokeSite + " in call context " + context.getCallString().toStringVerbose(false));
return appInfo.findImplementations(invokeSite, context.getCallString());
}
if (receivers.size() == 0) {
// This can happen if a method is analyzed for some contexts but not for this context
logger.debug("No receivers for " + invokeSite.getInvokeeRef() + " at " + invokeSite + " in call context " + context.getCallString().toStringVerbose(false));
return appInfo.findImplementations(invokeSite, context.getCallString());
}
Set<MethodInfo> methods = new LinkedHashSet<MethodInfo>(receivers.size());
for (String rcv : receivers) {
MemberID mId = MemberID.parse(rcv);
methods.add(appInfo.getMethodRef(mId).getMethodInfo());
}
return methods;
}
use of com.jopdesign.common.MethodInfo in project jop by jop-devel.
the class PhaseExecutor method removeDebugAttributes.
public void removeDebugAttributes() {
logger.info("Starting removal of debug attributes");
MethodVisitor visitor = new MethodVisitor() {
@Override
public void visitMethod(MethodInfo method) {
method.getCode().removeDebugAttributes();
}
};
appInfo.iterate(new MethodTraverser(visitor, true));
logger.info("Finished removal of debug attributes");
}
use of com.jopdesign.common.MethodInfo in project jop by jop-devel.
the class ExecFrequencyAnalysis method getExecFrequency.
public long getExecFrequency(ExecutionContext context, InstructionHandle ih) {
MethodInfo method = context.getMethodInfo();
// By loading the CFG, loopbounds are attached to the blocks if the WCA tool is loaded
ControlFlowGraph cfg = method.getCode().getControlFlowGraph(false);
LoopColoring<CFGNode, CFGEdge> lc = cfg.getLoopColoring();
BasicBlockNode node = cfg.getHandleNode(ih, true);
if (node == null) {
// THIS IS UNSAFE! but what can you do ...
return 1;
}
long ef = 1;
for (CFGNode hol : lc.getLoopColor(node)) {
LoopBound lb = hol.getLoopBound();
if (lb != null) {
if (lb.isDefaultBound() && !analyses.isWCAMethod(method)) {
ef *= DEFAULT_ACET_LOOP_BOUND;
} else {
ef *= lb.getUpperBound(context);
}
} else {
ef *= DEFAULT_ACET_LOOP_BOUND;
}
}
return ef;
}
Aggregations