[Tizen] Unify dnetmemoryenumlib terms to match the codebase (#291)
[platform/upstream/coreclr.git] / src / vm / codeman.h
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 Module Name:
11
12     codeman.h
13
14 Abstract:
15
16     Wrapper to facilitate multiple JITcompiler support in the COM+ Runtime
17
18     The ExecutionManager is responsible for managing the RangeSections.
19     Given an IP, it can find the RangeSection which holds that IP.
20
21     RangeSections contain the JITed codes. Each RangeSection knows the 
22     IJitManager which created it.
23
24     An IJitManager knows about which method bodies live in each RangeSection.
25     It can handle methods of one given CodeType. It can map a method body to
26     a MethodDesc. It knows where the GCInfo about the method lives.
27     Today, we have three IJitManagers viz.
28     1. EEJitManager for JITcompiled code generated by clrjit.dll
29     2. NativeImageJitManager for ngenned code.
30     3. ReadyToRunJitManager for version resiliant ReadyToRun code
31
32     An ICodeManager knows how to crack a specific format of GCInfo. There is
33     a default format (handled by ExecutionManager::GetDefaultCodeManager())
34     which can be shared by different IJitManagers/IJitCompilers.
35
36     An ICorJitCompiler knows how to generate code for a method IL, and produce
37     GCInfo in a format which the corresponding IJitManager's ICodeManager 
38     can handle.
39
40                                                ExecutionManager
41                                                        |
42                            +-----------+---------------+---------------+-----------+--- ...
43                            |           |                               |           |
44                         CodeType       |                            CodeType       |
45                            |           |                               |           |
46                            v           v                               v           v
47 +---------------+      +--------+<---- R    +---------------+      +--------+<---- R
48 |ICorJitCompiler|<---->|IJitMan |<---- R    |ICorJitCompiler|<---->|IJitMan |<---- R
49 +---------------+      +--------+<---- R    +---------------+      +--------+<---- R
50                            |       x   .                               |       x   .
51                            |        \  .                               |        \  .
52                            v         \ .                               v         \ .
53                        +--------+      R                           +--------+      R
54                        |ICodeMan|                                  |ICodeMan|     (RangeSections)
55                        +--------+                                  +--------+       
56
57 ******************************************************************************/
58
59 #ifndef __CODEMAN_HPP__
60
61 #define __CODEMAN_HPP__
62
63 #include "crst.h"
64 #include "eetwain.h"
65 #include "ceeload.h"
66 #include "jitinterface.h"
67 #include "debuginfostore.h"
68 #include "shash.h"
69 #include "pedecoder.h"
70 #include "gcinfo.h"
71 #include "eexcp.h"
72
73 #if defined(WIN64EXCEPTIONS) && !defined(USE_INDIRECT_CODEHEADER)
74 #error "WIN64EXCEPTIONS requires USE_INDIRECT_CODEHEADER"
75 #endif // WIN64EXCEPTIONS && !USE_INDIRECT_CODEHEADER
76
77 class MethodDesc;
78 class ICorJitCompiler;
79 class IJitManager;
80 class EEJitManager;
81 class NativeImageJitManager;
82 class ReadyToRunJitManager;
83 class ExecutionManager;
84 class Thread;
85 class CrawlFrame;
86 struct EE_ILEXCEPTION;
87 struct EE_ILEXCEPTION_CLAUSE;
88 typedef struct 
89 {
90     unsigned iCurrentPos;
91     TADDR pExceptionClauseArray;
92 } EH_CLAUSE_ENUMERATOR;
93 class EECodeInfo;
94
95 #define ROUND_DOWN_TO_PAGE(x)   ( (size_t) (x)                        & ~((size_t)GetOsPageSize()-1))
96 #define ROUND_UP_TO_PAGE(x)     (((size_t) (x) + (GetOsPageSize()-1)) & ~((size_t)GetOsPageSize()-1))
97
98 enum StubCodeBlockKind : int
99 {
100     STUB_CODE_BLOCK_UNKNOWN,
101     STUB_CODE_BLOCK_JUMPSTUB,
102     STUB_CODE_BLOCK_PRECODE,
103     STUB_CODE_BLOCK_DYNAMICHELPER,
104     // Last valid value. Note that the definition is duplicated in debug\daccess\fntableaccess.cpp
105     STUB_CODE_BLOCK_LAST = 0xF,
106     // Placeholders returned by code:GetStubCodeBlockKind
107     STUB_CODE_BLOCK_NOCODE,
108     STUB_CODE_BLOCK_MANAGED,
109     STUB_CODE_BLOCK_STUBLINK,
110     // Placeholdes used by NGen images
111     STUB_CODE_BLOCK_VIRTUAL_METHOD_THUNK,
112     STUB_CODE_BLOCK_EXTERNAL_METHOD_THUNK,
113     // Placeholdes used by ReadyToRun images
114     STUB_CODE_BLOCK_METHOD_CALL_THUNK,
115 };
116
117 //-----------------------------------------------------------------------------
118 // Method header which exists just before the code.
119 // Every IJitManager could have its own format for the header. 
120 // Today CodeHeader is used by the EEJitManager.
121 // The GCInfo version is always current GCINFO_VERSION in this header.
122
123 #ifdef USE_INDIRECT_CODEHEADER
124 typedef DPTR(struct _hpRealCodeHdr) PTR_RealCodeHeader;
125 typedef DPTR(struct _hpCodeHdr) PTR_CodeHeader;
126
127 #else // USE_INDIRECT_CODEHEADER
128 typedef DPTR(struct _hpCodeHdr) PTR_CodeHeader;
129
130 #endif // USE_INDIRECT_CODEHEADER
131
132 #ifdef USE_INDIRECT_CODEHEADER
133 typedef struct _hpRealCodeHdr
134 #else // USE_INDIRECT_CODEHEADER
135 typedef struct _hpCodeHdr
136 #endif // USE_INDIRECT_CODEHEADER
137 {
138 public:
139     PTR_BYTE            phdrDebugInfo;
140     
141     // Note - *(&(pCodeHeader->phdrJitEHInfo) - sizeof(size_t)) 
142     // contains the number of EH clauses, See EEJitManager::allocEHInfo
143     PTR_EE_ILEXCEPTION  phdrJitEHInfo;
144     PTR_BYTE            phdrJitGCInfo;
145
146 #if defined(FEATURE_GDBJIT)
147     VOID*            pCalledMethods;
148 #endif
149
150     PTR_MethodDesc      phdrMDesc;
151
152 #ifdef WIN64EXCEPTIONS
153     DWORD               nUnwindInfos;
154     T_RUNTIME_FUNCTION  unwindInfos[0];
155 #endif // WIN64EXCEPTIONS
156
157 public:
158 #ifndef USE_INDIRECT_CODEHEADER
159     //
160     // Note: that the JITted code follows immediately after the MethodDesc*
161     //
162     PTR_BYTE                GetDebugInfo()
163     {
164         SUPPORTS_DAC;
165
166         return phdrDebugInfo;
167     }
168     PTR_EE_ILEXCEPTION      GetEHInfo()
169     {
170         return phdrJitEHInfo;
171     }
172     PTR_BYTE                GetGCInfo()
173     {
174         SUPPORTS_DAC;
175         return phdrJitGCInfo;
176     }
177     PTR_MethodDesc          GetMethodDesc()
178     {
179         SUPPORTS_DAC;
180         return phdrMDesc;
181     }
182 #if defined(FEATURE_GDBJIT)
183     VOID*                GetCalledMethods()
184     {
185         SUPPORTS_DAC;
186         return pCalledMethods;
187     }
188 #endif
189     TADDR                   GetCodeStartAddress()
190     {
191         SUPPORTS_DAC;
192         return dac_cast<TADDR>(dac_cast<PTR_CodeHeader>(this) + 1);
193     }
194     StubCodeBlockKind       GetStubCodeBlockKind()
195     {
196         SUPPORTS_DAC;
197         return (StubCodeBlockKind)dac_cast<TADDR>(phdrMDesc);
198     }
199     BOOL                    IsStubCodeBlock()
200     {
201         SUPPORTS_DAC;
202         // Note that it is important for this comparison to be unsigned
203         return dac_cast<TADDR>(phdrMDesc) <= (TADDR)STUB_CODE_BLOCK_LAST;
204     }
205
206     void SetDebugInfo(PTR_BYTE pDI)
207     {
208         phdrDebugInfo = pDI;
209     }
210     void SetEHInfo(PTR_EE_ILEXCEPTION pEH)
211     {
212         phdrJitEHInfo = pEH;
213     }
214     void SetGCInfo(PTR_BYTE pGC)
215     {
216         phdrJitGCInfo = pGC;
217     }
218     void SetMethodDesc(PTR_MethodDesc pMD)
219     {
220         phdrMDesc = pMD;
221     }
222 #if defined(FEATURE_GDBJIT)
223     void SetCalledMethods(VOID* pCM)
224     {
225         pCalledMethods = pCM;
226     }
227 #endif
228     void SetStubCodeBlockKind(StubCodeBlockKind kind)
229     {
230         phdrMDesc = (PTR_MethodDesc)kind;
231     }
232 #endif // !USE_INDIRECT_CODEHEADER
233
234 // if we're using the indirect codeheaders then all enumeration is done by the code header
235 #ifndef USE_INDIRECT_CODEHEADER
236 #ifdef DACCESS_COMPILE
237     void EnumMemoryRegions(CLRDataEnumMemoryFlags flags, IJitManager* pJitMan);
238 #endif  // DACCESS_COMPILE
239 #endif  // USE_INDIRECT_CODEHEADER
240 #ifdef USE_INDIRECT_CODEHEADER
241 } RealCodeHeader;
242 #else // USE_INDIRECT_CODEHEADER
243 } CodeHeader;
244 #endif // USE_INDIRECT_CODEHEADER
245
246 #ifdef USE_INDIRECT_CODEHEADER
247 typedef struct _hpCodeHdr
248 {
249     PTR_RealCodeHeader   pRealCodeHeader;
250
251 public:
252     PTR_BYTE                GetDebugInfo()
253     {
254         SUPPORTS_DAC;
255         return pRealCodeHeader->phdrDebugInfo;
256     }
257     PTR_EE_ILEXCEPTION      GetEHInfo()
258     {
259         return pRealCodeHeader->phdrJitEHInfo;
260     }
261     PTR_BYTE                GetGCInfo()
262     {
263         SUPPORTS_DAC;
264         return pRealCodeHeader->phdrJitGCInfo;
265     }
266     PTR_MethodDesc          GetMethodDesc()
267     {
268         SUPPORTS_DAC;
269         return pRealCodeHeader->phdrMDesc;
270     }
271 #if defined(FEATURE_GDBJIT)
272     VOID*                GetCalledMethods()
273     {
274         SUPPORTS_DAC;
275         return pRealCodeHeader->pCalledMethods;
276     }
277 #endif
278     TADDR                   GetCodeStartAddress()
279     {        
280         SUPPORTS_DAC;
281         return dac_cast<PCODE>(dac_cast<PTR_CodeHeader>(this) + 1);
282     }
283     StubCodeBlockKind       GetStubCodeBlockKind()
284     {
285         SUPPORTS_DAC;
286         return (StubCodeBlockKind)dac_cast<TADDR>(pRealCodeHeader);
287     }
288     BOOL                    IsStubCodeBlock()
289     {
290         SUPPORTS_DAC;
291         // Note that it is important for this comparison to be unsigned
292         return dac_cast<TADDR>(pRealCodeHeader) <= (TADDR)STUB_CODE_BLOCK_LAST;
293     }
294
295     void SetRealCodeHeader(BYTE* pRCH)
296     {
297         pRealCodeHeader = PTR_RealCodeHeader((RealCodeHeader*)pRCH);
298     }
299
300     void SetDebugInfo(PTR_BYTE pDI)
301     {
302         pRealCodeHeader->phdrDebugInfo = pDI;
303     }
304     void SetEHInfo(PTR_EE_ILEXCEPTION pEH)
305     {
306         pRealCodeHeader->phdrJitEHInfo = pEH;
307     }
308     void SetGCInfo(PTR_BYTE pGC)
309     {
310         pRealCodeHeader->phdrJitGCInfo = pGC;
311     }
312     void SetMethodDesc(PTR_MethodDesc pMD)
313     {
314         pRealCodeHeader->phdrMDesc = pMD;
315     }
316 #if defined(FEATURE_GDBJIT)
317     void SetCalledMethods(VOID* pCM)
318     {
319         pRealCodeHeader->pCalledMethods = pCM;
320     }
321 #endif
322     void SetStubCodeBlockKind(StubCodeBlockKind kind)
323     {
324         pRealCodeHeader = (PTR_RealCodeHeader)kind;
325     }
326
327 #if defined(WIN64EXCEPTIONS)
328     UINT                    GetNumberOfUnwindInfos()
329     {
330         SUPPORTS_DAC;
331         return pRealCodeHeader->nUnwindInfos;
332     }
333     void                    SetNumberOfUnwindInfos(UINT nUnwindInfos)
334     {
335         LIMITED_METHOD_CONTRACT;
336         pRealCodeHeader->nUnwindInfos = nUnwindInfos;
337     }
338     PTR_RUNTIME_FUNCTION    GetUnwindInfo(UINT iUnwindInfo)
339     {
340         SUPPORTS_DAC;
341         _ASSERTE(iUnwindInfo < GetNumberOfUnwindInfos());
342         return dac_cast<PTR_RUNTIME_FUNCTION>(
343             PTR_TO_MEMBER_TADDR(RealCodeHeader, pRealCodeHeader, unwindInfos) + iUnwindInfo * sizeof(T_RUNTIME_FUNCTION));
344     }
345 #endif // WIN64EXCEPTIONS
346
347 #ifdef DACCESS_COMPILE
348     void EnumMemoryRegions(CLRDataEnumMemoryFlags flags, IJitManager* pJitMan);
349 #endif  // DACCESS_COMPILE
350
351 } CodeHeader;
352 #endif // USE_INDIRECT_CODEHEADER
353
354
355 //-----------------------------------------------------------------------------
356 // This is a structure used to consolidate the information that we 
357 // need we creating new code heaps. 
358 // When creating new JumpStubs we have a constarint that the address used
359 // should be in the range [loAddr..hiAddr]
360 //
361 struct CodeHeapRequestInfo
362 {
363     MethodDesc * m_pMD;
364     LoaderAllocator* m_pAllocator;
365     const BYTE * m_loAddr;          // lowest address to use to satisfy our request (0 -- don't care)
366     const BYTE * m_hiAddr;          // hihest address to use to satisfy our request (0 -- don't care)
367     size_t       m_requestSize;     // minimum size that must be made available
368     size_t       m_reserveSize;     // Amount that VirtualAlloc will reserved
369     size_t       m_reserveForJumpStubs; // Amount to reserve for jump stubs (won't be allocated)
370     bool         m_isDynamicDomain;
371     bool         m_isCollectible;
372     bool         m_throwOnOutOfMemoryWithinRange;
373
374     bool   IsDynamicDomain()                    { return m_isDynamicDomain;    }
375     void   SetDynamicDomain()                   { m_isDynamicDomain = true;    }
376
377     bool   IsCollectible()                      { return m_isCollectible;      }
378     
379     size_t getRequestSize()                     { return m_requestSize;        }
380     void   setRequestSize(size_t requestSize)   { m_requestSize = requestSize; }
381     
382     size_t getReserveSize()                     { return m_reserveSize;        }
383     void   setReserveSize(size_t reserveSize)   { m_reserveSize = reserveSize; }
384
385     size_t getReserveForJumpStubs()             { return m_reserveForJumpStubs; }
386     void   setReserveForJumpStubs(size_t size)  { m_reserveForJumpStubs = size; }
387
388     bool   getThrowOnOutOfMemoryWithinRange()   { return m_throwOnOutOfMemoryWithinRange; }
389     void   setThrowOnOutOfMemoryWithinRange(bool value) { m_throwOnOutOfMemoryWithinRange = value; }
390         
391     void   Init();
392     
393     CodeHeapRequestInfo(MethodDesc *pMD)
394         : m_pMD(pMD), m_pAllocator(0), 
395           m_loAddr(0), m_hiAddr(0),
396           m_requestSize(0), m_reserveSize(0), m_reserveForJumpStubs(0)
397     { WRAPPER_NO_CONTRACT;   Init(); }
398     
399     CodeHeapRequestInfo(MethodDesc *pMD, LoaderAllocator* pAllocator,
400                         BYTE * loAddr, BYTE * hiAddr)
401         : m_pMD(pMD), m_pAllocator(pAllocator), 
402           m_loAddr(loAddr), m_hiAddr(hiAddr),
403           m_requestSize(0), m_reserveSize(0), m_reserveForJumpStubs(0)
404     { WRAPPER_NO_CONTRACT;   Init(); }
405 };
406
407 //-----------------------------------------------------------------------------
408 //
409 // A CodeHeap is the abstraction the IJitManager uses to allocate memory
410 // needed to the jitting of a method.
411 // The CodeHeap works together with the HeapList to manage a contiguous block of memory.
412 // The CodeHeap is a non growable chunk of memory (it can be reserved and
413 // committed on demand).
414 //
415 // A CodeHeap is naturally protected from multiple threads by the code heap
416 // critical section - m_pCodeHeapCritSec - so if the implementation of the heap
417 // is only for the code manager, no locking needs to occur.
418 // It's important however that a delete operation on the CodeHeap (if any) happens
419 // via EEJitManager::FreeCodeMemory(HostCodeHeap*, void*)
420 //
421 // The heap to be created depends on the MethodDesc that is being compiled. 
422 // Standard code uses the LoaderCodeHeap, a heap based on the LoaderHeap.
423 // DynamicMethods - and only those - use a HostCodeHeap, a heap that does
424 // normal Alloc/Free so reclamation can be performed. 
425 //
426 // The convention is that every heap implementation would have a static create
427 // function that returns a HeapList. The HeapList *must* be properly initialized
428 // on return except for the next pointer
429 //
430
431 typedef VPTR(class CodeHeap) PTR_CodeHeap;
432
433 class CodeHeap
434 {
435     VPTR_BASE_VTABLE_CLASS(CodeHeap)
436
437 public:
438     CodeHeap() {}
439
440     // virtual dtor. Clean up heap
441     virtual ~CodeHeap() {}
442
443     // Alloc the specified numbers of bytes for code. Returns NULL if the request does not fit
444     // Space for header is reserved immediately before. It is not included in size.
445     virtual void* AllocMemForCode_NoThrow(size_t header, size_t size, DWORD alignment, size_t reserveForJumpStubs) = 0;
446
447 #ifdef DACCESS_COMPILE
448     virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags) = 0;
449 #endif
450
451 protected:
452     friend class EEJitManager;
453 };
454
455 //-----------------------------------------------------------------------------
456 // The HeapList works together with the CodeHeap to manage a contiguous block of memory.
457 //
458 // A single HeapList contains code only for a single AppDomain. EEJitManager uses
459 // EEJitManager::DomainCodeHeapList to keep a list of HeapLists for each AppDomain.
460
461 // The number of code heaps at which we increase the size of new code heaps.
462 #define CODE_HEAP_SIZE_INCREASE_THRESHOLD 5
463
464 typedef DPTR(struct _HeapList) PTR_HeapList;
465
466 typedef struct _HeapList
467 {
468     PTR_HeapList        hpNext;
469
470     PTR_CodeHeap        pHeap;
471     
472     TADDR               startAddress;
473     TADDR               endAddress;     // the current end of the used portion of the Heap
474
475     TADDR               mapBase;        // "startAddress" rounded down to GetOsPageSize(). pHdrMap is relative to this address
476     PTR_DWORD           pHdrMap;        // bit array used to find the start of methods
477
478     size_t              maxCodeHeapSize;// Size of the entire contiguous block of memory
479     size_t              reserveForJumpStubs; // Amount of memory reserved for jump stubs in this block
480
481 #if defined(_TARGET_AMD64_)
482     BYTE        CLRPersonalityRoutine[JUMP_ALLOCATE_SIZE];                 // jump thunk to personality routine
483 #elif defined(_TARGET_ARM64_)
484     UINT32      CLRPersonalityRoutine[JUMP_ALLOCATE_SIZE/sizeof(UINT32)];  // jump thunk to personality routine    
485 #endif
486
487     PTR_HeapList GetNext()
488     { SUPPORTS_DAC; return hpNext; }
489
490     void SetNext(PTR_HeapList next)
491     { hpNext = next; }
492
493 } HeapList;
494
495 //-----------------------------------------------------------------------------
496 // Implementation of the standard CodeHeap.
497 // Use the ExplicitControlLoaderHeap for allocations
498 // (Check the base class above - CodeHeap - for comments on the functions)
499 //
500 typedef VPTR(class LoaderCodeHeap) PTR_LoaderCodeHeap;
501
502 class LoaderCodeHeap : CodeHeap
503 {
504 #ifdef DACCESS_COMPILE
505     friend class ClrDataAccess;
506 #endif
507     
508     VPTR_VTABLE_CLASS(LoaderCodeHeap, CodeHeap)
509
510 private:
511     ExplicitControlLoaderHeap m_LoaderHeap;
512     SSIZE_T m_cbMinNextPad;
513
514     LoaderCodeHeap(size_t * pPrivatePCLBytes);
515
516 public:
517     static HeapList* CreateCodeHeap(CodeHeapRequestInfo *pInfo, LoaderHeap *pJitMetaHeap);
518
519 public:
520     virtual ~LoaderCodeHeap()
521     {
522         WRAPPER_NO_CONTRACT;
523     }
524
525     virtual void* AllocMemForCode_NoThrow(size_t header, size_t size, DWORD alignment, size_t reserveForJumpStubs) DAC_EMPTY_RET(NULL);
526
527 #ifdef DACCESS_COMPILE
528     virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
529     {
530         WRAPPER_NO_CONTRACT;
531         m_LoaderHeap.EnumMemoryRegions(flags);
532     }
533 #endif
534 };
535
536 #if defined(_WIN64)
537 // On non X86 platforms, the OS defined UnwindInfo (accessed from RUNTIME_FUNCTION
538 // structures) to  support the ability unwind the stack.   Unfortunatey the pre-Win8 
539 // APIs defined a callback API for publishing this data dynamically that ETW does 
540 // not use (and really can't because the walk happens in the kernel).   In Win8
541 // new APIs were defined that allow incremental publishing via a table.  
542 //
543 // UnwindInfoTable is a class that wraps the OS APIs that we use to publish 
544 // this table.  Its job is to allocate the table, deallocate it when we are
545 // done and allow us to add new entries one at a time (AddToUnwindInfoTable)
546 // 
547 // Each _rangesection has a UnwindInfoTable's which hold the
548 // RUNTIME_FUNCTION array as well as other bookeeping (the current and maximum
549 // size of the array, and the handle used to publish it to the OS.  
550 //
551 // Ideally we would just use this new API when it is available, however to mininmize
552 // risk and to make the change perfectly pay-for-play, we us the original mechanism
553 // ALWAYS, and in addition publish via the Table ONLY WHEN ETW JIT events are turned
554 // on.  
555 // 
556 // This class implements a 'catchup' routine that allows us to publish existing JITTed
557 // methods when ETW turns on.  Currently this is 'sticky' (once we start publishing
558 // both ways, we do so for the life of the process.  
559 //
560 typedef DPTR(class UnwindInfoTable) PTR_UnwindInfoTable;
561 class UnwindInfoTable {
562 public:
563     // All public functions are thread-safe.
564
565     // These are wrapper functions over the UnwindInfoTable functions that are specific to JIT compile code
566     static void PublishUnwindInfoForMethod(TADDR baseAddress, T_RUNTIME_FUNCTION* unwindInfo, int unwindInfoCount);
567     static void UnpublishUnwindInfoForMethod(TADDR entryPoint);
568
569     // These are lower level functions that assume you have found the list of UnwindInfoTable entries
570     // These are used by the stublinker and the high-level method functions above
571     static void AddToUnwindInfoTable(UnwindInfoTable** unwindInfoPtr, T_RUNTIME_FUNCTION* data, TADDR rangeStart, TADDR rangeEnd);
572     static void RemoveFromUnwindInfoTable(UnwindInfoTable** unwindInfoPtr, TADDR baseAddress, TADDR entryPoint);
573
574     // By default this publishing is off, this routine turns it on (and optionally publishes existing methods)
575     static void PublishUnwindInfo(bool publishExisting);
576     ~UnwindInfoTable();
577
578 private:
579     void UnRegister();
580     void Register();
581     UnwindInfoTable(ULONG_PTR rangeStart, ULONG_PTR rangeEnd, ULONG size);
582     static void PublishUnwindInfoForExistingMethods();
583
584 private:
585     static Volatile<bool> s_publishingActive;            // Publishing to ETW is turned on 
586     static class Crst*  s_pUnwindInfoTableLock;          // lock protects all public UnwindInfoTable functions
587
588     PVOID               hHandle;          // OS handle for a published RUNTIME_FUNCTION table
589     ULONG_PTR           iRangeStart;      // Start of memory described by this table
590     ULONG_PTR           iRangeEnd;        // End of memory described by this table
591     T_RUNTIME_FUNCTION* pTable;           // The actual list of method unwind info, sorted by address
592     ULONG               cTableCurCount;   
593     ULONG               cTableMaxCount; 
594     int                 cDeletedEntries;    // Number of slots we removed. 
595 };
596
597 #endif // defined(_WIN64)
598
599 //-----------------------------------------------------------------------------
600 // The ExecutionManager uses RangeSection as the abstraction of a contiguous
601 // address range to track the code heaps.
602
603 typedef DPTR(struct RangeSection) PTR_RangeSection;
604
605 struct RangeSection
606 {
607     TADDR               LowAddress;
608     TADDR               HighAddress;
609
610     PTR_IJitManager     pjit;           // The owner of this address range
611
612 #ifndef DACCESS_COMPILE
613     // Volatile because of the list can be walked lock-free
614     Volatile<RangeSection *> pnext;  // link rangesections in a sorted list
615 #else
616     PTR_RangeSection    pnext;
617 #endif
618
619     PTR_RangeSection    pLastUsed;      // for the head node only:  a link to rangesections that was used most recently
620
621     enum RangeSectionFlags
622     {
623         RANGE_SECTION_NONE          = 0x0,
624         RANGE_SECTION_COLLECTIBLE   = 0x1,
625         RANGE_SECTION_CODEHEAP      = 0x2,
626 #ifdef FEATURE_READYTORUN
627         RANGE_SECTION_READYTORUN    = 0x4,
628 #endif
629     };
630
631     DWORD               flags;
632
633     // union
634     // {
635     //    PTR_CodeHeap    pCodeHeap;    // valid if RANGE_SECTION_HEAP is set
636     //    PTR_Module      pZapModule;   // valid if RANGE_SECTION_HEAP is not set
637     // };
638     TADDR           pHeapListOrZapModule;
639 #if defined(_WIN64)
640     PTR_UnwindInfoTable pUnwindInfoTable; // Points to unwind information for this memory range. 
641 #endif // defined(_WIN64)
642 };
643
644 /*****************************************************************************/
645
646 #ifdef CROSSGEN_COMPILE
647 #define CodeFragmentHeap LoaderHeap
648 #else
649
650 //
651 // A simple linked-list based allocator to expose code heap as loader heap for allocation of precodes. 
652 // The loader heap like interface is necessary to support backout. It is also conveniently used to reduce space overhead 
653 // for small blocks that are common for precodes.
654 //
655 // Allocating precodes on code heap makes them close to other code, it reduces need for jump stubs and thus chance
656 // that we run into bogus OOM because of not being able to allocate memory in particular memory range.
657 //
658 class CodeFragmentHeap : public ILoaderHeapBackout
659 {
660     PTR_LoaderAllocator m_pAllocator;
661
662     struct FreeBlock
663     {
664         DPTR(FreeBlock) m_pNext;    // Next block
665         SIZE_T m_dwSize;            // Size of this block (includes size of FreeBlock)
666     };
667     typedef DPTR(FreeBlock) PTR_FreeBlock;
668
669     PTR_FreeBlock       m_pFreeBlocks;
670     StubCodeBlockKind   m_kind;
671
672     Crst                m_CritSec;
673
674     void AddBlock(VOID * pMem, size_t dwSize);
675     void RemoveBlock(FreeBlock ** ppBlock);
676
677 public:
678     CodeFragmentHeap(LoaderAllocator * pAllocator, StubCodeBlockKind kind);
679     virtual ~CodeFragmentHeap() {}
680
681     TaggedMemAllocPtr RealAllocAlignedMem(size_t  dwRequestedSize
682                                          ,unsigned  dwAlignment
683 #ifdef _DEBUG
684                                          ,__in __in_z const char *szFile
685                                          ,int  lineNum
686 #endif
687                                          );
688
689     virtual void RealBackoutMem(void *pMem
690                         , size_t dwSize
691 #ifdef _DEBUG
692                         , __in __in_z const char *szFile
693                         , int lineNum
694                         , __in __in_z const char *szAllocFile
695                         , int allocLineNum
696 #endif
697                         ) DAC_EMPTY();
698
699 #ifdef DACCESS_COMPILE
700     void EnumMemoryRegions(enum CLRDataEnumMemoryFlags flags)
701     {
702         WRAPPER_NO_CONTRACT;
703         DAC_ENUM_DTHIS();
704     }
705 #endif
706 };
707 #endif // CROSSGEN_COMPILE
708
709 typedef DPTR(class CodeFragmentHeap) PTR_CodeFragmentHeap;
710
711 //-----------------------------------------------------------------------------
712 //
713 // Manages the CodeHeap for some of the RangeSections in the ExecutionManager
714 //
715 //-----------------------------------------------------------------------------
716
717 class IJitManager 
718 {
719     VPTR_BASE_VTABLE_CLASS(IJitManager)
720     
721 public:
722     struct MethodRegionInfo
723     {
724         TADDR hotStartAddress;
725         size_t hotSize;
726         TADDR coldStartAddress;
727         size_t coldSize;
728     };
729
730 #ifndef DACCESS_COMPILE
731     IJitManager();
732 #endif // !DACCESS_COMPILE
733
734     virtual DWORD GetCodeType() = 0;
735
736     // Used to read debug info.
737     // 1) Caller passes an allocator which these functions use to allocate memory. 
738     //    This is b/c the store may need to decompress the information just to figure out the size.
739     // 2) Note that these methods use Uncompressed (Normal) jit data. 
740     //    Compression is just an implementation detail.
741     // 3) These throw on OOM (exceptional case), and may return a 
742     //    failing HR if no data is available (not exceptional)
743
744     virtual BOOL GetBoundariesAndVars(
745         const DebugInfoRequest & request,
746         IN FP_IDS_NEW fpNew, IN void * pNewData,
747         OUT ULONG32 * pcMap, 
748         OUT ICorDebugInfo::OffsetMapping **ppMap,
749         OUT ULONG32 * pcVars, 
750         OUT ICorDebugInfo::NativeVarInfo **ppVars) = 0;
751         
752     virtual BOOL JitCodeToMethodInfo(
753             RangeSection * pRangeSection,
754             PCODE currentPC,
755             MethodDesc** ppMethodDesc,
756             OUT EECodeInfo * pCodeInfo) = 0;
757
758     virtual PCODE GetCodeAddressForRelOffset(const METHODTOKEN& MethodToken, DWORD relOffset) = 0;
759
760     virtual TADDR       JitTokenToStartAddress(const METHODTOKEN& MethodToken)=0;
761     virtual void        JitTokenToMethodRegionInfo(const METHODTOKEN& MethodToken, MethodRegionInfo *methodRegionInfo) = 0;
762     virtual unsigned    InitializeEHEnumeration(const METHODTOKEN& MethodToken, EH_CLAUSE_ENUMERATOR* pEnumState)=0;
763     virtual PTR_EXCEPTION_CLAUSE_TOKEN GetNextEHClause(EH_CLAUSE_ENUMERATOR* pEnumState, 
764                                  EE_ILEXCEPTION_CLAUSE* pEHclause)=0; 
765 #ifndef DACCESS_COMPILE    
766     virtual TypeHandle  ResolveEHClause(EE_ILEXCEPTION_CLAUSE* pEHClause,
767                                         CrawlFrame *pCf)=0;
768 #endif // #ifndef DACCESS_COMPILE
769
770     virtual GCInfoToken GetGCInfoToken(const METHODTOKEN& MethodToken)=0;
771     PTR_VOID GetGCInfo(const METHODTOKEN& MethodToken)
772     {
773         return GetGCInfoToken(MethodToken).Info;
774     }
775
776     TADDR JitTokenToModuleBase(const METHODTOKEN& MethodToken);
777
778 #if defined(WIN64EXCEPTIONS)
779     virtual PTR_RUNTIME_FUNCTION LazyGetFunctionEntry(EECodeInfo * pCodeInfo) = 0;
780
781     // GetFuncletStartAddress returns the starting address of the function or funclet indicated by the EECodeInfo address.
782     virtual TADDR GetFuncletStartAddress(EECodeInfo * pCodeInfo);
783
784     virtual DWORD GetFuncletStartOffsets(const METHODTOKEN& MethodToken, DWORD* pStartFuncletOffsets, DWORD dwLength) = 0;
785
786     BOOL IsFunclet(EECodeInfo * pCodeInfo);
787     virtual BOOL IsFilterFunclet(EECodeInfo * pCodeInfo);
788 #endif // WIN64EXCEPTIONS
789
790     virtual StubCodeBlockKind   GetStubCodeBlockKind(RangeSection * pRangeSection, PCODE currentPC) = 0;
791
792     // DAC-specific virtual functions.
793     // Note that these MUST occur below any other virtual function definitions to ensure that the vtable in
794     // DAC builds is compatible with the non-DAC one so that DAC virtual dispatch will work correctly.
795 #if defined(DACCESS_COMPILE)
796     virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
797     virtual void EnumMemoryRegionsForMethodDebugInfo(CLRDataEnumMemoryFlags flags, MethodDesc * pMD) = 0;
798 #if defined(WIN64EXCEPTIONS)
799     // Enumerate the memory necessary to retrieve the unwind info for a specific method
800     virtual void EnumMemoryRegionsForMethodUnwindInfo(CLRDataEnumMemoryFlags flags, EECodeInfo * pCodeInfo) = 0;
801 #endif // WIN64EXCEPTIONS
802 #endif // DACCESS_COMPILE
803
804 #ifndef DACCESS_COMPILE
805     void SetCodeManager(ICodeManager *codeMgr)
806     {
807         LIMITED_METHOD_CONTRACT;
808
809         m_runtimeSupport = codeMgr;
810     }
811 #endif // !DACCESS_COMPILE
812
813     ICodeManager *GetCodeManager() 
814     {
815         LIMITED_METHOD_DAC_CONTRACT;
816         return m_runtimeSupport;
817     }
818
819 protected:
820     PTR_ICodeManager m_runtimeSupport;
821 };
822
823 //-----------------------------------------------------------------------------
824
825 class HostCodeHeap;
826 typedef VPTR(class HostCodeHeap) PTR_HostCodeHeap;
827
828 typedef VPTR(class EEJitManager) PTR_EEJitManager;
829 typedef VPTR(class NativeImageJitManager) PTR_NativeImageJitManager;
830 typedef VPTR(class ReadyToRunJitManager) PTR_ReadyToRunJitManager;
831
832 struct JumpStubBlockHeader
833 {
834     JumpStubBlockHeader *  m_next;
835     UINT32                 m_used;
836     UINT32                 m_allocated;
837
838     LoaderAllocator* GetLoaderAllocator()
839     {
840         _ASSERTE(m_zero == 0);
841         return m_Allocator;
842     }
843
844     void SetLoaderAllocator(LoaderAllocator * loaderAllocator)
845     {
846         m_zero = 0;
847         m_Allocator = loaderAllocator;
848     }
849
850     HostCodeHeap* GetHostCodeHeap()
851     {
852         WRAPPER_NO_CONTRACT;
853         _ASSERTE(m_zero == -1);
854         return m_CodeHeap;
855     }
856
857     void SetHostCodeHeap(HostCodeHeap * hostCodeHeap)
858     {
859         m_zero = -1;
860         m_CodeHeap = hostCodeHeap;
861     }
862
863 private:
864     union {
865         HostCodeHeap    *m_CodeHeap;
866         LoaderAllocator *m_Allocator;
867     };
868
869     INT64   m_zero; // 0 for normal methods and -1 for LCG methods
870 };
871
872
873 /*****************************************************************************/
874
875 class EEJitManager : public IJitManager
876 {
877 #ifdef DACCESS_COMPILE
878     friend class ClrDataAccess;
879 #endif
880     friend class CheckDuplicatedStructLayouts;
881     friend class CodeHeapIterator;
882
883     VPTR_VTABLE_CLASS(EEJitManager, IJitManager)
884     
885 public:
886
887     // Failing to load the main JIT is a failure.
888     // If the user requested an altjit and we failed to load an altjit, that is also a failure.
889     BOOL IsJitLoaded()
890     {
891         LIMITED_METHOD_CONTRACT;
892
893         return (m_jit != NULL)
894 #ifdef ALLOW_SXS_JIT
895             && (!m_AltJITRequired || (m_alternateJit != NULL))
896 #endif // ALLOW_SXS_JIT
897             ;
898     }
899
900 #ifdef ALLOW_SXS_JIT
901     BOOL IsMainJitLoaded()
902     {
903         LIMITED_METHOD_CONTRACT;
904
905         return (m_jit != NULL);
906     }
907
908     BOOL IsAltJitLoaded()
909     {
910         LIMITED_METHOD_CONTRACT;
911
912         return (m_alternateJit != NULL);
913     }
914 #endif // ALLOW_SXS_JIT
915
916     VOID ClearCache()
917     {
918         CONTRACTL {
919             NOTHROW;
920             GC_NOTRIGGER;
921         } CONTRACTL_END;
922
923         if( m_jit != NULL )
924         {
925             m_jit->clearCache();
926         }
927 #ifdef ALLOW_SXS_JIT
928         if( m_alternateJit != NULL )
929         {
930             m_alternateJit->clearCache();
931         }
932 #endif // ALLOW_SXS_JIT
933     }
934
935     BOOL IsCacheCleanupRequired()
936     {
937         CONTRACTL {
938             NOTHROW;
939             GC_NOTRIGGER;
940         } CONTRACTL_END;
941
942         BOOL ret = FALSE;
943
944         if( m_jit != NULL )
945         {
946             if (m_jit->isCacheCleanupRequired())
947                 ret = TRUE;
948         }
949
950 #ifdef ALLOW_SXS_JIT
951         if( !ret && m_alternateJit != NULL )
952         {
953             if (m_alternateJit->isCacheCleanupRequired())
954                 ret = TRUE;
955         }
956 #endif // ALLOW_SXS_JIT
957
958         return ret;
959     }
960
961 #if !defined CROSSGEN_COMPILE && !defined DACCESS_COMPILE
962     EEJitManager();
963
964     // No destructor necessary. Only one instance of this class that is destroyed at process shutdown.
965     // ~EEJitManager();
966 #endif // !CROSSGEN_COMPILE && !DACCESS_COMPILE
967
968
969     virtual DWORD GetCodeType()
970     {
971         LIMITED_METHOD_DAC_CONTRACT;
972         return (miManaged | miIL);
973     }
974
975 #ifndef CROSSGEN_COMPILE
976     // Used to read debug info.
977     virtual BOOL GetBoundariesAndVars(
978         const DebugInfoRequest & request,
979         IN FP_IDS_NEW fpNew, IN void * pNewData,
980         OUT ULONG32 * pcMap, 
981         OUT ICorDebugInfo::OffsetMapping **ppMap,
982         OUT ULONG32 * pcVars, 
983         OUT ICorDebugInfo::NativeVarInfo **ppVars);
984
985     virtual PCODE GetCodeAddressForRelOffset(const METHODTOKEN& MethodToken, DWORD relOffset);
986 #endif // !CROSSGEN_COMPILE
987
988     virtual BOOL JitCodeToMethodInfo(RangeSection * pRangeSection,
989                                      PCODE currentPC, 
990                                      MethodDesc ** ppMethodDesc, 
991                                      EECodeInfo * pCodeInfo);
992
993     virtual TADDR       JitTokenToStartAddress(const METHODTOKEN& MethodToken);
994     virtual void        JitTokenToMethodRegionInfo(const METHODTOKEN& MethodToken, MethodRegionInfo *methodRegionInfo);
995
996 #ifndef CROSSGEN_COMPILE
997     virtual unsigned    InitializeEHEnumeration(const METHODTOKEN& MethodToken, EH_CLAUSE_ENUMERATOR* pEnumState);
998     virtual PTR_EXCEPTION_CLAUSE_TOKEN GetNextEHClause(EH_CLAUSE_ENUMERATOR* pEnumState, 
999                                         EE_ILEXCEPTION_CLAUSE* pEHclause); 
1000 #ifndef DACCESS_COMPILE    
1001     virtual TypeHandle  ResolveEHClause(EE_ILEXCEPTION_CLAUSE* pEHClause,
1002                                         CrawlFrame *pCf);
1003 #endif // !DACCESS_COMPILE
1004     GCInfoToken         GetGCInfoToken(const METHODTOKEN& MethodToken);
1005 #endif // !CROSSGEN_COMPILE
1006 #if !defined DACCESS_COMPILE && !defined CROSSGEN_COMPILE
1007     void                RemoveJitData(CodeHeader * pCHdr, size_t GCinfo_len, size_t EHinfo_len);
1008     void                Unload(LoaderAllocator* pAllocator);
1009     void                CleanupCodeHeaps();
1010
1011     BOOL                LoadJIT();
1012
1013     CodeHeader*         allocCode(MethodDesc* pFD, size_t blockSize, size_t reserveForJumpStubs, CorJitAllocMemFlag flag
1014 #ifdef WIN64EXCEPTIONS
1015                                   , UINT nUnwindInfos
1016                                   , TADDR * pModuleBase
1017 #endif
1018                                   );
1019     BYTE *              allocGCInfo(CodeHeader* pCodeHeader, DWORD blockSize, size_t * pAllocationSize);
1020     EE_ILEXCEPTION*     allocEHInfo(CodeHeader* pCodeHeader, unsigned numClauses, size_t * pAllocationSize);
1021     JumpStubBlockHeader* allocJumpStubBlock(MethodDesc* pMD, DWORD numJumps, 
1022                                             BYTE * loAddr, BYTE * hiAddr,
1023                                             LoaderAllocator *pLoaderAllocator,
1024                                             bool throwOnOutOfMemoryWithinRange);
1025
1026     void *              allocCodeFragmentBlock(size_t blockSize, unsigned alignment, LoaderAllocator *pLoaderAllocator, StubCodeBlockKind kind);
1027 #endif // !DACCESS_COMPILE && !CROSSGEN_COMPILE
1028
1029     static CodeHeader * GetCodeHeader(const METHODTOKEN& MethodToken);
1030     static CodeHeader * GetCodeHeaderFromStartAddress(TADDR methodStartAddress);
1031
1032 #ifndef CROSSGEN_COMPILE
1033 #if defined(WIN64EXCEPTIONS)
1034     // Compute function entry lazily. Do not call directly. Use EECodeInfo::GetFunctionEntry instead.
1035     virtual PTR_RUNTIME_FUNCTION    LazyGetFunctionEntry(EECodeInfo * pCodeInfo);
1036
1037     virtual DWORD                   GetFuncletStartOffsets(const METHODTOKEN& MethodToken, DWORD* pStartFuncletOffsets, DWORD dwLength);
1038 #endif // WIN64EXCEPTIONS
1039
1040     virtual StubCodeBlockKind       GetStubCodeBlockKind(RangeSection * pRangeSection, PCODE currentPC);
1041
1042 #if defined(DACCESS_COMPILE)
1043     virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
1044     virtual void EnumMemoryRegionsForMethodDebugInfo(CLRDataEnumMemoryFlags flags, MethodDesc * pMD);
1045 #endif // DACCESS_COMPILE
1046 #if defined(WIN64EXCEPTIONS)
1047     // Enumerate the memory necessary to retrieve the unwind info for a specific method
1048     virtual void EnumMemoryRegionsForMethodUnwindInfo(CLRDataEnumMemoryFlags flags, EECodeInfo * pCodeInfo)
1049     {
1050         // We don't need to do explicitly enumerate the memory for unwind information for JITted methods because
1051         // it is stored using the Win64 standard dynamic function table mechanism, and dump generation code knows
1052         // it needs to call our code:OutOfProcessFunctionTableCallback in order to save the function table including
1053         // unwind information at dump generation time (since it's dynamic, it will not be otherwise
1054         // available at debug time).
1055     }
1056 #endif // WIN64EXCEPTIONS
1057 #endif // !CROSSGEN_COMPILE
1058     
1059 #ifndef CROSSGEN_COMPILE
1060 #ifndef DACCESS_COMPILE
1061         // Heap Management functions
1062     void NibbleMapSet(HeapList * pHp, TADDR pCode, BOOL bSet);
1063 #endif  // !DACCESS_COMPILE
1064
1065     static TADDR FindMethodCode(RangeSection * pRangeSection, PCODE currentPC);
1066     static TADDR FindMethodCode(PCODE currentPC);
1067 #endif // !CROSSGEN_COMPILE
1068         
1069 #if !defined DACCESS_COMPILE && !defined CROSSGEN_COMPILE
1070     void        FreeCodeMemory(HostCodeHeap *pCodeHeap, void * codeStart);
1071     void        RemoveFromCleanupList(HostCodeHeap *pCodeHeap);
1072     void        AddToCleanupList(HostCodeHeap *pCodeHeap);
1073     void        DeleteCodeHeap(HeapList *pHeapList);
1074     void        RemoveCodeHeapFromDomainList(CodeHeap *pHeap, LoaderAllocator *pAllocator);
1075 #endif // !DACCESS_COMPILE && !CROSSGEN_COMPILE
1076
1077 private :
1078 #ifndef CROSSGEN_COMPILE
1079     struct DomainCodeHeapList {
1080         LoaderAllocator *m_pAllocator;
1081         CDynArray<HeapList *> m_CodeHeapList;
1082         DomainCodeHeapList();
1083         ~DomainCodeHeapList();
1084     };
1085 #endif
1086
1087 #ifndef DACCESS_COMPILE
1088 #ifndef CROSSGEN_COMPILE
1089     HeapList*   NewCodeHeap(CodeHeapRequestInfo *pInfo, DomainCodeHeapList *pADHeapList);
1090     bool        CanUseCodeHeap(CodeHeapRequestInfo *pInfo, HeapList *pCodeHeap);
1091     void*       allocCodeRaw(CodeHeapRequestInfo *pInfo, 
1092                              size_t header, size_t blockSize, unsigned align,
1093                              HeapList ** ppCodeHeap);
1094
1095     DomainCodeHeapList *GetCodeHeapList(CodeHeapRequestInfo *pInfo, LoaderAllocator *pAllocator, BOOL fDynamicOnly = FALSE);
1096     DomainCodeHeapList *CreateCodeHeapList(CodeHeapRequestInfo *pInfo);
1097     LoaderHeap* GetJitMetaHeap(MethodDesc *pMD);
1098 #endif // !CROSSGEN_COMPILE
1099
1100     HeapList * GetCodeHeapList()
1101     {
1102         return m_pCodeHeap;
1103     }
1104
1105 #ifndef CROSSGEN_COMPILE
1106 protected:
1107     void *      allocEHInfoRaw(CodeHeader* pCodeHeader, DWORD blockSize, size_t * pAllocationSize);
1108 private:
1109 #endif
1110 #endif // !DACCESS_COMPILE
1111
1112     PTR_HeapList m_pCodeHeap;
1113
1114 protected :    
1115     Crst            m_CodeHeapCritSec;
1116
1117 #if !defined(DACCESS_COMPILE)
1118 public:
1119     class CodeHeapIterator
1120     {
1121         CrstHolder m_lockHolder;
1122         HeapList *m_pHeapList;
1123         LoaderAllocator *m_pLoaderAllocator;
1124         MethodSectionIterator m_Iterator;
1125         MethodDesc *m_pCurrent;
1126
1127     public:
1128         CodeHeapIterator(LoaderAllocator *pLoaderAllocatorFilter = NULL);
1129         ~CodeHeapIterator();
1130         BOOL Next();
1131
1132         MethodDesc *GetMethod()
1133         {
1134             LIMITED_METHOD_CONTRACT;
1135             return m_pCurrent;
1136         }
1137
1138         TADDR GetMethodCode()
1139         {
1140             LIMITED_METHOD_CONTRACT;
1141             return (TADDR)m_Iterator.GetMethodCode();
1142         }
1143     };
1144 #endif // !DACCESS_COMPILE
1145
1146 private:
1147     CORJIT_FLAGS m_CPUCompileFlags;
1148
1149 #if !defined CROSSGEN_COMPILE && !defined DACCESS_COMPILE
1150     void SetCpuInfo();
1151 #endif
1152
1153 public:
1154     inline CORJIT_FLAGS GetCPUCompileFlags()
1155     {
1156         LIMITED_METHOD_CONTRACT;
1157         return m_CPUCompileFlags;
1158     }
1159
1160 private :
1161     PTR_HostCodeHeap    m_cleanupList;
1162     //When EH Clauses are resolved we need to atomically update the TypeHandle
1163     Crst                m_EHClauseCritSec;
1164
1165 #if !defined CROSSGEN_COMPILE
1166     // must hold critical section to access this structure.
1167     CUnorderedArray<DomainCodeHeapList *, 5> m_DomainCodeHeaps;
1168     CUnorderedArray<DomainCodeHeapList *, 5> m_DynamicDomainCodeHeaps;
1169 #endif
1170
1171 #ifdef _TARGET_AMD64_
1172 private:
1173     //
1174     // List of reserved memory blocks to be used for jump stub allocation if no suitable memory block is found 
1175     // via the regular mechanism
1176     //
1177     struct EmergencyJumpStubReserve
1178     {
1179         EmergencyJumpStubReserve * m_pNext;
1180         BYTE *   m_ptr;
1181         SIZE_T   m_size;
1182         SIZE_T   m_free;
1183     };
1184     EmergencyJumpStubReserve * m_pEmergencyJumpStubReserveList;
1185
1186 public:
1187     BYTE * AllocateFromEmergencyJumpStubReserve(const BYTE * loAddr, const BYTE * hiAddr, SIZE_T * pReserveSize);
1188     VOID EnsureJumpStubReserve(BYTE * pImageBase, SIZE_T imageSize, SIZE_T reserveSize);
1189 #endif
1190
1191 public:
1192     ICorJitCompiler *   m_jit;
1193     HINSTANCE           m_JITCompiler;
1194 #if defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
1195     HINSTANCE           m_JITCompilerOther; // Stores the handle of the legacy JIT, if one is loaded.
1196 #endif
1197
1198 #ifdef ALLOW_SXS_JIT
1199     //put these at the end so that we don't mess up the offsets in the DAC.
1200     ICorJitCompiler *   m_alternateJit;
1201     HINSTANCE           m_AltJITCompiler;
1202     bool                m_AltJITRequired;
1203 #endif //ALLOW_SXS_JIT
1204 };
1205
1206 //*****************************************************************************
1207 //
1208 // This class manages IJitManagers and ICorJitCompilers.  It has only static
1209 // members.  It should never be constucted.
1210 //
1211 //*****************************************************************************
1212
1213 class ExecutionManager
1214 {
1215     friend class CorExternalDataAccess;
1216     friend struct _DacGlobals;
1217
1218 #ifdef DACCESS_COMPILE
1219     friend class ClrDataAccess;
1220 #endif
1221
1222 public:
1223     static void Init();
1224
1225     enum ScanFlag
1226     {
1227         // When this is passed to a function, it must directly acquire a reader lock
1228         // before it may continue
1229         ScanReaderLock, 
1230         
1231         // This means the function need not directly acquire a reader lock; however, it
1232         // may call other functions that may require other reader locks (e.g.,
1233         // ExecutionManager::FindJitMan may be called with ScanNoReaderLock, but
1234         // still calls IJitManager::JitCodeToMethodInfo which acquires its own
1235         // IJitManager reader lock)
1236         ScanNoReaderLock
1237     };
1238
1239     // Returns default scan flag for current thread
1240     static ScanFlag GetScanFlags();
1241
1242     // Returns whether currentPC is in managed code. Returns false for jump stubs on WIN64.
1243     static BOOL IsManagedCode(PCODE currentPC);
1244
1245     // Special version with profiler hook
1246     static BOOL IsManagedCode(PCODE currentPC, HostCallPreference hostCallPreference, BOOL *pfFailedReaderLock);
1247
1248     // Returns true if currentPC is ready to run codegen
1249     static BOOL IsReadyToRunCode(PCODE currentPC);
1250
1251     // Returns method's start address for a given PC
1252     static PCODE GetCodeStartAddress(PCODE currentPC);
1253
1254     static NativeCodeVersion GetNativeCodeVersion(PCODE currentPC);
1255
1256     // Returns methodDesc for given PC
1257     static MethodDesc * GetCodeMethodDesc(PCODE currentPC);
1258
1259     static IJitManager* FindJitMan(PCODE currentPC)
1260     {
1261         CONTRACTL {
1262             NOTHROW;
1263             GC_NOTRIGGER;
1264             SUPPORTS_DAC;
1265         } CONTRACTL_END;
1266
1267         RangeSection * pRange = FindCodeRange(currentPC, GetScanFlags());
1268         return (pRange != NULL) ? pRange->pjit : NULL;
1269     }
1270
1271     static RangeSection * FindCodeRange(PCODE currentPC, ScanFlag scanFlag);
1272
1273     static BOOL IsCollectibleMethod(const METHODTOKEN& MethodToken);
1274
1275     class ReaderLockHolder
1276     {
1277     public:
1278         ReaderLockHolder(HostCallPreference hostCallPreference = AllowHostCalls);
1279         ~ReaderLockHolder();
1280
1281         BOOL Acquired();
1282     };
1283
1284 #ifdef _TARGET_64BIT_
1285     static ULONG          GetCLRPersonalityRoutineValue()
1286     {
1287         LIMITED_METHOD_CONTRACT;
1288         static_assert_no_msg(offsetof(HeapList, CLRPersonalityRoutine) ==
1289             (size_t)((ULONG)offsetof(HeapList, CLRPersonalityRoutine)));
1290         return offsetof(HeapList, CLRPersonalityRoutine);
1291     }
1292 #endif // _TARGET_64BIT_
1293
1294     static EEJitManager * GetEEJitManager()
1295     {
1296         LIMITED_METHOD_DAC_CONTRACT;
1297         return m_pEEJitManager;
1298     }
1299
1300 #ifdef FEATURE_PREJIT
1301     static NativeImageJitManager * GetNativeImageJitManager()
1302     {
1303         LIMITED_METHOD_DAC_CONTRACT;
1304         return m_pNativeImageJitManager;
1305     }
1306 #endif
1307
1308 #ifdef FEATURE_READYTORUN
1309     static ReadyToRunJitManager * GetReadyToRunJitManager()
1310     {
1311         LIMITED_METHOD_DAC_CONTRACT;
1312         return m_pReadyToRunJitManager;
1313     }
1314 #endif
1315
1316     static void ClearCaches( void );
1317     static BOOL IsCacheCleanupRequired();
1318
1319     static LPCWSTR         GetJitName();
1320
1321     static void           Unload(LoaderAllocator *pLoaderAllocator);
1322
1323     static void           AddCodeRange(TADDR StartRange, TADDR EndRange,
1324                                        IJitManager* pJit,
1325                                        RangeSection::RangeSectionFlags flags,
1326                                        void * pHp);
1327
1328     static void           AddNativeImageRange(TADDR StartRange, 
1329                                               SIZE_T Size, 
1330                                               Module * pModule);
1331
1332     static void           DeleteRange(TADDR StartRange);
1333
1334     static void           CleanupCodeHeaps();
1335
1336     static ICodeManager*  GetDefaultCodeManager()
1337     {
1338         LIMITED_METHOD_CONTRACT;
1339         return (ICodeManager *)m_pDefaultCodeMan;    
1340     }
1341
1342     static PTR_Module FindZapModule(TADDR currentData);
1343     static PTR_Module FindReadyToRunModule(TADDR currentData);
1344
1345     // FindZapModule flavor to be used during GC to find GCRefMap
1346     static PTR_Module FindModuleForGCRefMap(TADDR currentData);
1347
1348     static RangeSection*  GetRangeSectionAndPrev(RangeSection *pRS, TADDR addr, RangeSection **ppPrev);
1349
1350 #ifdef DACCESS_COMPILE
1351     static void EnumRangeList(RangeSection* list,
1352                               CLRDataEnumMemoryFlags flags);
1353     static void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
1354 #endif
1355
1356 #ifndef DACCESS_COMPILE
1357     static PCODE jumpStub(MethodDesc* pMD,
1358                           PCODE target,
1359                           BYTE * loAddr,
1360                           BYTE * hiAddr,
1361                           LoaderAllocator *pLoaderAllocator = NULL,
1362                           bool throwOnOutOfMemoryWithinRange = true);
1363 #endif
1364
1365 private:
1366     static RangeSection * FindCodeRangeWithLock(PCODE currentPC);
1367
1368     static BOOL IsManagedCodeWithLock(PCODE currentPC);
1369     static BOOL IsManagedCodeWorker(PCODE currentPC);
1370
1371     static RangeSection* GetRangeSection(TADDR addr);
1372
1373     SPTR_DECL(EECodeManager, m_pDefaultCodeMan);
1374
1375     SPTR_DECL(EEJitManager, m_pEEJitManager);
1376 #ifdef FEATURE_PREJIT
1377     SPTR_DECL(NativeImageJitManager, m_pNativeImageJitManager);
1378 #endif
1379 #ifdef FEATURE_READYTORUN
1380     SPTR_DECL(ReadyToRunJitManager, m_pReadyToRunJitManager);
1381 #endif
1382
1383     static CrstStatic       m_JumpStubCrst;
1384     static CrstStatic       m_RangeCrst;        // Aquire before writing into m_CodeRangeList and m_DataRangeList
1385
1386     // infrastructure to manage readers so we can lock them out and delete domain data
1387     // make ReaderCount volatile because we have order dependency in READER_INCREMENT
1388 #ifndef DACCESS_COMPILE
1389     static Volatile<RangeSection *> m_CodeRangeList;
1390     static Volatile<LONG>   m_dwReaderCount;
1391     static Volatile<LONG>   m_dwWriterLock;
1392 #else
1393     SPTR_DECL(RangeSection,  m_CodeRangeList);
1394     SVAL_DECL(LONG, m_dwReaderCount);
1395     SVAL_DECL(LONG, m_dwWriterLock);
1396 #endif
1397
1398 #ifndef DACCESS_COMPILE
1399     class WriterLockHolder
1400     {
1401     public:
1402         WriterLockHolder();
1403         ~WriterLockHolder();
1404     };
1405 #endif
1406
1407 #if defined(_DEBUG)
1408     // The LOCK_TAKEN/RELEASED macros need a "pointer" to the lock object to do
1409     // comparisons between takes & releases (and to provide debugging info to the
1410     // developer).  Since Inc/Dec Reader/Writer are static, there's no object to
1411     // use.  So we just use the pointer to m_dwReaderCount.  Note that both
1412     // readers & writers use this same pointer, which follows the general convention
1413     // of other ReaderWriter locks in the EE code base: each reader/writer locking object
1414     // instance protects only 1 piece of data or code.  Readers & writers both access the
1415     // same locking object & shared resource, so conceptually they would share the same
1416     // lock pointer.
1417     static void * GetPtrForLockContract()
1418     {
1419         return (void *) &m_dwReaderCount;
1420     }
1421 #endif // defined(_DEBUG)
1422
1423     static void AddRangeHelper(TADDR StartRange,
1424                                TADDR EndRange,
1425                                IJitManager* pJit, 
1426                                RangeSection::RangeSectionFlags flags,
1427                                TADDR pHeapListOrZapModule);
1428     static void DeleteRangeHelper(RangeSection** ppRangeList,
1429                                   TADDR StartRange);
1430
1431 #ifndef DACCESS_COMPILE
1432     static PCODE getNextJumpStub(MethodDesc* pMD,
1433                                  PCODE target,
1434                                  BYTE * loAddr,  BYTE * hiAddr,
1435                                  LoaderAllocator *pLoaderAllocator,
1436                                  bool throwOnOutOfMemoryWithinRange);
1437 #endif    
1438
1439 private:
1440     // ***************************************************************************
1441     // Hashtable for JumpStubs for jitted code
1442
1443     struct JumpStubEntry {
1444         PCODE m_target;
1445         PCODE m_jumpStub;
1446     };
1447
1448     class JumpStubTraits : public DefaultSHashTraits<JumpStubEntry>
1449     {
1450     public:
1451         typedef PCODE key_t;
1452
1453         static key_t GetKey(element_t e)
1454         {
1455             LIMITED_METHOD_CONTRACT;
1456             return e.m_target;
1457         }
1458         static BOOL Equals(key_t k1, key_t k2)
1459         {
1460             LIMITED_METHOD_CONTRACT;
1461             return k1 == k2;
1462         }
1463         static count_t Hash(key_t k)
1464         {
1465             LIMITED_METHOD_CONTRACT;
1466 #ifdef _WIN64
1467             return (count_t) ((size_t) k ^ ((size_t) k >> 32));
1468 #else
1469             return (count_t)(size_t)k;
1470 #endif
1471         }
1472
1473         static const element_t Null() { LIMITED_METHOD_CONTRACT; JumpStubEntry e; e.m_target = NULL; e.m_jumpStub = NULL; return e; }
1474         static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e.m_target == NULL; }
1475         static const element_t Deleted() { LIMITED_METHOD_CONTRACT; JumpStubEntry e; e.m_target = (PCODE)-1; e.m_jumpStub = NULL; return e; }
1476         static bool IsDeleted(const element_t &e) { LIMITED_METHOD_CONTRACT; return e.m_target == (PCODE)-1; }
1477     };
1478     typedef SHash<JumpStubTraits> JumpStubTable;
1479
1480     static unsigned m_normal_JumpStubLookup;
1481     static unsigned m_normal_JumpStubUnique;
1482     static unsigned m_normal_JumpStubBlockAllocCount;
1483     static unsigned m_normal_JumpStubBlockFullCount;
1484
1485     static unsigned m_LCG_JumpStubLookup;
1486     static unsigned m_LCG_JumpStubUnique;
1487     static unsigned m_LCG_JumpStubBlockAllocCount;
1488     static unsigned m_LCG_JumpStubBlockFullCount;
1489
1490 public:
1491     struct JumpStubCache
1492     {
1493         JumpStubCache() 
1494             : m_pBlocks(NULL)
1495         {
1496             LIMITED_METHOD_CONTRACT;
1497         }
1498
1499         JumpStubBlockHeader * m_pBlocks;
1500         JumpStubTable m_Table;
1501     };
1502 };
1503
1504 inline CodeHeader * EEJitManager::GetCodeHeader(const METHODTOKEN& MethodToken)
1505 {
1506     LIMITED_METHOD_DAC_CONTRACT;
1507     _ASSERTE(!MethodToken.IsNull());
1508     return dac_cast<PTR_CodeHeader>(MethodToken.m_pCodeHeader);
1509 }
1510
1511 inline CodeHeader * EEJitManager::GetCodeHeaderFromStartAddress(TADDR methodStartAddress)
1512 {
1513     LIMITED_METHOD_DAC_CONTRACT;
1514     _ASSERTE(methodStartAddress != NULL);
1515     ARM_ONLY(_ASSERTE((methodStartAddress & THUMB_CODE) == 0));
1516     return dac_cast<PTR_CodeHeader>(methodStartAddress - sizeof(CodeHeader));
1517 }
1518
1519 inline TADDR EEJitManager::JitTokenToStartAddress(const METHODTOKEN& MethodToken)
1520 {
1521     CONTRACTL {
1522         NOTHROW;
1523         GC_NOTRIGGER;
1524         HOST_NOCALLS;
1525         SUPPORTS_DAC;
1526     } CONTRACTL_END;
1527
1528     CodeHeader * pCH = GetCodeHeader(MethodToken);
1529     return pCH->GetCodeStartAddress();
1530 }
1531
1532 inline void EEJitManager::JitTokenToMethodRegionInfo(const METHODTOKEN& MethodToken, 
1533                                                      MethodRegionInfo * methodRegionInfo)
1534 {
1535     CONTRACTL {
1536         NOTHROW;
1537         GC_NOTRIGGER;
1538         HOST_NOCALLS;
1539         SUPPORTS_DAC;
1540         PRECONDITION(methodRegionInfo != NULL);
1541     } CONTRACTL_END;
1542
1543     methodRegionInfo->hotStartAddress  = JitTokenToStartAddress(MethodToken);
1544     methodRegionInfo->hotSize          = GetCodeManager()->GetFunctionSize(GetGCInfoToken(MethodToken));
1545     methodRegionInfo->coldStartAddress = 0;
1546     methodRegionInfo->coldSize         = 0;
1547 }
1548
1549
1550 //-----------------------------------------------------------------------------
1551 #ifdef FEATURE_PREJIT
1552
1553 //*****************************************************************************
1554 // Stub JitManager for Managed native.
1555
1556 class NativeImageJitManager : public IJitManager 
1557 {
1558     VPTR_VTABLE_CLASS(NativeImageJitManager, IJitManager)
1559     
1560 public:
1561 #ifndef DACCESS_COMPILE
1562     NativeImageJitManager();
1563 #endif // #ifndef DACCESS_COMPILE
1564
1565     virtual DWORD GetCodeType()
1566     {
1567         LIMITED_METHOD_DAC_CONTRACT;
1568         return (miManaged | miNative);
1569     }
1570
1571     // Used to read debug info.
1572     virtual BOOL GetBoundariesAndVars(
1573         const DebugInfoRequest & request,
1574         IN FP_IDS_NEW fpNew, IN void * pNewData,
1575         OUT ULONG32 * pcMap, 
1576         OUT ICorDebugInfo::OffsetMapping **ppMap,
1577         OUT ULONG32 * pcVars, 
1578         OUT ICorDebugInfo::NativeVarInfo **ppVars);
1579
1580     virtual BOOL JitCodeToMethodInfo(RangeSection * pRangeSection,
1581                                      PCODE currentPC, 
1582                                      MethodDesc ** ppMethodDesc, 
1583                                      EECodeInfo * pCodeInfo);
1584
1585     virtual PCODE GetCodeAddressForRelOffset(const METHODTOKEN& MethodToken, DWORD relOffset);
1586
1587     static PTR_Module   JitTokenToZapModule(const METHODTOKEN& MethodToken);
1588     virtual TADDR       JitTokenToStartAddress(const METHODTOKEN& MethodToken);
1589     virtual void        JitTokenToMethodRegionInfo(const METHODTOKEN& MethodToken, MethodRegionInfo * methodRegionInfo);
1590
1591     virtual unsigned    InitializeEHEnumeration(const METHODTOKEN& MethodToken, EH_CLAUSE_ENUMERATOR* pEnumState);
1592
1593     virtual PTR_EXCEPTION_CLAUSE_TOKEN  GetNextEHClause(EH_CLAUSE_ENUMERATOR* pEnumState, 
1594                                         EE_ILEXCEPTION_CLAUSE* pEHclause);
1595
1596 #ifndef DACCESS_COMPILE    
1597     virtual TypeHandle  ResolveEHClause(EE_ILEXCEPTION_CLAUSE* pEHClause,
1598                                         CrawlFrame *pCf);
1599 #endif // #ifndef DACCESS_COMPILE
1600     
1601     virtual GCInfoToken  GetGCInfoToken(const METHODTOKEN& MethodToken);
1602
1603 #if defined(WIN64EXCEPTIONS)
1604     virtual PTR_RUNTIME_FUNCTION    LazyGetFunctionEntry(EECodeInfo * pCodeInfo);
1605
1606     virtual TADDR                   GetFuncletStartAddress(EECodeInfo * pCodeInfo);
1607     virtual DWORD                   GetFuncletStartOffsets(const METHODTOKEN& MethodToken, DWORD* pStartFuncletOffsets, DWORD dwLength);
1608     virtual BOOL                    IsFilterFunclet(EECodeInfo * pCodeInfo);
1609 #endif // WIN64EXCEPTIONS
1610
1611     virtual StubCodeBlockKind       GetStubCodeBlockKind(RangeSection * pRangeSection, PCODE currentPC);
1612
1613 #if defined(DACCESS_COMPILE)
1614     virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
1615     virtual void EnumMemoryRegionsForMethodDebugInfo(CLRDataEnumMemoryFlags flags, MethodDesc * pMD);
1616 #if defined(WIN64EXCEPTIONS)
1617     // Enumerate the memory necessary to retrieve the unwind info for a specific method
1618     virtual void EnumMemoryRegionsForMethodUnwindInfo(CLRDataEnumMemoryFlags flags, EECodeInfo * pCodeInfo);
1619 #endif //WIN64EXCEPTIONS
1620 #endif //DACCESS_COMPILE
1621 };
1622
1623 inline TADDR NativeImageJitManager::JitTokenToStartAddress(const METHODTOKEN& MethodToken)
1624 {
1625     CONTRACTL{
1626         NOTHROW;
1627         GC_NOTRIGGER;
1628         HOST_NOCALLS;
1629         SUPPORTS_DAC;
1630     } CONTRACTL_END;
1631
1632     return JitTokenToModuleBase(MethodToken) +
1633         RUNTIME_FUNCTION__BeginAddress(dac_cast<PTR_RUNTIME_FUNCTION>(MethodToken.m_pCodeHeader));
1634 }
1635
1636 #endif // FEATURE_PREJIT
1637
1638 #if defined(FEATURE_PREJIT) || defined(FEATURE_READYTORUN)
1639
1640 class NativeExceptionInfoLookupTable
1641 {
1642 public:
1643     static DWORD LookupExceptionInfoRVAForMethod(PTR_CORCOMPILE_EXCEPTION_LOOKUP_TABLE pTable,
1644                                                                    COUNT_T numLookupEntries,
1645                                                                    DWORD methodStartRVA, 
1646                                                                    COUNT_T* pSize);
1647 };
1648
1649 class NativeUnwindInfoLookupTable
1650 {
1651 public:
1652     static int LookupUnwindInfoForMethod(DWORD codeOffset,
1653                                          PTR_RUNTIME_FUNCTION pRuntimeFunctionTable, 
1654                                          int StartIndex, 
1655                                          int EndIndex);
1656
1657 #ifdef FEATURE_PREJIT
1658     static BOOL HasExceptionInfo(NGenLayoutInfo * pNgenLayout, PTR_RUNTIME_FUNCTION pMainRuntimeFunction);
1659     static PTR_MethodDesc GetMethodDesc(NGenLayoutInfo * pNgenLayout, PTR_RUNTIME_FUNCTION pMainRuntimeFunction, TADDR moduleBase);
1660
1661 private:
1662     static DWORD GetMethodDescRVA(NGenLayoutInfo * pNgenLayout, PTR_RUNTIME_FUNCTION pMainRuntimeFunction);
1663 #endif
1664 };
1665
1666 #endif // FEATURE_PREJIT || FEATURE_READYTORUN
1667
1668 #ifdef FEATURE_READYTORUN
1669
1670 class ReadyToRunJitManager : public IJitManager 
1671 {
1672     VPTR_VTABLE_CLASS(ReadyToRunJitManager, IJitManager)
1673
1674 public:
1675 #ifndef DACCESS_COMPILE
1676     ReadyToRunJitManager();
1677 #endif // #ifndef DACCESS_COMPILE
1678
1679     virtual DWORD GetCodeType()
1680     {
1681         LIMITED_METHOD_DAC_CONTRACT;
1682         return (miManaged | miNative);
1683     }
1684
1685     // Used to read debug info.
1686     virtual BOOL GetBoundariesAndVars(
1687         const DebugInfoRequest & request,
1688         IN FP_IDS_NEW fpNew, IN void * pNewData,
1689         OUT ULONG32 * pcMap, 
1690         OUT ICorDebugInfo::OffsetMapping **ppMap,
1691         OUT ULONG32 * pcVars, 
1692         OUT ICorDebugInfo::NativeVarInfo **ppVars);
1693
1694     virtual BOOL JitCodeToMethodInfo(RangeSection * pRangeSection,
1695                                      PCODE currentPC, 
1696                                      MethodDesc** ppMethodDesc,
1697                                      OUT EECodeInfo * pCodeInfo);
1698
1699     virtual PCODE GetCodeAddressForRelOffset(const METHODTOKEN& MethodToken, DWORD relOffset);
1700
1701     static ReadyToRunInfo * JitTokenToReadyToRunInfo(const METHODTOKEN& MethodToken);
1702     static UINT32 JitTokenToGCInfoVersion(const METHODTOKEN& MethodToken);
1703
1704     static PTR_RUNTIME_FUNCTION JitTokenToRuntimeFunction(const METHODTOKEN& MethodToken);
1705
1706     virtual TADDR       JitTokenToStartAddress(const METHODTOKEN& MethodToken);
1707     virtual void        JitTokenToMethodRegionInfo(const METHODTOKEN& MethodToken, MethodRegionInfo * methodRegionInfo);
1708
1709     virtual unsigned    InitializeEHEnumeration(const METHODTOKEN& MethodToken, EH_CLAUSE_ENUMERATOR* pEnumState);
1710
1711     virtual PTR_EXCEPTION_CLAUSE_TOKEN  GetNextEHClause(EH_CLAUSE_ENUMERATOR* pEnumState, 
1712                                         EE_ILEXCEPTION_CLAUSE* pEHclause);
1713
1714 #ifndef DACCESS_COMPILE
1715     virtual TypeHandle  ResolveEHClause(EE_ILEXCEPTION_CLAUSE* pEHClause,
1716                                         CrawlFrame *pCf);
1717 #endif // #ifndef DACCESS_COMPILE
1718     
1719     virtual GCInfoToken  GetGCInfoToken(const METHODTOKEN& MethodToken);
1720
1721 #if defined(WIN64EXCEPTIONS)
1722     virtual PTR_RUNTIME_FUNCTION    LazyGetFunctionEntry(EECodeInfo * pCodeInfo);
1723
1724     virtual TADDR                   GetFuncletStartAddress(EECodeInfo * pCodeInfo);
1725     virtual DWORD                   GetFuncletStartOffsets(const METHODTOKEN& MethodToken, DWORD* pStartFuncletOffsets, DWORD dwLength);
1726     virtual BOOL                    IsFilterFunclet(EECodeInfo * pCodeInfo);
1727 #endif // WIN64EXCEPTIONS
1728
1729     virtual StubCodeBlockKind       GetStubCodeBlockKind(RangeSection * pRangeSection, PCODE currentPC);
1730
1731 #if defined(DACCESS_COMPILE)
1732     virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
1733     virtual void EnumMemoryRegionsForMethodDebugInfo(CLRDataEnumMemoryFlags flags, MethodDesc * pMD);
1734 #if defined(WIN64EXCEPTIONS)
1735     // Enumerate the memory necessary to retrieve the unwind info for a specific method
1736     virtual void EnumMemoryRegionsForMethodUnwindInfo(CLRDataEnumMemoryFlags flags, EECodeInfo * pCodeInfo);
1737 #endif //WIN64EXCEPTIONS
1738 #endif //DACCESS_COMPILE
1739 };
1740
1741 #endif
1742
1743 //*****************************************************************************
1744 // EECodeInfo provides information about code at particular address:
1745 //  - Start of the method and relative offset
1746 //  - GC Info of the method
1747 //  etc.
1748 //
1749 // EECodeInfo caches information from IJitManager and thus avoids
1750 // quering IJitManager repeatedly for same data.
1751 //
1752 class EECodeInfo
1753 {
1754     friend BOOL EEJitManager::JitCodeToMethodInfo(RangeSection * pRangeSection, PCODE currentPC, MethodDesc** ppMethodDesc, EECodeInfo * pCodeInfo);
1755 #ifdef FEATURE_PREJIT
1756     friend BOOL NativeImageJitManager::JitCodeToMethodInfo(RangeSection * pRangeSection, PCODE currentPC, MethodDesc** ppMethodDesc, EECodeInfo * pCodeInfo);
1757 #endif
1758 #ifdef FEATURE_READYTORUN
1759     friend BOOL ReadyToRunJitManager::JitCodeToMethodInfo(RangeSection * pRangeSection, PCODE currentPC, MethodDesc** ppMethodDesc, EECodeInfo * pCodeInfo);
1760 #endif
1761
1762 public:
1763     EECodeInfo();
1764
1765     EECodeInfo(PCODE codeAddress)
1766     {
1767         Init(codeAddress);
1768     }
1769
1770     // Explicit initialization
1771     void Init(PCODE codeAddress);
1772     void Init(PCODE codeAddress, ExecutionManager::ScanFlag scanFlag);
1773
1774     TADDR       GetSavedMethodCode();
1775
1776     TADDR       GetStartAddress();
1777
1778     BOOL        IsValid()
1779     {
1780         LIMITED_METHOD_DAC_CONTRACT; 
1781         return m_pJM != NULL;
1782     }
1783
1784     IJitManager* GetJitManager()
1785     { 
1786         LIMITED_METHOD_DAC_CONTRACT;
1787         _ASSERTE(m_pJM != NULL);
1788         return m_pJM;
1789     }
1790
1791     ICodeManager* GetCodeManager()
1792     { 
1793         LIMITED_METHOD_DAC_CONTRACT; 
1794         return GetJitManager()->GetCodeManager();
1795     }
1796
1797     const METHODTOKEN& GetMethodToken()
1798     { 
1799         LIMITED_METHOD_DAC_CONTRACT; 
1800         return m_methodToken;
1801     }
1802
1803     // This returns a pointer to the start of an instruction; conceptually, a PINSTR.
1804     TADDR       GetCodeAddress() 
1805     {
1806         LIMITED_METHOD_DAC_CONTRACT; 
1807         return PCODEToPINSTR(m_codeAddress);
1808     }
1809
1810     NativeCodeVersion GetNativeCodeVersion();
1811
1812     MethodDesc * GetMethodDesc()
1813     { 
1814         LIMITED_METHOD_DAC_CONTRACT; 
1815         return m_pMD;
1816     }
1817
1818     DWORD       GetRelOffset()
1819     { 
1820         LIMITED_METHOD_DAC_CONTRACT; 
1821         return m_relOffset;
1822     }
1823
1824     GCInfoToken  GetGCInfoToken()
1825     {
1826         WRAPPER_NO_CONTRACT; 
1827         return GetJitManager()->GetGCInfoToken(GetMethodToken());
1828     }
1829
1830     PTR_VOID GetGCInfo()
1831     {
1832         WRAPPER_NO_CONTRACT;
1833         return GetGCInfoToken().Info;
1834     }
1835
1836     void        GetMethodRegionInfo(IJitManager::MethodRegionInfo *methodRegionInfo)
1837     {
1838         WRAPPER_NO_CONTRACT; 
1839         return GetJitManager()->JitTokenToMethodRegionInfo(GetMethodToken(), methodRegionInfo);
1840     }
1841
1842     TADDR       GetModuleBase()
1843     {
1844         WRAPPER_NO_CONTRACT;
1845         return GetJitManager()->JitTokenToModuleBase(GetMethodToken());
1846     }
1847
1848 #ifdef WIN64EXCEPTIONS
1849     PTR_RUNTIME_FUNCTION GetFunctionEntry();
1850     BOOL        IsFunclet()     { WRAPPER_NO_CONTRACT; return GetJitManager()->IsFunclet(this); }
1851     EECodeInfo  GetMainFunctionInfo();
1852     ULONG               GetFixedStackSize();
1853     
1854 #if defined(_TARGET_AMD64_)
1855     BOOL        HasFrameRegister();
1856 #endif // _TARGET_AMD64_
1857
1858 #else // WIN64EXCEPTIONS
1859     ULONG       GetFixedStackSize()
1860     {
1861         WRAPPER_NO_CONTRACT;
1862         return GetCodeManager()->GetFrameSize(GetGCInfoToken());
1863     }
1864 #endif // WIN64EXCEPTIONS
1865
1866 #if defined(_TARGET_AMD64_)
1867     void         GetOffsetsFromUnwindInfo(ULONG* pRSPOffset, ULONG* pRBPOffset);
1868
1869 #if defined(_DEBUG) && defined(HAVE_GCCOVER)
1870     // Find first funclet inside (pvFuncletStart, pvFuncletStart + cbCode)
1871     static LPVOID findNextFunclet (LPVOID pvFuncletStart, SIZE_T cbCode, LPVOID *ppvFuncletEnd);
1872 #endif // _DEBUG && HAVE_GCCOVER
1873 #endif // _TARGET_AMD64_
1874
1875 private:
1876     PCODE               m_codeAddress;
1877     METHODTOKEN         m_methodToken;
1878     MethodDesc         *m_pMD;
1879     IJitManager        *m_pJM;
1880     DWORD               m_relOffset;
1881 #ifdef WIN64EXCEPTIONS
1882     PTR_RUNTIME_FUNCTION m_pFunctionEntry;
1883 #endif // WIN64EXCEPTIONS
1884
1885 #ifdef _TARGET_AMD64_
1886     // Simple helper to return a pointer to the UNWIND_INFO given the offset to the unwind info.
1887     UNWIND_INFO * GetUnwindInfoHelper(ULONG unwindInfoOffset);
1888 #endif // _TARGET_AMD64_
1889 };
1890
1891 #include "codeman.inl"
1892
1893
1894 #ifdef FEATURE_PREJIT
1895 class MethodSectionIterator;
1896
1897 //
1898 //  MethodIterator class is used to iterate all the methods in an ngen image.
1899 //  It will match and report hot (and cold, if any) sections of a method at the same time.
1900 //  GcInfo version is always current
1901 class MethodIterator
1902 {
1903 public:
1904     enum MethodIteratorOptions
1905     {
1906         Hot = 0x1, 
1907         Unprofiled =0x2, 
1908         All = Hot | Unprofiled
1909     };
1910 private:
1911     TADDR                 m_ModuleBase;
1912     MethodIteratorOptions methodIteratorOptions;
1913
1914     NGenLayoutInfo *        m_pNgenLayout;
1915     BOOL                    m_fHotMethodsDone;
1916     COUNT_T                 m_CurrentRuntimeFunctionIndex;
1917     COUNT_T                 m_CurrentColdRuntimeFunctionIndex;
1918
1919     void Init(PTR_Module pModule, PEDecoder * pPEDecoder, MethodIteratorOptions mio);
1920
1921   public:
1922     MethodIterator(PTR_Module pModule, MethodIteratorOptions mio = All);
1923     MethodIterator(PTR_Module pModule, PEDecoder * pPEDecoder, MethodIteratorOptions mio = All);
1924
1925     BOOL Next();
1926
1927     PTR_MethodDesc GetMethodDesc();
1928     GCInfoToken GetGCInfoToken();
1929     TADDR GetMethodStartAddress();
1930     TADDR GetMethodColdStartAddress();
1931     ULONG GetHotCodeSize();
1932
1933     PTR_RUNTIME_FUNCTION GetRuntimeFunction();
1934
1935     void GetMethodRegionInfo(IJitManager::MethodRegionInfo *methodRegionInfo);
1936 };
1937 #endif //FEATURE_PREJIT
1938
1939 void ThrowOutOfMemoryWithinRange();
1940
1941 #endif // !__CODEMAN_HPP__