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