Adding the old tracker variable for debugging/testing purposes.
[jpf-core.git] / src / main / gov / nasa / jpf / listener / StackTracker.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.VM;
29 import gov.nasa.jpf.vm.MethodInfo;
30 import gov.nasa.jpf.vm.ThreadInfo;
31
32 import java.io.PrintWriter;
33
34 /**
35  * simple tool to log stack invocations
36  *
37  * at this point, it doesn't do fancy things yet, but gives a more high
38  * level idea of what got executed by JPF than the ExecTracker
39  */
40 public class StackTracker extends ListenerAdapter {
41
42   static final String INDENT = "  ";
43
44   MethodInfo lastMi;
45   PrintWriter out;
46   long nextLog;
47   int logPeriod;
48
49   public StackTracker (Config conf, JPF jpf) {
50     out = new PrintWriter(System.out, true);
51     logPeriod = conf.getInt("jpf.stack_tracker.log_period", 5000);
52   }
53
54   void logStack(ThreadInfo ti) {
55     long time = System.currentTimeMillis();
56
57     if (time < nextLog) {
58       return;
59     }
60
61     nextLog = time + logPeriod;
62
63     out.println();
64     out.print("Thread: ");
65     out.print(ti.getId());
66     out.println(":");
67
68     out.println(ti.getStackTrace());
69     out.println();
70   }
71
72   @Override
73   public void executeInstruction (VM vm, ThreadInfo ti, Instruction insnToExecute) {
74     MethodInfo mi = insnToExecute.getMethodInfo();
75
76     if (mi != lastMi) {
77       logStack(ti);
78       lastMi = mi;
79
80     } else if (insnToExecute instanceof JVMInvokeInstruction) {
81       MethodInfo callee;
82
83       // that's the only little gist of it - if this is a VirtualInvocation,
84       // we have to dig the callee out by ourselves (it's not known
85       // before execution)
86
87       if (insnToExecute instanceof VirtualInvocation) {
88         VirtualInvocation callInsn = (VirtualInvocation)insnToExecute;
89         int objref = callInsn.getCalleeThis(ti);
90         callee = callInsn.getInvokedMethod(ti, objref);
91
92       } else if (insnToExecute instanceof INVOKESPECIAL) {
93         INVOKESPECIAL callInsn = (INVOKESPECIAL)insnToExecute;
94         callee = callInsn.getInvokedMethod(ti);
95
96       } else {
97         JVMInvokeInstruction callInsn = (JVMInvokeInstruction)insnToExecute;
98         callee = callInsn.getInvokedMethod(ti);
99       }
100
101       if (callee != null) {
102         if (callee.isMJI()) {
103           logStack(ti);
104         }
105       } else {
106         out.println("ERROR: unknown callee of: " + insnToExecute);
107       }
108     }
109   }
110
111   @Override
112   public void stateAdvanced(Search search) {
113     lastMi = null;
114   }
115
116   @Override
117   public void stateBacktracked(Search search) {
118     lastMi = null;
119   }
120 }