001: /*
002: * FindBugs - Find Bugs in Java programs
003: * Copyright (C) 2003-2007 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;
021:
022: import java.util.IdentityHashMap;
023: import java.util.Iterator;
024: import java.util.Map;
025:
026: /**
027: * A useful starting point for defining a dataflow analysis.
028: * Handles access and caching of start and result facts for
029: * basic blocks.
030: *
031: * <p>
032: * Subclasses that model instructions within basic blocks
033: * should extend AbstractDataflowAnalysis.
034: * </p>
035: *
036: * @author David Hovemeyer
037: */
038: public abstract class BasicAbstractDataflowAnalysis<Fact> implements
039: DataflowAnalysis<Fact> {
040: private IdentityHashMap<BasicBlock, Fact> startFactMap;
041: private IdentityHashMap<BasicBlock, Fact> resultFactMap;
042:
043: /**
044: * Constructor.
045: */
046: public BasicAbstractDataflowAnalysis() {
047: this .startFactMap = new IdentityHashMap<BasicBlock, Fact>();
048: this .resultFactMap = new IdentityHashMap<BasicBlock, Fact>();
049: }
050:
051: /**
052: * Get an iterator over the result facts.
053: */
054: public Iterator<Fact> resultFactIterator() {
055: return resultFactMap.values().iterator();
056: }
057:
058: /*
059: * Default implementation - subclasses may override.
060: */
061: public String factToString(Fact fact) {
062: return fact.toString();
063: }
064:
065: public/*final*/Fact getStartFact(BasicBlock block) {
066: return lookupOrCreateFact(startFactMap, block);
067: }
068:
069: public/*final*/Fact getResultFact(BasicBlock block) {
070: return lookupOrCreateFact(resultFactMap, block);
071: }
072:
073: /**
074: * Get dataflow fact at (just before) given Location.
075: * Note "before" is meant in the logical sense, so for backward analyses,
076: * before means after the location in the control flow sense.
077: *
078: * <p>
079: * The default implementation ignores instructions within basic blocks.
080: * Subclasses that model individual instructions must override this method.
081: * </p>
082: *
083: * @param location the Location
084: * @return the dataflow value at given Location
085: * @throws DataflowAnalysisException
086: */
087: public Fact getFactAtLocation(Location location)
088: throws DataflowAnalysisException {
089: return getStartFact(location.getBasicBlock());
090: }
091:
092: /**
093: * Get the dataflow fact representing the point just after given Location.
094: * Note "after" is meant in the logical sense, so for backward analyses,
095: * after means before the location in the control flow sense.
096: *
097: * <p>
098: * The default implementation ignores instructions within basic blocks.
099: * Subclasses that model individual instructions must override this method.
100: * </p>
101: *
102: * @param location the Location
103: * @return the dataflow value after given Location
104: * @throws DataflowAnalysisException
105: */
106: public Fact getFactAfterLocation(Location location)
107: throws DataflowAnalysisException {
108: return getResultFact(location.getBasicBlock());
109: }
110:
111: /**
112: * Get the fact that is true on the given control edge,
113: * <em>after applying the edge transfer function</em> (if any).
114: *
115: * @param edge the edge
116: * @return the fact that is true after applying the edge transfer function
117: * @throws DataflowAnalysisException
118: */
119: public/*final*/Fact getFactOnEdge(Edge edge)
120: throws DataflowAnalysisException {
121: BasicBlock block = isForwards() ? edge.getSource() : edge
122: .getTarget();
123:
124: Fact predFact = createFact();
125: copy(getResultFact(block), predFact);
126:
127: edgeTransfer(edge, predFact);
128:
129: Fact result = createFact();
130: makeFactTop(result);
131: meetInto(predFact, edge, result);
132:
133: return result;
134: }
135:
136: /* (non-Javadoc)
137: * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#startIteration()
138: */
139: public void startIteration() {
140: // Do nothing - subclass may override
141: }
142:
143: /* (non-Javadoc)
144: * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#finishIteration()
145: */
146: public void finishIteration() {
147: // Do nothing - subclass may override
148: }
149:
150: /* (non-Javadoc)
151: * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#edgeTransfer(edu.umd.cs.findbugs.ba.Edge, java.lang.Object)
152: */
153: public void edgeTransfer(Edge edge, Fact fact)
154: throws DataflowAnalysisException {
155: // By default, edge transfer function is identity.
156: // Subclasses may override.
157: }
158:
159: private Fact lookupOrCreateFact(Map<BasicBlock, Fact> map,
160: BasicBlock block) {
161: Fact fact = map.get(block);
162: if (fact == null) {
163: fact = createFact();
164: map.put(block, fact);
165: }
166: return fact;
167: }
168:
169: public int getLastUpdateTimestamp(Fact fact) {
170: return 0;
171: }
172:
173: public void setLastUpdateTimestamp(Fact fact,
174: int lastUpdateTimestamp) {
175:
176: }
177:
178: }
|