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