Search in sources :

Example 31 with RegisterSpec

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

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

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

the class EscapeAnalysis method movePropagate.

/**
     * Identifies extra moves added by scalar replacement and propagates the
     * source of the move to any users of the result.
     */
private void movePropagate() {
    for (int i = 0; i < ssaMeth.getRegCount(); i++) {
        SsaInsn insn = ssaMeth.getDefinitionForRegister(i);
        // Look for move instructions only
        if (insn == null || insn.getOpcode() == null || insn.getOpcode().getOpcode() != RegOps.MOVE) {
            continue;
        }
        final ArrayList<SsaInsn>[] useList = ssaMeth.getUseListCopy();
        final RegisterSpec source = insn.getSources().get(0);
        final RegisterSpec result = insn.getResult();
        // Ignore moves that weren't added due to scalar replacement
        if (source.getReg() < regCount && result.getReg() < regCount) {
            continue;
        }
        // Create a mapping from source to result
        RegisterMapper mapper = new RegisterMapper() {

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

            @Override
            public RegisterSpec map(RegisterSpec registerSpec) {
                if (registerSpec.getReg() == result.getReg()) {
                    return source;
                }
                return registerSpec;
            }
        };
        // Modify all uses of the move to use the source of the move instead
        for (SsaInsn use : useList[result.getReg()]) {
            use.mapSourceRegisters(mapper);
        }
    }
}
Also used : ArrayList(java.util.ArrayList) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Example 34 with RegisterSpec

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

the class EscapeAnalysis method processRegister.

/**
     * Iterate through all the uses of a new object.
     *
     * @param result {@code non-null;} register where new object is stored
     * @param escSet {@code non-null;} EscapeSet for the new object
     */
private void processRegister(RegisterSpec result, EscapeSet escSet) {
    ArrayList<RegisterSpec> regWorklist = new ArrayList<RegisterSpec>();
    regWorklist.add(result);
    // Go through the worklist
    while (!regWorklist.isEmpty()) {
        int listSize = regWorklist.size() - 1;
        RegisterSpec def = regWorklist.remove(listSize);
        List<SsaInsn> useList = ssaMeth.getUseListForRegister(def.getReg());
        // Handle all the uses of this register
        for (SsaInsn use : useList) {
            Rop useOpcode = use.getOpcode();
            if (useOpcode == null) {
                // Handle phis
                processPhiUse(use, escSet, regWorklist);
            } else {
                // Handle other opcodes
                processUse(def, use, escSet, regWorklist);
            }
        }
    }
}
Also used : Rop(com.taobao.android.dx.rop.code.Rop) ArrayList(java.util.ArrayList) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Example 35 with RegisterSpec

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

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