1 /*
2  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  *
23  */
24 
25 #ifndef SHARE_VM_RUNTIME_FPROFILER_HPP
26 #define SHARE_VM_RUNTIME_FPROFILER_HPP
27 
28 #include "utilities/macros.hpp"
29 #include "runtime/timer.hpp"
30 
31 // a simple flat profiler for Java
32 
33 
34 // Forward declaration of classes defined in this header file
35 class ThreadProfiler;
36 class ThreadProfilerMark;
37 class FlatProfiler;
38 class IntervalData;
39 
40 // Declarations of classes defined only in the implementation.
41 class ProfilerNode;
42 class FlatProfilerTask;
43 
44 enum TickPosition {
45   tp_code,
46   tp_native
47 };
48 
49 // One of these guys is constructed as we enter interesting regions
50 // and destructed as we exit the region.  While we are in the region
51 // ticks are allotted to the region.
52 class ThreadProfilerMark: public StackObj {
53 public:
54   // For now, the only thread-specific region is the class loader.
55   enum Region { noRegion, classLoaderRegion, extraRegion, maxRegion };
56 
57   ThreadProfilerMark(Region)  NOT_FPROF_RETURN;
58   ~ThreadProfilerMark()       NOT_FPROF_RETURN;
59 
60 private:
61   ThreadProfiler* _pp;
62   Region _r;
63 };
64 
65 #if INCLUDE_FPROF
66 
67 class IntervalData VALUE_OBJ_CLASS_SPEC {
68   // Just to keep these things all together
69 private:
70   int _interpreted;
71   int _compiled;
72   int _native;
73   int _compiling;
74 public:
interpreted()75   int interpreted() {
76     return _interpreted;
77   }
compiled()78   int compiled() {
79     return _compiled;
80   }
native()81   int native() {
82     return _native;
83   }
compiling()84   int compiling() {
85     return _compiling;
86   }
total()87   int total() {
88     return (interpreted() + compiled() + native() + compiling());
89   }
inc_interpreted()90   void inc_interpreted() {
91     _interpreted += 1;
92   }
inc_compiled()93   void inc_compiled() {
94     _compiled += 1;
95   }
inc_native()96   void inc_native() {
97     _native += 1;
98   }
inc_compiling()99   void inc_compiling() {
100     _compiling += 1;
101   }
reset()102   void reset() {
103     _interpreted = 0;
104     _compiled = 0;
105     _native = 0;
106     _compiling = 0;
107   }
108   static void print_header(outputStream* st);
109   void print_data(outputStream* st);
110 };
111 #endif // INCLUDE_FPROF
112 
113 class ThreadProfiler: public CHeapObj<mtInternal> {
114 public:
115   ThreadProfiler()    NOT_FPROF_RETURN;
116   ~ThreadProfiler()   NOT_FPROF_RETURN;
117 
118   // Resets the profiler
119   void reset()        NOT_FPROF_RETURN;
120 
121   // Activates the profiler for a certain thread
122   void engage()       NOT_FPROF_RETURN;
123 
124   // Deactivates the profiler
125   void disengage()    NOT_FPROF_RETURN;
126 
127   // Prints the collected profiling information
128   void print(const char* thread_name) NOT_FPROF_RETURN;
129 
130   // Garbage Collection Support
131   void oops_do(OopClosure* f)         NOT_FPROF_RETURN;
132 
133 #if INCLUDE_FPROF
134 private:
135   // for recording ticks.
136   friend class ProfilerNode;
137   char* area_bottom; // preallocated area for pnodes
138   char* area_top;
139   char* area_limit;
140   static int            table_size;
141   ProfilerNode** table;
142 
143 private:
144   void record_interpreted_tick(JavaThread* thread, frame fr, TickPosition where, int* ticks);
145   void record_compiled_tick   (JavaThread* thread, frame fr, TickPosition where);
146   void interpreted_update(Method* method, TickPosition where);
147   void compiled_update   (Method* method, TickPosition where);
148   void stub_update       (Method* method, const char* name, TickPosition where);
149   void adapter_update    (TickPosition where);
150 
151   void runtime_stub_update(const CodeBlob* stub, const char* name, TickPosition where);
152   void unknown_compiled_update    (const CodeBlob* cb, TickPosition where);
153 
154   void vm_update    (TickPosition where);
155   void vm_update    (const char* name, TickPosition where);
156 
157   void record_tick_for_running_frame(JavaThread* thread, frame fr);
158   void record_tick_for_calling_frame(JavaThread* thread, frame fr);
159 
160   void initialize();
161 
162   static int  entry(int value);
163 
164 
165 private:
166   friend class FlatProfiler;
167   void record_tick(JavaThread* thread);
168   bool engaged;
169   // so we can do percentages for this thread, and quick checks for activity
170   int thread_ticks;
171   int compiler_ticks;
172   int interpreter_ticks;
173 
174 public:
inc_thread_ticks()175   void inc_thread_ticks() { thread_ticks += 1; }
176 
177 private:
178   friend class ThreadProfilerMark;
179   // counters for thread-specific regions
180   bool region_flag[ThreadProfilerMark::maxRegion];
181   int class_loader_ticks;
182   int extra_ticks;
183 
184 private:
185   // other thread-specific regions
186   int blocked_ticks;
187   enum UnknownTickSites {
188       ut_null_method,
189       ut_vtable_stubs,
190       ut_running_frame,
191       ut_calling_frame,
192       ut_no_pc,
193       ut_no_last_Java_frame,
194       ut_unknown_thread_state,
195       ut_end
196   };
197   int unknown_ticks_array[ut_end];
unknown_ticks()198   int unknown_ticks() {
199     int result = 0;
200     for (int ut = 0; ut < ut_end; ut += 1) {
201       result += unknown_ticks_array[ut];
202     }
203     return result;
204   }
205 
206   elapsedTimer timer;
207 
208   // For interval timing
209 private:
210   IntervalData _interval_data;
interval_data()211   IntervalData interval_data() {
212     return _interval_data;
213   }
interval_data_ref()214   IntervalData* interval_data_ref() {
215     return &_interval_data;
216   }
217 #endif // INCLUDE_FPROF
218 };
219 
220 class FlatProfiler: AllStatic {
221 public:
222   static void reset() NOT_FPROF_RETURN ;
223   static void engage(JavaThread* mainThread, bool fullProfile) NOT_FPROF_RETURN ;
224   static void disengage() NOT_FPROF_RETURN ;
225   static void print(int unused) NOT_FPROF_RETURN ;
226   static bool is_active() NOT_FPROF_RETURN_(false) ;
227 
228   // This is NULL if each thread has its own thread profiler,
229   // else this is the single thread profiler used by all threads.
230   // In particular it makes a difference during garbage collection,
231   // where you only want to traverse each thread profiler once.
232   static ThreadProfiler* get_thread_profiler() NOT_FPROF_RETURN_(NULL);
233 
234   // Garbage Collection Support
235   static void oops_do(OopClosure* f) NOT_FPROF_RETURN ;
236 
237   // Support for disassembler to inspect the PCRecorder
238 
239   // Returns the start address for a given pc
240   // NULL is returned if the PCRecorder is inactive
241   static address bucket_start_for(address pc) NOT_FPROF_RETURN_(NULL);
242 
243   enum { MillisecsPerTick = 10 };   // ms per profiling ticks
244 
245   // Returns the number of ticks recorded for the bucket
246   // pc belongs to.
247   static int bucket_count_for(address pc) NOT_FPROF_RETURN_(0);
248 
249 #if INCLUDE_FPROF
250 
251  private:
full_profile()252   static bool full_profile() {
253     return full_profile_flag;
254   }
255 
256   friend class ThreadProfiler;
257   // the following group of ticks cover everything that's not attributed to individual Java methods
258   static int  received_gc_ticks;      // ticks during which gc was active
259   static int vm_operation_ticks;      // total ticks in vm_operations other than GC
260   static int threads_lock_ticks;      // the number of times we couldn't get the Threads_lock without blocking
261   static int      blocked_ticks;      // ticks when the thread was blocked.
262   static int class_loader_ticks;      // total ticks in class loader
263   static int        extra_ticks;      // total ticks an extra temporary measuring
264   static int     compiler_ticks;      // total ticks in compilation
265   static int  interpreter_ticks;      // ticks in unknown interpreted method
266   static int        deopt_ticks;      // ticks in deoptimization
267   static int      unknown_ticks;      // ticks that cannot be categorized
268   static int     received_ticks;      // ticks that were received by task
269   static int    delivered_ticks;      // ticks that were delivered by task
non_method_ticks()270   static int non_method_ticks() {
271     return
272       ( received_gc_ticks
273       + vm_operation_ticks
274       + deopt_ticks
275       + threads_lock_ticks
276       + blocked_ticks
277       + compiler_ticks
278       + interpreter_ticks
279       + unknown_ticks );
280   }
281   static elapsedTimer timer;
282 
283   // Counts of each of the byte codes
284   static int*           bytecode_ticks;
285   static int*           bytecode_ticks_stub;
286   static void print_byte_code_statistics();
287 
288   // the ticks below are for continuous profiling (to adjust recompilation, etc.)
289   static int          all_ticks;      // total count of ticks received so far
290   static int      all_int_ticks;      // ticks in interpreter
291   static int     all_comp_ticks;      // ticks in compiled code (+ native)
292   static bool full_profile_flag;      // collecting full profile?
293 
294   // to accumulate thread-specific data
295   // if we aren't profiling individual threads.
296   static ThreadProfiler* thread_profiler;
297   static ThreadProfiler* vm_thread_profiler;
298 
299   static void allocate_table();
300 
301   // The task that periodically interrupts things.
302   friend class FlatProfilerTask;
303   static FlatProfilerTask* task;
304   static void record_vm_operation();
305   static void record_vm_tick();
306   static void record_thread_ticks();
307 
308   // For interval analysis
309  private:
310   static int interval_ticks_previous;  // delivered_ticks from the last interval
311   static void interval_record_thread(ThreadProfiler* tp); // extract ticks from ThreadProfiler.
312   static void interval_print();       // print interval data.
313   static void interval_reset();       // reset interval data.
314   enum {interval_print_size = 10};
315   static IntervalData* interval_data;
316 #endif // INCLUDE_FPROF
317 };
318 
319 #endif // SHARE_VM_RUNTIME_FPROFILER_HPP
320