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)
394 #ifdef DACCESS_COMPILE
398 // virtual dtor. Clean up heap
399 virtual ~CodeHeap() {}
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;
405 #ifdef DACCESS_COMPILE
406 virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags) = 0;
410 friend class EEJitManager;
413 //-----------------------------------------------------------------------------
414 // The HeapList works together with the CodeHeap to manage a contiguous block of memory.
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.
419 // The number of code heaps at which we increase the size of new code heaps.
420 #define CODE_HEAP_SIZE_INCREASE_THRESHOLD 5
422 typedef DPTR(struct _HeapList) PTR_HeapList;
424 typedef struct _HeapList
431 TADDR endAddress; // the current end of the used portion of the Heap
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
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
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
447 PTR_HeapList GetNext()
448 { SUPPORTS_DAC; return hpNext; }
450 void SetNext(PTR_HeapList next)
454 { VolatileStore(&bFull, true); }
457 { return VolatileLoad(&bFull); }
459 void SetHeapFullForJumpStubs()
460 { VolatileStore(&bFullForJumpStubs, true); }
462 bool IsHeapFullForJumpStubs()
463 { return VolatileLoad(&bFullForJumpStubs); }
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)
472 typedef VPTR(class LoaderCodeHeap) PTR_LoaderCodeHeap;
474 class LoaderCodeHeap : CodeHeap
476 #ifdef DACCESS_COMPILE
477 friend class ClrDataAccess;
480 VPTR_VTABLE_CLASS(LoaderCodeHeap, CodeHeap)
483 ExplicitControlLoaderHeap m_LoaderHeap;
484 SSIZE_T m_cbMinNextPad;
486 LoaderCodeHeap(size_t * pPrivatePCLBytes);
489 static HeapList* CreateCodeHeap(CodeHeapRequestInfo *pInfo, LoaderHeap *pJitMetaHeap);
492 virtual ~LoaderCodeHeap()
497 virtual void* AllocMemForCode_NoThrow(size_t header, size_t size, DWORD alignment) DAC_EMPTY_RET(NULL);
499 #ifdef DACCESS_COMPILE
500 virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
503 m_LoaderHeap.EnumMemoryRegions(flags);
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.
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)
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.
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
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.
532 typedef DPTR(class UnwindInfoTable) PTR_UnwindInfoTable;
533 class UnwindInfoTable {
535 // All public functions are thread-safe.
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);
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);
546 // By default this publishing is off, this routine turns it on (and optionally publishes existing methods)
547 static void PublishUnwindInfo(bool publishExisting);
553 UnwindInfoTable(ULONG_PTR rangeStart, ULONG_PTR rangeEnd, ULONG size);
554 static void PublishUnwindInfoForExistingMethods();
557 static Volatile<bool> s_publishingActive; // Publishing to ETW is turned on
558 static class Crst* s_pUnwindInfoTableLock; // lock protects all public UnwindInfoTable functions
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.
569 #endif // defined(_WIN64)
571 //-----------------------------------------------------------------------------
572 // The ExecutionManager uses RangeSection as the abstraction of a contiguous
573 // address range to track the code heaps.
575 typedef DPTR(struct RangeSection) PTR_RangeSection;
582 PTR_IJitManager pjit; // The owner of this address range
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
588 PTR_RangeSection pnext;
591 PTR_RangeSection pLastUsed; // for the head node only: a link to rangesections that was used most recently
593 enum RangeSectionFlags
595 RANGE_SECTION_NONE = 0x0,
596 RANGE_SECTION_COLLECTIBLE = 0x1,
597 RANGE_SECTION_CODEHEAP = 0x2,
598 #ifdef FEATURE_READYTORUN
599 RANGE_SECTION_READYTORUN = 0x4,
607 // PTR_CodeHeap pCodeHeap; // valid if RANGE_SECTION_HEAP is set
608 // PTR_Module pZapModule; // valid if RANGE_SECTION_HEAP is not set
610 TADDR pHeapListOrZapModule;
612 PTR_UnwindInfoTable pUnwindInfoTable; // Points to unwind information for this memory range.
613 #endif // defined(_WIN64)
616 /*****************************************************************************/
618 #ifdef CROSSGEN_COMPILE
619 #define CodeFragmentHeap LoaderHeap
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.
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.
630 class CodeFragmentHeap : public ILoaderHeapBackout
632 PTR_LoaderAllocator m_pAllocator;
636 DPTR(FreeBlock) m_pNext; // Next block
637 SIZE_T m_dwSize; // Size of this block (includes size of FreeBlock)
639 typedef DPTR(FreeBlock) PTR_FreeBlock;
641 PTR_FreeBlock m_pFreeBlocks;
642 StubCodeBlockKind m_kind;
646 void AddBlock(VOID * pMem, size_t dwSize);
647 void RemoveBlock(FreeBlock ** ppBlock);
650 CodeFragmentHeap(LoaderAllocator * pAllocator, StubCodeBlockKind kind);
652 TaggedMemAllocPtr RealAllocAlignedMem(size_t dwRequestedSize
653 ,unsigned dwAlignment
655 ,__in __in_z const char *szFile
660 virtual void RealBackoutMem(void *pMem
663 , __in __in_z const char *szFile
665 , __in __in_z const char *szAllocFile
670 #ifdef DACCESS_COMPILE
671 void EnumMemoryRegions(enum CLRDataEnumMemoryFlags flags)
678 #endif // CROSSGEN_COMPILE
680 typedef DPTR(class CodeFragmentHeap) PTR_CodeFragmentHeap;
682 //-----------------------------------------------------------------------------
684 // Manages the CodeHeap for some of the RangeSections in the ExecutionManager
686 //-----------------------------------------------------------------------------
690 VPTR_BASE_VTABLE_CLASS(IJitManager)
693 struct MethodRegionInfo
695 TADDR hotStartAddress;
697 TADDR coldStartAddress;
701 #ifndef DACCESS_COMPILE
703 #endif // !DACCESS_COMPILE
705 virtual DWORD GetCodeType() = 0;
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)
715 virtual BOOL GetBoundariesAndVars(
716 const DebugInfoRequest & request,
717 IN FP_IDS_NEW fpNew, IN void * pNewData,
719 OUT ICorDebugInfo::OffsetMapping **ppMap,
720 OUT ULONG32 * pcVars,
721 OUT ICorDebugInfo::NativeVarInfo **ppVars) = 0;
723 virtual BOOL JitCodeToMethodInfo(
724 RangeSection * pRangeSection,
726 MethodDesc** ppMethodDesc,
727 OUT EECodeInfo * pCodeInfo) = 0;
729 virtual PCODE GetCodeAddressForRelOffset(const METHODTOKEN& MethodToken, DWORD relOffset) = 0;
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,
739 #endif // #ifndef DACCESS_COMPILE
741 virtual PTR_VOID GetGCInfo(const METHODTOKEN& MethodToken)=0;
743 TADDR JitTokenToModuleBase(const METHODTOKEN& MethodToken);
745 #if defined(WIN64EXCEPTIONS)
746 virtual PTR_RUNTIME_FUNCTION LazyGetFunctionEntry(EECodeInfo * pCodeInfo) = 0;
748 // GetFuncletStartAddress returns the starting address of the function or funclet indicated by the EECodeInfo address.
749 virtual TADDR GetFuncletStartAddress(EECodeInfo * pCodeInfo);
751 virtual DWORD GetFuncletStartOffsets(const METHODTOKEN& MethodToken, DWORD* pStartFuncletOffsets, DWORD dwLength) = 0;
753 BOOL IsFunclet(EECodeInfo * pCodeInfo);
754 virtual BOOL IsFilterFunclet(EECodeInfo * pCodeInfo);
755 #endif // WIN64EXCEPTIONS
757 virtual StubCodeBlockKind GetStubCodeBlockKind(RangeSection * pRangeSection, PCODE currentPC) = 0;
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
771 #ifndef DACCESS_COMPILE
772 void SetCodeManager(ICodeManager *codeMgr)
774 LIMITED_METHOD_CONTRACT;
776 m_runtimeSupport = codeMgr;
778 #endif // !DACCESS_COMPILE
780 ICodeManager *GetCodeManager()
782 LIMITED_METHOD_DAC_CONTRACT;
783 return m_runtimeSupport;
787 PTR_ICodeManager m_runtimeSupport;
790 //-----------------------------------------------------------------------------
793 typedef VPTR(class HostCodeHeap) PTR_HostCodeHeap;
795 typedef VPTR(class EEJitManager) PTR_EEJitManager;
796 typedef VPTR(class NativeImageJitManager) PTR_NativeImageJitManager;
797 typedef VPTR(class ReadyToRunJitManager) PTR_ReadyToRunJitManager;
799 struct JumpStubBlockHeader
801 JumpStubBlockHeader * m_next;
805 LoaderAllocator* GetLoaderAllocator()
807 _ASSERTE(m_zero == 0);
811 void SetLoaderAllocator(LoaderAllocator * loaderAllocator)
814 m_Allocator = loaderAllocator;
817 HostCodeHeap* GetHostCodeHeap()
820 _ASSERTE(m_zero == -1);
824 void SetHostCodeHeap(HostCodeHeap * hostCodeHeap)
827 m_CodeHeap = hostCodeHeap;
832 HostCodeHeap *m_CodeHeap;
833 LoaderAllocator *m_Allocator;
836 INT64 m_zero; // 0 for normal methods and -1 for LCG methods
840 /*****************************************************************************/
842 class EEJitManager :public IJitManager
844 #ifdef DACCESS_COMPILE
845 friend class ClrDataAccess;
847 friend class CheckDuplicatedStructLayouts;
848 friend class CodeHeapIterator;
850 VPTR_VTABLE_CLASS(EEJitManager, IJitManager)
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.
858 LIMITED_METHOD_CONTRACT;
860 return (m_jit != NULL)
862 && (!m_AltJITRequired || (m_alternateJit != NULL))
863 #endif // ALLOW_SXS_JIT
868 BOOL IsMainJitLoaded()
870 LIMITED_METHOD_CONTRACT;
872 return (m_jit != NULL);
875 BOOL IsAltJitLoaded()
877 LIMITED_METHOD_CONTRACT;
879 return (m_alternateJit != NULL);
881 #endif // ALLOW_SXS_JIT
895 if( m_alternateJit != NULL )
897 m_alternateJit->clearCache();
899 #endif // ALLOW_SXS_JIT
902 BOOL IsCacheCleanupRequired()
913 if (m_jit->isCacheCleanupRequired())
918 if( !ret && m_alternateJit != NULL )
920 if (m_alternateJit->isCacheCleanupRequired())
923 #endif // ALLOW_SXS_JIT
928 #ifndef DACCESS_COMPILE
931 // No destructor necessary. Only one instance of this class that is destroyed at process shutdown.
933 #endif // #ifndef DACCESS_COMPILE
935 virtual DWORD GetCodeType()
937 LIMITED_METHOD_DAC_CONTRACT;
938 return (miManaged | miIL);
941 // Used to read debug info.
942 virtual BOOL GetBoundariesAndVars(
943 const DebugInfoRequest & request,
944 IN FP_IDS_NEW fpNew, IN void * pNewData,
946 OUT ICorDebugInfo::OffsetMapping **ppMap,
947 OUT ULONG32 * pcVars,
948 OUT ICorDebugInfo::NativeVarInfo **ppVars);
950 virtual BOOL JitCodeToMethodInfo(RangeSection * pRangeSection,
952 MethodDesc ** ppMethodDesc,
953 EECodeInfo * pCodeInfo);
955 virtual PCODE GetCodeAddressForRelOffset(const METHODTOKEN& MethodToken, DWORD relOffset);
957 virtual TADDR JitTokenToStartAddress(const METHODTOKEN& MethodToken);
958 virtual void JitTokenToMethodRegionInfo(const METHODTOKEN& MethodToken, MethodRegionInfo *methodRegionInfo);
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,
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);
971 void Unload(LoaderAllocator* pAllocator);
972 void CleanupCodeHeaps();
976 CodeHeader* allocCode(MethodDesc* pFD, size_t blockSize, CorJitAllocMemFlag flag
977 #ifdef WIN64EXCEPTIONS
979 , TADDR * pModuleBase
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);
989 void * allocCodeFragmentBlock(size_t blockSize, unsigned alignment, LoaderAllocator *pLoaderAllocator, StubCodeBlockKind kind);
990 #endif // #ifndef DACCESS_COMPILE
992 static CodeHeader * GetCodeHeader(const METHODTOKEN& MethodToken);
993 static CodeHeader * GetCodeHeaderFromStartAddress(TADDR methodStartAddress);
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);
999 virtual DWORD GetFuncletStartOffsets(const METHODTOKEN& MethodToken, DWORD* pStartFuncletOffsets, DWORD dwLength);
1000 #endif // WIN64EXCEPTIONS
1002 virtual StubCodeBlockKind GetStubCodeBlockKind(RangeSection * pRangeSection, PCODE currentPC);
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)
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).
1017 #endif // WIN64EXCEPTIONS
1018 #endif // DACCESS_COMPILE
1020 // Heap Management functions
1021 void NibbleMapSet(HeapList * pHp, TADDR pCode, BOOL bSet);
1023 static TADDR FindMethodCode(RangeSection * pRangeSection, PCODE currentPC);
1024 static TADDR FindMethodCode(PCODE currentPC);
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);
1035 struct DomainCodeHeapList {
1036 LoaderAllocator *m_pAllocator;
1037 CDynArray<HeapList *> m_CodeHeapList;
1038 DomainCodeHeapList();
1039 ~DomainCodeHeapList();
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 */ );
1049 DomainCodeHeapList *GetCodeHeapList(MethodDesc *pMD, LoaderAllocator *pAllocator, BOOL fDynamicOnly = FALSE);
1050 DomainCodeHeapList *CreateCodeHeapList(CodeHeapRequestInfo *pInfo);
1051 LoaderHeap* GetJitMetaHeap(MethodDesc *pMD);
1053 HeapList * GetCodeHeapList()
1059 void * allocEHInfoRaw(CodeHeader* pCodeHeader, DWORD blockSize, size_t * pAllocationSize);
1061 #endif // #ifndef DACCESS_COMPILE
1063 PTR_HeapList m_pCodeHeap;
1066 Crst m_CodeHeapCritSec;
1068 #if !defined(DACCESS_COMPILE)
1070 class CodeHeapIterator
1072 CrstHolder m_lockHolder;
1073 HeapList *m_pHeapList;
1074 LoaderAllocator *m_pLoaderAllocator;
1075 BaseDomain *m_pDomain;
1076 MethodSectionIterator m_Iterator;
1077 MethodDesc *m_pCurrent;
1080 CodeHeapIterator(BaseDomain *pDomainFilter = NULL, LoaderAllocator *pLoaderAllocatorFilter = NULL);
1081 ~CodeHeapIterator();
1084 MethodDesc *GetMethod()
1086 LIMITED_METHOD_CONTRACT;
1090 TADDR GetMethodCode()
1092 LIMITED_METHOD_CONTRACT;
1093 return (TADDR)m_Iterator.GetMethodCode();
1096 #endif // !DACCESS_COMPILE
1099 DWORD m_dwCPUCompileFlags;
1104 inline DWORD GetCPUCompileFlags()
1106 LIMITED_METHOD_CONTRACT;
1107 return m_dwCPUCompileFlags;
1111 PTR_HostCodeHeap m_cleanupList;
1112 //When EH Clauses are resolved we need to atomically update the TypeHandle
1113 Crst m_EHClauseCritSec;
1115 // must hold critical section to access this structure.
1116 CUnorderedArray<DomainCodeHeapList *, 5> m_DomainCodeHeaps;
1117 CUnorderedArray<DomainCodeHeapList *, 5> m_DynamicDomainCodeHeaps;
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
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
1136 //*****************************************************************************
1138 // This class manages IJitManagers and ICorJitCompilers. It has only static
1139 // members. It should never be constucted.
1141 //*****************************************************************************
1143 class ExecutionManager
1145 friend class CorExternalDataAccess;
1147 #ifdef DACCESS_COMPILE
1148 friend class ClrDataAccess;
1156 // When this is passed to a function, it must directly acquire a reader lock
1157 // before it may continue
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)
1168 // Returns default scan flag for current thread
1169 static ScanFlag GetScanFlags();
1171 // Returns whether currentPC is in managed code. Returns false for jump stubs on WIN64.
1172 static BOOL IsManagedCode(PCODE currentPC);
1174 // Special version with profiler hook
1175 static BOOL IsManagedCode(PCODE currentPC, HostCallPreference hostCallPreference, BOOL *pfFailedReaderLock);
1177 // Returns methodDesc for given PC
1178 static MethodDesc * GetCodeMethodDesc(PCODE currentPC);
1180 static IJitManager* FindJitMan(PCODE currentPC)
1189 RangeSection * pRange = FindCodeRange(currentPC, GetScanFlags());
1190 return (pRange != NULL) ? pRange->pjit : NULL;
1193 static RangeSection * FindCodeRange(PCODE currentPC, ScanFlag scanFlag);
1195 static BOOL IsCollectibleMethod(const METHODTOKEN& MethodToken);
1197 class ReaderLockHolder
1200 ReaderLockHolder(HostCallPreference hostCallPreference = AllowHostCalls);
1201 ~ReaderLockHolder();
1207 static ULONG GetCLRPersonalityRoutineValue()
1209 LIMITED_METHOD_CONTRACT;
1210 static_assert_no_msg(offsetof(HeapList, CLRPersonalityRoutine) ==
1211 (size_t)((ULONG)offsetof(HeapList, CLRPersonalityRoutine)));
1212 return offsetof(HeapList, CLRPersonalityRoutine);
1216 static EEJitManager * GetEEJitManager()
1218 LIMITED_METHOD_DAC_CONTRACT;
1219 return m_pEEJitManager;
1222 #ifdef FEATURE_PREJIT
1223 static NativeImageJitManager * GetNativeImageJitManager()
1225 LIMITED_METHOD_DAC_CONTRACT;
1226 return m_pNativeImageJitManager;
1230 #ifdef FEATURE_READYTORUN
1231 static ReadyToRunJitManager * GetReadyToRunJitManager()
1233 LIMITED_METHOD_DAC_CONTRACT;
1234 return m_pReadyToRunJitManager;
1238 static void ClearCaches( void );
1239 static BOOL IsCacheCleanupRequired();
1241 static LPWSTR GetJitName();
1243 static void Unload(LoaderAllocator *pLoaderAllocator);
1245 static void AddCodeRange(TADDR StartRange, TADDR EndRange,
1247 RangeSection::RangeSectionFlags flags,
1250 static void AddNativeImageRange(TADDR StartRange,
1254 static void DeleteRange(TADDR StartRange);
1256 static void CleanupCodeHeaps();
1258 static ICodeManager* GetDefaultCodeManager()
1260 LIMITED_METHOD_CONTRACT;
1261 return (ICodeManager *)m_pDefaultCodeMan;
1264 static PTR_Module FindZapModule(TADDR currentData);
1266 // FindZapModule flavor to be used during GC to find GCRefMap
1267 static PTR_Module FindModuleForGCRefMap(TADDR currentData);
1269 static RangeSection* GetRangeSectionAndPrev(RangeSection *pRS, TADDR addr, RangeSection **ppPrev);
1271 #ifdef DACCESS_COMPILE
1272 static void EnumRangeList(RangeSection* list,
1273 CLRDataEnumMemoryFlags flags);
1274 static void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
1277 #ifndef DACCESS_COMPILE
1278 static PCODE jumpStub(MethodDesc* pMD,
1282 LoaderAllocator *pLoaderAllocator = NULL);
1286 static RangeSection * FindCodeRangeWithLock(PCODE currentPC);
1288 static BOOL IsManagedCodeWithLock(PCODE currentPC);
1289 static BOOL IsManagedCodeWorker(PCODE currentPC);
1291 static RangeSection* GetRangeSection(TADDR addr);
1293 SPTR_DECL(EECodeManager, m_pDefaultCodeMan);
1295 SPTR_DECL(EEJitManager, m_pEEJitManager);
1296 #ifdef FEATURE_PREJIT
1297 SPTR_DECL(NativeImageJitManager, m_pNativeImageJitManager);
1299 #ifdef FEATURE_READYTORUN
1300 SPTR_DECL(ReadyToRunJitManager, m_pReadyToRunJitManager);
1303 static CrstStatic m_JumpStubCrst;
1304 static CrstStatic m_RangeCrst; // Aquire before writing into m_CodeRangeList and m_DataRangeList
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;
1313 SPTR_DECL(RangeSection, m_CodeRangeList);
1314 SVAL_DECL(LONG, m_dwReaderCount);
1315 SVAL_DECL(LONG, m_dwWriterLock);
1318 #ifndef DACCESS_COMPILE
1319 class WriterLockHolder
1323 ~WriterLockHolder();
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
1337 static void * GetPtrForLockContract()
1339 return (void *) &m_dwReaderCount;
1341 #endif // defined(_DEBUG)
1343 static void AddRangeHelper(TADDR StartRange,
1346 RangeSection::RangeSectionFlags flags,
1347 TADDR pHeapListOrZapModule);
1348 static void DeleteRangeHelper(RangeSection** ppRangeList,
1351 #ifndef DACCESS_COMPILE
1352 static PCODE getNextJumpStub(MethodDesc* pMD,
1354 BYTE * loAddr, BYTE * hiAddr,
1355 LoaderAllocator *pLoaderAllocator);
1359 // ***************************************************************************
1360 // Hashtable for JumpStubs for jitted code
1362 struct JumpStubEntry {
1367 class JumpStubTraits : public DefaultSHashTraits<JumpStubEntry>
1370 typedef PCODE key_t;
1372 static key_t GetKey(element_t e)
1374 LIMITED_METHOD_CONTRACT;
1377 static BOOL Equals(key_t k1, key_t k2)
1379 LIMITED_METHOD_CONTRACT;
1382 static count_t Hash(key_t k)
1384 LIMITED_METHOD_CONTRACT;
1386 return (count_t) ((size_t) k ^ ((size_t) k >> 32));
1388 return (count_t)(size_t)k;
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; }
1397 typedef SHash<JumpStubTraits> JumpStubTable;
1399 struct JumpStubCache
1404 LIMITED_METHOD_CONTRACT;
1407 JumpStubBlockHeader * m_pBlocks;
1408 JumpStubTable m_Table;
1411 #if defined(_TARGET_AMD64_)
1413 static bool UsingCompatJit()
1415 LIMITED_METHOD_DAC_CONTRACT;
1416 return (m_pEEJitManager != nullptr) && m_pEEJitManager->m_fUsingCompatJit;
1421 inline CodeHeader * EEJitManager::GetCodeHeader(const METHODTOKEN& MethodToken)
1423 LIMITED_METHOD_DAC_CONTRACT;
1424 _ASSERTE(!MethodToken.IsNull());
1425 return dac_cast<PTR_CodeHeader>(MethodToken.m_pCodeHeader);
1428 inline CodeHeader * EEJitManager::GetCodeHeaderFromStartAddress(TADDR methodStartAddress)
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));
1436 inline TADDR EEJitManager::JitTokenToStartAddress(const METHODTOKEN& MethodToken)
1445 CodeHeader * pCH = GetCodeHeader(MethodToken);
1446 return pCH->GetCodeStartAddress();
1449 inline void EEJitManager::JitTokenToMethodRegionInfo(const METHODTOKEN& MethodToken,
1450 MethodRegionInfo * methodRegionInfo)
1457 PRECONDITION(methodRegionInfo != NULL);
1460 methodRegionInfo->hotStartAddress = JitTokenToStartAddress(MethodToken);
1461 methodRegionInfo->hotSize = GetCodeManager()->GetFunctionSize(GetGCInfo(MethodToken));
1462 methodRegionInfo->coldStartAddress = 0;
1463 methodRegionInfo->coldSize = 0;
1467 //-----------------------------------------------------------------------------
1468 #ifdef FEATURE_PREJIT
1470 //*****************************************************************************
1471 // Stub JitManager for Managed native.
1473 class NativeImageJitManager : public IJitManager
1475 VPTR_VTABLE_CLASS(NativeImageJitManager, IJitManager)
1478 #ifndef DACCESS_COMPILE
1479 NativeImageJitManager();
1480 #endif // #ifndef DACCESS_COMPILE
1482 virtual DWORD GetCodeType()
1484 LIMITED_METHOD_DAC_CONTRACT;
1485 return (miManaged | miNative);
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);
1497 virtual BOOL JitCodeToMethodInfo(RangeSection * pRangeSection,
1499 MethodDesc ** ppMethodDesc,
1500 EECodeInfo * pCodeInfo);
1502 virtual PCODE GetCodeAddressForRelOffset(const METHODTOKEN& MethodToken, DWORD relOffset);
1504 static PTR_Module JitTokenToZapModule(const METHODTOKEN& MethodToken);
1505 virtual TADDR JitTokenToStartAddress(const METHODTOKEN& MethodToken);
1506 virtual void JitTokenToMethodRegionInfo(const METHODTOKEN& MethodToken, MethodRegionInfo * methodRegionInfo);
1508 virtual unsigned InitializeEHEnumeration(const METHODTOKEN& MethodToken, EH_CLAUSE_ENUMERATOR* pEnumState);
1510 virtual PTR_EXCEPTION_CLAUSE_TOKEN GetNextEHClause(EH_CLAUSE_ENUMERATOR* pEnumState,
1511 EE_ILEXCEPTION_CLAUSE* pEHclause);
1513 #ifndef DACCESS_COMPILE
1514 virtual TypeHandle ResolveEHClause(EE_ILEXCEPTION_CLAUSE* pEHClause,
1516 #endif // #ifndef DACCESS_COMPILE
1518 virtual PTR_VOID GetGCInfo(const METHODTOKEN& MethodToken);
1520 #if defined(WIN64EXCEPTIONS)
1521 virtual PTR_RUNTIME_FUNCTION LazyGetFunctionEntry(EECodeInfo * pCodeInfo);
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
1528 virtual StubCodeBlockKind GetStubCodeBlockKind(RangeSection * pRangeSection, PCODE currentPC);
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
1540 class NativeExceptionInfoLookupTable
1543 static DWORD LookupExceptionInfoRVAForMethod(PTR_CORCOMPILE_EXCEPTION_LOOKUP_TABLE pTable,
1544 COUNT_T numLookupEntries,
1545 DWORD methodStartRVA,
1549 class NativeUnwindInfoLookupTable
1552 static int LookupUnwindInfoForMethod(DWORD codeOffset,
1553 PTR_RUNTIME_FUNCTION pRuntimeFunctionTable,
1557 static BOOL HasExceptionInfo(NGenLayoutInfo * pNgenLayout, PTR_RUNTIME_FUNCTION pMainRuntimeFunction);
1558 static PTR_MethodDesc GetMethodDesc(NGenLayoutInfo * pNgenLayout, PTR_RUNTIME_FUNCTION pMainRuntimeFunction, TADDR moduleBase);
1561 static DWORD GetMethodDescRVA(NGenLayoutInfo * pNgenLayout, PTR_RUNTIME_FUNCTION pMainRuntimeFunction);
1564 inline TADDR NativeImageJitManager::JitTokenToStartAddress(const METHODTOKEN& MethodToken)
1573 return JitTokenToModuleBase(MethodToken) +
1574 RUNTIME_FUNCTION__BeginAddress(dac_cast<PTR_RUNTIME_FUNCTION>(MethodToken.m_pCodeHeader));
1577 #endif // FEATURE_PREJIT
1579 #ifdef FEATURE_READYTORUN
1581 class ReadyToRunJitManager : public IJitManager
1583 VPTR_VTABLE_CLASS(ReadyToRunJitManager, IJitManager)
1586 #ifndef DACCESS_COMPILE
1587 ReadyToRunJitManager();
1588 #endif // #ifndef DACCESS_COMPILE
1590 virtual DWORD GetCodeType()
1592 LIMITED_METHOD_DAC_CONTRACT;
1593 return (miManaged | miNative);
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);
1605 virtual BOOL JitCodeToMethodInfo(RangeSection * pRangeSection,
1607 MethodDesc** ppMethodDesc,
1608 OUT EECodeInfo * pCodeInfo);
1610 virtual PCODE GetCodeAddressForRelOffset(const METHODTOKEN& MethodToken, DWORD relOffset);
1612 static ReadyToRunInfo * JitTokenToReadyToRunInfo(const METHODTOKEN& MethodToken);
1613 static PTR_RUNTIME_FUNCTION JitTokenToRuntimeFunction(const METHODTOKEN& MethodToken);
1615 virtual TADDR JitTokenToStartAddress(const METHODTOKEN& MethodToken);
1616 virtual void JitTokenToMethodRegionInfo(const METHODTOKEN& MethodToken, MethodRegionInfo * methodRegionInfo);
1618 virtual unsigned InitializeEHEnumeration(const METHODTOKEN& MethodToken, EH_CLAUSE_ENUMERATOR* pEnumState);
1620 virtual PTR_EXCEPTION_CLAUSE_TOKEN GetNextEHClause(EH_CLAUSE_ENUMERATOR* pEnumState,
1621 EE_ILEXCEPTION_CLAUSE* pEHclause);
1623 #ifndef DACCESS_COMPILE
1624 virtual TypeHandle ResolveEHClause(EE_ILEXCEPTION_CLAUSE* pEHClause,
1626 #endif // #ifndef DACCESS_COMPILE
1628 virtual PTR_VOID GetGCInfo(const METHODTOKEN& MethodToken);
1630 #if defined(WIN64EXCEPTIONS)
1631 virtual PTR_RUNTIME_FUNCTION LazyGetFunctionEntry(EECodeInfo * pCodeInfo);
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
1638 virtual StubCodeBlockKind GetStubCodeBlockKind(RangeSection * pRangeSection, PCODE currentPC);
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
1652 //*****************************************************************************
1653 // EECodeInfo provides information about code at particular address:
1654 // - Start of the method and relative offset
1655 // - GC Info of the method
1658 // EECodeInfo caches information from IJitManager and thus avoids
1659 // quering IJitManager repeatedly for same data.
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);
1672 EECodeInfo(PCODE codeAddress)
1677 // Explicit initialization
1678 void Init(PCODE codeAddress);
1679 void Init(PCODE codeAddress, ExecutionManager::ScanFlag scanFlag);
1681 TADDR GetSavedMethodCode();
1683 TADDR GetStartAddress();
1687 LIMITED_METHOD_DAC_CONTRACT;
1688 return m_pJM != NULL;
1691 IJitManager* GetJitManager()
1693 LIMITED_METHOD_DAC_CONTRACT;
1694 _ASSERTE(m_pJM != NULL);
1698 ICodeManager* GetCodeManager()
1700 LIMITED_METHOD_DAC_CONTRACT;
1701 return GetJitManager()->GetCodeManager();
1704 const METHODTOKEN& GetMethodToken()
1706 LIMITED_METHOD_DAC_CONTRACT;
1707 return m_methodToken;
1710 // This returns a pointer to the start of an instruction; conceptually, a PINSTR.
1711 TADDR GetCodeAddress()
1713 LIMITED_METHOD_DAC_CONTRACT;
1714 return PCODEToPINSTR(m_codeAddress);
1717 MethodDesc * GetMethodDesc()
1719 LIMITED_METHOD_DAC_CONTRACT;
1723 DWORD GetRelOffset()
1725 LIMITED_METHOD_DAC_CONTRACT;
1729 PTR_VOID GetGCInfo()
1731 WRAPPER_NO_CONTRACT;
1732 return GetJitManager()->GetGCInfo(GetMethodToken());
1735 void GetMethodRegionInfo(IJitManager::MethodRegionInfo *methodRegionInfo)
1737 WRAPPER_NO_CONTRACT;
1738 return GetJitManager()->JitTokenToMethodRegionInfo(GetMethodToken(), methodRegionInfo);
1741 TADDR GetModuleBase()
1743 WRAPPER_NO_CONTRACT;
1744 return GetJitManager()->JitTokenToModuleBase(GetMethodToken());
1747 #ifdef WIN64EXCEPTIONS
1748 PTR_RUNTIME_FUNCTION GetFunctionEntry();
1749 BOOL IsFunclet() { WRAPPER_NO_CONTRACT; return GetJitManager()->IsFunclet(this); }
1750 EECodeInfo GetMainFunctionInfo();
1751 ULONG GetFixedStackSize();
1753 #if defined(_TARGET_AMD64_)
1754 BOOL HasFrameRegister();
1755 #endif // _TARGET_AMD64_
1757 #else // WIN64EXCEPTIONS
1758 ULONG GetFixedStackSize()
1760 WRAPPER_NO_CONTRACT;
1761 return GetCodeManager()->GetFrameSize(GetGCInfo());
1763 #endif // WIN64EXCEPTIONS
1765 #if defined(_TARGET_AMD64_)
1766 void GetOffsetsFromUnwindInfo(ULONG* pRSPOffset, ULONG* pRBPOffset);
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_
1775 PCODE m_codeAddress;
1776 METHODTOKEN m_methodToken;
1780 #ifdef WIN64EXCEPTIONS
1781 PTR_RUNTIME_FUNCTION m_pFunctionEntry;
1782 #endif // WIN64EXCEPTIONS
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_
1790 #include "codeman.inl"
1793 #ifdef FEATURE_PREJIT
1794 class MethodSectionIterator;
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.
1800 class MethodIterator
1803 enum MethodIteratorOptions
1807 All = Hot | Unprofiled
1811 MethodIteratorOptions methodIteratorOptions;
1813 NGenLayoutInfo * m_pNgenLayout;
1814 BOOL m_fHotMethodsDone;
1815 COUNT_T m_CurrentRuntimeFunctionIndex;
1816 COUNT_T m_CurrentColdRuntimeFunctionIndex;
1818 void Init(PTR_Module pModule, PEDecoder * pPEDecoder, MethodIteratorOptions mio);
1821 MethodIterator(PTR_Module pModule, MethodIteratorOptions mio = All);
1822 MethodIterator(PTR_Module pModule, PEDecoder * pPEDecoder, MethodIteratorOptions mio = All);
1826 PTR_MethodDesc GetMethodDesc();
1827 PTR_VOID GetGCInfo();
1828 TADDR GetMethodStartAddress();
1829 TADDR GetMethodColdStartAddress();
1830 ULONG GetHotCodeSize();
1832 PTR_RUNTIME_FUNCTION GetRuntimeFunction();
1834 void GetMethodRegionInfo(IJitManager::MethodRegionInfo *methodRegionInfo);
1836 #endif //FEATURE_PREJIT
1838 void ThrowOutOfMemoryWithinRange();
1840 #endif // !__CODEMAN_HPP__