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

RegisterSpec

public final class RegisterSpec extends Object implements com.android.dx.util.ToHuman, Comparable, com.android.dx.rop.type.TypeBearer
Combination of a register number and a type, used as the sources and destinations of register-based operations.

Fields Summary
public static final String
PREFIX
non-null; string to prefix register numbers with
private static final HashMap
theInterns
non-null; intern table for instances
private static final ForComparison
theInterningItem
non-null; common comparison instance used while interning
private final int
reg
>= 0; register number
private final com.android.dx.rop.type.TypeBearer
type
non-null; type loaded or stored
private final LocalItem
local
null-ok; local variable info associated with this register, if any
Constructors Summary
private RegisterSpec(int reg, com.android.dx.rop.type.TypeBearer type, LocalItem local)
Constructs an instance. This constructor is private. Use {@link #make}.

param
reg >= 0; the register number
param
type non-null; the type (or possibly actual value) which is loaded from or stored to the indicated register
param
local null-ok; the associated local variable, if any

        if (reg < 0) {
            throw new IllegalArgumentException("reg < 0");
        }

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

        this.reg = reg;
        this.type = type;
        this.local = local;
    
Methods Summary
public intcompareTo(com.android.dx.rop.code.RegisterSpec other)
Compares by (in priority order) register number, unwrapped type (that is types not {@link TypeBearer}s, and local info.

param
other non-null; spec to compare to
return
{@code -1..1}; standard result of comparison

        if (this.reg < other.reg) {
            return -1;
        } else if (this.reg > other.reg) {
            return 1;
        }

        int compare = type.getType().compareTo(other.type.getType());

        if (compare != 0) {
            return compare;
        }

        if (this.local == null) {
            return (other.local == null) ? 0 : -1;
        } else if (other.local == null) {
            return 1;
        }

        return this.local.compareTo(other.local);
    
private booleanequals(int reg, com.android.dx.rop.type.TypeBearer type, LocalItem local)
Helper for {@link #equals} and {@link #ForComparison.equals}, which actually does the test.

param
reg value of the instance variable, for another instance
param
type value of the instance variable, for another instance
param
local value of the instance variable, for another instance
return
whether this instance is equal to one with the given values

        return (this.reg == reg)
            && this.type.equals(type)
            && ((this.local == local)
                    || ((this.local != null) && this.local.equals(local)));
    
public booleanequals(java.lang.Object other)
{@inheritDoc}

        if (!(other instanceof RegisterSpec)) {
            if (other instanceof ForComparison) {
                ForComparison fc = (ForComparison) other;
                return equals(fc.reg, fc.type, fc.local);
            }
            return false;
        }

        RegisterSpec spec = (RegisterSpec) other;
        return equals(spec.reg, spec.type, spec.local);
    
public booleanequalsUsingSimpleType(com.android.dx.rop.code.RegisterSpec other)
Like {@code equals}, but only consider the simple types of the registers. That is, this compares {@code getType()} on the types to ignore whatever arbitrary extra stuff might be carried around by an outer {@link TypeBearer}.

param
other null-ok; spec to compare to
return
{@code true} iff {@code this} and {@code other} are equal in the stated way

        if (!matchesVariable(other)) {
            return false;
        }

        return (reg == other.reg);
    
public final intgetBasicFrameType()
{@inheritDoc}

        return type.getBasicFrameType();
    
public final intgetBasicType()
{@inheritDoc}

        return type.getBasicType();
    
public intgetCategory()
Gets the category of this instance's type. This is just a convenient shorthand for getType().getCategory().

see
#isCategory1
see
#isCategory2
return
1..2; the category of this instance's type

        return type.getType().getCategory();
    
public com.android.dx.rop.type.TypeBearergetFrameType()
{@inheritDoc}

        return type.getFrameType();
    
public LocalItemgetLocalItem()
Gets the variable info associated with this instance, if any.

return
null-ok; the variable info, or null if this instance has none

        return local;
    
public intgetNextReg()
Gets the next available register number after the one in this instance. This is equal to the register number plus the width (category) of the type used. Among other things, this may also be used to determine the minimum required register count implied by this instance.

return
>= 0; the required registers size

        return reg + getCategory();
    
public intgetReg()
Gets the register number.

return
>= 0; the register number

        return reg;
    
public com.android.dx.rop.type.TypegetType()
{@inheritDoc}

        return type.getType();
    
public com.android.dx.rop.type.TypeBearergetTypeBearer()
Gets the type (or actual value) which is loaded from or stored to the register associated with this instance.

return
non-null; the type

        return type;
    
public inthashCode()
{@inheritDoc}

        return hashCodeOf(reg, type, local);
    
private static inthashCodeOf(int reg, com.android.dx.rop.type.TypeBearer type, LocalItem local)
Helper for {@link #hashCode} and {@link #ForComparison.hashCode}, which actually does the calculation.

param
reg value of the instance variable
param
type value of the instance variable
param
local value of the instance variable
return
the hash code

        int hash = (local != null) ? local.hashCode() : 0;

        hash = (hash * 31 + type.hashCode()) * 31 + reg;
        return hash;
    
private static com.android.dx.rop.code.RegisterSpecintern(int reg, com.android.dx.rop.type.TypeBearer type, LocalItem local)
Intern the given triple as an instance of this class.

param
reg >= 0; the register number
param
type non-null; the type (or possibly actual value) which is loaded from or stored to the indicated register
param
local null-ok; the associated local variable, if any
return
non-null; an appropriately-constructed instance


                                                           
          
              
        theInterningItem.set(reg, type, local);
        RegisterSpec found = theInterns.get(theInterningItem);

        if (found != null) {
            return found;
        }

        found = theInterningItem.toRegisterSpec();
        theInterns.put(found, found);
        return found;
    
public com.android.dx.rop.code.RegisterSpecintersect(com.android.dx.rop.code.RegisterSpec other, boolean localPrimary)
Returns an instance that is the intersection between this instance and the given one, if any. The intersection is defined as follows:
  • If other is null, then the result is null.
  • If the register numbers don't match, then the intersection is null. Otherwise, the register number of the intersection is the same as the one in the two instances.
  • If the types returned by getType() are not equals(), then the intersection is null.
  • If the type bearers returned by getTypeBearer() are equals(), then the intersection's type bearer is the one from this instance. Otherwise, the intersection's type bearer is the getType() of this instance.
  • If the locals are equals(), then the local info of the intersection is the local info of this instance. Otherwise, the local info of the intersection is null.

param
other null-ok; instance to intersect with (or null)
param
localPrimary whether local variables are primary to the intersection; if true, then the only non-null results occur when registers being intersected have equal local infos (or both have null local infos)
return
null-ok; the intersection

        if (this == other) {
            // Easy out.
            return this;
        }

        if ((other == null) || (reg != other.getReg())) {
            return null;
        }

        LocalItem resultLocal =
            ((local == null) || !local.equals(other.getLocalItem()))
            ? null : local;
        boolean sameName = (resultLocal == local);

        if (localPrimary && !sameName) {
            return null;
        }

        Type thisType = getType();
        Type otherType = other.getType();

        // Note: Types are always interned.
        if (thisType != otherType) {
            return null;
        }

        TypeBearer resultTypeBearer =
            type.equals(other.getTypeBearer()) ? type : thisType;

        if ((resultTypeBearer == type) && sameName) {
            // It turns out that the intersection is "this" after all.
            return this;
        }

        return (resultLocal == null) ? make(reg, resultTypeBearer) :
            make(reg, resultTypeBearer, resultLocal);
    
public booleanisCategory1()
Gets whether this instance's type is category 1. This is just a convenient shorthand for getType().isCategory1().

see
#getCategory
see
#isCategory2
return
whether or not this instance's type is of category 1

        return type.getType().isCategory1();
    
public booleanisCategory2()
Gets whether this instance's type is category 2. This is just a convenient shorthand for getType().isCategory2().

see
#getCategory
see
#isCategory1
return
whether or not this instance's type is of category 2

        return type.getType().isCategory2();
    
public final booleanisConstant()
{@inheritDoc}

        return false;
    
public static com.android.dx.rop.code.RegisterSpecmake(int reg, com.android.dx.rop.type.TypeBearer type)
Returns an instance for the given register number and type, with no variable info. This method is allowed to return shared instances (but doesn't necessarily do so).

param
reg >= 0; the register number
param
type non-null; the type (or possibly actual value) which is loaded from or stored to the indicated register
return
non-null; an appropriately-constructed instance

        return intern(reg, type, null);
    
public static com.android.dx.rop.code.RegisterSpecmake(int reg, com.android.dx.rop.type.TypeBearer type, LocalItem local)
Returns an instance for the given register number, type, and variable info. This method is allowed to return shared instances (but doesn't necessarily do so).

param
reg >= 0; the register number
param
type non-null; the type (or possibly actual value) which is loaded from or stored to the indicated register
param
local non-null; the associated local variable
return
non-null; an appropriately-constructed instance

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

        return intern(reg, type, local);
    
public static com.android.dx.rop.code.RegisterSpecmakeLocalOptional(int reg, com.android.dx.rop.type.TypeBearer type, LocalItem local)
Returns an instance for the given register number, type, and variable info. This method is allowed to return shared instances (but doesn't necessarily do so).

param
reg >= 0; the register number
param
type non-null; the type (or possibly actual value) which is loaded from or stored to the indicated register
param
local null-ok; the associated variable info or null for none
return
non-null; an appropriately-constructed instance


        return intern(reg, type, local);
    
public booleanmatchesVariable(com.android.dx.rop.code.RegisterSpec other)
Like {@link #equalsUsingSimpleType} but ignoring the register number. This is useful to determine if two instances refer to the "same" local variable.

param
other null-ok; spec to compare to
return
{@code true} iff {@code this} and {@code other} are equal in the stated way

        if (other == null) {
            return false;
        }

        return type.getType().equals(other.type.getType())
            && ((local == other.local)
                    || ((local != null) && local.equals(other.local)));
    
public java.lang.StringregString()
Gets the string form for just the register number of this instance.

return
non-null; the register string form

        return regString(reg);
    
public static java.lang.StringregString(int reg)
Gets the string form for the given register number.

param
reg >= 0; the register number
return
non-null; the string form

        return PREFIX + reg;
    
public java.lang.StringtoHuman()
{@inheritDoc}

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

        return toString0(false);
    
private java.lang.StringtoString0(boolean human)
Helper for {@link #toString} and {@link #toHuman}.

param
human whether to be human-oriented
return
non-null; the string form

        StringBuffer sb = new StringBuffer(40);

        sb.append(regString());
        sb.append(":");

        if (local != null) {
            sb.append(local.toString());
        }

        Type justType = type.getType();
        sb.append(justType);

        if (justType != type) {
            sb.append("=");
            if (human && (type instanceof Constant)) {
                sb.append(((Constant) type).toHuman());
            } else {
                sb.append(type);
            }
        }

        return sb.toString();
    
public com.android.dx.rop.code.RegisterSpecwithLocalItem(LocalItem local)
Returns an instance that is identical to this one except that the local variable is as specified in the parameter.

param
local null-ok; the local item or null for none
return
an appropriate instance

        if ((this.local== local)
                    || ((this.local != null) && this.local.equals(local))) {

            return this;
        }

        return makeLocalOptional(reg, type, local);
    
public com.android.dx.rop.code.RegisterSpecwithOffset(int delta)
Returns an instance that is identical to this one, except that the register number is offset by the given amount.

param
delta the amount to offset the register number by
return
non-null; an appropriately-constructed instance

        if (delta == 0) {
            return this;
        }

        return withReg(reg + delta);
    
public com.android.dx.rop.code.RegisterSpecwithReg(int newReg)
Returns an instance that is identical to this one, except that the register number is replaced by the given one.

param
newReg >= 0; the new register number
return
non-null; an appropriately-constructed instance

        if (reg == newReg) {
            return this;
        }

        return makeLocalOptional(newReg, type, local);
    
public com.android.dx.rop.code.RegisterSpecwithSimpleType()
Returns an instance that is identical to this one, except that the type bearer is replaced by the actual underlying type (thereby stripping off non-type information) with any initialization information stripped away as well.

return
non-null; an appropriately-constructed instance

        TypeBearer orig = type;
        Type newType;

        if (orig instanceof Type) {
            newType = (Type) orig;
        } else {
            newType = orig.getType();
        }

        if (newType.isUninitialized()) {
            newType = newType.getInitializedType();
        }

        if (newType == orig) {
            return this;
        }

        return makeLocalOptional(reg, newType, local);
    
public com.android.dx.rop.code.RegisterSpecwithType(com.android.dx.rop.type.TypeBearer newType)
Returns an instance that is identical to this one, except that the type is replaced by the given one.

param
newType non-null; the new type
return
non-null; an appropriately-constructed instance

        return makeLocalOptional(reg, newType, local);