Search in sources :

Example 11 with MethodCode

use of com.jopdesign.common.MethodCode in project jop by jop-devel.

the class DFATool method loadMethod.

private void loadMethod(MethodInfo method) {
    MethodCode mcode = method.getCode();
    // TODO is there a better way to get an instruction handle? Do we need to keep the list somehow?
    InstructionHandle exit;
    exit = (InstructionHandle) method.getCustomValue(KEY_NOP);
    // we reuse the NOP if it exists, so that we can have multiple DFAs running at the same time
    if (exit == null) {
        exit = new InstructionList(new NOP()).getStart();
        // We do not really want to modify the REAL instruction list and append exit
        // (SH) Fixed :) Yep, we need the NOP somewhere, else doInvoke() will collect the wrong result state.
        //      But we can eliminate the NOP by adding the instruction not to the list, but instead to the
        //      MethodInfo, and also retrieve it from there.
        method.setCustomValue(KEY_NOP, exit);
    }
    this.getStatements().add(exit);
    // We do not modify the code, so we leave existing CFGs alone, just make sure the instruction list is uptodate
    InstructionList il = mcode.getInstructionList(true, false);
    // we need correct positions for the DFA cache serialization stuff
    il.setPositions();
    for (Iterator<?> l = il.iterator(); l.hasNext(); ) {
        InstructionHandle handle = (InstructionHandle) l.next();
        this.getStatements().add(handle);
        Instruction instr = handle.getInstruction();
        if (instr instanceof BranchInstruction) {
            if (instr instanceof Select) {
                Select s = (Select) instr;
                InstructionHandle[] target = s.getTargets();
                for (InstructionHandle aTarget : target) {
                    this.getFlow().addEdge(new FlowEdge(handle, aTarget, FlowEdge.TRUE_EDGE));
                }
                this.getFlow().addEdge(new FlowEdge(handle, s.getTarget(), FlowEdge.FALSE_EDGE));
            } else {
                BranchInstruction b = (BranchInstruction) instr;
                this.getFlow().addEdge(new FlowEdge(handle, b.getTarget(), FlowEdge.TRUE_EDGE));
            }
        }
        if (handle.getNext() != null && !(instr instanceof UnconditionalBranch || instr instanceof Select || instr instanceof ReturnInstruction)) {
            if (instr instanceof BranchInstruction) {
                this.getFlow().addEdge(new FlowEdge(handle, handle.getNext(), FlowEdge.FALSE_EDGE));
            } else {
                this.getFlow().addEdge(new FlowEdge(handle, handle.getNext(), FlowEdge.NORMAL_EDGE));
            }
        }
        if (instr instanceof ReturnInstruction) {
            this.getFlow().addEdge(new FlowEdge(handle, exit, FlowEdge.NORMAL_EDGE));
        }
    }
}
Also used : FlowEdge(com.jopdesign.dfa.framework.FlowEdge) ReturnInstruction(org.apache.bcel.generic.ReturnInstruction) UnconditionalBranch(org.apache.bcel.generic.UnconditionalBranch) BranchInstruction(org.apache.bcel.generic.BranchInstruction) InstructionList(org.apache.bcel.generic.InstructionList) Select(org.apache.bcel.generic.Select) MethodCode(com.jopdesign.common.MethodCode) Instruction(org.apache.bcel.generic.Instruction) BranchInstruction(org.apache.bcel.generic.BranchInstruction) ReturnInstruction(org.apache.bcel.generic.ReturnInstruction) InstructionHandle(org.apache.bcel.generic.InstructionHandle) NOP(org.apache.bcel.generic.NOP)

Example 12 with MethodCode

use of com.jopdesign.common.MethodCode 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 13 with MethodCode

use of com.jopdesign.common.MethodCode in project jop by jop-devel.

the class InlineHelper method checkConstraints.

/**
     * Check if inlining is possible under the target code restrictions. This check depends on the caller code,
     * so this check can turn to false if other invokes in the caller are inlined.
     * <p>
     * This does not check the application code size, this must be done by the optimization.
     * </p>
     *
     * @param invoker the method into which the invokee is inlined.
     * @param invokeSite The invoke site. Does not need to refer to an invoke instruction, and does not need to
     *                   refer to the method which will actually contain the invocation (in case of recursive inlining).
     * @param invokee the devirtualized invokee.
     * @param deltaCode size of code inserted or removed from the caller in addition to the inlined method.
     *                  This can include nullpointer checks, other invokes which will be inlined in the caller but have
     *                  not yet been inlined or code to save the stack. This does not include the current invoke instruction
     *                  or the code to be inlined (i.e. if only the invokesite is replaced by the invokee code, this is 0).
     * @param numLocals the number of (live) local variable slots in the caller at the invokesite. This code
     *                  does not check if a local variable assignment is actually possible, i.e. it might be possible
     *                  that although enough slots are available, inlining is not possible due to fragmentation of the
     *                  unused slots in the caller if the callee uses double or long values, so you either need to
     *                  check this yourself or simply pass largest live slot number. Pass 0 to skip this test.
     * @param stackSize Used slots on the stack before the invoke site.
     * @return true if no target size constraints are violated.
     */
public boolean checkConstraints(MethodInfo invoker, InvokeSite invokeSite, MethodInfo invokee, int deltaCode, int numLocals, int stackSize) {
    MethodCode code = invokee.getCode();
    // TODO needed to make sure maxLocals and maxStack is uptodate.. Maybe we can skip this and require the analysis to do that?
    code.compile();
    int codeSize = invoker.getCode().getNumberOfBytes() + code.getNumberOfBytes() + deltaCode;
    if ((maxCodesize > 0 && codeSize > maxCodesize)) {
        return false;
    }
    // check if we have enough local variables available
    if (maxLocals > 0 && numLocals + code.getMaxLocals() > maxLocals) {
        return false;
    }
    if (maxStacksize > 0 && stackSize + code.getMaxStack() > maxStacksize) {
        return false;
    }
    return true;
}
Also used : MethodCode(com.jopdesign.common.MethodCode)

Example 14 with MethodCode

use of com.jopdesign.common.MethodCode 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 15 with MethodCode

use of com.jopdesign.common.MethodCode in project jop by jop-devel.

the class HashTest method main.

public static void main(String[] args) {
    TestFramework test = new TestFramework();
    AppSetup setup = test.setupAppSetup();
    AppInfo appInfo = test.setupAppInfo("common.code.HashTest", false);
    ClassInfo testClass = appInfo.loadClass("common.TestFramework");
    MethodInfo mainMethod = appInfo.getMainMethod();
    MethodCode code = mainMethod.getCode();
    InstructionHandle[] ih = code.getInstructionList().getInstructionHandles();
    InvokeSite i1 = code.getInvokeSite(ih[1]);
    InvokeSite i2 = code.getInvokeSite(ih[2]);
    InvokeSite i3 = code.getInvokeSite(ih[3]);
    InvokeSite i11 = code.getInvokeSite(ih[1]);
    check(i1 == i11);
    CallString c1 = new CallString(i1);
    CallString c2 = new CallString(i2);
    CallString c11 = new CallString(i1);
    check(c1.equals(c11));
    check(!c1.equals(c2));
    ExecutionContext e1 = new ExecutionContext(mainMethod, c1);
    ExecutionContext e2 = new ExecutionContext(mainMethod, c2);
    ExecutionContext e11 = new ExecutionContext(mainMethod, c11);
    check(e1.equals(e11));
    check(!e1.equals(e2));
    // TODO put stuff into maps, check contains() and get()
    // modify instruction list, check if everything still works
    InstructionList il = code.getInstructionList();
    il.insert(new ILOAD(0));
    il.insert(ih[2], new ILOAD(1));
    ih = il.getInstructionHandles();
    InvokeSite i12 = code.getInvokeSite(ih[2]);
    InvokeSite i22 = code.getInvokeSite(ih[4]);
    check(i12 == i1);
    check(i22 == i2);
    check(e1.equals(e11));
    check(!e1.equals(e2));
    il.setPositions();
    check(c1.equals(c11));
    check(!c1.equals(c2));
    check(e1.equals(e11));
    check(!e1.equals(e2));
}
Also used : InstructionList(org.apache.bcel.generic.InstructionList) ILOAD(org.apache.bcel.generic.ILOAD) InstructionHandle(org.apache.bcel.generic.InstructionHandle) AppInfo(com.jopdesign.common.AppInfo) TestFramework(com.jopdesign.common.TestFramework) AppSetup(com.jopdesign.common.AppSetup) MethodInfo(com.jopdesign.common.MethodInfo) MethodCode(com.jopdesign.common.MethodCode) ClassInfo(com.jopdesign.common.ClassInfo)

Aggregations

MethodCode (com.jopdesign.common.MethodCode)15 InstructionHandle (org.apache.bcel.generic.InstructionHandle)12 MethodInfo (com.jopdesign.common.MethodInfo)8 InstructionList (org.apache.bcel.generic.InstructionList)6 ExecutionContext (com.jopdesign.common.code.ExecutionContext)3 InvokeSite (com.jopdesign.common.code.InvokeSite)3 Instruction (org.apache.bcel.generic.Instruction)3 ClassInfo (com.jopdesign.common.ClassInfo)2 FieldInfo (com.jopdesign.common.FieldInfo)2 BasicBlockNode (com.jopdesign.common.code.ControlFlowGraph.BasicBlockNode)2 CFGNode (com.jopdesign.common.code.ControlFlowGraph.CFGNode)2 FieldRef (com.jopdesign.common.type.FieldRef)2 MethodRef (com.jopdesign.common.type.MethodRef)2 Iterator (java.util.Iterator)2 ConstantPushInstruction (org.apache.bcel.generic.ConstantPushInstruction)2 FieldInstruction (org.apache.bcel.generic.FieldInstruction)2 ILOAD (org.apache.bcel.generic.ILOAD)2 InvokeInstruction (org.apache.bcel.generic.InvokeInstruction)2 LocalVariableInstruction (org.apache.bcel.generic.LocalVariableInstruction)2 InstructionFinder (org.apache.bcel.util.InstructionFinder)2