FileDocCategorySizeDatePackage
LocalVariableInfo.javaAPI DocAndroid 5.1 API8426Thu Mar 12 22:18:30 GMT 2015com.android.dexgen.rop.code

LocalVariableInfo

public final class LocalVariableInfo extends com.android.dexgen.util.MutabilityControl
Container for local variable information for a particular {@link RopMethod}.

Fields Summary
private final int
regCount
{@code >= 0;} the register count for the method
private final RegisterSpecSet
emptySet
{@code non-null;} {@link RegisterSpecSet} to use when indicating a block that has no locals; it is empty and immutable but has an appropriate max size for the method
private final RegisterSpecSet[]
blockStarts
{@code non-null;} array consisting of register sets representing the sets of variables already assigned upon entry to each block, where array indices correspond to block labels
private final HashMap
insnAssignments
{@code non-null;} map from instructions to the variable each assigns
Constructors Summary
public LocalVariableInfo(RopMethod method)
Constructs an instance.

param
method {@code non-null;} the method being represented by this instance

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

        BasicBlockList blocks = method.getBlocks();
        int maxLabel = blocks.getMaxLabel();

        this.regCount = blocks.getRegCount();
        this.emptySet = new RegisterSpecSet(regCount);
        this.blockStarts = new RegisterSpecSet[maxLabel];
        this.insnAssignments =
            new HashMap<Insn, RegisterSpec>(blocks.getInstructionCount());

        emptySet.setImmutable();
    
Methods Summary
public voidaddAssignment(Insn insn, RegisterSpec spec)
Adds an assignment association for the given instruction and register spec. This throws an exception if the instruction doesn't actually perform a named variable assignment. Note: Although the instruction contains its own spec for the result, it still needs to be passed in explicitly to this method, since the spec that is stored here should always have a simple type and the one in the instruction can be an arbitrary {@link TypeBearer} (such as a constant value).

param
insn {@code non-null;} the instruction in question
param
spec {@code non-null;} the associated register spec

        throwIfImmutable();

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

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

        insnAssignments.put(insn, spec);
    
public voiddebugDump()

        for (int label = 0 ; label < blockStarts.length; label++) {
            if (blockStarts[label] == null) {
                continue;
            }

            if (blockStarts[label] == emptySet) {
                System.out.printf("%04x: empty set\n", label);
            } else {
                System.out.printf("%04x: %s\n", label, blockStarts[label]);
            }
        }
    
public RegisterSpecgetAssignment(Insn insn)
Gets the named register being assigned by the given instruction, if previously stored in this instance.

param
insn {@code non-null;} instruction in question
return
{@code null-ok;} the named register being assigned, if any

        return insnAssignments.get(insn);
    
public intgetAssignmentCount()
Gets the number of assignments recorded by this instance.

return
{@code >= 0;} the number of assignments

        return insnAssignments.size();
    
public RegisterSpecSetgetStarts(int label)
Gets the register set associated with the start of the block with the given label. This returns an empty set with the appropriate max size if no set was associated with the block in question.

param
label {@code >= 0;} the block label
return
{@code non-null;} the associated register set

        RegisterSpecSet result = getStarts0(label);

        return (result != null) ? result : emptySet;
    
public RegisterSpecSetgetStarts(BasicBlock block)
Gets the register set associated with the start of the given block. This is just convenient shorthand for {@code getStarts(block.getLabel())}.

param
block {@code non-null;} the block in question
return
{@code non-null;} the associated register set

        return getStarts(block.getLabel());
    
private RegisterSpecSetgetStarts0(int label)
Helper method, to get the starts for a label, throwing the right exception for range problems.

param
label {@code >= 0;} the block label
return
{@code null-ok;} associated register set or {@code null} if there is none

        try {
            return blockStarts[label];
        } catch (ArrayIndexOutOfBoundsException ex) {
            // Translate the exception.
            throw new IllegalArgumentException("bogus label");
        }
    
public booleanmergeStarts(int label, RegisterSpecSet specs)
Merges the given register set into the set for the block with the given label. If there was not already an associated set, then this is the same as calling {@link #setStarts}. Otherwise, this will merge the two sets and call {@link #setStarts} on the result of the merge.

param
label {@code >= 0;} the block label
param
specs {@code non-null;} the register set to merge into the start set for the block
return
{@code true} if the merge resulted in an actual change to the associated set (including storing one for the first time) or {@code false} if there was no change

        RegisterSpecSet start = getStarts0(label);
        boolean changed = false;

        if (start == null) {
            setStarts(label, specs);
            return true;
        }

        RegisterSpecSet newStart = start.mutableCopy();
        newStart.intersect(specs, true);

        if (start.equals(newStart)) {
            return false;
        }

        newStart.setImmutable();
        setStarts(label, newStart);

        return true;
    
public RegisterSpecSetmutableCopyOfStarts(int label)
Gets a mutable copy of the register set associated with the start of the block with the given label. This returns a newly-allocated empty {@link RegisterSpecSet} of appropriate max size if there is not yet any set associated with the block.

param
label {@code >= 0;} the block label
return
{@code non-null;} the associated register set

        RegisterSpecSet result = getStarts0(label);

        return (result != null) ?
            result.mutableCopy() : new RegisterSpecSet(regCount);
    
public voidsetStarts(int label, RegisterSpecSet specs)
Sets the register set associated with the start of the block with the given label.

param
label {@code >= 0;} the block label
param
specs {@code non-null;} the register set to associate with the block

        throwIfImmutable();

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

        try {
            blockStarts[label] = specs;
        } catch (ArrayIndexOutOfBoundsException ex) {
            // Translate the exception.
            throw new IllegalArgumentException("bogus label");
        }