1 package Analysis.TaskStateAnalysis;
2 import Analysis.TaskStateAnalysis.*;
8 import java.io.FileWriter;
9 import java.io.FileOutputStream;
12 public class TaskAnalysis {
16 Hashtable extern_flags;
17 Queue<FlagState> toprocess;
24 * @param state a flattened State object
27 public TaskAnalysis(State state)
30 this.typeutil=new TypeUtil(state);
33 /** Builds a table of flags for each class in the Bristlecone program.
34 * It creates two hashtables: one which holds the ClassDescriptors and arrays of
35 * FlagDescriptors as key-value pairs; the other holds the ClassDescriptor and the
36 * number of external flags for that specific class.
39 private void getFlagsfromClasses() {
40 flags=new Hashtable();
41 extern_flags = new Hashtable();
43 /** Iterate through the classes used in the program to build the table of flags
45 for(Iterator it_classes=state.getClassSymbolTable().getDescriptorsIterator();it_classes.hasNext();) {
47 ClassDescriptor cd = (ClassDescriptor)it_classes.next();
48 System.out.println(cd.getSymbol());
49 Vector vFlags=new Vector();
50 FlagDescriptor flag[];
54 /* Adding the flags of the super class */
55 if (cd.getSuper()!=null) {
56 ClassDescriptor superdesc=cd.getSuperDesc();
58 for(Iterator it_cflags=superdesc.getFlags();it_cflags.hasNext();) {
59 FlagDescriptor fd = (FlagDescriptor)it_cflags.next();
60 System.out.println(fd.toString());
65 for(Iterator it_cflags=cd.getFlags();it_cflags.hasNext();) {
66 FlagDescriptor fd = (FlagDescriptor)it_cflags.next();
70 if (vFlags.size()!=0) {
71 flag=new FlagDescriptor[vFlags.size()];
73 for(int i=0;i < vFlags.size() ; i++) {
74 if (((FlagDescriptor)vFlags.get(i)).getExternal()) {
75 flag[ctr]=(FlagDescriptor)vFlags.get(i);
76 vFlags.remove(flag[ctr]);
80 for(int i=0;i < vFlags.size() ; i++) {
81 flag[i+ctr]=(FlagDescriptor)vFlags.get(i);
83 extern_flags.put(cd,new Integer(ctr));
89 /** Method which starts up the analysis
93 public void taskAnalysis() throws java.io.IOException {
94 flagstates=new Hashtable();
95 Hashtable<FlagState,FlagState> sourcenodes;
98 getFlagsfromClasses();
101 toprocess=new LinkedList<FlagState>();
103 for(Iterator it_classes=(Iterator)flags.keys();it_classes.hasNext();) {
104 ClassDescriptor cd=(ClassDescriptor)it_classes.next();
105 externs=((Integer)extern_flags.get(cd)).intValue();
106 FlagDescriptor[] fd=(FlagDescriptor[])flags.get(cd);
109 System.out.println("Inside taskAnalysis;\n Class:"+ cd.getSymbol());
110 System.out.println("No of externs " + externs);
111 System.out.println("No of flags: "+fd.length);
114 flagstates.put(cd,new Hashtable<FlagState,FlagState>());
118 ClassDescriptor startupobject=typeutil.getClass(TypeUtil.StartupClass);
120 sourcenodes=(Hashtable<FlagState,FlagState>)flagstates.get(startupobject);
122 FlagState fsstartup=new FlagState(startupobject);
123 FlagDescriptor[] fd=(FlagDescriptor[])flags.get(startupobject);
125 fsstartup=fsstartup.setFlag(fd[0],true);
127 sourcenodes.put(fsstartup,fsstartup);
128 toprocess.add(fsstartup);
130 /** Looping through the flagstates in the toprocess queue to perform the state analysis */
131 while (!toprocess.isEmpty()) {
132 FlagState trigger=toprocess.poll();
133 createPossibleRuntimeStates(trigger);
135 analyseTasks(trigger);
138 /** Creating DOT files */
139 Enumeration e=flagstates.keys();
141 while (e.hasMoreElements()) {
142 System.out.println("creating dot file");
143 ClassDescriptor cdtemp=(ClassDescriptor)e.nextElement();
144 System.out.println((cdtemp.getSymbol()));
145 createDOTfile(cdtemp);
150 /** Analyses the set of tasks based on the given flagstate, checking
151 * to see which tasks are triggered and what new flagstates are created
152 * from the base flagstate.
153 * @param fs A FlagState object which is used to analyse the task
157 private void analyseTasks(FlagState fs) {
158 ClassDescriptor cd=fs.getClassDescriptor();
159 Hashtable<FlagState,FlagState> sourcenodes=(Hashtable<FlagState,FlagState>)flagstates.get(cd);
161 for(Iterator it_tasks=state.getTaskSymbolTable().getDescriptorsIterator();it_tasks.hasNext();) {
162 TaskDescriptor td = (TaskDescriptor)it_tasks.next();
163 String taskname=td.getSymbol();
166 System.out.println();
167 System.out.println(cd.getSymbol()+" : "+fs.getTextLabel());
168 System.out.println("Task: "+taskname);
173 /** counter to keep track of the number of parameters (of the task being analyzed) that
174 * are satisfied by the flagstate.
177 TempDescriptor temp=null;
178 FlatMethod fm = state.getMethodFlat(td);
180 for(int i=0; i < td.numParameters(); i++) {
181 FlagExpressionNode fen=td.getFlag(td.getParameter(i));
182 TagExpressionList tel=td.getTag(td.getParameter(i));
184 /** Checking to see if the parameter is of the same type/class as the
185 * flagstate's and also if the flagstate fs triggers the given task*/
186 if (typeutil.isSuperorType(td.getParamType(i).getClassDesc(),cd)
187 && isTaskTrigger_flag(fen,fs)
188 && isTaskTrigger_tag(tel,fs)) {
189 temp=fm.getParameter(i);
194 if (trigger_ctr==0) //Look at next task
198 throw new Error("Illegal Operation: A single flagstate cannot satisfy more than one parameter of a task.");
202 System.out.println("Task:" + taskname +" is triggered");
205 //Iterating through the nodes
206 FlatNode fn=fm.methodEntryNode();
208 HashSet tovisit= new HashSet();
209 HashSet visited= new HashSet();
212 while(!tovisit.isEmpty()) {
213 FlatNode fn1 = (FlatNode)tovisit.iterator().next();
216 // Queue all of the next nodes
217 for(int i = 0; i < fn1.numNext(); i++) {
218 FlatNode nn=fn1.getNext(i);
219 if (!visited.contains(nn))
222 if (fn1.kind()==FKind.FlatFlagActionNode) {
223 FlatFlagActionNode ffan=(FlatFlagActionNode)fn1;
224 if (ffan.getTaskType() == FlatFlagActionNode.PRE) {
225 if (ffan.getTempFlagPairs().hasNext()||ffan.getTempTagPairs().hasNext())
226 throw new Error("PRE FlagActions not supported");
227 } else if (ffan.getTaskType() == FlatFlagActionNode.NEWOBJECT) {
229 System.out.println("NEWOBJ");
231 FlagState fsnew=evalNewObjNode(ffan);
232 //Have we seen this node yet
234 if (! ((Hashtable<FlagState,FlagState>)flagstates.get(fsnew.getClassDescriptor())).containsKey(fsnew)) {
235 ((Hashtable<FlagState,FlagState>)flagstates.get(fsnew.getClassDescriptor())).put(fsnew, fsnew);
236 toprocess.add(fsnew);
239 } else if (ffan.getTaskType() == FlatFlagActionNode.TASKEXIT) {
241 System.out.println("TASKEXIT");
244 Vector<FlagState> fsv_taskexit=evalTaskExitNode(ffan,cd,fs,temp);
246 for(Enumeration en=fsv_taskexit.elements();en.hasMoreElements();){
247 FlagState fs_taskexit=(FlagState)en.nextElement();
248 if (!sourcenodes.containsKey(fs_taskexit)) {
249 toprocess.add(fs_taskexit);
252 //seen this node already
253 fs_taskexit=canonicalizeFlagState(sourcenodes,fs_taskexit);
254 FEdge newedge=new FEdge(fs_taskexit,taskname);
255 //FEdge newedge=new FEdge(fs_taskexit,td);
264 /** Determines whether the given flagstate satisfies a
265 * single parameter in the given task.
266 * @param fen FlagExpressionNode
267 * @see FlagExpressionNode
268 * @param fs FlagState
270 * @return <CODE>true</CODE> if fs satisfies the boolean expression
271 denoted by fen else <CODE>false</CODE>.
275 private boolean isTaskTrigger_flag(FlagExpressionNode fen,FlagState fs) {
276 if (fen instanceof FlagNode)
277 return fs.get(((FlagNode)fen).getFlag());
279 switch (((FlagOpNode)fen).getOp().getOp()) {
280 case Operation.LOGIC_AND:
281 return ((isTaskTrigger_flag(((FlagOpNode)fen).getLeft(),fs)) && (isTaskTrigger_flag(((FlagOpNode)fen).getRight(),fs)));
282 case Operation.LOGIC_OR:
283 return ((isTaskTrigger_flag(((FlagOpNode)fen).getLeft(),fs)) || (isTaskTrigger_flag(((FlagOpNode)fen).getRight(),fs)));
284 case Operation.LOGIC_NOT:
285 return !(isTaskTrigger_flag(((FlagOpNode)fen).getLeft(),fs));
291 private boolean isTaskTrigger_tag(TagExpressionList tel, FlagState fs){
294 for (int i=0;i<tel.numTags() ; i++){
295 switch (fs.getTagCount(tel.getType(i))){
296 case FlagState.ONETAG:
297 case FlagState.MULTITAGS:
299 case FlagState.NOTAGS:
307 /*private int tagTypeCount(TagExpressionList tel, String tagtype){
309 for(int i=0;i<tel.numTags() ; i++){
310 if (tel.getType(i).equals(tagtype))
316 /** Evaluates a NewObject Node and returns the newly created
317 * flagstate to add to the process queue.
324 private FlagState evalNewObjNode(FlatNode nn){
326 ClassDescriptor cd_new=((FlatNew)nn.getPrev(0)).getType().getClassDesc();
329 //TempDescriptor[] tdArray = ((FlatFlagActionNode)nn).readsTemps();
331 //if (tdArray.length==0)
334 //Under the safe assumption that all the temps in FFAN.NewObject node are of the same type(class)
335 //ClassDescriptor cd_new=tdArray[0].getType().getClassDesc();
337 FlagState fstemp=new FlagState(cd_new);
339 for(Iterator it_tfp=((FlatFlagActionNode)nn).getTempFlagPairs();it_tfp.hasNext();) {
340 TempFlagPair tfp=(TempFlagPair)it_tfp.next();
341 if (! (tfp.getFlag()==null))// condition checks if the new object was created without any flag setting
343 fstemp=fstemp.setFlag(tfp.getFlag(),((FlatFlagActionNode)nn).getFlagChange(tfp));
349 for(Iterator it_ttp=((FlatFlagActionNode)nn).getTempTagPairs();it_ttp.hasNext();) {
350 TempTagPair ttp=(TempTagPair)it_ttp.next();
351 if (! (ttp.getTag()==null)){
352 fstemp=fstemp.setTag(ttp.getTag());
361 private Vector<FlagState> evalTaskExitNode(FlatNode nn,ClassDescriptor cd,FlagState fs, TempDescriptor temp){
363 //FlagState[] fstemparray=new FlagState[3];
364 Vector<FlagState> inprocess=new Vector<FlagState>();
365 Vector<FlagState> processed=new Vector<FlagState>();
367 for(Iterator it_tfp=((FlatFlagActionNode)nn).getTempFlagPairs();it_tfp.hasNext();) {
368 TempFlagPair tfp=(TempFlagPair)it_tfp.next();
369 if (temp==tfp.getTemp())
370 fstemp=fstemp.setFlag(tfp.getFlag(),((FlatFlagActionNode)nn).getFlagChange(tfp));
373 inprocess.add(fstemp);
374 processed.add(fstemp);
376 for(Iterator it_ttp=((FlatFlagActionNode)nn).getTempTagPairs();it_ttp.hasNext();) {
377 TempTagPair ttp=(TempTagPair)it_ttp.next();
379 if (temp==ttp.getTemp()){
380 processed=new Vector<FlagState>();
381 for (Enumeration en=inprocess.elements();en.hasMoreElements();){
382 FlagState fsworking=(FlagState)en.nextElement();
383 if (((FlatFlagActionNode)nn).getTagChange(ttp)){
384 fsworking=fsworking.setTag(ttp.getTag());
385 processed.add(fsworking);
389 processed.addAll(Arrays.asList(fsworking.clearTag(ttp.getTag())));
400 private FlagState canonicalizeFlagState(Hashtable sourcenodes, FlagState fs){
401 if (sourcenodes.containsKey(fs))
402 return (FlagState)sourcenodes.get(fs);
404 sourcenodes.put(fs,fs);
409 /** Creates a DOT file using the flagstates for a given class
410 * @param cd ClassDescriptor of the class
411 * @throws java.io.IOException
412 * @see ClassDescriptor
415 public void createDOTfile(ClassDescriptor cd) throws java.io.IOException {
416 File dotfile_flagstates= new File("graph"+cd.getSymbol()+".dot");
417 FileOutputStream dotstream=new FileOutputStream(dotfile_flagstates,true);
418 FlagState.DOTVisitor.visit(dotstream,((Hashtable)flagstates.get(cd)).values());
420 File dotfile_tasknodes=new File("graph"+cd.getSymbol()+"_task.dot");
421 dotstream=new FileOutputStream(dotfile_tasknodes,true);
422 TaskNode.DOTVisitor.visit(dotstream,(produceTaskNodes((Hashtable)flagstates.get(cd))).values());
426 private void createPossibleRuntimeStates(FlagState fs) {
427 ClassDescriptor cd = fs.getClassDescriptor();
428 Hashtable<FlagState,FlagState> sourcenodes=(Hashtable<FlagState,FlagState>)flagstates.get(cd);
429 FlagDescriptor[] fd=(FlagDescriptor[])flags.get(cd);
430 int externs=((Integer)extern_flags.get(cd)).intValue();
435 int noOfIterations=(1<<externs) - 1;
436 boolean BoolValTable[]=new boolean[externs];
439 for(int i=0; i < externs ; i++) {
440 BoolValTable[i]=fs.get(fd[i]);
443 for(int k=0; k<noOfIterations; k++) {
444 for(int j=0; j < externs ;j++) {
445 if ((k% (1<<j)) == 0)
446 BoolValTable[j]=(!BoolValTable[j]);
451 for(int i=0; i < externs;i++) {
452 fstemp=fstemp.setFlag(fd[i],BoolValTable[i]);
454 if (!sourcenodes.containsKey(fstemp))
455 toprocess.add(fstemp);
457 fstemp=canonicalizeFlagState(sourcenodes,fstemp);
458 fs.addEdge(new FEdge(fstemp,"Runtime"));
462 private TaskNode canonicalizeTaskNode(Hashtable nodes, TaskNode node){
463 if (nodes.containsKey(node))
464 return (TaskNode)nodes.get(node);
466 nodes.put(node,node);
467 return (TaskNode)node;
471 public Hashtable produceTaskNodes(Hashtable<FlagState,FlagState> fsnodes){
473 Hashtable<TaskNode,TaskNode> tasknodes=new Hashtable<TaskNode,TaskNode>();
474 for(Enumeration en=fsnodes.keys();en.hasMoreElements();){
475 FlagState fs=(FlagState)en.nextElement();
477 Iterator it_inedges=fs.inedges();
480 if (!fs.inedges().hasNext()){
481 tn=new TaskNode("Start Node");
483 FEdge inedge=(FEdge)it_inedges.next();
484 tn=new TaskNode(inedge.getLabel());
486 if(fs.edges().hasNext()){
487 tn=(TaskNode)canonicalizeTaskNode(tasknodes, tn);
488 for (Iterator it_edges=fs.edges();it_edges.hasNext();){
489 TaskNode target=new TaskNode(((FEdge)it_edges.next()).getLabel());
490 target=(TaskNode)canonicalizeTaskNode(tasknodes,target);
491 tn.addEdge(new TEdge(target));
494 }while(it_inedges.hasNext());