Search in sources :

Example 36 with RegisterSpec

use of com.taobao.android.dx.rop.code.RegisterSpec 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 37 with RegisterSpec

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

the class PhiTypeResolver method resolveResultType.

/**
     * Resolves the result of a phi insn based on its operands. The "void"
     * type, which is a nonsensical type for a register, is used for
     * registers defined by as-of-yet-unresolved phi operations.
     *
     * @return true if the result type changed, false if no change
     */
boolean resolveResultType(PhiInsn insn) {
    insn.updateSourcesToDefinitions(ssaMeth);
    RegisterSpecList sources = insn.getSources();
    // Start by finding the first non-void operand
    RegisterSpec first = null;
    int firstIndex = -1;
    int szSources = sources.size();
    for (int i = 0; i < szSources; i++) {
        RegisterSpec rs = sources.get(i);
        if (rs.getBasicType() != Type.BT_VOID) {
            first = rs;
            firstIndex = i;
        }
    }
    if (first == null) {
        // All operands are void -- we're not ready to resolve yet
        return false;
    }
    LocalItem firstLocal = first.getLocalItem();
    Type mergedType = first.getType();
    boolean sameLocals = true;
    for (int i = 0; i < szSources; i++) {
        if (i == firstIndex) {
            continue;
        }
        RegisterSpec rs = sources.get(i);
        // Just skip void (unresolved phi results) for now
        if (rs.getBasicType() == Type.BT_VOID) {
            continue;
        }
        sameLocals = sameLocals && equalsHandlesNulls(firstLocal, rs.getLocalItem());
        mergedType = (Type) Merger.mergeType(mergedType, rs.getType());
    }
    Type newResultType;
    if (mergedType != null) {
        newResultType = mergedType;
    } else {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < szSources; i++) {
            sb.append(sources.get(i).toString());
            sb.append(' ');
        }
        throw new RuntimeException("Couldn't map types in phi insn:" + sb);
    }
    LocalItem newLocal = sameLocals ? firstLocal : null;
    RegisterSpec result = insn.getResult();
    if ((result.getTypeBearer() == newResultType) && equalsHandlesNulls(newLocal, result.getLocalItem())) {
        return false;
    }
    insn.changeResultType(newResultType, newLocal);
    return true;
}
Also used : Type(com.taobao.android.dx.rop.type.Type) LocalItem(com.taobao.android.dx.rop.code.LocalItem) RegisterSpecList(com.taobao.android.dx.rop.code.RegisterSpecList) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Example 38 with RegisterSpec

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

the class PhiTypeResolver method run.

/**
     * Runs the phi-type resolver.
     */
private void run() {
    int regCount = ssaMeth.getRegCount();
    for (int reg = 0; reg < regCount; reg++) {
        SsaInsn definsn = ssaMeth.getDefinitionForRegister(reg);
        if (definsn != null && (definsn.getResult().getBasicType() == Type.BT_VOID)) {
            worklist.set(reg);
        }
    }
    int reg;
    while (0 <= (reg = worklist.nextSetBit(0))) {
        worklist.clear(reg);
        /*
             * definitions on the worklist have a type of BT_VOID, which
             * must have originated from a PhiInsn.
             */
        PhiInsn definsn = (PhiInsn) ssaMeth.getDefinitionForRegister(reg);
        if (resolveResultType(definsn)) {
            /*
                 * If the result type has changed, re-resolve all phis
                 * that use this.
                 */
            List<SsaInsn> useList = ssaMeth.getUseListForRegister(reg);
            int sz = useList.size();
            for (int i = 0; i < sz; i++) {
                SsaInsn useInsn = useList.get(i);
                RegisterSpec resultReg = useInsn.getResult();
                if (resultReg != null && useInsn instanceof PhiInsn) {
                    worklist.set(resultReg.getReg());
                }
            }
        }
    }
}
Also used : RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Example 39 with RegisterSpec

use of com.taobao.android.dx.rop.code.RegisterSpec 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 40 with RegisterSpec

use of com.taobao.android.dx.rop.code.RegisterSpec 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

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