use of org.apache.bcel.generic.InstructionHandle in project jop by jop-devel.
the class Interpreter method interpret.
public Map<InstructionHandle, ContextMap<K, V>> interpret(Context context, InstructionHandle entry, Map<InstructionHandle, ContextMap<K, V>> state, boolean start) {
LinkedList<FlowEdge> worklist = new LinkedList<FlowEdge>();
for (FlowEdge f : dfaTool.getFlow().getOutEdges(entry)) {
if (entry.equals(f.getTail())) {
worklist.add(new FlowEdge(f, context));
}
}
Map<InstructionHandle, ContextMap<K, V>> result = state;
if (start) {
for (InstructionHandle s : dfaTool.getStatements()) {
result.put(s, analysis.bottom());
}
result.put(entry, analysis.initial(entry));
}
while (!worklist.isEmpty()) {
FlowEdge edge = worklist.removeFirst();
//System.out.println("computing: "+edge);
InstructionHandle tail = edge.getTail();
InstructionHandle head = edge.getHead();
ContextMap<K, V> tailSet = result.get(tail);
tailSet.setContext(edge.getContext());
ContextMap<K, V> transferred = analysis.transfer(tail, edge, tailSet, this, result);
ContextMap<K, V> headSet = result.get(head);
if (!analysis.compare(transferred, headSet)) {
ContextMap<K, V> joinedSet = analysis.join(headSet, transferred);
result.put(head, joinedSet);
Set<FlowEdge> outEdges = dfaTool.getFlow().getOutEdges(head);
if (outEdges != null) {
for (FlowEdge outEdge : outEdges) {
FlowEdge f = new FlowEdge(outEdge, transferred.getContext());
if (worklist.isEmpty() || !worklist.getFirst().equals(f)) {
if (outEdges.size() > 1)
worklist.addLast(f);
else
worklist.addFirst(f);
//System.out.println("pushing: "+f);
}
}
}
}
//System.out.println("worklist: "+worklist);
}
return result;
}
use of org.apache.bcel.generic.InstructionHandle in project jop by jop-devel.
the class WCETEventHandler method loadLoopAnnotations.
/**
* load annotations for the flow graph.
*
* @param cfg the control flow graph of the method
* @throws BadAnnotationException if an annotations is missing
*/
public void loadLoopAnnotations(ControlFlowGraph cfg) throws BadAnnotationException {
SourceAnnotations wcaMap;
MethodInfo method = cfg.getMethodInfo();
MethodCode code = method.getCode();
ExecutionContext eCtx = new ExecutionContext(cfg.getMethodInfo());
for (CFGNode n : cfg.getLoopColoring().getHeadOfLoops()) {
BasicBlockNode headOfLoop = (BasicBlockNode) n;
BasicBlock block = headOfLoop.getBasicBlock();
// check if loopbound has already been loaded
if (block.getLoopBound() != null) {
// or at least check if the source-annotation is tighter than what is currently set?
continue;
}
Set<LoopBound> bounds = new HashSet<LoopBound>(2);
InstructionHandle first = block.getFirstInstruction();
InstructionHandle last = first;
ClassInfo sourceInfo = method.getCode().getSourceClassInfo(block.getFirstInstruction());
for (InstructionHandle ih : block.getInstructions()) {
ClassInfo cls = method.getCode().getSourceClassInfo(ih);
boolean isLast = ih.equals(block.getLastInstruction());
if (!cls.equals(sourceInfo) || isLast) {
try {
wcaMap = getAnnotations(method.getCode().getSourceClassInfo(block.getFirstInstruction()));
} catch (IOException e) {
throw new BadAnnotationException("IO Error reading annotation: " + e.getMessage(), e);
}
if (isLast) {
last = ih;
}
// search for loop annotation in range
int sourceRangeStart = code.getLineNumber(first);
int sourceRangeStop = code.getLineNumber(last);
bounds.addAll(wcaMap.annotationsForLineRange(sourceRangeStart, sourceRangeStop + 1));
first = ih;
}
last = ih;
}
if (bounds.size() > 1) {
String reason = "Ambiguous Annotation [" + bounds + "]";
throw new BadAnnotationException(reason, code, block);
}
LoopBound loopAnnot = null;
if (bounds.size() == 1) {
loopAnnot = bounds.iterator().next();
}
// if we have loop bounds from DFA analysis, use them
loopAnnot = dfaLoopBound(block, eCtx, loopAnnot);
if (loopAnnot == null) {
// Bit of a hack: if we load CFGs before the callgraph is constructed, this will log errors anyway
if (ignoreMissingLoopBounds) {
logger.trace("No loop bound annotation: " + method + ":" + n + " " + getLineRangeText(code, block) + ".\nApproximating with " + DEFAULT_LOOP_BOUND + ", but result is not safe anymore.");
} else if (project.getCallGraph() != null && !project.getCallGraph().containsMethod(method)) {
logger.debug("No loop bound annotation for non-WCET method: " + method + ":" + n + " " + getLineRangeText(code, block) + ".\nApproximating with " + DEFAULT_LOOP_BOUND);
} else {
logger.error("No loop bound annotation: " + method + ":" + n + " " + getLineRangeText(code, block) + ".\nApproximating with " + DEFAULT_LOOP_BOUND + ", but result is not safe anymore.");
}
loopAnnot = LoopBound.defaultBound(DEFAULT_LOOP_BOUND);
}
block.setLoopBound(loopAnnot);
}
}
use of org.apache.bcel.generic.InstructionHandle in project jop by jop-devel.
the class MethodCacheAnalysis method getReturnMissCount.
public long getReturnMissCount(ExecFrequencyProvider ecp, CodeModification modification) {
if (analysisType == AnalysisType.ALWAYS_HIT)
return 0;
if (analysisType == AnalysisType.ALWAYS_MISS || !allFit(modification.getMethod())) {
// outside all-fit, every invoke returns with a miss
long retCount = 0;
for (InvokeSite invokeSite : modification.getMethod().getCode().getInvokeSites()) {
InstructionHandle ih = invokeSite.getInstructionHandle();
if (modification.getStart().getPosition() <= ih.getPosition() && modification.getEnd().getPosition() >= ih.getPosition()) {
continue;
}
retCount += ecp.getExecFrequency(invokeSite);
}
return ecp.getExecCount(modification.getMethod()) * retCount;
}
if (analysisType == AnalysisType.ALWAYS_MISS_OR_HIT || cache.isLRU()) {
return 0;
}
// we have at most one return miss of invokes in this method
return getPersistentMisses(ecp, callGraph.getNodes(modification.getMethod()));
}
use of org.apache.bcel.generic.InstructionHandle in project jop by jop-devel.
the class InlineOptimizer method findCandidates.
@Override
public Collection<Candidate> findCandidates(MethodInfo method, AnalysisManager analyses, StacksizeAnalysis stacksize, int maxLocals, InstructionHandle start, InstructionHandle end) {
List<Candidate> candidates = new LinkedList<Candidate>();
MethodCode code = method.getCode();
InstructionHandle next = end.getNext();
for (InstructionHandle ih = start; ih != next; ih = ih.getNext()) {
if (code.isInvokeSite(ih)) {
InvokeSite site = code.getInvokeSite(ih);
// since we update the appInfo callgraph, the callstring only contains the invokesite and no
// inlined methods
CallString cs = new CallString(site);
countInvokeSites++;
MethodInfo invokee = helper.devirtualize(cs);
if (invokee == null)
continue;
countDevirtualized++;
// for the initial check and the DFA lookup we need the old callstring
cs = getInlineCallString(code, ih).push(site);
Candidate candidate = checkInvoke(code, cs, site, invokee, maxLocals);
if (candidate == null) {
continue;
}
// initial check for locals and stack, calculate gain and codesize
if (!candidate.recalculate(analyses, stacksize)) {
continue;
}
candidates.add(candidate);
}
}
return candidates;
}
use of org.apache.bcel.generic.InstructionHandle in project jop by jop-devel.
the class SimpleInliner method analyzeInvokeSite.
/**
* Check if the invokesite can be modified in a way so that the parameters are passed in the correct order
* @param invokeSite the invokesite to inline.
* @param invokee the invoked method.
* @param inlineData the map to store the analyzer results
* @return true if the prologue can be changed to match the expected behaviour
*/
private boolean analyzeInvokeSite(InvokeSite invokeSite, MethodInfo invokee, InlineData inlineData) {
MethodInfo invoker = invokeSite.getInvoker();
ConstantPoolGen invokerCpg = invoker.getConstantPoolGen();
InstructionHandle invoke = invokeSite.getInstructionHandle();
// Check epilogue
Type[] ret = StackHelper.produceStack(invokerCpg, invoke.getInstruction());
// works if the invoked method returns the same (single) type as the replaced instruction..
boolean match = (ret.length == 1 && TypeHelper.canAssign(invokee.getType(), ret[0]));
// return something but doesn't then it is a JVM call and throws an exception.
if (!match && !invokee.getType().equals(Type.VOID)) {
return false;
}
// Check and build prologue
Type[] args = StackHelper.consumeStack(invokerCpg, invoke.getInstruction());
List<Instruction> oldPrologue = new LinkedList<Instruction>();
int cnt = 0;
InstructionHandle current = invoke;
while (cnt < args.length) {
if (current.hasTargeters()) {
// stay within the basic block
break;
}
current = current.getPrev();
Instruction instr = current.getInstruction();
// we only rearrange push-instructions
if (!(instr instanceof PushInstruction) || (instr instanceof DUP) || (instr instanceof DUP2)) {
break;
}
// we add this instruction to the old prologue to replace
cnt++;
oldPrologue.add(0, instr);
}
inlineData.setOldPrologueLength(cnt);
List<ValueInfo> params = inlineData.getParams();
// other parameters must be used in the order they are pushed on the stack, we do not rearrange them
int offset = args.length - cnt;
for (int i = 0; i < offset; i++) {
if (i >= params.size()) {
Type t = args[i];
// unused argument, we cannot remove the push instruction so we pop it
inlineData.addPrologue(t.getSize() == 2 ? new POP2() : new POP());
} else {
ValueInfo value = params.get(i);
int argNum = value.getParamNr();
if (!invokee.isStatic()) {
argNum++;
}
if (argNum != i) {
return false;
}
}
}
// Now, we create a new prologue using the expected argument values and the old push instructions
for (int i = offset; i < params.size(); i++) {
ValueInfo value = params.get(i);
if (value.isThisReference() || value.isParamReference()) {
int argNum = value.getParamNr();
if (!invokee.isStatic()) {
argNum++;
}
if (argNum < offset) {
// loading a param a second time which we do not duplicate, cannot inline this
return false;
}
// To be on the safe side, copy the instruction in case a param is used more than once
Instruction instr = oldPrologue.get(argNum - offset).copy();
inlineData.addPrologue(instr);
} else if (value.isNullReference()) {
inlineData.addPrologue(InstructionConstants.ACONST_NULL);
} else if (value.isConstantValue() || value.isStaticFieldReference()) {
// We need to push a constant on the stack
Instruction instr = value.getConstantValue().createPushInstruction(invoker.getConstantPoolGen());
inlineData.addPrologue(instr);
} else if (!value.isContinued()) {
throw new AssertionError("Unhandled value type");
}
}
return true;
}
Aggregations