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

RegisterSpecSet

public final class RegisterSpecSet extends com.android.dexgen.util.MutabilityControl
Set of {@link RegisterSpec} instances, where a given register number may appear only once in the set.

Fields Summary
public static final RegisterSpecSet
EMPTY
{@code non-null;} no-element instance
private final RegisterSpec[]
specs
{@code non-null;} array of register specs, where each element is {@code null} or is an instance whose {@code reg} matches the array index
private int
size
{@code >= -1;} size of the set or {@code -1} if not yet calculated
Constructors Summary
public RegisterSpecSet(int maxSize)
Constructs an instance. The instance is initially empty.

param
maxSize {@code >= 0;} the maximum register number (exclusive) that may be represented in this instance


                                  
       
        super(maxSize != 0);

        this.specs = new RegisterSpec[maxSize];
        this.size = 0;
    
Methods Summary
public booleanequals(java.lang.Object other)
{@inheritDoc}

        if (!(other instanceof RegisterSpecSet)) {
            return false;
        }

        RegisterSpecSet otherSet = (RegisterSpecSet) other;
        RegisterSpec[] otherSpecs = otherSet.specs;
        int len = specs.length;

        if ((len != otherSpecs.length) || (size() != otherSet.size())) {
            return false;
        }

        for (int i = 0; i < len; i++) {
            RegisterSpec s1 = specs[i];
            RegisterSpec s2 = otherSpecs[i];

            if (s1 == s2) {
                continue;
            }

            if ((s1 == null) || !s1.equals(s2)) {
                return false;
            }
        }

        return true;
    
public RegisterSpecfindMatchingLocal(RegisterSpec spec)
Returns the spec in this set that's currently associated with a given local (type, name, and signature), or {@code null} if there is none. This ignores the register number of the given spec but matches on everything else.

param
spec {@code non-null;} local to look for
return
{@code null-ok;} first register found that matches, if any

        int length = specs.length;

        for (int reg = 0; reg < length; reg++) {
            RegisterSpec s = specs[reg];

            if (s == null) {
                continue;
            }

            if (spec.matchesVariable(s)) {
                return s;
            }
        }

        return null;
    
public RegisterSpecget(int reg)
Gets the element with the given register number, if any.

param
reg {@code >= 0;} the desired register number
return
{@code null-ok;} the element with the given register number or {@code null} if there is none

        try {
            return specs[reg];
        } catch (ArrayIndexOutOfBoundsException ex) {
            // Translate the exception.
            throw new IllegalArgumentException("bogus reg");
        }
    
public RegisterSpecget(RegisterSpec spec)
Gets the element with the same register number as the given spec, if any. This is just a convenient shorthand for {@code get(spec.getReg())}.

param
spec {@code non-null;} spec with the desired register number
return
{@code null-ok;} the element with the matching register number or {@code null} if there is none

        return get(spec.getReg());
    
public intgetMaxSize()
Gets the maximum number of registers that may be in this instance, which is also the maximum-plus-one of register numbers that may be represented.

return
{@code >= 0;} the maximum size

        return specs.length;
    
public inthashCode()
{@inheritDoc}

        int len = specs.length;
        int hash = 0;

        for (int i = 0; i < len; i++) {
            RegisterSpec spec = specs[i];
            int oneHash = (spec == null) ? 0 : spec.hashCode();
            hash = (hash * 31) + oneHash;
        }

        return hash;
    
public voidintersect(com.android.dexgen.rop.code.RegisterSpecSet other, boolean localPrimary)
Intersects this instance with the given one, modifying this instance. The intersection consists of the pairwise {@link RegisterSpec#intersect} of corresponding elements from this instance and the given one where both are non-null.

param
other {@code non-null;} set to intersect with
param
localPrimary whether local variables are primary to the intersection; if {@code true}, then the only non-null result elements occur when registers being intersected have equal names (or both have {@code null} names)

        throwIfImmutable();

        RegisterSpec[] otherSpecs = other.specs;
        int thisLen = specs.length;
        int len = Math.min(thisLen, otherSpecs.length);

        size = -1;

        for (int i = 0; i < len; i++) {
            RegisterSpec spec = specs[i];

            if (spec == null) {
                continue;
            }

            RegisterSpec intersection =
                spec.intersect(otherSpecs[i], localPrimary);
            if (intersection != spec) {
                specs[i] = intersection;
            }
        }

        for (int i = len; i < thisLen; i++) {
            specs[i] = null;
        }
    
public RegisterSpeclocalItemToSpec(LocalItem local)
Returns the spec in this set that's currently associated with a given local (name and signature), or {@code null} if there is none.

param
local {@code non-null;} local item to search for
return
{@code null-ok;} first register found with matching name and signature

        int length = specs.length;

        for (int reg = 0; reg < length; reg++) {
            RegisterSpec spec = specs[reg];

            if ((spec != null) && local.equals(spec.getLocalItem())) {
                return spec;
            }
        }

        return null;
    
public com.android.dexgen.rop.code.RegisterSpecSetmutableCopy()
Makes and return a mutable copy of this instance.

return
{@code non-null;} the mutable copy

        int len = specs.length;
        RegisterSpecSet copy = new RegisterSpecSet(len);

        for (int i = 0; i < len; i++) {
            RegisterSpec spec = specs[i];
            if (spec != null) {
                copy.put(spec);
            }
        }

        copy.size = size;

        return copy;
    
public voidput(RegisterSpec spec)
Puts the given spec into the set. If there is already an element in the set with the same register number, it is replaced. Additionally, if the previous element is for a category-2 register, then that previous element is nullified. Finally, if the given spec is for a category-2 register, then the immediately subsequent element is nullified.

param
spec {@code non-null;} the register spec to put in the instance

        throwIfImmutable();

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

        size = -1;

        try {
            int reg = spec.getReg();
            specs[reg] = spec;

            if (reg > 0) {
                int prevReg = reg - 1;
                RegisterSpec prevSpec = specs[prevReg];
                if ((prevSpec != null) && (prevSpec.getCategory() == 2)) {
                    specs[prevReg] = null;
                }
            }

            if (spec.getCategory() == 2) {
                specs[reg + 1] = null;
            }
        } catch (ArrayIndexOutOfBoundsException ex) {
            // Translate the exception.
            throw new IllegalArgumentException("spec.getReg() out of range");
        }
    
public voidputAll(com.android.dexgen.rop.code.RegisterSpecSet set)
Put the entire contents of the given set into this one.

param
set {@code non-null;} the set to put into this instance

        int max = set.getMaxSize();

        for (int i = 0; i < max; i++) {
            RegisterSpec spec = set.get(i);
            if (spec != null) {
                put(spec);
            }
        }
    
public voidremove(RegisterSpec toRemove)
Removes a spec from the set. Only the register number of the parameter is significant.

param
toRemove {@code non-null;} register to remove.

        try {
            specs[toRemove.getReg()] = null;
            size = -1;
        } catch (ArrayIndexOutOfBoundsException ex) {
            // Translate the exception.
            throw new IllegalArgumentException("bogus reg");
        }
    
public intsize()
Gets the current size of this instance.

return
{@code >= 0;} the size

        int result = size;

        if (result < 0) {
            int len = specs.length;

            result = 0;
            for (int i = 0; i < len; i++) {
                if (specs[i] != null) {
                    result++;
                }
            }

            size = result;
        }

        return result;
    
public java.lang.StringtoString()
{@inheritDoc}

        int len = specs.length;
        StringBuffer sb = new StringBuffer(len * 25);

        sb.append('{");

        boolean any = false;
        for (int i = 0; i < len; i++) {
            RegisterSpec spec = specs[i];
            if (spec != null) {
                if (any) {
                    sb.append(", ");
                } else {
                    any = true;
                }
                sb.append(spec);
            }
        }

        sb.append('}");
        return sb.toString();
    
public com.android.dexgen.rop.code.RegisterSpecSetwithOffset(int delta)
Returns an instance that is identical to this one, except that all register numbers are offset by the given amount. Mutability of the result is inherited from the original.

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

        int len = specs.length;
        RegisterSpecSet result = new RegisterSpecSet(len + delta);

        for (int i = 0; i < len; i++) {
            RegisterSpec spec = specs[i];
            if (spec != null) {
                result.put(spec.withOffset(delta));
            }
        }

        result.size = size;

        if (isImmutable()) {
            result.setImmutable();
        }

        return result;