set up OoOJava analysis.
authoryeom <yeom>
Tue, 22 Jun 2010 20:46:56 +0000 (20:46 +0000)
committeryeom <yeom>
Tue, 22 Jun 2010 20:46:56 +0000 (20:46 +0000)
Robust/src/Analysis/Disjoint/DisjointAnalysis.java
Robust/src/Analysis/OoOJava/CodePlan.java [new file with mode: 0644]
Robust/src/Analysis/OoOJava/OoOJavaAnalysis.java
Robust/src/Analysis/OoOJava/SVKey.java [new file with mode: 0644]
Robust/src/Analysis/OoOJava/VSTWrapper.java [new file with mode: 0644]
Robust/src/Analysis/OoOJava/VarSrcTokTable.java [new file with mode: 0644]
Robust/src/Analysis/OoOJava/VariableSourceToken.java [new file with mode: 0644]
Robust/src/Main/Main.java

index f150279f165ae1ff9e45de62e121fd0f59bc53f4..f40261fa6a2bc632fe27e349ad92f1e77d52aa13 100644 (file)
@@ -2172,6 +2172,9 @@ getFlaggedAllocationSitesReachableFromTaskPRIVATE(TaskDescriptor td) {
   return asSetTotal;
 }
 
+  public Set<Descriptor> getDescriptorsToAnalyze() {
+    return descriptorsToAnalyze;
+  }
 
   
   
diff --git a/Robust/src/Analysis/OoOJava/CodePlan.java b/Robust/src/Analysis/OoOJava/CodePlan.java
new file mode 100644 (file)
index 0000000..efb82ca
--- /dev/null
@@ -0,0 +1,108 @@
+package Analysis.OoOJava;
+
+import IR.*;
+import IR.Flat.*;
+import java.util.*;
+import java.io.*;
+
+
+// a code plan contains information based on analysis results
+// for injecting code before and/or after a flat node
+public class CodePlan {
+    
+  private Hashtable< VariableSourceToken, Set<TempDescriptor> > stall2copySet;
+  private Set<TempDescriptor>                                   dynamicStallSet;
+  private Hashtable<TempDescriptor, TempDescriptor>             dynAssign_lhs2rhs;
+  private Set<TempDescriptor>                                   dynAssign_lhs2curr;
+  private FlatSESEEnterNode                                     currentSESE;
+  
+  public CodePlan( FlatSESEEnterNode fsen ) {
+    stall2copySet      = new Hashtable< VariableSourceToken, Set<TempDescriptor> >();
+    dynamicStallSet    = new HashSet<TempDescriptor>();
+    dynAssign_lhs2rhs  = new Hashtable<TempDescriptor, TempDescriptor>();
+    dynAssign_lhs2curr = new HashSet<TempDescriptor>();
+    currentSESE        = fsen;
+  }
+
+  public FlatSESEEnterNode getCurrentSESE() {
+    return currentSESE;
+  }
+  
+  public void addStall2CopySet( VariableSourceToken stallToken,
+                               Set<TempDescriptor> copySet ) {
+
+    if( stall2copySet.containsKey( stallToken ) ) {
+      Set<TempDescriptor> priorCopySet = stall2copySet.get( stallToken );
+      priorCopySet.addAll( copySet );
+    } else {
+      stall2copySet.put( stallToken, copySet );
+    }
+  }
+
+  public Set<VariableSourceToken> getStallTokens() {
+    return stall2copySet.keySet();
+  }
+
+  public Set<TempDescriptor> getCopySet( VariableSourceToken stallToken ) {
+    return stall2copySet.get( stallToken );
+  }
+
+
+  public void addDynamicStall( TempDescriptor var ) {
+    dynamicStallSet.add( var );
+  }
+
+  public Set<TempDescriptor> getDynamicStallSet() {
+    return dynamicStallSet;
+  }
+
+  public void addDynAssign( TempDescriptor lhs,
+                           TempDescriptor rhs ) {
+    dynAssign_lhs2rhs.put( lhs, rhs );
+  }
+
+  public Hashtable<TempDescriptor, TempDescriptor> getDynAssigns() {
+    return dynAssign_lhs2rhs;
+  }
+
+  public void addDynAssign( TempDescriptor lhs ) {
+    dynAssign_lhs2curr.add( lhs );
+  }
+
+  public Set<TempDescriptor> getDynAssignCurr() {
+    return dynAssign_lhs2curr;
+  }
+
+  public String toString() {
+    String s = " PLAN: ";
+
+    if( !stall2copySet.entrySet().isEmpty() ) {
+      s += "[STATIC STALLS:";
+    }
+    Iterator cpsItr = stall2copySet.entrySet().iterator();
+    while( cpsItr.hasNext() ) {
+      Map.Entry           me         = (Map.Entry)           cpsItr.next();
+      VariableSourceToken stallToken = (VariableSourceToken) me.getKey();
+      Set<TempDescriptor> copySet    = (Set<TempDescriptor>) me.getValue();
+
+      s += "("+stallToken+"->"+copySet+")";
+    }
+    if( !stall2copySet.entrySet().isEmpty() ) {
+      s += "]";
+    }
+
+    if( !dynamicStallSet.isEmpty() ) {
+      s += "[DYN STALLS:"+dynamicStallSet+"]";
+    }
+
+    if( !dynAssign_lhs2rhs.isEmpty() ) {
+      s += "[DYN ASSIGNS:"+dynAssign_lhs2rhs+"]";
+    }
+
+    if( !dynAssign_lhs2curr.isEmpty() ) {
+      s += "[DYN ASS2CURR:"+dynAssign_lhs2curr+"]";
+    }
+
+    return s;
+  }
+}
index 95941e6e9bc161d9dc418dbb1027af1f81263e3a..ee4cff96b9f9f25e95664aa03d51c0b719bee4a4 100644 (file)
 package Analysis.OoOJava;
 
-import java.io.BufferedWriter;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.StringWriter;
-import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.Map;
 import java.util.Set;
 import java.util.Stack;
-import java.util.Map.Entry;
-import Analysis.Liveness;
+
 import Analysis.ArrayReferencees;
+import Analysis.Liveness;
 import Analysis.CallGraph.CallGraph;
+import Analysis.Disjoint.DisjointAnalysis;
+import Analysis.OwnershipAnalysis.AllocationSite;
+import Analysis.OwnershipAnalysis.MethodContext;
 import IR.Descriptor;
-import IR.FieldDescriptor;
-import IR.MethodDescriptor;
 import IR.Operation;
 import IR.State;
-import IR.TypeDescriptor;
 import IR.TypeUtil;
 import IR.Flat.FKind;
-import IR.Flat.FlatCall;
-import IR.Flat.FlatCondBranch;
 import IR.Flat.FlatEdge;
-import IR.Flat.FlatElementNode;
-import IR.Flat.FlatFieldNode;
 import IR.Flat.FlatMethod;
-import IR.Flat.FlatNew;
 import IR.Flat.FlatNode;
 import IR.Flat.FlatOpNode;
 import IR.Flat.FlatReturnNode;
 import IR.Flat.FlatSESEEnterNode;
 import IR.Flat.FlatSESEExitNode;
-import IR.Flat.FlatSetElementNode;
-import IR.Flat.FlatSetFieldNode;
 import IR.Flat.FlatWriteDynamicVarNode;
 import IR.Flat.TempDescriptor;
 
-
 public class OoOJavaAnalysis {
 
   // data from the compiler
-  private State             state;
-  private TypeUtil          typeUtil;
-  private CallGraph         callGraph;
+  private State state;
+  private TypeUtil typeUtil;
+  private CallGraph callGraph;
+  private DisjointAnalysis disjointAnalysis;
+
+  // an implicit SESE is automatically spliced into
+  // the IR graph around the C main before this analysis--it
+  // is nothing special except that we can make assumptions
+  // about it, such as the whole program ends when it ends
+  private FlatSESEEnterNode mainSESE;
+
+  // SESEs that are the root of an SESE tree belong to this
+  // set--the main SESE is always a root, statically SESEs
+  // inside methods are a root because we don't know how they
+  // will fit into the runtime tree of SESEs
+  private Set<FlatSESEEnterNode> rootSESEs;
+
+  // simply a set of every reachable SESE in the program, not
+  // including caller placeholder SESEs
+  private Set<FlatSESEEnterNode> allSESEs;
+
+  // A mapping of flat nodes to the stack of SESEs for that node, where
+  // an SESE is the child of the SESE directly below it on the stack.
+  // These stacks do not reflect the heirarchy over methods calls--whenever
+  // there is an empty stack it means all variables are available.
+  private Hashtable<FlatNode, Stack<FlatSESEEnterNode>> seseStacks;
+
+  private Hashtable<FlatNode, Set<TempDescriptor>> livenessRootView;
+  private Hashtable<FlatNode, Set<TempDescriptor>> livenessVirtualReads;
+  private Hashtable<FlatNode, VarSrcTokTable> variableResults;
+  private Hashtable<FlatNode, Set<TempDescriptor>> notAvailableResults;
+  private Hashtable<FlatNode, CodePlan> codePlans;
+
+  private Hashtable<FlatSESEEnterNode, Set<TempDescriptor>> notAvailableIntoSESE;
+
+  private Hashtable<FlatEdge, FlatWriteDynamicVarNode> wdvNodesToSpliceIn;
+
+  private Hashtable<MethodContext, HashSet<AllocationSite>> mapMethodContextToLiveInAllocationSiteSet;
+
+//  private Hashtable<FlatNode, ParentChildConflictsMap> conflictsResults;
+//  private Hashtable<FlatMethod, MethodSummary> methodSummaryResults;
+//  private OwnershipAnalysis ownAnalysisForSESEConflicts;
+//  private Hashtable<FlatNode, ConflictGraph> conflictGraphResults;
+
+  // temporal data structures to track analysis progress.
+  static private int uniqueLockSetId = 0;
+
+  public static int maxSESEage = -1;
+
+  // use these methods in BuildCode to have access to analysis results
+  public FlatSESEEnterNode getMainSESE() {
+    return mainSESE;
+  }
+
+  public Set<FlatSESEEnterNode> getRootSESEs() {
+    return rootSESEs;
+  }
+
+  public Set<FlatSESEEnterNode> getAllSESEs() {
+    return allSESEs;
+  }
+
+  public int getMaxSESEage() {
+    return maxSESEage;
+  }
+
+  // may be null
+  public CodePlan getCodePlan(FlatNode fn) {
+    CodePlan cp = codePlans.get(fn);
+    return cp;
+  }
+
+  public OoOJavaAnalysis(State state, TypeUtil tu, CallGraph callGraph,
+      DisjointAnalysis disjointAnalysis, Liveness liveness, ArrayReferencees arrayReferencees) {
+
+    double timeStartAnalysis = (double) System.nanoTime();
+
+    this.state = state;
+    this.typeUtil = tu;
+    this.callGraph = callGraph;
+    this.disjointAnalysis = disjointAnalysis;
+    this.maxSESEage = state.MLP_MAXSESEAGE;
+
+    rootSESEs = new HashSet<FlatSESEEnterNode>();
+    allSESEs = new HashSet<FlatSESEEnterNode>();
+
+    seseStacks = new Hashtable<FlatNode, Stack<FlatSESEEnterNode>>();
+    livenessRootView = new Hashtable<FlatNode, Set<TempDescriptor>>();
+    livenessVirtualReads = new Hashtable<FlatNode, Set<TempDescriptor>>();
+    variableResults = new Hashtable<FlatNode, VarSrcTokTable>();
+    notAvailableResults = new Hashtable<FlatNode, Set<TempDescriptor>>();
+    codePlans = new Hashtable<FlatNode, CodePlan>();
+    wdvNodesToSpliceIn = new Hashtable<FlatEdge, FlatWriteDynamicVarNode>();
+
+    notAvailableIntoSESE = new Hashtable<FlatSESEEnterNode, Set<TempDescriptor>>();
+
+    mapMethodContextToLiveInAllocationSiteSet = new Hashtable<MethodContext, HashSet<AllocationSite>>();
+
+//    conflictsResults = new Hashtable<FlatNode, ParentChildConflictsMap>();
+//    methodSummaryResults = new Hashtable<FlatMethod, MethodSummary>();
+//    conflictGraphResults = new Hashtable<FlatNode, ConflictGraph>();
+
+    // seseSummaryMap = new Hashtable<FlatNode, SESESummary>();
+    // isAfterChildSESEIndicatorMap = new Hashtable<FlatNode, Boolean>();
+    // conflictGraphLockMap = new Hashtable<ConflictGraph, HashSet<SESELock>>();
+
+    FlatMethod fmMain = state.getMethodFlat(typeUtil.getMain());
+
+    mainSESE = (FlatSESEEnterNode) fmMain.getNext(0);
+    mainSESE.setfmEnclosing(fmMain);
+    mainSESE.setmdEnclosing(fmMain.getMethod());
+    mainSESE.setcdEnclosing(fmMain.getMethod().getClassDesc());
+
+    // 1st pass
+    // run analysis on each method that is actually called
+    // reachability analysis already computed this so reuse
+    Iterator<Descriptor> methItr = disjointAnalysis.getDescriptorsToAnalyze().iterator();
+    while (methItr.hasNext()) {
+      Descriptor d = methItr.next();
+      FlatMethod fm = state.getMethodFlat(d);
+
+      // find every SESE from methods that may be called
+      // and organize them into roots and children
+      buildForestForward(fm);
+    }
+
+    // 2nd pass, results are saved in FlatSESEEnterNode, so
+    // intermediate results, for safety, are discarded
+    Iterator<FlatSESEEnterNode> rootItr = rootSESEs.iterator();
+    while (rootItr.hasNext()) {
+      FlatSESEEnterNode root = rootItr.next();
+      livenessAnalysisBackward(root, true, null);
+    }
+
+    // 3rd pass
+    methItr = disjointAnalysis.getDescriptorsToAnalyze().iterator();
+    while (methItr.hasNext()) {
+      Descriptor d = methItr.next();
+      FlatMethod fm = state.getMethodFlat(d);
+
+      // starting from roots do a forward, fixed-point
+      // variable analysis for refinement and stalls
+      variableAnalysisForward(fm);
+    }
+
+    // 4th pass, compute liveness contribution from
+    // virtual reads discovered in variable pass
+    rootItr = rootSESEs.iterator();
+    while (rootItr.hasNext()) {
+      FlatSESEEnterNode root = rootItr.next();
+      livenessAnalysisBackward(root, true, null);
+    }
+
+    /*
+     * SOMETHING IS WRONG WITH THIS, DON'T USE IT UNTIL IT CAN BE FIXED
+     * 
+     * // 5th pass methItr = ownAnalysis.descriptorsToAnalyze.iterator(); while(
+     * methItr.hasNext() ) { Descriptor d = methItr.next(); FlatMethod fm =
+     * state.getMethodFlat( d );
+     * 
+     * // prune variable results in one traversal // by removing reference
+     * variables that are not live pruneVariableResultsWithLiveness( fm ); }
+     */
+
+    // 6th pass
+    methItr = disjointAnalysis.getDescriptorsToAnalyze().iterator();
+    while (methItr.hasNext()) {
+      Descriptor d = methItr.next();
+      FlatMethod fm = state.getMethodFlat(d);
+
+      // compute what is not available at every program
+      // point, in a forward fixed-point pass
+      notAvailableForward(fm);
+    }
+
+  }
+
+  private void buildForestForward(FlatMethod fm) {
+
+    // start from flat method top, visit every node in
+    // method exactly once, find SESEs and remember
+    // roots and child relationships
+    Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
+    flatNodesToVisit.add(fm);
+
+    Set<FlatNode> visited = new HashSet<FlatNode>();
+
+    Stack<FlatSESEEnterNode> seseStackFirst = new Stack<FlatSESEEnterNode>();
+    seseStacks.put(fm, seseStackFirst);
+
+    while (!flatNodesToVisit.isEmpty()) {
+      Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
+      FlatNode fn = fnItr.next();
+
+      Stack<FlatSESEEnterNode> seseStack = seseStacks.get(fn);
+      assert seseStack != null;
+
+      flatNodesToVisit.remove(fn);
+      visited.add(fn);
+
+      buildForest_nodeActions(fn, seseStack, fm);
+
+      for (int i = 0; i < fn.numNext(); i++) {
+        FlatNode nn = fn.getNext(i);
+
+        if (!visited.contains(nn)) {
+          flatNodesToVisit.add(nn);
+
+          // clone stack and send along each analysis path
+          seseStacks.put(nn, (Stack<FlatSESEEnterNode>) seseStack.clone());
+        }
+      }
+    }
+  }
+
+  private void buildForest_nodeActions(FlatNode fn, Stack<FlatSESEEnterNode> seseStack,
+      FlatMethod fm) {
+    switch (fn.kind()) {
+
+    case FKind.FlatSESEEnterNode: {
+      FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
+
+      if (!fsen.getIsCallerSESEplaceholder()) {
+        allSESEs.add(fsen);
+      }
+
+      fsen.setfmEnclosing(fm);
+      fsen.setmdEnclosing(fm.getMethod());
+      fsen.setcdEnclosing(fm.getMethod().getClassDesc());
+
+      if (seseStack.empty()) {
+        rootSESEs.add(fsen);
+        fsen.setParent(null);
+      } else {
+        seseStack.peek().addChild(fsen);
+        fsen.setParent(seseStack.peek());
+      }
+
+      seseStack.push(fsen);
+    }
+      break;
+
+    case FKind.FlatSESEExitNode: {
+      FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
+      assert !seseStack.empty();
+      FlatSESEEnterNode fsen = seseStack.pop();
+    }
+      break;
+
+    case FKind.FlatReturnNode: {
+      FlatReturnNode frn = (FlatReturnNode) fn;
+      if (!seseStack.empty() && !seseStack.peek().getIsCallerSESEplaceholder()) {
+        throw new Error("Error: return statement enclosed within SESE "
+            + seseStack.peek().getPrettyIdentifier());
+      }
+    }
+      break;
+
+    }
+  }
+
+  private void livenessAnalysisBackward(FlatSESEEnterNode fsen, boolean toplevel,
+      Hashtable<FlatSESEExitNode, Set<TempDescriptor>> liveout) {
+
+    // start from an SESE exit, visit nodes in reverse up to
+    // SESE enter in a fixed-point scheme, where children SESEs
+    // should already be analyzed and therefore can be skipped
+    // because child SESE enter node has all necessary info
+    Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
+
+    if (toplevel) {
+      flatNodesToVisit.add(fsen.getfmEnclosing().getFlatExit());
+    } else {
+      flatNodesToVisit.add(fsen.getFlatExit());
+    }
+
+    Hashtable<FlatNode, Set<TempDescriptor>> livenessResults = new Hashtable<FlatNode, Set<TempDescriptor>>();
+
+    if (toplevel) {
+      liveout = new Hashtable<FlatSESEExitNode, Set<TempDescriptor>>();
+    }
+
+    while (!flatNodesToVisit.isEmpty()) {
+      FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
+      flatNodesToVisit.remove(fn);
+
+      Set<TempDescriptor> prev = livenessResults.get(fn);
+
+      // merge sets from control flow joins
+      Set<TempDescriptor> u = new HashSet<TempDescriptor>();
+      for (int i = 0; i < fn.numNext(); i++) {
+        FlatNode nn = fn.getNext(i);
+        Set<TempDescriptor> s = livenessResults.get(nn);
+        if (s != null) {
+          u.addAll(s);
+        }
+      }
+
+      Set<TempDescriptor> curr = liveness_nodeActions(fn, u, fsen, toplevel, liveout);
+
+      // if a new result, schedule backward nodes for analysis
+      if (!curr.equals(prev)) {
+        livenessResults.put(fn, curr);
+
+        // don't flow backwards past current SESE enter
+        if (!fn.equals(fsen)) {
+          for (int i = 0; i < fn.numPrev(); i++) {
+            FlatNode nn = fn.getPrev(i);
+            flatNodesToVisit.add(nn);
+          }
+        }
+      }
+    }
+
+    Set<TempDescriptor> s = livenessResults.get(fsen);
+    if (s != null) {
+      fsen.addInVarSet(s);
+    }
 
+    // remember liveness per node from the root view as the
+    // global liveness of variables for later passes to use
+    if (toplevel) {
+      livenessRootView.putAll(livenessResults);
+    }
 
+    // post-order traversal, so do children first
+    Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
+    while (childItr.hasNext()) {
+      FlatSESEEnterNode fsenChild = childItr.next();
+      livenessAnalysisBackward(fsenChild, false, liveout);
+    }
+  }
+
+  private Set<TempDescriptor> liveness_nodeActions(FlatNode fn, Set<TempDescriptor> liveIn,
+      FlatSESEEnterNode currentSESE, boolean toplevel,
+      Hashtable<FlatSESEExitNode, Set<TempDescriptor>> liveout) {
+    switch (fn.kind()) {
+
+    case FKind.FlatSESEExitNode:
+      if (toplevel) {
+        FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
+        if (!liveout.containsKey(fsexn)) {
+          liveout.put(fsexn, new HashSet<TempDescriptor>());
+        }
+        liveout.get(fsexn).addAll(liveIn);
+      }
+      // no break, sese exits should also execute default actions
+
+    default: {
+      // handle effects of statement in reverse, writes then reads
+      TempDescriptor[] writeTemps = fn.writesTemps();
+      for (int i = 0; i < writeTemps.length; ++i) {
+        liveIn.remove(writeTemps[i]);
+
+        if (!toplevel) {
+          FlatSESEExitNode fsexn = currentSESE.getFlatExit();
+          Set<TempDescriptor> livetemps = liveout.get(fsexn);
+          if (livetemps != null && livetemps.contains(writeTemps[i])) {
+            // write to a live out temp...
+            // need to put in SESE liveout set
+            currentSESE.addOutVar(writeTemps[i]);
+          }
+        }
+      }
+
+      TempDescriptor[] readTemps = fn.readsTemps();
+      for (int i = 0; i < readTemps.length; ++i) {
+        liveIn.add(readTemps[i]);
+      }
 
-  public OoOJavaAnalysis( State            state,
-                          TypeUtil         tu,
-                          CallGraph        callGraph,
-                          Liveness         liveness,
-                          ArrayReferencees arrayReferencees
-                          ) {
+      Set<TempDescriptor> virtualReadTemps = livenessVirtualReads.get(fn);
+      if (virtualReadTemps != null) {
+        liveIn.addAll(virtualReadTemps);
+      }
+
+    }
+      break;
+
+    } // end switch
+
+    return liveIn;
   }
+
+  private void variableAnalysisForward(FlatMethod fm) {
+
+    Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
+    flatNodesToVisit.add(fm);
+
+    while (!flatNodesToVisit.isEmpty()) {
+      FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
+      flatNodesToVisit.remove(fn);
+
+      Stack<FlatSESEEnterNode> seseStack = seseStacks.get(fn);
+      assert seseStack != null;
+
+      VarSrcTokTable prev = variableResults.get(fn);
+
+      // merge sets from control flow joins
+      VarSrcTokTable curr = new VarSrcTokTable();
+      for (int i = 0; i < fn.numPrev(); i++) {
+        FlatNode nn = fn.getPrev(i);
+        VarSrcTokTable incoming = variableResults.get(nn);
+        curr.merge(incoming);
+      }
+
+      if (!seseStack.empty()) {
+        variable_nodeActions(fn, curr, seseStack.peek());
+      }
+
+      // if a new result, schedule forward nodes for analysis
+      if (!curr.equals(prev)) {
+        variableResults.put(fn, curr);
+
+        for (int i = 0; i < fn.numNext(); i++) {
+          FlatNode nn = fn.getNext(i);
+          flatNodesToVisit.add(nn);
+        }
+      }
+    }
+  }
+
+  private void variable_nodeActions(FlatNode fn, VarSrcTokTable vstTable,
+      FlatSESEEnterNode currentSESE) {
+    switch (fn.kind()) {
+
+    case FKind.FlatSESEEnterNode: {
+      FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
+      assert fsen.equals(currentSESE);
+
+      vstTable.age(currentSESE);
+      vstTable.assertConsistency();
+    }
+      break;
+
+    case FKind.FlatSESEExitNode: {
+      FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
+      FlatSESEEnterNode fsen = fsexn.getFlatEnter();
+      assert currentSESE.getChildren().contains(fsen);
+
+      // remap all of this child's children tokens to be
+      // from this child as the child exits
+      vstTable.remapChildTokens(fsen);
+
+      // liveness virtual reads are things that might be
+      // written by an SESE and should be added to the in-set
+      // anything virtually read by this SESE should be pruned
+      // of parent or sibling sources
+      Set<TempDescriptor> liveVars = livenessRootView.get(fn);
+      Set<TempDescriptor> fsenVirtReads = vstTable.calcVirtReadsAndPruneParentAndSiblingTokens(
+          fsen, liveVars);
+      Set<TempDescriptor> fsenVirtReadsOld = livenessVirtualReads.get(fn);
+      if (fsenVirtReadsOld != null) {
+        fsenVirtReads.addAll(fsenVirtReadsOld);
+      }
+      livenessVirtualReads.put(fn, fsenVirtReads);
+
+      // then all child out-set tokens are guaranteed
+      // to be filled in, so clobber those entries with
+      // the latest, clean sources
+      Iterator<TempDescriptor> outVarItr = fsen.getOutVarSet().iterator();
+      while (outVarItr.hasNext()) {
+        TempDescriptor outVar = outVarItr.next();
+        HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
+        ts.add(outVar);
+        VariableSourceToken vst = new VariableSourceToken(ts, fsen, new Integer(0), outVar);
+        vstTable.remove(outVar);
+        vstTable.add(vst);
+      }
+      vstTable.assertConsistency();
+
+    }
+      break;
+
+    case FKind.FlatOpNode: {
+      FlatOpNode fon = (FlatOpNode) fn;
+
+      if (fon.getOp().getOp() == Operation.ASSIGN) {
+        TempDescriptor lhs = fon.getDest();
+        TempDescriptor rhs = fon.getLeft();
+
+        vstTable.remove(lhs);
+
+        Set<VariableSourceToken> forAddition = new HashSet<VariableSourceToken>();
+
+        Iterator<VariableSourceToken> itr = vstTable.get(rhs).iterator();
+        while (itr.hasNext()) {
+          VariableSourceToken vst = itr.next();
+
+          HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
+          ts.add(lhs);
+
+          if (currentSESE.getChildren().contains(vst.getSESE())) {
+            // if the source comes from a child, copy it over
+            forAddition.add(new VariableSourceToken(ts, vst.getSESE(), vst.getAge(), vst
+                .getAddrVar()));
+          } else {
+            // otherwise, stamp it as us as the source
+            forAddition.add(new VariableSourceToken(ts, currentSESE, new Integer(0), lhs));
+          }
+        }
+
+        vstTable.addAll(forAddition);
+
+        // only break if this is an ASSIGN op node,
+        // otherwise fall through to default case
+        vstTable.assertConsistency();
+        break;
+      }
+    }
+
+      // note that FlatOpNode's that aren't ASSIGN
+      // fall through to this default case
+    default: {
+      TempDescriptor[] writeTemps = fn.writesTemps();
+      if (writeTemps.length > 0) {
+
+        // for now, when writeTemps > 1, make sure
+        // its a call node, programmer enforce only
+        // doing stuff like calling a print routine
+        // assert writeTemps.length == 1;
+        if (writeTemps.length > 1) {
+          assert fn.kind() == FKind.FlatCall || fn.kind() == FKind.FlatMethod;
+          break;
+        }
+
+        vstTable.remove(writeTemps[0]);
+
+        HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
+        ts.add(writeTemps[0]);
+
+        vstTable.add(new VariableSourceToken(ts, currentSESE, new Integer(0), writeTemps[0]));
+      }
+
+      vstTable.assertConsistency();
+    }
+      break;
+
+    } // end switch
+  }
+
+  private void notAvailableForward(FlatMethod fm) {
+
+    Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
+    flatNodesToVisit.add(fm);
+
+    while (!flatNodesToVisit.isEmpty()) {
+      FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
+      flatNodesToVisit.remove(fn);
+
+      Stack<FlatSESEEnterNode> seseStack = seseStacks.get(fn);
+      assert seseStack != null;
+
+      Set<TempDescriptor> prev = notAvailableResults.get(fn);
+
+      Set<TempDescriptor> curr = new HashSet<TempDescriptor>();
+      for (int i = 0; i < fn.numPrev(); i++) {
+        FlatNode nn = fn.getPrev(i);
+        Set<TempDescriptor> notAvailIn = notAvailableResults.get(nn);
+        if (notAvailIn != null) {
+          curr.addAll(notAvailIn);
+        }
+      }
+
+      if (!seseStack.empty()) {
+        notAvailable_nodeActions(fn, curr, seseStack.peek());
+      }
+
+      // if a new result, schedule forward nodes for analysis
+      if (!curr.equals(prev)) {
+        notAvailableResults.put(fn, curr);
+
+        for (int i = 0; i < fn.numNext(); i++) {
+          FlatNode nn = fn.getNext(i);
+          flatNodesToVisit.add(nn);
+        }
+      }
+    }
+  }
+
+  private void notAvailable_nodeActions(FlatNode fn, Set<TempDescriptor> notAvailSet,
+      FlatSESEEnterNode currentSESE) {
+
+    // any temps that are removed from the not available set
+    // at this node should be marked in this node's code plan
+    // as temps to be grabbed at runtime!
+
+    switch (fn.kind()) {
+
+    case FKind.FlatSESEEnterNode: {
+      FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
+      assert fsen.equals(currentSESE);
+
+      // keep a copy of what's not available into the SESE
+      // and restore it at the matching exit node
+      Set<TempDescriptor> notAvailCopy = new HashSet<TempDescriptor>();
+      Iterator<TempDescriptor> tdItr = notAvailSet.iterator();
+      while (tdItr.hasNext()) {
+        notAvailCopy.add(tdItr.next());
+      }
+      notAvailableIntoSESE.put(fsen, notAvailCopy);
+
+      notAvailSet.clear();
+    }
+      break;
+
+    case FKind.FlatSESEExitNode: {
+      FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
+      FlatSESEEnterNode fsen = fsexn.getFlatEnter();
+      assert currentSESE.getChildren().contains(fsen);
+
+      notAvailSet.addAll(fsen.getOutVarSet());
+
+      Set<TempDescriptor> notAvailIn = notAvailableIntoSESE.get(fsen);
+      assert notAvailIn != null;
+      notAvailSet.addAll(notAvailIn);
+
+    }
+      break;
+
+    case FKind.FlatMethod: {
+      notAvailSet.clear();
+    }
+
+    case FKind.FlatOpNode: {
+      FlatOpNode fon = (FlatOpNode) fn;
+
+      if (fon.getOp().getOp() == Operation.ASSIGN) {
+        TempDescriptor lhs = fon.getDest();
+        TempDescriptor rhs = fon.getLeft();
+
+        // copy makes lhs same availability as rhs
+        if (notAvailSet.contains(rhs)) {
+          notAvailSet.add(lhs);
+        } else {
+          notAvailSet.remove(lhs);
+        }
+
+        // only break if this is an ASSIGN op node,
+        // otherwise fall through to default case
+        break;
+      }
+    }
+
+      // note that FlatOpNode's that aren't ASSIGN
+      // fall through to this default case
+    default: {
+      TempDescriptor[] writeTemps = fn.writesTemps();
+      for (int i = 0; i < writeTemps.length; i++) {
+        TempDescriptor wTemp = writeTemps[i];
+        notAvailSet.remove(wTemp);
+      }
+      TempDescriptor[] readTemps = fn.readsTemps();
+      for (int i = 0; i < readTemps.length; i++) {
+        TempDescriptor rTemp = readTemps[i];
+        notAvailSet.remove(rTemp);
+
+        // if this variable has exactly one source, potentially
+        // get other things from this source as well
+        VarSrcTokTable vstTable = variableResults.get(fn);
+
+        VSTWrapper vstIfStatic = new VSTWrapper();
+        Integer srcType = vstTable.getRefVarSrcType(rTemp, currentSESE, vstIfStatic);
+
+        if (srcType.equals(VarSrcTokTable.SrcType_STATIC)) {
+
+          VariableSourceToken vst = vstIfStatic.vst;
+
+          Iterator<VariableSourceToken> availItr = vstTable.get(vst.getSESE(), vst.getAge())
+              .iterator();
+
+          // look through things that are also available from same source
+          while (availItr.hasNext()) {
+            VariableSourceToken vstAlsoAvail = availItr.next();
+
+            Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
+            while (refVarItr.hasNext()) {
+              TempDescriptor refVarAlso = refVarItr.next();
+
+              // if a variable is available from the same source, AND it ALSO
+              // only comes from one statically known source, mark it available
+              VSTWrapper vstIfStaticNotUsed = new VSTWrapper();
+              Integer srcTypeAlso = vstTable.getRefVarSrcType(refVarAlso, currentSESE,
+                  vstIfStaticNotUsed);
+              if (srcTypeAlso.equals(VarSrcTokTable.SrcType_STATIC)) {
+                notAvailSet.remove(refVarAlso);
+              }
+            }
+          }
+        }
+      }
+    }
+      break;
+
+    } // end switch
+  }
+
 }
diff --git a/Robust/src/Analysis/OoOJava/SVKey.java b/Robust/src/Analysis/OoOJava/SVKey.java
new file mode 100644 (file)
index 0000000..e98ff31
--- /dev/null
@@ -0,0 +1,50 @@
+package Analysis.OoOJava;
+
+import IR.*;
+import IR.Flat.*;
+import java.util.*;
+import java.io.*;
+
+public class SVKey {
+
+  private FlatSESEEnterNode sese;
+  private TempDescriptor    var;
+
+  public SVKey( FlatSESEEnterNode sese,
+               TempDescriptor    var ) {
+    this.sese = sese;
+    this.var  = var;
+  }
+
+  public FlatSESEEnterNode getSESE() {
+    return sese;
+  }
+
+  public TempDescriptor getVar() {
+    return var;
+  }
+
+  public boolean equals( Object o ) {
+    if( o == null ) {
+      return false;
+    }
+
+    if( !(o instanceof SVKey) ) {
+      return false;
+    }
+
+    SVKey k = (SVKey) o;
+
+    return var.equals( k.var  ) &&
+          sese.equals( k.sese );
+  }
+
+  public int hashCode() {
+    return (sese.hashCode() << 2)*(var.hashCode() << 5);
+  }
+
+
+  public String toString() {
+    return "key["+sese.getPrettyIdentifier()+", "+var+"]";
+  }
+}
diff --git a/Robust/src/Analysis/OoOJava/VSTWrapper.java b/Robust/src/Analysis/OoOJava/VSTWrapper.java
new file mode 100644 (file)
index 0000000..6f17610
--- /dev/null
@@ -0,0 +1,17 @@
+package Analysis.OoOJava;
+
+import IR.*;
+import IR.Flat.*;
+import java.util.*;
+import java.io.*;
+
+// the reason for this class is to allow a VariableSourceToken
+// to be null in some circumstances
+
+public class VSTWrapper {
+  public VariableSourceToken vst;
+
+  public VSTWrapper() {
+    vst = null;
+  }
+}
diff --git a/Robust/src/Analysis/OoOJava/VarSrcTokTable.java b/Robust/src/Analysis/OoOJava/VarSrcTokTable.java
new file mode 100644 (file)
index 0000000..782d45e
--- /dev/null
@@ -0,0 +1,884 @@
+package Analysis.OoOJava;
+
+import IR.*;
+import IR.Flat.*;
+import java.util.*;
+import java.io.*;
+
+// This class formerly had lazy consistency properties, but
+// it is being changed so that the full set and the extra
+// hash tables to access the full set efficiently by different
+// elements will be consistent after EVERY operation.  Also,
+// a consistent assert method allows a debugger to ask whether
+// an operation has produced an inconsistent VarSrcTokTable.
+
+// in an effort to make sure operations keep the table consistent,
+// all public methods that are also used by other methods for
+// intermediate results (add and remove are used in other methods)
+// there should be a public version that calls the private version
+// so consistency is checked after public ops, but not private ops
+public class VarSrcTokTable {
+
+  // a set of every token in the table
+  private HashSet<VariableSourceToken> trueSet;
+
+  // these hashtables provide an efficient retreival from the true set
+  private Hashtable< TempDescriptor,    Set<VariableSourceToken> >  var2vst;
+  private Hashtable< FlatSESEEnterNode, Set<VariableSourceToken> > sese2vst;
+  private Hashtable< SVKey,             Set<VariableSourceToken> >   sv2vst;
+
+  // maximum age from aging operation
+  private static final Integer MAX_AGE = new Integer( 2 );
+  
+  public static final Integer SrcType_READY   = new Integer( 34 );
+  public static final Integer SrcType_STATIC  = new Integer( 35 );
+  public static final Integer SrcType_DYNAMIC = new Integer( 36 );
+
+
+  public VarSrcTokTable() {
+    trueSet  = new HashSet<VariableSourceToken>();
+
+    sese2vst = new Hashtable< FlatSESEEnterNode, Set<VariableSourceToken> >();
+    var2vst  = new Hashtable< TempDescriptor,    Set<VariableSourceToken> >();
+    sv2vst   = new Hashtable< SVKey,             Set<VariableSourceToken> >();
+
+    assertConsistency();
+  }
+
+
+  // make a deep copy of the in table
+  public VarSrcTokTable( VarSrcTokTable in ) {
+    this();
+    merge( in );
+    assertConsistency();
+  }
+
+
+  public void add( VariableSourceToken vst ) {
+    addPrivate( vst );
+    assertConsistency();
+  }
+
+  private void addPrivate( VariableSourceToken vst ) {
+
+    // make sure we aren't clobbering anything!
+    if( trueSet.contains( vst ) ) {
+      // if something with the same hashcode is in the true set, they might
+      // have different reference variable sets because that set is not considered
+      // in a token's equality, so make sure we smooth that out right here
+      Iterator<VariableSourceToken> vstItr = trueSet.iterator();
+      while( vstItr.hasNext() ) {
+        VariableSourceToken vstAlready = vstItr.next();
+
+        if( vstAlready.equals( vst ) ) {    
+
+          // take out the one that is in (we dont' want collisions in
+          // any of the other hash map sets either)
+          removePrivate( vstAlready );
+
+          // combine reference variable sets
+          vst.getRefVars().addAll( vstAlready.getRefVars() );
+
+          // now jump back as we are adding in a brand new token
+          break;
+        }
+      }
+    }
+
+    trueSet.add( vst );
+
+    Set<VariableSourceToken> s;
+
+    s = sese2vst.get( vst.getSESE() );
+    if( s == null ) {
+      s = new HashSet<VariableSourceToken>();
+    }
+    s.add( vst );
+    sese2vst.put( vst.getSESE(), s );
+
+    Iterator<TempDescriptor> refVarItr = vst.getRefVars().iterator();
+    while( refVarItr.hasNext() ) {
+      TempDescriptor refVar = refVarItr.next();
+      s = var2vst.get( refVar );
+      if( s == null ) {
+        s = new HashSet<VariableSourceToken>();
+      }
+      s.add( vst );
+      var2vst.put( refVar, s );
+
+      SVKey key = new SVKey( vst.getSESE(), refVar );
+      s = sv2vst.get( key );
+      if( s == null ) {
+        s = new HashSet<VariableSourceToken>();
+      }
+      s.add( vst );
+      sv2vst.put( key, s );
+    }
+  }
+
+  public void addAll( Set<VariableSourceToken> s ) {
+    Iterator<VariableSourceToken> itr = s.iterator();
+    while( itr.hasNext() ) {
+      addPrivate( itr.next() );
+    }
+    assertConsistency();
+  }
+
+
+  public Set<VariableSourceToken> get() {
+    return trueSet;
+  }
+
+  public Set<VariableSourceToken> get( FlatSESEEnterNode sese ) {
+    Set<VariableSourceToken> s = sese2vst.get( sese );
+    if( s == null ) {
+      s = new HashSet<VariableSourceToken>();      
+      sese2vst.put( sese, s );
+    }
+    return s;
+  }
+
+  public Set<VariableSourceToken> get( TempDescriptor refVar ) {
+    Set<VariableSourceToken> s = var2vst.get( refVar );
+    if( s == null ) {
+      s = new HashSet<VariableSourceToken>();
+      var2vst.put( refVar, s );
+    }
+    return s;
+  }
+
+  public Set<VariableSourceToken> get( FlatSESEEnterNode sese,
+                                       TempDescriptor    refVar ) {
+    SVKey key = new SVKey( sese, refVar );
+    Set<VariableSourceToken> s = sv2vst.get( key );
+    if( s == null ) {
+      s = new HashSet<VariableSourceToken>();
+      sv2vst.put( key, s );
+    }
+    return s;
+  }
+
+  public Set<VariableSourceToken> get( FlatSESEEnterNode sese,
+                                       Integer           age ) {
+
+    HashSet<VariableSourceToken> s0 = (HashSet<VariableSourceToken>) sese2vst.get( sese );
+    if( s0 == null ) {
+      s0 = new HashSet<VariableSourceToken>();      
+      sese2vst.put( sese, s0 );
+    }
+
+    Set<VariableSourceToken> s = (Set<VariableSourceToken>) s0.clone();
+    Iterator<VariableSourceToken> sItr = s.iterator();
+    while( sItr.hasNext() ) {
+      VariableSourceToken vst = sItr.next();
+      if( !vst.getAge().equals( age ) ) {
+        s.remove( vst );
+      }
+    }
+
+    return s;
+  }
+
+
+  // merge now makes a deep copy of incoming stuff because tokens may
+  // be modified (reference var sets) by later ops that change more
+  // than one table, causing inconsistency
+  public void merge( VarSrcTokTable in ) {
+
+    if( in == null ) {
+      return;
+    }
+
+    Iterator<VariableSourceToken> vstItr = in.trueSet.iterator();
+    while( vstItr.hasNext() ) {
+      VariableSourceToken vst = vstItr.next();
+      this.addPrivate( vst.copy() );
+    }
+
+    assertConsistency();
+  }
+
+
+  // remove operations must leave the trueSet 
+  // and the hash maps consistent
+  public void remove( VariableSourceToken vst ) {
+    removePrivate( vst );
+    assertConsistency();
+  }
+
+  private void removePrivate( VariableSourceToken vst ) {
+    trueSet.remove( vst );
+    
+    Set<VariableSourceToken> s;
+
+    s = get( vst.getSESE() );
+    if( s != null ) { s.remove( vst ); }
+
+    Iterator<TempDescriptor> refVarItr = vst.getRefVars().iterator();
+    while( refVarItr.hasNext() ) {
+      TempDescriptor refVar = refVarItr.next();
+
+      s = get( refVar );
+      if( s != null ) { 
+       s.remove( vst );
+       if( s.isEmpty() ) {
+         var2vst.remove( refVar );
+       }
+      }
+      
+      s = get( vst.getSESE(), refVar );
+      if( s != null ) { 
+       s.remove( vst );
+       if( s.isEmpty() ) {
+         sv2vst.remove( new SVKey( vst.getSESE(), refVar ) );
+       }
+      }
+    }
+  }
+
+
+  public void remove( FlatSESEEnterNode sese ) {
+    removePrivate( sese );
+    assertConsistency();
+  }
+
+  public void removePrivate( FlatSESEEnterNode sese ) {
+    Set<VariableSourceToken> s = sese2vst.get( sese );
+    if( s == null ) {
+      return;
+    }
+
+    Iterator<VariableSourceToken> itr = s.iterator();
+    while( itr.hasNext() ) {
+      VariableSourceToken vst = itr.next();
+      removePrivate( vst );
+    }
+
+    sese2vst.remove( sese );
+  }
+
+
+  public void remove( TempDescriptor refVar ) {
+    removePrivate( refVar );
+    assertConsistency();
+  }
+
+  private void removePrivate( TempDescriptor refVar ) {
+    Set<VariableSourceToken> s = var2vst.get( refVar );
+    if( s == null ) {
+      return;
+    }
+    
+    Set<VariableSourceToken> forRemoval = new HashSet<VariableSourceToken>();
+
+    // iterate over tokens that this temp can reference, make a set
+    // of tokens that need this temp stripped out of them
+    Iterator<VariableSourceToken> itr = s.iterator();
+    while( itr.hasNext() ) {
+      VariableSourceToken vst = itr.next();
+      Set<TempDescriptor> refVars = vst.getRefVars();
+      assert refVars.contains( refVar );
+      forRemoval.add( vst );
+    }
+
+    itr = forRemoval.iterator();
+    while( itr.hasNext() ) {
+
+      // here's a token marked for removal
+      VariableSourceToken vst = itr.next();
+      Set<TempDescriptor> refVars = vst.getRefVars();
+
+      // if there was only one one variable
+      // referencing this token, just take it
+      // out of the table all together
+      if( refVars.size() == 1 ) {
+        removePrivate( vst );
+      }
+
+      sv2vst.remove( new SVKey( vst.getSESE(), refVar ) );
+
+      refVars.remove( refVar );      
+    }
+
+    var2vst.remove( refVar );    
+  }
+
+
+  public void remove( FlatSESEEnterNode sese,
+                     TempDescriptor    var  ) {
+
+    // don't seem to need this, don't bother maintaining
+    // until its clear we need it
+    assert false;
+  }
+
+
+  // age tokens with respect to SESE curr, where
+  // any curr tokens increase age by 1
+  public void age( FlatSESEEnterNode curr ) {
+
+    Set<VariableSourceToken> forRemoval =
+      new HashSet<VariableSourceToken>();
+
+    Set<VariableSourceToken> forAddition =
+      new HashSet<VariableSourceToken>();
+
+    Iterator<VariableSourceToken> itr = trueSet.iterator();
+    while( itr.hasNext() ) {
+      VariableSourceToken vst = itr.next();
+
+      if( vst.getSESE().equals( curr ) ) {
+
+       // only age if the token isn't already the maximum age
+       if( vst.getAge() < MAX_AGE ) {
+       
+         forRemoval.add( vst );
+
+         forAddition.add( new VariableSourceToken( vst.getRefVars(), 
+                                                   curr,                                           
+                                                   vst.getAge() + 1,
+                                                   vst.getAddrVar()
+                                                   )
+                          );
+       }
+      }        
+    }
+    
+    itr = forRemoval.iterator();
+    while( itr.hasNext() ) {
+      VariableSourceToken vst = itr.next();
+      remove( vst );
+    }
+    
+    itr = forRemoval.iterator();
+    while( itr.hasNext() ) {
+      VariableSourceToken vst = itr.next();
+      add( vst );
+    }
+
+    assertConsistency();
+  }
+
+
+  // at an SESE enter node, all ref vars in the SESE's in-set will
+  // be copied into the SESE's local scope, change source to itself
+  public void ownInSet( FlatSESEEnterNode curr ) {
+    Iterator<TempDescriptor> inVarItr = curr.getInVarSet().iterator();
+    while( inVarItr.hasNext() ) {
+      TempDescriptor inVar = inVarItr.next();
+
+      remove( inVar );
+      assertConsistency();
+
+      Set<TempDescriptor> refVars = new HashSet<TempDescriptor>();
+      refVars.add( inVar );
+      add( new VariableSourceToken( refVars,
+                                   curr,
+                                   new Integer( 0 ),
+                                   inVar
+                                   )
+          );
+      assertConsistency();
+    }
+  }
+
+  
+  // for the given SESE, change child tokens into this parent
+  public void remapChildTokens( FlatSESEEnterNode curr ) {
+
+    Iterator<FlatSESEEnterNode> childItr = curr.getChildren().iterator();
+    if( childItr.hasNext() ) {
+      FlatSESEEnterNode child = childItr.next();
+      
+      // set of VSTs for removal
+      HashSet<VariableSourceToken> removalSet=new HashSet<VariableSourceToken>();
+      // set of VSTs for additon
+      HashSet<VariableSourceToken> additionSet=new HashSet<VariableSourceToken>();
+      
+      Iterator<VariableSourceToken> vstItr = get( child ).iterator();
+      while( vstItr.hasNext() ) {
+        VariableSourceToken vst = vstItr.next();
+        removalSet.add(vst);
+        additionSet.add(new VariableSourceToken( vst.getRefVars(),
+                             curr,
+                             new Integer( 0 ),
+                             vst.getAddrVar()
+                                  ));
+      }
+      
+      // remove( eah item in forremoval )
+      vstItr = removalSet.iterator();
+      while( vstItr.hasNext() ) {
+        VariableSourceToken vst = vstItr.next();
+        remove( vst );
+      }
+      // add( each  ite inm for additon _
+      vstItr = additionSet.iterator();
+      while( vstItr.hasNext() ) {
+        VariableSourceToken vst = vstItr.next();
+        add( vst );
+      }
+    }
+
+    assertConsistency();
+  }   
+  
+
+  // this method is called at the SESE exit of SESE 'curr'
+  // if the sources for a variable written by curr can also
+  // come from curr's parent or curr's siblings then we're not
+  // sure that curr will actually modify the variable.  There are
+  // many ways to handle this, but for now, mark the variable as
+  // virtually read so curr insists on having ownership of it
+  // whether it ends up writing to it or not.  It will always, then,
+  // appear in curr's out-set.
+  public Set<TempDescriptor>
+    calcVirtReadsAndPruneParentAndSiblingTokens( FlatSESEEnterNode exiter,
+                                                Set<TempDescriptor> liveVars ) {
+
+    Set<TempDescriptor> virtReadSet = new HashSet<TempDescriptor>();
+
+    FlatSESEEnterNode parent = exiter.getParent();
+    if( parent == null ) {
+      // having no parent means no siblings, too
+      return virtReadSet;
+    }
+
+    Set<FlatSESEEnterNode> alternateSESEs = new HashSet<FlatSESEEnterNode>();
+    alternateSESEs.add( parent );
+    Iterator<FlatSESEEnterNode> childItr = parent.getChildren().iterator();
+    while( childItr.hasNext() ) {
+      FlatSESEEnterNode sibling = childItr.next();      
+      if( !sibling.equals( exiter ) ) {
+        alternateSESEs.add( sibling );
+      }
+    }
+    
+    // VSTs to remove if they are alternate sources for exiter VSTs
+    // whose variables will become virtual reads
+    Set<VariableSourceToken> forRemoval = new HashSet<VariableSourceToken>();
+
+    // look at all of this SESE's VSTs at exit...
+    Iterator<VariableSourceToken> vstItr = get( exiter ).iterator();
+    while( vstItr.hasNext() ) {
+      VariableSourceToken vstExiterSrc = vstItr.next();
+
+      // only interested in tokens that come from our current instance
+      if( vstExiterSrc.getAge() != 0 ) {
+       continue;
+      }
+
+      // for each variable that might come from those sources...
+      Iterator<TempDescriptor> refVarItr = vstExiterSrc.getRefVars().iterator();
+      while( refVarItr.hasNext() ) {
+        TempDescriptor refVar = refVarItr.next();
+
+       // only matters for live variables at SESE exit program point
+       if( !liveVars.contains( refVar ) ) {
+         continue;
+       }
+
+       // examine other sources for a variable...
+       Iterator<VariableSourceToken> srcItr = get( refVar ).iterator();
+       while( srcItr.hasNext() ) {
+         VariableSourceToken vstPossibleOtherSrc = srcItr.next();
+
+         if( vstPossibleOtherSrc.getSESE().equals( exiter ) &&
+             vstPossibleOtherSrc.getAge() > 0 
+           ) {
+           // this is an alternate source if its 
+           // an older instance of this SESE               
+           virtReadSet.add( refVar );
+           forRemoval.add( vstPossibleOtherSrc );
+           
+         } else if( alternateSESEs.contains( vstPossibleOtherSrc.getSESE() ) ) {
+           // this is an alternate source from parent or sibling
+           virtReadSet.add( refVar );
+           forRemoval.add( vstPossibleOtherSrc );  
+
+         } else {
+           assert vstPossibleOtherSrc.getSESE().equals( exiter );
+           assert vstPossibleOtherSrc.getAge().equals( 0 );
+         }
+       }
+      }
+    }
+
+    vstItr = forRemoval.iterator();
+    while( vstItr.hasNext() ) {
+      VariableSourceToken vst = vstItr.next();
+      remove( vst );
+    }
+    assertConsistency();
+    
+    return virtReadSet;
+  }
+  
+  
+  // get the set of VST's that come from a child
+  public Set<VariableSourceToken> getChildrenVSTs( FlatSESEEnterNode curr ) {
+    
+    Set<VariableSourceToken> out = new HashSet<VariableSourceToken>();
+    
+    Iterator<FlatSESEEnterNode> cItr = curr.getChildren().iterator();
+    while( cItr.hasNext() ) {
+      FlatSESEEnterNode child = cItr.next();
+      out.addAll( get( child ) );
+    }
+
+    return out;
+  }
+
+
+  // given a table from a subsequent program point, decide
+  // which variables are going from a non-dynamic to a
+  // dynamic source and return them
+  public Hashtable<TempDescriptor, VSTWrapper> 
+    getReadyOrStatic2DynamicSet( VarSrcTokTable nextTable,
+                                 Set<TempDescriptor> nextLiveIn,
+                                 FlatSESEEnterNode current
+                                 ) {
+    
+    Hashtable<TempDescriptor, VSTWrapper> out = 
+      new Hashtable<TempDescriptor, VSTWrapper>();
+    
+    Iterator itr = var2vst.entrySet().iterator();
+    while( itr.hasNext() ) {
+      Map.Entry                    me  = (Map.Entry)                    itr.next();
+      TempDescriptor               var = (TempDescriptor)               me.getKey();
+      HashSet<VariableSourceToken> s1  = (HashSet<VariableSourceToken>) me.getValue();      
+
+      // only worth tracking if live
+      if( nextLiveIn.contains( var ) ) {
+        
+        VSTWrapper vstIfStaticBefore = new VSTWrapper();
+        VSTWrapper vstIfStaticAfter  = new VSTWrapper();
+
+        Integer srcTypeBefore =      this.getRefVarSrcType( var, current, vstIfStaticBefore );
+        Integer srcTypeAfter  = nextTable.getRefVarSrcType( var, current, vstIfStaticAfter  );
+
+       if( !srcTypeBefore.equals( SrcType_DYNAMIC ) &&
+              srcTypeAfter.equals( SrcType_DYNAMIC )      
+          ) {
+         // remember the variable and a source
+         // it had before crossing the transition
+          // 1) if it was ready, vstIfStatic.vst is null
+          // 2) if is was static, use vstIfStatic.vst
+         out.put( var, vstIfStaticBefore );
+       }
+      }
+    }
+
+    return out;
+  }
+
+
+  // for some reference variable, return the type of source
+  // it might have in this table, which might be:
+  // 1. Ready -- this variable is
+  //      definitely available when you are issued.
+  // 2. Static -- there is definitely one child SESE with
+  //      a known age that will produce the value
+  // 3. Dynamic -- we don't know where the value will come
+  //      from statically, so we'll track it dynamically
+  public Integer getRefVarSrcType( TempDescriptor    refVar,
+                                  FlatSESEEnterNode current,
+                                   VSTWrapper        vstIfStatic ) {
+    assert refVar      != null;
+    assert vstIfStatic != null;
+
+    vstIfStatic.vst = null;
+   
+    // when the current SESE is null, that simply means it is
+    // an unknown placeholder, in which case the system will
+    // ensure that any variables are READY
+    if( current == null ) {
+      return SrcType_READY;
+    }
+
+    // if there appear to be no sources, it means this variable
+    // comes from outside of any statically-known SESE scope,
+    // which means the system guarantees its READY, so jump over
+    // while loop
+    Set<VariableSourceToken>      srcs    = get( refVar );
+    Iterator<VariableSourceToken> itrSrcs = srcs.iterator();
+    while( itrSrcs.hasNext() ) {
+      VariableSourceToken vst = itrSrcs.next();
+
+      // to make the refVar non-READY we have to find at least
+      // one child token
+      if( current.getChildren().contains( vst.getSESE() ) ) {
+
+        // if we ever have at least one child source with an
+        // unknown age, have to treat var as dynamic
+        if( vst.getAge().equals( OoOJavaAnalysis.maxSESEage ) ) {
+          return SrcType_DYNAMIC;
+        }
+
+        // if we have a known-age child source, this var is
+        // either static or dynamic now: it's static if this
+        // source is the only source, otherwise dynamic
+        if( srcs.size() > 1 ) {
+          return SrcType_DYNAMIC;
+        }
+        
+        vstIfStatic.vst = vst;
+        return SrcType_STATIC;
+      }
+    }
+
+    // if we never found a child source, all other
+    // sources must be READY before we could even
+    // begin executing!
+    return SrcType_READY;
+  }
+
+
+  // any reference variables that are not live can be pruned
+  // from the table, and if any VSTs are then no longer 
+  // referenced, they can be dropped as well
+  // THIS CAUSES INCONSISTENCY, FIX LATER, NOT REQUIRED
+  public void pruneByLiveness( Set<TempDescriptor> rootLiveSet ) {
+    
+    // the set of reference variables in the table minus the
+    // live set gives the set of reference variables to remove
+    Set<TempDescriptor> deadRefVars = new HashSet<TempDescriptor>();
+    deadRefVars.addAll( var2vst.keySet() );
+
+    if( rootLiveSet != null ) {
+      deadRefVars.removeAll( rootLiveSet );
+    }
+
+    // just use the remove operation to prune the table now
+    Iterator<TempDescriptor> deadItr = deadRefVars.iterator();
+    while( deadItr.hasNext() ) {
+      TempDescriptor dead = deadItr.next();
+      removePrivate( dead );
+    }
+
+    assertConsistency();
+  }
+
+
+  // use as an aid for debugging, where true-set is checked
+  // against the alternate mappings: assert that nothing is
+  // missing or extra in the alternates
+  public void assertConsistency() {
+
+    Iterator itr; 
+    Set s;
+
+    Set<VariableSourceToken> trueSetByAlts = new HashSet<VariableSourceToken>();
+    itr = sese2vst.entrySet().iterator();
+    while( itr.hasNext() ) {
+      Map.Entry                    me   = (Map.Entry)                    itr.next();
+      FlatSESEEnterNode            sese = (FlatSESEEnterNode)            me.getKey();
+      HashSet<VariableSourceToken> s1   = (HashSet<VariableSourceToken>) me.getValue();      
+      assert s1 != null;
+      
+      // the trueSet should have all entries in s1
+      assert trueSet.containsAll( s1 );
+
+      // s1 should not have anything that doesn't appear in trueset
+      Set<VariableSourceToken> sInt = (Set<VariableSourceToken>) s1.clone();
+      sInt.removeAll( trueSet );
+
+      assert sInt.isEmpty();
+
+      // add s1 to a running union--at the end check if trueSet has extra
+      trueSetByAlts.addAll( s1 );
+    }
+    // make sure trueSet isn't too big
+    assert trueSetByAlts.containsAll( trueSet );
+
+
+    trueSetByAlts = new HashSet<VariableSourceToken>();
+    itr = var2vst.entrySet().iterator();
+    while( itr.hasNext() ) {
+      Map.Entry                    me   = (Map.Entry)                    itr.next();
+      TempDescriptor               var  = (TempDescriptor)               me.getKey();
+      HashSet<VariableSourceToken> s1   = (HashSet<VariableSourceToken>) me.getValue();      
+      assert s1 != null;
+      
+      // the trueSet should have all entries in s1
+      assert trueSet.containsAll( s1 );
+
+      // s1 should not have anything that doesn't appear in trueset
+      Set<VariableSourceToken> sInt = (Set<VariableSourceToken>) s1.clone();
+      sInt.removeAll( trueSet );
+
+      assert sInt.isEmpty();
+
+      // add s1 to a running union--at the end check if trueSet has extra
+      trueSetByAlts.addAll( s1 );
+    }
+    // make sure trueSet isn't too big
+    assert trueSetByAlts.containsAll( trueSet );
+
+
+    trueSetByAlts = new HashSet<VariableSourceToken>();
+    itr = sv2vst.entrySet().iterator();
+    while( itr.hasNext() ) {
+      Map.Entry                    me   = (Map.Entry)                    itr.next();
+      SVKey                        key  = (SVKey)                        me.getKey();
+      HashSet<VariableSourceToken> s1   = (HashSet<VariableSourceToken>) me.getValue();      
+      assert s1 != null;
+      
+      // the trueSet should have all entries in s1
+      assert trueSet.containsAll( s1 );
+
+      // s1 should not have anything that doesn't appear in trueset
+      Set<VariableSourceToken> sInt = (Set<VariableSourceToken>) s1.clone();
+      sInt.removeAll( trueSet );
+
+      assert sInt.isEmpty();
+
+      // add s1 to a running union--at the end check if trueSet has extra
+      trueSetByAlts.addAll( s1 );
+    }
+    // make sure trueSet isn't too big
+    assert trueSetByAlts.containsAll( trueSet );
+
+
+    // also check that the reference var sets are consistent
+    Hashtable<VariableSourceToken, Set<TempDescriptor> > vst2refVars =
+      new Hashtable<VariableSourceToken, Set<TempDescriptor> >();
+    itr = var2vst.entrySet().iterator();
+    while( itr.hasNext() ) {
+      Map.Entry                     me     = (Map.Entry)                    itr.next();
+      TempDescriptor                refVar = (TempDescriptor)               me.getKey();
+      HashSet<VariableSourceToken>  s1     = (HashSet<VariableSourceToken>) me.getValue();      
+      Iterator<VariableSourceToken> vstItr = s1.iterator();
+      while( vstItr.hasNext() ) {
+       VariableSourceToken vst = vstItr.next();
+       assert vst.getRefVars().contains( refVar );
+
+       Set<TempDescriptor> refVarsPart = vst2refVars.get( vst );
+       if( refVarsPart == null ) {
+         refVarsPart = new HashSet<TempDescriptor>();
+       }
+       refVarsPart.add( refVar );
+       vst2refVars.put( vst, refVarsPart );
+      }
+    }
+    itr = vst2refVars.entrySet().iterator();
+    while( itr.hasNext() ) {
+      Map.Entry           me  = (Map.Entry)           itr.next();
+      VariableSourceToken vst = (VariableSourceToken) me.getKey();
+      Set<TempDescriptor> s1  = (Set<TempDescriptor>) me.getValue();
+
+      assert vst.getRefVars().equals( s1 );
+    }    
+  }
+
+
+  public boolean equals( Object o ) {
+    if( o == null ) {
+      return false;
+    }
+
+    if( !(o instanceof VarSrcTokTable) ) {
+      return false;
+    }
+
+    VarSrcTokTable table = (VarSrcTokTable) o;
+    return trueSet.equals( table.trueSet );
+  }
+
+  public int hashCode() {
+    return trueSet.hashCode();
+  }
+
+  public Iterator<VariableSourceToken> iterator() {
+    return trueSet.iterator();
+  }
+
+  public String toString() {
+    return toStringPretty();
+  }
+
+  public String toStringVerbose() {
+    return "trueSet ="+trueSet.toString()+"\n"+
+           "sese2vst="+sese2vst.toString()+"\n"+
+           "var2vst ="+var2vst.toString()+"\n"+
+           "sv2vst  ="+sv2vst.toString();
+  }
+
+  public String toStringPretty() {
+    String tokHighlighter = "o";
+
+    String str = "VarSrcTokTable\n";
+    Iterator<VariableSourceToken> vstItr = trueSet.iterator();    
+    while( vstItr.hasNext() ) {
+      str += "   "+tokHighlighter+" "+vstItr.next()+"\n";
+    }
+    return str;
+  }
+
+  public String toStringPrettyVerbose() {
+    String tokHighlighter = "o";
+
+    String str = "VarSrcTokTable\n";
+
+    Set s;
+    Iterator itr; 
+    Iterator<VariableSourceToken> vstItr;
+
+    str += "  trueSet\n";
+    vstItr = trueSet.iterator();    
+    while( vstItr.hasNext() ) {
+      str += "     "+tokHighlighter+" "+vstItr.next()+"\n";
+    }
+
+    str += "  sese2vst\n";
+    itr = sese2vst.entrySet().iterator();
+    while( itr.hasNext() ) {
+      Map.Entry                    me   = (Map.Entry)                    itr.next();
+      FlatSESEEnterNode            sese = (FlatSESEEnterNode)            me.getKey();
+      HashSet<VariableSourceToken> s1   = (HashSet<VariableSourceToken>) me.getValue();      
+      assert s1 != null;
+
+      str += "    "+sese.getPrettyIdentifier()+" -> \n";
+
+      vstItr = s1.iterator();
+      while( vstItr.hasNext() ) {
+       str += "       "+tokHighlighter+" "+vstItr.next()+"\n";
+      }
+    }
+
+    str += "  var2vst\n";
+    itr = var2vst.entrySet().iterator();
+    while( itr.hasNext() ) {
+      Map.Entry                me  = (Map.Entry)                itr.next();
+      TempDescriptor           var = (TempDescriptor)           me.getKey();
+      Set<VariableSourceToken> s1  = (Set<VariableSourceToken>) me.getValue();
+      assert s1 != null;
+
+      str += "    "+var+" -> \n";
+
+      vstItr = s1.iterator();
+      while( vstItr.hasNext() ) {
+       str += "       "+tokHighlighter+" "+vstItr.next()+"\n";
+      }
+    }
+
+    str += "  sv2vst\n";
+    itr = sv2vst.entrySet().iterator();
+    while( itr.hasNext() ) {
+      Map.Entry                me  = (Map.Entry)                itr.next();
+      SVKey                    key = (SVKey)                    me.getKey();
+      Set<VariableSourceToken> s1  = (Set<VariableSourceToken>) me.getValue();
+      assert s1 != null;
+
+      str += "    "+key+" -> \n";
+
+      vstItr = s1.iterator();
+      while( vstItr.hasNext() ) {
+       str += "       "+tokHighlighter+" "+vstItr.next()+"\n";
+      }
+    }
+
+    return str;
+  }
+}
diff --git a/Robust/src/Analysis/OoOJava/VariableSourceToken.java b/Robust/src/Analysis/OoOJava/VariableSourceToken.java
new file mode 100644 (file)
index 0000000..1d84507
--- /dev/null
@@ -0,0 +1,82 @@
+package Analysis.OoOJava;
+
+import IR.*;
+import IR.Flat.*;
+import java.util.*;
+import java.io.*;
+
+public class VariableSourceToken {
+
+  private Set<TempDescriptor> refVars;
+  private FlatSESEEnterNode   sese;
+  private Integer             seseAge;
+  private TempDescriptor      addrVar; 
+
+  public VariableSourceToken( Set<TempDescriptor> refVars, 
+                              FlatSESEEnterNode   sese,                              
+                             Integer             seseAge, 
+                              TempDescriptor      addrVar 
+                              ) {
+    this.refVars = refVars;
+    this.sese    = sese;
+    this.seseAge = seseAge;
+    this.addrVar = addrVar; 
+  }
+
+  public Set<TempDescriptor> getRefVars() {
+    return refVars;
+  }
+
+  public FlatSESEEnterNode getSESE() {
+    return sese;
+  }
+
+  public Integer getAge() {
+    return seseAge;
+  }
+
+  public TempDescriptor getAddrVar() {
+    return addrVar;
+  }
+
+  public VariableSourceToken copy() {
+    Set<TempDescriptor> refVarsCopy = new HashSet<TempDescriptor>();
+
+    Iterator<TempDescriptor> rvItr = refVars.iterator();
+    while( rvItr.hasNext() ) {
+      refVarsCopy.add( rvItr.next() );
+    }
+
+    return new VariableSourceToken( refVarsCopy,
+                                    sese,
+                                    new Integer( seseAge ),
+                                    addrVar );
+  }
+
+  public boolean equals( Object o ) {
+    if( o == null ) {
+      return false;
+    }
+
+    if( !(o instanceof VariableSourceToken) ) {
+      return false;
+    }
+
+    VariableSourceToken vst = (VariableSourceToken) o;
+
+    // the reference vars have no bearing on equality
+    return    sese.equals( vst.sese    ) &&
+           addrVar.equals( vst.addrVar ) &&
+           seseAge.equals( vst.seseAge );
+  }
+
+  public int hashCode() {
+    // the reference vars have no bearing on hashCode
+    return (sese.hashCode() << 3) * (addrVar.hashCode() << 4) ^ seseAge.intValue();
+  }
+
+
+  public String toString() {
+    return refVars+"\tref "+addrVar+"\t@"+sese.toPrettyString()+"("+seseAge+")";
+  }
+}
index 51ebbeb670fad504c8e19f893d4cc9e0ba22f1e8..2bd8897b1ee23b09e2235e9cf62b5ebe0249fea7 100644 (file)
@@ -512,7 +512,8 @@ public class Main {
       CallGraph        cg = new CallGraph(state);
       Liveness         l  = new Liveness();
       ArrayReferencees ar = new ArrayReferencees(state);
-      OoOJavaAnalysis  oa = new OoOJavaAnalysis(state, tu, cg, l, ar);
+      DisjointAnalysis da = new DisjointAnalysis(state, tu, cg, l, ar);
+      OoOJavaAnalysis  oa = new OoOJavaAnalysis(state, tu, cg, da, l, ar);
     }