Search in sources :

Example 71 with RegisterSpecList

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

the class Form22b method isCompatible.

/** {@inheritDoc} */
@Override
public boolean isCompatible(DalvInsn insn) {
    RegisterSpecList regs = insn.getRegisters();
    if (!((insn instanceof CstInsn) && (regs.size() == 2) && unsignedFitsInByte(regs.get(0).getReg()) && unsignedFitsInByte(regs.get(1).getReg()))) {
        return false;
    }
    CstInsn ci = (CstInsn) insn;
    Constant cst = ci.getConstant();
    if (!(cst instanceof CstLiteralBits)) {
        return false;
    }
    CstLiteralBits cb = (CstLiteralBits) cst;
    return cb.fitsInInt() && signedFitsInByte(cb.getIntBits());
}
Also used : CstInsn(com.taobao.android.dx.dex.code.CstInsn) CstLiteralBits(com.taobao.android.dx.rop.cst.CstLiteralBits) Constant(com.taobao.android.dx.rop.cst.Constant) RegisterSpecList(com.taobao.android.dx.rop.code.RegisterSpecList)

Example 72 with RegisterSpecList

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

the class DeadCodeRemover method run.

/**
     * Runs the dead code remover.
     */
private void run() {
    pruneDeadInstructions();
    HashSet<SsaInsn> deletedInsns = new HashSet<SsaInsn>();
    ssaMeth.forEachInsn(new NoSideEffectVisitor(worklist));
    int regV;
    while (0 <= (regV = worklist.nextSetBit(0))) {
        worklist.clear(regV);
        if (useList[regV].size() == 0 || isCircularNoSideEffect(regV, null)) {
            SsaInsn insnS = ssaMeth.getDefinitionForRegister(regV);
            // This insn has already been deleted.
            if (deletedInsns.contains(insnS)) {
                continue;
            }
            RegisterSpecList sources = insnS.getSources();
            int sz = sources.size();
            for (int i = 0; i < sz; i++) {
                // Delete this insn from all usage lists.
                RegisterSpec source = sources.get(i);
                useList[source.getReg()].remove(insnS);
                if (!hasSideEffect(ssaMeth.getDefinitionForRegister(source.getReg()))) {
                    /*
                         * Only registers whose definition has no side effect
                         * should be added back to the worklist.
                         */
                    worklist.set(source.getReg());
                }
            }
            // Schedule this insn for later deletion.
            deletedInsns.add(insnS);
        }
    }
    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 73 with RegisterSpecList

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

the class EscapeAnalysis method processUse.

/**
     * Handles non-phi uses of new objects. Checks to see how instruction is
     * used and updates the escape state accordingly.
     *
     * @param def {@code non-null;} register holding definition of new object
     * @param use {@code non-null;} use of object being processed
     * @param escSet {@code non-null;} EscapeSet for the object
     * @param regWorklist {@code non-null;} worklist of instructions left to
     * process for this object
     */
private void processUse(RegisterSpec def, SsaInsn use, EscapeSet escSet, ArrayList<RegisterSpec> regWorklist) {
    int useOpcode = use.getOpcode().getOpcode();
    switch(useOpcode) {
        case RegOps.MOVE:
            // Follow uses of the move by adding it to the worklist
            escSet.regSet.set(use.getResult().getReg());
            regWorklist.add(use.getResult());
            break;
        case RegOps.IF_EQ:
        case RegOps.IF_NE:
        case RegOps.CHECK_CAST:
            // Compared objects can't be replaced, so promote if necessary
            if (escSet.escape.compareTo(EscapeState.METHOD) < 0) {
                escSet.escape = EscapeState.METHOD;
            }
            break;
        case RegOps.APUT:
            // For array puts, check for a constant array index
            RegisterSpec putIndex = use.getSources().get(2);
            if (!putIndex.getTypeBearer().isConstant()) {
                // If not constant, array can't be replaced
                escSet.replaceableArray = false;
            }
        // Intentional fallthrough
        case RegOps.PUT_FIELD:
            // Skip non-object puts
            RegisterSpec putValue = use.getSources().get(0);
            if (putValue.getTypeBearer().getBasicType() != Type.BT_OBJECT) {
                break;
            }
            escSet.replaceableArray = false;
            // Raise 1st object's escape state to 2nd if 2nd is higher
            RegisterSpecList sources = use.getSources();
            if (sources.get(0).getReg() == def.getReg()) {
                int setIndex = findSetIndex(sources.get(1));
                if (setIndex != latticeValues.size()) {
                    EscapeSet parentSet = latticeValues.get(setIndex);
                    addEdge(parentSet, escSet);
                    if (escSet.escape.compareTo(parentSet.escape) < 0) {
                        escSet.escape = parentSet.escape;
                    }
                }
            } else {
                int setIndex = findSetIndex(sources.get(0));
                if (setIndex != latticeValues.size()) {
                    EscapeSet childSet = latticeValues.get(setIndex);
                    addEdge(escSet, childSet);
                    if (childSet.escape.compareTo(escSet.escape) < 0) {
                        childSet.escape = escSet.escape;
                    }
                }
            }
            break;
        case RegOps.AGET:
            // For array gets, check for a constant array index
            RegisterSpec getIndex = use.getSources().get(1);
            if (!getIndex.getTypeBearer().isConstant()) {
                // If not constant, array can't be replaced
                escSet.replaceableArray = false;
            }
            break;
        case RegOps.PUT_STATIC:
            // Static puts cause an object to escape globally
            escSet.escape = EscapeState.GLOBAL;
            break;
        case RegOps.INVOKE_STATIC:
        case RegOps.INVOKE_VIRTUAL:
        case RegOps.INVOKE_SUPER:
        case RegOps.INVOKE_DIRECT:
        case RegOps.INVOKE_INTERFACE:
        case RegOps.RETURN:
        case RegOps.THROW:
            // These operations cause an object to escape interprocedurally
            escSet.escape = EscapeState.INTER;
            break;
        default:
            break;
    }
}
Also used : RegisterSpecList(com.taobao.android.dx.rop.code.RegisterSpecList) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Example 74 with RegisterSpecList

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

the class EscapeAnalysis method replaceUse.

/**
     * Replaces the use for a scalar replaceable array. Gets and puts become
     * move instructions, and array lengths and fills are handled. Can also
     * identify ArrayIndexOutOfBounds exceptions and throw them if detected.
     *
     * @param use {@code non-null;} move result instruction for array
     * @param prev {@code non-null;} instruction for instantiating new array
     * @param newRegs {@code non-null;} mapping of array indices to new
     * registers
     * @param deletedInsns {@code non-null;} set of instructions marked for
     * deletion
     */
private void replaceUse(SsaInsn use, SsaInsn prev, ArrayList<RegisterSpec> newRegs, HashSet<SsaInsn> deletedInsns) {
    int index;
    int length = newRegs.size();
    SsaInsn next;
    RegisterSpecList sources;
    RegisterSpec source, result;
    CstLiteralBits indexReg;
    switch(use.getOpcode().getOpcode()) {
        case RegOps.AGET:
            // Replace array gets with moves
            next = getMoveForInsn(use);
            sources = use.getSources();
            indexReg = ((CstLiteralBits) sources.get(1).getTypeBearer());
            index = indexReg.getIntBits();
            if (index < length) {
                source = newRegs.get(index);
                result = source.withReg(next.getResult().getReg());
                insertPlainInsnBefore(next, RegisterSpecList.make(source), result, RegOps.MOVE, null);
            } else {
                // Throw an exception if the index is out of bounds
                insertExceptionThrow(next, sources.get(1), deletedInsns);
                deletedInsns.add(next.getBlock().getInsns().get(2));
            }
            deletedInsns.add(next);
            break;
        case RegOps.APUT:
            // Replace array puts with moves
            sources = use.getSources();
            indexReg = ((CstLiteralBits) sources.get(2).getTypeBearer());
            index = indexReg.getIntBits();
            if (index < length) {
                source = sources.get(0);
                result = source.withReg(newRegs.get(index).getReg());
                insertPlainInsnBefore(use, RegisterSpecList.make(source), result, RegOps.MOVE, null);
                // Update the newReg entry to mark value as unknown now
                newRegs.set(index, result.withSimpleType());
            } else {
                // Throw an exception if the index is out of bounds
                insertExceptionThrow(use, sources.get(2), deletedInsns);
            }
            break;
        case RegOps.ARRAY_LENGTH:
            // Replace array lengths with const instructions
            TypeBearer lengthReg = prev.getSources().get(0).getTypeBearer();
            //CstInteger lengthReg = CstInteger.make(length);
            next = getMoveForInsn(use);
            insertPlainInsnBefore(next, RegisterSpecList.EMPTY, next.getResult(), RegOps.CONST, (Constant) lengthReg);
            deletedInsns.add(next);
            break;
        case RegOps.MARK_LOCAL:
            // Remove mark local instructions
            break;
        case RegOps.FILL_ARRAY_DATA:
            // Create const instructions for each fill value
            Insn ropUse = use.getOriginalRopInsn();
            FillArrayDataInsn fill = (FillArrayDataInsn) ropUse;
            ArrayList<Constant> constList = fill.getInitValues();
            for (int i = 0; i < length; i++) {
                RegisterSpec newFill = RegisterSpec.make(newRegs.get(i).getReg(), (TypeBearer) constList.get(i));
                insertPlainInsnBefore(use, RegisterSpecList.EMPTY, newFill, RegOps.CONST, constList.get(i));
                // Update the newRegs to hold the new const value
                newRegs.set(i, newFill);
            }
            break;
        default:
    }
}
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) FillArrayDataInsn(com.taobao.android.dx.rop.code.FillArrayDataInsn) CstLiteralBits(com.taobao.android.dx.rop.cst.CstLiteralBits) FillArrayDataInsn(com.taobao.android.dx.rop.code.FillArrayDataInsn) Constant(com.taobao.android.dx.rop.cst.Constant) TypedConstant(com.taobao.android.dx.rop.cst.TypedConstant) TypeBearer(com.taobao.android.dx.rop.type.TypeBearer) RegisterSpecList(com.taobao.android.dx.rop.code.RegisterSpecList) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Example 75 with RegisterSpecList

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

the class PhiInsn method getSources.

/**
     * Gets sources. Constructed lazily from phi operand data structures and
     * then cached.
     *
     * @return {@code non-null;} sources list
     */
@Override
public RegisterSpecList getSources() {
    if (sources != null) {
        return sources;
    }
    if (operands.size() == 0) {
        // How'd this happen? A phi insn with no operand?
        return RegisterSpecList.EMPTY;
    }
    int szSources = operands.size();
    sources = new RegisterSpecList(szSources);
    for (int i = 0; i < szSources; i++) {
        Operand o = operands.get(i);
        sources.set(i, o.regSpec);
    }
    sources.setImmutable();
    return sources;
}
Also used : RegisterSpecList(com.taobao.android.dx.rop.code.RegisterSpecList)

Aggregations

RegisterSpecList (com.taobao.android.dx.rop.code.RegisterSpecList)98 RegisterSpec (com.taobao.android.dx.rop.code.RegisterSpec)24 BitSet (java.util.BitSet)22 CstLiteralBits (com.taobao.android.dx.rop.cst.CstLiteralBits)21 CstInsn (com.taobao.android.dx.dex.code.CstInsn)17 Constant (com.taobao.android.dx.rop.cst.Constant)17 PlainInsn (com.taobao.android.dx.rop.code.PlainInsn)9 CstType (com.taobao.android.dx.rop.cst.CstType)6 TargetInsn (com.taobao.android.dx.dex.code.TargetInsn)5 Insn (com.taobao.android.dx.rop.code.Insn)5 TypedConstant (com.taobao.android.dx.rop.cst.TypedConstant)5 PlainCstInsn (com.taobao.android.dx.rop.code.PlainCstInsn)4 Rop (com.taobao.android.dx.rop.code.Rop)4 CstFieldRef (com.taobao.android.dx.rop.cst.CstFieldRef)4 ThrowingCstInsn (com.taobao.android.dx.rop.code.ThrowingCstInsn)3 ThrowingInsn (com.taobao.android.dx.rop.code.ThrowingInsn)3 CstInteger (com.taobao.android.dx.rop.cst.CstInteger)3 CstMethodRef (com.taobao.android.dx.rop.cst.CstMethodRef)3 TypeBearer (com.taobao.android.dx.rop.type.TypeBearer)3 FillArrayDataInsn (com.taobao.android.dx.rop.code.FillArrayDataInsn)2