Search in sources :

Example 81 with RegisterSpec

use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.

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 : Type(com.android.dx.rop.type.Type) CstType(com.android.dx.rop.cst.CstType) TypedConstant(com.android.dx.rop.cst.TypedConstant) Constant(com.android.dx.rop.cst.Constant) TypedConstant(com.android.dx.rop.cst.TypedConstant) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 82 with RegisterSpec

use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.

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 : ThrowingCstInsn(com.android.dx.rop.code.ThrowingCstInsn) ThrowingInsn(com.android.dx.rop.code.ThrowingInsn) PlainInsn(com.android.dx.rop.code.PlainInsn) FillArrayDataInsn(com.android.dx.rop.code.FillArrayDataInsn) Insn(com.android.dx.rop.code.Insn) PlainCstInsn(com.android.dx.rop.code.PlainCstInsn) CstLiteralBits(com.android.dx.rop.cst.CstLiteralBits) FillArrayDataInsn(com.android.dx.rop.code.FillArrayDataInsn) Constant(com.android.dx.rop.cst.Constant) TypedConstant(com.android.dx.rop.cst.TypedConstant) TypeBearer(com.android.dx.rop.type.TypeBearer) RegisterSpecList(com.android.dx.rop.code.RegisterSpecList) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 83 with RegisterSpec

use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.

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.android.dx.rop.code.Rop) ArrayList(java.util.ArrayList) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 84 with RegisterSpec

use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.

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.android.dx.rop.code.RegisterSpec)

Example 85 with RegisterSpec

use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.

the class InterferenceRegisterMapper method areAnyPinned.

/**
     * Checks to see if any of a set of old-namespace registers are
     * pinned to the specified new-namespace reg + category. Takes into
     * account the category of the old-namespace registers.
     *
     * @param oldSpecs {@code non-null;} set of old-namespace regs
     * @param newReg {@code >= 0;} new-namespace register
     * @param targetCategory {@code 1..2;} the number of adjacent new-namespace
     * registers (starting at ropReg) to consider
     * @return true if any of the old-namespace register have been mapped
     * to the new-namespace register + category
     */
public boolean areAnyPinned(RegisterSpecList oldSpecs, int newReg, int targetCategory) {
    int sz = oldSpecs.size();
    for (int i = 0; i < sz; i++) {
        RegisterSpec oldSpec = oldSpecs.get(i);
        int r = oldToNew(oldSpec.getReg());
        /*
             * If oldSpec is a category-2 register, then check both newReg
             * and newReg - 1.
             */
        if (r == newReg || (oldSpec.getCategory() == 2 && (r + 1) == newReg) || (targetCategory == 2 && (r == newReg + 1))) {
            return true;
        }
    }
    return false;
}
Also used : RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Aggregations

RegisterSpec (com.android.dx.rop.code.RegisterSpec)135 RegisterSpecList (com.android.dx.rop.code.RegisterSpecList)50 PlainInsn (com.android.dx.rop.code.PlainInsn)24 Constant (com.android.dx.rop.cst.Constant)20 TypedConstant (com.android.dx.rop.cst.TypedConstant)16 TypeBearer (com.android.dx.rop.type.TypeBearer)16 ArrayList (java.util.ArrayList)16 Insn (com.android.dx.rop.code.Insn)14 PlainCstInsn (com.android.dx.rop.code.PlainCstInsn)14 Rop (com.android.dx.rop.code.Rop)14 ThrowingCstInsn (com.android.dx.rop.code.ThrowingCstInsn)14 CstType (com.android.dx.rop.cst.CstType)14 BitSet (java.util.BitSet)11 LocalItem (com.android.dx.rop.code.LocalItem)10 RegisterSpecSet (com.android.dx.rop.code.RegisterSpecSet)10 ThrowingInsn (com.android.dx.rop.code.ThrowingInsn)10 CstString (com.android.dx.rop.cst.CstString)10 HashSet (java.util.HashSet)10 SourcePosition (com.android.dx.rop.code.SourcePosition)8 CstFieldRef (com.android.dx.rop.cst.CstFieldRef)8