Search in sources :

Example 1 with ValueInfo

use of com.jopdesign.common.type.ValueInfo 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 ValueInfo

use of com.jopdesign.common.type.ValueInfo in project jop by jop-devel.

the class ValueMapAnalysis method transfer.

public void transfer(Instruction instruction) {
    switch(instruction.getOpcode()) {
        case Constants.NOP:
            break;
        case Constants.ACONST_NULL:
            values.push(new ValueInfo(Type.NULL));
            break;
        case Constants.ICONST_M1:
        case Constants.ICONST_0:
        case Constants.ICONST_1:
        case Constants.ICONST_2:
        case Constants.ICONST_3:
        case Constants.ICONST_4:
        case Constants.ICONST_5:
        case Constants.BIPUSH:
        case Constants.SIPUSH:
            {
                ConstantPushInstruction instr = (ConstantPushInstruction) instruction;
                int value = instr.getValue().intValue();
                values.push(new ValueInfo(instr.getType(cpg), new ConstantIntegerInfo(value)));
                break;
            }
        case Constants.LCONST_0:
        case Constants.LCONST_1:
            {
                ConstantPushInstruction instr = (ConstantPushInstruction) instruction;
                long value = instr.getValue().longValue();
                values.push(new ValueInfo(instr.getType(cpg), new ConstantLongInfo(value)));
                break;
            }
        case Constants.FCONST_0:
        case Constants.FCONST_1:
        case Constants.FCONST_2:
            {
                ConstantPushInstruction instr = (ConstantPushInstruction) instruction;
                float value = instr.getValue().floatValue();
                values.push(new ValueInfo(instr.getType(cpg), new ConstantFloatInfo(value)));
                break;
            }
        case Constants.DCONST_0:
        case Constants.DCONST_1:
            {
                ConstantPushInstruction instr = (ConstantPushInstruction) instruction;
                double value = instr.getValue().doubleValue();
                values.push(new ValueInfo(instr.getType(cpg), new ConstantDoubleInfo(value)));
                break;
            }
        case Constants.LDC:
        case Constants.LDC_W:
        case Constants.LDC2_W:
            {
                CPInstruction instr = (CPInstruction) instruction;
                values.push(new ValueInfo(methodInfo.getClassInfo().getConstantInfo(instr.getIndex())));
                break;
            }
        case Constants.ISTORE_0:
        case Constants.ISTORE_1:
        case Constants.ISTORE_2:
        case Constants.ISTORE_3:
        case Constants.ISTORE:
        case Constants.ASTORE_0:
        case Constants.ASTORE_1:
        case Constants.ASTORE_2:
        case Constants.ASTORE_3:
        case Constants.ASTORE:
        case Constants.LSTORE_0:
        case Constants.LSTORE_1:
        case Constants.LSTORE_2:
        case Constants.LSTORE_3:
        case Constants.LSTORE:
        case Constants.DSTORE_0:
        case Constants.DSTORE_1:
        case Constants.DSTORE_2:
        case Constants.DSTORE_3:
        case Constants.DSTORE:
        case Constants.FSTORE_0:
        case Constants.FSTORE_1:
        case Constants.FSTORE_2:
        case Constants.FSTORE_3:
        case Constants.FSTORE:
            {
                StoreInstruction instr = (StoreInstruction) instruction;
                int index = instr.getIndex();
                values.setLocalValue(index, values.popValue());
                break;
            }
        case Constants.ILOAD_0:
        case Constants.ILOAD_1:
        case Constants.ILOAD_2:
        case Constants.ILOAD_3:
        case Constants.ILOAD:
        case Constants.LLOAD_0:
        case Constants.LLOAD_1:
        case Constants.LLOAD_2:
        case Constants.LLOAD_3:
        case Constants.LLOAD:
        case Constants.FLOAD_0:
        case Constants.FLOAD_1:
        case Constants.FLOAD_2:
        case Constants.FLOAD_3:
        case Constants.FLOAD:
        case Constants.DLOAD_0:
        case Constants.DLOAD_1:
        case Constants.DLOAD_2:
        case Constants.DLOAD_3:
        case Constants.DLOAD:
        case Constants.ALOAD_0:
        case Constants.ALOAD_1:
        case Constants.ALOAD_2:
        case Constants.ALOAD_3:
        case Constants.ALOAD:
            {
                LoadInstruction instr = (LoadInstruction) instruction;
                int index = instr.getIndex();
                values.push(values.getLocalValue(index));
                break;
            }
        case Constants.DUP:
            values.push(values.top());
            break;
        case Constants.DUP_X1:
            values.insert(2, values.top());
            break;
        case Constants.DUP_X2:
            values.insert(3, values.top());
        case Constants.DUP2:
            values.push(values.top(1), false);
            values.push(values.top(1), false);
            break;
        case Constants.DUP2_X1:
            values.insert(3, values.top(1));
            values.insert(3, values.top(0));
            break;
        case Constants.DUP2_X2:
            values.insert(4, values.top(1));
            values.insert(4, values.top(0));
            break;
        case Constants.POP:
            values.pop();
            break;
        case Constants.POP2:
            values.pop();
            values.pop();
            break;
        case Constants.SWAP:
            values.insert(1, values.pop());
            break;
        case Constants.IASTORE:
        case Constants.LASTORE:
        case Constants.FASTORE:
        case Constants.DASTORE:
        case Constants.CASTORE:
        case Constants.SASTORE:
        case Constants.BASTORE:
        case Constants.AASTORE:
            values.popValue();
            values.pop();
            values.pop();
            break;
        case Constants.IALOAD:
        case Constants.LALOAD:
        case Constants.FALOAD:
        case Constants.DALOAD:
        case Constants.CALOAD:
        case Constants.SALOAD:
        case Constants.BALOAD:
        case Constants.AALOAD:
            {
                values.pop();
                values.pop();
                Type t = ((ArrayInstruction) instruction).getType(cpg);
                values.push(new ValueInfo(t));
                break;
            }
        case Constants.IINC:
            {
                int i = ((IINC) instruction).getIndex();
                ValueInfo old = values.getLocalValue(i);
                if (old.isConstantValue() && old.getConstantValue() instanceof ConstantIntegerInfo) {
                    ConstantIntegerInfo value = (ConstantIntegerInfo) old.getConstantValue();
                    int newval = value.getValue() + ((IINC) instruction).getIncrement();
                    values.setLocalValue(i, new ValueInfo(new ConstantIntegerInfo(newval)));
                } else {
                    values.setLocalValue(i, new ValueInfo(Type.INT));
                }
                break;
            }
        case Constants.IADD:
        case Constants.ISUB:
        case Constants.IMUL:
        case Constants.IDIV:
        case Constants.IREM:
        case Constants.IAND:
        case Constants.IOR:
        case Constants.IXOR:
        case Constants.ISHL:
        case Constants.ISHR:
        case Constants.IUSHR:
            values.pop();
        case Constants.INEG:
            values.pop();
            values.push(new ValueInfo(Type.INT));
            break;
        case Constants.FADD:
        case Constants.FSUB:
        case Constants.FMUL:
        case Constants.FDIV:
        case Constants.FREM:
            values.pop();
        case Constants.FNEG:
            values.pop();
            values.push(new ValueInfo(Type.FLOAT));
            break;
        case Constants.LADD:
        case Constants.LSUB:
        case Constants.LMUL:
        case Constants.LDIV:
        case Constants.LREM:
        case Constants.LAND:
        case Constants.LOR:
        case Constants.LXOR:
            values.pop();
            values.pop();
        case Constants.LNEG:
            values.pop();
            values.pop();
            values.push(new ValueInfo(Type.LONG));
            break;
        case Constants.DADD:
        case Constants.DSUB:
        case Constants.DMUL:
        case Constants.DDIV:
        case Constants.DREM:
            values.pop();
            values.pop();
        case Constants.DNEG:
            values.pop();
            values.pop();
            values.push(new ValueInfo(Type.DOUBLE));
            break;
        case Constants.LSHL:
        case Constants.LSHR:
        case Constants.LUSHR:
            values.pop();
            values.pop();
            values.pop();
            values.push(new ValueInfo(Type.LONG));
            break;
        case Constants.I2B:
        case Constants.I2C:
        case Constants.I2S:
        case Constants.I2L:
        case Constants.I2F:
        case Constants.I2D:
        case Constants.L2I:
        case Constants.L2F:
        case Constants.L2D:
        case Constants.F2I:
        case Constants.F2L:
        case Constants.F2D:
        case Constants.D2I:
        case Constants.D2L:
        case Constants.D2F:
            {
                values.popValue();
                values.push(new ValueInfo(((ConversionInstruction) instruction).getType(cpg)));
                break;
            }
        case Constants.LCMP:
        case Constants.DCMPL:
        case Constants.DCMPG:
            values.pop();
            values.pop();
        case Constants.FCMPL:
        case Constants.FCMPG:
            values.pop();
            values.pop();
            values.push(new ValueInfo(Type.INT));
            break;
        case Constants.IF_ICMPEQ:
        case Constants.IF_ICMPNE:
        case Constants.IF_ICMPLT:
        case Constants.IF_ICMPGE:
        case Constants.IF_ICMPGT:
        case Constants.IF_ICMPLE:
        case Constants.IF_ACMPEQ:
        case Constants.IF_ACMPNE:
            values.pop();
        case Constants.IFEQ:
        case Constants.IFNE:
        case Constants.IFLT:
        case Constants.IFGE:
        case Constants.IFLE:
        case Constants.IFGT:
        case Constants.IFNULL:
        case Constants.IFNONNULL:
            values.pop();
            break;
        case Constants.GOTO:
        case Constants.RET:
            break;
        case Constants.JSR:
            // This is of type 'returnAddress'
            values.push(new ValueInfo(Type.INT));
            break;
        case Constants.ARETURN:
        case Constants.IRETURN:
        case Constants.LRETURN:
        case Constants.FRETURN:
        case Constants.DRETURN:
        case Constants.RETURN:
            values.clearStack();
            break;
        case Constants.LOOKUPSWITCH:
        case Constants.TABLESWITCH:
            values.pop();
            break;
        case Constants.GETFIELD:
            values.pop();
        case Constants.GETSTATIC:
            {
                FieldInstruction f = (FieldInstruction) instruction;
                ConstantFieldInfo field = (ConstantFieldInfo) methodInfo.getClassInfo().getConstantInfo(f.getIndex());
                values.push(new ValueInfo(f.getFieldType(cpg), field.getValue()));
                break;
            }
        case Constants.PUTFIELD:
            values.pop();
        case Constants.PUTSTATIC:
            {
                FieldInstruction f = (FieldInstruction) instruction;
                values.pop(f.getFieldType(cpg).getSize());
                break;
            }
        case Constants.INVOKEVIRTUAL:
        case Constants.INVOKEINTERFACE:
        case Constants.INVOKESPECIAL:
            values.pop();
        case Constants.INVOKESTATIC:
            {
                InvokeInstruction invoke = (InvokeInstruction) instruction;
                values.pop(TypeHelper.getNumSlots(invoke.getArgumentTypes(cpg)));
                values.push(new ValueInfo(invoke.getReturnType(cpg)));
                break;
            }
        case Constants.MONITORENTER:
        case Constants.MONITOREXIT:
            values.pop();
            break;
        case Constants.ATHROW:
            ValueInfo ref = values.pop();
            values.clearStack();
            values.push(ref);
            break;
        case Constants.CHECKCAST:
            break;
        case Constants.INSTANCEOF:
            values.pop();
            values.push(new ValueInfo(Type.INT));
            break;
        case Constants.NEW:
            values.push(new ValueInfo(((NEW) instruction).getType(cpg)));
            break;
        case Constants.NEWARRAY:
            {
                Type t = ((NEWARRAY) instruction).getType();
                values.push(new ValueInfo(new ArrayType(t, 1)));
                break;
            }
        case Constants.ANEWARRAY:
            {
                Type t = ((ANEWARRAY) instruction).getType(cpg);
                values.push(new ValueInfo(new ArrayType(t, 1)));
                break;
            }
        case Constants.MULTIANEWARRAY:
            {
                MULTIANEWARRAY instr = (MULTIANEWARRAY) instruction;
                values.pop(instr.getDimensions());
                values.push(new ValueInfo(new ArrayType(instr.getType(cpg), instr.getDimensions())));
                break;
            }
        case Constants.ARRAYLENGTH:
            values.pop();
            values.push(new ValueInfo(Type.INT));
            break;
        default:
            throw new AppInfoError("Instruction not supported: " + instruction);
    }
}
Also used : NEW(org.apache.bcel.generic.NEW) ConstantDoubleInfo(com.jopdesign.common.type.ConstantDoubleInfo) MULTIANEWARRAY(org.apache.bcel.generic.MULTIANEWARRAY) ConstantIntegerInfo(com.jopdesign.common.type.ConstantIntegerInfo) ConstantFloatInfo(com.jopdesign.common.type.ConstantFloatInfo) ConstantFieldInfo(com.jopdesign.common.type.ConstantFieldInfo) ConstantLongInfo(com.jopdesign.common.type.ConstantLongInfo) AppInfoError(com.jopdesign.common.misc.AppInfoError) ArrayType(org.apache.bcel.generic.ArrayType) CPInstruction(org.apache.bcel.generic.CPInstruction) InvokeInstruction(org.apache.bcel.generic.InvokeInstruction) LoadInstruction(org.apache.bcel.generic.LoadInstruction) Type(org.apache.bcel.generic.Type) ArrayType(org.apache.bcel.generic.ArrayType) ValueInfo(com.jopdesign.common.type.ValueInfo) IINC(org.apache.bcel.generic.IINC) FieldInstruction(org.apache.bcel.generic.FieldInstruction) ConstantPushInstruction(org.apache.bcel.generic.ConstantPushInstruction) StoreInstruction(org.apache.bcel.generic.StoreInstruction)

Example 3 with ValueInfo

use of com.jopdesign.common.type.ValueInfo in project jop by jop-devel.

the class ValueMapAnalysis method loadParameters.

public void loadParameters() {
    values.clear();
    if (!methodInfo.isStatic()) {
        values.addLocalValue(new ValueInfo(methodInfo));
    }
    int i = 0;
    for (Type type : methodInfo.getArgumentTypes()) {
        values.addLocalValue(new ValueInfo(type, i++));
    }
}
Also used : Type(org.apache.bcel.generic.Type) ArrayType(org.apache.bcel.generic.ArrayType) ValueInfo(com.jopdesign.common.type.ValueInfo)

Example 4 with ValueInfo

use of com.jopdesign.common.type.ValueInfo in project jop by jop-devel.

the class SimpleInliner method analyzeInvokeSite.

/**
     * Check if the invokesite can be modified in a way so that the parameters are passed in the correct order
     * @param invokeSite the invokesite to inline.
     * @param invokee the invoked method.
     * @param inlineData the map to store the analyzer results
     * @return true if the prologue can be changed to match the expected behaviour
     */
private boolean analyzeInvokeSite(InvokeSite invokeSite, MethodInfo invokee, InlineData inlineData) {
    MethodInfo invoker = invokeSite.getInvoker();
    ConstantPoolGen invokerCpg = invoker.getConstantPoolGen();
    InstructionHandle invoke = invokeSite.getInstructionHandle();
    // Check epilogue
    Type[] ret = StackHelper.produceStack(invokerCpg, invoke.getInstruction());
    // works if the invoked method returns the same (single) type as the replaced instruction..
    boolean match = (ret.length == 1 && TypeHelper.canAssign(invokee.getType(), ret[0]));
    //    return something but doesn't then it is a JVM call and throws an exception.
    if (!match && !invokee.getType().equals(Type.VOID)) {
        return false;
    }
    // Check and build prologue
    Type[] args = StackHelper.consumeStack(invokerCpg, invoke.getInstruction());
    List<Instruction> oldPrologue = new LinkedList<Instruction>();
    int cnt = 0;
    InstructionHandle current = invoke;
    while (cnt < args.length) {
        if (current.hasTargeters()) {
            // stay within the basic block
            break;
        }
        current = current.getPrev();
        Instruction instr = current.getInstruction();
        // we only rearrange push-instructions
        if (!(instr instanceof PushInstruction) || (instr instanceof DUP) || (instr instanceof DUP2)) {
            break;
        }
        // we add this instruction to the old prologue to replace
        cnt++;
        oldPrologue.add(0, instr);
    }
    inlineData.setOldPrologueLength(cnt);
    List<ValueInfo> params = inlineData.getParams();
    // other parameters must be used in the order they are pushed on the stack, we do not rearrange them
    int offset = args.length - cnt;
    for (int i = 0; i < offset; i++) {
        if (i >= params.size()) {
            Type t = args[i];
            // unused argument, we cannot remove the push instruction so we pop it
            inlineData.addPrologue(t.getSize() == 2 ? new POP2() : new POP());
        } else {
            ValueInfo value = params.get(i);
            int argNum = value.getParamNr();
            if (!invokee.isStatic()) {
                argNum++;
            }
            if (argNum != i) {
                return false;
            }
        }
    }
    // Now, we create a new prologue using the expected argument values and the old push instructions
    for (int i = offset; i < params.size(); i++) {
        ValueInfo value = params.get(i);
        if (value.isThisReference() || value.isParamReference()) {
            int argNum = value.getParamNr();
            if (!invokee.isStatic()) {
                argNum++;
            }
            if (argNum < offset) {
                // loading a param a second time which we do not duplicate, cannot inline this
                return false;
            }
            // To be on the safe side, copy the instruction in case a param is used more than once
            Instruction instr = oldPrologue.get(argNum - offset).copy();
            inlineData.addPrologue(instr);
        } else if (value.isNullReference()) {
            inlineData.addPrologue(InstructionConstants.ACONST_NULL);
        } else if (value.isConstantValue() || value.isStaticFieldReference()) {
            // We need to push a constant on the stack
            Instruction instr = value.getConstantValue().createPushInstruction(invoker.getConstantPoolGen());
            inlineData.addPrologue(instr);
        } else if (!value.isContinued()) {
            throw new AssertionError("Unhandled value type");
        }
    }
    return true;
}
Also used : POP2(org.apache.bcel.generic.POP2) 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) PushInstruction(org.apache.bcel.generic.PushInstruction) InstructionHandle(org.apache.bcel.generic.InstructionHandle) LinkedList(java.util.LinkedList) POP(org.apache.bcel.generic.POP) ConstantPoolGen(org.apache.bcel.generic.ConstantPoolGen) Type(org.apache.bcel.generic.Type) DUP2(org.apache.bcel.generic.DUP2) ValueInfo(com.jopdesign.common.type.ValueInfo) MethodInfo(com.jopdesign.common.MethodInfo) DUP(org.apache.bcel.generic.DUP)

Example 5 with ValueInfo

use of com.jopdesign.common.type.ValueInfo 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

ValueInfo (com.jopdesign.common.type.ValueInfo)5 FieldInstruction (org.apache.bcel.generic.FieldInstruction)4 InvokeInstruction (org.apache.bcel.generic.InvokeInstruction)4 Type (org.apache.bcel.generic.Type)4 Instruction (org.apache.bcel.generic.Instruction)3 InstructionHandle (org.apache.bcel.generic.InstructionHandle)3 InvokeSite (com.jopdesign.common.code.InvokeSite)2 ValueMapAnalysis (com.jopdesign.jcopter.analysis.ValueMapAnalysis)2 ArithmeticInstruction (org.apache.bcel.generic.ArithmeticInstruction)2 ArrayType (org.apache.bcel.generic.ArrayType)2 ConstantPushInstruction (org.apache.bcel.generic.ConstantPushInstruction)2 ConversionInstruction (org.apache.bcel.generic.ConversionInstruction)2 GETFIELD (org.apache.bcel.generic.GETFIELD)2 InstructionList (org.apache.bcel.generic.InstructionList)2 POP (org.apache.bcel.generic.POP)2 POP2 (org.apache.bcel.generic.POP2)2 PUTFIELD (org.apache.bcel.generic.PUTFIELD)2 PushInstruction (org.apache.bcel.generic.PushInstruction)2 ReturnInstruction (org.apache.bcel.generic.ReturnInstruction)2 StackInstruction (org.apache.bcel.generic.StackInstruction)2