/*
* Bytecode Analysis Framework
* Copyright (C) 2003,2004 University of Maryland
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package edu.umd.cs.findbugs.ba.vna;
import edu.umd.cs.findbugs.ba.XField;
/**
* An AvailableLoad indicates a field and (optionally) object reference for
* which a value is available. It is used to implement redundant load
* elimination and forward substitution in ValueNumberAnalysis. The idea is that
* programmers often reload fields unnecessarily when they "know" that the value
* will not change. In order to deduce the intended meaning of such code, our
* analyses need to figure out that such loads return the same value.
* <p/>
* <p>
* AvailableLoad objects may be used as keys in both hash and tree sets and
* maps.
*
* @author David Hovemeyer
* @see ValueNumberAnalysis
*/
public class AvailableLoad implements Comparable<AvailableLoad> {
private final ValueNumber reference;
private final XField field;
/**
* Constructor from static field.
*
* @param staticField
* the StaticField
*/
public AvailableLoad(XField staticField) {
this.reference = null;
this.field = staticField;
}
/**
* Constructor from object reference and instance field.
*
* @param reference
* the ValueNumber of the object reference
* @param field
* the InstanceField
*/
public AvailableLoad(ValueNumber reference, XField field) {
if (reference == null)
throw new IllegalArgumentException();
this.reference = reference;
this.field = field;
}
/**
* Get the ValueNumber of the object reference.
*
* @return the ValueNumber, or null if this is a an available static field
* load
*/
public ValueNumber getReference() {
return reference;
}
public boolean matchesReference(ValueNumber v) {
if (v == reference)
return true;
if (reference == null)
return false;
return reference.equals(v);
}
/**
* Get the field for which a load is available.
*
* @return the XField
*/
public XField getField() {
return field;
}
@SuppressWarnings("unchecked")
public int compareTo(AvailableLoad other) {
int cmp = field.compareTo(other.field);
if (cmp != 0)
return cmp;
else if (reference == other.reference)
return 0;
else if (reference == null)
return -1;
else if (other.reference == null)
return 1;
else
return reference.compareTo(other.reference);
}
@Override
public int hashCode() {
return (reference == null ? 0 : reference.hashCode()) ^ field.hashCode();
}
@Override
public boolean equals(Object o) {
if (o == null || this.getClass() != o.getClass())
return false;
AvailableLoad other = (AvailableLoad) o;
return (reference == other.reference || (reference != null && other.reference != null && reference
.equals(other.reference))) && field.equals(other.field);
}
@Override
public String toString() {
return (reference == null ? "" : reference.getNumber() + ".") + field;
}
}
// vim:ts=4