Search in sources :

Example 1 with TargetLostException

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

the class ReplaceAtomicAnnotation method transform.

public static Method transform(Method m, JavaClass clazz, ConstantPoolGen _cp) {
    MethodGen method = new MethodGen(m, clazz.getClassName(), _cp);
    InstructionList oldIl = method.getInstructionList();
    Type returnType = m.getReturnType();
    if (returnType.equals(Type.LONG) || returnType.equals(Type.DOUBLE)) {
        throw new UnsupportedOperationException();
    }
    final int transactionLocals = 2;
    /*
		 * local variable indices:
		 * isNotNestedTransaction is -2+2
		 * result is -2+3
		 * Throwable e is -2+3 
		 */
    final int maxLocals = method.getMaxLocals();
    final int transactionLocalsBaseIndex = maxLocals;
    final int copyBaseIndex = transactionLocalsBaseIndex + transactionLocals;
    SortedSet<Integer> modifiedArguments = getModifiedArguments(method);
    // maps modified arguments indices to copies
    Map<Integer, Integer> modifiedArgumentsCopies = new TreeMap<Integer, Integer>();
    {
        int copyIndex = copyBaseIndex;
        for (Integer i : modifiedArguments) {
            System.out.println("RTTM: method " + method.getClassName() + "." + method.getName() + method.getSignature() + ": saving argument " + i + " to variable " + copyIndex);
            modifiedArgumentsCopies.put(i, copyIndex++);
        }
    }
    InstructionList il = new InstructionList();
    InstructionFactory _factory = new InstructionFactory(_cp);
    method.setInstructionList(il);
    {
        //			InstructionHandle ih_0 = il.append(new PUSH(_cp, -559038737));
        //			il.append(_factory.createStore(Type.INT, transactionLocalsBaseIndex-2+1));
        InstructionHandle ih_3 = il.append(_factory.createFieldAccess("rttm.internal.Utils", "inTransaction", new ArrayType(Type.BOOLEAN, 1), Constants.GETSTATIC));
        il.append(new PUSH(_cp, -122));
        il.append(_factory.createInvoke("com.jopdesign.sys.Native", "rd", Type.INT, new Type[] { Type.INT }, Constants.INVOKESTATIC));
        il.append(InstructionConstants.BALOAD);
        BranchInstruction ifne_12 = InstructionFactory.createBranchInstruction(Constants.IFNE, null);
        il.append(ifne_12);
        il.append(new PUSH(_cp, 1));
        BranchInstruction goto_16 = InstructionFactory.createBranchInstruction(Constants.GOTO, null);
        il.append(goto_16);
        InstructionHandle ih_19 = il.append(new PUSH(_cp, 0));
        InstructionHandle ih_20 = il.append(InstructionFactory.createStore(Type.INT, transactionLocalsBaseIndex - 2 + 2));
        InstructionHandle ih_21 = il.append(InstructionFactory.createLoad(Type.INT, transactionLocalsBaseIndex - 2 + 2));
        BranchInstruction ifeq_22 = InstructionFactory.createBranchInstruction(Constants.IFEQ, null);
        il.append(ifeq_22);
        //			InstructionHandle ih_25 = il.append(_factory.createLoad(Type.INT, transactionLocalsBaseIndex-2+0));
        //			il.append(_factory.createStore(Type.INT, transactionLocalsBaseIndex-2+1));
        {
            // only save arguments which might be modified
            for (int i : modifiedArguments) {
                il.append(InstructionFactory.createLoad(Type.INT, i));
                il.append(InstructionFactory.createStore(Type.INT, modifiedArgumentsCopies.get(i)));
            }
        }
        InstructionHandle ih_27 = il.append(new PUSH(_cp, 0));
        il.append(new PUSH(_cp, -128));
        il.append(_factory.createInvoke("com.jopdesign.sys.Native", "wr", Type.VOID, new Type[] { Type.INT, Type.INT }, Constants.INVOKESTATIC));
        InstructionHandle ih_33 = il.append(_factory.createFieldAccess("rttm.internal.Utils", "inTransaction", new ArrayType(Type.BOOLEAN, 1), Constants.GETSTATIC));
        il.append(new PUSH(_cp, -122));
        il.append(_factory.createInvoke("com.jopdesign.sys.Native", "rd", Type.INT, new Type[] { Type.INT }, Constants.INVOKESTATIC));
        il.append(new PUSH(_cp, 1));
        il.append(InstructionConstants.BASTORE);
        // transaction loop
        InstructionHandle ih_43 = il.append(InstructionFactory.createLoad(Type.INT, transactionLocalsBaseIndex - 2 + 2));
        BranchInstruction ifeq_44 = InstructionFactory.createBranchInstruction(Constants.IFEQ, null);
        il.append(ifeq_44);
        InstructionHandle ih_47 = il.append(new PUSH(_cp, 1));
        il.append(new PUSH(_cp, Const.MEM_TM_MAGIC));
        il.append(_factory.createInvoke("com.jopdesign.sys.Native", "wrMem", Type.VOID, new Type[] { Type.INT, Type.INT }, Constants.INVOKESTATIC));
        //			InstructionHandle ih_53 = il.append(_factory.createLoad(Type.INT, transactionLocalsBaseIndex-2+0));
        //			il.append(_factory.createInvoke("rttm.swtest.Transaction", "atomicSection", Type.INT, new Type[] { Type.INT }, Constants.INVOKESTATIC));
        //			il.append(_factory.createStore(Type.INT, transactionLocalsBaseIndex-2+3));
        InstructionHandle ih_53 = oldIl.getStart();
        Collection<BranchInstruction> gotos_transactionCommit = new ArrayList<BranchInstruction>();
        {
            // redirect returns
            InstructionFinder f = new InstructionFinder(oldIl);
            String returnInstructionsPattern = "ARETURN|IRETURN|FRETURN|RETURN";
            for (Iterator i = f.search(returnInstructionsPattern); i.hasNext(); ) {
                InstructionHandle oldIh = ((InstructionHandle[]) i.next())[0];
                InstructionList nl = new InstructionList();
                if (!method.getReturnType().equals(Type.VOID)) {
                    nl.append(InstructionFactory.createStore(method.getReturnType(), transactionLocalsBaseIndex - 2 + 3));
                }
                BranchInstruction goto_transactionCommit = InstructionFactory.createBranchInstruction(Constants.GOTO, null);
                nl.append(goto_transactionCommit);
                gotos_transactionCommit.add(goto_transactionCommit);
                InstructionHandle newTarget = nl.getStart();
                oldIl.append(oldIh, nl);
                try {
                    oldIl.delete(oldIh);
                } catch (TargetLostException e) {
                    InstructionHandle[] targets = e.getTargets();
                    for (int k = 0; k < targets.length; k++) {
                        InstructionTargeter[] targeters = targets[k].getTargeters();
                        for (int j = 0; j < targeters.length; j++) {
                            targeters[j].updateTarget(targets[k], newTarget);
                        }
                    }
                }
            }
            il.append(oldIl);
        }
        InstructionHandle ih_58 = il.append(InstructionFactory.createLoad(Type.INT, transactionLocalsBaseIndex - 2 + 2));
        BranchInstruction ifeq_59 = InstructionFactory.createBranchInstruction(Constants.IFEQ, null);
        il.append(ifeq_59);
        InstructionHandle ih_62 = il.append(new PUSH(_cp, 0));
        il.append(new PUSH(_cp, Const.MEM_TM_MAGIC));
        il.append(_factory.createInvoke("com.jopdesign.sys.Native", "wrMem", Type.VOID, new Type[] { Type.INT, Type.INT }, Constants.INVOKESTATIC));
        InstructionHandle ih_68 = il.append(_factory.createFieldAccess("rttm.internal.Utils", "inTransaction", new ArrayType(Type.BOOLEAN, 1), Constants.GETSTATIC));
        il.append(new PUSH(_cp, -122));
        il.append(_factory.createInvoke("com.jopdesign.sys.Native", "rd", Type.INT, new Type[] { Type.INT }, Constants.INVOKESTATIC));
        il.append(new PUSH(_cp, 0));
        il.append(InstructionConstants.BASTORE);
        InstructionHandle ih_78 = il.append(new PUSH(_cp, 1));
        il.append(new PUSH(_cp, -128));
        il.append(_factory.createInvoke("com.jopdesign.sys.Native", "wr", Type.VOID, new Type[] { Type.INT, Type.INT }, Constants.INVOKESTATIC));
        //			InstructionHandle ih_84 = il.append(_factory.createLoad(Type.INT, transactionLocalsBaseIndex-2+3));
        //			il.append(_factory.createReturn(Type.INT));
        InstructionHandle ih_84;
        {
            // return
            if (!method.getReturnType().equals(Type.VOID)) {
                ih_84 = il.append(InstructionFactory.createLoad(method.getReturnType(), transactionLocalsBaseIndex - 2 + 3));
                il.append(InstructionFactory.createReturn(method.getReturnType()));
            } else {
                ih_84 = il.append(InstructionFactory.createReturn(method.getReturnType()));
            }
        }
        // catch block
        // variable e has index 3
        // } catch (Throwable e) {
        InstructionHandle nih_86 = il.append(InstructionFactory.createStore(Type.OBJECT, transactionLocalsBaseIndex - 2 + 3));
        // if (isNotNestedTransaction) {
        InstructionHandle nih_87 = il.append(InstructionFactory.createLoad(Type.INT, transactionLocalsBaseIndex - 2 + 2));
        BranchInstruction ifeq_88 = InstructionFactory.createBranchInstruction(Constants.IFEQ, null);
        il.append(ifeq_88);
        InstructionHandle nih_91 = il.append(InstructionFactory.createLoad(Type.OBJECT, transactionLocalsBaseIndex - 2 + 3));
        il.append(_factory.createFieldAccess("com.jopdesign.sys.RetryException", "instance", new ObjectType("com.jopdesign.sys.RetryException"), Constants.GETSTATIC));
        BranchInstruction if_acmpne_95 = InstructionFactory.createBranchInstruction(Constants.IF_ACMPNE, null);
        il.append(if_acmpne_95);
        // InstructionHandle nih_98 = il.append(_factory.createLoad(Type.INT,
        // 1));
        // il.append(_factory.createStore(Type.INT, 0));
        {
            for (int i : modifiedArguments) {
                il.append(InstructionFactory.createLoad(Type.INT, modifiedArgumentsCopies.get(i)));
                il.append(InstructionFactory.createStore(Type.INT, i));
            }
        }
        BranchInstruction goto_110 = InstructionFactory.createBranchInstruction(Constants.GOTO, ih_43);
        InstructionHandle ih_110 = il.append(goto_110);
        // exception was manually aborted or a bug triggered
        InstructionHandle nih_103 = il.append(_factory.createFieldAccess("rttm.internal.Utils", "inTransaction", new ArrayType(Type.BOOLEAN, 1), Constants.GETSTATIC));
        il.append(new PUSH(_cp, -122));
        il.append(_factory.createInvoke("com.jopdesign.sys.Native", "rd", Type.INT, new Type[] { Type.INT }, Constants.INVOKESTATIC));
        il.append(new PUSH(_cp, 0));
        il.append(InstructionConstants.BASTORE);
        InstructionHandle nih_113 = il.append(new PUSH(_cp, 1));
        il.append(new PUSH(_cp, -128));
        il.append(_factory.createInvoke("com.jopdesign.sys.Native", "wrMem", Type.VOID, new Type[] { Type.INT, Type.INT }, Constants.INVOKESTATIC));
        InstructionHandle nih_119 = il.append(InstructionFactory.createLoad(Type.OBJECT, transactionLocalsBaseIndex - 2 + 3));
        // il.append(_factory.createCheckCast(new
        // ObjectType("java.lang.RuntimeException")));
        il.append(InstructionConstants.ATHROW);
        // set branch targets			
        ifne_12.setTarget(ih_19);
        goto_16.setTarget(ih_20);
        ifeq_22.setTarget(ih_43);
        ifeq_44.setTarget(ih_53);
        ifeq_59.setTarget(ih_84);
        ifeq_88.setTarget(nih_119);
        if_acmpne_95.setTarget(nih_103);
        {
            for (BranchInstruction b : gotos_transactionCommit) {
                b.setTarget(ih_58);
            }
        }
        // set exception handlers 
        // TODO restrict exception handler
        method.addExceptionHandler(ih_53, ih_84, nih_86, null);
        method.setMaxStack();
        method.setMaxLocals();
    }
    m = method.getMethod();
    oldIl.dispose();
    il.dispose();
    return m;
}
Also used : BranchInstruction(org.apache.bcel.generic.BranchInstruction) InstructionList(org.apache.bcel.generic.InstructionList) InstructionFinder(org.apache.bcel.util.InstructionFinder) TreeMap(java.util.TreeMap) MethodGen(org.apache.bcel.generic.MethodGen) InstructionHandle(org.apache.bcel.generic.InstructionHandle) InstructionFactory(org.apache.bcel.generic.InstructionFactory) ArrayType(org.apache.bcel.generic.ArrayType) ObjectType(org.apache.bcel.generic.ObjectType) Type(org.apache.bcel.generic.Type) ObjectType(org.apache.bcel.generic.ObjectType) ArrayType(org.apache.bcel.generic.ArrayType) Iterator(java.util.Iterator) Collection(java.util.Collection) TargetLostException(org.apache.bcel.generic.TargetLostException) PUSH(org.apache.bcel.generic.PUSH)

Example 2 with TargetLostException

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

the class MethodCode method replace.

/**
     * Replace instructions in this code with an instruction list or a part of it.
     * If the number of instructions to replace differs from the number of source instructions, instruction
     * handles will be removed or inserted appropriately and the targets will be updated.
     * <p>
     *     Instruction handles will be reused, so attached values and targets will not be lost if the new length is not
     *     shorter than the old length. Else instruction handles are removed and the targeters to removed instructions
     *     are updated to the instruction after the next instruction after the deleted instructions.
     * </p>
     *
     * @param replaceStart the first instruction in this code to replace
     * @param replaceCount the number of instructions in this code to replace
     * @param sourceInfo the MethodInfo containing the source instruction. If non-null, the instructions will be copied
     *                   using the constant pool from the given MethodInfo. If null, the instructions will not be copied.
     * @param sourceStart the first instruction in the source list to use for replacing the code.
     * @param sourceCount the number of instructions to use from the source.
     * @param copyCustomValues if true copy the custom values from the source.
     * @return the first handle in the target list after the inserted code, or null if the last instruction in this
     *         list has been replaced.
     */
public InstructionHandle replace(InstructionHandle replaceStart, int replaceCount, MethodInfo sourceInfo, InstructionHandle sourceStart, int sourceCount, boolean copyCustomValues) {
    InstructionList il = getInstructionList();
    InstructionHandle current = replaceStart;
    InstructionHandle currSource = sourceStart;
    // update the common prefix
    int cnt = Math.min(replaceCount, sourceCount);
    for (int i = 0; i < cnt; i++) {
        Instruction instr;
        if (sourceInfo != null) {
            instr = copyFrom(sourceInfo.getClassInfo(), currSource.getInstruction());
        } else {
            instr = currSource.getInstruction();
        }
        // TODO support branch instructions! need to replace the IH too
        current.setInstruction(instr);
        if (copyCustomValues) {
            copyCustomValues(sourceInfo, current, currSource);
        }
        current = current.getNext();
        currSource = currSource.getNext();
    }
    InstructionHandle next = current;
    // Case 1: delete unused handles, update targets to next instruction
    if (replaceCount > sourceCount) {
        int rest = replaceCount - sourceCount;
        for (int i = 1; i < rest; i++) {
            next = next.getNext();
        }
        InstructionHandle end = next;
        next = next.getNext();
        try {
            // we cannot use next.getPrev, since next might be null
            il.delete(current, end);
        } catch (TargetLostException e) {
            retarget(e, next);
        }
    }
    // Case 2: insert new handles for rest of source
    if (replaceCount < sourceCount) {
        int rest = sourceCount - replaceCount;
        for (int i = 0; i < rest; i++) {
            Instruction instr;
            if (sourceInfo != null) {
                instr = copyFrom(sourceInfo.getClassInfo(), currSource.getInstruction());
            } else {
                instr = currSource.getInstruction();
            }
            if (next == null) {
                current = il.append(instr);
            } else {
                current = il.insert(next, instr);
            }
            if (copyCustomValues) {
                copyCustomValues(sourceInfo, current, currSource);
            }
            currSource = currSource.getNext();
        }
    }
    return next;
}
Also used : InstructionList(org.apache.bcel.generic.InstructionList) InvokeInstruction(org.apache.bcel.generic.InvokeInstruction) Instruction(org.apache.bcel.generic.Instruction) FieldInstruction(org.apache.bcel.generic.FieldInstruction) CPInstruction(org.apache.bcel.generic.CPInstruction) TargetLostException(org.apache.bcel.generic.TargetLostException) InstructionHandle(org.apache.bcel.generic.InstructionHandle)

Example 3 with TargetLostException

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

the class PeepholeOptimizer method optimizeBoolExpressions.

/**
     * Optimize some boolean expressions.
     * <p>
     * This code is taken directly from the BCEL manual, chapter 3.3.8.
     * </p>
     *
     * @param il the instruction list to optimize.
     */
private void optimizeBoolExpressions(InstructionList il) {
    InstructionFinder f = new InstructionFinder(il);
    String pat = "IfInstruction ICONST_0 GOTO ICONST_1 NOP(IFEQ|IFNE)";
    CodeConstraint constraint = new CodeConstraint() {

        @Override
        public boolean checkCode(InstructionHandle[] match) {
            IfInstruction if1 = (IfInstruction) match[0].getInstruction();
            GOTO g = (GOTO) match[2].getInstruction();
            return (if1.getTarget() == match[3]) && (g.getTarget() == match[4]);
        }
    };
    for (Iterator e = f.search(pat, constraint); e.hasNext(); ) {
        InstructionHandle[] match = (InstructionHandle[]) e.next();
        IfInstruction if1 = (IfInstruction) match[0].getInstruction();
        IfInstruction if2 = (IfInstruction) match[5].getInstruction();
        // Update target
        if1.setTarget(if2.getTarget());
        try {
            il.delete(match[1], match[5]);
        } catch (TargetLostException ex) {
            for (InstructionHandle target : ex.getTargets()) {
                for (InstructionTargeter t : target.getTargeters()) {
                    t.updateTarget(target, match[0]);
                }
            }
        }
        matchBoolExpressions++;
    }
}
Also used : GOTO(org.apache.bcel.generic.GOTO) InstructionTargeter(org.apache.bcel.generic.InstructionTargeter) IfInstruction(org.apache.bcel.generic.IfInstruction) Iterator(java.util.Iterator) CodeConstraint(org.apache.bcel.util.InstructionFinder.CodeConstraint) InstructionFinder(org.apache.bcel.util.InstructionFinder) TargetLostException(org.apache.bcel.generic.TargetLostException) InstructionHandle(org.apache.bcel.generic.InstructionHandle)

Aggregations

InstructionHandle (org.apache.bcel.generic.InstructionHandle)3 TargetLostException (org.apache.bcel.generic.TargetLostException)3 Iterator (java.util.Iterator)2 InstructionList (org.apache.bcel.generic.InstructionList)2 InstructionFinder (org.apache.bcel.util.InstructionFinder)2 Collection (java.util.Collection)1 TreeMap (java.util.TreeMap)1 ArrayType (org.apache.bcel.generic.ArrayType)1 BranchInstruction (org.apache.bcel.generic.BranchInstruction)1 CPInstruction (org.apache.bcel.generic.CPInstruction)1 FieldInstruction (org.apache.bcel.generic.FieldInstruction)1 GOTO (org.apache.bcel.generic.GOTO)1 IfInstruction (org.apache.bcel.generic.IfInstruction)1 Instruction (org.apache.bcel.generic.Instruction)1 InstructionFactory (org.apache.bcel.generic.InstructionFactory)1 InstructionTargeter (org.apache.bcel.generic.InstructionTargeter)1 InvokeInstruction (org.apache.bcel.generic.InvokeInstruction)1 MethodGen (org.apache.bcel.generic.MethodGen)1 ObjectType (org.apache.bcel.generic.ObjectType)1 PUSH (org.apache.bcel.generic.PUSH)1