| 1 | // Licensed to the .NET Foundation under one or more agreements. |
| 2 | // The .NET Foundation licenses this file to you under the MIT license. |
| 3 | // See the LICENSE file in the project root for more information. |
| 4 | //----------------------------------------------------------------------------- |
| 5 | // JitPerf.h |
| 6 | // Internal interface for gathering JIT perfmormance stats. These stats are |
| 7 | // logged (or displayed) in two ways. If PERF_COUNTERS are enabled the |
| 8 | // perfmon etc. would display the jit stats. If ENABLE_PERF_LOG is enabled |
| 9 | // and PERF_OUTPUT env var is defined then the jit stats are displayed on the |
| 10 | // stdout. (The jit stats are outputted in a specific format to a file for |
| 11 | // automated perf tests.) |
| 12 | // |
| 13 | |
| 14 | //----------------------------------------------------------------------------- |
| 15 | |
| 16 | |
| 17 | #ifndef __JITPERF_H__ |
| 18 | #define __JITPERF_H__ |
| 19 | |
| 20 | #include "mscoree.h" |
| 21 | #include "clrinternal.h" |
| 22 | |
| 23 | // ENABLE_JIT_PERF tag used to activate JIT specific profiling. |
| 24 | #define ENABLE_JIT_PERF |
| 25 | |
| 26 | #if defined(ENABLE_JIT_PERF) |
| 27 | |
| 28 | extern __int64 g_JitCycles; |
| 29 | extern size_t g_NonJitCycles; |
| 30 | extern CRITSEC_COOKIE g_csJit; |
| 31 | extern __int64 g_tlsJitCycles; |
| 32 | extern int g_fJitPerfOn; |
| 33 | |
| 34 | extern size_t g_dwTlsx86CodeSize; |
| 35 | extern size_t g_TotalILCodeSize; |
| 36 | extern size_t g_Totalx86CodeSize; |
| 37 | extern size_t g_TotalMethodsJitted; |
| 38 | |
| 39 | // Public interface to initialize jit stats data structs |
| 40 | void InitJitPerf(void); |
| 41 | // Public interface to deallocate datastruct and output the stats. |
| 42 | void DoneJitPerfStats(void); |
| 43 | |
| 44 | // Start/StopNonJITPerf macros are used many times. Factor out the payload |
| 45 | // into helper method to reduce code size. |
| 46 | void StartNonJITPerfWorker(LARGE_INTEGER * pCycleStart); |
| 47 | void StopNonJITPerfWorker(LARGE_INTEGER * pCycleStart); |
| 48 | |
| 49 | // Use the callee's stack frame (so START & STOP functions can share variables) |
| 50 | #define START_JIT_PERF() \ |
| 51 | if (g_fJitPerfOn) { \ |
| 52 | ClrFlsSetValue (TlsIdx_JitPerf, (LPVOID)0); \ |
| 53 | g_dwTlsx86CodeSize = 0; \ |
| 54 | ClrFlsSetValue (TlsIdx_JitX86Perf, (LPVOID)g_dwTlsx86CodeSize); \ |
| 55 | } |
| 56 | |
| 57 | |
| 58 | #define STOP_JIT_PERF() \ |
| 59 | if (g_fJitPerfOn) { \ |
| 60 | size_t dwTlsNonJitCycles = (size_t)ClrFlsGetValue (TlsIdx_JitPerf); \ |
| 61 | size_t dwx86CodeSize = (size_t)ClrFlsGetValue (TlsIdx_JitX86Perf); \ |
| 62 | CRITSEC_Holder csh (g_csJit); \ |
| 63 | g_JitCycles += static_cast<size_t>(CycleStop.QuadPart - CycleStart.QuadPart); \ |
| 64 | g_NonJitCycles += dwTlsNonJitCycles; \ |
| 65 | g_TotalILCodeSize += methodInfo.ILCodeSize; \ |
| 66 | g_Totalx86CodeSize += dwx86CodeSize; \ |
| 67 | g_TotalMethodsJitted ++; \ |
| 68 | } |
| 69 | |
| 70 | #define START_NON_JIT_PERF() \ |
| 71 | LARGE_INTEGER CycleStart; \ |
| 72 | if(g_fJitPerfOn) { \ |
| 73 | StartNonJITPerfWorker(&CycleStart); \ |
| 74 | } |
| 75 | |
| 76 | #define STOP_NON_JIT_PERF() \ |
| 77 | if(g_fJitPerfOn) { \ |
| 78 | StopNonJITPerfWorker(&CycleStart); \ |
| 79 | } |
| 80 | |
| 81 | #define JIT_PERF_UPDATE_X86_CODE_SIZE(size) \ |
| 82 | if(g_fJitPerfOn) { \ |
| 83 | size_t dwx86CodeSize = (size_t)ClrFlsGetValue (TlsIdx_JitX86Perf); \ |
| 84 | dwx86CodeSize += (size); \ |
| 85 | ClrFlsSetValue (TlsIdx_JitX86Perf, (LPVOID)dwx86CodeSize); \ |
| 86 | } |
| 87 | |
| 88 | |
| 89 | #else //ENABLE_JIT_PERF |
| 90 | #define START_JIT_PERF() |
| 91 | #define STOP_JIT_PERF() |
| 92 | #define START_NON_JIT_PERF() |
| 93 | #define STOP_NON_JIT_PERF() |
| 94 | #define JIT_PERF_UPDATE_X86_CODE_SIZE(size) |
| 95 | #endif //ENABLE_JIT_PERF |
| 96 | |
| 97 | #endif //__JITPERF_H__ |
| 98 | |