Search in sources :

Example 1 with InstructionList

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

the class AnalysisResultSerialization method fromContextMapResult.

/** 
	 * <p>Result Map: MethodInfo -> Instruction Offset -> Callstring -> R</p>
	 * <p>TODO: More efficient representations are possible</p>
	 * @param result the result of the DFA analysis
	 * @param serializer converter for the result domain (if not serializable), or null
	 *                   if the results of type T should be serialized directly
	 */
public static <T, R> AnalysisResultSerialization<R> fromContextMapResult(Map<InstructionHandle, ContextMap<CallString, T>> result, Serializer<T, R> serializer) {
    AnalysisResultSerialization<R> analysisResult = new AnalysisResultSerialization<R>();
    /* sort instruction handle by: method, offset */
    for (InstructionHandle instr : result.keySet()) {
        ContextMap<CallString, T> r = result.get(instr);
        Context c = r.getContext();
        InstructionList il = c.getMethodInfo().getCode().getInstructionList(true, false);
        for (CallString cs : r.keySet()) {
            Integer position = instr.getPosition();
            // skip stuff that is not used anymore
            if (position < 0)
                continue;
            if (il.findHandle(position) != instr)
                continue;
            if (serializer != null) {
                T rValue = r.get(cs);
                R sValue = serializer.serializedRepresentation(rValue);
                analysisResult.addResult(c.getMethodInfo(), position, cs, sValue);
            } else {
                analysisResult.addResult(c.getMethodInfo(), position, cs, (R) r.get(cs));
            }
        }
    }
    return analysisResult;
}
Also used : InstructionList(org.apache.bcel.generic.InstructionList) InstructionHandle(org.apache.bcel.generic.InstructionHandle) CallString(com.jopdesign.common.code.CallString)

Example 2 with InstructionList

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

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

the class InlineHelper method needsNullpointerCheck.

/**
     * Check if an exception must be generated if the 'this' reference is null.
     * This test can return false if
     * <ul><li>There is no 'this' reference</li>
     * <li>The DFA analysis showed that the reference is never null</li>
     * <li>The inlined code will always generate an exception anyway</li>
     * <li>Generating checks has been disabled by configuration</li>
     * </ul>
     * <p>
     * The callstring does not need to start or to end at the method to optimize. However since the callstring is
     * used to check the DFA results if available, the callstring must match what the DFA expects, i.e. if
     * the DFA-results and -callstrings are updated during inlining, this callstring must not include inlined
     * invokes. Contrariwise if the DFA results are not updated during inline, the callstring must contain already
     * inlined invokes.
     * </p>
     *
     * @param callString The callstring including the invokesite of the invokee. The top invokesite does not need to
     *                   refer to an invoke instruction, and the referenced invoker method does not need to
     *                   be the method containing the invoke to inline (e.g. if the invoke to inline has
     *                   been inlined itself). However the callstring needs to match what the DFA expects.
     * @param invokee the devirtualized invokee.
     * @param analyzeCode if false, skip checking the code of the invokee.
     * @return true if a nullpointer check code should be generated.
     */
public boolean needsNullpointerCheck(CallString callString, MethodInfo invokee, boolean analyzeCode) {
    if (inlineConfig.skipNullpointerChecks())
        return false;
    InvokeSite invokeSite = callString.top();
    // check if we have a 'this' reference anyway
    if (invokeSite.isInvokeStatic() || invokeSite.isJVMCall()) {
        return false;
    }
    // TODO check the DFA results if available
    if (jcopter.useDFA()) {
    } else if ("<init>".equals(invokee.getShortName())) {
        // the NP check in this case (and hope that compilers for languages other than Java do the same..)
        return false;
    }
    if (!analyzeCode) {
        return true;
    }
    // check if the code will always throw an exception anyway (without producing any side effects before throwing)
    ValueMapAnalysis analysis = new ValueMapAnalysis(invokee);
    analysis.loadParameters();
    InstructionList list = invokee.getCode().getInstructionList(true, false);
    for (InstructionHandle ih : list.getInstructionHandles()) {
        Instruction instr = ih.getInstruction();
        if (instr instanceof ConstantPushInstruction || instr instanceof LocalVariableInstruction) {
            analysis.transfer(instr);
        } else if (instr instanceof GETFIELD || instr instanceof PUTFIELD || instr instanceof INVOKEVIRTUAL || instr instanceof INVOKEINTERFACE || instr instanceof INVOKESPECIAL) {
            int down = instr.consumeStack(invokee.getConstantPoolGen());
            ValueInfo value = analysis.getValueTable().top(down);
            // the same way as the inlined invoke
            if (value.isThisReference()) {
                return false;
            }
            break;
        } else {
            // we ignore all other instructions (for now..)
            break;
        }
    }
    return true;
}
Also used : ValueMapAnalysis(com.jopdesign.jcopter.analysis.ValueMapAnalysis) InstructionList(org.apache.bcel.generic.InstructionList) PUTFIELD(org.apache.bcel.generic.PUTFIELD) 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) INVOKESPECIAL(org.apache.bcel.generic.INVOKESPECIAL) InstructionHandle(org.apache.bcel.generic.InstructionHandle) GETFIELD(org.apache.bcel.generic.GETFIELD) INVOKEINTERFACE(org.apache.bcel.generic.INVOKEINTERFACE) ValueInfo(com.jopdesign.common.type.ValueInfo) LocalVariableInstruction(org.apache.bcel.generic.LocalVariableInstruction) InvokeSite(com.jopdesign.common.code.InvokeSite) ConstantPushInstruction(org.apache.bcel.generic.ConstantPushInstruction) INVOKEVIRTUAL(org.apache.bcel.generic.INVOKEVIRTUAL)

Example 4 with InstructionList

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

the class InlineOptimizer method initialize.

@Override
public void initialize(AnalysisManager analyses, Collection<MethodInfo> roots) {
    if (!preciseCycleEstimate) {
        ExecutionContext dummy = new ExecutionContext(roots.iterator().next());
        WCETProcessorModel pm = analyses.getJCopter().getWCETProcessorModel();
        InstructionList il = new InstructionList();
        // TODO very messy approximation of exec time
        storeCycles = (int) pm.getExecutionTime(dummy, il.append(new ASTORE(10)));
        checkNPCycles = 0;
        checkNPCycles += (int) pm.getExecutionTime(dummy, il.append(new DUP()));
        checkNPCycles += (int) pm.getExecutionTime(dummy, il.append(new IFNONNULL(il.append(new ATHROW()))));
        deltaReturnCycles = (int) pm.getExecutionTime(dummy, il.append(new RETURN()));
        deltaReturnCycles -= (int) pm.getExecutionTime(dummy, il.append(new GOTO(il.getEnd())));
    }
    countInvokeSites = 0;
    countDevirtualized = 0;
}
Also used : RETURN(org.apache.bcel.generic.RETURN) GOTO(org.apache.bcel.generic.GOTO) ExecutionContext(com.jopdesign.common.code.ExecutionContext) ASTORE(org.apache.bcel.generic.ASTORE) WCETProcessorModel(com.jopdesign.wcet.WCETProcessorModel) InstructionList(org.apache.bcel.generic.InstructionList) ATHROW(org.apache.bcel.generic.ATHROW) IFNONNULL(org.apache.bcel.generic.IFNONNULL) DUP(org.apache.bcel.generic.DUP)

Example 5 with InstructionList

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

Aggregations

InstructionList (org.apache.bcel.generic.InstructionList)37 InstructionHandle (org.apache.bcel.generic.InstructionHandle)27 Iterator (java.util.Iterator)9 MethodGen (org.apache.bcel.generic.MethodGen)8 Instruction (org.apache.bcel.generic.Instruction)7 InvokeInstruction (org.apache.bcel.generic.InvokeInstruction)7 Type (org.apache.bcel.generic.Type)7 InstructionFinder (org.apache.bcel.util.InstructionFinder)7 MethodCode (com.jopdesign.common.MethodCode)6 CPInstruction (org.apache.bcel.generic.CPInstruction)6 ConstantPoolGen (org.apache.bcel.generic.ConstantPoolGen)6 FieldInstruction (org.apache.bcel.generic.FieldInstruction)6 MethodInfo (com.jopdesign.common.MethodInfo)5 NOP (org.apache.bcel.generic.NOP)5 BranchInstruction (org.apache.bcel.generic.BranchInstruction)4 ReturnInstruction (org.apache.bcel.generic.ReturnInstruction)4 ClassInfo (com.jopdesign.common.ClassInfo)3 InvokeSite (com.jopdesign.common.code.InvokeSite)3 Constant (org.apache.bcel.classfile.Constant)3 JavaClass (org.apache.bcel.classfile.JavaClass)3