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 | // EEConfig.H |
5 | // |
6 | |
7 | // |
8 | // Fetched configuration data from the registry (should we Jit, run GC checks ...) |
9 | // |
10 | // |
11 | |
12 | |
13 | |
14 | #ifndef EECONFIG_H |
15 | #define EECONFIG_H |
16 | |
17 | class MethodDesc; |
18 | |
19 | #include "shash.h" |
20 | #include "corhost.h" |
21 | |
22 | #ifdef _DEBUG |
23 | class TypeNamesList |
24 | { |
25 | class TypeName |
26 | { |
27 | LPUTF8 typeName; |
28 | TypeName *next; // Next name |
29 | |
30 | friend class TypeNamesList; |
31 | }; |
32 | |
33 | TypeName *pNames; // List of names |
34 | |
35 | public: |
36 | TypeNamesList(); |
37 | ~TypeNamesList(); |
38 | |
39 | HRESULT Init(__in_z LPCWSTR str); |
40 | bool IsInList(LPCUTF8 typeName); |
41 | }; |
42 | #endif |
43 | |
44 | typedef struct _ConfigStringKeyValuePair |
45 | { |
46 | WCHAR * key; |
47 | WCHAR * value; |
48 | |
49 | _ConfigStringKeyValuePair() |
50 | { |
51 | key = NULL; |
52 | value = NULL; |
53 | } |
54 | |
55 | WCHAR * GetKey() |
56 | { |
57 | return key; |
58 | } |
59 | } ConfigStringKeyValuePair; |
60 | |
61 | typedef WStringSHash<ConfigStringKeyValuePair> ConfigStringHashtable; |
62 | |
63 | class ConfigList; |
64 | |
65 | // |
66 | // Holds a pointer to a hashtable that is populated with data from config files. |
67 | // Also acts as a node for a circular doubly-linked list. |
68 | // |
69 | class ConfigSource |
70 | { |
71 | friend class ConfigList; |
72 | public: |
73 | ConfigSource(); |
74 | ~ConfigSource(); |
75 | |
76 | ConfigStringHashtable* Table(); |
77 | |
78 | // |
79 | // Connect this node into the list that prev is in. |
80 | // |
81 | void Add(ConfigSource* prev); |
82 | |
83 | ConfigSource* Next() |
84 | { |
85 | LIMITED_METHOD_CONTRACT; |
86 | return m_pNext; |
87 | } |
88 | |
89 | ConfigSource* Previous() |
90 | { |
91 | LIMITED_METHOD_CONTRACT; |
92 | return m_pPrev; |
93 | } |
94 | |
95 | |
96 | private: |
97 | ConfigStringHashtable m_Table; |
98 | ConfigSource *m_pNext; |
99 | ConfigSource *m_pPrev; |
100 | }; |
101 | |
102 | // |
103 | // Wrapper around the ConfigSource circular doubly-linked list. |
104 | // |
105 | class ConfigList |
106 | { |
107 | public: |
108 | // |
109 | // Iterator for traversing through a ConfigList. |
110 | // |
111 | class ConfigIter |
112 | { |
113 | public: |
114 | ConfigIter(ConfigList* pList) |
115 | { |
116 | CONTRACTL { |
117 | NOTHROW; |
118 | GC_NOTRIGGER; |
119 | // MODE_ANY; |
120 | FORBID_FAULT; |
121 | SO_TOLERANT; |
122 | } CONTRACTL_END; |
123 | |
124 | pEnd = &(pList->m_pElement); |
125 | pCurrent = pEnd; |
126 | } |
127 | |
128 | // |
129 | // TODO: Check if iterating through the list once skips an element. |
130 | // Returns the next node. If the next node is the head, returns null. |
131 | // Note that iteration can be resumed by calling next again. |
132 | // |
133 | ConfigStringHashtable* Next() |
134 | { |
135 | CONTRACT (ConfigStringHashtable*) { |
136 | NOTHROW; |
137 | GC_NOTRIGGER; |
138 | // MODE_ANY; |
139 | FORBID_FAULT; |
140 | SO_TOLERANT; |
141 | POSTCONDITION(CheckPointer(RETVAL, NULL_OK)); |
142 | } CONTRACT_END; |
143 | |
144 | pCurrent = pCurrent->Next();; |
145 | if(pCurrent == pEnd) |
146 | RETURN NULL; |
147 | else |
148 | RETURN pCurrent->Table(); |
149 | } |
150 | |
151 | ConfigStringHashtable* Previous() |
152 | { |
153 | CONTRACT (ConfigStringHashtable*) { |
154 | NOTHROW; |
155 | GC_NOTRIGGER; |
156 | FORBID_FAULT; |
157 | // MODE_ANY; |
158 | SO_TOLERANT; |
159 | POSTCONDITION(CheckPointer(RETVAL, NULL_OK)); |
160 | } CONTRACT_END; |
161 | |
162 | pCurrent = pCurrent->Previous(); |
163 | if(pCurrent == pEnd) |
164 | RETURN NULL; |
165 | else |
166 | RETURN pCurrent->Table(); |
167 | } |
168 | |
169 | private: |
170 | ConfigSource* pEnd; |
171 | ConfigSource* pCurrent; |
172 | }; |
173 | |
174 | ConfigStringHashtable* Add() |
175 | { |
176 | CONTRACT (ConfigStringHashtable*) { |
177 | NOTHROW; |
178 | GC_NOTRIGGER; |
179 | // MODE_ANY; |
180 | POSTCONDITION(CheckPointer(RETVAL, NULL_OK)); |
181 | } CONTRACT_END; |
182 | |
183 | ConfigSource* pEntry = new (nothrow) ConfigSource(); |
184 | |
185 | if (pEntry == NULL) |
186 | RETURN NULL; |
187 | |
188 | pEntry->Add(&m_pElement); |
189 | RETURN pEntry->Table(); |
190 | } |
191 | |
192 | ConfigStringHashtable* Append() |
193 | { |
194 | CONTRACT (ConfigStringHashtable*) { |
195 | NOTHROW; |
196 | GC_NOTRIGGER; |
197 | // MODE_ANY; |
198 | POSTCONDITION(CheckPointer(RETVAL, NULL_OK)); |
199 | } CONTRACT_END; |
200 | |
201 | ConfigSource* pEntry = new (nothrow) ConfigSource(); |
202 | if (pEntry == NULL) |
203 | RETURN NULL; |
204 | |
205 | pEntry->Add(m_pElement.Previous()); |
206 | RETURN pEntry->Table(); |
207 | } |
208 | |
209 | void Append(ConfigSource * pEntry) |
210 | { |
211 | LIMITED_METHOD_CONTRACT; |
212 | PRECONDITION(CheckPointer(pEntry)); |
213 | |
214 | pEntry->Add(m_pElement.Previous()); |
215 | } |
216 | |
217 | ~ConfigList() |
218 | { |
219 | CONTRACTL { |
220 | NOTHROW; |
221 | GC_NOTRIGGER; |
222 | // MODE_ANY; |
223 | FORBID_FAULT; |
224 | } CONTRACTL_END; |
225 | |
226 | ConfigSource* pNext = m_pElement.Next(); |
227 | while(pNext != &m_pElement) { |
228 | ConfigSource *last = pNext; |
229 | pNext = pNext->m_pNext; |
230 | delete last; |
231 | } |
232 | } |
233 | |
234 | friend class ConfigIter; |
235 | |
236 | private: |
237 | ConfigSource m_pElement; |
238 | }; |
239 | |
240 | enum { OPT_BLENDED, |
241 | OPT_SIZE, |
242 | OPT_SPEED, |
243 | OPT_RANDOM, |
244 | OPT_DEFAULT = OPT_BLENDED }; |
245 | |
246 | enum ParseCtl { |
247 | parseAll, // parse entire config file |
248 | stopAfterRuntimeSection // stop after <runtime>...</runtime> section |
249 | }; |
250 | |
251 | class EEConfig |
252 | { |
253 | public: |
254 | typedef enum { |
255 | CONFIG_SYSTEM, |
256 | CONFIG_APPLICATION, |
257 | CONFIG_SYSTEMONLY |
258 | } ConfigSearch; |
259 | |
260 | static HRESULT Setup(); |
261 | |
262 | void *operator new(size_t size); |
263 | |
264 | HRESULT Init(); |
265 | HRESULT Cleanup(); |
266 | |
267 | // Spinning heuristics |
268 | |
269 | DWORD SpinInitialDuration(void) const {LIMITED_METHOD_CONTRACT; return dwSpinInitialDuration; } |
270 | DWORD SpinBackoffFactor(void) const {LIMITED_METHOD_CONTRACT; return dwSpinBackoffFactor; } |
271 | DWORD SpinLimitProcCap(void) const {LIMITED_METHOD_CONTRACT; return dwSpinLimitProcCap; } |
272 | DWORD SpinLimitProcFactor(void) const {LIMITED_METHOD_CONTRACT; return dwSpinLimitProcFactor; } |
273 | DWORD SpinLimitConstant(void) const {LIMITED_METHOD_CONTRACT; return dwSpinLimitConstant; } |
274 | DWORD SpinRetryCount(void) const {LIMITED_METHOD_CONTRACT; return dwSpinRetryCount; } |
275 | DWORD MonitorSpinCount(void) const {LIMITED_METHOD_CONTRACT; return dwMonitorSpinCount; } |
276 | |
277 | // Jit-config |
278 | |
279 | unsigned int GenOptimizeType(void) const {LIMITED_METHOD_CONTRACT; return iJitOptimizeType; } |
280 | bool JitFramed(void) const {LIMITED_METHOD_CONTRACT; return fJitFramed; } |
281 | bool JitAlignLoops(void) const {LIMITED_METHOD_CONTRACT; return fJitAlignLoops; } |
282 | bool AddRejitNops(void) const {LIMITED_METHOD_DAC_CONTRACT; return fAddRejitNops; } |
283 | bool JitMinOpts(void) const {LIMITED_METHOD_CONTRACT; return fJitMinOpts; } |
284 | |
285 | // Tiered Compilation config |
286 | #if defined(FEATURE_TIERED_COMPILATION) |
287 | bool TieredCompilation(void) const {LIMITED_METHOD_CONTRACT; return fTieredCompilation; } |
288 | bool TieredCompilation_CallCounting() const {LIMITED_METHOD_CONTRACT; return fTieredCompilation_CallCounting; } |
289 | bool TieredCompilation_OptimizeTier0() const {LIMITED_METHOD_CONTRACT; return fTieredCompilation_OptimizeTier0; } |
290 | DWORD TieredCompilation_Tier1CallCountThreshold() const { LIMITED_METHOD_CONTRACT; return tieredCompilation_tier1CallCountThreshold; } |
291 | DWORD TieredCompilation_Tier1CallCountingDelayMs() const { LIMITED_METHOD_CONTRACT; return tieredCompilation_tier1CallCountingDelayMs; } |
292 | #endif |
293 | |
294 | #if defined(FEATURE_GDBJIT) && defined(_DEBUG) |
295 | inline bool ShouldDumpElfOnMethod(LPCUTF8 methodName) const |
296 | { |
297 | CONTRACTL { |
298 | NOTHROW; |
299 | GC_NOTRIGGER; |
300 | PRECONDITION(CheckPointer(methodName, NULL_OK)); |
301 | } CONTRACTL_END |
302 | return RegexOrExactMatch(pszGDBJitElfDump, methodName); |
303 | } |
304 | #endif // FEATURE_GDBJIT && _DEBUG |
305 | |
306 | #if defined(FEATURE_GDBJIT_FRAME) |
307 | inline bool ShouldEmitDebugFrame(void) const {LIMITED_METHOD_CONTRACT; return fGDBJitEmitDebugFrame;} |
308 | #endif // FEATURE_GDBJIT_FRAME |
309 | BOOL PInvokeRestoreEsp(BOOL fDefault) const |
310 | { |
311 | LIMITED_METHOD_CONTRACT; |
312 | |
313 | switch (fPInvokeRestoreEsp) |
314 | { |
315 | case (unsigned)-1: return fDefault; |
316 | case 0: return FALSE; |
317 | default : return TRUE; |
318 | } |
319 | } |
320 | |
321 | bool LegacyNullReferenceExceptionPolicy(void) const {LIMITED_METHOD_CONTRACT; return fLegacyNullReferenceExceptionPolicy; } |
322 | bool LegacyUnhandledExceptionPolicy(void) const {LIMITED_METHOD_CONTRACT; return fLegacyUnhandledExceptionPolicy; } |
323 | |
324 | #ifdef FEATURE_CORRUPTING_EXCEPTIONS |
325 | // Returns a bool to indicate if the legacy CSE (pre-v4) behaviour is enabled or not |
326 | bool LegacyCorruptedStateExceptionsPolicy(void) const {LIMITED_METHOD_CONTRACT; return fLegacyCorruptedStateExceptionsPolicy; } |
327 | #endif // FEATURE_CORRUPTING_EXCEPTIONS |
328 | |
329 | bool InteropValidatePinnedObjects() const { LIMITED_METHOD_CONTRACT; return m_fInteropValidatePinnedObjects; } |
330 | bool InteropLogArguments() const { LIMITED_METHOD_CONTRACT; return m_fInteropLogArguments; } |
331 | |
332 | #ifdef _DEBUG |
333 | bool GenDebuggableCode(void) const {LIMITED_METHOD_CONTRACT; return fDebuggable; } |
334 | bool IsStressOn(void) const {LIMITED_METHOD_CONTRACT; return fStressOn; } |
335 | int GetAPIThreadStressCount(void) const {LIMITED_METHOD_CONTRACT; return apiThreadStressCount; } |
336 | |
337 | bool ShouldExposeExceptionsInCOMToConsole() const {LIMITED_METHOD_CONTRACT; return (iExposeExceptionsInCOM & 1) != 0; } |
338 | bool ShouldExposeExceptionsInCOMToMsgBox() const {LIMITED_METHOD_CONTRACT; return (iExposeExceptionsInCOM & 2) != 0; } |
339 | |
340 | static bool RegexOrExactMatch(LPCUTF8 regex, LPCUTF8 input); |
341 | |
342 | inline bool ShouldPrestubHalt(MethodDesc* pMethodInfo) const |
343 | { |
344 | WRAPPER_NO_CONTRACT; |
345 | return IsInMethList(pPrestubHalt, pMethodInfo); |
346 | } |
347 | |
348 | inline bool ShouldInvokeHalt(MethodDesc* pMethodInfo) const |
349 | { |
350 | WRAPPER_NO_CONTRACT; |
351 | return IsInMethList(pInvokeHalt, pMethodInfo); |
352 | } |
353 | |
354 | |
355 | inline bool ShouldPrestubGC(MethodDesc* pMethodInfo) const |
356 | { |
357 | WRAPPER_NO_CONTRACT; |
358 | return IsInMethList(pPrestubGC, pMethodInfo); |
359 | } |
360 | inline bool ShouldBreakOnClassLoad(LPCUTF8 className) const |
361 | { |
362 | CONTRACTL { |
363 | NOTHROW; |
364 | GC_NOTRIGGER; |
365 | // MODE_ANY; |
366 | PRECONDITION(CheckPointer(className, NULL_OK)); |
367 | } CONTRACTL_END |
368 | return RegexOrExactMatch(pszBreakOnClassLoad, className); |
369 | } |
370 | inline bool ShouldBreakOnClassBuild(LPCUTF8 className) const |
371 | { |
372 | CONTRACTL { |
373 | NOTHROW; |
374 | GC_NOTRIGGER; |
375 | // MODE_ANY; |
376 | PRECONDITION(CheckPointer(className, NULL_OK)); |
377 | } CONTRACTL_END |
378 | return RegexOrExactMatch(pszBreakOnClassBuild, className); |
379 | } |
380 | inline bool BreakOnInstantiationEnabled() const |
381 | { |
382 | LIMITED_METHOD_CONTRACT; |
383 | return pszBreakOnInstantiation != NULL; |
384 | } |
385 | inline bool ShouldBreakOnInstantiation(LPCUTF8 className) const |
386 | { |
387 | CONTRACTL { |
388 | NOTHROW; |
389 | GC_NOTRIGGER; |
390 | // MODE_ANY; |
391 | PRECONDITION(CheckPointer(className, NULL_OK)); |
392 | } CONTRACTL_END |
393 | return RegexOrExactMatch(pszBreakOnInstantiation, className); |
394 | } |
395 | inline bool ShouldBreakOnMethod(LPCUTF8 methodName) const |
396 | { |
397 | CONTRACTL { |
398 | NOTHROW; |
399 | GC_NOTRIGGER; |
400 | // MODE_ANY; |
401 | PRECONDITION(CheckPointer(methodName, NULL_OK)); |
402 | } CONTRACTL_END |
403 | return RegexOrExactMatch(pszBreakOnMethodName, methodName); |
404 | } |
405 | inline bool ShouldDumpOnClassLoad(LPCUTF8 className) const |
406 | { |
407 | CONTRACTL { |
408 | NOTHROW; |
409 | GC_NOTRIGGER; |
410 | // MODE_ANY; |
411 | PRECONDITION(CheckPointer(className, NULL_OK)); |
412 | } CONTRACTL_END |
413 | return RegexOrExactMatch(pszDumpOnClassLoad, className); |
414 | } |
415 | inline bool ShouldBreakOnInteropStubSetup(LPCUTF8 methodName) const |
416 | { |
417 | CONTRACTL { |
418 | NOTHROW; |
419 | GC_NOTRIGGER; |
420 | // MODE_ANY; |
421 | PRECONDITION(CheckPointer(methodName, NULL_OK)); |
422 | } CONTRACTL_END |
423 | return RegexOrExactMatch(pszBreakOnInteropStubSetup, methodName); |
424 | } |
425 | inline bool ShouldBreakOnComToClrNativeInfoInit(LPCUTF8 methodName) const |
426 | { |
427 | CONTRACTL { |
428 | NOTHROW; |
429 | GC_NOTRIGGER; |
430 | // MODE_ANY; |
431 | PRECONDITION(CheckPointer(methodName, NULL_OK)); |
432 | } CONTRACTL_END |
433 | return RegexOrExactMatch(pszBreakOnComToClrNativeInfoInit, methodName); |
434 | } |
435 | inline bool ShouldBreakOnStructMarshalSetup(LPCUTF8 className) const |
436 | { |
437 | CONTRACTL { |
438 | NOTHROW; |
439 | GC_NOTRIGGER; |
440 | // MODE_ANY; |
441 | PRECONDITION(CheckPointer(className, NULL_OK)); |
442 | } CONTRACTL_END |
443 | return RegexOrExactMatch(pszBreakOnStructMarshalSetup, className); |
444 | } |
445 | static HRESULT ParseTypeList(__in_z LPWSTR str, TypeNamesList** out); |
446 | static void DestroyTypeList(TypeNamesList* list); |
447 | |
448 | inline bool ShouldGcCoverageOnMethod(LPCUTF8 methodName) const |
449 | { |
450 | CONTRACTL { |
451 | NOTHROW; |
452 | GC_NOTRIGGER; |
453 | // MODE_ANY; |
454 | PRECONDITION(CheckPointer(methodName, NULL_OK)); |
455 | } CONTRACTL_END |
456 | return (pszGcCoverageOnMethod == 0 || methodName == 0 || RegexOrExactMatch(pszGcCoverageOnMethod, methodName)); |
457 | } |
458 | |
459 | bool IsJitVerificationDisabled(void) const {LIMITED_METHOD_CONTRACT; return fJitVerificationDisable; } |
460 | |
461 | #ifdef WIN64EXCEPTIONS |
462 | bool SuppressLockViolationsOnReentryFromOS() const {LIMITED_METHOD_CONTRACT; return fSuppressLockViolationsOnReentryFromOS; } |
463 | #endif |
464 | |
465 | #ifdef STUBLINKER_GENERATES_UNWIND_INFO |
466 | bool IsStubLinkerUnwindInfoVerificationOn() const { LIMITED_METHOD_CONTRACT; return fStubLinkerUnwindInfoVerificationOn; } |
467 | #endif |
468 | |
469 | #endif // _DEBUG |
470 | |
471 | #ifdef FEATURE_COMINTEROP |
472 | inline bool LogCCWRefCountChangeEnabled() |
473 | { |
474 | LIMITED_METHOD_CONTRACT; |
475 | return bLogCCWRefCountChange; |
476 | } |
477 | |
478 | void SetLogCCWRefCountChangeEnabled(bool newVal); |
479 | bool ShouldLogCCWRefCountChange(LPCUTF8 pszClassName, LPCUTF8 pszNamespace) const; |
480 | |
481 | inline bool EnableRCWCleanupOnSTAShutdown() |
482 | { |
483 | LIMITED_METHOD_CONTRACT; |
484 | return fEnableRCWCleanupOnSTAShutdown; |
485 | } |
486 | #endif // FEATURE_COMINTEROP |
487 | |
488 | #ifdef _DEBUG |
489 | bool ExpandModulesOnLoad(void) const { LIMITED_METHOD_CONTRACT; return fExpandAllOnLoad; } |
490 | #endif //_DEBUG |
491 | |
492 | #ifdef FEATURE_DOUBLE_ALIGNMENT_HINT |
493 | // Because the large object heap is 8 byte aligned, we want to put |
494 | // arrays of doubles there more agressively than normal objects. |
495 | // This is the threshold for this. It is the number of doubles, |
496 | // not the number of bytes in the array. |
497 | unsigned int GetDoubleArrayToLargeObjectHeapThreshold() const { LIMITED_METHOD_CONTRACT; return DoubleArrayToLargeObjectHeapThreshold; } |
498 | #endif |
499 | |
500 | inline bool ProbeForStackOverflow() const |
501 | { |
502 | LIMITED_METHOD_CONTRACT; |
503 | return fProbeForStackOverflow; |
504 | } |
505 | |
506 | inline bool AppDomainUnload() const |
507 | {LIMITED_METHOD_CONTRACT; return fAppDomainUnload; } |
508 | |
509 | inline DWORD AppDomainUnloadRetryCount() const |
510 | {LIMITED_METHOD_CONTRACT; return dwADURetryCount; } |
511 | |
512 | |
513 | #ifdef _DEBUG |
514 | inline bool AppDomainLeaks() const |
515 | { |
516 | // Workaround for CoreCLR bug #12075, until this configuration option is removed |
517 | // (CoreCLR Bug #12094) |
518 | LIMITED_METHOD_DAC_CONTRACT; |
519 | return false; |
520 | } |
521 | #endif |
522 | |
523 | #ifdef TEST_DATA_CONSISTENCY |
524 | // get the value of fTestDataConsistency, which controls whether we test that we can correctly detect |
525 | // held locks in DAC builds. This is determined by an environment variable. |
526 | inline bool TestDataConsistency() const { LIMITED_METHOD_DAC_CONTRACT; return fTestDataConsistency; } |
527 | #endif |
528 | |
529 | #ifdef _DEBUG |
530 | |
531 | unsigned SuspendThreadDeadlockTimeoutMs() const |
532 | {LIMITED_METHOD_CONTRACT; return m_SuspendThreadDeadlockTimeoutMs; } |
533 | |
534 | unsigned SuspendDeadlockTimeout() const |
535 | {LIMITED_METHOD_CONTRACT; return m_SuspendDeadlockTimeout; } |
536 | |
537 | // Verifier |
538 | bool IsVerifierOff() const {LIMITED_METHOD_CONTRACT; return fVerifierOff; } |
539 | |
540 | inline bool fAssertOnBadImageFormat() const |
541 | {LIMITED_METHOD_CONTRACT; return m_fAssertOnBadImageFormat; } |
542 | |
543 | inline bool fAssertOnFailFast() const |
544 | {LIMITED_METHOD_CONTRACT; return m_fAssertOnFailFast; } |
545 | |
546 | inline bool SuppressChecks() const |
547 | {LIMITED_METHOD_CONTRACT; return fSuppressChecks; } |
548 | |
549 | inline bool EnableFullDebug() const |
550 | {LIMITED_METHOD_CONTRACT; return fEnableFullDebug; } |
551 | |
552 | #endif |
553 | #ifdef ENABLE_STARTUP_DELAY |
554 | inline int StartupDelayMS() |
555 | { LIMITED_METHOD_CONTRACT; return iStartupDelayMS; } |
556 | #endif |
557 | |
558 | #ifdef VERIFY_HEAP |
559 | // GC config |
560 | enum HeapVerifyFlags { |
561 | HEAPVERIFY_NONE = 0, |
562 | HEAPVERIFY_GC = 1, // Verify the heap at beginning and end of GC |
563 | HEAPVERIFY_BARRIERCHECK = 2, // Verify the brick table |
564 | HEAPVERIFY_SYNCBLK = 4, // Verify sync block scanning |
565 | |
566 | // the following options can be used to mitigate some of the overhead introduced |
567 | // by heap verification. some options might cause heap verifiction to be less |
568 | // effective depending on the scenario. |
569 | |
570 | HEAPVERIFY_NO_RANGE_CHECKS = 0x10, // Excludes checking if an OBJECTREF is within the bounds of the managed heap |
571 | HEAPVERIFY_NO_MEM_FILL = 0x20, // Excludes filling unused segment portions with fill pattern |
572 | HEAPVERIFY_POST_GC_ONLY = 0x40, // Performs heap verification post-GCs only (instead of before and after each GC) |
573 | HEAPVERIFY_DEEP_ON_COMPACT = 0x80 // Performs deep object verfication only on compacting GCs. |
574 | }; |
575 | |
576 | int GetHeapVerifyLevel() {LIMITED_METHOD_CONTRACT; return iGCHeapVerify; } |
577 | |
578 | bool IsHeapVerifyEnabled() const {LIMITED_METHOD_CONTRACT; return iGCHeapVerify != 0; } |
579 | #endif |
580 | |
581 | #if defined(STRESS_HEAP) || defined(_DEBUG) |
582 | void SetGCStressLevel(int val) {LIMITED_METHOD_CONTRACT; iGCStress = val; } |
583 | |
584 | enum GCStressFlags { |
585 | GCSTRESS_NONE = 0, |
586 | GCSTRESS_ALLOC = 1, // GC on all allocs and 'easy' places |
587 | GCSTRESS_TRANSITION = 2, // GC on transitions to preemtive GC |
588 | GCSTRESS_INSTR_JIT = 4, // GC on every allowable JITed instr |
589 | GCSTRESS_INSTR_NGEN = 8, // GC on every allowable NGEN instr |
590 | GCSTRESS_UNIQUE = 16, // GC only on a unique stack trace |
591 | }; |
592 | |
593 | GCStressFlags GetGCStressLevel() const { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; return GCStressFlags(iGCStress); } |
594 | #endif |
595 | |
596 | #ifdef STRESS_HEAP |
597 | |
598 | bool IsGCStressMix () const {LIMITED_METHOD_CONTRACT; return iGCStressMix != 0;} |
599 | int GetGCStressStep() const {LIMITED_METHOD_CONTRACT; return iGCStressStep; } |
600 | #endif |
601 | |
602 | bool IsGCBreakOnOOMEnabled() const {LIMITED_METHOD_CONTRACT; return fGCBreakOnOOM; } |
603 | |
604 | size_t GetGCgen0size () const {LIMITED_METHOD_CONTRACT; return iGCgen0size; } |
605 | void SetGCgen0size (size_t iSize) {LIMITED_METHOD_CONTRACT; iGCgen0size = iSize; } |
606 | size_t GetSegmentSize () const {LIMITED_METHOD_CONTRACT; return iGCSegmentSize; } |
607 | void SetSegmentSize (size_t iSize) {LIMITED_METHOD_CONTRACT; iGCSegmentSize = iSize; } |
608 | |
609 | int GetGCconcurrent() const {LIMITED_METHOD_CONTRACT; return iGCconcurrent; } |
610 | void SetGCconcurrent(int val) {LIMITED_METHOD_CONTRACT; iGCconcurrent = val; } |
611 | #ifdef _DEBUG |
612 | int GetGCLatencyMode() const {LIMITED_METHOD_CONTRACT; return iGCLatencyMode; } |
613 | #endif //_DEBUG |
614 | int GetGCForceCompact() const {LIMITED_METHOD_CONTRACT; return iGCForceCompact; } |
615 | int GetGCRetainVM () const {LIMITED_METHOD_CONTRACT; return iGCHoardVM;} |
616 | DWORD GetGCLOHThreshold() const {LIMITED_METHOD_CONTRACT; return iGCLOHThreshold;} |
617 | int GetGCLOHCompactionMode() const {LIMITED_METHOD_CONTRACT; return iGCLOHCompactionMode;} |
618 | int GetGCHeapCount() const {LIMITED_METHOD_CONTRACT; return iGCHeapCount;} |
619 | int GetGCNoAffinitize () const {LIMITED_METHOD_CONTRACT; return iGCNoAffinitize;} |
620 | size_t GetGCAffinityMask() const {LIMITED_METHOD_CONTRACT; return iGCAffinityMask;} |
621 | |
622 | #ifdef GCTRIMCOMMIT |
623 | |
624 | int GetGCTrimCommit() const {LIMITED_METHOD_CONTRACT; return iGCTrimCommit;} |
625 | |
626 | #endif |
627 | |
628 | #ifdef FEATURE_CONSERVATIVE_GC |
629 | bool GetGCConservative() const {LIMITED_METHOD_CONTRACT; return iGCConservative;} |
630 | #endif |
631 | #ifdef _WIN64 |
632 | bool GetGCAllowVeryLargeObjects() const {LIMITED_METHOD_CONTRACT; return iGCAllowVeryLargeObjects;} |
633 | #endif |
634 | #ifdef _DEBUG |
635 | bool SkipGCCoverage(LPCUTF8 assemblyName) const {WRAPPER_NO_CONTRACT; return (pSkipGCCoverageList != NULL |
636 | && pSkipGCCoverageList->IsInList(assemblyName));} |
637 | #endif |
638 | |
639 | #ifdef _DEBUG |
640 | inline DWORD FastGCStressLevel() const |
641 | {LIMITED_METHOD_CONTRACT; return iFastGCStress;} |
642 | |
643 | inline DWORD InjectFatalError() const |
644 | { |
645 | LIMITED_METHOD_CONTRACT; |
646 | return iInjectFatalError; |
647 | } |
648 | |
649 | inline BOOL SaveThreadInfo() const |
650 | { |
651 | return fSaveThreadInfo; |
652 | } |
653 | |
654 | inline DWORD SaveThreadInfoMask() const |
655 | { |
656 | return dwSaveThreadInfoMask; |
657 | } |
658 | #endif |
659 | |
660 | |
661 | #ifdef _DEBUG |
662 | // Interop config |
663 | IUnknown* GetTraceIUnknown() const {LIMITED_METHOD_CONTRACT; return m_pTraceIUnknown; } |
664 | int GetTraceWrapper() const {LIMITED_METHOD_CONTRACT; return m_TraceWrapper; } |
665 | #endif |
666 | |
667 | // Loader |
668 | |
669 | enum RequireZapsType |
670 | { |
671 | REQUIRE_ZAPS_NONE, // Dont care if native image is used or not |
672 | REQUIRE_ZAPS_ALL, // All assemblies must have native images |
673 | REQUIRE_ZAPS_ALL_JIT_OK,// All assemblies must have native images, but its OK if the JIT-compiler also gets used (if some function was not ngenned) |
674 | REQUIRE_ZAPS_SUPPORTED, // All assemblies must have native images, unless the loader does not support the scenario. Its OK if the JIT-compiler also gets used |
675 | |
676 | REQUIRE_ZAPS_COUNT |
677 | }; |
678 | RequireZapsType RequireZaps() const {LIMITED_METHOD_CONTRACT; return iRequireZaps; } |
679 | bool RequireZap(LPCUTF8 assemblyName) const; |
680 | #ifdef _DEBUG |
681 | bool ForbidZap(LPCUTF8 assemblyName) const; |
682 | #endif |
683 | bool ExcludeReadyToRun(LPCUTF8 assemblyName) const; |
684 | |
685 | LPCWSTR ZapSet() const { LIMITED_METHOD_CONTRACT; return pZapSet; } |
686 | |
687 | bool NgenBindOptimizeNonGac() const { LIMITED_METHOD_CONTRACT; return fNgenBindOptimizeNonGac; } |
688 | |
689 | LPUTF8 GetZapBBInstr() const { LIMITED_METHOD_CONTRACT; return szZapBBInstr; } |
690 | LPWSTR GetZapBBInstrDir() const { LIMITED_METHOD_CONTRACT; return szZapBBInstrDir; } |
691 | DWORD DisableStackwalkCache() const {LIMITED_METHOD_CONTRACT; return dwDisableStackwalkCache; } |
692 | |
693 | bool StressLog() const { LIMITED_METHOD_CONTRACT; return fStressLog; } |
694 | bool ForceEnc() const { LIMITED_METHOD_CONTRACT; return fForceEnc; } |
695 | |
696 | // Optimizations to improve working set |
697 | |
698 | HRESULT sync(); // check the registry again and update local state |
699 | |
700 | // Helpers to read configuration |
701 | |
702 | // This function exposes the config file data to CLRConfig. A pointer to this function is passed into CLRConfig on EEConfig::init. |
703 | // We are using BOOLs instead of ConfigSearch for direction since CLRConfig isn't always linked to EEConfig. |
704 | static HRESULT GetConfigValueCallback(__in_z LPCWSTR pKey, __deref_out_opt LPCWSTR* value, BOOL systemOnly, BOOL applicationFirst); |
705 | |
706 | // |
707 | // NOTE: The following function is deprecated; use the CLRConfig class instead. |
708 | // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h. |
709 | // |
710 | static HRESULT GetConfigString_DontUse_(__in_z LPCWSTR name, __deref_out_z LPWSTR*out, BOOL fPrependCOMPLUS = TRUE, |
711 | ConfigSearch direction = CONFIG_SYSTEM); // Note that you own the returned string! |
712 | |
713 | // |
714 | // NOTE: The following function is deprecated; use the CLRConfig class instead. |
715 | // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h. |
716 | // |
717 | static DWORD GetConfigDWORD_DontUse_(__in_z LPCWSTR name, DWORD defValue, |
718 | DWORD level=(DWORD) REGUTIL::COR_CONFIG_ALL, |
719 | BOOL fPrependCOMPLUS = TRUE, |
720 | ConfigSearch direction = CONFIG_SYSTEM); |
721 | |
722 | // |
723 | // NOTE: The following function is deprecated; use the CLRConfig class instead. |
724 | // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h. |
725 | // |
726 | static ULONGLONG GetConfigULONGLONG_DontUse_(__in_z LPCWSTR name, ULONGLONG defValue, |
727 | DWORD level=(DWORD) REGUTIL::COR_CONFIG_ALL, |
728 | BOOL fPrependCOMPLUS = TRUE, |
729 | ConfigSearch direction = CONFIG_SYSTEM); |
730 | // |
731 | // NOTE: The following function is deprecated; use the CLRConfig class instead. |
732 | // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h. |
733 | // |
734 | static DWORD GetConfigDWORDFavoringConfigFile_DontUse_(__in_z LPCWSTR name, DWORD defValue, |
735 | DWORD level=(DWORD) REGUTIL::COR_CONFIG_ALL, |
736 | BOOL fPrependCOMPLUS = TRUE, |
737 | ConfigSearch direction = CONFIG_SYSTEM); |
738 | |
739 | // |
740 | // NOTE: The following function is deprecated; use the CLRConfig class instead. |
741 | // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h. |
742 | // |
743 | static DWORD GetConfigFlag_DontUse_(__in_z LPCWSTR name, DWORD bitToSet, bool defValue = FALSE); |
744 | |
745 | #ifdef _DEBUG |
746 | // GC alloc logging |
747 | bool ShouldLogAlloc(const char *pClass) const { LIMITED_METHOD_CONTRACT; return pPerfTypesToLog && pPerfTypesToLog->IsInList(pClass);} |
748 | int AllocSizeThreshold() const {LIMITED_METHOD_CONTRACT; return iPerfAllocsSizeThreshold; } |
749 | int AllocNumThreshold() const { LIMITED_METHOD_CONTRACT; return iPerfNumAllocsThreshold; } |
750 | |
751 | #endif // _DEBUG |
752 | |
753 | #ifdef _DEBUG |
754 | DWORD NgenForceFailureMask() { LIMITED_METHOD_CONTRACT; return dwNgenForceFailureMask; } |
755 | DWORD NgenForceFailureCount() { LIMITED_METHOD_CONTRACT; return dwNgenForceFailureCount; } |
756 | DWORD NgenForceFailureKind() { LIMITED_METHOD_CONTRACT; return dwNgenForceFailureKind; } |
757 | #endif |
758 | enum GCPollType |
759 | { |
760 | GCPOLL_TYPE_DEFAULT, // Use the default gc poll for the platform |
761 | GCPOLL_TYPE_HIJACK, // Depend on thread hijacking for gc suspension |
762 | GCPOLL_TYPE_POLL, // Emit function calls to a helper for GC Poll |
763 | GCPOLL_TYPE_INLINE, // Emit inlined tests to the helper for GC Poll |
764 | GCPOLL_TYPE_COUNT |
765 | }; |
766 | GCPollType GetGCPollType() { LIMITED_METHOD_CONTRACT; return iGCPollType; } |
767 | |
768 | #ifdef _DEBUG |
769 | |
770 | DWORD GetHostTestThreadAbort() const {LIMITED_METHOD_CONTRACT; return testThreadAbort;} |
771 | |
772 | #define INJECTFAULT_LOADERHEAP 0x1 |
773 | #define INJECTFAULT_GCHEAP 0x2 |
774 | #define INJECTFAULT_SO 0x4 |
775 | #define INJECTFAULT_GMHEAP 0x8 |
776 | #define INJECTFAULT_DYNAMICCODEHEAP 0x10 |
777 | #define INJECTFAULT_MAPVIEWOFFILE 0x20 |
778 | #define INJECTFAULT_JITHEAP 0x40 |
779 | |
780 | DWORD ShouldInjectFault(DWORD faultType) const {LIMITED_METHOD_CONTRACT; return fShouldInjectFault & faultType;} |
781 | |
782 | #endif |
783 | |
784 | private: //---------------------------------------------------------------- |
785 | |
786 | bool fInited; // have we synced to the registry at least once? |
787 | |
788 | // Jit-config |
789 | |
790 | bool fJitFramed; // Enable/Disable EBP based frames |
791 | bool fJitAlignLoops; // Enable/Disable loop alignment |
792 | bool fAddRejitNops; // Enable/Disable nop padding for rejit. default is true |
793 | bool fJitMinOpts; // Enable MinOpts for all jitted methods |
794 | |
795 | unsigned iJitOptimizeType; // 0=Blended,1=SmallCode,2=FastCode, default is 0=Blended |
796 | |
797 | unsigned fPInvokeRestoreEsp; // -1=Default, 0=Never, Else=Always |
798 | |
799 | bool fLegacyNullReferenceExceptionPolicy; // Old AV's as NullRef behavior |
800 | bool fLegacyUnhandledExceptionPolicy; // Old unhandled exception policy (many are swallowed) |
801 | |
802 | #ifdef FEATURE_CORRUPTING_EXCEPTIONS |
803 | bool fLegacyCorruptedStateExceptionsPolicy; |
804 | #endif // FEATURE_CORRUPTING_EXCEPTIONS |
805 | |
806 | LPUTF8 pszBreakOnClassLoad; // Halt just before loading this class |
807 | |
808 | #ifdef TEST_DATA_CONSISTENCY |
809 | bool fTestDataConsistency; // true if we are testing locks for data consistency in the debugger-- |
810 | // If a lock is held during inspection, we assume the data under the lock |
811 | // is inconsistent. We have a special code path for testing this |
812 | // which we will follow if this is set. The value is determined by |
813 | // the environment variable TestDataConsistency |
814 | #endif |
815 | |
816 | bool m_fInteropValidatePinnedObjects; // After returning from a M->U interop call, validate GC heap around objects pinned by IL stubs. |
817 | bool m_fInteropLogArguments; // Log all pinned arguments passed to an interop call |
818 | |
819 | #ifdef _DEBUG |
820 | static HRESULT ParseMethList(__in_z LPWSTR str, MethodNamesList* * out); |
821 | static void DestroyMethList(MethodNamesList* list); |
822 | static bool IsInMethList(MethodNamesList* list, MethodDesc* pMD); |
823 | |
824 | bool fDebuggable; |
825 | bool fStressOn; |
826 | int apiThreadStressCount; |
827 | |
828 | MethodNamesList* pPrestubHalt; // list of methods on which to break when hit prestub |
829 | MethodNamesList* pPrestubGC; // list of methods on which to cause a GC when hit prestub |
830 | MethodNamesList* pInvokeHalt; // list of methods on which to break when hit prestub |
831 | |
832 | |
833 | LPUTF8 pszBreakOnClassBuild; // Halt just before loading this class |
834 | LPUTF8 pszBreakOnInstantiation; // Halt just before instantiating a non-canonical generic type |
835 | LPUTF8 pszBreakOnMethodName; // Halt when doing something with this method in the class defined in ClassBuild |
836 | LPUTF8 pszDumpOnClassLoad; // Dump the class to the log |
837 | |
838 | LPUTF8 pszBreakOnInteropStubSetup; // Halt before we set up the interop stub for a method |
839 | LPUTF8 pszBreakOnComToClrNativeInfoInit; // Halt before we init the native info for a COM to CLR call |
840 | LPUTF8 pszBreakOnStructMarshalSetup; // Halt before the field marshallers are set up for a struct |
841 | |
842 | bool m_fAssertOnBadImageFormat; // If false, don't assert on invalid IL (for testing) |
843 | bool m_fAssertOnFailFast; // If false, don't assert if we detect a stack corruption |
844 | |
845 | bool fConditionalContracts; // Conditional contracts (off inside asserts) |
846 | bool fSuppressChecks; // Disable checks (including contracts) |
847 | |
848 | DWORD iExposeExceptionsInCOM; // Should we exposed exceptions that will be transformed into HRs? |
849 | |
850 | unsigned m_SuspendThreadDeadlockTimeoutMs; // Used in Thread::SuspendThread() |
851 | unsigned m_SuspendDeadlockTimeout; // Used in Thread::SuspendRuntime. |
852 | |
853 | bool fEnableFullDebug; |
854 | #endif // _DEBUG |
855 | |
856 | #ifdef FEATURE_COMINTEROP |
857 | bool bLogCCWRefCountChange; // Is CCW logging on |
858 | LPCUTF8 pszLogCCWRefCountChange; // OutputDebugString when AddRef/Release is called on a CCW |
859 | // for the specified type(s) |
860 | bool fEnableRCWCleanupOnSTAShutdown; // Register our IInitializeSpy even in classic processes |
861 | #endif // FEATURE_COMINTEROP |
862 | |
863 | #ifdef FEATURE_DOUBLE_ALIGNMENT_HINT |
864 | unsigned int DoubleArrayToLargeObjectHeapThreshold; // double arrays of more than this number of elems go in large object heap |
865 | #endif |
866 | |
867 | bool fAppDomainUnload; // Enable appdomain unloading |
868 | |
869 | DWORD dwADURetryCount; |
870 | |
871 | #ifdef _DEBUG |
872 | bool fExpandAllOnLoad; // True if we want to load all types/jit all methods in an assembly |
873 | // at load time. |
874 | bool fJitVerificationDisable; // Turn off jit verification (for testing purposes only) |
875 | |
876 | |
877 | // Verifier |
878 | bool fVerifierOff; |
879 | |
880 | #ifdef WIN64EXCEPTIONS |
881 | bool fSuppressLockViolationsOnReentryFromOS; |
882 | #endif |
883 | |
884 | #ifdef STUBLINKER_GENERATES_UNWIND_INFO |
885 | bool fStubLinkerUnwindInfoVerificationOn; |
886 | #endif |
887 | #endif // _DEBUG |
888 | #ifdef ENABLE_STARTUP_DELAY |
889 | int iStartupDelayMS; //Adds sleep to startup. |
890 | #endif |
891 | |
892 | // Spinning heuristics |
893 | DWORD dwSpinInitialDuration; |
894 | DWORD dwSpinBackoffFactor; |
895 | DWORD dwSpinLimitProcCap; |
896 | DWORD dwSpinLimitProcFactor; |
897 | DWORD dwSpinLimitConstant; |
898 | DWORD dwSpinRetryCount; |
899 | DWORD dwMonitorSpinCount; |
900 | |
901 | #ifdef VERIFY_HEAP |
902 | int iGCHeapVerify; |
903 | #endif |
904 | |
905 | #if defined(STRESS_HEAP) || defined(_DEBUG) |
906 | int iGCStress; |
907 | #endif |
908 | |
909 | #ifdef STRESS_HEAP |
910 | int iGCStressMix; |
911 | int iGCStressStep; |
912 | #endif |
913 | |
914 | #define DEFAULT_GC_PRN_LVL 3 |
915 | size_t iGCgen0size; |
916 | size_t iGCSegmentSize; |
917 | int iGCconcurrent; |
918 | #ifdef _DEBUG |
919 | int iGCLatencyMode; |
920 | #endif //_DEBUG |
921 | int iGCForceCompact; |
922 | int iGCHoardVM; |
923 | int iGCLOHCompactionMode; |
924 | DWORD iGCLOHThreshold; |
925 | int iGCHeapCount; |
926 | int iGCNoAffinitize; |
927 | size_t iGCAffinityMask; |
928 | |
929 | #ifdef GCTRIMCOMMIT |
930 | |
931 | int iGCTrimCommit; |
932 | |
933 | #endif |
934 | |
935 | #ifdef FEATURE_CONSERVATIVE_GC |
936 | bool iGCConservative; |
937 | #endif // FEATURE_CONSERVATIVE_GC |
938 | #ifdef _WIN64 |
939 | bool iGCAllowVeryLargeObjects; |
940 | #endif // _WIN64 |
941 | |
942 | bool fGCBreakOnOOM; |
943 | |
944 | #ifdef _DEBUG |
945 | DWORD iFastGCStress; |
946 | LPUTF8 pszGcCoverageOnMethod; |
947 | |
948 | DWORD iInjectFatalError; |
949 | |
950 | BOOL fSaveThreadInfo; |
951 | DWORD dwSaveThreadInfoMask; |
952 | |
953 | AssemblyNamesList *pSkipGCCoverageList; |
954 | #endif |
955 | |
956 | RequireZapsType iRequireZaps; |
957 | // Assemblies which need to have native images. |
958 | // This is only used if iRequireZaps!=REQUIRE_ZAPS_NONE |
959 | // This can be used to enforce that ngen images are used only selectively for some assemblies |
960 | AssemblyNamesList * pRequireZapsList; |
961 | // assemblies which need NOT have native images. |
962 | // This is only used if iRequireZaps!=REQUIRE_ZAPS_NONE |
963 | // This overrides pRequireZapsList. |
964 | AssemblyNamesList * pRequireZapsExcludeList; |
965 | |
966 | // Assemblies which cannot use Ready to Run images. |
967 | AssemblyNamesList * pReadyToRunExcludeList; |
968 | |
969 | #ifdef _DEBUG |
970 | // Exact opposite of require zaps |
971 | BOOL iForbidZaps; |
972 | AssemblyNamesList * pForbidZapsList; |
973 | AssemblyNamesList * pForbidZapsExcludeList; |
974 | #endif |
975 | |
976 | LPCWSTR pZapSet; |
977 | |
978 | bool fNgenBindOptimizeNonGac; |
979 | |
980 | bool fStressLog; |
981 | bool fForceEnc; |
982 | bool fProbeForStackOverflow; |
983 | |
984 | // Stackwalk optimization flag |
985 | DWORD dwDisableStackwalkCache; |
986 | |
987 | LPUTF8 szZapBBInstr; |
988 | LPWSTR szZapBBInstrDir; |
989 | |
990 | #ifdef _DEBUG |
991 | // interop logging |
992 | IUnknown* m_pTraceIUnknown; |
993 | int m_TraceWrapper; |
994 | #endif |
995 | |
996 | // Flag to keep track of memory |
997 | int m_fFreepZapSet; |
998 | |
999 | #ifdef _DEBUG |
1000 | // GC Alloc perf flags |
1001 | int iPerfNumAllocsThreshold; // Start logging after this many allocations are made |
1002 | int iPerfAllocsSizeThreshold; // Log allocations of this size or above |
1003 | TypeNamesList* pPerfTypesToLog; // List of types whose allocations are to be logged |
1004 | |
1005 | #endif // _DEBUG |
1006 | |
1007 | // New configuration |
1008 | ConfigList m_Configuration; |
1009 | |
1010 | #ifdef _DEBUG |
1011 | DWORD dwNgenForceFailureMask; |
1012 | DWORD dwNgenForceFailureCount; |
1013 | DWORD dwNgenForceFailureKind; |
1014 | #endif |
1015 | |
1016 | GCPollType iGCPollType; |
1017 | |
1018 | #ifdef _DEBUG |
1019 | DWORD fShouldInjectFault; |
1020 | DWORD testThreadAbort; |
1021 | #endif |
1022 | |
1023 | #if defined(FEATURE_TIERED_COMPILATION) |
1024 | bool fTieredCompilation; |
1025 | bool fTieredCompilation_CallCounting; |
1026 | bool fTieredCompilation_OptimizeTier0; |
1027 | DWORD tieredCompilation_tier1CallCountThreshold; |
1028 | DWORD tieredCompilation_tier1CallCountingDelayMs; |
1029 | #endif |
1030 | |
1031 | #if defined(FEATURE_GDBJIT) && defined(_DEBUG) |
1032 | LPCUTF8 pszGDBJitElfDump; |
1033 | #endif // FEATURE_GDBJIT && _DEBUG |
1034 | |
1035 | #if defined(FEATURE_GDBJIT_FRAME) |
1036 | bool fGDBJitEmitDebugFrame; |
1037 | #endif |
1038 | public: |
1039 | |
1040 | HRESULT GetConfiguration_DontUse_(__in_z LPCWSTR pKey, ConfigSearch direction, __deref_out_opt LPCWSTR* value); |
1041 | |
1042 | DWORD GetConfigDWORDInternal_DontUse_ (__in_z LPCWSTR name, DWORD defValue, //for getting data in the constructor of EEConfig |
1043 | DWORD level=(DWORD) REGUTIL::COR_CONFIG_ALL, |
1044 | BOOL fPrependCOMPLUS = TRUE, |
1045 | ConfigSearch direction = CONFIG_SYSTEM); |
1046 | |
1047 | enum BitForMask { |
1048 | CallSite_1 = 0x0001, |
1049 | CallSite_2 = 0x0002, |
1050 | CallSite_3 = 0x0004, |
1051 | CallSite_4 = 0x0008, |
1052 | CallSite_5 = 0x0010, |
1053 | CallSite_6 = 0x0020, |
1054 | CallSite_7 = 0x0040, |
1055 | CallSite_8 = 0x0080, |
1056 | }; |
1057 | |
1058 | #if defined(_DEBUG) && !defined(DACCESS_COMPILE) |
1059 | void DebugCheckAndForceIBCFailure(BitForMask bitForMask); |
1060 | #endif |
1061 | |
1062 | #if defined(_DEBUG) |
1063 | #if defined(_TARGET_AMD64_) |
1064 | private: |
1065 | |
1066 | // Defaults to 0, which means we will not generate long jump dispatch stubs. |
1067 | // But if this is set to a positive integer, then this |
1068 | // will be 1/x ration of stubs we generate as long jump. So if x is 4, then |
1069 | // every 1 in 4 dispatch stubs will be long jump stubs. |
1070 | size_t m_cGenerateLongJumpDispatchStubRatio; |
1071 | |
1072 | // Total count of stubs generated, used with above variable to determine if |
1073 | // the next stub should be a long jump. |
1074 | size_t m_cDispatchStubsGenerated; |
1075 | |
1076 | public: |
1077 | BOOL ShouldGenerateLongJumpDispatchStub() |
1078 | { |
1079 | return (m_cDispatchStubsGenerated++ % m_cGenerateLongJumpDispatchStubRatio) == 0; |
1080 | } |
1081 | #else |
1082 | public: |
1083 | // Just return false when we're in DEBUG but not on AMD64 |
1084 | BOOL ShouldGenerateLongJumpDispatchStub() |
1085 | { |
1086 | return FALSE; |
1087 | } |
1088 | #endif // _TARGET_AMD64_ |
1089 | #endif // _DEBUG |
1090 | |
1091 | #if defined(_DEBUG) |
1092 | private: |
1093 | bool bDiagnosticSuspend; |
1094 | |
1095 | public: |
1096 | bool GetDiagnosticSuspend() |
1097 | { return bDiagnosticSuspend; } |
1098 | #endif |
1099 | |
1100 | private: |
1101 | DWORD dwSleepOnExit; |
1102 | |
1103 | public: |
1104 | DWORD GetSleepOnExit() |
1105 | { return dwSleepOnExit; } |
1106 | }; |
1107 | |
1108 | |
1109 | |
1110 | #ifdef _DEBUG_IMPL |
1111 | |
1112 | // We actually want our asserts for illegal IL, but testers need to test that |
1113 | // we fail gracefully under those conditions. Thus we have to hide them for those runs. |
1114 | #define BAD_FORMAT_NOTHROW_ASSERT(str) \ |
1115 | do { \ |
1116 | if (g_pConfig->fAssertOnBadImageFormat()) { \ |
1117 | _ASSERTE(str); \ |
1118 | } \ |
1119 | else if (!(str)) { \ |
1120 | if (IsDebuggerPresent()) DebugBreak(); \ |
1121 | } \ |
1122 | } while(0) |
1123 | |
1124 | // STRESS_ASSERT is meant to be temperary additions to the code base that stop the |
1125 | // runtime quickly when running stress |
1126 | #define STRESS_ASSERT(cond) do { if (!(cond) && g_pConfig->IsStressOn()) DebugBreak(); } while(0) |
1127 | |
1128 | #define FILE_FORMAT_CHECK_MSG(_condition, _message) \ |
1129 | do { \ |
1130 | if (g_pConfig != NULL && g_pConfig->fAssertOnBadImageFormat()) \ |
1131 | ASSERT_CHECK(_condition, _message, "Bad file format"); \ |
1132 | else if (!(_condition)) \ |
1133 | DebugBreak(); \ |
1134 | } while (0) |
1135 | |
1136 | #define FILE_FORMAT_CHECK(_condition) FILE_FORMAT_CHECK_MSG(_condition, "") |
1137 | |
1138 | #else |
1139 | |
1140 | #define STRESS_ASSERT(cond) |
1141 | #define BAD_FORMAT_NOTHROW_ASSERT(str) |
1142 | |
1143 | #define FILE_FORMAT_CHECK_MSG(_condition, _message) |
1144 | #define FILE_FORMAT_CHECK(_condition) |
1145 | |
1146 | #endif |
1147 | |
1148 | extern BOOL g_CLRPolicyRequested; |
1149 | |
1150 | // NGENImagesAllowed is the safe way to determine if NGEN Images are allowed to be loaded. (Defined as |
1151 | // a macro instead of an inlined function to avoid compilation errors due to dependent |
1152 | // definitions not being available to this header.) |
1153 | #ifdef PROFILING_SUPPORTED |
1154 | #define NGENImagesAllowed() \ |
1155 | (g_fAllowNativeImages && /* No one disabled use of native images */ \ |
1156 | !(CORProfilerDisableAllNGenImages())) /* Profiler didn't explicitly refuse NGEN images */ |
1157 | #else |
1158 | #define NGENImagesAllowed() \ |
1159 | (g_fAllowNativeImages) |
1160 | #endif |
1161 | |
1162 | #endif // EECONFIG_H |
1163 | |