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
17class MethodDesc;
18
19#include "shash.h"
20#include "corhost.h"
21
22#ifdef _DEBUG
23class 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
35public:
36 TypeNamesList();
37 ~TypeNamesList();
38
39 HRESULT Init(__in_z LPCWSTR str);
40 bool IsInList(LPCUTF8 typeName);
41};
42#endif
43
44typedef 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
61typedef WStringSHash<ConfigStringKeyValuePair> ConfigStringHashtable;
62
63class 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//
69class ConfigSource
70{
71 friend class ConfigList;
72public:
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
96private:
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//
105class ConfigList
106{
107public:
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
234friend class ConfigIter;
235
236private:
237 ConfigSource m_pElement;
238};
239
240enum { OPT_BLENDED,
241 OPT_SIZE,
242 OPT_SPEED,
243 OPT_RANDOM,
244 OPT_DEFAULT = OPT_BLENDED };
245
246enum ParseCtl {
247 parseAll, // parse entire config file
248 stopAfterRuntimeSection // stop after <runtime>...</runtime> section
249};
250
251class EEConfig
252{
253public:
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
784private: //----------------------------------------------------------------
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
1038public:
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_)
1064private:
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
1076public:
1077 BOOL ShouldGenerateLongJumpDispatchStub()
1078 {
1079 return (m_cDispatchStubsGenerated++ % m_cGenerateLongJumpDispatchStubRatio) == 0;
1080 }
1081#else
1082public:
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)
1092private:
1093 bool bDiagnosticSuspend;
1094
1095public:
1096 bool GetDiagnosticSuspend()
1097 { return bDiagnosticSuspend; }
1098#endif
1099
1100private:
1101 DWORD dwSleepOnExit;
1102
1103public:
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
1148extern 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