Adding the old tracker variable for debugging/testing purposes.
[jpf-core.git] / src / main / gov / nasa / jpf / listener / MethodTracker.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.jvm.bytecode.INVOKESPECIAL;
24 import gov.nasa.jpf.jvm.bytecode.JVMInvokeInstruction;
25 import gov.nasa.jpf.jvm.bytecode.VirtualInvocation;
26 import gov.nasa.jpf.search.Search;
27 import gov.nasa.jpf.vm.Instruction;
28 import gov.nasa.jpf.vm.MJIEnv;
29 import gov.nasa.jpf.vm.VM;
30 import gov.nasa.jpf.vm.MethodInfo;
31 import gov.nasa.jpf.vm.ThreadInfo;
32
33 import java.io.PrintWriter;
34
35 /**
36  * simple tool to log method invocations
37  *
38  * at this point, it doesn't do fancy things yet, but gives a more high
39  * level idea of what got executed by JPF than the ExecTracker
40  */
41 public class MethodTracker extends ListenerAdapter {
42
43   static final String INDENT = "  ";
44
45   MethodInfo lastMi;
46   PrintWriter out;
47
48   public MethodTracker (Config conf, JPF jpf) {
49     out = new PrintWriter(System.out, true);
50   }
51
52   void logMethodCall(ThreadInfo ti, MethodInfo mi, int stackDepth) {
53     out.print(ti.getId());
54     out.print(":");
55
56     for (int i=0; i<stackDepth%80; i++) {
57       out.print(INDENT);
58     }
59
60     if (mi.isMJI()) {
61       out.print("native ");
62     }
63
64     out.print(mi.getFullName());
65
66     if (ti.isFirstStepInsn()) {
67       out.print("...");
68     }
69
70     out.println();
71   }
72
73   @Override
74   public void executeInstruction (VM vm, ThreadInfo ti, Instruction insnToExecute) {
75     MethodInfo mi = insnToExecute.getMethodInfo();
76
77     if (mi != lastMi) {
78       logMethodCall(ti, mi, ti.getStackDepth());
79       lastMi = mi;
80
81     } else if (insnToExecute instanceof JVMInvokeInstruction) {
82       MethodInfo callee;
83
84       // that's the only little gist of it - if this is a VirtualInvocation,
85       // we have to dig the callee out by ourselves (it's not known
86       // before execution)
87
88       if (insnToExecute instanceof VirtualInvocation) {
89         VirtualInvocation callInsn = (VirtualInvocation)insnToExecute;
90         int objref = callInsn.getCalleeThis(ti);
91         if (objref != MJIEnv.NULL){
92           callee = callInsn.getInvokedMethod(ti, objref);
93         } else {
94           return; // this is causing a NPE, so don't report it as a unknown callee
95         }
96
97       } else if (insnToExecute instanceof INVOKESPECIAL) {
98         INVOKESPECIAL callInsn = (INVOKESPECIAL)insnToExecute;
99         callee = callInsn.getInvokedMethod(ti);
100
101       } else {
102         JVMInvokeInstruction callInsn = (JVMInvokeInstruction)insnToExecute;
103         callee = callInsn.getInvokedMethod(ti);
104       }
105
106       if (callee != null) {
107         if (callee.isMJI()) {
108           logMethodCall(ti, callee, ti.getStackDepth()+1);
109         }
110       } else {
111         out.println("ERROR: unknown callee of: " + insnToExecute);
112       }
113     }
114   }
115
116   /*
117    * those are not really required, but mark the transition boundaries
118    */
119   @Override
120   public void stateRestored(Search search) {
121     int id = search.getStateId();
122     out.println("----------------------------------- [" +
123                        search.getDepth() + "] restored: " + id);
124   }
125
126   //--- the ones we are interested in
127   @Override
128   public void searchStarted(Search search) {
129     out.println("----------------------------------- search started");
130   }
131
132   @Override
133   public void stateAdvanced(Search search) {
134     int id = search.getStateId();
135
136     out.print("----------------------------------- [" +
137                      search.getDepth() + "] forward: " + id);
138     if (search.isNewState()) {
139       out.print(" new");
140     } else {
141       out.print(" visited");
142     }
143
144     if (search.isEndState()) {
145       out.print(" end");
146     }
147
148     out.println();
149
150     lastMi = null;
151   }
152
153   @Override
154   public void stateBacktracked(Search search) {
155     int id = search.getStateId();
156
157     lastMi = null;
158
159     out.println("----------------------------------- [" +
160                        search.getDepth() + "] backtrack: " + id);
161   }
162
163   @Override
164   public void searchFinished(Search search) {
165     out.println("----------------------------------- search finished");
166   }
167
168 }