60782a98e9b73615789c937a80326eaee3fbbfdd
[jpf-core.git] / src / main / gov / nasa / jpf / listener / StateReducer.java
1 /*
2  * Copyright (C) 2014, United States Government, as represented by the
3  * Administrator of the National Aeronautics and Space Administration.
4  * All rights reserved.
5  *
6  * The Java Pathfinder core (jpf-core) platform is licensed under the
7  * Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0.
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 package gov.nasa.jpf.listener;
19
20 import gov.nasa.jpf.Config;
21 import gov.nasa.jpf.JPF;
22 import gov.nasa.jpf.ListenerAdapter;
23 import gov.nasa.jpf.search.Search;
24 import gov.nasa.jpf.jvm.bytecode.*;
25 import gov.nasa.jpf.vm.*;
26 import gov.nasa.jpf.vm.bytecode.LocalVariableInstruction;
27 import gov.nasa.jpf.vm.bytecode.ReadInstruction;
28 import gov.nasa.jpf.vm.bytecode.StoreInstruction;
29 import gov.nasa.jpf.vm.bytecode.WriteInstruction;
30 import gov.nasa.jpf.vm.choice.IntIntervalGenerator;
31
32 import java.io.PrintWriter;
33
34 import java.util.*;
35
36 // TODO: Fix for Groovy's model-checking
37 // TODO: This is a listener created to detect device conflicts and global variable conflicts
38 /**
39  * Simple listener tool to track remove unwanted ChoiceGenerators that are registered
40  * while an existing ChoiceGenerator is being explored. Multiple ChoiceGenerators of the same
41  * type could be registered spuriously during a while(true) loop.
42  */
43 public class StateReducer extends ListenerAdapter {
44
45   private boolean debugMode;
46   private final PrintWriter out;
47   private String detail;
48   private int depth;
49   private int id;
50   private Transition transition;
51
52   // Holds values that have appeared during CG advances
53   private HashSet<Integer> cgChoiceSet;
54   private Integer choiceUpperBound;
55   private boolean isInitialized;
56
57   public StateReducer (Config config, JPF jpf) {
58     debugMode = config.getBoolean("debug_state_transition", false);
59     if (debugMode) {
60       out = new PrintWriter(System.out, true);
61     } else {
62       out = null;
63     }
64     detail = null;
65     depth = 0;
66     id = 0;
67     transition = null;
68     cgChoiceSet = new HashSet<>();
69     choiceUpperBound = 0;
70     isInitialized = false;
71   }
72
73   @Override
74   public void stateRestored(Search search) {
75     if (debugMode) {
76       id = search.getStateId();
77       depth = search.getDepth();
78       transition = search.getTransition();
79       detail = null;
80       out.println("\n==> DEBUG: The state is restored to state with id: " + id + " -- Transition: " + transition +
81               " and depth: " + depth + "\n");
82     }
83   }
84
85   //--- the ones we are interested in
86   @Override
87   public void searchStarted(Search search) {
88     if (debugMode) {
89       out.println("\n==> DEBUG: ----------------------------------- search started" + "\n");
90     }
91   }
92
93   @Override
94   public void choiceGeneratorSet (VM vm, ChoiceGenerator<?> newCG) {
95     // Initialize with necessary information from the CG
96     if (newCG instanceof IntIntervalGenerator) {
97       IntIntervalGenerator iigCG = (IntIntervalGenerator) newCG;
98       // Check if CG has been initialized, otherwise initialize it
99       if (!isInitialized) {
100         Integer[] choices = iigCG.getChoices();
101         // Get the upper bound from the last element of the choices
102         choiceUpperBound = choices[choices.length - 1];
103         isInitialized = true;
104       } else {
105         newCG.setDone();
106       }
107     }
108   }
109
110   @Override
111   public void choiceGeneratorAdvanced (VM vm, ChoiceGenerator<?> currentCG) {
112     // Check every choice generated and make sure that all the available choices
113     // are chosen first before repeating the same choice of value twice!
114     if (currentCG instanceof IntIntervalGenerator) {
115       IntIntervalGenerator iigCG = (IntIntervalGenerator) currentCG;
116       Integer nextChoice = iigCG.getNextChoice();
117       if (!cgChoiceSet.contains(nextChoice)) {
118         cgChoiceSet.add(nextChoice);
119       }
120       // Allow reinitialization after an upper bound is hit
121       // This means all available choices have been explored once during this iteration
122       if (cgChoiceSet.contains(choiceUpperBound)) {
123         isInitialized = false;
124         cgChoiceSet.clear();
125       }
126     }
127   }
128
129   @Override
130   public void stateAdvanced(Search search) {
131     if (debugMode) {
132       id = search.getStateId();
133       depth = search.getDepth();
134       transition = search.getTransition();
135       if (search.isNewState()) {
136         detail = "new";
137       } else {
138         detail = "visited";
139       }
140
141       if (search.isEndState()) {
142         out.println("\n==> DEBUG: This is the last state!\n");
143         detail += " end";
144       }
145       out.println("\n==> DEBUG: The state is forwarded to state with id: " + id + " with depth: " + depth +
146               " which is " + detail + " Transition: " + transition + "\n");
147     }
148   }
149
150   @Override
151   public void stateBacktracked(Search search) {
152     if (debugMode) {
153       id = search.getStateId();
154       depth = search.getDepth();
155       transition = search.getTransition();
156       detail = null;
157
158       out.println("\n==> DEBUG: The state is backtracked to state with id: " + id + " -- Transition: " + transition +
159               " and depth: " + depth + "\n");
160     }
161   }
162
163   @Override
164   public void searchFinished(Search search) {
165     if (debugMode) {
166       out.println("\n==> DEBUG: ----------------------------------- search finished" + "\n");
167     }
168   }
169 }