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