Search in sources :

Example 81 with InstructionHandle

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;
}
Also used : LinkedList(java.util.LinkedList) InstructionHandle(org.apache.bcel.generic.InstructionHandle)

Example 82 with InstructionHandle

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);
    }
}
Also used : CFGNode(com.jopdesign.common.code.ControlFlowGraph.CFGNode) BasicBlockNode(com.jopdesign.common.code.ControlFlowGraph.BasicBlockNode) LoopBound(com.jopdesign.common.code.LoopBound) BasicBlock(com.jopdesign.common.code.BasicBlock) IOException(java.io.IOException) InstructionHandle(org.apache.bcel.generic.InstructionHandle) ExecutionContext(com.jopdesign.common.code.ExecutionContext) MethodInfo(com.jopdesign.common.MethodInfo) BadAnnotationException(com.jopdesign.wcet.annotations.BadAnnotationException) MethodCode(com.jopdesign.common.MethodCode) SourceAnnotations(com.jopdesign.wcet.annotations.SourceAnnotations) HashSet(java.util.HashSet) ClassInfo(com.jopdesign.common.ClassInfo)

Example 83 with InstructionHandle

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()));
}
Also used : InvokeSite(com.jopdesign.common.code.InvokeSite) InstructionHandle(org.apache.bcel.generic.InstructionHandle)

Example 84 with InstructionHandle

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;
}
Also used : Candidate(com.jopdesign.jcopter.greedy.Candidate) MethodInfo(com.jopdesign.common.MethodInfo) InvokeSite(com.jopdesign.common.code.InvokeSite) MethodCode(com.jopdesign.common.MethodCode) LinkedList(java.util.LinkedList) InstructionHandle(org.apache.bcel.generic.InstructionHandle) CallString(com.jopdesign.common.code.CallString)

Example 85 with InstructionHandle

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;
}
Also used : POP2(org.apache.bcel.generic.POP2) InvokeInstruction(org.apache.bcel.generic.InvokeInstruction) StackInstruction(org.apache.bcel.generic.StackInstruction) Instruction(org.apache.bcel.generic.Instruction) FieldInstruction(org.apache.bcel.generic.FieldInstruction) ArithmeticInstruction(org.apache.bcel.generic.ArithmeticInstruction) ConversionInstruction(org.apache.bcel.generic.ConversionInstruction) ReturnInstruction(org.apache.bcel.generic.ReturnInstruction) PushInstruction(org.apache.bcel.generic.PushInstruction) PushInstruction(org.apache.bcel.generic.PushInstruction) InstructionHandle(org.apache.bcel.generic.InstructionHandle) LinkedList(java.util.LinkedList) POP(org.apache.bcel.generic.POP) ConstantPoolGen(org.apache.bcel.generic.ConstantPoolGen) Type(org.apache.bcel.generic.Type) DUP2(org.apache.bcel.generic.DUP2) ValueInfo(com.jopdesign.common.type.ValueInfo) MethodInfo(com.jopdesign.common.MethodInfo) DUP(org.apache.bcel.generic.DUP)

Aggregations

InstructionHandle (org.apache.bcel.generic.InstructionHandle)103 InstructionList (org.apache.bcel.generic.InstructionList)26 MethodInfo (com.jopdesign.common.MethodInfo)20 CallString (com.jopdesign.common.code.CallString)20 Instruction (org.apache.bcel.generic.Instruction)13 MethodCode (com.jopdesign.common.MethodCode)12 ContextMap (com.jopdesign.dfa.framework.ContextMap)11 IntermediateEdge (org.candle.decompiler.intermediate.graph.edge.IntermediateEdge)11 Context (com.jopdesign.dfa.framework.Context)10 InvokeInstruction (org.apache.bcel.generic.InvokeInstruction)10 Iterator (java.util.Iterator)9 BranchInstruction (org.apache.bcel.generic.BranchInstruction)9 FieldInstruction (org.apache.bcel.generic.FieldInstruction)9 AbstractIntermediate (org.candle.decompiler.intermediate.code.AbstractIntermediate)9 ReturnInstruction (org.apache.bcel.generic.ReturnInstruction)8 InstructionFinder (org.apache.bcel.util.InstructionFinder)8 ClassInfo (com.jopdesign.common.ClassInfo)7 HashMap (java.util.HashMap)7 HashSet (java.util.HashSet)7 LinkedList (java.util.LinkedList)7