FileDocCategorySizeDatePackage
LocalVariableInfo.javaAPI DocAndroid 5.1 API8574Thu Mar 12 22:18:30 GMT 2015com.android.dx.ssa

LocalVariableInfo

public class LocalVariableInfo extends com.android.dx.util.MutabilityControl
Container for local variable information for a particular {@link com.android.dx.ssa.SsaMethod}. Stolen from {@link com.android.dx.rop.code.LocalVariableInfo}.

Fields Summary
private final int
regCount
{@code >= 0;} the register count for the method
private final com.android.dx.rop.code.RegisterSpecSet
emptySet
{@code non-null;} {@link com.android.dx.rop.code.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 com.android.dx.rop.code.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 indices
private final HashMap
insnAssignments
{@code non-null;} map from instructions to the variable each assigns
Constructors Summary
public LocalVariableInfo(SsaMethod method)
Constructs an instance.

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

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

        List<SsaBasicBlock> blocks = method.getBlocks();

        this.regCount = method.getRegCount();
        this.emptySet = new RegisterSpecSet(regCount);
        this.blockStarts = new RegisterSpecSet[blocks.size()];
        this.insnAssignments =
            new HashMap<SsaInsn, RegisterSpec>(/*hint here*/);

        emptySet.setImmutable();
    
Methods Summary
public voidaddAssignment(SsaInsn insn, com.android.dx.rop.code.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 com.android.dx.rop.type.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 index = 0 ; index < blockStarts.length; index++) {
            if (blockStarts[index] == null) {
                continue;
            }

            if (blockStarts[index] == emptySet) {
                System.out.printf("%04x: empty set\n", index);
            } else {
                System.out.printf("%04x: %s\n", index, blockStarts[index]);
            }
        }
    
public com.android.dx.rop.code.RegisterSpecgetAssignment(SsaInsn 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 com.android.dx.rop.code.RegisterSpecSetgetStarts(int index)
Gets the register set associated with the start of the block with the given index. This returns an empty set with the appropriate max size if no set was associated with the block in question.

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

        RegisterSpecSet result = getStarts0(index);

        return (result != null) ? result : emptySet;
    
public com.android.dx.rop.code.RegisterSpecSetgetStarts(SsaBasicBlock 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.getIndex());
    
private com.android.dx.rop.code.RegisterSpecSetgetStarts0(int index)
Helper method, to get the starts for a index, throwing the right exception for range problems.

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

        try {
            return blockStarts[index];
        } catch (ArrayIndexOutOfBoundsException ex) {
            // Translate the exception.
            throw new IllegalArgumentException("bogus index");
        }
    
public booleanmergeStarts(int index, com.android.dx.rop.code.RegisterSpecSet specs)
Merges the given register set into the set for the block with the given index. 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
index {@code >= 0;} the block index
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(index);
        boolean changed = false;

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

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

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

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

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

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

        RegisterSpecSet result = getStarts0(index);

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

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

        throwIfImmutable();

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

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