Search in sources :

Example 11 with PlainInsn

use of com.taobao.android.dx.rop.code.PlainInsn in project atlas by alibaba.

the class SCCP method replaceBranches.

/**
     * Replaces branches that have constant conditions with gotos
     */
private void replaceBranches() {
    for (SsaInsn insn : branchWorklist) {
        // Find if a successor block is never executed
        int oldSuccessor = -1;
        SsaBasicBlock block = insn.getBlock();
        int successorSize = block.getSuccessorList().size();
        for (int i = 0; i < successorSize; i++) {
            int successorBlock = block.getSuccessorList().get(i);
            if (!executableBlocks.get(successorBlock)) {
                oldSuccessor = successorBlock;
            }
        }
        /*
             * Prune branches that have already been handled and ones that no
             * longer have constant conditions (no nonexecutable successors)
             */
        if (successorSize != 2 || oldSuccessor == -1)
            continue;
        // Replace branch with goto
        Insn originalRopInsn = insn.getOriginalRopInsn();
        block.replaceLastInsn(new PlainInsn(Rops.GOTO, originalRopInsn.getPosition(), null, RegisterSpecList.EMPTY));
        block.removeSuccessor(oldSuccessor);
    }
}
Also used : PlainInsn(com.taobao.android.dx.rop.code.PlainInsn) Insn(com.taobao.android.dx.rop.code.Insn) CstInsn(com.taobao.android.dx.rop.code.CstInsn) PlainInsn(com.taobao.android.dx.rop.code.PlainInsn)

Example 12 with PlainInsn

use of com.taobao.android.dx.rop.code.PlainInsn in project atlas by alibaba.

the class SsaBasicBlock method scheduleMovesFromPhis.

/**
     * Sorts move instructions added via {@code addMoveToEnd} during
     * phi removal so that results don't overwrite sources that are used.
     * For use after all phis have been removed and all calls to
     * addMoveToEnd() have been made.<p>
     *
     * This is necessary because copy-propogation may have left us in a state
     * where the same basic block has the same register as a phi operand
     * and a result. In this case, the register in the phi operand always
     * refers value before any other phis have executed.
     */
public void scheduleMovesFromPhis() {
    if (movesFromPhisAtBeginning > 1) {
        List<SsaInsn> toSchedule;
        toSchedule = insns.subList(0, movesFromPhisAtBeginning);
        scheduleUseBeforeAssigned(toSchedule);
        SsaInsn firstNonPhiMoveInsn = insns.get(movesFromPhisAtBeginning);
        /*
             * TODO: It's actually possible that this case never happens,
             * because a move-exception block, having only one predecessor
             * in SSA form, perhaps is never on a dominance frontier.
             */
        if (firstNonPhiMoveInsn.isMoveException()) {
            if (true) {
                /*
                     * We've yet to observe this case, and if it can
                     * occur the code written to handle it probably
                     * does not work.
                     */
                throw new RuntimeException("Unexpected: moves from " + "phis before move-exception");
            } else {
                /*
                     * A move-exception insn must be placed first in this block
                     * We need to move it there, and deal with possible
                     * interference.
                     */
                boolean moveExceptionInterferes = false;
                int moveExceptionResult = firstNonPhiMoveInsn.getResult().getReg();
                /*
                     * Does the move-exception result reg interfere with the
                     * phi moves?
                     */
                for (SsaInsn insn : toSchedule) {
                    if (insn.isResultReg(moveExceptionResult) || insn.isRegASource(moveExceptionResult)) {
                        moveExceptionInterferes = true;
                        break;
                    }
                }
                if (!moveExceptionInterferes) {
                    // This is the easy case.
                    insns.remove(movesFromPhisAtBeginning);
                    insns.add(0, firstNonPhiMoveInsn);
                } else {
                    /*
                         * We need to move the result to a spare reg
                         * and move it back.
                         */
                    RegisterSpec originalResultSpec = firstNonPhiMoveInsn.getResult();
                    int spareRegister = parent.borrowSpareRegister(originalResultSpec.getCategory());
                    // We now move it to a spare register.
                    firstNonPhiMoveInsn.changeResultReg(spareRegister);
                    RegisterSpec tempSpec = firstNonPhiMoveInsn.getResult();
                    insns.add(0, firstNonPhiMoveInsn);
                    // And here we move it back.
                    NormalSsaInsn toAdd = new NormalSsaInsn(new PlainInsn(Rops.opMove(tempSpec.getType()), SourcePosition.NO_INFO, originalResultSpec, RegisterSpecList.make(tempSpec)), this);
                    /*
                         * Place it immediately after the phi-moves,
                         * overwriting the move-exception that was there.
                         */
                    insns.set(movesFromPhisAtBeginning + 1, toAdd);
                }
            }
        }
    }
    if (movesFromPhisAtEnd > 1) {
        scheduleUseBeforeAssigned(insns.subList(insns.size() - movesFromPhisAtEnd - 1, insns.size() - 1));
    }
    // Return registers borrowed here and in scheduleUseBeforeAssigned().
    parent.returnSpareRegisters();
}
Also used : PlainInsn(com.taobao.android.dx.rop.code.PlainInsn) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Example 13 with PlainInsn

use of com.taobao.android.dx.rop.code.PlainInsn in project atlas by alibaba.

the class SsaBasicBlock method addMoveToBeginning.

/**
     * Adds a move instruction after the phi insn block.
     *
     * @param result move destination
     * @param source move source
     */
public void addMoveToBeginning(RegisterSpec result, RegisterSpec source) {
    if (result.getReg() == source.getReg()) {
        // Sometimes we end up with no-op moves. Ignore them here.
        return;
    }
    RegisterSpecList sources = RegisterSpecList.make(source);
    NormalSsaInsn toAdd = new NormalSsaInsn(new PlainInsn(Rops.opMove(result.getType()), SourcePosition.NO_INFO, result, sources), this);
    insns.add(getCountPhiInsns(), toAdd);
    movesFromPhisAtBeginning++;
}
Also used : PlainInsn(com.taobao.android.dx.rop.code.PlainInsn) RegisterSpecList(com.taobao.android.dx.rop.code.RegisterSpecList)

Example 14 with PlainInsn

use of com.taobao.android.dx.rop.code.PlainInsn in project atlas by alibaba.

the class RegisterAllocator method insertMoveBefore.

/**
     * Inserts a move instruction for a specified SSA register before a
     * specified instruction, creating a new SSA register and adjusting the
     * interference graph in the process. The insn currently must be the
     * last insn in a block.
     *
     * @param insn {@code non-null;} insn to insert move before, must
     * be last insn in block
     * @param reg {@code non-null;} SSA register to duplicate
     * @return {@code non-null;} spec of new SSA register created by move
     */
protected final RegisterSpec insertMoveBefore(SsaInsn insn, RegisterSpec reg) {
    SsaBasicBlock block = insn.getBlock();
    ArrayList<SsaInsn> insns = block.getInsns();
    int insnIndex = insns.indexOf(insn);
    if (insnIndex < 0) {
        throw new IllegalArgumentException("specified insn is not in this block");
    }
    if (insnIndex != insns.size() - 1) {
        /*
             * Presently, the interference updater only works when
             * adding before the last insn, and the last insn must have no
             * result
             */
        throw new IllegalArgumentException("Adding move here not supported:" + insn.toHuman());
    }
    /*
         * Get new register and make new move instruction.
         */
    // The new result must not have an associated local variable.
    RegisterSpec newRegSpec = RegisterSpec.make(ssaMeth.makeNewSsaReg(), reg.getTypeBearer());
    SsaInsn toAdd = SsaInsn.makeFromRop(new PlainInsn(Rops.opMove(newRegSpec.getType()), SourcePosition.NO_INFO, newRegSpec, RegisterSpecList.make(reg)), block);
    insns.add(insnIndex, toAdd);
    int newReg = newRegSpec.getReg();
    /*
         * Adjust interference graph based on what's live out of the current
         * block and what's used by the final instruction.
         */
    IntSet liveOut = block.getLiveOutRegs();
    IntIterator liveOutIter = liveOut.iterator();
    while (liveOutIter.hasNext()) {
        interference.add(newReg, liveOutIter.next());
    }
    // Everything that's a source in the last insn interferes.
    RegisterSpecList sources = insn.getSources();
    int szSources = sources.size();
    for (int i = 0; i < szSources; i++) {
        interference.add(newReg, sources.get(i).getReg());
    }
    ssaMeth.onInsnsChanged();
    return newRegSpec;
}
Also used : PlainInsn(com.taobao.android.dx.rop.code.PlainInsn) IntIterator(com.taobao.android.dx.util.IntIterator) IntSet(com.taobao.android.dx.util.IntSet) SsaBasicBlock(com.taobao.android.dx.ssa.SsaBasicBlock) SsaInsn(com.taobao.android.dx.ssa.SsaInsn) NormalSsaInsn(com.taobao.android.dx.ssa.NormalSsaInsn) RegisterSpecList(com.taobao.android.dx.rop.code.RegisterSpecList) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Example 15 with PlainInsn

use of com.taobao.android.dx.rop.code.PlainInsn in project atlas by alibaba.

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 : Insn(com.taobao.android.dx.rop.code.Insn) PlainCstInsn(com.taobao.android.dx.rop.code.PlainCstInsn) PlainInsn(com.taobao.android.dx.rop.code.PlainInsn) ThrowingInsn(com.taobao.android.dx.rop.code.ThrowingInsn) ThrowingCstInsn(com.taobao.android.dx.rop.code.ThrowingCstInsn) Prototype(com.taobao.android.dx.rop.type.Prototype) ThrowingCstInsn(com.taobao.android.dx.rop.code.ThrowingCstInsn) BasicBlock(com.taobao.android.dx.rop.code.BasicBlock) InsnList(com.taobao.android.dx.rop.code.InsnList) ThrowingInsn(com.taobao.android.dx.rop.code.ThrowingInsn) PlainCstInsn(com.taobao.android.dx.rop.code.PlainCstInsn) PlainInsn(com.taobao.android.dx.rop.code.PlainInsn) CstType(com.taobao.android.dx.rop.cst.CstType) Type(com.taobao.android.dx.rop.type.Type) StdTypeList(com.taobao.android.dx.rop.type.StdTypeList) SourcePosition(com.taobao.android.dx.rop.code.SourcePosition) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Aggregations

PlainInsn (com.taobao.android.dx.rop.code.PlainInsn)17 Insn (com.taobao.android.dx.rop.code.Insn)10 PlainCstInsn (com.taobao.android.dx.rop.code.PlainCstInsn)9 RegisterSpec (com.taobao.android.dx.rop.code.RegisterSpec)9 ThrowingCstInsn (com.taobao.android.dx.rop.code.ThrowingCstInsn)8 ThrowingInsn (com.taobao.android.dx.rop.code.ThrowingInsn)7 RegisterSpecList (com.taobao.android.dx.rop.code.RegisterSpecList)6 SourcePosition (com.taobao.android.dx.rop.code.SourcePosition)6 BasicBlock (com.taobao.android.dx.rop.code.BasicBlock)5 InsnList (com.taobao.android.dx.rop.code.InsnList)5 Rop (com.taobao.android.dx.rop.code.Rop)5 CstType (com.taobao.android.dx.rop.cst.CstType)3 FillArrayDataInsn (com.taobao.android.dx.rop.code.FillArrayDataInsn)2 StdTypeList (com.taobao.android.dx.rop.type.StdTypeList)2 Type (com.taobao.android.dx.rop.type.Type)2 IntList (com.taobao.android.dx.util.IntList)2 BitSet (java.util.BitSet)2 CstInsn (com.taobao.android.dx.rop.code.CstInsn)1 LocalItem (com.taobao.android.dx.rop.code.LocalItem)1 SwitchInsn (com.taobao.android.dx.rop.code.SwitchInsn)1