001: /*
002: * Bytecode Analysis Framework
003: * Copyright (C) 2004,2005 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 java.util.BitSet;
023: import java.util.HashMap;
024: import java.util.Map;
025:
026: import org.apache.bcel.generic.InstructionHandle;
027: import org.apache.bcel.generic.MethodGen;
028:
029: import edu.umd.cs.findbugs.ba.XField;
030:
031: /**
032: * Object which stores which fields are loaded and stored
033: * by the instructions in a method (including through inner-class
034: * access methods), and also which fields are loaded/stored
035: * by the overall method. The main purpose is for doing
036: * redundant load elimination and forward substitution
037: * more efficiently, but it might be useful in other situations.
038: *
039: * @author David Hovemeyer
040: */
041: public class LoadedFieldSet {
042: /**
043: * Count number of times a field is loaded and/or stored in the method.
044: */
045: public static class LoadStoreCount {
046: int loadCount, storeCount;
047:
048: /** Get the number of times the field is loaded. */
049: public int getLoadCount() {
050: return loadCount;
051: }
052:
053: /** Get the number of times the field is stored. */
054: public int getStoreCount() {
055: return storeCount;
056: }
057: }
058:
059: // Fields
060: //private MethodGen methodGen;
061: private Map<XField, LoadStoreCount> loadStoreCountMap;
062: private Map<InstructionHandle, XField> handleToFieldMap;
063: private BitSet loadHandleSet;
064:
065: /**
066: * Constructor.
067: * Constructs an empty object.
068: *
069: * @param methodGen the method being analyzed for loads/stores
070: */
071: public LoadedFieldSet(MethodGen methodGen) {
072: //this.methodGen = methodGen;
073: this .loadStoreCountMap = new HashMap<XField, LoadStoreCount>();
074: this .handleToFieldMap = new HashMap<InstructionHandle, XField>();
075: this .loadHandleSet = new BitSet();
076: }
077:
078: /**
079: * Get the number of times given field is loaded and stored
080: * within the method.
081: * @param field the field
082: * @return the load/store count object
083: */
084: public LoadStoreCount getLoadStoreCount(XField field) {
085: LoadStoreCount loadStoreCount = loadStoreCountMap.get(field);
086: if (loadStoreCount == null) {
087: loadStoreCount = new LoadStoreCount();
088: loadStoreCountMap.put(field, loadStoreCount);
089: }
090: return loadStoreCount;
091: }
092:
093: /**
094: * Add a load of given field at given instruction.
095: *
096: * @param handle the instruction
097: * @param field the field
098: */
099: public void addLoad(InstructionHandle handle, XField field) {
100: getLoadStoreCount(field).loadCount++;
101: handleToFieldMap.put(handle, field);
102: loadHandleSet.set(handle.getPosition());
103: }
104:
105: /**
106: * Add a store of given field at given instruction.
107: *
108: * @param handle the instruction
109: * @param field the field
110: */
111: public void addStore(InstructionHandle handle, XField field) {
112: getLoadStoreCount(field).storeCount++;
113: handleToFieldMap.put(handle, field);
114: }
115:
116: /**
117: * Get the field loaded or stored at given instruction, if any.
118: *
119: * @param handle the instruction
120: * @return the field loaded or stored at the instruction, or null
121: * if the instruction is not a load or store
122: */
123: public XField getField(InstructionHandle handle) {
124: return handleToFieldMap.get(handle);
125: }
126:
127: /**
128: * Return whether or not the given field is loaded by any
129: * instruction in the method.
130: *
131: * @param field the field
132: * @return true if the field is loaded somewhere in the method,
133: * false if it is never loaded
134: */
135: public boolean isLoaded(XField field) {
136: return getLoadStoreCount(field).loadCount > 0;
137: }
138:
139: /**
140: * Return whether or not the given instruction is a load.
141: *
142: * @param handle the instruction
143: * @return true if the instruction is a load, false if not
144: */
145: public boolean instructionIsLoad(InstructionHandle handle) {
146: return loadHandleSet.get(handle.getPosition());
147: }
148: }
149:
150: // vim:ts=4
|