start of new file
[IRC.git] / Robust / src / Analysis / TaskStateAnalysis / TaskTagAnalysis.java
index f8e2e54b4a3a850cca98fba2a7d520097407cf61..a3b63820a64a899622d0ee5c1e09d356b619f8cc 100644 (file)
@@ -13,8 +13,11 @@ public class TaskTagAnalysis {
     TypeUtil typeutil;
     FlagInfo flaginfo;
     HashSet<TagState> toprocess;
+    HashSet<TagState> discovered;
     Hashtable<TaskDescriptor, TaskQueue> tasktable;
-    
+    Hashtable<TagDescriptor, Set<TagState>> tsresults;
+    Hashtable<ClassDescriptor, Set<TagState>> fsresults;
+
 
     /** 
      * Class Constructor
@@ -26,11 +29,39 @@ public class TaskTagAnalysis {
        this.taganalysis=taganalysis;
        this.flaginfo=new FlagInfo(state);
        this.toprocess=new HashSet<TagState>();
+       this.discovered=new HashSet<TagState>();
        this.tasktable=new Hashtable<TaskDescriptor, TaskQueue>();
+       this.tsresults=new Hashtable<TagDescriptor, Set<TagState>>();
+       this.fsresults=new Hashtable<ClassDescriptor, Set<TagState>>();
+       
+
        for(Iterator taskit=state.getTaskSymbolTable().getDescriptorsIterator();taskit.hasNext();) {
            TaskDescriptor td=(TaskDescriptor)taskit.next();
            tasktable.put(td, new TaskQueue(td));
        }
+       doAnalysis();
+       doOutput();
+    }
+
+    private void doOutput() {
+       try {
+       for(Iterator<TagDescriptor> tagit=tsresults.keySet().iterator();tagit.hasNext();) {
+           TagDescriptor tag=tagit.next();
+           Set<TagState> set=tsresults.get(tag);
+           File dotfile_flagstates= new File("tag"+tag.getSymbol()+".dot");
+           FileOutputStream dotstream=new FileOutputStream(dotfile_flagstates,false);
+           TagState.DOTVisitor.visit(dotstream,set);
+       }
+       for(Iterator<ClassDescriptor> cdit=fsresults.keySet().iterator();cdit.hasNext();) {
+           ClassDescriptor cd=cdit.next();
+           Set<TagState> set=fsresults.get(cd);
+           File dotfile_flagstates= new File("class"+cd.getSymbol()+".dot");
+           FileOutputStream dotstream=new FileOutputStream(dotfile_flagstates,false);
+           TagState.DOTVisitor.visit(dotstream,set);
+       }
+       } catch (Exception e) {
+           e.printStackTrace();
+       }
     }
 
     private void doAnalysis() {
@@ -53,9 +84,12 @@ public class TaskTagAnalysis {
            FlagState fs=fsit.next();
            FlagTagState fts=new FlagTagState(ts, fs);
            for(int i=0;i<td.numParameters();i++) {
+               System.out.println("Trying to enqueue "+td);
                if (canEnqueue(td, i, fs)) {
+                   System.out.println("Enqueued");
                    TaskQueueIterator tqi=tq.enqueue(i, fts);
                    while(tqi.hasNext()) {
+                       System.out.println("binding");
                        processBinding(tqi);
                        tqi.next();
                    }
@@ -97,8 +131,8 @@ public class TaskTagAnalysis {
                        }
                    }
                } else {
-                   TagWrapper clonetag=prevtag.clone();
-                   tagtable.put(prevtag, clonetag);
+                   TagWrapper clonetag=((TagWrapper)prevtag).clone();
+                   tagtable.put((TagWrapper)prevtag, clonetag);
                    table.put(tmp, clonetag);
                }
            }
@@ -110,58 +144,373 @@ public class TaskTagAnalysis {
                if (obj instanceof TagWrapper)
                    continue;
                ObjWrapper prevobj=(ObjWrapper)obj;
-               if (table.containsKey(tmp)) {
+               if (!table.containsKey(tmp)) {
                    //merge tag states
-                   ObjWrapper newobj=new ObjWrapper(prevobj.fs);
+                   ObjWrapper newobj=new ObjWrapper();
+                   newobj.initfs=prevobj.initfs;
                    table.put(tmp, newobj);
                }
                ObjWrapper currobj=(ObjWrapper) table.get(tmp);
-               for(int j=0;j<prevobj.tags.size();j++) {
-                   TagWrapper t=tagtable.get(prevobj.tags.get(j));
-                   if (!currobj.tags.contains(t))
-                       currobj.tags.add(t);
+               assert(currobj.initfs.equals(prevobj.initfs));
+               for(Iterator<TagWrapper> tagit=prevobj.tags.iterator();tagit.hasNext();) {
+                   TagWrapper tprev=tagit.next();
+                   TagWrapper t=tagtable.get(tprev);
+                   currobj.tags.add(t);
+               }
+               for(Iterator<FlagState> flagit=prevobj.fs.iterator();flagit.hasNext();) {
+                   FlagState fs=flagit.next();
+                   currobj.fs.add(fs);
                }
            }
        }
        return table;
     }
 
-    private void processFlatFlag(FlatFlagActionNode fn, Hashtable<TempDescriptor, TagState> table) {
+    private void processFlatFlag(FlatFlagActionNode fn, Hashtable<TempDescriptor, Wrapper> table, TaskDescriptor td) {
+       if (fn.getTaskType()==FlatFlagActionNode.PRE) {
+           throw new Error("Unsupported");
+       } else if (fn.getTaskType()==FlatFlagActionNode.TASKEXIT) {
+           evalTaskExitNode(fn, table);
+       } else if (fn.getTaskType()==FlatFlagActionNode.NEWOBJECT) {
+           evalNewNode(fn, table, td);
+       }
+    }
+
+    private void setFlag(ObjWrapper ow, FlagDescriptor fd, boolean value) {
+       HashSet<FlagState> newstate=new HashSet<FlagState>();
+       Hashtable<FlagState, FlagState> flagmap=new Hashtable<FlagState, FlagState>();
+       for(Iterator<FlagState> flagit=ow.fs.iterator();flagit.hasNext();) {
+           FlagState fs=flagit.next();
+           FlagState fsnew=canonical(fs.setFlag(fd, value));
+           newstate.add(fsnew);
+           flagmap.put(fs, fsnew);
+       }
        
+       for(Iterator<TagWrapper> tagit=ow.tags.iterator();tagit.hasNext();) {
+           TagWrapper tw=tagit.next();
+           HashSet<TagState> newstates=new HashSet<TagState>();
+           for(Iterator<TagState> tgit=tw.ts.iterator();tgit.hasNext();) {
+               TagState ts=tgit.next();
+               for(Iterator<FlagState> flagit=ts.getFS().iterator();flagit.hasNext();) {
+                   FlagState fs=flagit.next();
+                   if (flagmap.containsKey(fs)) {
+                       if (flagmap.get(fs).equals(fs)) {
+                           newstates.add(ts);
+                       } else {
+                           TagState tsarray[]=ts.clearFS(fs);
+                           //Can do strong update here because these
+                           //must be parameter objects...therefore
+                           //all possible aliasing relationships are
+                           //explored
+                           for(int i=0;i<tsarray.length;i++) {
+                               TagState ts2=canonical(tsarray[i]);
+                               TagState tsarray2[]=ts2.addnewFS(flagmap.get(fs));
+                               for(int j=0;j<tsarray2.length;j++)
+                                   newstates.add(canonical(tsarray2[j]));
+                           }
+                       }
+                   }
+               }
+           }
+           tw.ts=newstates;
+       }
     }
 
-    private void processFlatCall(FlatCall fc, Hashtable<TempDescriptor, TagState> table) {
-       //Do nothing for now
+    private void setTag(ObjWrapper ow, TagWrapper twnew, TagDescriptor tag, boolean value) {
+       if (value) {
+           if (ow.tags.contains(twnew)) {
+               System.out.println("Tag already bound to object.");
+               return;
+           }
+       } else {
+           if (!ow.tags.contains(twnew)) {
+               System.out.println("Tag not bound to object.");
+               return;
+           }
+       }
+       HashSet<FlagState> newfsstates=new HashSet<FlagState>();
+       Hashtable<FlagState, FlagState[]> flagmap=new Hashtable<FlagState, FlagState[]>();
+       //Change the flag states
+       for(Iterator<FlagState> fsit=ow.fs.iterator();fsit.hasNext();) {
+           FlagState fs=fsit.next();
+           FlagState[] fsnew=canonical(fs.setTag(tag, value));
+           flagmap.put(fs, fsnew);
+           newfsstates.addAll(Arrays.asList(fsnew));
+       }
+       for(Iterator<TagWrapper> tagit=ow.tags.iterator();tagit.hasNext();) {
+           TagWrapper tw=tagit.next();
+           HashSet<TagState> newstates=new HashSet<TagState>();
+           for(Iterator<TagState> tgit=tw.ts.iterator();tgit.hasNext();) {
+               TagState ts=tgit.next();
+               for(Iterator<FlagState> flagit=ts.getFS().iterator();flagit.hasNext();) {
+                   FlagState fs=flagit.next();
+                   if (flagmap.containsKey(fs)) {
+                       FlagState[] fmap=flagmap.get(fs);
+                       for(int i=0;i<fmap.length;i++) {
+                           FlagState fsnew=fmap[i];
+                           if (fsnew.equals(fs)) {
+                               newstates.add(ts);
+                           } else {
+                               TagState tsarray[]=ts.clearFS(fs);
+                               //Can do strong update here because
+                               //these must be parameter
+                               //objects...therefore all possible
+                               //aliasing relationships are explored
+                               for(int j=0;j<tsarray.length;j++) {
+                                   TagState ts2=canonical(tsarray[j]);
+                                   TagState tsarray2[]=ts2.addnewFS(fsnew);
+                                   for(int k=0;k<tsarray2.length;k++)
+                                       newstates.add(canonical(tsarray2[k]));
+                               }
+                           }
+                       }
+                   }
+               }
+           }
+           tw.ts=newstates;
+       }
+       
+       {
+           HashSet<TagState> newstates=new HashSet<TagState>();
+           for(Iterator<TagState> tgit=twnew.ts.iterator();tgit.hasNext();) {
+               TagState ts=tgit.next();
+               for(Iterator<FlagState> flagit=newfsstates.iterator();flagit.hasNext();) {
+                   FlagState fsnew=flagit.next();
+                   //Can do strong update here because these must
+                   //be parameter objects...therefore all
+                   //possible aliasing relationships are explored
+                   TagState tsarray2[];
+                   if (value) 
+                       tsarray2=ts.addnewFS(fsnew);
+                   else 
+                       tsarray2=ts.clearFS(fsnew);
+                   for(int j=0;j<tsarray2.length;j++)
+                       newstates.add(canonical(tsarray2[j]));
+               }
+           }
+           twnew.ts=newstates;
+       }
+       
+       if (value)
+           ow.tags.add(twnew);
+       else
+           ow.tags.remove(twnew);
+       ow.fs=newfsstates;
     }
 
-    private void processFlatReturnNode(FlatReturnNode fr, Hashtable<TempDescriptor, TagState> table) {
+    private void evalTaskExitNode(FlatFlagActionNode fn, Hashtable<TempDescriptor, Wrapper> table) {
+       //Process clears first
+       for(Iterator<TempTagPair> it_ttp=fn.getTempTagPairs();it_ttp.hasNext();) {
+           TempTagPair ttp=it_ttp.next();
+           TempDescriptor tmp=ttp.getTemp();
+           TagDescriptor tag=ttp.getTag();
+           TempDescriptor tagtmp=ttp.getTagTemp();
+           TagWrapper tagw=(TagWrapper)table.get(tagtmp);
+           boolean newtagstate=fn.getTagChange(ttp);
+           ObjWrapper ow=(ObjWrapper)table.get(tmp);
+           if (!newtagstate)
+               setTag(ow, tagw, tag, newtagstate);
+       }
+
+       //Do the flags next
+       for(Iterator<TempFlagPair> it_tfp=fn.getTempFlagPairs();it_tfp.hasNext();) {
+           TempFlagPair tfp=it_tfp.next();
+           TempDescriptor tmp=tfp.getTemp();
+           FlagDescriptor fd=tfp.getFlag();
+           boolean newflagstate=fn.getFlagChange(tfp);
+           ObjWrapper ow=(ObjWrapper)table.get(tmp);
+           setFlag(ow, fd, newflagstate);
+       }
 
+       //Process sets last
+       for(Iterator it_ttp=fn.getTempTagPairs();it_ttp.hasNext();) {
+           TempTagPair ttp=(TempTagPair)it_ttp.next();
+           TempDescriptor tmp=ttp.getTemp();
+           TagDescriptor tag=ttp.getTag();
+           TempDescriptor tagtmp=ttp.getTagTemp();
+           TagWrapper tagw=(TagWrapper)table.get(tagtmp);
+           boolean newtagstate=fn.getTagChange(ttp);
+           ObjWrapper ow=(ObjWrapper)table.get(tmp);
+           if (newtagstate)
+               setTag(ow, tagw, tag, newtagstate);
+       }
+    }
+
+    private void evalNewNode(FlatFlagActionNode fn, Hashtable<TempDescriptor, Wrapper> table, TaskDescriptor td) {
+       TempDescriptor fntemp=null;
+       {
+           /* Compute type */
+           Iterator it=fn.getTempFlagPairs();
+           if (it.hasNext()) {
+               TempFlagPair tfp=(TempFlagPair)it.next();
+               fntemp=tfp.getTemp();
+           } else {
+               it=fn.getTempTagPairs();
+               if (!it.hasNext())
+                   throw new Error();
+               TempTagPair ttp=(TempTagPair)it.next();
+               fntemp=ttp.getTemp();
+           }
+       }
+       FlagState fs=canonical(new FlagState(fntemp.getType().getClassDesc()));
+       ObjWrapper ow=new ObjWrapper();
+       ow.fs.add(fs);
+       table.put(fntemp, ow);
+       //Do the flags first
+       for(Iterator<TempFlagPair> it_tfp=fn.getTempFlagPairs();it_tfp.hasNext();) {
+           TempFlagPair tfp=it_tfp.next();
+           TempDescriptor tmp=tfp.getTemp();
+           FlagDescriptor fd=tfp.getFlag();
+           boolean newflagstate=fn.getFlagChange(tfp);
+           assert(ow==table.get(tmp));
+           setFlag(ow, fd, newflagstate);
+       }
+       //Process sets next
+       for(Iterator it_ttp=fn.getTempTagPairs();it_ttp.hasNext();) {
+           TempTagPair ttp=(TempTagPair)it_ttp.next();
+           TempDescriptor tmp=ttp.getTemp();
+           TagDescriptor tag=ttp.getTag();
+           TempDescriptor tagtmp=ttp.getTagTemp();
+           TagWrapper tagw=(TagWrapper)table.get(tagtmp);
+           boolean newtagstate=fn.getTagChange(ttp);
+           assert(ow==table.get(tmp));
+           if (newtagstate)
+               setTag(ow, tagw, tag, newtagstate);
+           else
+               throw new Error("Can't clear tag in newly allocated object");
+       }
+       for(Iterator<FlagState> fsit=ow.fs.iterator();fsit.hasNext();) {
+           FlagState fs2=fsit.next();
+           fs2.addAllocatingTask(td);
+           TagState ts2=new TagState(fs2.getClassDescriptor());
+           ts2.addFS(fs2);
+           ts2=canonical(ts2);
+           ts2.addSource(td);
+           addresult(fs2.getClassDescriptor(), ts2);
+           if (!discovered.contains(ts2)) {
+               discovered.add(ts2);
+               toprocess.add(ts2);
+           }
+       }
+    }
+
+    private void processFlatTag(FlatTagDeclaration fn, Hashtable<TempDescriptor, Wrapper> table, TaskDescriptor td) {
+       TempDescriptor tmp=fn.getDst();
+       if (table.containsKey(tmp)) {
+           recordtagchange((TagWrapper)table.get(tmp), td);
+       }
+       TagDescriptor tag=fn.getType();
+       TagState ts=canonical(new TagState(tag));
+       TagWrapper tw=new TagWrapper(ts);
+       tw.initts=null;
+       table.put(tmp, tw);
+    }
+
+    private void addresult(TagDescriptor td, TagState ts) {
+       if (!tsresults.containsKey(td))
+           tsresults.put(td, new HashSet<TagState>());
+       tsresults.get(td).add(ts);
+    }
+
+    private void addresult(ClassDescriptor cd, TagState ts) {
+       if (!fsresults.containsKey(cd))
+           fsresults.put(cd, new HashSet<TagState>());
+       fsresults.get(cd).add(ts);
+    }
+
+    public void recordtagchange(TagWrapper tw, TaskDescriptor td) {
+       TagState init=tw.initts;
+       for(Iterator<TagState> tsit=tw.ts.iterator(); tsit.hasNext();) {
+           TagState ts=tsit.next();
+           if (init==null) {
+               ts.addSource(td);
+           } else {
+               TagEdge te=new TagEdge(ts, td);
+               if (!init.containsEdge(te)) {
+                   init.addEdge(te);
+               }
+           }
+           if (ts.getTag()!=null)
+               addresult(ts.getTag(), ts);
+           else
+               addresult(ts.getClassDesc(), ts);
+           if (!discovered.contains(ts)) {
+               discovered.add(ts);
+               toprocess.add(ts);
+           }
+       }
+    }
+
+    private void recordobj(ObjWrapper ow, TaskDescriptor td) {
+       for(Iterator<TagWrapper> twit=ow.tags.iterator();twit.hasNext();) {
+           TagWrapper tw=twit.next();
+           recordtagchange(tw, td);
+       }
+    }
+
+    private void processFlatCall(FlatCall fc, Hashtable<TempDescriptor, Wrapper> table) {
+       //Do nothing for now
+    }
+    
+    private void processFlatReturnNode(FlatReturnNode fr, Hashtable<TempDescriptor, Wrapper> table, TaskDescriptor td) {
+       for(Iterator<TempDescriptor> tmpit=table.keySet().iterator();tmpit.hasNext();) {
+           TempDescriptor tmp=tmpit.next();
+           Wrapper w=table.get(tmp);
+           if (w instanceof TagWrapper) {
+               TagWrapper tw=(TagWrapper)w;
+               recordtagchange(tw, td);
+           } else {
+               ObjWrapper ow=(ObjWrapper)w;
+               recordobj(ow, td);
+           }
+       }
     }
 
     private boolean equivalent(Hashtable<TempDescriptor, Wrapper> table1, Hashtable<TempDescriptor, Wrapper> table2) {
-       Hashtable<Wrapper, Wrapper> emap=new Hashtable<Wrapper, Wrapper>;
+       Hashtable<Wrapper, Wrapper> emap=new Hashtable<Wrapper, Wrapper>();
+
+       if (table1.keySet().size()!=table2.keySet().size())
+           return false;
+
        for(Iterator<TempDescriptor> tmpit=table1.keySet().iterator();tmpit.hasNext();) {
            TempDescriptor tmp=tmpit.next();
            if (table2.containsKey(tmp)) {
                emap.put(table1.get(tmp), table2.get(tmp));
            } else return false;
        }
-       for(Iterator<TempDescriptor> tmpit=table2.keySet().iterator();tmpit.hasNext();) {
+       
+       for(Iterator<TempDescriptor> tmpit=table1.keySet().iterator();tmpit.hasNext();) {
            TempDescriptor tmp=tmpit.next();
-           if (table1.containsKey(tmp)) {
-               emap.put(table1.get(tmp), table2.get(tmp));
-           } else return false;
+           Wrapper w1=table1.get(tmp);
+           Wrapper w2=table2.get(tmp);
+           if (w1 instanceof TagWrapper) {
+               TagWrapper t1=(TagWrapper)w1;
+               TagWrapper t2=(TagWrapper)w2;
+               if (!t1.ts.equals(t2.ts))
+                   return false;
+               
+           } else {
+               ObjWrapper t1=(ObjWrapper)w1;
+               ObjWrapper t2=(ObjWrapper)w2;
+               if (!t1.fs.equals(t2.fs))
+                   return false;
+               if (t1.tags.size()!=t2.tags.size())
+                   return false;
+               for(Iterator<TagWrapper> twit=t1.tags.iterator();twit.hasNext();) {
+                   TagWrapper tw1=twit.next();
+                   if (!t2.tags.contains(emap.get(tw1)))
+                       return false;
+               }
+           }
        }
-       
-       for
-       
+       return true;
     }
 
     private void doAnalysis(TaskBinding tb) {
        TaskDescriptor td=tb.tqi.tq.getTask();
        FlatMethod fm=state.getMethodFlat(td);
        Hashtable<FlatNode, Hashtable<TempDescriptor, Wrapper>> wtable=new Hashtable<FlatNode, Hashtable<TempDescriptor, Wrapper>>();
-       wtable.put(fm, buildinittable(tb));
+       wtable.put(fm, buildinittable(tb, fm));
        HashSet<FlatNode> visited=new HashSet<FlatNode>();
        HashSet<FlatNode> tovisit=new HashSet<FlatNode>();
        tovisit.add(fm.getNext(0));
@@ -172,13 +521,16 @@ public class TaskTagAnalysis {
            Hashtable<TempDescriptor, Wrapper> table=computeInitialState(wtable, fn);
            switch(fn.kind()) {
            case FKind.FlatFlagActionNode:
-               processFlatFlag((FlatFlagActionNode)fn, table);
+               processFlatFlag((FlatFlagActionNode)fn, table, td);
+               break;
+           case FKind.FlatTagDeclaration:
+               processFlatTag((FlatTagDeclaration)fn, table, td);
                break;
            case FKind.FlatCall:
                processFlatCall((FlatCall)fn, table);
                break;
            case FKind.FlatReturnNode:
-               processFlatReturnNode((FlatReturn)fn, table);
+               processFlatReturnNode((FlatReturnNode)fn, table, td);
                break;
            default:
            }
@@ -265,11 +617,18 @@ public class TaskTagAnalysis {
        FlagState fsstartup=(new FlagState(startupobject)).setFlag(fd,true);
        fsstartup.setAsSourceNode();
        fsstartup=canonical(fsstartup);
-       TagState ts=new TagState();
+       TagState ts=new TagState(startupobject);
        TagState[] tsarray=ts.addFS(fsstartup);
        return canonical(tsarray[0]);
     }
 
+    FlagState[] canonical(FlagState[] fs) {
+       FlagState[] fsarray=new FlagState[fs.length];
+       for(int i=0;i<fs.length;i++)
+           fsarray[i]=canonical(fs[i]);
+       return fsarray;
+    }
+
     FlagState canonical(FlagState fs) {
        return fs;
     }