FileDocCategorySizeDatePackage
BasicBlockList.javaAPI DocAndroid 5.1 API11490Thu Mar 12 22:18:30 GMT 2015com.android.dx.rop.code

BasicBlockList

public final class BasicBlockList extends com.android.dx.util.LabeledList
List of {@link BasicBlock} instances.

Fields Summary
private int
regCount
{@code >= -1;} the count of registers required by this method or {@code -1} if not yet calculated
Constructors Summary
public BasicBlockList(int size)
Constructs an instance. All indices initially contain {@code null}, and the first-block label is initially {@code -1}.

param
size the size of the list

        super(size);

        regCount = -1;
    
private BasicBlockList(BasicBlockList old)
Constructs a mutable copy for {@code getMutableCopy()}.

param
old block to copy

        super(old);
        regCount = old.regCount;
    
Methods Summary
public booleancatchesEqual(BasicBlock block1, BasicBlock block2)
Compares the catches of two blocks for equality. This includes both the catch types and target labels.

param
block1 {@code non-null;} one block to compare
param
block2 {@code non-null;} the other block to compare
return
{@code true} if the two blocks' non-primary successors are identical

        TypeList catches1 = block1.getExceptionHandlerTypes();
        TypeList catches2 = block2.getExceptionHandlerTypes();

        if (!StdTypeList.equalContents(catches1, catches2)) {
            return false;
        }

        IntList succ1 = block1.getSuccessors();
        IntList succ2 = block2.getSuccessors();
        int size = succ1.size(); // Both are guaranteed to be the same size.

        int primary1 = block1.getPrimarySuccessor();
        int primary2 = block2.getPrimarySuccessor();

        if (((primary1 == -1) || (primary2 == -1))
                && (primary1 != primary2)) {
            /*
             * For the current purpose, both blocks in question must
             * either both have a primary or both not have a primary to
             * be considered equal, and it turns out here that that's not
             * the case.
             */
            return false;
        }

        for (int i = 0; i < size; i++) {
            int label1 = succ1.get(i);
            int label2 = succ2.get(i);

            if (label1 == primary1) {
                /*
                 * It should be the case that block2's primary is at the
                 * same index. If not, we consider the blocks unequal for
                 * the current purpose.
                 */
                if (label2 != primary2) {
                    return false;
                }
                continue;
            }

            if (label1 != label2) {
                return false;
            }
        }

        return true;
    
public voidforEachInsn(Insn.Visitor visitor)
Visits each instruction of each block in the list, in order.

param
visitor {@code non-null;} visitor to use

        int sz = size();

        for (int i = 0; i < sz; i++) {
            BasicBlock one = get(i);
            InsnList insns = one.getInsns();
            insns.forEach(visitor);
        }
    
public BasicBlockget(int n)
Gets the element at the given index. It is an error to call this with the index for an element which was never set; if you do that, this will throw {@code NullPointerException}.

param
n {@code >= 0, < size();} which index
return
{@code non-null;} element at that index

        return (BasicBlock) get0(n);
    
public intgetEffectiveInstructionCount()
Gets the total instruction count for this instance, ignoring mark-local instructions which are not actually emitted.

return
{@code >= 0;} the total instruction count

        int sz = size();
        int result = 0;

        for (int i = 0; i < sz; i++) {
            BasicBlock one = (BasicBlock) getOrNull0(i);
            if (one != null) {
                InsnList insns = one.getInsns();
                int insnsSz = insns.size();

                for (int j = 0; j < insnsSz; j++) {
                    Insn insn = insns.get(j);

                    if (insn.getOpcode().getOpcode() != RegOps.MARK_LOCAL) {
                        result++;
                    }
                }
            }
        }

        return result;
    
public intgetInstructionCount()
Gets the total instruction count for this instance. This is the sum of the instruction counts of each block.

return
{@code >= 0;} the total instruction count

        int sz = size();
        int result = 0;

        for (int i = 0; i < sz; i++) {
            BasicBlock one = (BasicBlock) getOrNull0(i);
            if (one != null) {
                result += one.getInsns().size();
            }
        }

        return result;
    
public com.android.dx.rop.code.BasicBlockListgetMutableCopy()
Returns a mutable copy of this list.

return
{@code non-null;} an appropriately-constructed instance

        return new BasicBlockList(this);
    
public intgetRegCount()
Returns how many registers this method requires. This is simply the maximum of register-number-plus-category referred to by this instance's instructions (indirectly through {@link BasicBlock} instances).

return
{@code >= 0;} the register count

        if (regCount == -1) {
            RegCountVisitor visitor = new RegCountVisitor();
            forEachInsn(visitor);
            regCount = visitor.getRegCount();
        }

        return regCount;
    
public BasicBlocklabelToBlock(int label)
Gets the first block in the list with the given label, if any.

param
label {@code >= 0;} the label to look for
return
{@code non-null;} the so-labelled block
throws
IllegalArgumentException thrown if the label isn't found

        int idx = indexOfLabel(label);

        if (idx < 0) {
            throw new IllegalArgumentException("no such label: "
                    + Hex.u2(label));
        }

        return get(idx);
    
public BasicBlockpreferredSuccessorOf(BasicBlock block)
Gets the preferred successor for the given block. If the block only has one successor, then that is the preferred successor. Otherwise, if the block has a primay successor, then that is the preferred successor. If the block has no successors, then this returns {@code null}.

param
block {@code non-null;} the block in question
return
{@code null-ok;} the preferred successor, if any

        int primarySuccessor = block.getPrimarySuccessor();
        IntList successors = block.getSuccessors();
        int succSize = successors.size();

        switch (succSize) {
            case 0: {
                return null;
            }
            case 1: {
                return labelToBlock(successors.get(0));
            }
        }

        if (primarySuccessor != -1) {
            return labelToBlock(primarySuccessor);
        } else {
            return labelToBlock(successors.get(0));
        }
    
public voidset(int n, BasicBlock bb)
Sets the basic block at the given index.

param
n {@code >= 0, < size();} which index
param
bb {@code null-ok;} the element to set at {@code n}

        super.set(n, bb);

        // Reset regCount, since it will need to be recalculated.
        regCount = -1;
    
public com.android.dx.rop.code.BasicBlockListwithRegisterOffset(int delta)
Returns an instance that is identical to this one, except that the registers in each instruction are offset by the given amount. Mutability of the result is inherited from the original.

param
delta the amount to offset register numbers by
return
{@code non-null;} an appropriately-constructed instance

        int sz = size();
        BasicBlockList result = new BasicBlockList(sz);

        for (int i = 0; i < sz; i++) {
            BasicBlock one = (BasicBlock) get0(i);
            if (one != null) {
                result.set(i, one.withRegisterOffset(delta));
            }
        }

        if (isImmutable()) {
            result.setImmutable();
        }

        return result;