Search in sources :

Example 21 with Constant

use of com.taobao.android.dx.rop.cst.Constant in project atlas by alibaba.

the class EscapeAnalysis method replaceDef.

/**
     * Replaces the instructions that define an array with equivalent registers.
     * For each entry in the array, a register is created, initialized to zero.
     * A mapping between this register and the corresponding array index is
     * added.
     *
     * @param def {@code non-null;} move result instruction for array
     * @param prev {@code non-null;} instruction for instantiating new array
     * @param length size of the new array
     * @param newRegs {@code non-null;} mapping of array indices to new
     * registers to be populated
     */
private void replaceDef(SsaInsn def, SsaInsn prev, int length, ArrayList<RegisterSpec> newRegs) {
    Type resultType = def.getResult().getType();
    // Create new zeroed out registers for each element in the array
    for (int i = 0; i < length; i++) {
        Constant newZero = Zeroes.zeroFor(resultType.getComponentType());
        TypedConstant typedZero = (TypedConstant) newZero;
        RegisterSpec newReg = RegisterSpec.make(ssaMeth.makeNewSsaReg(), typedZero);
        newRegs.add(newReg);
        insertPlainInsnBefore(def, RegisterSpecList.EMPTY, newReg, RegOps.CONST, newZero);
    }
}
Also used : CstType(com.taobao.android.dx.rop.cst.CstType) Type(com.taobao.android.dx.rop.type.Type) TypedConstant(com.taobao.android.dx.rop.cst.TypedConstant) Constant(com.taobao.android.dx.rop.cst.Constant) TypedConstant(com.taobao.android.dx.rop.cst.TypedConstant) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Example 22 with Constant

use of com.taobao.android.dx.rop.cst.Constant 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 23 with Constant

use of com.taobao.android.dx.rop.cst.Constant in project atlas by alibaba.

the class SCCP method simulateStmt.

/**
     * Simulates a statement and set the result lattice value.
     * @param insn instruction to simulate
     */
private void simulateStmt(SsaInsn insn) {
    Insn ropInsn = insn.getOriginalRopInsn();
    if (ropInsn.getOpcode().getBranchingness() != Rop.BRANCH_NONE || ropInsn.getOpcode().isCallLike()) {
        simulateBranch(insn);
    }
    int opcode = insn.getOpcode().getOpcode();
    RegisterSpec result = insn.getResult();
    if (result == null) {
        // Find move-result-pseudo result for int div and int rem
        if (opcode == RegOps.DIV || opcode == RegOps.REM) {
            SsaBasicBlock succ = insn.getBlock().getPrimarySuccessor();
            result = succ.getInsns().get(0).getResult();
        } else {
            return;
        }
    }
    int resultReg = result.getReg();
    int resultValue = VARYING;
    Constant resultConstant = null;
    switch(opcode) {
        case RegOps.CONST:
            {
                CstInsn cstInsn = (CstInsn) ropInsn;
                resultValue = CONSTANT;
                resultConstant = cstInsn.getConstant();
                break;
            }
        case RegOps.MOVE:
            {
                if (insn.getSources().size() == 1) {
                    int sourceReg = insn.getSources().get(0).getReg();
                    resultValue = latticeValues[sourceReg];
                    resultConstant = latticeConstants[sourceReg];
                }
                break;
            }
        case RegOps.ADD:
        case RegOps.SUB:
        case RegOps.MUL:
        case RegOps.DIV:
        case RegOps.AND:
        case RegOps.OR:
        case RegOps.XOR:
        case RegOps.SHL:
        case RegOps.SHR:
        case RegOps.USHR:
        case RegOps.REM:
            {
                resultConstant = simulateMath(insn, result.getBasicType());
                if (resultConstant != null) {
                    resultValue = CONSTANT;
                }
                break;
            }
        case RegOps.MOVE_RESULT_PSEUDO:
            {
                if (latticeValues[resultReg] == CONSTANT) {
                    resultValue = latticeValues[resultReg];
                    resultConstant = latticeConstants[resultReg];
                }
                break;
            }
        // TODO: Eliminate check casts that we can prove the type of.
        default:
            {
            }
    }
    if (setLatticeValueTo(resultReg, resultValue, resultConstant)) {
        addUsersToWorklist(resultReg, resultValue);
    }
}
Also used : CstInsn(com.taobao.android.dx.rop.code.CstInsn) Insn(com.taobao.android.dx.rop.code.Insn) CstInsn(com.taobao.android.dx.rop.code.CstInsn) PlainInsn(com.taobao.android.dx.rop.code.PlainInsn) Constant(com.taobao.android.dx.rop.cst.Constant) TypedConstant(com.taobao.android.dx.rop.cst.TypedConstant) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Example 24 with Constant

use of com.taobao.android.dx.rop.cst.Constant in project atlas by alibaba.

the class SCCP method simulateMath.

/**
     * Simulates math insns, if possible.
     *
     * @param insn non-null insn to simulate
     * @param resultType basic type of the result
     * @return constant result or null if not simulatable.
     */
private Constant simulateMath(SsaInsn insn, int resultType) {
    Insn ropInsn = insn.getOriginalRopInsn();
    int opcode = insn.getOpcode().getOpcode();
    RegisterSpecList sources = insn.getSources();
    int regA = sources.get(0).getReg();
    Constant cA;
    Constant cB;
    if (latticeValues[regA] != CONSTANT) {
        cA = null;
    } else {
        cA = latticeConstants[regA];
    }
    if (sources.size() == 1) {
        CstInsn cstInsn = (CstInsn) ropInsn;
        cB = cstInsn.getConstant();
    } else {
        /* sources.size() == 2 */
        int regB = sources.get(1).getReg();
        if (latticeValues[regB] != CONSTANT) {
            cB = null;
        } else {
            cB = latticeConstants[regB];
        }
    }
    if (cA == null || cB == null) {
        //TODO handle a constant of 0 with MUL or AND
        return null;
    }
    switch(resultType) {
        case Type.BT_INT:
            int vR;
            boolean skip = false;
            int vA = ((CstInteger) cA).getValue();
            int vB = ((CstInteger) cB).getValue();
            switch(opcode) {
                case RegOps.ADD:
                    vR = vA + vB;
                    break;
                case RegOps.SUB:
                    // 1 source for reverse sub, 2 sources for regular sub
                    if (sources.size() == 1) {
                        vR = vB - vA;
                    } else {
                        vR = vA - vB;
                    }
                    break;
                case RegOps.MUL:
                    vR = vA * vB;
                    break;
                case RegOps.DIV:
                    if (vB == 0) {
                        skip = true;
                        // just to hide a warning
                        vR = 0;
                    } else {
                        vR = vA / vB;
                    }
                    break;
                case RegOps.AND:
                    vR = vA & vB;
                    break;
                case RegOps.OR:
                    vR = vA | vB;
                    break;
                case RegOps.XOR:
                    vR = vA ^ vB;
                    break;
                case RegOps.SHL:
                    vR = vA << vB;
                    break;
                case RegOps.SHR:
                    vR = vA >> vB;
                    break;
                case RegOps.USHR:
                    vR = vA >>> vB;
                    break;
                case RegOps.REM:
                    if (vB == 0) {
                        skip = true;
                        // just to hide a warning
                        vR = 0;
                    } else {
                        vR = vA % vB;
                    }
                    break;
                default:
                    throw new RuntimeException("Unexpected op");
            }
            return skip ? null : CstInteger.make(vR);
        default:
            // not yet supported
            return null;
    }
}
Also used : CstInsn(com.taobao.android.dx.rop.code.CstInsn) Insn(com.taobao.android.dx.rop.code.Insn) CstInsn(com.taobao.android.dx.rop.code.CstInsn) PlainInsn(com.taobao.android.dx.rop.code.PlainInsn) Constant(com.taobao.android.dx.rop.cst.Constant) TypedConstant(com.taobao.android.dx.rop.cst.TypedConstant) CstInteger(com.taobao.android.dx.rop.cst.CstInteger) RegisterSpecList(com.taobao.android.dx.rop.code.RegisterSpecList)

Example 25 with Constant

use of com.taobao.android.dx.rop.cst.Constant in project atlas by alibaba.

the class SCCP method simulateBranch.

/**
     * Simulates branch insns, if possible. Adds reachable successor blocks
     * to the CFG worklists.
     * @param insn branch to simulate
     */
private void simulateBranch(SsaInsn insn) {
    Rop opcode = insn.getOpcode();
    RegisterSpecList sources = insn.getSources();
    boolean constantBranch = false;
    boolean constantSuccessor = false;
    // Check if the insn is a branch with a constant condition
    if (opcode.getBranchingness() == Rop.BRANCH_IF) {
        Constant cA = null;
        Constant cB = null;
        RegisterSpec specA = sources.get(0);
        int regA = specA.getReg();
        if (!ssaMeth.isRegALocal(specA) && latticeValues[regA] == CONSTANT) {
            cA = latticeConstants[regA];
        }
        if (sources.size() == 2) {
            RegisterSpec specB = sources.get(1);
            int regB = specB.getReg();
            if (!ssaMeth.isRegALocal(specB) && latticeValues[regB] == CONSTANT) {
                cB = latticeConstants[regB];
            }
        }
        // Calculate the result of the condition
        if (cA != null && sources.size() == 1) {
            switch(((TypedConstant) cA).getBasicType()) {
                case Type.BT_INT:
                    constantBranch = true;
                    int vA = ((CstInteger) cA).getValue();
                    switch(opcode.getOpcode()) {
                        case RegOps.IF_EQ:
                            constantSuccessor = (vA == 0);
                            break;
                        case RegOps.IF_NE:
                            constantSuccessor = (vA != 0);
                            break;
                        case RegOps.IF_LT:
                            constantSuccessor = (vA < 0);
                            break;
                        case RegOps.IF_GE:
                            constantSuccessor = (vA >= 0);
                            break;
                        case RegOps.IF_LE:
                            constantSuccessor = (vA <= 0);
                            break;
                        case RegOps.IF_GT:
                            constantSuccessor = (vA > 0);
                            break;
                        default:
                            throw new RuntimeException("Unexpected op");
                    }
                    break;
                default:
            }
        } else if (cA != null && cB != null) {
            switch(((TypedConstant) cA).getBasicType()) {
                case Type.BT_INT:
                    constantBranch = true;
                    int vA = ((CstInteger) cA).getValue();
                    int vB = ((CstInteger) cB).getValue();
                    switch(opcode.getOpcode()) {
                        case RegOps.IF_EQ:
                            constantSuccessor = (vA == vB);
                            break;
                        case RegOps.IF_NE:
                            constantSuccessor = (vA != vB);
                            break;
                        case RegOps.IF_LT:
                            constantSuccessor = (vA < vB);
                            break;
                        case RegOps.IF_GE:
                            constantSuccessor = (vA >= vB);
                            break;
                        case RegOps.IF_LE:
                            constantSuccessor = (vA <= vB);
                            break;
                        case RegOps.IF_GT:
                            constantSuccessor = (vA > vB);
                            break;
                        default:
                            throw new RuntimeException("Unexpected op");
                    }
                    break;
                default:
            }
        }
    }
    /*
         * If condition is constant, add only the target block to the
         * worklist. Otherwise, add all successors to the worklist.
         */
    SsaBasicBlock block = insn.getBlock();
    if (constantBranch) {
        int successorBlock;
        if (constantSuccessor) {
            successorBlock = block.getSuccessorList().get(1);
        } else {
            successorBlock = block.getSuccessorList().get(0);
        }
        addBlockToWorklist(ssaMeth.getBlocks().get(successorBlock));
        branchWorklist.add(insn);
    } else {
        for (int i = 0; i < block.getSuccessorList().size(); i++) {
            int successorBlock = block.getSuccessorList().get(i);
            addBlockToWorklist(ssaMeth.getBlocks().get(successorBlock));
        }
    }
}
Also used : Rop(com.taobao.android.dx.rop.code.Rop) TypedConstant(com.taobao.android.dx.rop.cst.TypedConstant) Constant(com.taobao.android.dx.rop.cst.Constant) TypedConstant(com.taobao.android.dx.rop.cst.TypedConstant) CstInteger(com.taobao.android.dx.rop.cst.CstInteger) RegisterSpecList(com.taobao.android.dx.rop.code.RegisterSpecList) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Aggregations

Constant (com.taobao.android.dx.rop.cst.Constant)42 RegisterSpecList (com.taobao.android.dx.rop.code.RegisterSpecList)17 CstType (com.taobao.android.dx.rop.cst.CstType)13 CstInsn (com.taobao.android.dx.dex.code.CstInsn)12 CstString (com.taobao.android.dx.rop.cst.CstString)12 RegisterSpec (com.taobao.android.dx.rop.code.RegisterSpec)10 TypedConstant (com.taobao.android.dx.rop.cst.TypedConstant)10 CstLiteralBits (com.taobao.android.dx.rop.cst.CstLiteralBits)9 CstFieldRef (com.taobao.android.dx.rop.cst.CstFieldRef)6 CstInteger (com.taobao.android.dx.rop.cst.CstInteger)6 Type (com.taobao.android.dx.rop.type.Type)5 NameValuePair (com.taobao.android.dx.rop.annotation.NameValuePair)4 Insn (com.taobao.android.dx.rop.code.Insn)4 PlainInsn (com.taobao.android.dx.rop.code.PlainInsn)4 CstMethodRef (com.taobao.android.dx.rop.cst.CstMethodRef)4 TypeBearer (com.taobao.android.dx.rop.type.TypeBearer)4 Rop (com.taobao.android.dx.rop.code.Rop)3 ThrowingCstInsn (com.taobao.android.dx.rop.code.ThrowingCstInsn)3 ArrayList (java.util.ArrayList)3 CstInsn (com.taobao.android.dx.rop.code.CstInsn)2