add more comments
[IRC.git] / Robust / src / Analysis / TaskStateAnalysis / FlagState.java
1 package Analysis.TaskStateAnalysis;
2 import Analysis.TaskStateAnalysis.*;
3 import IR.*;
4 import IR.Tree.*;
5 import IR.Flat.*;
6 import java.util.*;
7 import java.io.*;
8 import Util.GraphNode;
9
10 /** This class is used to hold the flag states that a class in the Bristlecone 
11  *  program can exist in, during runtime.
12  */
13 public class FlagState extends GraphNode {
14     public static final int ONETAG=1;
15     public static final int NOTAGS=0;
16     public static final int MULTITAGS=-1;
17     
18     private int uid;
19     private static int nodeid=0;
20
21     private final HashSet flagstate;
22     private final ClassDescriptor cd;
23     private final Hashtable<TagDescriptor,Integer> tags;
24     private boolean issourcenode;
25     private Vector tasks;
26
27     private boolean marked=false;
28     
29
30     /** Class constructor
31      *  Creates a new flagstate with all flags set to false.
32      *  @param cd ClassDescriptor
33      */
34     public FlagState(ClassDescriptor cd) {
35         this.flagstate=new HashSet();
36         this.cd=cd;
37         this.tags=new Hashtable<TagDescriptor,Integer>();
38         this.uid=FlagState.nodeid++;
39         this.issourcenode=false;
40     }
41
42     /** Class constructor
43      *  Creates a new flagstate with flags set according to the HashSet.
44      *  If the flag exists in the hashset, it's set to true else set to false.
45      *  @param cd ClassDescriptor
46      *  @param flagstate a <CODE>HashSet</CODE> containing FlagDescriptors
47      */
48     private FlagState(HashSet flagstate, ClassDescriptor cd,Hashtable<TagDescriptor,Integer> tags) {
49         this.flagstate=flagstate;
50         this.cd=cd;
51         this.tags=tags;
52         this.uid=FlagState.nodeid++;
53         this.issourcenode=false;
54         
55     }
56    
57     public int getuid() {
58         return uid;
59     }
60
61     public boolean isMarked() {
62         return marked;
63     }
64
65     public void doUnmarking() {
66         marked = false;
67     }
68
69     public void doMarking() {
70         marked = true;
71     }
72             
73     /** Accessor method
74       *  @param fd FlagDescriptor
75       *  @return true if the flagstate contains fd else false.
76       */
77     public boolean get(FlagDescriptor fd) {
78         return flagstate.contains(fd);
79     }
80     
81     /** Checks if the flagstate is a source node. 
82      *  @return true if the flagstate is a sourcenode(i.e. Is the product of an allocation site).
83      */
84       
85     public boolean isSourceNode(){
86             return issourcenode;
87         }
88         
89         /**  Sets the flagstate as a source node. 
90      */
91         public void setAsSourceNode(){
92                 if(!issourcenode){
93                         issourcenode=true;
94                         this.tasks=new Vector();
95                 }
96         }
97         
98         public void addAllocatingTask(TaskDescriptor task){
99                 tasks.add(task);
100         }
101
102         public Vector getAllocatingTasks(){
103                 return tasks;
104         }
105                 
106     
107     public String toString() {
108         return cd.toString()+getTextLabel();
109     }
110
111     /** @return Iterator over the flags in the flagstate.
112      */
113      
114     public Iterator getFlags() {
115         return flagstate.iterator();
116     }
117
118     public int numFlags(){
119         return flagstate.size();
120     }
121     
122     public FlagState[] setTag(TagDescriptor tag){
123         HashSet newset1=(HashSet)flagstate.clone();
124         Hashtable<TagDescriptor,Integer> newtags1=(Hashtable<TagDescriptor,Integer>)tags.clone();
125             
126         if (tags.containsKey(tag)){
127             //Code could try to remove flag that doesn't exist
128             
129             switch (tags.get(tag).intValue()){
130             case ONETAG:
131                 newtags1.put(tag,new Integer(MULTITAGS));
132                 return new FlagState[] {this, new FlagState(newset1, cd, newtags1)};
133             case MULTITAGS:
134                 return new FlagState[] {this};
135             default:
136                 throw new Error();
137             }
138         } else {
139             newtags1.put(tag,new Integer(ONETAG));
140             return new FlagState[] {new FlagState(newset1,cd,newtags1)};
141         }
142     }
143
144     public int getTagCount(String tagtype){
145         for (Enumeration en=getTags();en.hasMoreElements();){
146             TagDescriptor td=(TagDescriptor)en.nextElement();
147             if (tagtype.equals(td.getSymbol()))
148                 return tags.get(td).intValue();   //returns either ONETAG or MULTITAG
149         }
150         return NOTAGS;
151     }
152     
153     public FlagState[] clearTag(TagDescriptor tag){
154         if (tags.containsKey(tag)){
155             switch(tags.get(tag).intValue()){
156             case ONETAG:
157                 HashSet newset=(HashSet)flagstate.clone();
158                 Hashtable<TagDescriptor,Integer> newtags=(Hashtable<TagDescriptor,Integer>)tags.clone();
159                 newtags.remove(tag);
160                 return new FlagState[]{new FlagState(newset,cd,newtags)};
161                 
162             case MULTITAGS:
163                 //two possibilities - count remains 2 or becomes 1
164                 //2 case
165                 HashSet newset1=(HashSet)flagstate.clone();
166                 Hashtable<TagDescriptor,Integer> newtags1=(Hashtable<TagDescriptor,Integer>)tags.clone();
167
168                 //1 case
169                 HashSet newset2=(HashSet)flagstate.clone();
170                 Hashtable<TagDescriptor,Integer> newtags2=(Hashtable<TagDescriptor,Integer>)tags.clone();
171                 newtags1.put(tag,new Integer(ONETAG));
172                 return new FlagState[] {new FlagState(newset1, cd, newtags2),
173                                         new FlagState(newset2, cd, newtags2)};
174             default:
175                 throw new Error();
176             }
177         } else {
178             throw new Error("Invalid Operation: Can not clear a tag that doesn't exist.");
179         }
180     }
181     
182     /** Creates a string description of the flagstate
183      *  e.g.  a flagstate with five flags could look like 01001
184      *  @param flags an array of flagdescriptors.
185      *  @return string representation of the flagstate.
186      */
187         public String toString(FlagDescriptor[] flags)
188         {
189                 StringBuffer sb = new StringBuffer(flagstate.size());
190                 for(int i=0;i < flags.length; i++)
191                 {
192                         if (get(flags[i]))
193                                 sb.append(1);
194                         else
195                                 sb.append(0);
196                 }
197                         
198                 return new String(sb);
199         }
200
201         /** Accessor method
202          *  @return returns the classdescriptor of the flagstate.
203          */
204          
205     public ClassDescriptor getClassDescriptor(){
206         return cd;
207     }
208
209         /** Sets the status of a specific flag in a flagstate after cloning it.
210          *  @param      fd FlagDescriptor of the flag whose status is being set.
211          *  @param  status boolean value
212          *  @return the new flagstate with <CODE>fd</CODE> set to <CODE>status</CODE>.
213          */
214          
215     public FlagState setFlag(FlagDescriptor fd, boolean status) {
216         HashSet newset=(HashSet) flagstate.clone();
217         Hashtable<TagDescriptor,Integer> newtags=(Hashtable<TagDescriptor,Integer>)tags.clone();
218         if (status)
219             newset.add(fd);
220         else if (newset.contains(fd)){
221             newset.remove(fd);
222         }
223         
224         return new FlagState(newset, cd, newtags);
225     }
226     
227     /** Tests for equality of two flagstate objects.
228     */
229     
230     public boolean equals(Object o) {
231         if (o instanceof FlagState) {
232             FlagState fs=(FlagState)o;
233             if (fs.cd!=cd)
234                 return false;
235             return (fs.flagstate.equals(flagstate) & fs.tags.equals(tags));
236         }
237         return false;
238     }
239
240     public int hashCode() {
241         return cd.hashCode()^flagstate.hashCode()^tags.hashCode();
242     }
243
244     public String getLabel() {
245         return "N"+uid;
246     }
247     
248     
249         
250
251     public String getTextLabel() {
252         String label=null;
253         for(Iterator it=getFlags();it.hasNext();) {
254             FlagDescriptor fd=(FlagDescriptor) it.next();
255             if (label==null)
256                 label=fd.toString();
257             else
258                 label+=", "+fd.toString();
259         }
260         for (Enumeration en_tags=getTags();en_tags.hasMoreElements();){
261                 TagDescriptor td=(TagDescriptor)en_tags.nextElement();
262                 switch (tags.get(td).intValue()){
263                 case ONETAG:
264                     if (label==null)
265                         label=td.toString()+"(1)";
266                     else
267                         label+=", "+td.toString()+"(1)";
268                     break;
269                 case MULTITAGS:
270                     if (label==null)
271                         label=td.toString()+"(n)";
272                     else
273                         label+=", "+td.toString()+"(n)";
274                     break;
275                 default:
276                     break;
277                 }
278         }
279         if (label==null)
280             return " ";
281         return label;
282     }
283     
284     public Enumeration getTags(){
285             return tags.keys();
286     }
287 }