Search in sources :

Example 86 with InstructionHandle

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

the class SimpleInliner method analyzeInvokee.

/**
     * @param cs the callstring from the invoker to the invoke to inline (if recursive). Used to check DFA results.
     * @param invokee the invoked method to analyze
     * @param inlineData the map to populate with the parameters and the instructions to inline.
     * @return true if inlining is possible
     */
private boolean analyzeInvokee(CallString cs, MethodInfo invokee, InlineData inlineData) {
    // we allow loading of parameters, loading of constants, some instruction, and a return
    ValueMapAnalysis values = new ValueMapAnalysis(invokee);
    values.loadParameters();
    InstructionList il = invokee.getCode().getInstructionList(true, false);
    InstructionHandle ih = il.getStart();
    // we should at least have a return instruction, so even for empty methods we should fall through
    // generate the parameter mapping
    int count = 0;
    while (true) {
        Instruction instruction = ih.getInstruction();
        if (instruction instanceof PushInstruction || instruction instanceof NOP) {
            values.transfer(instruction);
            ih = ih.getNext();
            count++;
        } else {
            break;
        }
    }
    // store the mapping
    for (ValueInfo value : values.getValueTable().getStack()) {
        inlineData.addParam(value);
    }
    inlineData.setInlineStart(count);
    // if we do not need an NP check, we can also inline code which does not throw an exception in the same way
    boolean needsNPCheck = helper.needsNullpointerCheck(cs, invokee, false);
    boolean hasNPCheck = false;
    // we allow up to 5 instructions and one return before assuming that the resulting code will be too large
    for (int i = 0; i < 6; i++) {
        // now lets see what we have here as non-push instructions
        Instruction instruction = ih.getInstruction();
        if (instruction instanceof InvokeInstruction) {
            if (inlineData.getInvokeSite() != null) {
                // only inline at most one invoke
                return false;
            }
            InvokeSite is = invokee.getCode().getInvokeSite(ih);
            inlineData.setInvokeSite(is);
            hasNPCheck |= !is.isInvokeStatic();
        } else if (instruction instanceof FieldInstruction) {
            if (instruction instanceof GETFIELD) {
                hasNPCheck |= values.getValueTable().top().isThisReference();
            }
            if (instruction instanceof PUTFIELD) {
                int down = values.getValueTable().top().isContinued() ? 2 : 1;
                hasNPCheck |= values.getValueTable().top(down).isThisReference();
            }
        } else if (instruction instanceof ArithmeticInstruction || instruction instanceof ConversionInstruction || instruction instanceof StackInstruction || instruction instanceof LDC || instruction instanceof LDC2_W || instruction instanceof ARRAYLENGTH || instruction instanceof CHECKCAST || instruction instanceof NOP) {
        // nothing to do, just copy them
        } else if (instruction instanceof ReturnInstruction) {
            if (needsNPCheck && !hasNPCheck) {
                // We were nearly finished.. but NP check test failed
                this.requiresNPCheck++;
                if (logger.isTraceEnabled()) {
                    logger.trace("Not inlining " + invokee + " because it requires a NP check.");
                }
                return false;
            }
            // else we need to add pop instructions
            if (instruction instanceof RETURN) {
                // we do not return anything, so we must empty the stack
                while (values.getValueTable().getStackSize() > 0) {
                    Instruction pop;
                    if (values.getValueTable().top().isContinued()) {
                        pop = new POP2();
                    } else {
                        pop = new POP();
                    }
                    inlineData.addEpilogue(pop);
                    values.transfer(pop);
                }
                return true;
            } else {
                Type type = ((ReturnInstruction) instruction).getType();
                // javac anyway)
                return values.getValueTable().getStackSize() == type.getSize();
            }
        } else {
            // if we encounter an instruction which we do not handle, we do not inline
            unhandledInstructions++;
            if (logger.isTraceEnabled()) {
                logger.trace("Not inlining " + invokee + " because of unhandled instruction " + instruction.toString(invokee.getClassInfo().getConstantPoolGen().getConstantPool()));
            }
            return false;
        }
        // update the stack map since we need it to handle RETURN
        values.transfer(instruction);
        ih = ih.getNext();
    }
    // too many instructions, do not inline
    return false;
}
Also used : ArithmeticInstruction(org.apache.bcel.generic.ArithmeticInstruction) ValueMapAnalysis(com.jopdesign.jcopter.analysis.ValueMapAnalysis) ARRAYLENGTH(org.apache.bcel.generic.ARRAYLENGTH) POP2(org.apache.bcel.generic.POP2) InstructionList(org.apache.bcel.generic.InstructionList) CHECKCAST(org.apache.bcel.generic.CHECKCAST) StackInstruction(org.apache.bcel.generic.StackInstruction) ConversionInstruction(org.apache.bcel.generic.ConversionInstruction) LDC(org.apache.bcel.generic.LDC) 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) ReturnInstruction(org.apache.bcel.generic.ReturnInstruction) RETURN(org.apache.bcel.generic.RETURN) LDC2_W(org.apache.bcel.generic.LDC2_W) ValueInfo(com.jopdesign.common.type.ValueInfo) PUTFIELD(org.apache.bcel.generic.PUTFIELD) PushInstruction(org.apache.bcel.generic.PushInstruction) NOP(org.apache.bcel.generic.NOP) POP(org.apache.bcel.generic.POP) InvokeInstruction(org.apache.bcel.generic.InvokeInstruction) GETFIELD(org.apache.bcel.generic.GETFIELD) Type(org.apache.bcel.generic.Type) InvokeSite(com.jopdesign.common.code.InvokeSite) FieldInstruction(org.apache.bcel.generic.FieldInstruction)

Example 87 with InstructionHandle

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

the class WCETAnalysis method runBlockingTimeAnalysis.

private void runBlockingTimeAnalysis(MethodInfo targetMethod) throws InvalidFlowFactException, LpSolveException, UnsupportedCacheModelException {
    GlobalAnalysis an = new GlobalAnalysis(wcetTool, ipetConfig);
    CacheCostCalculationMethod requestedCacheApprox = IPETConfig.getRequestedCacheApprox(config);
    /* Find all synchronized segments */
    Segment target = Segment.methodSegment(targetMethod, CallString.EMPTY, wcetTool, wcetTool.getCallstringLength(), wcetTool);
    ArrayList<SynchronizedBlockResult> sBlocks = new ArrayList<SynchronizedBlockResult>();
    for (ContextCFG ccfg : target.getCallGraphNodes()) {
        for (CFGNode cfgNode : ccfg.getCfg().vertexSet()) {
            if (cfgNode.getBasicBlock() == null)
                continue;
            for (InstructionHandle ih : cfgNode.getBasicBlock().getInstructions()) {
                if (ih.getInstruction() instanceof MONITORENTER) {
                    /* compute synchronized block WCET */
                    Segment synchronizedSegment = Segment.synchronizedSegment(ccfg, cfgNode, ih, wcetTool, wcetTool.getCallstringLength(), wcetTool);
                    wcet = an.computeWCET(targetMethod.getShortName(), synchronizedSegment, requestedCacheApprox);
                    sBlocks.add(new SynchronizedBlockResult(sBlocks.size(), synchronizedSegment, cfgNode, ih, wcet));
                }
            }
        }
    }
    /* check nested synchronized blocks */
    for (SynchronizedBlockResult sBlock : sBlocks) {
        for (SynchronizedBlockResult otherBlock : sBlocks) {
            if (sBlock == otherBlock)
                continue;
            for (SuperGraphEdge entryEdge : otherBlock.synchronizedSegment.getEntryEdges()) {
                if (sBlock.synchronizedSegment.includesEdge(entryEdge)) {
                    sBlock.nested.add(otherBlock);
                    break;
                }
            }
        }
    }
    System.out.println("=== Synchronized Blocks ===");
    for (SynchronizedBlockResult sBlock : sBlocks) {
        sBlock.dump(System.out);
    }
}
Also used : CacheCostCalculationMethod(com.jopdesign.wcet.ipet.IPETConfig.CacheCostCalculationMethod) CFGNode(com.jopdesign.common.code.ControlFlowGraph.CFGNode) GlobalAnalysis(com.jopdesign.wcet.analysis.GlobalAnalysis) ContextCFG(com.jopdesign.common.code.SuperGraph.ContextCFG) ArrayList(java.util.ArrayList) SuperGraphEdge(com.jopdesign.common.code.SuperGraph.SuperGraphEdge) MONITORENTER(org.apache.bcel.generic.MONITORENTER) Segment(com.jopdesign.common.code.Segment) InstructionHandle(org.apache.bcel.generic.InstructionHandle)

Example 88 with InstructionHandle

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

the class PeepholeOptimizer method optimizeBoolExpressions.

/**
     * Optimize some boolean expressions.
     * <p>
     * This code is taken directly from the BCEL manual, chapter 3.3.8.
     * </p>
     *
     * @param il the instruction list to optimize.
     */
private void optimizeBoolExpressions(InstructionList il) {
    InstructionFinder f = new InstructionFinder(il);
    String pat = "IfInstruction ICONST_0 GOTO ICONST_1 NOP(IFEQ|IFNE)";
    CodeConstraint constraint = new CodeConstraint() {

        @Override
        public boolean checkCode(InstructionHandle[] match) {
            IfInstruction if1 = (IfInstruction) match[0].getInstruction();
            GOTO g = (GOTO) match[2].getInstruction();
            return (if1.getTarget() == match[3]) && (g.getTarget() == match[4]);
        }
    };
    for (Iterator e = f.search(pat, constraint); e.hasNext(); ) {
        InstructionHandle[] match = (InstructionHandle[]) e.next();
        IfInstruction if1 = (IfInstruction) match[0].getInstruction();
        IfInstruction if2 = (IfInstruction) match[5].getInstruction();
        // Update target
        if1.setTarget(if2.getTarget());
        try {
            il.delete(match[1], match[5]);
        } catch (TargetLostException ex) {
            for (InstructionHandle target : ex.getTargets()) {
                for (InstructionTargeter t : target.getTargeters()) {
                    t.updateTarget(target, match[0]);
                }
            }
        }
        matchBoolExpressions++;
    }
}
Also used : GOTO(org.apache.bcel.generic.GOTO) InstructionTargeter(org.apache.bcel.generic.InstructionTargeter) IfInstruction(org.apache.bcel.generic.IfInstruction) Iterator(java.util.Iterator) CodeConstraint(org.apache.bcel.util.InstructionFinder.CodeConstraint) InstructionFinder(org.apache.bcel.util.InstructionFinder) TargetLostException(org.apache.bcel.generic.TargetLostException) InstructionHandle(org.apache.bcel.generic.InstructionHandle)

Example 89 with InstructionHandle

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

the class MethodCacheAnalysis method getMissCost.

/**
	 * Get miss cost for an edge accessing the method cache
	 * @param accessEdge either a SuperInvoke or SuperReturn edge, or an entry edge of the segment analyzed
	 * @return maximum miss penalty (in cycles)
	 */
private long getMissCost(SuperGraphEdge accessEdge) {
    SuperGraphNode accessed = accessEdge.getTarget();
    ControlFlowGraph cfg = accessed.getCfg();
    if (accessEdge instanceof SuperReturnEdge) {
        /* return edge: return cost */
        Type returnType = accessEdge.getSource().getCfg().getMethodInfo().getType();
        return methodCache.getMissPenaltyOnReturn(cfg.getNumberOfWords(), returnType);
    } else if (accessEdge instanceof SuperInvokeEdge) {
        InstructionHandle invokeIns = ((SuperInvokeEdge) accessEdge).getInvokeNode().getInvokeSite().getInstructionHandle();
        return methodCache.getMissPenaltyOnInvoke(cfg.getNumberOfWords(), invokeIns.getInstruction());
    } else {
        /* entry edge of the segment: can be invoke or return cost */
        return methodCache.getMissPenalty(cfg.getNumberOfWords(), false);
    }
}
Also used : Type(org.apache.bcel.generic.Type) ControlFlowGraph(com.jopdesign.common.code.ControlFlowGraph) SuperReturnEdge(com.jopdesign.common.code.SuperGraph.SuperReturnEdge) SuperGraphNode(com.jopdesign.common.code.SuperGraph.SuperGraphNode) InstructionHandle(org.apache.bcel.generic.InstructionHandle) SuperInvokeEdge(com.jopdesign.common.code.SuperGraph.SuperInvokeEdge)

Example 90 with InstructionHandle

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

the class ObjectCacheAnalysis method extractAccessesAndCosts.

/** Traverse vertex set.
	 * <p>Add vertex to access set of referenced addresses
	 * For references whose type cannot be fully resolved, add a
	 * cost of 1.</p>
	 * <p>FIXME: We should deal with subtyping (or better use storage based alias-analysis)</p>
	 *
	 * @param nodes
	 * @param usedRefs the results of the local points-to analysis, or {@code null} for always miss costs
	 * @param costModel
	 */
private AccessCostInfo extractAccessesAndCosts(Iterable<SuperGraphNode> nodes, LocalPointsToResult usedRefs, ObjectCacheCostModel costModel) {
    AccessCostInfo aci = new AccessCostInfo();
    for (SuperGraphNode node : nodes) {
        /* Compute cost for basic block */
        BasicBlock bb = node.getCFGNode().getBasicBlock();
        if (bb == null)
            continue;
        long bypassCost = 0;
        long alwaysMissCost = 0;
        CallString cs = node.getContextCFG().getCallString();
        for (InstructionHandle ih : bb.getInstructions()) {
            String handleType = getHandleType(project, node.getCfg(), ih);
            if (handleType == null)
                continue;
            /* No getfield/handle access */
            int fieldIndex = getFieldIndex(project, node.getCfg(), ih);
            int blockIndex = getBlockIndex(fieldIndex);
            if (fieldIndex > this.maxCachedFieldIndex) {
                bypassCost += costModel.getFieldAccessCostBypass();
                continue;
            }
            BoundedSet<SymbolicAddress> refs = null;
            if (usedRefs != null) {
                if (!usedRefs.containsKey(ih)) {
                    usedRefs = null;
                    WCETTool.logger.error("No DFA results for: " + ih.getInstruction() + " with field " + ((FieldInstruction) ih.getInstruction()).getFieldName(bb.cpg()));
                } else {
                    refs = usedRefs.get(ih, cs);
                    if (refs.isSaturated())
                        refs = null;
                }
            }
            if (refs == null) {
                alwaysMissCost += costModel.getReplaceLineCost() + costModel.getLoadCacheBlockCost();
            } else {
                for (SymbolicAddress ref : refs.getSet()) {
                    aci.addRefAccess(ref, node);
                    aci.addBlockAccess(ref.accessArray(blockIndex), node);
                    // Handle getfield_long / getfield_double
                    if (getCachedType(project, node.getCfg(), ih) == Type.LONG || getCachedType(project, node.getCfg(), ih) == Type.DOUBLE) {
                        if (blockIndex + 1 > this.maxCachedFieldIndex) {
                            bypassCost += costModel.getFieldAccessCostBypass();
                        } else {
                            aci.addBlockAccess(ref.accessArray(blockIndex + 1), node);
                        }
                    }
                }
            }
        }
        aci.putBypassCost(node, bypassCost);
        aci.putStaticCost(node, bypassCost + alwaysMissCost);
    }
    return aci;
}
Also used : AccessCostInfo(com.jopdesign.wcet.analysis.cache.ObjectCacheAnalysis.AccessCostInfo) BasicBlock(com.jopdesign.common.code.BasicBlock) SuperGraphNode(com.jopdesign.common.code.SuperGraph.SuperGraphNode) CallString(com.jopdesign.common.code.CallString) FieldInstruction(org.apache.bcel.generic.FieldInstruction) SymbolicAddress(com.jopdesign.dfa.analyses.SymbolicAddress) InstructionHandle(org.apache.bcel.generic.InstructionHandle) CallString(com.jopdesign.common.code.CallString)

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