001: /*
002: * Bytecode Analysis Framework
003: * Copyright (C) 2003,2004 University of Maryland
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: */
019:
020: package edu.umd.cs.findbugs.ba.vna;
021:
022: import edu.umd.cs.findbugs.ba.XField;
023:
024: /**
025: * An AvailableLoad indicates a field and (optionally) object reference
026: * for which a value is available. It is used to implement
027: * redundant load elimination and forward substitution in ValueNumberAnalysis.
028: * The idea is that programmers often reload fields unnecessarily when they
029: * "know" that the value will not change. In order to deduce the intended
030: * meaning of such code, our analyses need to figure out that such
031: * loads return the same value.
032: * <p/>
033: * <p> AvailableLoad objects may be used as keys in both hash and tree
034: * sets and maps.
035: *
036: * @author David Hovemeyer
037: * @see ValueNumberAnalysis
038: */
039: public class AvailableLoad implements Comparable<AvailableLoad> {
040: private final ValueNumber reference;
041: private final XField field;
042:
043: /**
044: * Constructor from static field.
045: *
046: * @param staticField the StaticField
047: */
048: public AvailableLoad(XField staticField) {
049: this .reference = null;
050: this .field = staticField;
051: }
052:
053: /**
054: * Constructor from object reference and instance field.
055: *
056: * @param reference the ValueNumber of the object reference
057: * @param field the InstanceField
058: */
059: public AvailableLoad(ValueNumber reference, XField field) {
060: if (reference == null)
061: throw new IllegalArgumentException();
062: this .reference = reference;
063: this .field = field;
064: }
065:
066: /**
067: * Get the ValueNumber of the object reference.
068: *
069: * @return the ValueNumber, or null if this is a an available
070: * static field load
071: */
072: public ValueNumber getReference() {
073: return reference;
074: }
075:
076: public boolean matchesReference(ValueNumber v) {
077: if (v == reference)
078: return true;
079: if (reference == null)
080: return false;
081: return reference.equals(v);
082: }
083:
084: /**
085: * Get the field for which a load is available.
086: *
087: * @return the XField
088: */
089: public XField getField() {
090: return field;
091: }
092:
093: public int compareTo(AvailableLoad other) {
094: int cmp = field.compareTo(other.field);
095: if (cmp != 0)
096: return cmp;
097: else if (reference == other.reference)
098: return 0;
099: else if (reference == null)
100: return -1;
101: else if (other.reference == null)
102: return 1;
103: else
104: return reference.compareTo(other.reference);
105: }
106:
107: @Override
108: public int hashCode() {
109: return (reference == null ? 0 : reference.hashCode())
110: ^ field.hashCode();
111: }
112:
113: @Override
114: public boolean equals(Object o) {
115: if (o == null || this .getClass() != o.getClass())
116: return false;
117: AvailableLoad other = (AvailableLoad) o;
118: return (reference == other.reference || (reference != null
119: && other.reference != null && reference
120: .equals(other.reference)))
121: && field.equals(other.field);
122: }
123:
124: @Override
125: public String toString() {
126: return (reference == null ? "" : reference.getNumber() + ".")
127: + field;
128: }
129: }
130:
131: // vim:ts=4
|