Search in sources :

Example 26 with RegisterSpec

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

the class EscapeAnalysis method scalarReplacement.

/**
     * Performs scalar replacement on all eligible arrays.
     */
private void scalarReplacement() {
    // Iterate through lattice, looking for non-escaping replaceable arrays
    for (EscapeSet escSet : latticeValues) {
        if (!escSet.replaceableArray || escSet.escape != EscapeState.NONE) {
            continue;
        }
        // Get the instructions for the definition and move of the array
        int e = escSet.regSet.nextSetBit(0);
        SsaInsn def = ssaMeth.getDefinitionForRegister(e);
        SsaInsn prev = getInsnForMove(def);
        // Create a map for the new registers that will be created
        TypeBearer lengthReg = prev.getSources().get(0).getTypeBearer();
        int length = ((CstLiteralBits) lengthReg).getIntBits();
        ArrayList<RegisterSpec> newRegs = new ArrayList<RegisterSpec>(length);
        HashSet<SsaInsn> deletedInsns = new HashSet<SsaInsn>();
        // Replace the definition of the array with registers
        replaceDef(def, prev, length, newRegs);
        // Mark definition instructions for deletion
        deletedInsns.add(prev);
        deletedInsns.add(def);
        // Go through all uses of the array
        List<SsaInsn> useList = ssaMeth.getUseListForRegister(e);
        for (SsaInsn use : useList) {
            // Replace the use with scalars and then mark it for deletion
            replaceUse(use, prev, newRegs, deletedInsns);
            deletedInsns.add(use);
        }
        // Delete all marked instructions
        ssaMeth.deleteInsns(deletedInsns);
        ssaMeth.onInsnsChanged();
        // Convert the method back to SSA form
        SsaConverter.updateSsaMethod(ssaMeth, regCount);
        // Propagate and remove extra moves added by scalar replacement
        movePropagate();
    }
}
Also used : CstLiteralBits(com.android.dx.rop.cst.CstLiteralBits) ArrayList(java.util.ArrayList) TypeBearer(com.android.dx.rop.type.TypeBearer) RegisterSpec(com.android.dx.rop.code.RegisterSpec) HashSet(java.util.HashSet)

Example 27 with RegisterSpec

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

the class EscapeAnalysis method insertExceptionThrow.

/**
     * Replaces instructions that trigger an ArrayIndexOutofBounds exception
     * with an actual throw of the exception.
     *
     * @param insn {@code non-null;} instruction causing the exception
     * @param index {@code non-null;} index value that is out of bounds
     * @param deletedInsns {@code non-null;} set of instructions marked for
     * deletion
     */
private void insertExceptionThrow(SsaInsn insn, RegisterSpec index, HashSet<SsaInsn> deletedInsns) {
    // Create a new ArrayIndexOutOfBoundsException
    CstType exception = new CstType(Exceptions.TYPE_ArrayIndexOutOfBoundsException);
    insertThrowingInsnBefore(insn, RegisterSpecList.EMPTY, null, RegOps.NEW_INSTANCE, exception);
    // Add a successor block with a move result pseudo for the exception
    SsaBasicBlock currBlock = insn.getBlock();
    SsaBasicBlock newBlock = currBlock.insertNewSuccessor(currBlock.getPrimarySuccessor());
    SsaInsn newInsn = newBlock.getInsns().get(0);
    RegisterSpec newReg = RegisterSpec.make(ssaMeth.makeNewSsaReg(), exception);
    insertPlainInsnBefore(newInsn, RegisterSpecList.EMPTY, newReg, RegOps.MOVE_RESULT_PSEUDO, null);
    // Add another successor block to initialize the exception
    SsaBasicBlock newBlock2 = newBlock.insertNewSuccessor(newBlock.getPrimarySuccessor());
    SsaInsn newInsn2 = newBlock2.getInsns().get(0);
    CstNat newNat = new CstNat(new CstString("<init>"), new CstString("(I)V"));
    CstMethodRef newRef = new CstMethodRef(exception, newNat);
    insertThrowingInsnBefore(newInsn2, RegisterSpecList.make(newReg, index), null, RegOps.INVOKE_DIRECT, newRef);
    deletedInsns.add(newInsn2);
    // Add another successor block to throw the new exception
    SsaBasicBlock newBlock3 = newBlock2.insertNewSuccessor(newBlock2.getPrimarySuccessor());
    SsaInsn newInsn3 = newBlock3.getInsns().get(0);
    insertThrowingInsnBefore(newInsn3, RegisterSpecList.make(newReg), null, RegOps.THROW, null);
    newBlock3.replaceSuccessor(newBlock3.getPrimarySuccessorIndex(), ssaMeth.getExitBlock().getIndex());
    deletedInsns.add(newInsn3);
}
Also used : CstNat(com.android.dx.rop.cst.CstNat) CstType(com.android.dx.rop.cst.CstType) CstString(com.android.dx.rop.cst.CstString) CstMethodRef(com.android.dx.rop.cst.CstMethodRef) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 28 with RegisterSpec

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

the class LocalVariableExtractor method processBlock.

/**
     * Processes a single block.
     *
     * @param blockIndex {@code >= 0;} block index of the block to process
     */
private void processBlock(int blockIndex) {
    RegisterSpecSet primaryState = resultInfo.mutableCopyOfStarts(blockIndex);
    SsaBasicBlock block = blocks.get(blockIndex);
    List<SsaInsn> insns = block.getInsns();
    int insnSz = insns.size();
    // The exit block has no insns and no successors
    if (blockIndex == method.getExitBlockIndex()) {
        return;
    }
    /*
         * We may have to treat the last instruction specially: If it
         * can (but doesn't always) throw, and the exception can be
         * caught within the same method, then we need to use the
         * state *before* executing it to be what is merged into
         * exception targets.
         */
    SsaInsn lastInsn = insns.get(insnSz - 1);
    boolean hasExceptionHandlers = lastInsn.getOriginalRopInsn().getCatches().size() != 0;
    boolean canThrowDuringLastInsn = hasExceptionHandlers && (lastInsn.getResult() != null);
    int freezeSecondaryStateAt = insnSz - 1;
    RegisterSpecSet secondaryState = primaryState;
    for (int i = 0; i < insnSz; i++) {
        if (canThrowDuringLastInsn && (i == freezeSecondaryStateAt)) {
            // Until this point, primaryState == secondaryState.
            primaryState.setImmutable();
            primaryState = primaryState.mutableCopy();
        }
        SsaInsn insn = insns.get(i);
        RegisterSpec result;
        result = insn.getLocalAssignment();
        if (result == null) {
            // We may be nuking an existing local
            result = insn.getResult();
            if (result != null && primaryState.get(result.getReg()) != null) {
                primaryState.remove(primaryState.get(result.getReg()));
            }
            continue;
        }
        result = result.withSimpleType();
        RegisterSpec already = primaryState.get(result);
        /*
             * The equals() check ensures we only add new info if
             * the instruction causes a change to the set of
             * active variables.
             */
        if (!result.equals(already)) {
            /*
                 * If this insn represents a local moving from one register
                 * to another, remove the association between the old register
                 * and the local.
                 */
            RegisterSpec previous = primaryState.localItemToSpec(result.getLocalItem());
            if (previous != null && (previous.getReg() != result.getReg())) {
                primaryState.remove(previous);
            }
            resultInfo.addAssignment(insn, result);
            primaryState.put(result);
        }
    }
    primaryState.setImmutable();
    /*
         * Merge this state into the start state for each successor,
         * and update the work set where required (that is, in cases
         * where the start state for a block changes).
         */
    IntList successors = block.getSuccessorList();
    int succSz = successors.size();
    int primarySuccessor = block.getPrimarySuccessorIndex();
    for (int i = 0; i < succSz; i++) {
        int succ = successors.get(i);
        RegisterSpecSet state = (succ == primarySuccessor) ? primaryState : secondaryState;
        if (resultInfo.mergeStarts(succ, state)) {
            workSet.set(succ);
        }
    }
}
Also used : RegisterSpecSet(com.android.dx.rop.code.RegisterSpecSet) RegisterSpec(com.android.dx.rop.code.RegisterSpec) IntList(com.android.dx.util.IntList)

Example 29 with RegisterSpec

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

the class RegisterMapper method map.

/**
     *
     * @param sources old register set
     * @return new mapped register set, or old if nothing has changed.
     */
public final RegisterSpecSet map(RegisterSpecSet sources) {
    int sz = sources.getMaxSize();
    RegisterSpecSet newSources = new RegisterSpecSet(getNewRegisterCount());
    for (int i = 0; i < sz; i++) {
        RegisterSpec registerSpec = sources.get(i);
        if (registerSpec != null) {
            newSources.put(map(registerSpec));
        }
    }
    newSources.setImmutable();
    // Return the old sources if nothing has changed.
    return newSources.equals(sources) ? sources : newSources;
}
Also used : RegisterSpecSet(com.android.dx.rop.code.RegisterSpecSet) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 30 with RegisterSpec

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

the class SCCP method replaceConstants.

/**
     * Replaces TypeBearers in source register specs with constant type
     * bearers if possible. These are then referenced in later optimization
     * steps.
     */
private void replaceConstants() {
    for (int reg = 0; reg < regCount; reg++) {
        if (latticeValues[reg] != CONSTANT) {
            continue;
        }
        if (!(latticeConstants[reg] instanceof TypedConstant)) {
            // We can't do much with these
            continue;
        }
        SsaInsn defn = ssaMeth.getDefinitionForRegister(reg);
        TypeBearer typeBearer = defn.getResult().getTypeBearer();
        if (typeBearer.isConstant()) {
            /*
                 * The definition was a constant already.
                 * The uses should be as well.
                 */
            continue;
        }
        // Update the destination RegisterSpec with the constant value
        RegisterSpec dest = defn.getResult();
        RegisterSpec newDest = dest.withType((TypedConstant) latticeConstants[reg]);
        defn.setResult(newDest);
        /*
             * Update the sources RegisterSpec's of all non-move uses.
             * These will be used in later steps.
             */
        for (SsaInsn insn : ssaMeth.getUseListForRegister(reg)) {
            if (insn.isPhiOrMove()) {
                continue;
            }
            NormalSsaInsn nInsn = (NormalSsaInsn) insn;
            RegisterSpecList sources = insn.getSources();
            int index = sources.indexOfRegister(reg);
            RegisterSpec spec = sources.get(index);
            RegisterSpec newSpec = spec.withType((TypedConstant) latticeConstants[reg]);
            nInsn.changeOneSource(index, newSpec);
        }
    }
}
Also used : 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)

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