FileDocCategorySizeDatePackage
LocalVariableInfo.javaAPI DocAndroid 1.5 API8440Wed May 06 22:41:02 BST 2009com.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
>= 0; the register count for the method
private final com.android.dx.rop.code.RegisterSpecSet
emptySet
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
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
non-null; map from instructions to the variable each assigns
Constructors Summary
public LocalVariableInfo(SsaMethod method)
Constructs an instance.

param
method 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 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 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 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 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 >= 0; the block index
return
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 getStarts(block.getLabel()).

param
block non-null; the block in question
return
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 >= 0; the block index
return
null-ok; associated register set or 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 >= 0; the block index
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(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 >= 0; the block index
return
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 >= 0; the block index
param
specs 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");
        }