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.jsr305;
021:
022: import java.util.Collections;
023: import java.util.HashMap;
024: import java.util.HashSet;
025: import java.util.Map;
026: import java.util.Set;
027:
028: import org.apache.bcel.generic.ConstantPoolGen;
029: import org.apache.bcel.generic.InstructionHandle;
030:
031: import edu.umd.cs.findbugs.SystemProperties;
032: import edu.umd.cs.findbugs.ba.AbstractDataflowAnalysis;
033: import edu.umd.cs.findbugs.ba.BasicBlock;
034: import edu.umd.cs.findbugs.ba.CFG;
035: import edu.umd.cs.findbugs.ba.DataflowAnalysisException;
036: import edu.umd.cs.findbugs.ba.Edge;
037: import edu.umd.cs.findbugs.ba.Location;
038: import edu.umd.cs.findbugs.ba.XMethod;
039: import edu.umd.cs.findbugs.ba.vna.ValueNumber;
040: import edu.umd.cs.findbugs.ba.vna.ValueNumberDataflow;
041: import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;
042:
043: /**
044: * Abstract base class for type qualifier dataflow analyses.
045: *
046: * @author David Hovemeyer
047: */
048: public abstract class TypeQualifierDataflowAnalysis extends
049: AbstractDataflowAnalysis<TypeQualifierValueSet> {
050: static final boolean DEBUG_VERBOSE = SystemProperties
051: .getBoolean("ctq.dataflow.debug.verbose");
052:
053: protected final XMethod xmethod;
054: protected final CFG cfg;
055: protected final ValueNumberDataflow vnaDataflow;
056: protected final TypeQualifierValue typeQualifierValue;
057: protected final ConstantPoolGen cpg;
058: private Map<Location, Set<SourceSinkInfo>> sourceSinkMap;
059:
060: /**
061: * Constructor.
062: *
063: * @param dfs DepthFirstSearch on the control-flow graph of the method being analyzed
064: * @param xmethod XMethod object containing information about the method being analyzed
065: * @param cfg the control-flow graph (CFG) of the method being analyzed
066: * @param vnaDataflow ValueNumberDataflow for the method
067: * @param typeQualifierValue the TypeQualifierValue we want the dataflow analysis to check
068: */
069: public TypeQualifierDataflowAnalysis(XMethod xmethod, CFG cfg,
070: ValueNumberDataflow vnaDataflow, ConstantPoolGen cpg,
071: TypeQualifierValue typeQualifierValue) {
072: this .xmethod = xmethod;
073: this .cfg = cfg;
074: this .vnaDataflow = vnaDataflow;
075: this .cpg = cpg;
076: this .typeQualifierValue = typeQualifierValue;
077: this .sourceSinkMap = new HashMap<Location, Set<SourceSinkInfo>>();
078: }
079:
080: /* (non-Javadoc)
081: * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#initEntryFact(java.lang.Object)
082: */
083: public void initEntryFact(TypeQualifierValueSet result)
084: throws DataflowAnalysisException {
085: result.makeValid();
086: }
087:
088: /* (non-Javadoc)
089: * @see edu.umd.cs.findbugs.ba.AbstractDataflowAnalysis#isFactValid(java.lang.Object)
090: */
091: @Override
092: public boolean isFactValid(TypeQualifierValueSet fact) {
093: return fact.isValid();
094: }
095:
096: /* (non-Javadoc)
097: * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#copy(java.lang.Object, java.lang.Object)
098: */
099: public void copy(TypeQualifierValueSet source,
100: TypeQualifierValueSet dest) {
101: dest.makeSameAs(source);
102: }
103:
104: /* (non-Javadoc)
105: * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#createFact()
106: */
107: public TypeQualifierValueSet createFact() {
108: return new TypeQualifierValueSet();
109: }
110:
111: /* (non-Javadoc)
112: * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#isTop(java.lang.Object)
113: */
114: public boolean isTop(TypeQualifierValueSet fact) {
115: return fact.isTop();
116: }
117:
118: /* (non-Javadoc)
119: * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#makeFactTop(java.lang.Object)
120: */
121: public void makeFactTop(TypeQualifierValueSet fact) {
122: fact.setTop();
123: }
124:
125: /* (non-Javadoc)
126: * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#meetInto(java.lang.Object, edu.umd.cs.findbugs.ba.Edge, java.lang.Object)
127: */
128: public void meetInto(TypeQualifierValueSet fact, Edge edge,
129: TypeQualifierValueSet result)
130: throws DataflowAnalysisException {
131: if (fact.isTop() || result.isBottom()) {
132: // result does not change
133: return;
134: } else if (fact.isBottom() || result.isTop()) {
135: result.makeSameAs(fact);
136: return;
137: }
138:
139: assert fact.isValid();
140: assert result.isValid();
141:
142: result.mergeWith(fact);
143: }
144:
145: /* (non-Javadoc)
146: * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#same(java.lang.Object, java.lang.Object)
147: */
148: public boolean same(TypeQualifierValueSet fact1,
149: TypeQualifierValueSet fact2) {
150: return fact1.equals(fact2);
151: }
152:
153: /* (non-Javadoc)
154: * @see edu.umd.cs.findbugs.ba.BasicAbstractDataflowAnalysis#edgeTransfer(edu.umd.cs.findbugs.ba.Edge, java.lang.Object)
155: */
156: @Override
157: public void edgeTransfer(Edge edge, TypeQualifierValueSet fact)
158: throws DataflowAnalysisException {
159: if (!fact.isValid()) {
160: return;
161: }
162:
163: // Propagate flow values and source information across phi nodes.
164:
165: ValueNumberFrame targetVnaFrame = vnaDataflow.getStartFact(edge
166: .getTarget());
167: ValueNumberFrame sourceVnaFrame = vnaDataflow
168: .getResultFact(edge.getSource());
169:
170: if (!targetVnaFrame.isValid() || !sourceVnaFrame.isValid()) {
171: return;
172: }
173:
174: // The source and target frames can have different numbers of slots
175: // if the target is an exception handler.
176: // So, merge the minimum number of slots in either frame.
177: int numSlotsToMerge = Math.min(sourceVnaFrame.getNumSlots(),
178: targetVnaFrame.getNumSlots());
179:
180: for (int i = 0; i < numSlotsToMerge; i++) {
181: ValueNumber targetVN = targetVnaFrame.getValue(i);
182: ValueNumber sourceVN = sourceVnaFrame.getValue(i);
183:
184: if (!targetVN.equals(sourceVN)
185: && targetVN.hasFlag(ValueNumber.PHI_NODE)) {
186: // targetVN is a phi result
187: if (DEBUG_VERBOSE) {
188: System.out.println("Phi node: "
189: + fact.valueNumberToString(sourceVN)
190: + " -> "
191: + fact.valueNumberToString(targetVN));
192: }
193: propagateAcrossPhiNode(fact, sourceVN, targetVN);
194: if (DEBUG_VERBOSE) {
195: String dir = isForwards() ? "forwards"
196: : "backwards";
197: System.out.println("After propagating phi node "
198: + dir + ": " + fact.toString());
199: }
200: }
201: }
202: }
203:
204: protected abstract void propagateAcrossPhiNode(
205: TypeQualifierValueSet fact, ValueNumber sourceVN,
206: ValueNumber targetVN);
207:
208: /**
209: * This method must be called before the dataflow analysis
210: * is executed.
211: *
212: * @throws DataflowAnalysisException
213: */
214: public abstract void registerSourceSinkLocations()
215: throws DataflowAnalysisException;
216:
217: protected void registerSourceSink(SourceSinkInfo sourceSinkInfo) {
218: Set<SourceSinkInfo> set = sourceSinkMap.get(sourceSinkInfo
219: .getLocation());
220: if (set == null) {
221: set = new HashSet<SourceSinkInfo>();
222: sourceSinkMap.put(sourceSinkInfo.getLocation(), set);
223: }
224: set.add(sourceSinkInfo);
225: }
226:
227: /**
228: * Get the set of SourceSinkInfo objects representing sources/sinks
229: * at a given Location.
230: *
231: * @param location a Location
232: * @return Set of SourceSinkInfo objects representing sources/sinks at the Location
233: */
234: public Set<SourceSinkInfo> getSourceSinkInfoSet(Location location) {
235: Set<SourceSinkInfo> result = sourceSinkMap.get(location);
236: return result != null ? result
237: : (Set<SourceSinkInfo>) Collections.EMPTY_SET;
238: }
239:
240: /* (non-Javadoc)
241: * @see edu.umd.cs.findbugs.ba.AbstractDataflowAnalysis#transferInstruction(org.apache.bcel.generic.InstructionHandle, edu.umd.cs.findbugs.ba.BasicBlock, java.lang.Object)
242: */
243: @Override
244: public void transferInstruction(InstructionHandle handle,
245: BasicBlock basicBlock, TypeQualifierValueSet fact)
246: throws DataflowAnalysisException {
247: if (!fact.isValid()) {
248: return;
249: }
250:
251: // This is a simple process.
252: // Check to see if there are any sources/sinks at this location,
253: // and if so, model them.
254:
255: Location location = new Location(handle, basicBlock);
256: Set<SourceSinkInfo> sourceSinkSet = sourceSinkMap.get(location);
257: if (sourceSinkSet != null) {
258: if (DEBUG_VERBOSE) {
259: System.out.println("Modeling source/sink at "
260: + location.toCompactString() + ": "
261: + sourceSinkSet.toString());
262: }
263: for (SourceSinkInfo sourceSinkInfo : sourceSinkSet) {
264: fact.modelSourceSink(sourceSinkInfo);
265: }
266: }
267: }
268: }
|