Search in sources :

Example 6 with RegisterSpec

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

the class DeadCodeRemover method pruneDeadInstructions.

/**
     * Removes all instructions from every unreachable block.
     */
private void pruneDeadInstructions() {
    HashSet<SsaInsn> deletedInsns = new HashSet<SsaInsn>();
    ssaMeth.computeReachability();
    for (SsaBasicBlock block : ssaMeth.getBlocks()) {
        if (block.isReachable())
            continue;
        // Prune instructions from unreachable blocks
        for (int i = 0; i < block.getInsns().size(); i++) {
            SsaInsn insn = block.getInsns().get(i);
            RegisterSpecList sources = insn.getSources();
            int sourcesSize = sources.size();
            // Delete this instruction completely if it has sources
            if (sourcesSize != 0) {
                deletedInsns.add(insn);
            }
            // Delete this instruction from all usage lists.
            for (int j = 0; j < sourcesSize; j++) {
                RegisterSpec source = sources.get(j);
                useList[source.getReg()].remove(insn);
            }
            // Remove this instruction result from the sources of any phis
            RegisterSpec result = insn.getResult();
            if (result == null)
                continue;
            for (SsaInsn use : useList[result.getReg()]) {
                if (use instanceof PhiInsn) {
                    PhiInsn phiUse = (PhiInsn) use;
                    phiUse.removePhiRegister(result);
                }
            }
        }
    }
    ssaMeth.deleteInsns(deletedInsns);
}
Also used : RegisterSpecList(com.taobao.android.dx.rop.code.RegisterSpecList) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec) HashSet(java.util.HashSet)

Example 7 with RegisterSpec

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

the class EscapeAnalysis method processMoveResultPseudoInsn.

/**
     * Determine the origin of a move result pseudo instruction that generates
     * an object. Creates a new EscapeSet for the new object accordingly.
     *
     * @param insn {@code non-null;} move result pseudo instruction to process
     * @return {@code non-null;} an EscapeSet for the object referred to by the
     * move result pseudo instruction
     */
private EscapeSet processMoveResultPseudoInsn(SsaInsn insn) {
    RegisterSpec result = insn.getResult();
    SsaInsn prevSsaInsn = getInsnForMove(insn);
    int prevOpcode = prevSsaInsn.getOpcode().getOpcode();
    EscapeSet escSet;
    RegisterSpec prevSource;
    switch(prevOpcode) {
        // New instance / Constant
        case RegOps.NEW_INSTANCE:
        case RegOps.CONST:
            escSet = new EscapeSet(result.getReg(), regCount, EscapeState.NONE);
            break;
        // New array
        case RegOps.NEW_ARRAY:
        case RegOps.FILLED_NEW_ARRAY:
            prevSource = prevSsaInsn.getSources().get(0);
            if (prevSource.getTypeBearer().isConstant()) {
                // New fixed array
                escSet = new EscapeSet(result.getReg(), regCount, EscapeState.NONE);
                escSet.replaceableArray = true;
            } else {
                // New variable array
                escSet = new EscapeSet(result.getReg(), regCount, EscapeState.GLOBAL);
            }
            break;
        // Loading a static object
        case RegOps.GET_STATIC:
            escSet = new EscapeSet(result.getReg(), regCount, EscapeState.GLOBAL);
            break;
        // Type cast / load an object from a field or array
        case RegOps.CHECK_CAST:
        case RegOps.GET_FIELD:
        case RegOps.AGET:
            prevSource = prevSsaInsn.getSources().get(0);
            int setIndex = findSetIndex(prevSource);
            // Set should already exist, try to find it
            if (setIndex != latticeValues.size()) {
                escSet = latticeValues.get(setIndex);
                escSet.regSet.set(result.getReg());
                return escSet;
            }
            // Set not found, must be either null or unknown
            if (prevSource.getType() == Type.KNOWN_NULL) {
                escSet = new EscapeSet(result.getReg(), regCount, EscapeState.NONE);
            } else {
                escSet = new EscapeSet(result.getReg(), regCount, EscapeState.GLOBAL);
            }
            break;
        default:
            return null;
    }
    // Add the newly created escSet to the lattice and return it
    latticeValues.add(escSet);
    return escSet;
}
Also used : RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Example 8 with RegisterSpec

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

the class EscapeAnalysis method processInsn.

/**
     * Process a single instruction, looking for new objects resulting from
     * move result or move param.
     *
     * @param insn {@code non-null;} instruction to process
     */
private void processInsn(SsaInsn insn) {
    int op = insn.getOpcode().getOpcode();
    RegisterSpec result = insn.getResult();
    EscapeSet escSet;
    // Identify new objects
    if (op == RegOps.MOVE_RESULT_PSEUDO && result.getTypeBearer().getBasicType() == Type.BT_OBJECT) {
        // Handle objects generated through move_result_pseudo
        escSet = processMoveResultPseudoInsn(insn);
        processRegister(result, escSet);
    } else if (op == RegOps.MOVE_PARAM && result.getTypeBearer().getBasicType() == Type.BT_OBJECT) {
        // Track method arguments that are objects
        escSet = new EscapeSet(result.getReg(), regCount, EscapeState.NONE);
        latticeValues.add(escSet);
        processRegister(result, escSet);
    } else if (op == RegOps.MOVE_RESULT && result.getTypeBearer().getBasicType() == Type.BT_OBJECT) {
        // Track method return values that are objects
        escSet = new EscapeSet(result.getReg(), regCount, EscapeState.NONE);
        latticeValues.add(escSet);
        processRegister(result, escSet);
    }
}
Also used : RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Example 9 with RegisterSpec

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

the class EscapeAnalysis method insertExceptionThrow.

/**
     * Replaces instructions that trigger an ArrayIndexOutofBounds exception
     * with an actual throw of the exception.
     *
     * @param insn {@code non-null;} instruction causing the exception
     * @param index {@code non-null;} index value that is out of bounds
     * @param deletedInsns {@code non-null;} set of instructions marked for
     * deletion
     */
private void insertExceptionThrow(SsaInsn insn, RegisterSpec index, HashSet<SsaInsn> deletedInsns) {
    // Create a new ArrayIndexOutOfBoundsException
    CstType exception = new CstType(Exceptions.TYPE_ArrayIndexOutOfBoundsException);
    insertThrowingInsnBefore(insn, RegisterSpecList.EMPTY, null, RegOps.NEW_INSTANCE, exception);
    // Add a successor block with a move result pseudo for the exception
    SsaBasicBlock currBlock = insn.getBlock();
    SsaBasicBlock newBlock = currBlock.insertNewSuccessor(currBlock.getPrimarySuccessor());
    SsaInsn newInsn = newBlock.getInsns().get(0);
    RegisterSpec newReg = RegisterSpec.make(ssaMeth.makeNewSsaReg(), exception);
    insertPlainInsnBefore(newInsn, RegisterSpecList.EMPTY, newReg, RegOps.MOVE_RESULT_PSEUDO, null);
    // Add another successor block to initialize the exception
    SsaBasicBlock newBlock2 = newBlock.insertNewSuccessor(newBlock.getPrimarySuccessor());
    SsaInsn newInsn2 = newBlock2.getInsns().get(0);
    CstNat newNat = new CstNat(new CstString("<init>"), new CstString("(I)V"));
    CstMethodRef newRef = new CstMethodRef(exception, newNat);
    insertThrowingInsnBefore(newInsn2, RegisterSpecList.make(newReg, index), null, RegOps.INVOKE_DIRECT, newRef);
    deletedInsns.add(newInsn2);
    // Add another successor block to throw the new exception
    SsaBasicBlock newBlock3 = newBlock2.insertNewSuccessor(newBlock2.getPrimarySuccessor());
    SsaInsn newInsn3 = newBlock3.getInsns().get(0);
    insertThrowingInsnBefore(newInsn3, RegisterSpecList.make(newReg), null, RegOps.THROW, null);
    newBlock3.replaceSuccessor(newBlock3.getPrimarySuccessorIndex(), ssaMeth.getExitBlock().getIndex());
    deletedInsns.add(newInsn3);
}
Also used : CstNat(com.taobao.android.dx.rop.cst.CstNat) CstType(com.taobao.android.dx.rop.cst.CstType) CstString(com.taobao.android.dx.rop.cst.CstString) CstMethodRef(com.taobao.android.dx.rop.cst.CstMethodRef) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Example 10 with RegisterSpec

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

the class ConstCollector method updateConstUses.

/**
     * Updates all uses of various consts to use the values in the newly
     * assigned registers.
     *
     * @param newRegs {@code non-null;} mapping between constant and new reg
     * @param origRegCount {@code >=0;} original SSA reg count, not including
     * newly added constant regs
     */
private void updateConstUses(HashMap<TypedConstant, RegisterSpec> newRegs, int origRegCount) {
    /*
         * set of constants associated with a local variable; used
         * only if COLLECT_ONE_LOCAL is true.
         */
    final HashSet<TypedConstant> usedByLocal = new HashSet<TypedConstant>();
    final ArrayList<SsaInsn>[] useList = ssaMeth.getUseListCopy();
    for (int i = 0; i < origRegCount; i++) {
        SsaInsn insn = ssaMeth.getDefinitionForRegister(i);
        if (insn == null) {
            continue;
        }
        final RegisterSpec origReg = insn.getResult();
        TypeBearer typeBearer = insn.getResult().getTypeBearer();
        if (!typeBearer.isConstant())
            continue;
        TypedConstant cst = (TypedConstant) typeBearer;
        final RegisterSpec newReg = newRegs.get(cst);
        if (newReg == null) {
            continue;
        }
        if (ssaMeth.isRegALocal(origReg)) {
            if (!COLLECT_ONE_LOCAL) {
                continue;
            } else {
                /*
                     * TODO: If the same local gets the same cst
                     * multiple times, it would be nice to reuse the
                     * register.
                     */
                if (usedByLocal.contains(cst)) {
                    continue;
                } else {
                    usedByLocal.add(cst);
                    fixLocalAssignment(origReg, newRegs.get(cst));
                }
            }
        }
        // maps an original const register to the new collected register
        RegisterMapper mapper = new RegisterMapper() {

            @Override
            public int getNewRegisterCount() {
                return ssaMeth.getRegCount();
            }

            @Override
            public RegisterSpec map(RegisterSpec registerSpec) {
                if (registerSpec.getReg() == origReg.getReg()) {
                    return newReg.withLocalItem(registerSpec.getLocalItem());
                }
                return registerSpec;
            }
        };
        for (SsaInsn use : useList[origReg.getReg()]) {
            if (use.canThrow() && use.getBlock().getSuccessors().cardinality() > 1) {
                continue;
            }
            use.mapSourceRegisters(mapper);
        }
    }
}
Also used : TypedConstant(com.taobao.android.dx.rop.cst.TypedConstant) ArrayList(java.util.ArrayList) TypeBearer(com.taobao.android.dx.rop.type.TypeBearer) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec) HashSet(java.util.HashSet)

Aggregations

RegisterSpec (com.taobao.android.dx.rop.code.RegisterSpec)66 RegisterSpecList (com.taobao.android.dx.rop.code.RegisterSpecList)24 PlainInsn (com.taobao.android.dx.rop.code.PlainInsn)12 Constant (com.taobao.android.dx.rop.cst.Constant)10 TypedConstant (com.taobao.android.dx.rop.cst.TypedConstant)8 ArrayList (java.util.ArrayList)8 Insn (com.taobao.android.dx.rop.code.Insn)7 PlainCstInsn (com.taobao.android.dx.rop.code.PlainCstInsn)7 Rop (com.taobao.android.dx.rop.code.Rop)7 ThrowingCstInsn (com.taobao.android.dx.rop.code.ThrowingCstInsn)7 CstType (com.taobao.android.dx.rop.cst.CstType)7 TypeBearer (com.taobao.android.dx.rop.type.TypeBearer)7 LocalItem (com.taobao.android.dx.rop.code.LocalItem)5 RegisterSpecSet (com.taobao.android.dx.rop.code.RegisterSpecSet)5 ThrowingInsn (com.taobao.android.dx.rop.code.ThrowingInsn)5 CstString (com.taobao.android.dx.rop.cst.CstString)5 BitSet (java.util.BitSet)5 HashSet (java.util.HashSet)5 SourcePosition (com.taobao.android.dx.rop.code.SourcePosition)4 CstFieldRef (com.taobao.android.dx.rop.cst.CstFieldRef)4