Changes for William's Analysis
[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 FlagState setTag(TagDescriptor tag){
119            
120             HashSet newset=(HashSet)flagstate.clone();
121             Hashtable<TagDescriptor,Integer> newtags=(Hashtable<TagDescriptor,Integer>)tags.clone();
122             
123             if (newtags.containsKey(tag)){
124                    switch (newtags.get(tag).intValue()){
125                            case ONETAG:
126                                         newtags.put(tag,new Integer(MULTITAGS));
127                                         break;
128                            case MULTITAGS:
129                                         newtags.put(tag,new Integer(MULTITAGS));
130                                         break;
131                         }
132                 }
133                 else{
134                         newtags.put(tag,new Integer(ONETAG));
135                 }
136                 
137                 return new FlagState(newset,cd,newtags);
138                                 
139     }
140
141     public int getTagCount(String tagtype){
142                 for (Enumeration en=getTags();en.hasMoreElements();){
143                         TagDescriptor td=(TagDescriptor)en.nextElement();
144                         if (tagtype.equals(td.getSymbol()))
145                                 return tags.get(td).intValue();   //returns either ONETAG or MULTITAG
146                 }
147                 return NOTAGS;
148                 
149     }
150     
151     public FlagState[] clearTag(TagDescriptor tag){
152             FlagState[] retstates;
153             
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                         retstates=new FlagState[]{new FlagState(newset,cd,newtags)};
161                         return retstates;
162                         
163                     case MULTITAGS:
164                         //when tagcount is more than 2, COUNT stays at MULTITAGS
165                         retstates=new FlagState[2];
166                         HashSet newset1=(HashSet)flagstate.clone();
167                         Hashtable<TagDescriptor,Integer> newtags1=(Hashtable<TagDescriptor,Integer>)tags.clone();
168                         retstates[1]=new FlagState(newset1,cd,newtags1);
169                         //when tagcount is 2, COUNT changes to ONETAG
170                         HashSet newset2=(HashSet)flagstate.clone();
171                         Hashtable<TagDescriptor,Integer> newtags2=(Hashtable<TagDescriptor,Integer>)tags.clone();
172                         newtags1.put(tag,new Integer(ONETAG));
173                         retstates[1]=new FlagState(newset2,cd,newtags2);
174                         return retstates;
175                 default:
176                         return null;                    
177         }
178                 }else{
179                         throw new Error("Invalid Operation: Can not clear a tag that doesn't exist.");
180                         
181                 }
182                 
183     }
184     
185     /** Creates a string description of the flagstate
186      *  e.g.  a flagstate with five flags could look like 01001
187      *  @param flags an array of flagdescriptors.
188      *  @return string representation of the flagstate.
189      */
190         public String toString(FlagDescriptor[] flags)
191         {
192                 StringBuffer sb = new StringBuffer(flagstate.size());
193                 for(int i=0;i < flags.length; i++)
194                 {
195                         if (get(flags[i]))
196                                 sb.append(1);
197                         else
198                                 sb.append(0);
199                 }
200                         
201                 return new String(sb);
202         }
203
204         /** Accessor method
205          *  @return returns the classdescriptor of the flagstate.
206          */
207          
208     public ClassDescriptor getClassDescriptor(){
209         return cd;
210     }
211
212         /** Sets the status of a specific flag in a flagstate after cloning it.
213          *  @param      fd FlagDescriptor of the flag whose status is being set.
214          *  @param  status boolean value
215          *  @return the new flagstate with <CODE>fd</CODE> set to <CODE>status</CODE>.
216          */
217          
218     public FlagState setFlag(FlagDescriptor fd, boolean status) {
219         HashSet newset=(HashSet) flagstate.clone();
220         Hashtable<TagDescriptor,Integer> newtags=(Hashtable<TagDescriptor,Integer>)tags.clone();
221         if (status)
222             newset.add(fd);
223         else if (newset.contains(fd)){
224             newset.remove(fd);
225         }
226         
227         return new FlagState(newset, cd,newtags);
228     }
229     
230     /** Tests for equality of two flagstate objects.
231     */
232     
233     public boolean equals(Object o) {
234         if (o instanceof FlagState) {
235             FlagState fs=(FlagState)o;
236             if (fs.cd!=cd)
237                 return false;
238             return (fs.flagstate.equals(flagstate) & fs.tags.equals(tags));
239         }
240         return false;
241     }
242
243     public int hashCode() {
244         return cd.hashCode()^flagstate.hashCode()^tags.hashCode();
245     }
246
247     public String getLabel() {
248         return "N"+uid;
249     }
250     
251     
252         
253
254     public String getTextLabel() {
255         String label=null;
256         for(Iterator it=getFlags();it.hasNext();) {
257             FlagDescriptor fd=(FlagDescriptor) it.next();
258             if (label==null)
259                 label=fd.toString();
260             else
261                 label+=", "+fd.toString();
262         }
263         for (Enumeration en_tags=getTags();en_tags.hasMoreElements();){
264                 TagDescriptor td=(TagDescriptor)en_tags.nextElement();
265                 switch (tags.get(td).intValue()){
266                 case ONETAG:
267                     if (label==null)
268                         label=td.toString()+"(1)";
269                     else
270                         label+=", "+td.toString()+"(1)";
271                     break;
272                 case MULTITAGS:
273                     if (label==null)
274                         label=td.toString()+"(n)";
275                     else
276                         label+=", "+td.toString()+"(n)";
277                     break;
278                 default:
279                     break;
280                 }
281         }
282         if (label==null)
283             return " ";
284         return label;
285     }
286     
287     public Enumeration getTags(){
288             return tags.keys();
289     }
290 }