Search in sources :

Example 1 with ReturnInstruction

use of org.apache.bcel.generic.ReturnInstruction in project jop by jop-devel.

the class SimpleInliner method analyzeCodeSize.

/**
     * Check if the resulting code will not be larger than the older code.
     * @param invokeSite the invokesite to inline.
     * @param invokee the invoked method.
     * @param inlineData the map to store the analyzer results
     * @return true if the new code will not violate any size constrains
     */
private boolean analyzeCodeSize(InvokeSite invokeSite, MethodInfo invokee, InlineData inlineData) {
    ProcessorModel pm = AppInfo.getSingleton().getProcessorModel();
    MethodInfo invoker = invokeSite.getInvoker();
    // delta = new prologue + inlined code + epilogue - old prologue - invokesite
    int delta = 0;
    InstructionHandle[] il = invokee.getCode().getInstructionList().getInstructionHandles();
    InstructionHandle ih = il[inlineData.getInlineStart()];
    while (ih != null) {
        Instruction instr = ih.getInstruction();
        if (instr instanceof ReturnInstruction) {
            break;
        }
        delta += pm.getNumberOfBytes(invokee, instr);
        ih = ih.getNext();
    }
    for (InstructionHandle instr : inlineData.getPrologue().getInstructionHandles()) {
        delta += pm.getNumberOfBytes(invoker, instr.getInstruction());
    }
    for (InstructionHandle instr : inlineData.getEpilogue().getInstructionHandles()) {
        delta += pm.getNumberOfBytes(invoker, instr.getInstruction());
    }
    ih = invokeSite.getInstructionHandle();
    for (int i = 0; i <= inlineData.getOldPrologueLength(); i++) {
        Instruction instr = ih.getInstruction();
        delta -= pm.getNumberOfBytes(invoker, instr);
        ih = ih.getPrev();
    }
    // TODO we could allow for some slack, especially if we decreased the codesize before..
    return delta <= 0;
}
Also used : ReturnInstruction(org.apache.bcel.generic.ReturnInstruction) MethodInfo(com.jopdesign.common.MethodInfo) ProcessorModel(com.jopdesign.common.processormodel.ProcessorModel) 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) InstructionHandle(org.apache.bcel.generic.InstructionHandle)

Example 2 with ReturnInstruction

use of org.apache.bcel.generic.ReturnInstruction 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 3 with ReturnInstruction

use of org.apache.bcel.generic.ReturnInstruction in project jop by jop-devel.

the class InstructionInterpreter method getInEdges.

private List<Edge> getInEdges(InstructionList il, InstructionHandle ih) {
    List<Edge> edges = new LinkedList<Edge>();
    InstructionHandle prev = ih.getPrev();
    if (prev != null) {
        // check if we can fall through from prev instruction
        Instruction instr = prev.getInstruction();
        if (!(instr instanceof UnconditionalBranch || instr instanceof Select || instr instanceof ReturnInstruction)) {
            if (instr instanceof BranchInstruction) {
                edges.add(new Edge(prev, ih, EdgeType.FALSE_EDGE));
            } else {
                edges.add(new Edge(prev, ih, EdgeType.NORMAL_EDGE));
            }
        }
    }
    // flow graph explicitly
    for (InstructionHandle targeter = il.getStart(); targeter != null; targeter = targeter.getNext()) {
        //      for the instruction for the exception handler
        if (!(targeter.getInstruction() instanceof BranchInstruction))
            continue;
        BranchInstruction bi = (BranchInstruction) targeter.getInstruction();
        if (bi.containsTarget(ih)) {
            edges.add(new Edge(targeter, ih, EdgeType.TRUE_EDGE));
        }
    }
    return edges;
}
Also used : ReturnInstruction(org.apache.bcel.generic.ReturnInstruction) UnconditionalBranch(org.apache.bcel.generic.UnconditionalBranch) BranchInstruction(org.apache.bcel.generic.BranchInstruction) Select(org.apache.bcel.generic.Select) BranchInstruction(org.apache.bcel.generic.BranchInstruction) Instruction(org.apache.bcel.generic.Instruction) ReturnInstruction(org.apache.bcel.generic.ReturnInstruction) LinkedList(java.util.LinkedList) InstructionHandle(org.apache.bcel.generic.InstructionHandle)

Example 4 with ReturnInstruction

use of org.apache.bcel.generic.ReturnInstruction in project jop by jop-devel.

the class InstructionInterpreter method getOutEdges.

private List<Edge> getOutEdges(InstructionHandle ih) {
    List<Edge> edges = new LinkedList<Edge>();
    Instruction instr = ih.getInstruction();
    if (instr instanceof BranchInstruction) {
        if (instr instanceof Select) {
            Select s = (Select) instr;
            InstructionHandle[] target = s.getTargets();
            for (InstructionHandle aTarget : target) {
                edges.add(new Edge(ih, aTarget, EdgeType.TRUE_EDGE));
            }
            edges.add(new Edge(ih, s.getTarget(), EdgeType.FALSE_EDGE));
        } else {
            BranchInstruction b = (BranchInstruction) instr;
            edges.add(new Edge(ih, b.getTarget(), EdgeType.TRUE_EDGE));
        }
    }
    // Check if we can fall through to the next instruction
    if (ih.getNext() != null && !(instr instanceof UnconditionalBranch || instr instanceof Select || instr instanceof ReturnInstruction)) {
        if (instr instanceof BranchInstruction) {
            edges.add(new Edge(ih, ih.getNext(), EdgeType.FALSE_EDGE));
        } else {
            edges.add(new Edge(ih, ih.getNext(), EdgeType.NORMAL_EDGE));
        }
    }
    if (instr instanceof ReturnInstruction) {
        edges.add(new Edge(ih, getExitInstruction(), EdgeType.EXIT_EDGE));
    }
    if (instr instanceof ATHROW) {
    // TODO should we handle this somehow? Insert edges to the exception handlers or to an return-by-exception
    //      exit instruction?
    // for now, just ignore them
    }
    //      but for now, we just ignore them too.. in a safe way :)
    if (instr instanceof RET || instr instanceof JSR || instr instanceof JSR_W) {
        throw new JavaClassFormatError("Unsupported instruction " + instr + " in " + methodInfo);
    }
    return edges;
}
Also used : RET(org.apache.bcel.generic.RET) UnconditionalBranch(org.apache.bcel.generic.UnconditionalBranch) BranchInstruction(org.apache.bcel.generic.BranchInstruction) JSR(org.apache.bcel.generic.JSR) ATHROW(org.apache.bcel.generic.ATHROW) BranchInstruction(org.apache.bcel.generic.BranchInstruction) Instruction(org.apache.bcel.generic.Instruction) ReturnInstruction(org.apache.bcel.generic.ReturnInstruction) LinkedList(java.util.LinkedList) InstructionHandle(org.apache.bcel.generic.InstructionHandle) ReturnInstruction(org.apache.bcel.generic.ReturnInstruction) JavaClassFormatError(com.jopdesign.common.misc.JavaClassFormatError) Select(org.apache.bcel.generic.Select) JSR_W(org.apache.bcel.generic.JSR_W)

Example 5 with ReturnInstruction

use of org.apache.bcel.generic.ReturnInstruction 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)

Aggregations

InstructionHandle (org.apache.bcel.generic.InstructionHandle)6 ReturnInstruction (org.apache.bcel.generic.ReturnInstruction)6 Instruction (org.apache.bcel.generic.Instruction)5 BranchInstruction (org.apache.bcel.generic.BranchInstruction)3 InstructionList (org.apache.bcel.generic.InstructionList)3 Select (org.apache.bcel.generic.Select)3 UnconditionalBranch (org.apache.bcel.generic.UnconditionalBranch)3 MethodCode (com.jopdesign.common.MethodCode)2 MethodInfo (com.jopdesign.common.MethodInfo)2 LinkedList (java.util.LinkedList)2 ArithmeticInstruction (org.apache.bcel.generic.ArithmeticInstruction)2 ConversionInstruction (org.apache.bcel.generic.ConversionInstruction)2 FieldInstruction (org.apache.bcel.generic.FieldInstruction)2 InvokeInstruction (org.apache.bcel.generic.InvokeInstruction)2 NOP (org.apache.bcel.generic.NOP)2 PushInstruction (org.apache.bcel.generic.PushInstruction)2 StackInstruction (org.apache.bcel.generic.StackInstruction)2 InvokeSite (com.jopdesign.common.code.InvokeSite)1 JavaClassFormatError (com.jopdesign.common.misc.JavaClassFormatError)1 ProcessorModel (com.jopdesign.common.processormodel.ProcessorModel)1