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// File: MultiCoreJIT.h
6//
7
8//
9// Multicore JIT interface to other part of the VM (Thread, AppDomain, JIT)
10//
11// ======================================================================================
12
13#ifndef __MULTICORE_JIT_H__
14#define __MULTICORE_JIT_H__
15
16class MulticoreJitRecorder;
17
18
19class MulticoreJitCounter
20{
21 volatile LONG m_nValue;
22
23public:
24 MulticoreJitCounter()
25 {
26 LIMITED_METHOD_CONTRACT;
27
28 m_nValue = 0;
29 }
30
31 inline LONG GetValue() const
32 {
33 LIMITED_METHOD_CONTRACT;
34
35 return m_nValue;
36 }
37
38 LONG Increment()
39 {
40 LIMITED_METHOD_CONTRACT;
41
42 return InterlockedIncrement(& m_nValue);
43 }
44
45 LONG Decrement()
46 {
47 LIMITED_METHOD_CONTRACT;
48
49 return InterlockedDecrement(& m_nValue);
50 }
51};
52
53
54// Statistics, information shared by recorder and player
55struct MulticoreJitPlayerStat
56{
57 unsigned short m_nTotalMethod;
58 unsigned short m_nHasNativeCode;
59 unsigned short m_nTryCompiling;
60 unsigned short m_nFilteredMethods;
61 unsigned short m_nMissingModuleSkip;
62 unsigned short m_nTotalDelay;
63 unsigned short m_nDelayCount;
64 unsigned short m_nWalkBack;
65
66 HRESULT m_hr;
67
68 void Clear()
69 {
70 LIMITED_METHOD_CONTRACT;
71
72 memset(this, 0, sizeof(MulticoreJitPlayerStat));
73 }
74};
75
76
77// Code Storage
78
79class MulticoreJitCodeStorage
80{
81private:
82 MapSHashWithRemove<PVOID,PCODE> m_nativeCodeMap;
83 CrstExplicitInit m_crstCodeMap; // protecting m_nativeCodeMap
84 unsigned m_nStored;
85 unsigned m_nReturned;
86
87public:
88
89 void Init();
90
91#ifdef DACCESS_COMPILE
92
93 ~MulticoreJitCodeStorage()
94 {
95 LIMITED_METHOD_CONTRACT;
96 }
97
98#else
99
100 ~MulticoreJitCodeStorage();
101
102#endif
103
104 void StoreMethodCode(MethodDesc * pMethod, PCODE pCode);
105
106 PCODE QueryMethodCode(MethodDesc * pMethod, BOOL shouldRemoveCode);
107
108 inline unsigned GetRemainingMethodCount() const
109 {
110 LIMITED_METHOD_CONTRACT;
111
112 return m_nativeCodeMap.GetCount();
113 }
114
115 inline unsigned GetStored() const
116 {
117 LIMITED_METHOD_CONTRACT;
118
119 return m_nStored;
120 }
121
122 inline unsigned GetReturned() const
123 {
124 LIMITED_METHOD_CONTRACT;
125
126 return m_nReturned;
127 }
128
129};
130
131
132const LONG SETPROFILEROOTCALLED = 1;
133
134
135// Multicore JIT attachment to AppDomain class
136class MulticoreJitManager
137{
138private:
139 MulticoreJitCounter m_ProfileSession; // Sequential profile session within the domain,
140 // incremented for every StartProfile/StopProfile/AbortProfile call to signal older players to quit
141 // We're just afraid of keeping pointer to player
142
143 MulticoreJitRecorder * m_pMulticoreJitRecorder; // pointer to current recorder
144 SString m_profileRoot; // profile root string
145 LONG m_fSetProfileRootCalled; // SetProfileRoot has been called
146 LONG m_fAutoStartCalled;
147 bool m_fRecorderActive; // Manager open for recording/event, turned on when initialized properly, turned off when at full capacity
148 bool m_fAppxMode;
149 CrstExplicitInit m_playerLock; // Thread protection (accessing m_pMulticoreJitRecorder)
150 MulticoreJitPlayerStat m_stats; // Statistics: normally gathered by player, written to profile
151
152 MulticoreJitCodeStorage m_MulticoreJitCodeStorage;
153
154public:
155
156#ifndef DACCESS_COMPILE
157 MulticoreJitManager();
158
159 ~MulticoreJitManager();
160#else
161
162 MulticoreJitManager()
163 {
164 LIMITED_METHOD_CONTRACT;
165
166 m_pMulticoreJitRecorder = NULL;
167 m_fSetProfileRootCalled = 0;
168 m_fAutoStartCalled = 0;
169 m_fRecorderActive = false;
170 m_fAppxMode = false;
171 }
172
173 ~MulticoreJitManager()
174 {
175 LIMITED_METHOD_CONTRACT;
176 }
177
178#endif
179
180 inline bool IsRecorderActive() const
181 {
182 LIMITED_METHOD_CONTRACT;
183
184 return m_fRecorderActive;
185 }
186
187 inline MulticoreJitCounter & GetProfileSession()
188 {
189 LIMITED_METHOD_CONTRACT;
190
191 return m_ProfileSession;
192 }
193
194 // Check for environment variable to automatically start multicore JIT
195 void AutoStartProfile(AppDomain * pDomain);
196
197 // Multicore JIT API function: SetProfileRoot
198 void SetProfileRoot(AppDomain * pDomain, const wchar_t * pProfilePath);
199
200 // Multicore JIT API function: StartProfile
201 void StartProfile(AppDomain * pDomain, ICLRPrivBinder * pBinderContext, const wchar_t * pProfile, int suffix = -1);
202
203 // Multicore JIT API function (internal): AbortProfile
204 void AbortProfile();
205
206 // Called at AppDomain shut down to automatically shut down remaining profiling
207 void StopProfile(bool appDomainShutdown);
208
209 static void StopProfileAll();
210
211 // Track module loading event for recording
212 void RecordModuleLoad(Module * pModule, FileLoadLevel loadLevel);
213
214 static bool IsMethodSupported(MethodDesc * pMethod);
215
216 PCODE RequestMethodCode(MethodDesc * pMethod);
217
218 void RecordMethodJit(MethodDesc * pMethod);
219
220 MulticoreJitPlayerStat & GetStats()
221 {
222 LIMITED_METHOD_CONTRACT;
223
224 return m_stats;
225 }
226
227 MulticoreJitCodeStorage & GetMulticoreJitCodeStorage()
228 {
229 LIMITED_METHOD_CONTRACT;
230
231 return m_MulticoreJitCodeStorage;
232 }
233
234 static void DisableMulticoreJit();
235
236 static bool IsSupportedModule(Module * pModule, bool fMethodJit, bool fAppx);
237
238 static FileLoadLevel GetModuleFileLoadLevel(Module * pModule);
239
240 static bool ModuleHasNoCode(Module * pModule);
241
242
243};
244
245
246// For ecall.cpp
247
248class MultiCoreJITNative
249{
250public:
251 static void QCALLTYPE InternalSetProfileRoot(__in_z LPCWSTR directoryPath);
252
253 static void QCALLTYPE InternalStartProfile(__in_z LPCWSTR wszProfile, INT_PTR ptrNativeAssemblyLoadContext);
254};
255
256#endif // __MULTICORE_JIT_H__
257