duke@435: /* mikael@6198: * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. duke@435: * duke@435: */ duke@435: stefank@2314: #ifndef SHARE_VM_RUNTIME_FPROFILER_HPP stefank@2314: #define SHARE_VM_RUNTIME_FPROFILER_HPP stefank@2314: jprovino@4542: #include "utilities/macros.hpp" stefank@2314: #include "runtime/timer.hpp" stefank@2314: duke@435: // a simple flat profiler for Java duke@435: duke@435: duke@435: // Forward declaration of classes defined in this header file duke@435: class ThreadProfiler; duke@435: class ThreadProfilerMark; duke@435: class FlatProfiler; duke@435: class IntervalData; duke@435: duke@435: // Declarations of classes defined only in the implementation. duke@435: class ProfilerNode; duke@435: class FlatProfilerTask; duke@435: duke@435: enum TickPosition { duke@435: tp_code, duke@435: tp_native duke@435: }; duke@435: duke@435: // One of these guys is constructed as we enter interesting regions duke@435: // and destructed as we exit the region. While we are in the region duke@435: // ticks are allotted to the region. duke@435: class ThreadProfilerMark: public StackObj { duke@435: public: duke@435: // For now, the only thread-specific region is the class loader. duke@435: enum Region { noRegion, classLoaderRegion, extraRegion, maxRegion }; duke@435: jprovino@4165: ThreadProfilerMark(Region) NOT_FPROF_RETURN; jprovino@4165: ~ThreadProfilerMark() NOT_FPROF_RETURN; duke@435: duke@435: private: duke@435: ThreadProfiler* _pp; duke@435: Region _r; duke@435: }; duke@435: jprovino@4165: #if INCLUDE_FPROF duke@435: duke@435: class IntervalData VALUE_OBJ_CLASS_SPEC { duke@435: // Just to keep these things all together duke@435: private: duke@435: int _interpreted; duke@435: int _compiled; duke@435: int _native; duke@435: int _compiling; duke@435: public: duke@435: int interpreted() { duke@435: return _interpreted; duke@435: } duke@435: int compiled() { duke@435: return _compiled; duke@435: } duke@435: int native() { duke@435: return _native; duke@435: } duke@435: int compiling() { duke@435: return _compiling; duke@435: } duke@435: int total() { duke@435: return (interpreted() + compiled() + native() + compiling()); duke@435: } duke@435: void inc_interpreted() { duke@435: _interpreted += 1; duke@435: } duke@435: void inc_compiled() { duke@435: _compiled += 1; duke@435: } duke@435: void inc_native() { duke@435: _native += 1; duke@435: } duke@435: void inc_compiling() { duke@435: _compiling += 1; duke@435: } duke@435: void reset() { duke@435: _interpreted = 0; duke@435: _compiled = 0; duke@435: _native = 0; duke@435: _compiling = 0; duke@435: } duke@435: static void print_header(outputStream* st); duke@435: void print_data(outputStream* st); duke@435: }; jprovino@4165: #endif // INCLUDE_FPROF duke@435: zgu@3900: class ThreadProfiler: public CHeapObj { duke@435: public: jprovino@4165: ThreadProfiler() NOT_FPROF_RETURN; jprovino@4165: ~ThreadProfiler() NOT_FPROF_RETURN; duke@435: duke@435: // Resets the profiler jprovino@4165: void reset() NOT_FPROF_RETURN; duke@435: duke@435: // Activates the profiler for a certain thread jprovino@4165: void engage() NOT_FPROF_RETURN; duke@435: duke@435: // Deactivates the profiler jprovino@4165: void disengage() NOT_FPROF_RETURN; duke@435: duke@435: // Prints the collected profiling information jprovino@4165: void print(const char* thread_name) NOT_FPROF_RETURN; duke@435: duke@435: // Garbage Collection Support jprovino@4165: void oops_do(OopClosure* f) NOT_FPROF_RETURN; duke@435: jprovino@4165: #if INCLUDE_FPROF duke@435: private: duke@435: // for recording ticks. duke@435: friend class ProfilerNode; duke@435: char* area_bottom; // preallocated area for pnodes duke@435: char* area_top; duke@435: char* area_limit; duke@435: static int table_size; duke@435: ProfilerNode** table; duke@435: duke@435: private: sgoldman@542: void record_interpreted_tick(JavaThread* thread, frame fr, TickPosition where, int* ticks); duke@435: void record_compiled_tick (JavaThread* thread, frame fr, TickPosition where); coleenp@4037: void interpreted_update(Method* method, TickPosition where); coleenp@4037: void compiled_update (Method* method, TickPosition where); coleenp@4037: void stub_update (Method* method, const char* name, TickPosition where); duke@435: void adapter_update (TickPosition where); duke@435: duke@435: void runtime_stub_update(const CodeBlob* stub, const char* name, TickPosition where); duke@435: void unknown_compiled_update (const CodeBlob* cb, TickPosition where); duke@435: duke@435: void vm_update (TickPosition where); duke@435: void vm_update (const char* name, TickPosition where); duke@435: duke@435: void record_tick_for_running_frame(JavaThread* thread, frame fr); duke@435: void record_tick_for_calling_frame(JavaThread* thread, frame fr); duke@435: duke@435: void initialize(); duke@435: duke@435: static int entry(int value); duke@435: duke@435: duke@435: private: duke@435: friend class FlatProfiler; duke@435: void record_tick(JavaThread* thread); duke@435: bool engaged; duke@435: // so we can do percentages for this thread, and quick checks for activity duke@435: int thread_ticks; duke@435: int compiler_ticks; duke@435: int interpreter_ticks; duke@435: duke@435: public: duke@435: void inc_thread_ticks() { thread_ticks += 1; } duke@435: duke@435: private: duke@435: friend class ThreadProfilerMark; duke@435: // counters for thread-specific regions duke@435: bool region_flag[ThreadProfilerMark::maxRegion]; duke@435: int class_loader_ticks; duke@435: int extra_ticks; duke@435: duke@435: private: duke@435: // other thread-specific regions duke@435: int blocked_ticks; duke@435: enum UnknownTickSites { duke@435: ut_null_method, duke@435: ut_vtable_stubs, duke@435: ut_running_frame, duke@435: ut_calling_frame, duke@435: ut_no_pc, duke@435: ut_no_last_Java_frame, duke@435: ut_unknown_thread_state, duke@435: ut_end duke@435: }; duke@435: int unknown_ticks_array[ut_end]; duke@435: int unknown_ticks() { duke@435: int result = 0; duke@435: for (int ut = 0; ut < ut_end; ut += 1) { duke@435: result += unknown_ticks_array[ut]; duke@435: } duke@435: return result; duke@435: } duke@435: duke@435: elapsedTimer timer; duke@435: duke@435: // For interval timing duke@435: private: duke@435: IntervalData _interval_data; duke@435: IntervalData interval_data() { duke@435: return _interval_data; duke@435: } duke@435: IntervalData* interval_data_ref() { duke@435: return &_interval_data; duke@435: } jprovino@4165: #endif // INCLUDE_FPROF duke@435: }; duke@435: duke@435: class FlatProfiler: AllStatic { duke@435: public: jprovino@4165: static void reset() NOT_FPROF_RETURN ; jprovino@4165: static void engage(JavaThread* mainThread, bool fullProfile) NOT_FPROF_RETURN ; jprovino@4165: static void disengage() NOT_FPROF_RETURN ; jprovino@4165: static void print(int unused) NOT_FPROF_RETURN ; jprovino@4165: static bool is_active() NOT_FPROF_RETURN_(false) ; duke@435: duke@435: // This is NULL if each thread has its own thread profiler, duke@435: // else this is the single thread profiler used by all threads. duke@435: // In particular it makes a difference during garbage collection, duke@435: // where you only want to traverse each thread profiler once. jprovino@4165: static ThreadProfiler* get_thread_profiler() NOT_FPROF_RETURN_(NULL); duke@435: duke@435: // Garbage Collection Support jprovino@4165: static void oops_do(OopClosure* f) NOT_FPROF_RETURN ; duke@435: duke@435: // Support for disassembler to inspect the PCRecorder duke@435: duke@435: // Returns the start address for a given pc duke@435: // NULL is returned if the PCRecorder is inactive jprovino@4165: static address bucket_start_for(address pc) NOT_FPROF_RETURN_(NULL); duke@435: duke@435: enum { MillisecsPerTick = 10 }; // ms per profiling ticks duke@435: duke@435: // Returns the number of ticks recorded for the bucket duke@435: // pc belongs to. jprovino@4165: static int bucket_count_for(address pc) NOT_FPROF_RETURN_(0); duke@435: jprovino@4165: #if INCLUDE_FPROF duke@435: duke@435: private: duke@435: static bool full_profile() { duke@435: return full_profile_flag; duke@435: } duke@435: duke@435: friend class ThreadProfiler; duke@435: // the following group of ticks cover everything that's not attributed to individual Java methods duke@435: static int received_gc_ticks; // ticks during which gc was active duke@435: static int vm_operation_ticks; // total ticks in vm_operations other than GC duke@435: static int threads_lock_ticks; // the number of times we couldn't get the Threads_lock without blocking duke@435: static int blocked_ticks; // ticks when the thread was blocked. duke@435: static int class_loader_ticks; // total ticks in class loader duke@435: static int extra_ticks; // total ticks an extra temporary measuring duke@435: static int compiler_ticks; // total ticks in compilation duke@435: static int interpreter_ticks; // ticks in unknown interpreted method duke@435: static int deopt_ticks; // ticks in deoptimization duke@435: static int unknown_ticks; // ticks that cannot be categorized duke@435: static int received_ticks; // ticks that were received by task duke@435: static int delivered_ticks; // ticks that were delivered by task duke@435: static int non_method_ticks() { duke@435: return duke@435: ( received_gc_ticks duke@435: + vm_operation_ticks duke@435: + deopt_ticks duke@435: + threads_lock_ticks duke@435: + blocked_ticks duke@435: + compiler_ticks duke@435: + interpreter_ticks duke@435: + unknown_ticks ); duke@435: } duke@435: static elapsedTimer timer; duke@435: duke@435: // Counts of each of the byte codes duke@435: static int* bytecode_ticks; duke@435: static int* bytecode_ticks_stub; duke@435: static void print_byte_code_statistics(); duke@435: duke@435: // the ticks below are for continuous profiling (to adjust recompilation, etc.) duke@435: static int all_ticks; // total count of ticks received so far duke@435: static int all_int_ticks; // ticks in interpreter duke@435: static int all_comp_ticks; // ticks in compiled code (+ native) duke@435: static bool full_profile_flag; // collecting full profile? duke@435: duke@435: // to accumulate thread-specific data duke@435: // if we aren't profiling individual threads. duke@435: static ThreadProfiler* thread_profiler; duke@435: static ThreadProfiler* vm_thread_profiler; duke@435: duke@435: static void allocate_table(); duke@435: duke@435: // The task that periodically interrupts things. duke@435: friend class FlatProfilerTask; duke@435: static FlatProfilerTask* task; duke@435: static void record_vm_operation(); duke@435: static void record_vm_tick(); duke@435: static void record_thread_ticks(); duke@435: duke@435: // For interval analysis duke@435: private: duke@435: static int interval_ticks_previous; // delivered_ticks from the last interval duke@435: static void interval_record_thread(ThreadProfiler* tp); // extract ticks from ThreadProfiler. duke@435: static void interval_print(); // print interval data. duke@435: static void interval_reset(); // reset interval data. duke@435: enum {interval_print_size = 10}; duke@435: static IntervalData* interval_data; jprovino@4165: #endif // INCLUDE_FPROF duke@435: }; stefank@2314: stefank@2314: #endif // SHARE_VM_RUNTIME_FPROFILER_HPP