Search in sources :

Example 1 with ValueMapAnalysis

use of com.jopdesign.jcopter.analysis.ValueMapAnalysis 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 2 with ValueMapAnalysis

use of com.jopdesign.jcopter.analysis.ValueMapAnalysis 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)

Aggregations

InvokeSite (com.jopdesign.common.code.InvokeSite)2 ValueInfo (com.jopdesign.common.type.ValueInfo)2 ValueMapAnalysis (com.jopdesign.jcopter.analysis.ValueMapAnalysis)2 FieldInstruction (org.apache.bcel.generic.FieldInstruction)2 GETFIELD (org.apache.bcel.generic.GETFIELD)2 Instruction (org.apache.bcel.generic.Instruction)2 InstructionHandle (org.apache.bcel.generic.InstructionHandle)2 InstructionList (org.apache.bcel.generic.InstructionList)2 InvokeInstruction (org.apache.bcel.generic.InvokeInstruction)2 PUTFIELD (org.apache.bcel.generic.PUTFIELD)2 ARRAYLENGTH (org.apache.bcel.generic.ARRAYLENGTH)1 ArithmeticInstruction (org.apache.bcel.generic.ArithmeticInstruction)1 CHECKCAST (org.apache.bcel.generic.CHECKCAST)1 ConstantPushInstruction (org.apache.bcel.generic.ConstantPushInstruction)1 ConversionInstruction (org.apache.bcel.generic.ConversionInstruction)1 INVOKEINTERFACE (org.apache.bcel.generic.INVOKEINTERFACE)1 INVOKESPECIAL (org.apache.bcel.generic.INVOKESPECIAL)1 INVOKEVIRTUAL (org.apache.bcel.generic.INVOKEVIRTUAL)1 LDC (org.apache.bcel.generic.LDC)1 LDC2_W (org.apache.bcel.generic.LDC2_W)1