JIT: Fix bug in finally cloning caused by unsound callfinally reordering
[platform/upstream/coreclr.git] / src / zap / zapperstats.cpp
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 /*
6
7  */
8
9
10 #include "common.h"
11
12 namespace
13 {
14 //  some helper functions
15 //
16
17 template < typename T >
18 void init_array( T * arr, size_t size )
19 {
20     ::ZeroMemory( arr, size * sizeof( T ) );
21 }
22
23
24 //  locals
25 //
26
27 const char * const fixupNames[] =
28 {
29     "Class Handle",
30     "Field Handle",
31     "Method Handle",
32     "Function Call/Pointer",
33     "Sync",
34     "Pinvoke",
35     "Profiling Handle",
36     "Interface Table",
37     "Module Handle",
38     "Module Domain ID",
39     "Class Domain ID",
40     "Field Address",
41     "Varargs Handle",
42     "String",
43     "Init Class",
44     "Load Class",
45     "Stub Dispatch",
46     "Active Dependency"
47 };
48
49 const char * const callReasons[] =
50 {
51     "Unknown",
52     "Exotic (Not IL or ECall)",
53     "PInvoke",
54     "Has Generic Instantiation",
55     "No code generated yet",
56     "Method has fixups",
57     "Prestub may produce stub",
58     "Remoting interception",
59     "Contains Cer root",
60     "Restore method (Generics)",
61     "Restore first call",
62     "Restore value type",
63     "Restore",
64     "Can't patch",
65     "Profiling",
66     "Other loader module",
67 };
68
69 static_assert_no_msg((sizeof(callReasons)/sizeof(callReasons[0])) == CORINFO_INDIRECT_CALL_COUNT);
70
71 }
72
73 ZapperStats::ZapperStats()
74     : m_methods( 0 )
75     , m_failedMethods( 0 )
76     , m_failedILStubs( 0 )
77     , m_ilCodeSize( 0 )
78     , m_nativeCodeSize( 0 )
79     , m_nativeColdCodeSize( 0 )
80     , m_nativeRODataSize( 0 )
81     , m_gcInfoSize( 0 )
82 #ifdef WIN64EXCEPTIONS
83     , m_unwindInfoSize( 0 )
84 #endif // WIN64EXCEPTIONS
85     , m_NumHotAllocations( 0 )
86     , m_NumHotColdAllocations( 0 )
87     , m_NumMediumHeaders( 0 )
88     , m_nativeCodeSizeInSplitMethods( 0 )
89     , m_nativeColdCodeSizeInSplitMethods( 0 )
90     , m_nativeCodeSizeInSplitProfiledMethods( 0 )
91     , m_nativeColdCodeSizeInSplitProfiledMethods( 0 )
92     , m_nativeCodeSizeInProfiledMethods( 0 )
93     , m_nativeColdCodeSizeInProfiledMethods( 0 )
94     , m_totalHotCodeSize( 0 )
95     , m_totalUnprofiledCodeSize( 0 )
96     , m_totalColdCodeSize( 0 )
97     , m_totalCodeSizeInProfiledMethods( 0 )
98     , m_totalColdCodeSizeInProfiledMethods( 0 )
99     , m_inputFileSize( 0 )
100     , m_outputFileSize( 0 )
101     , m_metadataSize( 0 )
102     , m_preloadImageSize( 0 )
103     , m_hotCodeMgrSize( 0 )
104     , m_unprofiledCodeMgrSize( 0 )
105     , m_coldCodeMgrSize( 0 )
106     , m_eeInfoTableSize( 0 )
107     , m_helperTableSize( 0 )
108     , m_dynamicInfoTableSize( 0 )
109     , m_dynamicInfoDelayListSize( 0 )
110     , m_importTableSize( 0 )
111     , m_debuggingTableSize( 0 )
112     , m_headerSectionSize( 0 )
113     , m_codeSectionSize( 0 )
114     , m_coldCodeSectionSize( 0 )
115     , m_exceptionSectionSize( 0 )
116     , m_readOnlyDataSectionSize( 0 )
117     , m_relocSectionSize( 0 )
118     , m_ILMetadataSize( 0 )
119     , m_externalMethodThunkSize( 0 )
120     , m_externalMethodDataSize( 0 )
121     , m_prestubMethods( 0 )
122     , m_directMethods( 0 )
123 {
124     init_array( m_indirectMethodReasons, CORINFO_INDIRECT_CALL_COUNT );
125 }
126
127 #ifdef _PREFAST_
128 #pragma warning(push)
129 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
130 #endif
131 void ZapperStats::PrintStats()
132 {
133     if (m_outputFileSize > 0) {
134
135         GetSvcLogger()->Printf( "-------------------------------------------------------\n");
136         GetSvcLogger()->Printf( "Input file size:            %8d\n",         m_inputFileSize);
137         GetSvcLogger()->Printf( "Output file size:           %8d\n", m_outputFileSize);
138         GetSvcLogger()->Printf( "Input file size/Output file size ratio:\t%8.2fx\n", double( m_outputFileSize ) / m_inputFileSize);
139         GetSvcLogger()->Printf( "\n");
140         GetSvcLogger()->Printf( "Metadata:                   %8d\t%8.2f%%\n", m_metadataSize, (double)m_metadataSize/m_outputFileSize*100);
141         GetSvcLogger()->Printf( "Debugging maps:             %8d\t%8.2f%%\n", m_debuggingTableSize, (double)m_debuggingTableSize/m_outputFileSize*100);
142         GetSvcLogger()->Printf( "Hot Code manager:           %8d\t%8.2f%%\n", m_hotCodeMgrSize, (double)m_hotCodeMgrSize/m_outputFileSize*100);
143         GetSvcLogger()->Printf( "Unprofiled Code manager:    %8d\t%8.2f%%\n", m_unprofiledCodeMgrSize, (double)m_unprofiledCodeMgrSize/m_outputFileSize*100);
144         GetSvcLogger()->Printf( "Cold Code manager:          %8d\t%8.2f%%\n", m_coldCodeMgrSize, (double)m_coldCodeMgrSize/m_outputFileSize*100);
145         GetSvcLogger()->Printf( "GC info:                    %8d\t%8.2f%%\n", m_headerSectionSize, (double)m_headerSectionSize/m_outputFileSize*100);
146         GetSvcLogger()->Printf( "Native code & r/o data:     %8d\t%8.2f%%\n", m_codeSectionSize, (double)m_codeSectionSize/m_outputFileSize*100);
147         GetSvcLogger()->Printf( "Cold code:                  %8d\t%8.2f%%\n", m_coldCodeSectionSize, (double)m_coldCodeSectionSize/m_outputFileSize*100);
148         GetSvcLogger()->Printf( "Exception tables:           %8d\t%8.2f%%\n", m_exceptionSectionSize, (double)m_exceptionSectionSize/m_outputFileSize*100);
149         GetSvcLogger()->Printf( "Relocs:                     %8d\t%8.2f%%\n", m_relocSectionSize, (double)m_relocSectionSize/m_outputFileSize*100);
150         GetSvcLogger()->Printf( "IL metadata:                %8d\t%8.2f%%\n", m_ILMetadataSize, (double)m_ILMetadataSize/m_outputFileSize*100);
151         GetSvcLogger()->Printf( "External Method Thunks:     %8d\t%8.2f%%\n", m_externalMethodThunkSize, (double)m_externalMethodThunkSize/m_outputFileSize*100);
152         GetSvcLogger()->Printf( "External Method Data:       %8d\t%8.2f%%\n", m_externalMethodDataSize, (double)m_externalMethodDataSize/m_outputFileSize*100);
153         GetSvcLogger()->Printf( "Image of EE structures:     %8d\t%8.2f%%\n", m_preloadImageSize, (double)m_preloadImageSize/m_outputFileSize*100);
154
155         unsigned totalIndirections =
156           m_dynamicInfoDelayListSize +
157           m_eeInfoTableSize +
158           m_helperTableSize +
159           m_dynamicInfoTableSize +
160           m_importTableSize;
161
162         GetSvcLogger()->Printf( "Indirections:               %8d\t%8.2f%%\n",
163                 totalIndirections, (double)totalIndirections/m_outputFileSize*100);
164         GetSvcLogger()->Printf( "       ----- Breakdown of Indirections ----\n");
165
166         GetSvcLogger()->Printf( "       Delay load lists:           %8d\t%8.2f%%\n",
167                 m_dynamicInfoDelayListSize, (double)m_dynamicInfoDelayListSize/totalIndirections*100);
168         GetSvcLogger()->Printf( "       Tables:                     %8d\t%8.2f%%\n",
169                 m_dynamicInfoTableSize, (double)m_dynamicInfoTableSize/totalIndirections*100);
170         GetSvcLogger()->Printf( "       EE Values:                  %8d\t%8.2f%%\n",
171                 m_eeInfoTableSize, (double)m_eeInfoTableSize/totalIndirections*100);
172         GetSvcLogger()->Printf( "       Helper functions:           %8d\t%8.2f%%\n",
173                 m_helperTableSize, (double)m_helperTableSize/totalIndirections*100);
174     }
175
176     GetSvcLogger()->Printf( "       Direct method descs:\t%5d/%5d %8.2f%%\n",
177             m_directMethods, m_prestubMethods+m_directMethods,
178             (double)m_directMethods/(m_directMethods+m_prestubMethods)*100);
179     GetSvcLogger()->Printf( "       Indirect method descs:\t%5d/%5d %8.2f%%\n",
180             m_prestubMethods, m_prestubMethods+m_directMethods,
181             (double)m_prestubMethods/(m_directMethods+m_prestubMethods)*100);
182
183     for (int i=0; i < CORINFO_INDIRECT_CALL_COUNT; i++)
184         GetSvcLogger()->Printf( "               %-30s  %5d %8.2f%%\n",
185                 callReasons[i],
186                 m_indirectMethodReasons[i],
187                 double(m_indirectMethodReasons[i])/(m_directMethods+m_prestubMethods)*100);
188
189     GetSvcLogger()->Printf( "-------------------------------------------------------\n");
190     GetSvcLogger()->Printf( "Total Methods: \t\t\t\t%8d\n", m_methods);
191     GetSvcLogger()->Printf( "Total Hot Only: \t\t\t%8d\n", m_NumHotAllocations);
192     GetSvcLogger()->Printf( "Total Split (Hot/Cold): \t\t%8d\n", m_NumHotColdAllocations);
193     GetSvcLogger()->Printf( "Total Medium Headers: \t\t\t%8d\n", m_NumMediumHeaders);
194     GetSvcLogger()->Printf( "Split Methods: Hot Code \t\t%8d\n", m_nativeCodeSizeInSplitMethods);
195     GetSvcLogger()->Printf( "Split Methods: Cold Code \t\t%8d\n", m_nativeColdCodeSizeInSplitMethods);
196     GetSvcLogger()->Printf( "Split Profiled Methods: Hot Code \t%8d\n", m_nativeCodeSizeInSplitProfiledMethods);
197     GetSvcLogger()->Printf( "Split Profiled Methods: Cold Code \t%8d\n", m_nativeColdCodeSizeInSplitProfiledMethods);
198     GetSvcLogger()->Printf( "Profiled Methods: Hot Code \t\t%8d\n", m_nativeCodeSizeInProfiledMethods);
199     GetSvcLogger()->Printf( "Profiled Methods: Cold Code \t\t%8d\n", m_nativeColdCodeSizeInProfiledMethods);
200     GetSvcLogger()->Printf( "Profiled Methods: Total Hot Code+Headers %7d\n", m_totalCodeSizeInProfiledMethods);
201     GetSvcLogger()->Printf( "Profiled Methods: Total Cold Code+Headers %6d\n", m_totalColdCodeSizeInProfiledMethods);
202     GetSvcLogger()->Printf( "All Methods: Total Hot+Unprofiled Code \t\t%8d\n",  m_nativeCodeSize);
203     GetSvcLogger()->Printf( "All Methods: Total Cold Code \t\t%8d\n", m_nativeColdCodeSize);
204     GetSvcLogger()->Printf( "All Methods: Total Hot Code+Headers \t%8d\n",  m_totalHotCodeSize);
205     GetSvcLogger()->Printf( "All Methods: Total Unprofiled Code+Headers \t%8d\n", m_totalUnprofiledCodeSize);
206     GetSvcLogger()->Printf( "All Methods: Total Cold Code+Headers \t%8d\n", m_totalColdCodeSize);
207
208     GetSvcLogger()->Printf( "-------------------------------------------------------\n");
209     GetSvcLogger()->Printf( "Total IL Code:          %8d\n", m_ilCodeSize);
210     GetSvcLogger()->Printf( "Total Native Code:      %8d\n", m_nativeCodeSize + m_nativeColdCodeSize);
211     GetSvcLogger()->Printf( "Total Code+Headers:     %8d\n", m_totalHotCodeSize + m_totalUnprofiledCodeSize + m_totalColdCodeSize);
212
213     GetSvcLogger()->Printf( "Total Native RO Data:   %8d\n", m_nativeRODataSize);
214     GetSvcLogger()->Printf( "Total Native GC Info:   %8d\n", m_gcInfoSize);
215     size_t nativeTotal = m_nativeCodeSize + m_nativeRODataSize + m_gcInfoSize;
216 #ifdef WIN64EXCEPTIONS
217     GetSvcLogger()->Printf( "Total Native UnwindInfo:%8d\n", m_unwindInfoSize);
218     nativeTotal += m_unwindInfoSize;
219 #endif // WIN64EXCEPTIONS
220     GetSvcLogger()->Printf( "Total Native Total :    %8d\n", nativeTotal);
221
222     if (m_methods > 0) {
223         GetSvcLogger()->Printf( "\n");
224         GetSvcLogger()->Printf( "Average IL Code:            %8.2f\n", double(m_ilCodeSize) / m_methods);
225         GetSvcLogger()->Printf( "Average NativeCode:         %8.2f\n", double(m_nativeCodeSize) / m_methods);
226         GetSvcLogger()->Printf( "Average Native RO Data:     %8.2f\n", double(m_nativeRODataSize) / m_methods);
227         GetSvcLogger()->Printf( "Average Native GC Info:     %8.2f\n", double(m_gcInfoSize) / m_methods);
228 #ifdef WIN64EXCEPTIONS
229         GetSvcLogger()->Printf( "Average Native UnwindInfo:  %8.2f\n", double(m_unwindInfoSize) / m_methods);
230 #endif // WIN64EXCEPTIONS
231         GetSvcLogger()->Printf( "Average Native:             %8.2f\n", double(nativeTotal) / m_methods);
232         GetSvcLogger()->Printf( "\n");
233         GetSvcLogger()->Printf( "NativeGC / Native:      %8.2f\n", double(m_gcInfoSize) / nativeTotal);
234         GetSvcLogger()->Printf( "Native / IL:            %8.2f\n", double(nativeTotal) / m_ilCodeSize);
235     }
236
237     if (m_failedMethods > 0)
238         GetSvcLogger()->Printf( "Methods which did not compile: %d\n", m_failedMethods);
239     if (m_failedILStubs > 0)
240         GetSvcLogger()->Printf( "IL STUBS which did not compile: %d\n", m_failedILStubs);
241 }
242 #ifdef _PREFAST_
243 #pragma warning(pop)
244 #endif
245
246 char const * GetCallReasonString( CorInfoIndirectCallReason reason )
247 {
248     return callReasons[ reason ];
249 }