run ooojava and rcrpointer that print out effects and annotate them with the source...
[IRC.git] / Robust / src / Analysis / Disjoint / ProcessStateMachines.java
index 816c6e02bc4a3c566cbb7dfb7200aad6910c1f3e..0c29cdd184ac4a1e4cb46ca967e8ecbd5b36ff8e 100644 (file)
@@ -22,10 +22,11 @@ public class ProcessStateMachines {
     computeConflictEffects();
     prune();
     merge();
+    protectAgainstEvilTasks();
   }
 
   private void merge() {
-    for(Pair<FlatNode, TempDescriptor> machinepair: bsm.getAllMachineNames()) {
+    for(Pair<FlatNode, TempDescriptor> machinepair : bsm.getAllMachineNames()) {
       StateMachineForEffects sm=bsm.getStateMachine(machinepair);
       merge(sm);
     }
@@ -39,28 +40,28 @@ public class ProcessStateMachines {
     do {
       mergeAgain=false;
       HashMap<Pair<SMFEState, FieldDescriptor>, Set<SMFEState>> revMap=buildReverse(backMap);
-      for(Map.Entry<Pair<SMFEState,FieldDescriptor>, Set<SMFEState>> entry:revMap.entrySet()) {
-       if (entry.getValue().size()>1) {
-         SMFEState first=null;
-         for(SMFEState state:entry.getValue()) {
-           if (removedStates.contains(state))
-             continue;
-           if (first==null) {
-             first=state;
-           } else {
-             mergeAgain=true;
-             System.out.println("MERGING:"+first+" and "+state);
-             //Make sure we don't merge the initial state someplace else
-             if (state==sm.initialState) {
-               state=first;
-               first=sm.initialState;
-             }
-             mergeTwoStates(first, state, backMap);
-             removedStates.add(state);
-             sm.fn2state.remove(state.whereDefined);
-           }
-         }
-       }
+      for(Map.Entry<Pair<SMFEState,FieldDescriptor>, Set<SMFEState>> entry : revMap.entrySet()) {
+        if (entry.getValue().size()>1) {
+          SMFEState first=null;
+          for(SMFEState state : entry.getValue()) {
+            if (removedStates.contains(state))
+              continue;
+            if (first==null) {
+              first=state;
+            } else {
+              mergeAgain=true;
+              System.out.println("MERGING:"+first+" and "+state);
+              //Make sure we don't merge the initial state someplace else
+              if (state==sm.initialState) {
+                state=first;
+                first=sm.initialState;
+              }
+              mergeTwoStates(first, state, backMap);
+              removedStates.add(state);
+              sm.fn2state.remove(state.whereDefined);
+            }
+          }
+        }
       }
     } while(mergeAgain);
   }
@@ -68,12 +69,12 @@ public class ProcessStateMachines {
 
   private HashMap<Pair<SMFEState, FieldDescriptor>, Set<SMFEState>> buildReverse(HashMap<SMFEState, Set<Pair<SMFEState, FieldDescriptor>>> backMap) {
     HashMap<Pair<SMFEState, FieldDescriptor>, Set<SMFEState>> revMap=new HashMap<Pair<SMFEState, FieldDescriptor>, Set<SMFEState>>();
-    for(Map.Entry<SMFEState, Set<Pair<SMFEState, FieldDescriptor>>>entry:backMap.entrySet()) {
+    for(Map.Entry<SMFEState, Set<Pair<SMFEState, FieldDescriptor>>>entry : backMap.entrySet()) {
       SMFEState state=entry.getKey();
-      for(Pair<SMFEState, FieldDescriptor> pair:entry.getValue()) {
-       if (!revMap.containsKey(pair))
-         revMap.put(pair, new HashSet<SMFEState>());
-       revMap.get(pair).add(state);
+      for(Pair<SMFEState, FieldDescriptor> pair : entry.getValue()) {
+        if (!revMap.containsKey(pair))
+          revMap.put(pair, new HashSet<SMFEState>());
+        revMap.get(pair).add(state);
       }
     }
     return revMap;
@@ -88,53 +89,55 @@ public class ProcessStateMachines {
     backMap.get(state1).addAll(backMap.get(state2));
 
     //merge outgoing transitions
-    for(Map.Entry<Effect, Set<SMFEState>> entry:state2.e2states.entrySet()) {
+    for(Map.Entry<Effect, Set<SMFEState>> entry : state2.e2states.entrySet()) {
       Effect e=entry.getKey();
       Set<SMFEState> states=entry.getValue();
       if (state1.e2states.containsKey(e)) {
-       for(SMFEState statetoadd:states) {
-         if (!state1.e2states.get(e).add(statetoadd)) {
-           //already added...reduce reference count
-           statetoadd.refCount--;
-         }
-       }
+        for(SMFEState statetoadd : states) {
+          if (!state1.e2states.get(e).add(statetoadd)) {
+            //already added...reduce reference count
+            statetoadd.refCount--;
+          }
+        }
       } else {
-       state1.e2states.put(e, states);
+        state1.e2states.put(e, states);
       }
       Set<SMFEState> states1=state1.e2states.get(e);
 
       //move now-self edges
       if (states1.contains(state2)) {
-       states1.remove(state2);
-       states1.add(state1);
+        states1.remove(state2);
+        states1.add(state1);
       }
 
       //fix up the backmap of the edges we point to
-      for(SMFEState st:states1) {
-       HashSet<Pair<SMFEState, FieldDescriptor>> toRemove=new HashSet<Pair<SMFEState, FieldDescriptor>>();
-       HashSet<Pair<SMFEState, FieldDescriptor>> toAdd=new HashSet<Pair<SMFEState, FieldDescriptor>>();
-       for(Pair<SMFEState, FieldDescriptor> backpair:backMap.get(st)) {
-         if (backpair.getFirst()==state2) {
-           Pair<SMFEState, FieldDescriptor> newpair=new Pair<SMFEState, FieldDescriptor>(state1, backpair.getSecond());
-           toRemove.add(backpair);
-           toAdd.add(newpair);
-         }
-       }
-       backMap.get(st).removeAll(toRemove);
-       backMap.get(st).addAll(toAdd);
+      for(SMFEState st : states1) {
+        HashSet<Pair<SMFEState, FieldDescriptor>> toRemove=new HashSet<Pair<SMFEState, FieldDescriptor>>();
+        HashSet<Pair<SMFEState, FieldDescriptor>> toAdd=new HashSet<Pair<SMFEState, FieldDescriptor>>();
+        for(Pair<SMFEState, FieldDescriptor> backpair : backMap.get(st)) {
+          if (backpair.getFirst()==state2) {
+            Pair<SMFEState, FieldDescriptor> newpair=new Pair<SMFEState, FieldDescriptor>(state1, backpair.getSecond());
+            toRemove.add(backpair);
+            toAdd.add(newpair);
+          }
+        }
+        backMap.get(st).removeAll(toRemove);
+        backMap.get(st).addAll(toAdd);
       }
     }
 
     //Fix up our new incoming edges
-    for(Pair<SMFEState,FieldDescriptor> fromStatePair:backMap.get(state2)) {
+    for(Pair<SMFEState,FieldDescriptor> fromStatePair : backMap.get(state2)) {
       SMFEState fromState=fromStatePair.getFirst();
-      for(Map.Entry<Effect, Set<SMFEState>> fromEntry:fromState.e2states.entrySet()) {
-       Effect e=fromEntry.getKey();
-       Set<SMFEState> states=fromEntry.getValue();
-       if (states.contains(state2)) {
-         states.remove(state2);
-         states.add(state1);
-       }
+      for(Map.Entry<Effect, Set<SMFEState>> fromEntry : fromState.e2states.entrySet()) {
+        Effect e=fromEntry.getKey();
+        Set<SMFEState> states=fromEntry.getValue();
+        if (states.contains(state2)) {
+          states.remove(state2);
+          if(states.add(state1) && !fromState.equals(state2)) {
+            state1.refCount++;
+          }
+        }
       }
     }
     //Clear out unreachable state's backmap
@@ -143,7 +146,7 @@ public class ProcessStateMachines {
 
 
   private void prune() {
-    for(Pair<FlatNode, TempDescriptor> machinepair: bsm.getAllMachineNames()) {
+    for(Pair<FlatNode, TempDescriptor> machinepair : bsm.getAllMachineNames()) {
       StateMachineForEffects sm=bsm.getStateMachine(machinepair);
       pruneNonConflictingStates(sm);
       pruneEffects(sm);
@@ -151,46 +154,46 @@ public class ProcessStateMachines {
   }
 
   private void pruneEffects(StateMachineForEffects sm) {
-    for(Iterator<FlatNode> fnit=sm.fn2state.keySet().iterator(); fnit.hasNext();) {
+    for(Iterator<FlatNode> fnit=sm.fn2state.keySet().iterator(); fnit.hasNext(); ) {
       FlatNode fn=fnit.next();
       SMFEState state=sm.fn2state.get(fn);
-      for(Iterator<Effect> efit=state.effects.iterator();efit.hasNext();) {
-       Effect e=efit.next();
-       //Is it a conflicting effecting
-       if (state.getConflicts().contains(e))
-         continue;
-       //Does it still have transitions
-       if (state.e2states.containsKey(e))
-         continue;
-       //If no to both, remove it
-       efit.remove();
+      for(Iterator<Effect> efit=state.effects.iterator(); efit.hasNext(); ) {
+        Effect e=efit.next();
+        //Is it a conflicting effecting
+        if (state.getConflicts().contains(e))
+          continue;
+        //Does it still have transitions
+        if (state.e2states.containsKey(e))
+          continue;
+        //If no to both, remove it
+        efit.remove();
       }
     }
   }
 
   private void pruneNonConflictingStates(StateMachineForEffects sm) {
     Set<SMFEState> canReachConflicts=buildConflictsAndMap(sm);
-    for(Iterator<FlatNode> fnit=sm.fn2state.keySet().iterator(); fnit.hasNext();) {
+    for(Iterator<FlatNode> fnit=sm.fn2state.keySet().iterator(); fnit.hasNext(); ) {
       FlatNode fn=fnit.next();
       SMFEState state=sm.fn2state.get(fn);
       if (canReachConflicts.contains(state)) {
-       for(Iterator<Effect> efit=state.e2states.keySet().iterator(); efit.hasNext();) {
-         Effect e=efit.next();
-         Set<SMFEState> stateset=state.e2states.get(e);
-         for(Iterator<SMFEState> stit=stateset.iterator(); stit.hasNext();) {
-           SMFEState tostate=stit.next();
-           if(!canReachConflicts.contains(tostate))
-             stit.remove();
-         }
-         if (stateset.isEmpty())
-           efit.remove();
-       }
+        for(Iterator<Effect> efit=state.e2states.keySet().iterator(); efit.hasNext(); ) {
+          Effect e=efit.next();
+          Set<SMFEState> stateset=state.e2states.get(e);
+          for(Iterator<SMFEState> stit=stateset.iterator(); stit.hasNext(); ) {
+            SMFEState tostate=stit.next();
+            if(!canReachConflicts.contains(tostate))
+              stit.remove();
+          }
+          if (stateset.isEmpty())
+            efit.remove();
+        }
       } else {
-       fnit.remove();
+        fnit.remove();
       }
     }
   }
-  
+
   private HashMap<SMFEState, Set<Pair<SMFEState, FieldDescriptor>>> buildBackMap(StateMachineForEffects sm) {
     return buildBackMap(sm, null);
   }
@@ -203,23 +206,23 @@ public class ProcessStateMachines {
     while(!toprocess.isEmpty()) {
       SMFEState state=toprocess.pop();
       if (!state.getConflicts().isEmpty()&&conflictStates!=null) {
-       conflictStates.add(state);
+        conflictStates.add(state);
       }
-      for(Effect e:state.getEffectsAllowed()) {
-       for(SMFEState stateout:state.transitionsTo(e)) {
-         if (!backMap.containsKey(stateout)) {
-           toprocess.add(stateout);
-           backMap.put(stateout, new HashSet<Pair<SMFEState,FieldDescriptor>>());
-         }
-         Pair<SMFEState, FieldDescriptor> p=new Pair<SMFEState, FieldDescriptor>(state, e.getField());
-         backMap.get(stateout).add(p);
-       }
+      for(Effect e : state.getEffectsAllowed()) {
+        for(SMFEState stateout : state.transitionsTo(e)) {
+          if (!backMap.containsKey(stateout)) {
+            toprocess.add(stateout);
+            backMap.put(stateout, new HashSet<Pair<SMFEState,FieldDescriptor>>());
+          }
+          Pair<SMFEState, FieldDescriptor> p=new Pair<SMFEState, FieldDescriptor>(state, e.getField());
+          backMap.get(stateout).add(p);
+        }
       }
     }
     return backMap;
   }
 
-  
+
   private Set<SMFEState> buildConflictsAndMap(StateMachineForEffects sm) {
     Set<SMFEState> conflictStates=new HashSet<SMFEState>();
     HashMap<SMFEState, Set<Pair<SMFEState,FieldDescriptor>>> backMap=buildBackMap(sm, conflictStates);
@@ -231,75 +234,112 @@ public class ProcessStateMachines {
     while(!toprocess.isEmpty()) {
       SMFEState state=toprocess.pop();
 
-      for(Pair<SMFEState,FieldDescriptor> instatepair:backMap.get(state)) {
-       SMFEState instate=instatepair.getFirst();
-       if (!canReachConflicts.contains(instate)) {
-         toprocess.add(instate);
-         canReachConflicts.add(instate);
-       }
+      for(Pair<SMFEState,FieldDescriptor> instatepair : backMap.get(state)) {
+        SMFEState instate=instatepair.getFirst();
+        if (!canReachConflicts.contains(instate)) {
+          toprocess.add(instate);
+          canReachConflicts.add(instate);
+        }
       }
     }
     return canReachConflicts;
   }
-  
+
   private void groupStateMachines() {
-    for(Pair<FlatNode, TempDescriptor> machinePair: bsm.getAllMachineNames()) {
+    for(Pair<FlatNode, TempDescriptor> machinePair : bsm.getAllMachineNames()) {
       FlatNode fn=machinePair.getFirst();
       StateMachineForEffects sm=bsm.getStateMachine(machinePair);
       Set<FlatSESEEnterNode> taskSet=taskAnalysis.getPossibleExecutingRBlocks(fn);
-      for(FlatSESEEnterNode sese:taskSet) {
-       if (!groupMap.containsKey(sese))
-         groupMap.put(sese, new HashSet<StateMachineForEffects>());
-       groupMap.get(sese).add(sm);
+      for(FlatSESEEnterNode sese : taskSet) {
+        if (!groupMap.containsKey(sese))
+          groupMap.put(sese, new HashSet<StateMachineForEffects>());
+        groupMap.get(sese).add(sm);
       }
     }
   }
 
   private void computeConflictEffects() {
     //Loop through all state machines
-    for(Pair<FlatNode, TempDescriptor> machinePair: bsm.getAllMachineNames()) {
+    for(Pair<FlatNode, TempDescriptor> machinePair : bsm.getAllMachineNames()) {
       FlatNode fn=machinePair.getFirst();
       StateMachineForEffects sm=bsm.getStateMachine(machinePair);
       Set<FlatSESEEnterNode> taskSet=taskAnalysis.getPossibleExecutingRBlocks(fn);
-      for(FlatSESEEnterNode sese:taskSet) {
-       Set<StateMachineForEffects> smgroup=groupMap.get(sese);
-       computeConflictingEffects(sm, smgroup);
+      for(FlatSESEEnterNode sese : taskSet) {
+        Set<StateMachineForEffects> smgroup=groupMap.get(sese);
+        computeConflictingEffects(sm, smgroup);
       }
     }
   }
-  
+
   private void computeConflictingEffects(StateMachineForEffects sm, Set<StateMachineForEffects> smgroup) {
     boolean isStall=sm.getStallorSESE().kind()!=FKind.FlatSESEEnterNode;
-    for(SMFEState state:sm.getStates()) {
-      for(Effect e:state.getEffectsAllowed()) {
-       Alloc a=e.getAffectedAllocSite();
-       FieldDescriptor fd=e.getField();
-       int type=e.getType();
-       boolean hasConflict=false;
-       if (!isStall&&Effect.isWrite(type)) {
-         hasConflict=true;
-       } else {
-         for(StateMachineForEffects othersm:smgroup) {
-           boolean otherIsStall=othersm.getStallorSESE().kind()!=FKind.FlatSESEEnterNode;
-           //Stall sites can't conflict with each other
-           if (isStall&&otherIsStall) continue;
-
-           int effectType=othersm.getEffects(a, fd);
-           if (Effect.isWrite(type)&&effectType!=0) {
-             //Original effect is a write and we have some effect on the same field/alloc site
-             hasConflict=true;
-             break;
-           }
-           if (Effect.isWrite(effectType)) {
-             //We are a write
-             hasConflict=true;
-             break;
-           }
-         }
-       }
-       if (hasConflict) {
-         state.addConflict(e);
-       }
+    for(SMFEState state : sm.getStates()) {
+      for(Effect e : state.getEffectsAllowed()) {
+        Alloc a=e.getAffectedAllocSite();
+        FieldDescriptor fd=e.getField();
+        int type=e.getType();
+        boolean hasConflict=false;
+        if (!isStall&&Effect.isWrite(type)) {
+          hasConflict=true;
+        } else {
+          for(StateMachineForEffects othersm : smgroup) {
+            boolean otherIsStall=othersm.getStallorSESE().kind()!=FKind.FlatSESEEnterNode;
+            //Stall sites can't conflict with each other
+            if (isStall&&otherIsStall) continue;
+
+            int effectType=othersm.getEffects(a, fd);
+            if (Effect.isWrite(type)&&effectType!=0) {
+              //Original effect is a write and we have some effect on the same field/alloc site
+              hasConflict=true;
+              break;
+            }
+            if (Effect.isWrite(effectType)) {
+              //We are a write
+              hasConflict=true;
+              break;
+            }
+          }
+        }
+        if (hasConflict) {
+          state.addConflict(e);
+        }
+      }
+    }
+  }
+
+
+  private void protectAgainstEvilTasks() {
+    for( Pair<FlatNode, TempDescriptor> machinepair : bsm.getAllMachineNames() ) {
+      StateMachineForEffects sm = bsm.getStateMachine(machinepair);
+      protectAgainstEvilTasks(sm);
+    }
+  }
+
+  private void protectAgainstEvilTasks(StateMachineForEffects sm) {
+    // first identify the set of <Alloc, Field> pairs for which this
+    // traverser will both read and write, remember the read effect
+    Set<Effect> allocAndFieldRW = new HashSet<Effect>();
+    for( Pair<Alloc, FieldDescriptor> af : sm.effectsMap.keySet() ) {
+      Integer effectType = sm.effectsMap.get(af);
+      if( (effectType & Effect.read)  != 0 &&
+          (effectType & Effect.write) != 0
+          ) {
+        allocAndFieldRW.add( new Effect( af.getFirst(),
+                                         Effect.read,
+                                         af.getSecond(),
+                                         null )
+                             );
+      }
+    }
+
+    // next check the state machine: if an effect that initiates
+    // a transition is in the allocAndFieldRW set, then mark it
+    // as... POSSIBLY EVIL!!!!!
+    for( SMFEState state : sm.getStates() ) {
+      for( Effect effect : state.getTransitionEffects() ) {
+        if( allocAndFieldRW.contains(effect) ) {
+          sm.addPossiblyEvilEffect(effect);
+        }
       }
     }
   }