Search in sources :

Example 6 with InsnList

use of com.android.dx.rop.code.InsnList in project J2ME-Loader by nikita36078.

the class Ropper method addSynchExceptionHandlerBlock.

/**
 * Constructs and adds, if necessary, the catch-all exception handler
 * block to deal with unwinding the lock taken on entry to a synchronized
 * method.
 */
private void addSynchExceptionHandlerBlock() {
    if (!synchNeedsExceptionHandler) {
        /*
             * The method being converted either isn't synchronized or
             * can't possibly throw exceptions in its main body, so
             * there's no need for a synchronized method exception
             * handler.
             */
        return;
    }
    SourcePosition pos = method.makeSourcePosistion(0);
    RegisterSpec exReg = RegisterSpec.make(0, Type.THROWABLE);
    BasicBlock bb;
    Insn insn;
    InsnList insns = new InsnList(2);
    insn = new PlainInsn(Rops.opMoveException(Type.THROWABLE), pos, exReg, RegisterSpecList.EMPTY);
    insns.set(0, insn);
    insn = new ThrowingInsn(Rops.MONITOR_EXIT, pos, RegisterSpecList.make(getSynchReg()), StdTypeList.EMPTY);
    insns.set(1, insn);
    insns.setImmutable();
    int label2 = getSpecialLabel(SYNCH_CATCH_2);
    bb = new BasicBlock(getSpecialLabel(SYNCH_CATCH_1), insns, IntList.makeImmutable(label2), label2);
    addBlock(bb, IntList.EMPTY);
    insns = new InsnList(1);
    insn = new ThrowingInsn(Rops.THROW, pos, RegisterSpecList.make(exReg), StdTypeList.EMPTY);
    insns.set(0, insn);
    insns.setImmutable();
    bb = new BasicBlock(label2, insns, IntList.EMPTY, -1);
    addBlock(bb, IntList.EMPTY);
}
Also used : PlainInsn(com.android.dx.rop.code.PlainInsn) ThrowingCstInsn(com.android.dx.rop.code.ThrowingCstInsn) ThrowingInsn(com.android.dx.rop.code.ThrowingInsn) PlainInsn(com.android.dx.rop.code.PlainInsn) Insn(com.android.dx.rop.code.Insn) PlainCstInsn(com.android.dx.rop.code.PlainCstInsn) SourcePosition(com.android.dx.rop.code.SourcePosition) BasicBlock(com.android.dx.rop.code.BasicBlock) InsnList(com.android.dx.rop.code.InsnList) ThrowingInsn(com.android.dx.rop.code.ThrowingInsn) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 7 with InsnList

use of com.android.dx.rop.code.InsnList in project J2ME-Loader by nikita36078.

the class Ropper method filterMoveReturnAddressInsns.

/**
 * Removes all {@code move-return-address} instructions, returning a new
 * {@code InsnList} if necessary. The {@code move-return-address}
 * insns are dead code after subroutines have been inlined.
 *
 * @param insns {@code InsnList} that may contain
 * {@code move-return-address} insns
 * @return {@code InsnList} with {@code move-return-address} removed
 */
private InsnList filterMoveReturnAddressInsns(InsnList insns) {
    int sz;
    int newSz = 0;
    // First see if we need to filter, and if so what the new size will be
    sz = insns.size();
    for (int i = 0; i < sz; i++) {
        if (insns.get(i).getOpcode() != Rops.MOVE_RETURN_ADDRESS) {
            newSz++;
        }
    }
    if (newSz == sz) {
        return insns;
    }
    // Make a new list without the MOVE_RETURN_ADDRESS insns
    InsnList newInsns = new InsnList(newSz);
    int newIndex = 0;
    for (int i = 0; i < sz; i++) {
        Insn insn = insns.get(i);
        if (insn.getOpcode() != Rops.MOVE_RETURN_ADDRESS) {
            newInsns.set(newIndex++, insn);
        }
    }
    newInsns.setImmutable();
    return newInsns;
}
Also used : ThrowingCstInsn(com.android.dx.rop.code.ThrowingCstInsn) ThrowingInsn(com.android.dx.rop.code.ThrowingInsn) PlainInsn(com.android.dx.rop.code.PlainInsn) Insn(com.android.dx.rop.code.Insn) PlainCstInsn(com.android.dx.rop.code.PlainCstInsn) InsnList(com.android.dx.rop.code.InsnList)

Example 8 with InsnList

use of com.android.dx.rop.code.InsnList in project J2ME-Loader by nikita36078.

the class Ropper method processBlock.

/**
 * Processes the given block.
 *
 * @param block {@code non-null;} block to process
 * @param frame {@code non-null;} start frame for the block
 * @param workSet {@code non-null;} bits representing work to do,
 * which this method may add to
 */
private void processBlock(ByteBlock block, Frame frame, int[] workSet) {
    // Prepare the list of caught exceptions for this block.
    ByteCatchList catches = block.getCatches();
    machine.startBlock(catches.toRopCatchList());
    /*
         * Using a copy of the given frame, simulate each instruction,
         * calling into machine for each.
         */
    frame = frame.copy();
    sim.simulate(block, frame);
    frame.setImmutable();
    int extraBlockCount = machine.getExtraBlockCount();
    ArrayList<Insn> insns = machine.getInsns();
    int insnSz = insns.size();
    /*
         * Merge the frame into each possible non-exceptional
         * successor.
         */
    int catchSz = catches.size();
    IntList successors = block.getSuccessors();
    int startSuccessorIndex;
    Subroutine calledSubroutine = null;
    if (machine.hasJsr()) {
        /*
             * If this frame ends in a JSR, only merge our frame with
             * the subroutine start, not the subroutine's return target.
             */
        startSuccessorIndex = 1;
        int subroutineLabel = successors.get(1);
        if (subroutines[subroutineLabel] == null) {
            subroutines[subroutineLabel] = new Subroutine(subroutineLabel);
        }
        subroutines[subroutineLabel].addCallerBlock(block.getLabel());
        calledSubroutine = subroutines[subroutineLabel];
    } else if (machine.hasRet()) {
        /*
             * This block ends in a ret, which means it's the final block
             * in some subroutine. Ultimately, this block will be copied
             * and inlined for each call and then disposed of.
             */
        ReturnAddress ra = machine.getReturnAddress();
        int subroutineLabel = ra.getSubroutineAddress();
        if (subroutines[subroutineLabel] == null) {
            subroutines[subroutineLabel] = new Subroutine(subroutineLabel, block.getLabel());
        } else {
            subroutines[subroutineLabel].addRetBlock(block.getLabel());
        }
        successors = subroutines[subroutineLabel].getSuccessors();
        subroutines[subroutineLabel].mergeToSuccessors(frame, workSet);
        // Skip processing below since we just did it.
        startSuccessorIndex = successors.size();
    } else if (machine.wereCatchesUsed()) {
        /*
             * If there are catches, then the first successors
             * (which will either be all of them or all but the last one)
             * are catch targets.
             */
        startSuccessorIndex = catchSz;
    } else {
        startSuccessorIndex = 0;
    }
    int succSz = successors.size();
    for (int i = startSuccessorIndex; i < succSz; i++) {
        int succ = successors.get(i);
        try {
            mergeAndWorkAsNecessary(succ, block.getLabel(), calledSubroutine, frame, workSet);
        } catch (SimException ex) {
            ex.addContext("...while merging to block " + Hex.u2(succ));
            throw ex;
        }
    }
    if ((succSz == 0) && machine.returns()) {
        /*
             * The block originally contained a return, but it has
             * been made to instead end with a goto, and we need to
             * tell it at this point that its sole successor is the
             * return block. This has to happen after the merge loop
             * above, since, at this point, the return block doesn't
             * actually exist; it gets synthesized at the end of
             * processing the original blocks.
             */
        successors = IntList.makeImmutable(getSpecialLabel(RETURN));
        succSz = 1;
    }
    int primarySucc;
    if (succSz == 0) {
        primarySucc = -1;
    } else {
        primarySucc = machine.getPrimarySuccessorIndex();
        if (primarySucc >= 0) {
            primarySucc = successors.get(primarySucc);
        }
    }
    /*
         * This variable is true only when the method is synchronized and
         * the block being processed can possibly throw an exception.
         */
    boolean synch = isSynchronized() && machine.canThrow();
    if (synch || (catchSz != 0)) {
        /*
             * Deal with exception handlers: Merge an exception-catch
             * frame into each possible exception handler, and
             * construct a new set of successors to point at the
             * exception handler setup blocks (which get synthesized
             * at the very end of processing).
             */
        boolean catchesAny = false;
        IntList newSucc = new IntList(succSz);
        for (int i = 0; i < catchSz; i++) {
            ByteCatchList.Item one = catches.get(i);
            CstType exceptionClass = one.getExceptionClass();
            int targ = one.getHandlerPc();
            catchesAny |= (exceptionClass == CstType.OBJECT);
            Frame f = frame.makeExceptionHandlerStartFrame(exceptionClass);
            try {
                mergeAndWorkAsNecessary(targ, block.getLabel(), null, f, workSet);
            } catch (SimException ex) {
                ex.addContext("...while merging exception to block " + Hex.u2(targ));
                throw ex;
            }
            /*
                 * Set up the exception handler type.
                 */
            CatchInfo handlers = catchInfos[targ];
            if (handlers == null) {
                handlers = new CatchInfo();
                catchInfos[targ] = handlers;
            }
            ExceptionHandlerSetup handler = handlers.getSetup(exceptionClass.getClassType());
            /*
                 * The synthesized exception setup block will have the label given by handler.
                 */
            newSucc.add(handler.getLabel());
        }
        if (synch && !catchesAny) {
            /*
                 * The method is synchronized and this block doesn't
                 * already have a catch-all handler, so add one to the
                 * end, both in the successors and in the throwing
                 * instruction(s) at the end of the block (which is where
                 * the caught classes live).
                 */
            newSucc.add(getSpecialLabel(SYNCH_CATCH_1));
            synchNeedsExceptionHandler = true;
            for (int i = insnSz - extraBlockCount - 1; i < insnSz; i++) {
                Insn insn = insns.get(i);
                if (insn.canThrow()) {
                    insn = insn.withAddedCatch(Type.OBJECT);
                    insns.set(i, insn);
                }
            }
        }
        if (primarySucc >= 0) {
            newSucc.add(primarySucc);
        }
        newSucc.setImmutable();
        successors = newSucc;
    }
    // Construct the final resulting block(s), and store it (them).
    int primarySuccListIndex = successors.indexOf(primarySucc);
    /*
         * If there are any extra blocks, work backwards through the
         * list of instructions, adding single-instruction blocks, and
         * resetting the successors variables as appropriate.
         */
    for (; /*extraBlockCount*/
    extraBlockCount > 0; extraBlockCount--) {
        /*
             * Some of the blocks that the RopperMachine wants added
             * are for move-result insns, and these need goto insns as well.
             */
        Insn extraInsn = insns.get(--insnSz);
        boolean needsGoto = extraInsn.getOpcode().getBranchingness() == Rop.BRANCH_NONE;
        InsnList il = new InsnList(needsGoto ? 2 : 1);
        IntList extraBlockSuccessors = successors;
        il.set(0, extraInsn);
        if (needsGoto) {
            il.set(1, new PlainInsn(Rops.GOTO, extraInsn.getPosition(), null, RegisterSpecList.EMPTY));
            /*
                 * Obviously, this block won't be throwing an exception
                 * so it should only have one successor.
                 */
            extraBlockSuccessors = IntList.makeImmutable(primarySucc);
        }
        il.setImmutable();
        int label = getAvailableLabel();
        BasicBlock bb = new BasicBlock(label, il, extraBlockSuccessors, primarySucc);
        // All of these extra blocks will be in the same subroutine
        addBlock(bb, frame.getSubroutines());
        successors = successors.mutableCopy();
        successors.set(primarySuccListIndex, label);
        successors.setImmutable();
        primarySucc = label;
    }
    Insn lastInsn = (insnSz == 0) ? null : insns.get(insnSz - 1);
    /*
         * Add a goto to the end of the block if it doesn't already
         * end with a branch, to maintain the invariant that all
         * blocks end with a branch of some sort or other. Note that
         * it is possible for there to be blocks for which no
         * instructions were ever output (e.g., only consist of pop*
         * in the original Java bytecode).
         */
    if ((lastInsn == null) || (lastInsn.getOpcode().getBranchingness() == Rop.BRANCH_NONE)) {
        SourcePosition pos = (lastInsn == null) ? SourcePosition.NO_INFO : lastInsn.getPosition();
        insns.add(new PlainInsn(Rops.GOTO, pos, null, RegisterSpecList.EMPTY));
        insnSz++;
    }
    /*
         * Construct a block for the remaining instructions (which in
         * the usual case is all of them).
         */
    InsnList il = new InsnList(insnSz);
    for (int i = 0; i < insnSz; i++) {
        il.set(i, insns.get(i));
    }
    il.setImmutable();
    BasicBlock bb = new BasicBlock(block.getLabel(), il, successors, primarySucc);
    addOrReplaceBlock(bb, frame.getSubroutines());
}
Also used : ThrowingCstInsn(com.android.dx.rop.code.ThrowingCstInsn) ThrowingInsn(com.android.dx.rop.code.ThrowingInsn) PlainInsn(com.android.dx.rop.code.PlainInsn) Insn(com.android.dx.rop.code.Insn) PlainCstInsn(com.android.dx.rop.code.PlainCstInsn) BasicBlock(com.android.dx.rop.code.BasicBlock) InsnList(com.android.dx.rop.code.InsnList) IntList(com.android.dx.util.IntList) PlainInsn(com.android.dx.rop.code.PlainInsn) CstType(com.android.dx.rop.cst.CstType) SourcePosition(com.android.dx.rop.code.SourcePosition)

Example 9 with InsnList

use of com.android.dx.rop.code.InsnList in project J2ME-Loader by nikita36078.

the class Ropper method addSetupBlocks.

/**
 * Constructs and adds the blocks that perform setup for the rest of
 * the method. This includes a first block which merely contains
 * assignments from parameters to the same-numbered registers and
 * a possible second block which deals with synchronization.
 */
private void addSetupBlocks() {
    LocalVariableList localVariables = method.getLocalVariables();
    SourcePosition pos = method.makeSourcePosistion(0);
    Prototype desc = method.getEffectiveDescriptor();
    StdTypeList params = desc.getParameterTypes();
    int sz = params.size();
    InsnList insns = new InsnList(sz + 1);
    int at = 0;
    for (int i = 0; i < sz; i++) {
        Type one = params.get(i);
        LocalVariableList.Item local = localVariables.pcAndIndexToLocal(0, at);
        RegisterSpec result = (local == null) ? RegisterSpec.make(at, one) : RegisterSpec.makeLocalOptional(at, one, local.getLocalItem());
        Insn insn = new PlainCstInsn(Rops.opMoveParam(one), pos, result, RegisterSpecList.EMPTY, CstInteger.make(at));
        insns.set(i, insn);
        at += one.getCategory();
    }
    insns.set(sz, new PlainInsn(Rops.GOTO, pos, null, RegisterSpecList.EMPTY));
    insns.setImmutable();
    boolean synch = isSynchronized();
    int label = synch ? getSpecialLabel(SYNCH_SETUP_1) : 0;
    BasicBlock bb = new BasicBlock(getSpecialLabel(PARAM_ASSIGNMENT), insns, IntList.makeImmutable(label), label);
    addBlock(bb, IntList.EMPTY);
    if (synch) {
        RegisterSpec synchReg = getSynchReg();
        Insn insn;
        if (isStatic()) {
            insn = new ThrowingCstInsn(Rops.CONST_OBJECT, pos, RegisterSpecList.EMPTY, StdTypeList.EMPTY, method.getDefiningClass());
            insns = new InsnList(1);
            insns.set(0, insn);
        } else {
            insns = new InsnList(2);
            insn = new PlainCstInsn(Rops.MOVE_PARAM_OBJECT, pos, synchReg, RegisterSpecList.EMPTY, CstInteger.VALUE_0);
            insns.set(0, insn);
            insns.set(1, new PlainInsn(Rops.GOTO, pos, null, RegisterSpecList.EMPTY));
        }
        int label2 = getSpecialLabel(SYNCH_SETUP_2);
        insns.setImmutable();
        bb = new BasicBlock(label, insns, IntList.makeImmutable(label2), label2);
        addBlock(bb, IntList.EMPTY);
        insns = new InsnList(isStatic() ? 2 : 1);
        if (isStatic()) {
            insns.set(0, new PlainInsn(Rops.opMoveResultPseudo(synchReg), pos, synchReg, RegisterSpecList.EMPTY));
        }
        insn = new ThrowingInsn(Rops.MONITOR_ENTER, pos, RegisterSpecList.make(synchReg), StdTypeList.EMPTY);
        insns.set(isStatic() ? 1 : 0, insn);
        insns.setImmutable();
        bb = new BasicBlock(label2, insns, IntList.makeImmutable(0), 0);
        addBlock(bb, IntList.EMPTY);
    }
}
Also used : ThrowingCstInsn(com.android.dx.rop.code.ThrowingCstInsn) ThrowingInsn(com.android.dx.rop.code.ThrowingInsn) PlainInsn(com.android.dx.rop.code.PlainInsn) Insn(com.android.dx.rop.code.Insn) PlainCstInsn(com.android.dx.rop.code.PlainCstInsn) Prototype(com.android.dx.rop.type.Prototype) ThrowingCstInsn(com.android.dx.rop.code.ThrowingCstInsn) BasicBlock(com.android.dx.rop.code.BasicBlock) InsnList(com.android.dx.rop.code.InsnList) ThrowingInsn(com.android.dx.rop.code.ThrowingInsn) PlainCstInsn(com.android.dx.rop.code.PlainCstInsn) PlainInsn(com.android.dx.rop.code.PlainInsn) Type(com.android.dx.rop.type.Type) CstType(com.android.dx.rop.cst.CstType) StdTypeList(com.android.dx.rop.type.StdTypeList) SourcePosition(com.android.dx.rop.code.SourcePosition) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 10 with InsnList

use of com.android.dx.rop.code.InsnList in project J2ME-Loader by nikita36078.

the class Ropper method addExceptionSetupBlocks.

/**
 * Creates the exception handler setup blocks. "maxLocals"
 * below is because that's the register number corresponding
 * to the sole element on a one-deep stack (which is the
 * situation at the start of an exception handler block).
 */
private void addExceptionSetupBlocks() {
    int len = catchInfos.length;
    for (int i = 0; i < len; i++) {
        CatchInfo catches = catchInfos[i];
        if (catches != null) {
            for (ExceptionHandlerSetup one : catches.getSetups()) {
                Insn proto = labelToBlock(i).getFirstInsn();
                SourcePosition pos = proto.getPosition();
                InsnList il = new InsnList(2);
                Insn insn = new PlainInsn(Rops.opMoveException(one.getCaughtType()), pos, RegisterSpec.make(maxLocals, one.getCaughtType()), RegisterSpecList.EMPTY);
                il.set(0, insn);
                insn = new PlainInsn(Rops.GOTO, pos, null, RegisterSpecList.EMPTY);
                il.set(1, insn);
                il.setImmutable();
                BasicBlock bb = new BasicBlock(one.getLabel(), il, IntList.makeImmutable(i), i);
                addBlock(bb, startFrames[i].getSubroutines());
            }
        }
    }
}
Also used : PlainInsn(com.android.dx.rop.code.PlainInsn) ThrowingCstInsn(com.android.dx.rop.code.ThrowingCstInsn) ThrowingInsn(com.android.dx.rop.code.ThrowingInsn) PlainInsn(com.android.dx.rop.code.PlainInsn) Insn(com.android.dx.rop.code.Insn) PlainCstInsn(com.android.dx.rop.code.PlainCstInsn) SourcePosition(com.android.dx.rop.code.SourcePosition) BasicBlock(com.android.dx.rop.code.BasicBlock) InsnList(com.android.dx.rop.code.InsnList)

Aggregations

InsnList (com.android.dx.rop.code.InsnList)17 BasicBlock (com.android.dx.rop.code.BasicBlock)13 Insn (com.android.dx.rop.code.Insn)13 PlainCstInsn (com.android.dx.rop.code.PlainCstInsn)12 PlainInsn (com.android.dx.rop.code.PlainInsn)12 ThrowingCstInsn (com.android.dx.rop.code.ThrowingCstInsn)12 ThrowingInsn (com.android.dx.rop.code.ThrowingInsn)12 SourcePosition (com.android.dx.rop.code.SourcePosition)10 RegisterSpec (com.android.dx.rop.code.RegisterSpec)6 CstType (com.android.dx.rop.cst.CstType)4 StdTypeList (com.android.dx.rop.type.StdTypeList)4 BasicBlockList (com.android.dx.rop.code.BasicBlockList)3 IntList (com.android.dx.util.IntList)3 RegisterSpecList (com.android.dx.rop.code.RegisterSpecList)2 Rop (com.android.dx.rop.code.Rop)2 Prototype (com.android.dx.rop.type.Prototype)2 Type (com.android.dx.rop.type.Type)2 TypeList (com.android.dx.rop.type.TypeList)2 BytecodeArray (com.android.dx.cf.code.BytecodeArray)1 DexTranslationAdvice (com.android.dx.rop.code.DexTranslationAdvice)1