Search in sources :

Example 11 with RegisterSpec

use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.

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 12 with RegisterSpec

use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.

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 13 with RegisterSpec

use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.

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.android.dx.rop.code.PlainInsn) IntIterator(com.android.dx.util.IntIterator) IntSet(com.android.dx.util.IntSet) SsaBasicBlock(com.android.dx.ssa.SsaBasicBlock) NormalSsaInsn(com.android.dx.ssa.NormalSsaInsn) SsaInsn(com.android.dx.ssa.SsaInsn) RegisterSpecList(com.android.dx.rop.code.RegisterSpecList) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 14 with RegisterSpec

use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.

the class SsaConverter method placePhiFunctions.

/**
     * See Appel algorithm 19.6:
     *
     * Place Phi functions in appropriate locations.
     *
     * @param ssaMeth {@code non-null;} method to process.
     * Modifications are made in-place.
     * @param localInfo {@code non-null;} local variable info, used
     * when placing phis
     * @param threshold registers below this number are ignored
     */
private static void placePhiFunctions(SsaMethod ssaMeth, LocalVariableInfo localInfo, int threshold) {
    ArrayList<SsaBasicBlock> ssaBlocks;
    int regCount;
    int blockCount;
    ssaBlocks = ssaMeth.getBlocks();
    blockCount = ssaBlocks.size();
    regCount = ssaMeth.getRegCount() - threshold;
    DomFront df = new DomFront(ssaMeth);
    DomFront.DomInfo[] domInfos = df.run();
    // Bit set of registers vs block index "definition sites"
    BitSet[] defsites = new BitSet[regCount];
    // Bit set of registers vs block index "phi placement sites"
    BitSet[] phisites = new BitSet[regCount];
    for (int i = 0; i < regCount; i++) {
        defsites[i] = new BitSet(blockCount);
        phisites[i] = new BitSet(blockCount);
    }
    /*
         * For each register, build a set of all basic blocks where
         * containing an assignment to that register.
         */
    for (int bi = 0, s = ssaBlocks.size(); bi < s; bi++) {
        SsaBasicBlock b = ssaBlocks.get(bi);
        for (SsaInsn insn : b.getInsns()) {
            RegisterSpec rs = insn.getResult();
            if (rs != null && rs.getReg() - threshold >= 0) {
                defsites[rs.getReg() - threshold].set(bi);
            }
        }
    }
    if (DEBUG) {
        System.out.println("defsites");
        for (int i = 0; i < regCount; i++) {
            StringBuilder sb = new StringBuilder();
            sb.append('v').append(i).append(": ");
            sb.append(defsites[i].toString());
            System.out.println(sb);
        }
    }
    BitSet worklist;
    /*
         * For each register, compute all locations for phi placement
         * based on dominance-frontier algorithm.
         */
    for (int reg = 0, s = regCount; reg < s; reg++) {
        int workBlockIndex;
        /* Worklist set starts out with each node where reg is assigned. */
        worklist = (BitSet) (defsites[reg].clone());
        while (0 <= (workBlockIndex = worklist.nextSetBit(0))) {
            worklist.clear(workBlockIndex);
            IntIterator dfIterator = domInfos[workBlockIndex].dominanceFrontiers.iterator();
            while (dfIterator.hasNext()) {
                int dfBlockIndex = dfIterator.next();
                if (!phisites[reg].get(dfBlockIndex)) {
                    phisites[reg].set(dfBlockIndex);
                    int tReg = reg + threshold;
                    RegisterSpec rs = localInfo.getStarts(dfBlockIndex).get(tReg);
                    if (rs == null) {
                        ssaBlocks.get(dfBlockIndex).addPhiInsnForReg(tReg);
                    } else {
                        ssaBlocks.get(dfBlockIndex).addPhiInsnForReg(rs);
                    }
                    if (!defsites[reg].get(dfBlockIndex)) {
                        worklist.set(dfBlockIndex);
                    }
                }
            }
        }
    }
    if (DEBUG) {
        System.out.println("phisites");
        for (int i = 0; i < regCount; i++) {
            StringBuilder sb = new StringBuilder();
            sb.append('v').append(i).append(": ");
            sb.append(phisites[i].toString());
            System.out.println(sb);
        }
    }
}
Also used : IntIterator(com.android.dx.util.IntIterator) BitSet(java.util.BitSet) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 15 with RegisterSpec

use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.

the class SsaMethod method updateOneDefinition.

/**
     * Updates a single definition.
     *
     * @param insn {@code non-null;} insn who's result should be recorded as
     * a definition
     * @param oldResult {@code null-ok;} a previous result that should
     * be no longer considered a definition by this insn
     */
/*package*/
void updateOneDefinition(SsaInsn insn, RegisterSpec oldResult) {
    if (definitionList == null)
        return;
    if (oldResult != null) {
        int reg = oldResult.getReg();
        definitionList[reg] = null;
    }
    RegisterSpec resultReg = insn.getResult();
    if (resultReg != null) {
        int reg = resultReg.getReg();
        if (definitionList[reg] != null) {
            throw new RuntimeException("Duplicate add of insn");
        } else {
            definitionList[resultReg.getReg()] = insn;
        }
    }
}
Also used : RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Aggregations

RegisterSpec (com.android.dx.rop.code.RegisterSpec)135 RegisterSpecList (com.android.dx.rop.code.RegisterSpecList)50 PlainInsn (com.android.dx.rop.code.PlainInsn)24 Constant (com.android.dx.rop.cst.Constant)20 TypedConstant (com.android.dx.rop.cst.TypedConstant)16 TypeBearer (com.android.dx.rop.type.TypeBearer)16 ArrayList (java.util.ArrayList)16 Insn (com.android.dx.rop.code.Insn)14 PlainCstInsn (com.android.dx.rop.code.PlainCstInsn)14 Rop (com.android.dx.rop.code.Rop)14 ThrowingCstInsn (com.android.dx.rop.code.ThrowingCstInsn)14 CstType (com.android.dx.rop.cst.CstType)14 BitSet (java.util.BitSet)11 LocalItem (com.android.dx.rop.code.LocalItem)10 RegisterSpecSet (com.android.dx.rop.code.RegisterSpecSet)10 ThrowingInsn (com.android.dx.rop.code.ThrowingInsn)10 CstString (com.android.dx.rop.cst.CstString)10 HashSet (java.util.HashSet)10 SourcePosition (com.android.dx.rop.code.SourcePosition)8 CstFieldRef (com.android.dx.rop.cst.CstFieldRef)8