Search in sources :

Example 6 with FieldInstruction

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

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

Example 8 with FieldInstruction

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

the class ObjectCacheAnalysis method getFieldIndex.

/**
	 * @return the index of the field accessed by the instruction, or 0 if the instruction
	 * does not access a field
	 */
private static int getFieldIndex(WCETTool p, ControlFlowGraph cfg, InstructionHandle ih) {
    ConstantPoolGen constPool = cfg.getMethodInfo().getConstantPoolGen();
    Instruction instr = ih.getInstruction();
    if (instr instanceof FieldInstruction) {
        FieldInstruction fieldInstr = (FieldInstruction) instr;
        ReferenceType refType = fieldInstr.getReferenceType(constPool);
        if (!(refType instanceof ObjectType)) {
            throw new RuntimeException("getFieldIndex(): Unsupported object kind: " + refType.getClass());
        }
        ObjectType objType = (ObjectType) refType;
        String klassName = objType.getClassName();
        String fieldName = fieldInstr.getFieldName(constPool);
        String fieldSig = fieldInstr.getSignature(constPool);
        return p.getLinkerInfo().getFieldIndex(klassName, fieldName + fieldSig);
    } else {
        return 0;
    }
}
Also used : ConstantPoolGen(org.apache.bcel.generic.ConstantPoolGen) ObjectType(org.apache.bcel.generic.ObjectType) FieldInstruction(org.apache.bcel.generic.FieldInstruction) CallString(com.jopdesign.common.code.CallString) Instruction(org.apache.bcel.generic.Instruction) FieldInstruction(org.apache.bcel.generic.FieldInstruction) ArrayInstruction(org.apache.bcel.generic.ArrayInstruction) ReferenceType(org.apache.bcel.generic.ReferenceType)

Aggregations

FieldInstruction (org.apache.bcel.generic.FieldInstruction)8 InstructionHandle (org.apache.bcel.generic.InstructionHandle)5 InvokeInstruction (org.apache.bcel.generic.InvokeInstruction)5 Instruction (org.apache.bcel.generic.Instruction)4 Type (org.apache.bcel.generic.Type)4 InvokeSite (com.jopdesign.common.code.InvokeSite)3 ConstantPushInstruction (org.apache.bcel.generic.ConstantPushInstruction)3 GETFIELD (org.apache.bcel.generic.GETFIELD)3 InstructionList (org.apache.bcel.generic.InstructionList)3 PUTFIELD (org.apache.bcel.generic.PUTFIELD)3 ReferenceType (org.apache.bcel.generic.ReferenceType)3 FieldInfo (com.jopdesign.common.FieldInfo)2 MethodCode (com.jopdesign.common.MethodCode)2 MethodInfo (com.jopdesign.common.MethodInfo)2 CallString (com.jopdesign.common.code.CallString)2 AppInfoError (com.jopdesign.common.misc.AppInfoError)2 FieldRef (com.jopdesign.common.type.FieldRef)2 MethodRef (com.jopdesign.common.type.MethodRef)2 ValueInfo (com.jopdesign.common.type.ValueInfo)2 BasicType (org.apache.bcel.generic.BasicType)2