return asSetTotal;
}
+ public Set<Descriptor> getDescriptorsToAnalyze() {
+ return descriptorsToAnalyze;
+ }
--- /dev/null
+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;
+ }
+}
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
+ }
+
}
--- /dev/null
+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+"]";
+ }
+}
--- /dev/null
+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;
+ }
+}
--- /dev/null
+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;
+ }
+}
--- /dev/null
+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+")";
+ }
+}
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);
}