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

RopMethod

public final class RopMethod extends Object
All of the parts that make up a method at the rop layer.

Fields Summary
private final BasicBlockList
blocks
{@code non-null;} basic block list of the method
private final int
firstLabel
{@code >= 0;} label for the block which starts the method
private com.android.dx.util.IntList[]
predecessors
{@code null-ok;} array of predecessors for each block, indexed by block label
private com.android.dx.util.IntList
exitPredecessors
{@code null-ok;} the predecessors for the implicit "exit" block, that is the labels for the blocks that return, if calculated
Constructors Summary
public RopMethod(BasicBlockList blocks, int firstLabel)
Constructs an instance.

param
blocks {@code non-null;} basic block list of the method
param
firstLabel {@code >= 0;} the label of the first block to execute

        if (blocks == null) {
            throw new NullPointerException("blocks == null");
        }

        if (firstLabel < 0) {
            throw new IllegalArgumentException("firstLabel < 0");
        }

        this.blocks = blocks;
        this.firstLabel = firstLabel;

        this.predecessors = null;
        this.exitPredecessors = null;
    
Methods Summary
private voidcalcPredecessors()
Calculates the predecessor sets for each block as well as for the exit.

        int maxLabel = blocks.getMaxLabel();
        IntList[] predecessors = new IntList[maxLabel];
        IntList exitPredecessors = new IntList(10);
        int sz = blocks.size();

        /*
         * For each block, find its successors, and add the block's label to
         * the successor's predecessors.
         */
        for (int i = 0; i < sz; i++) {
            BasicBlock one = blocks.get(i);
            int label = one.getLabel();
            IntList successors = one.getSuccessors();
            int ssz = successors.size();
            if (ssz == 0) {
                // This block exits.
                exitPredecessors.add(label);
            } else {
                for (int j = 0; j < ssz; j++) {
                    int succLabel = successors.get(j);
                    IntList succPreds = predecessors[succLabel];
                    if (succPreds == null) {
                        succPreds = new IntList(10);
                        predecessors[succLabel] = succPreds;
                    }
                    succPreds.add(label);
                }
            }
        }

        // Sort and immutablize all the predecessor lists.
        for (int i = 0; i < maxLabel; i++) {
            IntList preds = predecessors[i];
            if (preds != null) {
                preds.sort();
                preds.setImmutable();
            }
        }

        exitPredecessors.sort();
        exitPredecessors.setImmutable();

        /*
         * The start label might not ever have had any predecessors
         * added to it (probably doesn't, because of how Java gets
         * translated into rop form). So, check for this and rectify
         * the situation if required.
         */
        if (predecessors[firstLabel] == null) {
            predecessors[firstLabel] = IntList.EMPTY;
        }

        this.predecessors = predecessors;
        this.exitPredecessors = exitPredecessors;
    
public BasicBlockListgetBlocks()
Gets the basic block list for this method.

return
{@code non-null;} the list

        return blocks;
    
public com.android.dx.util.IntListgetExitPredecessors()
Gets the exit predecessors for this instance.

return
{@code non-null;} the exit predecessors

        if (exitPredecessors == null) {
            calcPredecessors();
        }

        return exitPredecessors;
    
public intgetFirstLabel()
Gets the label for the first block in the method that this list represents.

return
{@code >= 0;} the first-block label

        return firstLabel;
    
public com.android.dx.util.IntListlabelToPredecessors(int label)
Gets the predecessors associated with the given block. This throws an exception if there is no block with the given label.

param
label {@code >= 0;} the label of the block in question
return
{@code non-null;} the predecessors of that block

        if (exitPredecessors == null) {
            calcPredecessors();
        }

        IntList result = predecessors[label];

        if (result == null) {
            throw new RuntimeException("no such block: " + Hex.u2(label));
        }

        return result;
    
public com.android.dx.rop.code.RopMethodwithRegisterOffset(int delta)
Returns an instance that is identical to this one, except that the registers in each instruction are offset by the given amount.

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

        RopMethod result = new RopMethod(blocks.withRegisterOffset(delta),
                                         firstLabel);

        if (exitPredecessors != null) {
            /*
             * The predecessors have been calculated. It's safe to
             * inject these into the new instance, since the
             * transformation being applied doesn't affect the
             * predecessors.
             */
            result.exitPredecessors = exitPredecessors;
            result.predecessors = predecessors;
        }

        return result;