Search in sources :

Example 31 with InstructionList

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

the class ReplaceIinc method replace.

private void replace(MethodInfo method) {
    MethodCode mc = method.getCode();
    InstructionList il = mc.getInstructionList();
    InstructionFinder f = new InstructionFinder(il);
    for (Iterator i = f.search("IINC"); i.hasNext(); ) {
        InstructionHandle[] match = (InstructionHandle[]) i.next();
        InstructionHandle ih = match[0];
        IINC ii = (IINC) ih.getInstruction();
        int idx = ii.getIndex();
        int inc = ii.getIncrement();
        //  	    IINC rep = new IINC(idx, inc);
        ih.setInstruction(new ILOAD(idx));
        if (inc >= -1 && inc <= 5) {
            ih = il.append(ih, new ICONST(inc));
        } else if (inc >= -128 && inc < 127) {
            ih = il.append(ih, new BIPUSH((byte) inc));
        } else if (inc >= -32768 && inc < 32767) {
            ih = il.append(ih, new SIPUSH((short) inc));
        } else {
            System.out.println("IINC constant too big");
            System.exit(-1);
        }
        ih = il.append(ih, new IADD());
        ih = il.append(ih, new ISTORE(idx));
    }
    method.compile();
}
Also used : InstructionList(org.apache.bcel.generic.InstructionList) ILOAD(org.apache.bcel.generic.ILOAD) InstructionFinder(org.apache.bcel.util.InstructionFinder) BIPUSH(org.apache.bcel.generic.BIPUSH) InstructionHandle(org.apache.bcel.generic.InstructionHandle) ISTORE(org.apache.bcel.generic.ISTORE) IINC(org.apache.bcel.generic.IINC) Iterator(java.util.Iterator) IADD(org.apache.bcel.generic.IADD) MethodCode(com.jopdesign.common.MethodCode) SIPUSH(org.apache.bcel.generic.SIPUSH) ICONST(org.apache.bcel.generic.ICONST)

Example 32 with InstructionList

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

the class DFATool method loadMethod.

private void loadMethod(MethodInfo method) {
    MethodCode mcode = method.getCode();
    // TODO is there a better way to get an instruction handle? Do we need to keep the list somehow?
    InstructionHandle exit;
    exit = (InstructionHandle) method.getCustomValue(KEY_NOP);
    // we reuse the NOP if it exists, so that we can have multiple DFAs running at the same time
    if (exit == null) {
        exit = new InstructionList(new NOP()).getStart();
        // We do not really want to modify the REAL instruction list and append exit
        // (SH) Fixed :) Yep, we need the NOP somewhere, else doInvoke() will collect the wrong result state.
        //      But we can eliminate the NOP by adding the instruction not to the list, but instead to the
        //      MethodInfo, and also retrieve it from there.
        method.setCustomValue(KEY_NOP, exit);
    }
    this.getStatements().add(exit);
    // We do not modify the code, so we leave existing CFGs alone, just make sure the instruction list is uptodate
    InstructionList il = mcode.getInstructionList(true, false);
    // we need correct positions for the DFA cache serialization stuff
    il.setPositions();
    for (Iterator<?> l = il.iterator(); l.hasNext(); ) {
        InstructionHandle handle = (InstructionHandle) l.next();
        this.getStatements().add(handle);
        Instruction instr = handle.getInstruction();
        if (instr instanceof BranchInstruction) {
            if (instr instanceof Select) {
                Select s = (Select) instr;
                InstructionHandle[] target = s.getTargets();
                for (InstructionHandle aTarget : target) {
                    this.getFlow().addEdge(new FlowEdge(handle, aTarget, FlowEdge.TRUE_EDGE));
                }
                this.getFlow().addEdge(new FlowEdge(handle, s.getTarget(), FlowEdge.FALSE_EDGE));
            } else {
                BranchInstruction b = (BranchInstruction) instr;
                this.getFlow().addEdge(new FlowEdge(handle, b.getTarget(), FlowEdge.TRUE_EDGE));
            }
        }
        if (handle.getNext() != null && !(instr instanceof UnconditionalBranch || instr instanceof Select || instr instanceof ReturnInstruction)) {
            if (instr instanceof BranchInstruction) {
                this.getFlow().addEdge(new FlowEdge(handle, handle.getNext(), FlowEdge.FALSE_EDGE));
            } else {
                this.getFlow().addEdge(new FlowEdge(handle, handle.getNext(), FlowEdge.NORMAL_EDGE));
            }
        }
        if (instr instanceof ReturnInstruction) {
            this.getFlow().addEdge(new FlowEdge(handle, exit, FlowEdge.NORMAL_EDGE));
        }
    }
}
Also used : FlowEdge(com.jopdesign.dfa.framework.FlowEdge) ReturnInstruction(org.apache.bcel.generic.ReturnInstruction) UnconditionalBranch(org.apache.bcel.generic.UnconditionalBranch) BranchInstruction(org.apache.bcel.generic.BranchInstruction) InstructionList(org.apache.bcel.generic.InstructionList) Select(org.apache.bcel.generic.Select) MethodCode(com.jopdesign.common.MethodCode) Instruction(org.apache.bcel.generic.Instruction) BranchInstruction(org.apache.bcel.generic.BranchInstruction) ReturnInstruction(org.apache.bcel.generic.ReturnInstruction) InstructionHandle(org.apache.bcel.generic.InstructionHandle) NOP(org.apache.bcel.generic.NOP)

Example 33 with InstructionList

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

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

the class PeepholeOptimizer method optimizeMethod.

@Override
public void optimizeMethod(MethodInfo method) {
    InstructionList il = method.getCode().getInstructionList();
    // BCEL Example optimization
    optimizeBoolExpressions(il);
}
Also used : InstructionList(org.apache.bcel.generic.InstructionList)

Example 35 with InstructionList

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

the class HashTest method main.

public static void main(String[] args) {
    TestFramework test = new TestFramework();
    AppSetup setup = test.setupAppSetup();
    AppInfo appInfo = test.setupAppInfo("common.code.HashTest", false);
    ClassInfo testClass = appInfo.loadClass("common.TestFramework");
    MethodInfo mainMethod = appInfo.getMainMethod();
    MethodCode code = mainMethod.getCode();
    InstructionHandle[] ih = code.getInstructionList().getInstructionHandles();
    InvokeSite i1 = code.getInvokeSite(ih[1]);
    InvokeSite i2 = code.getInvokeSite(ih[2]);
    InvokeSite i3 = code.getInvokeSite(ih[3]);
    InvokeSite i11 = code.getInvokeSite(ih[1]);
    check(i1 == i11);
    CallString c1 = new CallString(i1);
    CallString c2 = new CallString(i2);
    CallString c11 = new CallString(i1);
    check(c1.equals(c11));
    check(!c1.equals(c2));
    ExecutionContext e1 = new ExecutionContext(mainMethod, c1);
    ExecutionContext e2 = new ExecutionContext(mainMethod, c2);
    ExecutionContext e11 = new ExecutionContext(mainMethod, c11);
    check(e1.equals(e11));
    check(!e1.equals(e2));
    // TODO put stuff into maps, check contains() and get()
    // modify instruction list, check if everything still works
    InstructionList il = code.getInstructionList();
    il.insert(new ILOAD(0));
    il.insert(ih[2], new ILOAD(1));
    ih = il.getInstructionHandles();
    InvokeSite i12 = code.getInvokeSite(ih[2]);
    InvokeSite i22 = code.getInvokeSite(ih[4]);
    check(i12 == i1);
    check(i22 == i2);
    check(e1.equals(e11));
    check(!e1.equals(e2));
    il.setPositions();
    check(c1.equals(c11));
    check(!c1.equals(c2));
    check(e1.equals(e11));
    check(!e1.equals(e2));
}
Also used : InstructionList(org.apache.bcel.generic.InstructionList) ILOAD(org.apache.bcel.generic.ILOAD) InstructionHandle(org.apache.bcel.generic.InstructionHandle) AppInfo(com.jopdesign.common.AppInfo) TestFramework(com.jopdesign.common.TestFramework) AppSetup(com.jopdesign.common.AppSetup) MethodInfo(com.jopdesign.common.MethodInfo) MethodCode(com.jopdesign.common.MethodCode) ClassInfo(com.jopdesign.common.ClassInfo)

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