FileDocCategorySizeDatePackage
LocalVariableInfo.javaAPI DocAndroid 1.5 API8292Wed May 06 22:41:02 BST 2009com.android.dx.rop.code

LocalVariableInfo

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

Fields Summary
private final int
regCount
>= 0; the register count for the method
private final RegisterSpecSet
emptySet
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
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
non-null; map from instructions to the variable each assigns
Constructors Summary
public LocalVariableInfo(RopMethod method)
Constructs an instance.

param
method 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 non-null; the instruction in question
param
spec 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 non-null; instruction in question
return
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
>= 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 >= 0; the block label
return
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 getStarts(block.getLabel()).

param
block non-null; the block in question
return
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 >= 0; the block label
return
null-ok; associated register set or 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 >= 0; the block label
param
specs non-null; the register set to merge into the start set for the block
return
true if the merge resulted in an actual change to the associated set (including storing one for the first time) or 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 >= 0; the block label
return
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 >= 0; the block label
param
specs 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");
        }