Fixing a bug: separating the state tracking for cycle analysis.
authorrtrimana <rtrimana@uci.edu>
Wed, 15 Apr 2020 06:53:59 +0000 (23:53 -0700)
committerrtrimana <rtrimana@uci.edu>
Wed, 15 Apr 2020 06:53:59 +0000 (23:53 -0700)
src/main/gov/nasa/jpf/listener/DPORStateReducer.java

index c8c7806..0c513f2 100644 (file)
@@ -76,7 +76,8 @@ public class DPORStateReducer extends ListenerAdapter {
   private HashMap<Integer, HashSet<Integer>> conflictPairMap;     // Record conflicting events
   private HashSet<String> doneBacktrackSet;                       // Record state ID and trace already constructed
   private HashMap<Integer, ReadWriteSet> readWriteFieldsMap;      // Record fields that are accessed
-  private HashMap<Integer, RestorableState> restorableStateMap;   // Maps state IDs to the restorable state object
+  private HashMap<Integer, RestorableVMState> restorableStateMap; // Maps state IDs to the restorable state object
+  private HashMap<Integer, Integer> stateToChoiceCounterMap;      // Maps state IDs to the choice counter
 
   // Boolean states
   private boolean isBooleanCGFlipped;
@@ -365,25 +366,6 @@ public class DPORStateReducer extends ListenerAdapter {
     }
   }
 
-  // This class compactly stores: 1) restorable VM state, and 2) global choice counter
-  private class RestorableState {
-    private RestorableVMState restorableState;
-    private int choiceCounter;
-
-    public RestorableState (RestorableVMState restState, int choCtr) {
-      restorableState = restState;
-      choiceCounter = choCtr;
-    }
-
-    public RestorableVMState getRestorableState() {
-      return restorableState;
-    }
-
-    public int getChoiceCounter() {
-      return choiceCounter;
-    }
-  }
-
   // -- CONSTANTS
   private final static String DO_CALL_METHOD = "doCall";
   // We exclude fields that come from libraries (Java and Groovy), and also the infrastructure
@@ -421,7 +403,11 @@ public class DPORStateReducer extends ListenerAdapter {
     backtrackPointList.add(new BacktrackPoint(icsCG, stateId, refChoices[choiceIndex]));
     // Store restorable state object for this state (always store the latest)
     RestorableVMState restorableState = vm.getRestorableState();
-    restorableStateMap.put(stateId, new RestorableState(restorableState, choiceCounter));
+    restorableStateMap.put(stateId, restorableState);
+    // Map multiple state IDs to a choice counter
+    for (Integer stId : justVisitedStates) {
+      stateToChoiceCounterMap.put(stId, choiceCounter);
+    }
   }
 
   private Integer[] copyChoices(Integer[] choicesToCopy) {
@@ -474,6 +460,7 @@ public class DPORStateReducer extends ListenerAdapter {
     conflictPairMap = new HashMap<>();
     doneBacktrackSet = new HashSet<>();
     readWriteFieldsMap = new HashMap<>();
+    stateToChoiceCounterMap = new HashMap<>();
     // Booleans
     isEndOfExecution = false;
   }
@@ -683,7 +670,7 @@ public class DPORStateReducer extends ListenerAdapter {
                        int hiStateId = backtrackStateQ.peek();
                        // Restore the state first if necessary
                        if (vm.getStateId() != hiStateId) {
-                               RestorableVMState restorableState = restorableStateMap.get(hiStateId).getRestorableState();
+                               RestorableVMState restorableState = restorableStateMap.get(hiStateId);
                                vm.restoreState(restorableState);
                        }
                        // Set the backtrack CG
@@ -848,21 +835,19 @@ public class DPORStateReducer extends ListenerAdapter {
   // 2) We need to analyze and find conflicts for the reachable choices/events in the cycle
   // 3) Then we create a new backtrack point for every new conflict
   private void analyzeReachabilityAndCreateBacktrackPoints(VM vm, int stateId) {
-    // Perform this analysis only when there is a state match
-    if (!vm.isNewState()) {
-      if (restorableStateMap.containsKey(stateId)) {
-        // Find the choice/event that marks the start of this cycle: first choice we explore for conflicts
-        int conflictChoice = restorableStateMap.get(stateId).getChoiceCounter();
-        int currentChoice = choiceCounter - 1;
-        // Find conflicts between choices/events in this cycle (we scan forward in the cycle, not backward)
-        while (conflictChoice < currentChoice) {
-          for (int eventCounter = conflictChoice + 1; eventCounter <= currentChoice; eventCounter++) {
-            if (isConflictFound(eventCounter, conflictChoice) && isNewConflict(conflictChoice, eventCounter)) {
-              createBacktrackingPoint(conflictChoice, eventCounter);
-            }
+    // Perform this analysis only when there is a state match and state > 0 (state 0 is for boolean CG)
+    if (!vm.isNewState() && (stateId > 0)) {
+      // Find the choice/event that marks the start of this cycle: first choice we explore for conflicts
+      int conflictChoice = stateToChoiceCounterMap.get(stateId);
+      int currentChoice = choiceCounter - 1;
+      // Find conflicts between choices/events in this cycle (we scan forward in the cycle, not backward)
+      while (conflictChoice < currentChoice) {
+        for (int eventCounter = conflictChoice + 1; eventCounter <= currentChoice; eventCounter++) {
+          if (isConflictFound(eventCounter, conflictChoice) && isNewConflict(conflictChoice, eventCounter)) {
+            createBacktrackingPoint(conflictChoice, eventCounter);
           }
-          conflictChoice++;
         }
+        conflictChoice++;
       }
     }
   }