Search in sources :

Example 6 with Instruction

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

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

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

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

the class InvokeSite method getInvokeeRef.

/**
     * Get the MethodRef to the referenced method. If the instruction is handled in java, return a reference
     * to the method which implements the instruction.
     * <p>
     * The MethodRef refers to the actual reference. {@link MethodRef#getMethodInfo()} resolves the actual
     * MethodInfo, which might be defined in a super class of the referenced method, if the method is inherited.
     * For invokespecial, the implementing method might even be defined in a subclass of the referenced method,
     * if resolveSuper is set to false, see {@link #isInvokeSuper()} for details.
     * </p>
     * <p>To find all possible implementations if the invocation is a virtual invoke (see {@link #isVirtual()}),
     * use {@link AppInfo#findImplementations(InvokeSite)}.</p>
     *
     * @see #isInvokeSuper()
     * @see AppInfo#findImplementations(InvokeSite)
     * @param resolveSuper if true, try to resolve the super method reference (see {@link #isInvokeSuper()}),
     *                     else return a reference to the method as it is defined by the instruction.
     * @return a method reference to the invokee method.
     */
public MethodRef getInvokeeRef(boolean resolveSuper) {
    Instruction instr = instruction.getInstruction();
    AppInfo appInfo = AppInfo.getSingleton();
    if (instr instanceof InvokeInstruction) {
        MethodRef ref = getReferencedMethod(invoker, (InvokeInstruction) instr);
        // need to check isInvokeSpecial here, since it is not checked by isSuperMethod!
        if (resolveSuper && isInvokeSpecial() && isSuperMethod(ref)) {
            ref = resolveInvokeSuper(ref);
        }
        return ref;
    }
    if (appInfo.getProcessorModel().isImplementedInJava(invoker, instr)) {
        return appInfo.getProcessorModel().getJavaImplementation(appInfo, invoker, instr).getMethodRef();
    }
    throw new JavaClassFormatError("InvokeSite handle does not refer to an invoke instruction: " + toString());
}
Also used : InvokeInstruction(org.apache.bcel.generic.InvokeInstruction) MethodRef(com.jopdesign.common.type.MethodRef) JavaClassFormatError(com.jopdesign.common.misc.JavaClassFormatError) InvokeInstruction(org.apache.bcel.generic.InvokeInstruction) Instruction(org.apache.bcel.generic.Instruction) AppInfo(com.jopdesign.common.AppInfo)

Example 10 with Instruction

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

the class DFATool method buildPrologue.

private MethodInfo buildPrologue(MethodInfo mainMethod, List<InstructionHandle> statements, Flow flow, List<ClassInfo> clinits) {
    // we use a prologue sequence for startup
    InstructionList prologue = new InstructionList();
    ConstantPoolGen prologueCP = mainMethod.getConstantPoolGen();
    Instruction instr;
    int idx;
    // add magic initializers to prologue sequence
    if (!analyzeBootMethod) {
        instr = new ICONST(0);
        prologue.append(instr);
        instr = new ICONST(0);
        prologue.append(instr);
        idx = prologueCP.addMethodref("com.jopdesign.sys.GC", "init", "(II)V");
        instr = new INVOKESTATIC(idx);
        prologue.append(instr);
    }
    // add class initializers
    for (ClassInfo clinit : clinits) {
        MemberID cSig = appInfo.getClinitSignature(clinit.getClassName());
        idx = prologueCP.addMethodref(cSig.getClassName(), cSig.getMemberName(), cSig.getDescriptor().toString());
        instr = new INVOKESTATIC(idx);
        prologue.append(instr);
    }
    if (analyzeBootMethod) {
        // Let's just analyze the full boot method, so that the callgraph-builder is happy.
        // Doing this after clinit, so that we have DFA infos on fields in JVMHelp.init()
        idx = prologueCP.addMethodref("com.jopdesign.sys.Startup", "boot", "()V");
        instr = new INVOKESTATIC(idx);
        prologue.append(instr);
    }
    // add main method
    instr = new ACONST_NULL();
    prologue.append(instr);
    idx = prologueCP.addMethodref(mainMethod.getClassName(), mainMethod.getShortName(), mainMethod.getDescriptor().toString());
    instr = new INVOKESTATIC(idx);
    prologue.append(instr);
    //      // invoke startMission() to ensure analysis of threads
    //      idx = prologueCP.addMethodref("joprt.RtThread", "startMission", "()V");
    //      instr = new INVOKESTATIC(idx);
    //      prologue.append(instr);
    instr = new NOP();
    prologue.append(instr);
    prologue.setPositions(true);
    // add prologue to program structure
    for (Iterator l = prologue.iterator(); l.hasNext(); ) {
        InstructionHandle handle = (InstructionHandle) l.next();
        statements.add(handle);
        if (handle.getInstruction() instanceof GOTO) {
            GOTO g = (GOTO) handle.getInstruction();
            flow.addEdge(new FlowEdge(handle, g.getTarget(), FlowEdge.NORMAL_EDGE));
        } else if (handle.getNext() != null) {
            flow.addEdge(new FlowEdge(handle, handle.getNext(), FlowEdge.NORMAL_EDGE));
        }
    }
    MemberID pSig = new MemberID(prologueName, Descriptor.parse(prologueSig));
    MethodInfo mi = mainMethod.getClassInfo().createMethod(pSig, null, prologue);
    mi.setAccessType(AccessType.ACC_PRIVATE);
    return mi;
}
Also used : FlowEdge(com.jopdesign.dfa.framework.FlowEdge) INVOKESTATIC(org.apache.bcel.generic.INVOKESTATIC) GOTO(org.apache.bcel.generic.GOTO) InstructionList(org.apache.bcel.generic.InstructionList) Instruction(org.apache.bcel.generic.Instruction) BranchInstruction(org.apache.bcel.generic.BranchInstruction) ReturnInstruction(org.apache.bcel.generic.ReturnInstruction) NOP(org.apache.bcel.generic.NOP) InstructionHandle(org.apache.bcel.generic.InstructionHandle) ConstantPoolGen(org.apache.bcel.generic.ConstantPoolGen) MemberID(com.jopdesign.common.type.MemberID) Iterator(java.util.Iterator) MethodInfo(com.jopdesign.common.MethodInfo) ACONST_NULL(org.apache.bcel.generic.ACONST_NULL) ICONST(org.apache.bcel.generic.ICONST) ClassInfo(com.jopdesign.common.ClassInfo)

Aggregations

Instruction (org.apache.bcel.generic.Instruction)27 FieldInstruction (org.apache.bcel.generic.FieldInstruction)15 InstructionHandle (org.apache.bcel.generic.InstructionHandle)15 InvokeInstruction (org.apache.bcel.generic.InvokeInstruction)14 MethodInfo (com.jopdesign.common.MethodInfo)9 GETFIELD (org.apache.bcel.generic.GETFIELD)8 BranchInstruction (org.apache.bcel.generic.BranchInstruction)7 InstructionList (org.apache.bcel.generic.InstructionList)7 ReferenceType (org.apache.bcel.generic.ReferenceType)7 ReturnInstruction (org.apache.bcel.generic.ReturnInstruction)7 Type (org.apache.bcel.generic.Type)7 ConstantPoolGen (org.apache.bcel.generic.ConstantPoolGen)6 CallString (com.jopdesign.common.code.CallString)5 ConstantPushInstruction (org.apache.bcel.generic.ConstantPushInstruction)5 PUTFIELD (org.apache.bcel.generic.PUTFIELD)5 StoreInstruction (org.apache.bcel.generic.StoreInstruction)5 InvokeSite (com.jopdesign.common.code.InvokeSite)4 MethodRef (com.jopdesign.common.type.MethodRef)4 LDC (org.apache.bcel.generic.LDC)4 LocalVariableInstruction (org.apache.bcel.generic.LocalVariableInstruction)4