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