Search in sources :

Example 1 with MethodCode

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;
}
Also used : InvokeInstruction(org.apache.bcel.generic.InvokeInstruction) MethodRef(com.jopdesign.common.type.MethodRef) FieldRef(com.jopdesign.common.type.FieldRef) MethodInfo(com.jopdesign.common.MethodInfo) InvokeSite(com.jopdesign.common.code.InvokeSite) FieldInstruction(org.apache.bcel.generic.FieldInstruction) MethodCode(com.jopdesign.common.MethodCode) InvokeInstruction(org.apache.bcel.generic.InvokeInstruction) ConstantPushInstruction(org.apache.bcel.generic.ConstantPushInstruction) Instruction(org.apache.bcel.generic.Instruction) FieldInstruction(org.apache.bcel.generic.FieldInstruction) LocalVariableInstruction(org.apache.bcel.generic.LocalVariableInstruction) InstructionHandle(org.apache.bcel.generic.InstructionHandle) FieldInfo(com.jopdesign.common.FieldInfo)

Example 2 with MethodCode

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");
            }
        }
    }
}
Also used : FieldRef(com.jopdesign.common.type.FieldRef) InstructionList(org.apache.bcel.generic.InstructionList) InvokeInstruction(org.apache.bcel.generic.InvokeInstruction) ConstantPushInstruction(org.apache.bcel.generic.ConstantPushInstruction) Instruction(org.apache.bcel.generic.Instruction) FieldInstruction(org.apache.bcel.generic.FieldInstruction) LocalVariableInstruction(org.apache.bcel.generic.LocalVariableInstruction) InstructionHandle(org.apache.bcel.generic.InstructionHandle) AppInfoError(com.jopdesign.common.misc.AppInfoError) InvokeInstruction(org.apache.bcel.generic.InvokeInstruction) MethodRef(com.jopdesign.common.type.MethodRef) MethodInfo(com.jopdesign.common.MethodInfo) InvokeSite(com.jopdesign.common.code.InvokeSite) FieldInstruction(org.apache.bcel.generic.FieldInstruction) MethodCode(com.jopdesign.common.MethodCode) FieldInfo(com.jopdesign.common.FieldInfo)

Example 3 with MethodCode

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();
}
Also used : CFGNode(com.jopdesign.common.code.ControlFlowGraph.CFGNode) BasicBlockNode(com.jopdesign.common.code.ControlFlowGraph.BasicBlockNode) ContextEdge(com.jopdesign.common.code.CallGraph.ContextEdge) InstructionHandle(org.apache.bcel.generic.InstructionHandle) NodeVisitor(com.jopdesign.common.graphutils.NodeVisitor) ExecutionContext(com.jopdesign.common.code.ExecutionContext) ControlFlowGraph(com.jopdesign.common.code.ControlFlowGraph) InvokeNode(com.jopdesign.common.code.ControlFlowGraph.InvokeNode) TopologicalTraverser(com.jopdesign.common.graphutils.TopologicalTraverser) MethodInfo(com.jopdesign.common.MethodInfo) MethodCode(com.jopdesign.common.MethodCode)

Example 4 with MethodCode

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

Example 5 with MethodCode

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();
}
Also used : Context(com.jopdesign.dfa.framework.Context) ExecutionContext(com.jopdesign.common.code.ExecutionContext) Interpreter(com.jopdesign.dfa.framework.Interpreter) MethodCode(com.jopdesign.common.MethodCode) InstructionHandle(org.apache.bcel.generic.InstructionHandle) ContextMap(com.jopdesign.dfa.framework.ContextMap)

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