Search in sources :

Example 21 with InstructionHandle

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

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

the class ClinitOrder method findDependencies.

private Set<ClassInfo> findDependencies(MethodInfo method, boolean inRec) {
    //		System.out.println("find dep. in "+cli.clazz.getClassName()+":"+mi.getMethod().getName());
    Set<ClassInfo> depends = new HashSet<ClassInfo>();
    if (method.isNative() || method.isAbstract()) {
        // subclasses???? :-(
        return depends;
    }
    ClassInfo classInfo = method.getClassInfo();
    ConstantPoolGen cpoolgen = method.getConstantPoolGen();
    InstructionList il = method.getCode().getInstructionList();
    InstructionFinder f = new InstructionFinder(il);
    // TODO can we encounter an empty instruction list?
    //if(il.getStart() == null) {
    //    return depends;
    //}
    // find instructions that access the constant pool
    // collect all indices to constants in ClassInfo
    String cpInstr = "CPInstruction";
    for (Iterator it = f.search(cpInstr); it.hasNext(); ) {
        InstructionHandle[] match = (InstructionHandle[]) it.next();
        InstructionHandle first = match[0];
        CPInstruction ii = (CPInstruction) first.getInstruction();
        int idx = ii.getIndex();
        Constant co = cpoolgen.getConstant(idx);
        ClassRef classRef = null;
        Set addDepends = null;
        ClassInfo clinfo;
        MethodInfo minfo;
        switch(co.getTag()) {
            case Constants.CONSTANT_Class:
                classRef = classInfo.getConstantInfo(co).getClassRef();
                clinfo = classRef.getClassInfo();
                if (clinfo != null) {
                    minfo = clinfo.getMethodInfo("<init>()V");
                    if (minfo != null) {
                        addDepends = findDependencies(minfo, true);
                    }
                }
                break;
            case Constants.CONSTANT_Fieldref:
            case Constants.CONSTANT_InterfaceMethodref:
                classRef = classInfo.getConstantInfo(co).getClassRef();
                break;
            case Constants.CONSTANT_Methodref:
                ConstantMethodInfo mref = (ConstantMethodInfo) classInfo.getConstantInfo(co);
                classRef = mref.getClassRef();
                minfo = mref.getMethodRef().getMethodInfo();
                if (minfo != null) {
                    addDepends = findDependencies(minfo, true);
                }
                break;
        }
        if (classRef != null) {
            ClassInfo clinf = classRef.getClassInfo();
            if (clinf != null) {
                if (clinf.getMethodInfo(clinitSig) != null) {
                    // don't add myself as dependency
                    if (!clinf.equals(method.getClassInfo())) {
                        depends.add(clinf);
                    }
                }
            }
        }
        if (addDepends != null) {
            for (Object addDepend : addDepends) {
                ClassInfo addCli = (ClassInfo) addDepend;
                if (addCli.equals(method.getClassInfo())) {
                    throw new JavaClassFormatError("cyclic indirect <clinit> dependency");
                }
                depends.add(addCli);
            }
        }
    }
    return depends;
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) ClassRef(com.jopdesign.common.type.ClassRef) InstructionList(org.apache.bcel.generic.InstructionList) Constant(org.apache.bcel.classfile.Constant) InstructionFinder(org.apache.bcel.util.InstructionFinder) InstructionHandle(org.apache.bcel.generic.InstructionHandle) ConstantMethodInfo(com.jopdesign.common.type.ConstantMethodInfo) ConstantPoolGen(org.apache.bcel.generic.ConstantPoolGen) CPInstruction(org.apache.bcel.generic.CPInstruction) JavaClassFormatError(com.jopdesign.common.misc.JavaClassFormatError) Iterator(java.util.Iterator) MethodInfo(com.jopdesign.common.MethodInfo) ConstantMethodInfo(com.jopdesign.common.type.ConstantMethodInfo) HashSet(java.util.HashSet) ClassInfo(com.jopdesign.common.ClassInfo)

Example 23 with InstructionHandle

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

the class ConstantPoolRebuilder method updateMethodGen.

public void updateMethodGen(MethodInfo methodInfo, MethodGen methodGen) {
    methodGen.setConstantPool(newPool);
    if (methodInfo.hasCode()) {
        // update all instructions
        InstructionList il = methodInfo.getCode().getInstructionList();
        class InstructionVisitor extends EmptyVisitor {

            @Override
            public void visitCPInstruction(CPInstruction obj) {
                obj.setIndex(mapIndex(obj.getIndex()));
            }
        }
        InstructionVisitor iv = new InstructionVisitor();
        for (InstructionHandle ih : il.getInstructionHandles()) {
            ih.getInstruction().accept(iv);
        }
        updateAttributes(methodInfo, methodGen.getCodeAttributes());
    }
    updateAttributes(methodInfo, methodGen.getAttributes());
}
Also used : CPInstruction(org.apache.bcel.generic.CPInstruction) InstructionList(org.apache.bcel.generic.InstructionList) InstructionHandle(org.apache.bcel.generic.InstructionHandle) EmptyVisitor(org.apache.bcel.generic.EmptyVisitor)

Example 24 with InstructionHandle

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

the class Segment method synchronizedSegment.

/**
	 * Create an interprocedural segment for a synchronized block. Currently we do
	 * not split basic blocks here, so either you are happy with basic block granularity,
	 * or you split the basic block while loading.
	 * @param targetBlock The block containing the monitorenter instruction
	 * @param monitorEnter The monitor enter instruction
	 * @param callString   The context for the method
	 * @param cfgProvider A control flow graph provider
	 * @param callStringLength Length of the callstrings
	 * @param infeasibles Information about infeasible edges (null if no information available)
	 *
	 * @return a segment representing executions of the synchronized block
	 */
public static Segment synchronizedSegment(ContextCFG ccfg, CFGNode entryNode, InstructionHandle monitorEnter, CFGProvider cfgProvider, int callStringLength, InfeasibleEdgeProvider infeasibles) {
    if (infeasibles == null) {
        infeasibles = InfeasibleEdgeProvider.NO_INFEASIBLES;
    }
    ControlFlowGraph cfg = ccfg.getCfg();
    SuperGraph superGraph = new SuperGraph(cfgProvider, cfg, ccfg.getCallString(), callStringLength, infeasibles);
    ContextCFG rootMethod = superGraph.getRootNode();
    /* lift entry edges */
    Set<SuperGraphEdge> entryEdges = Iterators.addAll(new HashSet<SuperGraphEdge>(), superGraph.liftCFGEdges(rootMethod, cfg.incomingEdgesOf(entryNode)));
    /* find exit blocks (might also be in the same block) */
    /* monitorenter followed bei monitorexit in same block => segment only contains this block */
    Set<CFGEdge> monitorExitEdges = new HashSet<CFGEdge>();
    CFGNode currentNode = entryNode;
    int currentNestingLevel = 1;
    Iterator<InstructionHandle> insIter = currentNode.getBasicBlock().getInstructions().iterator();
    while (insIter.hasNext()) {
        if (insIter.next() == monitorEnter)
            break;
    }
    Stack<Pair<CFGNode, Integer>> todo = new Stack<Pair<CFGNode, Integer>>();
    Set<CFGNode> visited = new HashSet<CFGNode>();
    do {
        boolean isExit = false;
        while (insIter.hasNext()) {
            InstructionHandle ih = insIter.next();
            if (ih.getInstruction() instanceof MONITOREXIT) {
                /* blocks outgoing edges terminate segment */
                currentNestingLevel--;
                if (currentNestingLevel == 0) {
                    isExit = true;
                    // If monitorexit is not implemented in Java, the outgoing edges of the
                    // basic block that contains monitorexit end the synchronized block.
                    // In order to avoid imprecision, it is advisable that monitorexit is the
                    // last statement in the basic block.
                    // We also handle the case when monitorexit is implemented in Java. In this case,
                    // currentNode will be a SpecialInvokeNode, urrentNode's only
                    // successor will be the corresponding ReturnNode, and the outgoing edges of
                    // the ReturnNode are the exit edges for the synchronized segment.
                    CFGNode onlySuccessor = Iterators.fromSingleton(cfg.getSuccessors(currentNode));
                    if (onlySuccessor != null && onlySuccessor instanceof ControlFlowGraph.ReturnNode) {
                        Iterators.addAll(monitorExitEdges, cfg.outgoingEdgesOf(onlySuccessor));
                    } else {
                        Iterators.addAll(monitorExitEdges, cfg.outgoingEdgesOf(currentNode));
                    }
                    break;
                }
            } else if (ih.getInstruction() instanceof MONITORENTER) {
                currentNestingLevel++;
            }
        }
        if (!isExit) {
            for (CFGNode node : cfg.getSuccessors(currentNode)) {
                todo.add(new Pair<CFGNode, Integer>(node, currentNestingLevel));
            }
        }
        currentNode = null;
        while (!todo.isEmpty()) {
            Pair<CFGNode, Integer> nextPair = todo.pop();
            CFGNode nextNode = nextPair.first();
            if (!visited.contains(nextNode)) {
                visited.add(nextNode);
                if (cfg.outgoingEdgesOf(nextNode).isEmpty()) {
                    throw new AssertionError("Found monitor-exit free path from monitorenter to the end of a function. In: " + cfg);
                } else if (nextNode.getBasicBlock() == null) {
                    for (CFGNode node : cfg.getSuccessors(nextNode)) {
                        todo.add(new Pair<CFGNode, Integer>(node, nextPair.second()));
                    }
                } else {
                    currentNode = nextNode;
                    currentNestingLevel = nextPair.second();
                    insIter = currentNode.getBasicBlock().getInstructions().iterator();
                    break;
                }
            }
        }
    } while (currentNode != null);
    Set<SuperGraphEdge> exitEdges = Iterators.addAll(new HashSet<SuperGraphEdge>(), superGraph.liftCFGEdges(rootMethod, monitorExitEdges));
    return new Segment(superGraph, entryEdges, exitEdges);
}
Also used : MONITORENTER(org.apache.bcel.generic.MONITORENTER) InstructionHandle(org.apache.bcel.generic.InstructionHandle) MONITOREXIT(org.apache.bcel.generic.MONITOREXIT) HashSet(java.util.HashSet) CFGEdge(com.jopdesign.common.code.ControlFlowGraph.CFGEdge) Pair(com.jopdesign.common.graphutils.Pair) CFGNode(com.jopdesign.common.code.ControlFlowGraph.CFGNode) Stack(java.util.Stack) ContextCFG(com.jopdesign.common.code.SuperGraph.ContextCFG) SuperGraphEdge(com.jopdesign.common.code.SuperGraph.SuperGraphEdge)

Example 25 with InstructionHandle

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

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