2 // Copyright (c) Microsoft. All rights reserved.
3 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
9 /******************************************************************************
17 Wrapper to facilitate multiple JITcompiler support in the COM+ Runtime
19 The ExecutionManager is responsible for managing the RangeSections.
20 Given an IP, it can find the RangeSection which holds that IP.
22 RangeSections contain the JITed codes. Each RangeSection knows the
23 IJitManager which created it.
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.
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.
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
42 +-----------+---------------+---------------+-----------+--- ...
47 +---------------+ +--------+<---- R +---------------+ +--------+<---- R
48 |ICorJitCompiler|<---->|IJitMan |<---- R |ICorJitCompiler|<---->|IJitMan |<---- R
49 +---------------+ +--------+<---- R +---------------+ +--------+<---- R
53 +--------+ R +--------+ R
54 |ICodeMan| |ICodeMan| (RangeSections)
57 ******************************************************************************/
59 #ifndef __CODEMAN_HPP__
61 #define __CODEMAN_HPP__
66 #include "jitinterface.h"
67 #include "debuginfostore.h"
69 #include "pedecoder.h"
72 class ICorJitCompiler;
75 class NativeImageJitManager;
76 class ReadyToRunJitManager;
77 class ExecutionManager;
80 struct EE_ILEXCEPTION;
81 struct EE_ILEXCEPTION_CLAUSE;
85 TADDR pExceptionClauseArray;
86 } EH_CLAUSE_ENUMERATOR;
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)
94 enum StubCodeBlockKind : int
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,
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.
118 #ifdef USE_INDIRECT_CODEHEADER
119 typedef DPTR(struct _hpRealCodeHdr) PTR_RealCodeHeader;
120 typedef DPTR(struct _hpCodeHdr) PTR_CodeHeader;
122 #else // USE_INDIRECT_CODEHEADER
123 typedef DPTR(struct _hpCodeHdr) PTR_CodeHeader;
125 #endif // USE_INDIRECT_CODEHEADER
127 #ifdef USE_INDIRECT_CODEHEADER
128 typedef struct _hpRealCodeHdr
129 #else // USE_INDIRECT_CODEHEADER
130 typedef struct _hpCodeHdr
131 #endif // USE_INDIRECT_CODEHEADER
134 PTR_BYTE phdrDebugInfo;
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;
141 PTR_MethodDesc phdrMDesc;
143 #ifdef WIN64EXCEPTIONS
145 RUNTIME_FUNCTION unwindInfos[0];
146 #endif // WIN64EXCEPTIONS
149 #ifndef USE_INDIRECT_CODEHEADER
151 // Note: that the JITted code follows immediately after the MethodDesc*
153 PTR_BYTE GetDebugInfo()
157 return phdrDebugInfo;
159 PTR_EE_ILEXCEPTION GetEHInfo()
161 return phdrJitEHInfo;
166 return phdrJitGCInfo;
168 PTR_MethodDesc GetMethodDesc()
173 TADDR GetCodeStartAddress()
176 return dac_cast<TADDR>(dac_cast<PTR_CodeHeader>(this) + 1);
178 StubCodeBlockKind GetStubCodeBlockKind()
181 return (StubCodeBlockKind)dac_cast<TADDR>(phdrMDesc);
183 BOOL IsStubCodeBlock()
186 // Note that it is important for this comparison to be unsigned
187 return dac_cast<TADDR>(phdrMDesc) <= (TADDR)STUB_CODE_BLOCK_LAST;
190 void SetDebugInfo(PTR_BYTE pDI)
194 void SetEHInfo(PTR_EE_ILEXCEPTION pEH)
198 void SetGCInfo(PTR_BYTE pGC)
202 void SetMethodDesc(PTR_MethodDesc pMD)
206 void SetStubCodeBlockKind(StubCodeBlockKind kind)
208 phdrMDesc = (PTR_MethodDesc)kind;
210 #endif // !USE_INDIRECT_CODEHEADER
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
220 #else // USE_INDIRECT_CODEHEADER
222 #endif // USE_INDIRECT_CODEHEADER
224 #ifdef USE_INDIRECT_CODEHEADER
225 typedef struct _hpCodeHdr
227 PTR_RealCodeHeader pRealCodeHeader;
230 PTR_BYTE GetDebugInfo()
233 return pRealCodeHeader->phdrDebugInfo;
235 PTR_EE_ILEXCEPTION GetEHInfo()
237 return pRealCodeHeader->phdrJitEHInfo;
242 return pRealCodeHeader->phdrJitGCInfo;
244 PTR_MethodDesc GetMethodDesc()
247 return pRealCodeHeader->phdrMDesc;
249 TADDR GetCodeStartAddress()
252 return dac_cast<PCODE>(dac_cast<PTR_CodeHeader>(this) + 1);
254 StubCodeBlockKind GetStubCodeBlockKind()
257 return (StubCodeBlockKind)dac_cast<TADDR>(pRealCodeHeader);
259 BOOL IsStubCodeBlock()
262 // Note that it is important for this comparison to be unsigned
263 return dac_cast<TADDR>(pRealCodeHeader) <= (TADDR)STUB_CODE_BLOCK_LAST;
266 void SetRealCodeHeader(BYTE* pRCH)
268 pRealCodeHeader = PTR_RealCodeHeader((RealCodeHeader*)pRCH);
271 void SetDebugInfo(PTR_BYTE pDI)
273 pRealCodeHeader->phdrDebugInfo = pDI;
275 void SetEHInfo(PTR_EE_ILEXCEPTION pEH)
277 pRealCodeHeader->phdrJitEHInfo = pEH;
279 void SetGCInfo(PTR_BYTE pGC)
281 pRealCodeHeader->phdrJitGCInfo = pGC;
283 void SetMethodDesc(PTR_MethodDesc pMD)
285 pRealCodeHeader->phdrMDesc = pMD;
287 void SetStubCodeBlockKind(StubCodeBlockKind kind)
289 pRealCodeHeader = (PTR_RealCodeHeader)kind;
292 #if defined(WIN64EXCEPTIONS)
293 UINT GetNumberOfUnwindInfos()
296 return pRealCodeHeader->nUnwindInfos;
298 void SetNumberOfUnwindInfos(UINT nUnwindInfos)
300 LIMITED_METHOD_CONTRACT;
301 pRealCodeHeader->nUnwindInfos = nUnwindInfos;
303 PTR_RUNTIME_FUNCTION GetUnwindInfo(UINT iUnwindInfo)
306 _ASSERTE(iUnwindInfo < GetNumberOfUnwindInfos());
307 return dac_cast<PTR_RUNTIME_FUNCTION>(
308 PTR_TO_MEMBER_TADDR(RealCodeHeader, pRealCodeHeader, unwindInfos) + iUnwindInfo * sizeof(RUNTIME_FUNCTION));
310 #endif // WIN64EXCEPTIONS
312 #ifdef DACCESS_COMPILE
313 void EnumMemoryRegions(CLRDataEnumMemoryFlags flags, IJitManager* pJitMan);
314 #endif // DACCESS_COMPILE
317 #endif // USE_INDIRECT_CODEHEADER
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]
326 struct CodeHeapRequestInfo
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;
337 bool IsDynamicDomain() { return m_isDynamicDomain; }
338 bool IsCollectible() { return m_isCollectible; }
340 size_t getRequestSize() { return m_requestSize; }
341 void setRequestSize(size_t requestSize) { m_requestSize = requestSize; }
343 size_t getReserveSize() { return m_reserveSize; }
344 void setReserveSize(size_t reserveSize) { m_reserveSize = reserveSize; }
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(); }
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(); }
362 //-----------------------------------------------------------------------------
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).
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*)
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.
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
386 typedef VPTR(class CodeHeap) PTR_CodeHeap;
390 VPTR_BASE_VTABLE_CLASS(CodeHeap)
395 // virtual dtor. Clean up heap
396 virtual ~CodeHeap() {}
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;
402 #ifdef DACCESS_COMPILE
403 virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags) = 0;
407 friend class EEJitManager;
410 //-----------------------------------------------------------------------------
411 // The HeapList works together with the CodeHeap to manage a contiguous block of memory.
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.
416 // The number of code heaps at which we increase the size of new code heaps.
417 #define CODE_HEAP_SIZE_INCREASE_THRESHOLD 5
419 typedef DPTR(struct _HeapList) PTR_HeapList;
421 typedef struct _HeapList
428 TADDR endAddress; // the current end of the used portion of the Heap
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
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
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
444 PTR_HeapList GetNext()
445 { SUPPORTS_DAC; return hpNext; }
447 void SetNext(PTR_HeapList next)
451 { VolatileStore(&bFull, true); }
454 { return VolatileLoad(&bFull); }
456 void SetHeapFullForJumpStubs()
457 { VolatileStore(&bFullForJumpStubs, true); }
459 bool IsHeapFullForJumpStubs()
460 { return VolatileLoad(&bFullForJumpStubs); }
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)
469 typedef VPTR(class LoaderCodeHeap) PTR_LoaderCodeHeap;
471 class LoaderCodeHeap : CodeHeap
473 #ifdef DACCESS_COMPILE
474 friend class ClrDataAccess;
477 VPTR_VTABLE_CLASS(LoaderCodeHeap, CodeHeap)
480 ExplicitControlLoaderHeap m_LoaderHeap;
481 SSIZE_T m_cbMinNextPad;
483 LoaderCodeHeap(size_t * pPrivatePCLBytes);
486 static HeapList* CreateCodeHeap(CodeHeapRequestInfo *pInfo, LoaderHeap *pJitMetaHeap);
489 virtual ~LoaderCodeHeap()
494 virtual void* AllocMemForCode_NoThrow(size_t header, size_t size, DWORD alignment) DAC_EMPTY_RET(NULL);
496 #ifdef DACCESS_COMPILE
497 virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
500 m_LoaderHeap.EnumMemoryRegions(flags);
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.
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)
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.
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
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.
529 typedef DPTR(class UnwindInfoTable) PTR_UnwindInfoTable;
530 class UnwindInfoTable {
532 // All public functions are thread-safe.
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);
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);
543 // By default this publishing is off, this routine turns it on (and optionally publishes existing methods)
544 static void PublishUnwindInfo(bool publishExisting);
550 UnwindInfoTable(ULONG_PTR rangeStart, ULONG_PTR rangeEnd, ULONG size);
551 static void PublishUnwindInfoForExistingMethods();
554 static Volatile<bool> s_publishingActive; // Publishing to ETW is turned on
555 static class Crst* s_pUnwindInfoTableLock; // lock protects all public UnwindInfoTable functions
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.
566 #endif // defined(_WIN64)
568 //-----------------------------------------------------------------------------
569 // The ExecutionManager uses RangeSection as the abstraction of a contiguous
570 // address range to track the code heaps.
572 typedef DPTR(struct RangeSection) PTR_RangeSection;
579 PTR_IJitManager pjit; // The owner of this address range
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
585 PTR_RangeSection pnext;
588 PTR_RangeSection pLastUsed; // for the head node only: a link to rangesections that was used most recently
590 enum RangeSectionFlags
592 RANGE_SECTION_NONE = 0x0,
593 RANGE_SECTION_COLLECTIBLE = 0x1,
594 RANGE_SECTION_CODEHEAP = 0x2,
595 #ifdef FEATURE_READYTORUN
596 RANGE_SECTION_READYTORUN = 0x4,
604 // PTR_CodeHeap pCodeHeap; // valid if RANGE_SECTION_HEAP is set
605 // PTR_Module pZapModule; // valid if RANGE_SECTION_HEAP is not set
607 TADDR pHeapListOrZapModule;
609 PTR_UnwindInfoTable pUnwindInfoTable; // Points to unwind information for this memory range.
610 #endif // defined(_WIN64)
613 /*****************************************************************************/
615 #ifdef CROSSGEN_COMPILE
616 #define CodeFragmentHeap LoaderHeap
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.
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.
627 class CodeFragmentHeap : public ILoaderHeapBackout
629 PTR_LoaderAllocator m_pAllocator;
633 DPTR(FreeBlock) m_pNext; // Next block
634 SIZE_T m_dwSize; // Size of this block (includes size of FreeBlock)
636 typedef DPTR(FreeBlock) PTR_FreeBlock;
638 PTR_FreeBlock m_pFreeBlocks;
639 StubCodeBlockKind m_kind;
643 void AddBlock(VOID * pMem, size_t dwSize);
644 void RemoveBlock(FreeBlock ** ppBlock);
647 CodeFragmentHeap(LoaderAllocator * pAllocator, StubCodeBlockKind kind);
649 TaggedMemAllocPtr RealAllocAlignedMem(size_t dwRequestedSize
650 ,unsigned dwAlignment
652 ,__in __in_z const char *szFile
657 virtual void RealBackoutMem(void *pMem
660 , __in __in_z const char *szFile
662 , __in __in_z const char *szAllocFile
667 #ifdef DACCESS_COMPILE
668 void EnumMemoryRegions(enum CLRDataEnumMemoryFlags flags)
675 #endif // CROSSGEN_COMPILE
677 typedef DPTR(class CodeFragmentHeap) PTR_CodeFragmentHeap;
679 //-----------------------------------------------------------------------------
681 // Manages the CodeHeap for some of the RangeSections in the ExecutionManager
683 //-----------------------------------------------------------------------------
687 VPTR_BASE_VTABLE_CLASS(IJitManager)
690 struct MethodRegionInfo
692 TADDR hotStartAddress;
694 TADDR coldStartAddress;
698 #ifndef DACCESS_COMPILE
700 #endif // !DACCESS_COMPILE
702 virtual DWORD GetCodeType() = 0;
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)
712 virtual BOOL GetBoundariesAndVars(
713 const DebugInfoRequest & request,
714 IN FP_IDS_NEW fpNew, IN void * pNewData,
716 OUT ICorDebugInfo::OffsetMapping **ppMap,
717 OUT ULONG32 * pcVars,
718 OUT ICorDebugInfo::NativeVarInfo **ppVars) = 0;
720 virtual BOOL JitCodeToMethodInfo(
721 RangeSection * pRangeSection,
723 MethodDesc** ppMethodDesc,
724 OUT EECodeInfo * pCodeInfo) = 0;
726 virtual PCODE GetCodeAddressForRelOffset(const METHODTOKEN& MethodToken, DWORD relOffset) = 0;
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,
736 #endif // #ifndef DACCESS_COMPILE
738 virtual PTR_VOID GetGCInfo(const METHODTOKEN& MethodToken)=0;
740 TADDR JitTokenToModuleBase(const METHODTOKEN& MethodToken);
742 #if defined(WIN64EXCEPTIONS)
743 virtual PTR_RUNTIME_FUNCTION LazyGetFunctionEntry(EECodeInfo * pCodeInfo) = 0;
745 // GetFuncletStartAddress returns the starting address of the function or funclet indicated by the EECodeInfo address.
746 virtual TADDR GetFuncletStartAddress(EECodeInfo * pCodeInfo);
748 virtual DWORD GetFuncletStartOffsets(const METHODTOKEN& MethodToken, DWORD* pStartFuncletOffsets, DWORD dwLength) = 0;
750 BOOL IsFunclet(EECodeInfo * pCodeInfo);
751 virtual BOOL IsFilterFunclet(EECodeInfo * pCodeInfo);
752 #endif // WIN64EXCEPTIONS
754 virtual StubCodeBlockKind GetStubCodeBlockKind(RangeSection * pRangeSection, PCODE currentPC) = 0;
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
768 #ifndef DACCESS_COMPILE
769 void SetCodeManager(ICodeManager *codeMgr)
771 LIMITED_METHOD_CONTRACT;
773 m_runtimeSupport = codeMgr;
775 #endif // !DACCESS_COMPILE
777 ICodeManager *GetCodeManager()
779 LIMITED_METHOD_DAC_CONTRACT;
780 return m_runtimeSupport;
784 PTR_ICodeManager m_runtimeSupport;
787 //-----------------------------------------------------------------------------
790 typedef VPTR(class HostCodeHeap) PTR_HostCodeHeap;
792 typedef VPTR(class EEJitManager) PTR_EEJitManager;
793 typedef VPTR(class NativeImageJitManager) PTR_NativeImageJitManager;
794 typedef VPTR(class ReadyToRunJitManager) PTR_ReadyToRunJitManager;
796 struct JumpStubBlockHeader
798 JumpStubBlockHeader * m_next;
802 LoaderAllocator* GetLoaderAllocator()
804 _ASSERTE(m_zero == 0);
808 void SetLoaderAllocator(LoaderAllocator * loaderAllocator)
811 m_Allocator = loaderAllocator;
814 HostCodeHeap* GetHostCodeHeap()
817 _ASSERTE(m_zero == -1);
821 void SetHostCodeHeap(HostCodeHeap * hostCodeHeap)
824 m_CodeHeap = hostCodeHeap;
829 HostCodeHeap *m_CodeHeap;
830 LoaderAllocator *m_Allocator;
833 INT64 m_zero; // 0 for normal methods and -1 for LCG methods
837 /*****************************************************************************/
839 class EEJitManager :public IJitManager
841 #ifdef DACCESS_COMPILE
842 friend class ClrDataAccess;
844 friend class CheckDuplicatedStructLayouts;
845 friend class CodeHeapIterator;
847 VPTR_VTABLE_CLASS(EEJitManager, IJitManager)
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.
855 LIMITED_METHOD_CONTRACT;
857 return (m_jit != NULL)
859 && (!m_AltJITRequired || (m_alternateJit != NULL))
860 #endif // ALLOW_SXS_JIT
865 BOOL IsMainJitLoaded()
867 LIMITED_METHOD_CONTRACT;
869 return (m_jit != NULL);
872 BOOL IsAltJitLoaded()
874 LIMITED_METHOD_CONTRACT;
876 return (m_alternateJit != NULL);
878 #endif // ALLOW_SXS_JIT
892 if( m_alternateJit != NULL )
894 m_alternateJit->clearCache();
896 #endif // ALLOW_SXS_JIT
899 BOOL IsCacheCleanupRequired()
910 if (m_jit->isCacheCleanupRequired())
915 if( !ret && m_alternateJit != NULL )
917 if (m_alternateJit->isCacheCleanupRequired())
920 #endif // ALLOW_SXS_JIT
925 #ifndef DACCESS_COMPILE
928 // No destructor necessary. Only one instance of this class that is destroyed at process shutdown.
930 #endif // #ifndef DACCESS_COMPILE
932 virtual DWORD GetCodeType()
934 LIMITED_METHOD_DAC_CONTRACT;
935 return (miManaged | miIL);
938 // Used to read debug info.
939 virtual BOOL GetBoundariesAndVars(
940 const DebugInfoRequest & request,
941 IN FP_IDS_NEW fpNew, IN void * pNewData,
943 OUT ICorDebugInfo::OffsetMapping **ppMap,
944 OUT ULONG32 * pcVars,
945 OUT ICorDebugInfo::NativeVarInfo **ppVars);
947 virtual BOOL JitCodeToMethodInfo(RangeSection * pRangeSection,
949 MethodDesc ** ppMethodDesc,
950 EECodeInfo * pCodeInfo);
952 virtual PCODE GetCodeAddressForRelOffset(const METHODTOKEN& MethodToken, DWORD relOffset);
954 virtual TADDR JitTokenToStartAddress(const METHODTOKEN& MethodToken);
955 virtual void JitTokenToMethodRegionInfo(const METHODTOKEN& MethodToken, MethodRegionInfo *methodRegionInfo);
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,
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);
968 void Unload(LoaderAllocator* pAllocator);
969 void CleanupCodeHeaps();
973 CodeHeader* allocCode(MethodDesc* pFD, size_t blockSize, CorJitAllocMemFlag flag
974 #ifdef WIN64EXCEPTIONS
976 , TADDR * pModuleBase
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);
986 void * allocCodeFragmentBlock(size_t blockSize, unsigned alignment, LoaderAllocator *pLoaderAllocator, StubCodeBlockKind kind);
987 #endif // #ifndef DACCESS_COMPILE
989 static CodeHeader * GetCodeHeader(const METHODTOKEN& MethodToken);
990 static CodeHeader * GetCodeHeaderFromStartAddress(TADDR methodStartAddress);
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);
996 virtual DWORD GetFuncletStartOffsets(const METHODTOKEN& MethodToken, DWORD* pStartFuncletOffsets, DWORD dwLength);
997 #endif // WIN64EXCEPTIONS
999 virtual StubCodeBlockKind GetStubCodeBlockKind(RangeSection * pRangeSection, PCODE currentPC);
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)
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).
1014 #endif // WIN64EXCEPTIONS
1015 #endif // DACCESS_COMPILE
1017 // Heap Management functions
1018 void NibbleMapSet(HeapList * pHp, TADDR pCode, BOOL bSet);
1020 static TADDR FindMethodCode(RangeSection * pRangeSection, PCODE currentPC);
1021 static TADDR FindMethodCode(PCODE currentPC);
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);
1032 struct DomainCodeHeapList {
1033 LoaderAllocator *m_pAllocator;
1034 CDynArray<HeapList *> m_CodeHeapList;
1035 DomainCodeHeapList();
1036 ~DomainCodeHeapList();
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 */ );
1046 DomainCodeHeapList *GetCodeHeapList(MethodDesc *pMD, LoaderAllocator *pAllocator, BOOL fDynamicOnly = FALSE);
1047 DomainCodeHeapList *CreateCodeHeapList(CodeHeapRequestInfo *pInfo);
1048 LoaderHeap* GetJitMetaHeap(MethodDesc *pMD);
1050 HeapList * GetCodeHeapList()
1056 void * allocEHInfoRaw(CodeHeader* pCodeHeader, DWORD blockSize, size_t * pAllocationSize);
1058 #endif // #ifndef DACCESS_COMPILE
1060 PTR_HeapList m_pCodeHeap;
1063 Crst m_CodeHeapCritSec;
1065 #if !defined(DACCESS_COMPILE)
1067 class CodeHeapIterator
1069 CrstHolder m_lockHolder;
1070 HeapList *m_pHeapList;
1071 LoaderAllocator *m_pLoaderAllocator;
1072 BaseDomain *m_pDomain;
1073 MethodSectionIterator m_Iterator;
1074 MethodDesc *m_pCurrent;
1077 CodeHeapIterator(BaseDomain *pDomainFilter = NULL, LoaderAllocator *pLoaderAllocatorFilter = NULL);
1078 ~CodeHeapIterator();
1081 MethodDesc *GetMethod()
1083 LIMITED_METHOD_CONTRACT;
1087 TADDR GetMethodCode()
1089 LIMITED_METHOD_CONTRACT;
1090 return (TADDR)m_Iterator.GetMethodCode();
1093 #endif // !DACCESS_COMPILE
1096 DWORD m_dwCPUCompileFlags;
1101 inline DWORD GetCPUCompileFlags()
1103 LIMITED_METHOD_CONTRACT;
1104 return m_dwCPUCompileFlags;
1108 PTR_HostCodeHeap m_cleanupList;
1109 //When EH Clauses are resolved we need to atomically update the TypeHandle
1110 Crst m_EHClauseCritSec;
1112 // must hold critical section to access this structure.
1113 CUnorderedArray<DomainCodeHeapList *, 5> m_DomainCodeHeaps;
1114 CUnorderedArray<DomainCodeHeapList *, 5> m_DynamicDomainCodeHeaps;
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
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
1133 //*****************************************************************************
1135 // This class manages IJitManagers and ICorJitCompilers. It has only static
1136 // members. It should never be constucted.
1138 //*****************************************************************************
1140 class ExecutionManager
1142 friend class CorExternalDataAccess;
1143 friend struct _DacGlobals;
1145 #ifdef DACCESS_COMPILE
1146 friend class ClrDataAccess;
1154 // When this is passed to a function, it must directly acquire a reader lock
1155 // before it may continue
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)
1166 // Returns default scan flag for current thread
1167 static ScanFlag GetScanFlags();
1169 // Returns whether currentPC is in managed code. Returns false for jump stubs on WIN64.
1170 static BOOL IsManagedCode(PCODE currentPC);
1172 // Special version with profiler hook
1173 static BOOL IsManagedCode(PCODE currentPC, HostCallPreference hostCallPreference, BOOL *pfFailedReaderLock);
1175 // Returns methodDesc for given PC
1176 static MethodDesc * GetCodeMethodDesc(PCODE currentPC);
1178 static IJitManager* FindJitMan(PCODE currentPC)
1187 RangeSection * pRange = FindCodeRange(currentPC, GetScanFlags());
1188 return (pRange != NULL) ? pRange->pjit : NULL;
1191 static RangeSection * FindCodeRange(PCODE currentPC, ScanFlag scanFlag);
1193 static BOOL IsCollectibleMethod(const METHODTOKEN& MethodToken);
1195 class ReaderLockHolder
1198 ReaderLockHolder(HostCallPreference hostCallPreference = AllowHostCalls);
1199 ~ReaderLockHolder();
1205 static ULONG GetCLRPersonalityRoutineValue()
1207 LIMITED_METHOD_CONTRACT;
1208 static_assert_no_msg(offsetof(HeapList, CLRPersonalityRoutine) ==
1209 (size_t)((ULONG)offsetof(HeapList, CLRPersonalityRoutine)));
1210 return offsetof(HeapList, CLRPersonalityRoutine);
1214 static EEJitManager * GetEEJitManager()
1216 LIMITED_METHOD_DAC_CONTRACT;
1217 return m_pEEJitManager;
1220 #ifdef FEATURE_PREJIT
1221 static NativeImageJitManager * GetNativeImageJitManager()
1223 LIMITED_METHOD_DAC_CONTRACT;
1224 return m_pNativeImageJitManager;
1228 #ifdef FEATURE_READYTORUN
1229 static ReadyToRunJitManager * GetReadyToRunJitManager()
1231 LIMITED_METHOD_DAC_CONTRACT;
1232 return m_pReadyToRunJitManager;
1236 static void ClearCaches( void );
1237 static BOOL IsCacheCleanupRequired();
1239 static LPWSTR GetJitName();
1241 static void Unload(LoaderAllocator *pLoaderAllocator);
1243 static void AddCodeRange(TADDR StartRange, TADDR EndRange,
1245 RangeSection::RangeSectionFlags flags,
1248 static void AddNativeImageRange(TADDR StartRange,
1252 static void DeleteRange(TADDR StartRange);
1254 static void CleanupCodeHeaps();
1256 static ICodeManager* GetDefaultCodeManager()
1258 LIMITED_METHOD_CONTRACT;
1259 return (ICodeManager *)m_pDefaultCodeMan;
1262 static PTR_Module FindZapModule(TADDR currentData);
1264 // FindZapModule flavor to be used during GC to find GCRefMap
1265 static PTR_Module FindModuleForGCRefMap(TADDR currentData);
1267 static RangeSection* GetRangeSectionAndPrev(RangeSection *pRS, TADDR addr, RangeSection **ppPrev);
1269 #ifdef DACCESS_COMPILE
1270 static void EnumRangeList(RangeSection* list,
1271 CLRDataEnumMemoryFlags flags);
1272 static void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
1275 #ifndef DACCESS_COMPILE
1276 static PCODE jumpStub(MethodDesc* pMD,
1280 LoaderAllocator *pLoaderAllocator = NULL);
1284 static RangeSection * FindCodeRangeWithLock(PCODE currentPC);
1286 static BOOL IsManagedCodeWithLock(PCODE currentPC);
1287 static BOOL IsManagedCodeWorker(PCODE currentPC);
1289 static RangeSection* GetRangeSection(TADDR addr);
1291 SPTR_DECL(EECodeManager, m_pDefaultCodeMan);
1293 SPTR_DECL(EEJitManager, m_pEEJitManager);
1294 #ifdef FEATURE_PREJIT
1295 SPTR_DECL(NativeImageJitManager, m_pNativeImageJitManager);
1297 #ifdef FEATURE_READYTORUN
1298 SPTR_DECL(ReadyToRunJitManager, m_pReadyToRunJitManager);
1301 static CrstStatic m_JumpStubCrst;
1302 static CrstStatic m_RangeCrst; // Aquire before writing into m_CodeRangeList and m_DataRangeList
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;
1311 SPTR_DECL(RangeSection, m_CodeRangeList);
1312 SVAL_DECL(LONG, m_dwReaderCount);
1313 SVAL_DECL(LONG, m_dwWriterLock);
1316 #ifndef DACCESS_COMPILE
1317 class WriterLockHolder
1321 ~WriterLockHolder();
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
1335 static void * GetPtrForLockContract()
1337 return (void *) &m_dwReaderCount;
1339 #endif // defined(_DEBUG)
1341 static void AddRangeHelper(TADDR StartRange,
1344 RangeSection::RangeSectionFlags flags,
1345 TADDR pHeapListOrZapModule);
1346 static void DeleteRangeHelper(RangeSection** ppRangeList,
1349 #ifndef DACCESS_COMPILE
1350 static PCODE getNextJumpStub(MethodDesc* pMD,
1352 BYTE * loAddr, BYTE * hiAddr,
1353 LoaderAllocator *pLoaderAllocator);
1357 // ***************************************************************************
1358 // Hashtable for JumpStubs for jitted code
1360 struct JumpStubEntry {
1365 class JumpStubTraits : public DefaultSHashTraits<JumpStubEntry>
1368 typedef PCODE key_t;
1370 static key_t GetKey(element_t e)
1372 LIMITED_METHOD_CONTRACT;
1375 static BOOL Equals(key_t k1, key_t k2)
1377 LIMITED_METHOD_CONTRACT;
1380 static count_t Hash(key_t k)
1382 LIMITED_METHOD_CONTRACT;
1384 return (count_t) ((size_t) k ^ ((size_t) k >> 32));
1386 return (count_t)(size_t)k;
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; }
1395 typedef SHash<JumpStubTraits> JumpStubTable;
1397 struct JumpStubCache
1402 LIMITED_METHOD_CONTRACT;
1405 JumpStubBlockHeader * m_pBlocks;
1406 JumpStubTable m_Table;
1409 #if defined(_TARGET_AMD64_)
1411 static bool UsingCompatJit()
1413 LIMITED_METHOD_DAC_CONTRACT;
1414 return (m_pEEJitManager != nullptr) && m_pEEJitManager->m_fUsingCompatJit;
1419 inline CodeHeader * EEJitManager::GetCodeHeader(const METHODTOKEN& MethodToken)
1421 LIMITED_METHOD_DAC_CONTRACT;
1422 _ASSERTE(!MethodToken.IsNull());
1423 return dac_cast<PTR_CodeHeader>(MethodToken.m_pCodeHeader);
1426 inline CodeHeader * EEJitManager::GetCodeHeaderFromStartAddress(TADDR methodStartAddress)
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));
1434 inline TADDR EEJitManager::JitTokenToStartAddress(const METHODTOKEN& MethodToken)
1443 CodeHeader * pCH = GetCodeHeader(MethodToken);
1444 return pCH->GetCodeStartAddress();
1447 inline void EEJitManager::JitTokenToMethodRegionInfo(const METHODTOKEN& MethodToken,
1448 MethodRegionInfo * methodRegionInfo)
1455 PRECONDITION(methodRegionInfo != NULL);
1458 methodRegionInfo->hotStartAddress = JitTokenToStartAddress(MethodToken);
1459 methodRegionInfo->hotSize = GetCodeManager()->GetFunctionSize(GetGCInfo(MethodToken));
1460 methodRegionInfo->coldStartAddress = 0;
1461 methodRegionInfo->coldSize = 0;
1465 //-----------------------------------------------------------------------------
1466 #ifdef FEATURE_PREJIT
1468 //*****************************************************************************
1469 // Stub JitManager for Managed native.
1471 class NativeImageJitManager : public IJitManager
1473 VPTR_VTABLE_CLASS(NativeImageJitManager, IJitManager)
1476 #ifndef DACCESS_COMPILE
1477 NativeImageJitManager();
1478 #endif // #ifndef DACCESS_COMPILE
1480 virtual DWORD GetCodeType()
1482 LIMITED_METHOD_DAC_CONTRACT;
1483 return (miManaged | miNative);
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);
1495 virtual BOOL JitCodeToMethodInfo(RangeSection * pRangeSection,
1497 MethodDesc ** ppMethodDesc,
1498 EECodeInfo * pCodeInfo);
1500 virtual PCODE GetCodeAddressForRelOffset(const METHODTOKEN& MethodToken, DWORD relOffset);
1502 static PTR_Module JitTokenToZapModule(const METHODTOKEN& MethodToken);
1503 virtual TADDR JitTokenToStartAddress(const METHODTOKEN& MethodToken);
1504 virtual void JitTokenToMethodRegionInfo(const METHODTOKEN& MethodToken, MethodRegionInfo * methodRegionInfo);
1506 virtual unsigned InitializeEHEnumeration(const METHODTOKEN& MethodToken, EH_CLAUSE_ENUMERATOR* pEnumState);
1508 virtual PTR_EXCEPTION_CLAUSE_TOKEN GetNextEHClause(EH_CLAUSE_ENUMERATOR* pEnumState,
1509 EE_ILEXCEPTION_CLAUSE* pEHclause);
1511 #ifndef DACCESS_COMPILE
1512 virtual TypeHandle ResolveEHClause(EE_ILEXCEPTION_CLAUSE* pEHClause,
1514 #endif // #ifndef DACCESS_COMPILE
1516 virtual PTR_VOID GetGCInfo(const METHODTOKEN& MethodToken);
1518 #if defined(WIN64EXCEPTIONS)
1519 virtual PTR_RUNTIME_FUNCTION LazyGetFunctionEntry(EECodeInfo * pCodeInfo);
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
1526 virtual StubCodeBlockKind GetStubCodeBlockKind(RangeSection * pRangeSection, PCODE currentPC);
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
1538 class NativeExceptionInfoLookupTable
1541 static DWORD LookupExceptionInfoRVAForMethod(PTR_CORCOMPILE_EXCEPTION_LOOKUP_TABLE pTable,
1542 COUNT_T numLookupEntries,
1543 DWORD methodStartRVA,
1547 class NativeUnwindInfoLookupTable
1550 static int LookupUnwindInfoForMethod(DWORD codeOffset,
1551 PTR_RUNTIME_FUNCTION pRuntimeFunctionTable,
1555 static BOOL HasExceptionInfo(NGenLayoutInfo * pNgenLayout, PTR_RUNTIME_FUNCTION pMainRuntimeFunction);
1556 static PTR_MethodDesc GetMethodDesc(NGenLayoutInfo * pNgenLayout, PTR_RUNTIME_FUNCTION pMainRuntimeFunction, TADDR moduleBase);
1559 static DWORD GetMethodDescRVA(NGenLayoutInfo * pNgenLayout, PTR_RUNTIME_FUNCTION pMainRuntimeFunction);
1562 inline TADDR NativeImageJitManager::JitTokenToStartAddress(const METHODTOKEN& MethodToken)
1571 return JitTokenToModuleBase(MethodToken) +
1572 RUNTIME_FUNCTION__BeginAddress(dac_cast<PTR_RUNTIME_FUNCTION>(MethodToken.m_pCodeHeader));
1575 #endif // FEATURE_PREJIT
1577 #ifdef FEATURE_READYTORUN
1579 class ReadyToRunJitManager : public IJitManager
1581 VPTR_VTABLE_CLASS(ReadyToRunJitManager, IJitManager)
1584 #ifndef DACCESS_COMPILE
1585 ReadyToRunJitManager();
1586 #endif // #ifndef DACCESS_COMPILE
1588 virtual DWORD GetCodeType()
1590 LIMITED_METHOD_DAC_CONTRACT;
1591 return (miManaged | miNative);
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);
1603 virtual BOOL JitCodeToMethodInfo(RangeSection * pRangeSection,
1605 MethodDesc** ppMethodDesc,
1606 OUT EECodeInfo * pCodeInfo);
1608 virtual PCODE GetCodeAddressForRelOffset(const METHODTOKEN& MethodToken, DWORD relOffset);
1610 static ReadyToRunInfo * JitTokenToReadyToRunInfo(const METHODTOKEN& MethodToken);
1611 static PTR_RUNTIME_FUNCTION JitTokenToRuntimeFunction(const METHODTOKEN& MethodToken);
1613 virtual TADDR JitTokenToStartAddress(const METHODTOKEN& MethodToken);
1614 virtual void JitTokenToMethodRegionInfo(const METHODTOKEN& MethodToken, MethodRegionInfo * methodRegionInfo);
1616 virtual unsigned InitializeEHEnumeration(const METHODTOKEN& MethodToken, EH_CLAUSE_ENUMERATOR* pEnumState);
1618 virtual PTR_EXCEPTION_CLAUSE_TOKEN GetNextEHClause(EH_CLAUSE_ENUMERATOR* pEnumState,
1619 EE_ILEXCEPTION_CLAUSE* pEHclause);
1621 #ifndef DACCESS_COMPILE
1622 virtual TypeHandle ResolveEHClause(EE_ILEXCEPTION_CLAUSE* pEHClause,
1624 #endif // #ifndef DACCESS_COMPILE
1626 virtual PTR_VOID GetGCInfo(const METHODTOKEN& MethodToken);
1628 #if defined(WIN64EXCEPTIONS)
1629 virtual PTR_RUNTIME_FUNCTION LazyGetFunctionEntry(EECodeInfo * pCodeInfo);
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
1636 virtual StubCodeBlockKind GetStubCodeBlockKind(RangeSection * pRangeSection, PCODE currentPC);
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
1650 //*****************************************************************************
1651 // EECodeInfo provides information about code at particular address:
1652 // - Start of the method and relative offset
1653 // - GC Info of the method
1656 // EECodeInfo caches information from IJitManager and thus avoids
1657 // quering IJitManager repeatedly for same data.
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);
1670 EECodeInfo(PCODE codeAddress)
1675 // Explicit initialization
1676 void Init(PCODE codeAddress);
1677 void Init(PCODE codeAddress, ExecutionManager::ScanFlag scanFlag);
1679 TADDR GetSavedMethodCode();
1681 TADDR GetStartAddress();
1685 LIMITED_METHOD_DAC_CONTRACT;
1686 return m_pJM != NULL;
1689 IJitManager* GetJitManager()
1691 LIMITED_METHOD_DAC_CONTRACT;
1692 _ASSERTE(m_pJM != NULL);
1696 ICodeManager* GetCodeManager()
1698 LIMITED_METHOD_DAC_CONTRACT;
1699 return GetJitManager()->GetCodeManager();
1702 const METHODTOKEN& GetMethodToken()
1704 LIMITED_METHOD_DAC_CONTRACT;
1705 return m_methodToken;
1708 // This returns a pointer to the start of an instruction; conceptually, a PINSTR.
1709 TADDR GetCodeAddress()
1711 LIMITED_METHOD_DAC_CONTRACT;
1712 return PCODEToPINSTR(m_codeAddress);
1715 MethodDesc * GetMethodDesc()
1717 LIMITED_METHOD_DAC_CONTRACT;
1721 DWORD GetRelOffset()
1723 LIMITED_METHOD_DAC_CONTRACT;
1727 PTR_VOID GetGCInfo()
1729 WRAPPER_NO_CONTRACT;
1730 return GetJitManager()->GetGCInfo(GetMethodToken());
1733 void GetMethodRegionInfo(IJitManager::MethodRegionInfo *methodRegionInfo)
1735 WRAPPER_NO_CONTRACT;
1736 return GetJitManager()->JitTokenToMethodRegionInfo(GetMethodToken(), methodRegionInfo);
1739 TADDR GetModuleBase()
1741 WRAPPER_NO_CONTRACT;
1742 return GetJitManager()->JitTokenToModuleBase(GetMethodToken());
1745 #ifdef WIN64EXCEPTIONS
1746 PTR_RUNTIME_FUNCTION GetFunctionEntry();
1747 BOOL IsFunclet() { WRAPPER_NO_CONTRACT; return GetJitManager()->IsFunclet(this); }
1748 EECodeInfo GetMainFunctionInfo();
1749 ULONG GetFixedStackSize();
1751 #if defined(_TARGET_AMD64_)
1752 BOOL HasFrameRegister();
1753 #endif // _TARGET_AMD64_
1755 #else // WIN64EXCEPTIONS
1756 ULONG GetFixedStackSize()
1758 WRAPPER_NO_CONTRACT;
1759 return GetCodeManager()->GetFrameSize(GetGCInfo());
1761 #endif // WIN64EXCEPTIONS
1763 #if defined(_TARGET_AMD64_)
1764 void GetOffsetsFromUnwindInfo(ULONG* pRSPOffset, ULONG* pRBPOffset);
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_
1773 PCODE m_codeAddress;
1774 METHODTOKEN m_methodToken;
1778 #ifdef WIN64EXCEPTIONS
1779 PTR_RUNTIME_FUNCTION m_pFunctionEntry;
1780 #endif // WIN64EXCEPTIONS
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_
1788 #include "codeman.inl"
1791 #ifdef FEATURE_PREJIT
1792 class MethodSectionIterator;
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.
1798 class MethodIterator
1801 enum MethodIteratorOptions
1805 All = Hot | Unprofiled
1809 MethodIteratorOptions methodIteratorOptions;
1811 NGenLayoutInfo * m_pNgenLayout;
1812 BOOL m_fHotMethodsDone;
1813 COUNT_T m_CurrentRuntimeFunctionIndex;
1814 COUNT_T m_CurrentColdRuntimeFunctionIndex;
1816 void Init(PTR_Module pModule, PEDecoder * pPEDecoder, MethodIteratorOptions mio);
1819 MethodIterator(PTR_Module pModule, MethodIteratorOptions mio = All);
1820 MethodIterator(PTR_Module pModule, PEDecoder * pPEDecoder, MethodIteratorOptions mio = All);
1824 PTR_MethodDesc GetMethodDesc();
1825 PTR_VOID GetGCInfo();
1826 TADDR GetMethodStartAddress();
1827 TADDR GetMethodColdStartAddress();
1828 ULONG GetHotCodeSize();
1830 PTR_RUNTIME_FUNCTION GetRuntimeFunction();
1832 void GetMethodRegionInfo(IJitManager::MethodRegionInfo *methodRegionInfo);
1834 #endif //FEATURE_PREJIT
1836 void ThrowOutOfMemoryWithinRange();
1838 #endif // !__CODEMAN_HPP__