diff options
author | Jan Kotas <jkotas@microsoft.com> | 2016-03-31 00:44:55 -0700 |
---|---|---|
committer | Jan Kotas <jkotas@microsoft.com> | 2016-03-31 00:44:55 -0700 |
commit | d3502c29c511292d0c6046b1aafe87295d2372d9 (patch) | |
tree | 92a8862dfa8f94137662dd16aae5d1a7b2859f72 | |
parent | 0cce34c8976fd887bee0cf877c36b9abfa555635 (diff) | |
parent | c4378e7f0773577e9924ff4ebad0cc3af43fb3a8 (diff) | |
download | coreclr-d3502c29c511292d0c6046b1aafe87295d2372d9.tar.gz coreclr-d3502c29c511292d0c6046b1aafe87295d2372d9.tar.bz2 coreclr-d3502c29c511292d0c6046b1aafe87295d2372d9.zip |
Merge pull request #4021 from dotnet-bot/from-tfs
Merge changes from TFS
45 files changed, 289 insertions, 114 deletions
diff --git a/src/ToolBox/SOS/Strike/platformspecific.h b/src/ToolBox/SOS/Strike/platformspecific.h index d79a46055e..fdbc5b52ca 100644 --- a/src/ToolBox/SOS/Strike/platformspecific.h +++ b/src/ToolBox/SOS/Strike/platformspecific.h @@ -47,6 +47,10 @@ struct DT_UNICODE_STRING #define IMAGE_FILE_MACHINE_ARMNT 0x01c4 // ARM Thumb-2 Little-Endian #endif +#ifndef IMAGE_FILE_MACHINE_ARM64 +#define IMAGE_FILE_MACHINE_ARM64 0xAA64 // ARM64 Little-Endian +#endif + #ifdef _TARGET_WIN64_ typedef ULONG DT_GDI_HANDLE_BUFFER[DT_GDI_HANDLE_BUFFER_SIZE64]; #else diff --git a/src/ToolBox/SOS/Strike/util.cpp b/src/ToolBox/SOS/Strike/util.cpp index 8722845a72..c26bae49fa 100644 --- a/src/ToolBox/SOS/Strike/util.cpp +++ b/src/ToolBox/SOS/Strike/util.cpp @@ -4557,6 +4557,8 @@ public: *pPlatform = CORDB_PLATFORM_WINDOWS_AMD64; else if(platformKind == IMAGE_FILE_MACHINE_ARMNT) *pPlatform = CORDB_PLATFORM_WINDOWS_ARM; + else if(platformKind == IMAGE_FILE_MACHINE_ARM64) + *pPlatform = CORDB_PLATFORM_WINDOWS_ARM64; else return E_FAIL; #endif diff --git a/src/debug/daccess/fntableaccess.cpp b/src/debug/daccess/fntableaccess.cpp index 66298832d2..e7b96ec3e0 100644 --- a/src/debug/daccess/fntableaccess.cpp +++ b/src/debug/daccess/fntableaccess.cpp @@ -143,7 +143,7 @@ static NTSTATUS OutOfProcessFunctionTableCallback_JIT(IN ReadMemoryFunction IN PVOID pUserContext, IN PVOID TableAddress, OUT PULONG pnEntries, - OUT PRUNTIME_FUNCTION* ppFunctions) + OUT PT_RUNTIME_FUNCTION* ppFunctions) { if (NULL == pnEntries) { return STATUS_INVALID_PARAMETER_3; } if (NULL == ppFunctions) { return STATUS_INVALID_PARAMETER_4; } @@ -179,7 +179,7 @@ static NTSTATUS OutOfProcessFunctionTableCallback_JIT(IN ReadMemoryFunction DWORD nEntries; DWORD index; DWORD_PTR pUnwindInfo; - PRUNTIME_FUNCTION pFunctions; + PT_RUNTIME_FUNCTION pFunctions; LONG64 lSmallestOffset; // @@ -217,7 +217,7 @@ static NTSTATUS OutOfProcessFunctionTableCallback_JIT(IN ReadMemoryFunction OutOfProcessFindHeader(fpReadMemory, pUserContext, Hp.pHdrMap, hdrOffset, hdrOffset); } - pFunctions = (PRUNTIME_FUNCTION)ClrHeapAlloc(ClrGetProcessHeap(), HEAP_ZERO_MEMORY, S_SIZE_T(nEntries) * S_SIZE_T(sizeof(RUNTIME_FUNCTION))); + pFunctions = (PT_RUNTIME_FUNCTION)ClrHeapAlloc(ClrGetProcessHeap(), HEAP_ZERO_MEMORY, S_SIZE_T(nEntries) * S_SIZE_T(sizeof(T_RUNTIME_FUNCTION))); *ppFunctions = pFunctions; *pnEntries = nEntries; @@ -274,7 +274,7 @@ static NTSTATUS OutOfProcessFunctionTableCallback_Stub(IN ReadMemoryFunction IN PVOID pUserContext, IN PVOID TableAddress, OUT PULONG pnEntries, - OUT PRUNTIME_FUNCTION* ppFunctions) + OUT PT_RUNTIME_FUNCTION* ppFunctions) { if (NULL == pnEntries) { return STATUS_INVALID_PARAMETER_3; } if (NULL == ppFunctions) { return STATUS_INVALID_PARAMETER_4; } @@ -292,7 +292,7 @@ static NTSTATUS OutOfProcessFunctionTableCallback_Stub(IN ReadMemoryFunction UINT nEntries = 0; UINT nEntriesAllocated = 0; - RUNTIME_FUNCTION *rgFunctions = NULL; + PT_RUNTIME_FUNCTION rgFunctions = NULL; for (int pass = 1; pass <= 2; pass++) { @@ -371,7 +371,7 @@ static NTSTATUS OutOfProcessFunctionTableCallback_Stub(IN ReadMemoryFunction _ASSERTE(!nEntriesAllocated); nEntriesAllocated = nEntries; - rgFunctions = (PRUNTIME_FUNCTION)ClrHeapAlloc(ClrGetProcessHeap(), HEAP_ZERO_MEMORY, S_SIZE_T(nEntries) * S_SIZE_T(sizeof(RUNTIME_FUNCTION))); + rgFunctions = (PT_RUNTIME_FUNCTION)ClrHeapAlloc(ClrGetProcessHeap(), HEAP_ZERO_MEMORY, S_SIZE_T(nEntries) * S_SIZE_T(sizeof(T_RUNTIME_FUNCTION))); nEntries = 0; } else @@ -397,7 +397,7 @@ BOOL ReadMemory(PVOID pUserContext, LPCVOID lpBaseAddress, PVOID lpBuffer, SIZE_ extern "C" NTSTATUS OutOfProcessFunctionTableCallback(IN HANDLE hProcess, IN PVOID TableAddress, OUT PULONG pnEntries, - OUT PRUNTIME_FUNCTION* ppFunctions) + OUT PT_RUNTIME_FUNCTION* ppFunctions) { return OutOfProcessFunctionTableCallbackEx(&ReadMemory, hProcess, TableAddress, pnEntries, ppFunctions); } @@ -406,7 +406,7 @@ extern "C" NTSTATUS OutOfProcessFunctionTableCallbackEx(IN ReadMemoryFunction IN PVOID pUserContext, IN PVOID TableAddress, OUT PULONG pnEntries, - OUT PRUNTIME_FUNCTION* ppFunctions) + OUT PT_RUNTIME_FUNCTION* ppFunctions) { if (NULL == pnEntries) { return STATUS_INVALID_PARAMETER_3; } if (NULL == ppFunctions) { return STATUS_INVALID_PARAMETER_4; } diff --git a/src/debug/daccess/fntableaccess.h b/src/debug/daccess/fntableaccess.h index 9e98e7c51f..0dbabdf8c9 100644 --- a/src/debug/daccess/fntableaccess.h +++ b/src/debug/daccess/fntableaccess.h @@ -53,7 +53,7 @@ typedef struct _FakeHpRealCodeHdr LPVOID phdrJitGCInfo; // changed from BYTE* LPVOID hdrMDesc; // changed from MethodDesc* DWORD nUnwindInfos; - RUNTIME_FUNCTION unwindInfos[0]; + T_RUNTIME_FUNCTION unwindInfos[0]; } FakeRealCodeHeader; typedef struct _FakeHpCodeHdr @@ -75,7 +75,7 @@ struct FakeStubUnwindInfoHeaderSuffix struct FakeStubUnwindInfoHeader { FakeStubUnwindInfoHeader *pNext; - RUNTIME_FUNCTION FunctionEntry; + T_RUNTIME_FUNCTION FunctionEntry; UNWIND_INFO UnwindInfo; // variable length }; @@ -200,7 +200,7 @@ static_assert_no_msg( FAKEDYNFNTABLE_STUB BOOL WINAPI DllMain(HINSTANCE hDLL, DWORD dwReason, LPVOID pReserved); //NTSTATUS OutOfProcessFindHeader(HANDLE hProcess, DWORD_PTR pMapIn, DWORD_PTR addr, DWORD_PTR &codeHead); -extern "C" NTSTATUS OutOfProcessFunctionTableCallback(IN HANDLE hProcess, IN PVOID TableAddress, OUT PULONG pnEntries, OUT PRUNTIME_FUNCTION* ppFunctions); +extern "C" NTSTATUS OutOfProcessFunctionTableCallback(IN HANDLE hProcess, IN PVOID TableAddress, OUT PULONG pnEntries, OUT PT_RUNTIME_FUNCTION* ppFunctions); // OutOfProcessFunctionTableCallbackEx is like the standard OS-defined OutOfProcessFunctionTableCallback, but rather @@ -209,7 +209,7 @@ extern "C" NTSTATUS OutOfProcessFunctionTableCallback(IN HANDLE hProcess, IN // pUserContext is passed directly to fpReadMemory, and the semantics of all other ReadMemoryFunction arguments (and return value) are // the same as those for kernel32!ReadProcessMemory. typedef BOOL (ReadMemoryFunction)(PVOID pUserContext, LPCVOID lpBaseAddress, PVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesRead); -extern "C" NTSTATUS OutOfProcessFunctionTableCallbackEx(IN ReadMemoryFunction fpReadMemory, IN PVOID pUserContext, IN PVOID TableAddress, OUT PULONG pnEntries, OUT PRUNTIME_FUNCTION* ppFunctions); +extern "C" NTSTATUS OutOfProcessFunctionTableCallbackEx(IN ReadMemoryFunction fpReadMemory, IN PVOID pUserContext, IN PVOID TableAddress, OUT PULONG pnEntries, OUT PT_RUNTIME_FUNCTION* ppFunctions); #endif // CHECK_DUPLICATED_STRUCT_LAYOUTS diff --git a/src/debug/daccess/nidump.cpp b/src/debug/daccess/nidump.cpp index 8dcac82865..9b4fe1c176 100644 --- a/src/debug/daccess/nidump.cpp +++ b/src/debug/daccess/nidump.cpp @@ -9315,7 +9315,7 @@ void NativeImageDumper::DumpReadyToRun() if (pRuntimeFunctionsDir != NULL) { m_pRuntimeFunctions = dac_cast<PTR_RUNTIME_FUNCTION>(m_decoder.GetDirectoryData(pRuntimeFunctionsDir)); - m_nRuntimeFunctions = pRuntimeFunctionsDir->Size / sizeof(RUNTIME_FUNCTION); + m_nRuntimeFunctions = pRuntimeFunctionsDir->Size / sizeof(T_RUNTIME_FUNCTION); } else { diff --git a/src/gcdump/gcdumpnonx86.cpp b/src/gcdump/gcdumpnonx86.cpp index 361a4f8ec4..8167d3abd8 100644 --- a/src/gcdump/gcdumpnonx86.cpp +++ b/src/gcdump/gcdumpnonx86.cpp @@ -42,12 +42,27 @@ PCSTR GetRegName (UINT32 regnum) return "???"; #elif defined(_TARGET_ARM64_) - if (regnum > 28) - return "???"; static CHAR szRegName[16]; - _snprintf_s(szRegName, _countof(szRegName), sizeof(szRegName), "X%u", regnum); - return szRegName; + if (regnum < 29) + { + _snprintf_s(szRegName, _countof(szRegName), sizeof(szRegName), "X%u", regnum); + return szRegName; + } + else if(regnum == 29) + { + return "Fp"; + } + else if(regnum == 30) + { + return "Lr"; + } + else if(regnum == 31) + { + return "Sp"; + } + + return "???"; #elif defined(_TARGET_ARM_) if (regnum > 128) return "???"; diff --git a/src/gcinfo/gcinfodumper.cpp b/src/gcinfo/gcinfodumper.cpp index 68465a301e..34666d63e8 100644 --- a/src/gcinfo/gcinfodumper.cpp +++ b/src/gcinfo/gcinfodumper.cpp @@ -75,6 +75,11 @@ void GcInfoDumper::FreePointerRecords (LivePointerRecord *pRecords) } } +//This function tries to find the address of the managed object in the registers of the current function's context, +//failing which it checks if it is present in the stack of the current function. IF it finds one it reports appropriately +// +//For Amd64, this additionally tries to probe in the stack for the caller. +//This behavior largely seems to be present for legacy x64 jit and is not likely to be used anywhere else BOOL GcInfoDumper::ReportPointerRecord ( UINT32 CodeOffset, BOOL fLive, @@ -146,7 +151,6 @@ BOOL GcInfoDumper::ReportPointerRecord ( { FIELD_OFFSET(T_CONTEXT, Sp) }, { FIELD_OFFSET(T_KNONVOLATILE_CONTEXT_POINTERS, R7) }, #elif defined(_TARGET_ARM64_) -//ARM64TODO: Verify the correctness of the following for ARM64 #undef REG #define REG(reg, field) { FIELD_OFFSET(Arm64VolatileContextPointer, field) } REG(x0, X0), @@ -167,7 +171,6 @@ BOOL GcInfoDumper::ReportPointerRecord ( REG(x15, X15), REG(x16, X16), REG(x17, X17), - { FIELD_OFFSET(T_CONTEXT, X18) }, #undef REG #define REG(reg, field) { FIELD_OFFSET(T_KNONVOLATILE_CONTEXT_POINTERS, field) } REG(x19, X19), @@ -180,11 +183,14 @@ BOOL GcInfoDumper::ReportPointerRecord ( REG(x26, X26), REG(x27, X27), REG(x28, X28), + REG(Fp, Fp), + REG(Lr, Lr), { FIELD_OFFSET(T_CONTEXT, Sp) }, - { FIELD_OFFSET(T_KNONVOLATILE_CONTEXT_POINTERS, Lr) }, +#undef REG +#else +PORTABILITY_ASSERT("GcInfoDumper::ReportPointerRecord is not implemented on this platform.") #endif -#undef REG }; const UINT nCONTEXTRegisters = sizeof(rgRegisters)/sizeof(rgRegisters[0]); @@ -199,13 +205,12 @@ BOOL GcInfoDumper::ReportPointerRecord ( iSPRegister = (FIELD_OFFSET(CONTEXT, Rsp) - FIELD_OFFSET(CONTEXT, Rax)) / sizeof(ULONGLONG); #elif defined(_TARGET_ARM64_) iSPRegister = (FIELD_OFFSET(T_CONTEXT, Sp) - FIELD_OFFSET(T_CONTEXT, X0)) / sizeof(ULONGLONG); - UINT iBFRegister = m_StackBaseRegister; #elif defined(_TARGET_ARM_) iSPRegister = (FIELD_OFFSET(T_CONTEXT, Sp) - FIELD_OFFSET(T_CONTEXT, R0)) / sizeof(ULONG); UINT iBFRegister = m_StackBaseRegister; #endif -#ifdef _TARGET_ARM_ +#if defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) BYTE* pContext = (BYTE*)&(pRD->volatileCurrContextPointers); #else BYTE* pContext = (BYTE*)pRD->pCurrentContext; @@ -254,6 +259,25 @@ BOOL GcInfoDumper::ReportPointerRecord ( { break; } +#elif defined (_TARGET_ARM64_) + + if (ctx == 1) + { + if (iReg < 18 ) // skip volatile registers for second context + { + continue; + } + + if (iReg == 30) + { + iEncodedReg = iSPRegister; + } + } + + if (ctx == 0 && iReg > 17) + { + break; + } #endif { _ASSERTE(iReg < nCONTEXTRegisters); @@ -271,6 +295,13 @@ BOOL GcInfoDumper::ReportPointerRecord ( { pReg = *(SIZE_T**)((BYTE*)pRD->pCurrentContextPointers + rgRegisters[iEncodedReg].cbContextOffset); } + +#elif defined(_TARGET_ARM64_) + pReg = *(SIZE_T**)(pContext + rgRegisters[iReg].cbContextOffset); + if (iEncodedReg == iSPRegister) + { + pReg = (SIZE_T*)((BYTE*)pRD->pCurrentContext + rgRegisters[iEncodedReg].cbContextOffset); + } #else pReg = (SIZE_T*)(pContext + rgRegisters[iReg].cbContextOffset); #endif @@ -286,7 +317,7 @@ BOOL GcInfoDumper::ReportPointerRecord ( if (ptr == (SIZE_T)pReg) { // Make sure the register is in the current frame. -#ifndef _TARGET_ARM_ +#if defined(_TARGET_AMD64_) if (0 != ctx) { m_Error = REPORTED_REGISTER_IN_CALLERS_FRAME; @@ -338,10 +369,14 @@ BOOL GcInfoDumper::ReportPointerRecord ( GcStackSlotBase base; if (iSPRegister == iEncodedReg) { +#if defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) + base = GC_SP_REL; +#else if (0 == ctx) base = GC_SP_REL; else base = GC_CALLER_SP_REL; +#endif //defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) } else { @@ -363,7 +398,7 @@ BOOL GcInfoDumper::ReportPointerRecord ( } } -#ifdef _TARGET_ARM_ +#if defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) pContext = (BYTE*)pRD->pCurrentContextPointers; #else pContext = (BYTE*)pRD->pCallerContext; @@ -542,6 +577,34 @@ GcInfoDumper::EnumerateStateChangesResults GcInfoDumper::EnumerateStateChanges ( } /// Set R12 *(ppVolatileReg+4) = ®disp.pCurrentContext->R0+12; + +#elif defined(_TARGET_ARM64_) + FILL_REGS(pCurrentContext->X0, 33); + FILL_REGS(pCallerContext->X0, 33); + + regdisp.pCurrentContextPointers = ®disp.ctxPtrsOne; + regdisp.pCallerContextPointers = ®disp.ctxPtrsTwo; + + ULONG64 **ppCurrentReg = ®disp.pCurrentContextPointers->X19; + ULONG64 **ppCallerReg = ®disp.pCallerContextPointers->X19; + + for (iReg = 0; iReg < 11; iReg++) + { + *(ppCurrentReg + iReg) = ®disp.pCurrentContext->X19 + iReg; + *(ppCallerReg + iReg) = ®disp.pCallerContext->X19 + iReg; + } + + /// Set Lr + *(ppCurrentReg + 11) = ®disp.pCurrentContext->Lr; + *(ppCallerReg + 11) = ®disp.pCallerContext->Lr; + + ULONG64 **ppVolatileReg = ®disp.volatileCurrContextPointers.X0; + for (iReg = 0; iReg < 18; iReg++) + { + *(ppVolatileReg+iReg) = ®disp.pCurrentContext->X0 + iReg; + } +#else +PORTABILITY_ASSERT("GcInfoDumper::EnumerateStateChanges is not implemented on this platform.") #endif #undef FILL_REGS diff --git a/src/inc/clrnt.h b/src/inc/clrnt.h index 5958906898..fd7e56b61b 100644 --- a/src/inc/clrnt.h +++ b/src/inc/clrnt.h @@ -762,7 +762,7 @@ typedef enum _FUNCTION_TABLE_TYPE { typedef struct _DYNAMIC_FUNCTION_TABLE { LIST_ENTRY Links; - PRUNTIME_FUNCTION FunctionTable; + PT_RUNTIME_FUNCTION FunctionTable; LARGE_INTEGER TimeStamp; #ifdef _TARGET_ARM_ @@ -796,7 +796,7 @@ typedef struct _DYNAMIC_FUNCTION_TABLE { #define RUNTIME_FUNCTION__GetUnwindInfoAddress(prf) (prf)->UnwindData #define RUNTIME_FUNCTION__SetUnwindInfoAddress(prf,address) do { (prf)->UnwindData = (address); } while (0) -#define OFFSETOF__RUNTIME_FUNCTION__UnwindInfoAddress offsetof(RUNTIME_FUNCTION, UnwindData) +#define OFFSETOF__RUNTIME_FUNCTION__UnwindInfoAddress offsetof(T_RUNTIME_FUNCTION, UnwindData) // @@ -893,7 +893,7 @@ PEXCEPTION_ROUTINE IN ULONG HandlerType, IN ULONG64 ImageBase, IN ULONG64 ControlPc, - IN PRUNTIME_FUNCTION FunctionEntry, + IN PT_RUNTIME_FUNCTION FunctionEntry, IN OUT PCONTEXT ContextRecord, OUT PVOID *HandlerData, OUT PULONG64 EstablisherFrame, @@ -908,7 +908,7 @@ RtlVirtualUnwind_Unsafe( IN ULONG HandlerType, IN ULONG64 ImageBase, IN ULONG64 ControlPc, - IN PRUNTIME_FUNCTION FunctionEntry, + IN PT_RUNTIME_FUNCTION FunctionEntry, IN OUT PCONTEXT ContextRecord, OUT PVOID *HandlerData, OUT PULONG64 EstablisherFrame, @@ -951,7 +951,7 @@ typedef struct _DISPATCHER_CONTEXT { FORCEINLINE ULONG RtlpGetFunctionEndAddress ( - __in PRUNTIME_FUNCTION FunctionEntry, + __in PT_RUNTIME_FUNCTION FunctionEntry, __in ULONG ImageBase ) { @@ -1011,6 +1011,7 @@ RtlVirtualUnwind ( #endif // _TARGET_ARM_ #ifdef _TARGET_ARM64_ +#include "daccess.h" #define UNW_FLAG_NHANDLER 0x0 /* any handler */ #define UNW_FLAG_EHANDLER 0x1 /* filter handler */ @@ -1031,7 +1032,7 @@ RtlpGetFunctionEndAddress ( if ((FunctionLength & 3) != 0) { FunctionLength = (FunctionLength >> 2) & 0x7ff; } else { - FunctionLength = *(ULONG64*)(ImageBase + FunctionLength) & 0x3ffff; + FunctionLength = *(PTR_ULONG64)(ImageBase + FunctionLength) & 0x3ffff; } return FunctionEntry->BeginAddress + 4 * FunctionLength; diff --git a/src/inc/corinfo.h b/src/inc/corinfo.h index bb1a1c339c..fb839996c0 100644 --- a/src/inc/corinfo.h +++ b/src/inc/corinfo.h @@ -231,11 +231,11 @@ TODO: Talk about initializing strutures before use #if COR_JIT_EE_VERSION > 460 // Update this one -SELECTANY const GUID JITEEVersionIdentifier = { /* 35ef98ab-fd22-4ccc-8ddb-b1156a7d94f3 */ - 0x35ef98ab, - 0xfd22, - 0x4ccc, - { 0x8d, 0xdb, 0xb1, 0x15, 0x6a, 0x7d, 0x94, 0xf3 } +SELECTANY const GUID JITEEVersionIdentifier = { /* 27626524-7315-4ed0-b74e-a0e4579883bb */ + 0x27626524, + 0x7315, + 0x4ed0, + { 0xb7, 0x4e, 0xa0, 0xe4, 0x57, 0x98, 0x83, 0xbb } }; #else @@ -2390,6 +2390,14 @@ public: CORINFO_CONST_LOOKUP * pLookup ) = 0; +#if COR_JIT_EE_VERSION > 460 + virtual void getReadyToRunDelegateCtorHelper( + CORINFO_RESOLVED_TOKEN * pTargetMethod, + CORINFO_CLASS_HANDLE delegateType, + CORINFO_CONST_LOOKUP * pLookup + ) = 0; +#endif + virtual const char* getHelperName( CorInfoHelpFunc ) = 0; diff --git a/src/inc/regdisp.h b/src/inc/regdisp.h index 1dbfafae41..09a6a38f62 100644 --- a/src/inc/regdisp.h +++ b/src/inc/regdisp.h @@ -104,6 +104,7 @@ typedef struct _Arm64VolatileContextPointer PDWORD64 X15; PDWORD64 X16; PDWORD64 X17; + //X18 is reserved by OS, in userspace it represents TEB }; PDWORD64 X[18]; }; diff --git a/src/jit/flowgraph.cpp b/src/jit/flowgraph.cpp index d075401ed4..4e3ba8648b 100644 --- a/src/jit/flowgraph.cpp +++ b/src/jit/flowgraph.cpp @@ -6924,7 +6924,12 @@ GenTreePtr Compiler::fgOptimizeDelegateConstructor(GenTreePtr call, CORINFO_C helperArgs->gtOp.gtOp2 = gtNewArgList(call->gtCall.gtCallArgs->gtOp.gtOp1); call = gtNewHelperCallNode(CORINFO_HELP_READYTORUN_DELEGATE_CTOR, TYP_VOID, GTF_EXCEPT, helperArgs); - call->gtCall.gtEntryPoint = targetMethod->gtFptrVal.gtDelegateCtor; +#if COR_JIT_EE_VERSION > 460 + info.compCompHnd->getReadyToRunDelegateCtorHelper(targetMethod->gtFptrVal.gtLdftnResolvedToken, clsHnd, &call->gtCall.gtEntryPoint); +#else + info.compCompHnd->getReadyToRunHelper(targetMethod->gtFptrVal.gtLdftnResolvedToken, + CORINFO_HELP_READYTORUN_DELEGATE_CTOR, &call->gtCall.gtEntryPoint); +#endif } } else diff --git a/src/jit/gentree.cpp b/src/jit/gentree.cpp index cad84177c4..a0ce79b11c 100755..100644 --- a/src/jit/gentree.cpp +++ b/src/jit/gentree.cpp @@ -5954,7 +5954,7 @@ GenTreePtr Compiler::gtCloneExpr(GenTree * tree, #ifdef FEATURE_READYTORUN_COMPILER copy->gtFptrVal.gtEntryPoint = tree->gtFptrVal.gtEntryPoint; - copy->gtFptrVal.gtDelegateCtor = tree->gtFptrVal.gtDelegateCtor; + copy->gtFptrVal.gtLdftnResolvedToken = tree->gtFptrVal.gtLdftnResolvedToken; #endif goto DONE; diff --git a/src/jit/gentree.h b/src/jit/gentree.h index 631f67b79f..d95c473e17 100644 --- a/src/jit/gentree.h +++ b/src/jit/gentree.h @@ -2547,7 +2547,7 @@ struct GenTreeFptrVal: public GenTree #ifdef FEATURE_READYTORUN_COMPILER CORINFO_CONST_LOOKUP gtEntryPoint; - CORINFO_CONST_LOOKUP gtDelegateCtor; + CORINFO_RESOLVED_TOKEN* gtLdftnResolvedToken; #endif GenTreeFptrVal(var_types type, CORINFO_METHOD_HANDLE meth) : diff --git a/src/jit/importer.cpp b/src/jit/importer.cpp index 7993918df0..558fc1f39f 100644 --- a/src/jit/importer.cpp +++ b/src/jit/importer.cpp @@ -1663,10 +1663,8 @@ GenTreePtr Compiler::impMethodPointer(CORINFO_RESOLVED_TOKEN * pResolvedToken, C if (opts.IsReadyToRun()) { op1->gtFptrVal.gtEntryPoint = pCallInfo->codePointerLookup.constLookup; - - // In almost all cases, we are going to create the delegate out of the function pointer. While we are here, - // get the pointer to the optimized delegate helper. Only one of the two is going to be embedded into the code. - info.compCompHnd->getReadyToRunHelper(pResolvedToken, CORINFO_HELP_READYTORUN_DELEGATE_CTOR, &op1->gtFptrVal.gtDelegateCtor); + op1->gtFptrVal.gtLdftnResolvedToken = new(this, CMK_Unknown) CORINFO_RESOLVED_TOKEN; + *op1->gtFptrVal.gtLdftnResolvedToken = *pResolvedToken; } else op1->gtFptrVal.gtEntryPoint.addr = nullptr; diff --git a/src/unwinder/amd64/unwinder_amd64.cpp b/src/unwinder/amd64/unwinder_amd64.cpp index 583a11f2dc..b3dd1ab1ac 100644 --- a/src/unwinder/amd64/unwinder_amd64.cpp +++ b/src/unwinder/amd64/unwinder_amd64.cpp @@ -170,7 +170,7 @@ UNWIND_INFO * DacGetUnwindInfo(TADDR taUnwindInfo) { cbUnwindInfo += sizeof(UNWIND_CODE); } - cbUnwindInfo += sizeof(RUNTIME_FUNCTION); + cbUnwindInfo += sizeof(T_RUNTIME_FUNCTION); } return reinterpret_cast<UNWIND_INFO *>(DacInstantiateTypeByAddress(taUnwindInfo, cbUnwindInfo, true)); } @@ -325,7 +325,7 @@ PEXCEPTION_ROUTINE RtlVirtualUnwind_Unsafe( __in ULONG HandlerType, __in ULONG64 ImageBase, __in ULONG64 ControlPc, - __in PRUNTIME_FUNCTION FunctionEntry, + __in PT_RUNTIME_FUNCTION FunctionEntry, __in OUT PCONTEXT ContextRecord, __out PVOID *HandlerData, __out PULONG64 EstablisherFrame, diff --git a/src/unwinder/arm/unwinder_arm.cpp b/src/unwinder/arm/unwinder_arm.cpp index af595b9bb9..6b1f6864cc 100644 --- a/src/unwinder/arm/unwinder_arm.cpp +++ b/src/unwinder/arm/unwinder_arm.cpp @@ -1501,7 +1501,7 @@ PEXCEPTION_ROUTINE RtlVirtualUnwind( __in ULONG HandlerType, __in ULONG ImageBase, __in ULONG ControlPc, - __in PRUNTIME_FUNCTION FunctionEntry, + __in PT_RUNTIME_FUNCTION FunctionEntry, __in OUT PCONTEXT ContextRecord, __out PVOID *HandlerData, __out PULONG EstablisherFrame, diff --git a/src/unwinder/arm64/unwinder_arm64.cpp b/src/unwinder/arm64/unwinder_arm64.cpp index fb2f9340af..e13c7b917d 100644 --- a/src/unwinder/arm64/unwinder_arm64.cpp +++ b/src/unwinder/arm64/unwinder_arm64.cpp @@ -103,9 +103,9 @@ typedef struct _ARM64_VFP_STATE // Macros for accessing memory. These can be overridden if other code // (in particular the debugger) needs to use them. -#define MEMORY_READ_BYTE(params, addr) (*(const BYTE *)(addr)) -#define MEMORY_READ_DWORD(params, addr) (*(const DWORD *)(addr)) -#define MEMORY_READ_QWORD(params, addr) (*(const UINT64 *)(addr)) +#define MEMORY_READ_BYTE(params, addr) (*dac_cast<PTR_BYTE>(addr)) +#define MEMORY_READ_DWORD(params, addr) (*dac_cast<PTR_DWORD>(addr)) +#define MEMORY_READ_QWORD(params, addr) (*dac_cast<PTR_UINT64>(addr)) typedef struct _ARM64_UNWIND_PARAMS { @@ -1597,7 +1597,7 @@ RtlVirtualUnwind( IN ULONG HandlerType, IN ULONG64 ImageBase, IN ULONG64 ControlPc, - IN PRUNTIME_FUNCTION FunctionEntry, + IN PT_RUNTIME_FUNCTION FunctionEntry, IN OUT PCONTEXT ContextRecord, OUT PVOID *HandlerData, OUT PULONG64 EstablisherFrame, diff --git a/src/unwinder/unwinder.cpp b/src/unwinder/unwinder.cpp index 7b14b80798..5ab3048905 100644 --- a/src/unwinder/unwinder.cpp +++ b/src/unwinder/unwinder.cpp @@ -51,7 +51,7 @@ HRESULT OOPStackUnwinder::GetFunctionEntry( DWORD64 addres __out_ecount(cbBuffer) PVOID pBuffer, DWORD cbBuffer) { - if (cbBuffer < sizeof(RUNTIME_FUNCTION)) + if (cbBuffer < sizeof(T_RUNTIME_FUNCTION)) { return E_INVALIDARG; } diff --git a/src/vm/amd64/cgenamd64.cpp b/src/vm/amd64/cgenamd64.cpp index 9ba89ae8cf..a83c166474 100644 --- a/src/vm/amd64/cgenamd64.cpp +++ b/src/vm/amd64/cgenamd64.cpp @@ -799,7 +799,7 @@ BOOL DoesSlotCallPrestub(PCODE pCode) // we use this function to get at these offsets // DWORD GetOffsetAtEndOfFunction(ULONGLONG uImageBase, - PRUNTIME_FUNCTION pFunctionEntry, + PT_RUNTIME_FUNCTION pFunctionEntry, int offsetNum /* = 1*/) { CONTRACTL diff --git a/src/vm/amd64/cgencpu.h b/src/vm/amd64/cgencpu.h index c66692467a..3d99b6f7f0 100644 --- a/src/vm/amd64/cgencpu.h +++ b/src/vm/amd64/cgencpu.h @@ -507,7 +507,7 @@ struct HijackArgs #ifndef DACCESS_COMPILE DWORD GetOffsetAtEndOfFunction(ULONGLONG uImageBase, - PRUNTIME_FUNCTION pFunctionEntry, + PT_RUNTIME_FUNCTION pFunctionEntry, int offsetNum = 1); #endif // DACCESS_COMPILE diff --git a/src/vm/amd64/excepamd64.cpp b/src/vm/amd64/excepamd64.cpp index cf8ed14a8b..2fc553a987 100644 --- a/src/vm/amd64/excepamd64.cpp +++ b/src/vm/amd64/excepamd64.cpp @@ -147,7 +147,7 @@ RtlVirtualUnwind ( IN ULONG HandlerType, IN ULONG64 ImageBase, IN ULONG64 ControlPc, - IN PRUNTIME_FUNCTION FunctionEntry, + IN PT_RUNTIME_FUNCTION FunctionEntry, IN OUT PCONTEXT ContextRecord, OUT PVOID *HandlerData, OUT PULONG64 EstablisherFrame, @@ -183,7 +183,7 @@ RtlVirtualUnwind_Worker ( IN ULONG HandlerType, IN ULONG64 ImageBase, IN ULONG64 ControlPc, - IN PRUNTIME_FUNCTION FunctionEntry, + IN PT_RUNTIME_FUNCTION FunctionEntry, IN OUT PCONTEXT ContextRecord, OUT PVOID *HandlerData, OUT PULONG64 EstablisherFrame, @@ -430,7 +430,7 @@ RtlVirtualUnwind_Worker ( // as well as a single byte representation of the Function code so that tests to make sure // that we're out of the prologue will not fail. - RUNTIME_FUNCTION FakeFunctionEntry; + T_RUNTIME_FUNCTION FakeFunctionEntry; // // The buffer contains 4 sections diff --git a/src/vm/amd64/excepcpu.h b/src/vm/amd64/excepcpu.h index 5e96dbd1c5..150416608b 100644 --- a/src/vm/amd64/excepcpu.h +++ b/src/vm/amd64/excepcpu.h @@ -65,7 +65,7 @@ RtlVirtualUnwind ( IN ULONG HandlerType, IN ULONG64 ImageBase, IN ULONG64 ControlPc, - IN PRUNTIME_FUNCTION FunctionEntry, + IN PT_RUNTIME_FUNCTION FunctionEntry, IN OUT PCONTEXT ContextRecord, OUT PVOID *HandlerData, OUT PULONG64 EstablisherFrame, @@ -77,7 +77,7 @@ RtlVirtualUnwind_Worker ( IN ULONG HandlerType, IN ULONG64 ImageBase, IN ULONG64 ControlPc, - IN PRUNTIME_FUNCTION FunctionEntry, + IN PT_RUNTIME_FUNCTION FunctionEntry, IN OUT PCONTEXT ContextRecord, OUT PVOID *HandlerData, OUT PULONG64 EstablisherFrame, diff --git a/src/vm/clsload.hpp b/src/vm/clsload.hpp index ca561a8049..e2705ae2e4 100644 --- a/src/vm/clsload.hpp +++ b/src/vm/clsload.hpp @@ -87,18 +87,24 @@ public: const HashedTypeEntry& SetClassHashBasedEntryValue(EEClassHashEntry_t * pClassHashEntry) { + LIMITED_METHOD_CONTRACT; + m_EntryType = EntryType::IsHashedClassEntry; m_pClassHashEntry = dac_cast<PTR_EEClassHashEntry>(pClassHashEntry); return *this; } EEClassHashEntry_t * GetClassHashBasedEntryValue() { + LIMITED_METHOD_CONTRACT; + _ASSERT(m_EntryType == EntryType::IsHashedClassEntry); return m_pClassHashEntry; } const HashedTypeEntry& SetTokenBasedEntryValue(mdTypeDef typeToken, Module * pModule) { + LIMITED_METHOD_CONTRACT; + m_EntryType = EntryType::IsHashedTokenEntry; m_TokenAndModulePair.m_TypeToken = typeToken; m_TokenAndModulePair.m_pModule = pModule; @@ -106,6 +112,8 @@ public: } const TokenTypeEntry& GetTokenBasedEntryValue() { + LIMITED_METHOD_CONTRACT; + _ASSERT(m_EntryType == EntryType::IsHashedTokenEntry); return m_TokenAndModulePair; } diff --git a/src/vm/codeman.cpp b/src/vm/codeman.cpp index fec74bb6ae..e625bca06c 100644 --- a/src/vm/codeman.cpp +++ b/src/vm/codeman.cpp @@ -73,7 +73,7 @@ CrstStatic ExecutionManager::m_RangeCrst; // Support for new style unwind information (to allow OS to stack crawl JIT compiled code). typedef NTSTATUS (WINAPI* RtlAddGrowableFunctionTableFnPtr) ( - PVOID *DynamicTable, RUNTIME_FUNCTION* FunctionTable, ULONG EntryCount, + PVOID *DynamicTable, PRUNTIME_FUNCTION FunctionTable, ULONG EntryCount, ULONG MaximumEntryCount, ULONG_PTR rangeStart, ULONG_PTR rangeEnd); typedef VOID (WINAPI* RtlGrowFunctionTableFnPtr) (PVOID DynamicTable, ULONG NewEntryCount); typedef VOID (WINAPI* RtlDeleteGrowableFunctionTableFnPtr) (PVOID DynamicTable); @@ -92,7 +92,7 @@ Volatile<bool> UnwindInfoTable::s_publishingActive = false; #if _DEBUG // Fake functions on Win7 checked build to excercize the code paths, they are no-ops NTSTATUS WINAPI FakeRtlAddGrowableFunctionTable ( - PVOID *DynamicTable, RUNTIME_FUNCTION* FunctionTable, ULONG EntryCount, + PVOID *DynamicTable, PT_RUNTIME_FUNCTION FunctionTable, ULONG EntryCount, ULONG MaximumEntryCount, ULONG_PTR rangeStart, ULONG_PTR rangeEnd) { *DynamicTable = (PVOID) 1; return 0; } VOID WINAPI FakeRtlGrowFunctionTable (PVOID DynamicTable, ULONG NewEntryCount) { } VOID WINAPI FakeRtlDeleteGrowableFunctionTable (PVOID DynamicTable) {} @@ -158,7 +158,7 @@ UnwindInfoTable::UnwindInfoTable(ULONG_PTR rangeStart, ULONG_PTR rangeEnd, ULONG iRangeStart = rangeStart; iRangeEnd = rangeEnd; hHandle = NULL; - pTable = new RUNTIME_FUNCTION[cTableMaxCount]; + pTable = new T_RUNTIME_FUNCTION[cTableMaxCount]; } /****************************************************************************/ @@ -221,7 +221,7 @@ void UnwindInfoTable::UnRegister() // Add 'data' to the linked list whose head is pointed at by 'unwindInfoPtr' // /* static */ -void UnwindInfoTable::AddToUnwindInfoTable(UnwindInfoTable** unwindInfoPtr, RUNTIME_FUNCTION* data, +void UnwindInfoTable::AddToUnwindInfoTable(UnwindInfoTable** unwindInfoPtr, PT_RUNTIME_FUNCTION data, TADDR rangeStart, TADDR rangeEnd) { CONTRACTL @@ -377,7 +377,7 @@ void UnwindInfoTable::AddToUnwindInfoTable(UnwindInfoTable** unwindInfoPtr, RUNT // Publish the stack unwind data 'data' which is relative 'baseAddress' // to the operating system in a way ETW stack tracing can use. -/* static */ void UnwindInfoTable::PublishUnwindInfoForMethod(TADDR baseAddress, RUNTIME_FUNCTION* unwindInfo, int unwindInfoCount) +/* static */ void UnwindInfoTable::PublishUnwindInfoForMethod(TADDR baseAddress, PT_RUNTIME_FUNCTION unwindInfo, int unwindInfoCount) { STANDARD_VM_CONTRACT; if (!s_publishingActive) @@ -2139,16 +2139,16 @@ void CodeHeapRequestInfo::Init() #ifdef WIN64EXCEPTIONS #ifdef _WIN64 -extern "C" PRUNTIME_FUNCTION GetRuntimeFunctionCallback(IN ULONG64 ControlPc, +extern "C" PT_RUNTIME_FUNCTION GetRuntimeFunctionCallback(IN ULONG64 ControlPc, IN PVOID Context) #else -extern "C" PRUNTIME_FUNCTION GetRuntimeFunctionCallback(IN ULONG ControlPc, +extern "C" PT_RUNTIME_FUNCTION GetRuntimeFunctionCallback(IN ULONG ControlPc, IN PVOID Context) #endif { WRAPPER_NO_CONTRACT; - PRUNTIME_FUNCTION prf = NULL; + PT_RUNTIME_FUNCTION prf = NULL; // We must preserve this so that GCStress=4 eh processing doesnt kill last error. BEGIN_PRESERVE_LAST_ERROR; @@ -2492,7 +2492,7 @@ CodeHeader* EEJitManager::allocCode(MethodDesc* pMD, size_t blockSize, CorJitAll SIZE_T totalSize = blockSize; #if defined(USE_INDIRECT_CODEHEADER) - SIZE_T realHeaderSize = offsetof(RealCodeHeader, unwindInfos[0]) + (sizeof(RUNTIME_FUNCTION) * nUnwindInfos); + SIZE_T realHeaderSize = offsetof(RealCodeHeader, unwindInfos[0]) + (sizeof(T_RUNTIME_FUNCTION) * nUnwindInfos); // if this is a LCG method then we will be allocating the RealCodeHeader // following the code so that the code block can be removed easily by @@ -3913,13 +3913,13 @@ void GetUnmanagedStackWalkInfo(IN ULONG64 ControlPc, T_RUNTIME_FUNCTION functionEntry; DWORD dwLow = 0; - DWORD dwHigh = cbSize / sizeof(RUNTIME_FUNCTION); + DWORD dwHigh = cbSize / sizeof(T_RUNTIME_FUNCTION); DWORD dwMid = 0; while (dwLow <= dwHigh) { dwMid = (dwLow + dwHigh) >> 1; - taFuncEntry = pExceptionDir + dwMid * sizeof(RUNTIME_FUNCTION); + taFuncEntry = pExceptionDir + dwMid * sizeof(T_RUNTIME_FUNCTION); hr = DacReadAll(taFuncEntry, &functionEntry, sizeof(functionEntry), false); if (FAILED(hr)) { @@ -5688,7 +5688,7 @@ static void EnumRuntimeFunctionEntriesToFindEntry(PTR_RUNTIME_FUNCTION pRtf, PTR IMAGE_DATA_DIRECTORY * pProgramExceptionsDirectory = pNativeLayout->GetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_EXCEPTION); if (!pProgramExceptionsDirectory || (pProgramExceptionsDirectory->Size == 0) || - (pProgramExceptionsDirectory->Size % sizeof(RUNTIME_FUNCTION) != 0)) + (pProgramExceptionsDirectory->Size % sizeof(T_RUNTIME_FUNCTION) != 0)) { // Program exceptions directory malformatted return; @@ -5698,7 +5698,7 @@ static void EnumRuntimeFunctionEntriesToFindEntry(PTR_RUNTIME_FUNCTION pRtf, PTR PTR_RUNTIME_FUNCTION firstFunctionEntry(moduleBase + pProgramExceptionsDirectory->VirtualAddress); if (pRtf < firstFunctionEntry || - ((dac_cast<TADDR>(pRtf) - dac_cast<TADDR>(firstFunctionEntry)) % sizeof(RUNTIME_FUNCTION) != 0)) + ((dac_cast<TADDR>(pRtf) - dac_cast<TADDR>(firstFunctionEntry)) % sizeof(T_RUNTIME_FUNCTION) != 0)) { // Program exceptions directory malformatted return; @@ -5717,7 +5717,7 @@ static void EnumRuntimeFunctionEntriesToFindEntry(PTR_RUNTIME_FUNCTION pRtf, PTR #endif // defined(_MSC_VER) ULONG low = 0; // index in the function entry table of low end of search range - ULONG high = (pProgramExceptionsDirectory->Size)/sizeof(RUNTIME_FUNCTION) - 1; // index of high end of search range + ULONG high = (pProgramExceptionsDirectory->Size)/sizeof(T_RUNTIME_FUNCTION) - 1; // index of high end of search range ULONG mid = (low + high) /2; // index of entry to be compared if (indexToLocate > high) diff --git a/src/vm/codeman.h b/src/vm/codeman.h index 3f10aba74c..dbe990e9ab 100644 --- a/src/vm/codeman.h +++ b/src/vm/codeman.h @@ -141,7 +141,7 @@ public: #ifdef WIN64EXCEPTIONS DWORD nUnwindInfos; - RUNTIME_FUNCTION unwindInfos[0]; + T_RUNTIME_FUNCTION unwindInfos[0]; #endif // WIN64EXCEPTIONS public: @@ -304,7 +304,7 @@ public: SUPPORTS_DAC; _ASSERTE(iUnwindInfo < GetNumberOfUnwindInfos()); return dac_cast<PTR_RUNTIME_FUNCTION>( - PTR_TO_MEMBER_TADDR(RealCodeHeader, pRealCodeHeader, unwindInfos) + iUnwindInfo * sizeof(RUNTIME_FUNCTION)); + PTR_TO_MEMBER_TADDR(RealCodeHeader, pRealCodeHeader, unwindInfos) + iUnwindInfo * sizeof(T_RUNTIME_FUNCTION)); } #endif // WIN64EXCEPTIONS @@ -531,12 +531,12 @@ public: // All public functions are thread-safe. // These are wrapper functions over the UnwindInfoTable functions that are specific to JIT compile code - static void PublishUnwindInfoForMethod(TADDR baseAddress, RUNTIME_FUNCTION* unwindInfo, int unwindInfoCount); + static void PublishUnwindInfoForMethod(TADDR baseAddress, T_RUNTIME_FUNCTION* unwindInfo, int unwindInfoCount); static void UnpublishUnwindInfoForMethod(TADDR entryPoint); // These are lower level functions that assume you have found the list of UnwindInfoTable entries // These are used by the stublinker and the high-level method functions above - static void AddToUnwindInfoTable(UnwindInfoTable** unwindInfoPtr, RUNTIME_FUNCTION* data, TADDR rangeStart, TADDR rangeEnd); + static void AddToUnwindInfoTable(UnwindInfoTable** unwindInfoPtr, T_RUNTIME_FUNCTION* data, TADDR rangeStart, TADDR rangeEnd); static void RemoveFromUnwindInfoTable(UnwindInfoTable** unwindInfoPtr, TADDR baseAddress, TADDR entryPoint); // By default this publishing is off, this routine turns it on (and optionally publishes existing methods) @@ -556,7 +556,7 @@ private: PVOID hHandle; // OS handle for a published RUNTIME_FUNCTION table ULONG_PTR iRangeStart; // Start of memory described by this table ULONG_PTR iRangeEnd; // End of memory described by this table - RUNTIME_FUNCTION* pTable; // The actual list of method unwind info, sorted by address + T_RUNTIME_FUNCTION* pTable; // The actual list of method unwind info, sorted by address ULONG cTableCurCount; ULONG cTableMaxCount; int cDeletedEntries; // Number of slots we removed. diff --git a/src/vm/exceptionhandling.cpp b/src/vm/exceptionhandling.cpp index 35d95120dd..14ba4e4b42 100644 --- a/src/vm/exceptionhandling.cpp +++ b/src/vm/exceptionhandling.cpp @@ -5350,7 +5350,7 @@ void FixupDispatcherContext(DISPATCHER_CONTEXT* pDispatcherContext, CONTEXT* pCo #endif // _TARGET_ARM_ || _TARGET_ARM64_ - INDEBUG(pDispatcherContext->FunctionEntry = (PRUNTIME_FUNCTION)INVALID_POINTER_CD); + INDEBUG(pDispatcherContext->FunctionEntry = (PT_RUNTIME_FUNCTION)INVALID_POINTER_CD); INDEBUG(pDispatcherContext->ImageBase = INVALID_POINTER_CD); pDispatcherContext->FunctionEntry = RtlLookupFunctionEntry(pDispatcherContext->ControlPc, @@ -5358,7 +5358,7 @@ void FixupDispatcherContext(DISPATCHER_CONTEXT* pDispatcherContext, CONTEXT* pCo NULL ); - _ASSERTE(((PRUNTIME_FUNCTION)INVALID_POINTER_CD) != pDispatcherContext->FunctionEntry); + _ASSERTE(((PT_RUNTIME_FUNCTION)INVALID_POINTER_CD) != pDispatcherContext->FunctionEntry); _ASSERTE(INVALID_POINTER_CD != pDispatcherContext->ImageBase); // diff --git a/src/vm/i386/stublinkerx86.cpp b/src/vm/i386/stublinkerx86.cpp index 362edb542c..2d9e01f69f 100644 --- a/src/vm/i386/stublinkerx86.cpp +++ b/src/vm/i386/stublinkerx86.cpp @@ -3638,7 +3638,7 @@ extern "C" VOID __cdecl DebugCheckStubUnwindInfoWorker (CONTEXT *pStubContext) LOG((LF_STUBS, LL_INFO1000000, "pc %p, sp %p\n", ControlPc, GetSP(&ctx))); ULONG64 ImageBase; - RUNTIME_FUNCTION *pFunctionEntry = RtlLookupFunctionEntry( + T_RUNTIME_FUNCTION *pFunctionEntry = RtlLookupFunctionEntry( ControlPc, &ImageBase, NULL); diff --git a/src/vm/jithelpers.cpp b/src/vm/jithelpers.cpp index 95ba2b4ae2..aa99f06ab9 100644 --- a/src/vm/jithelpers.cpp +++ b/src/vm/jithelpers.cpp @@ -6676,8 +6676,8 @@ void F_CALL_VA_CONV JIT_TailCall(PCODE copyArgs, PCODE target, ...) CONTEXT ctx; // Unwind back to our caller in managed code - static PRUNTIME_FUNCTION my_pdata; - static ULONG_PTR my_imagebase; + static PT_RUNTIME_FUNCTION my_pdata; + static ULONG_PTR my_imagebase; ctx.ContextFlags = CONTEXT_ALL; RtlCaptureContext(&ctx); @@ -7035,7 +7035,7 @@ void InitJitHelperLogging() hlpFuncCount->count = 0; #ifdef _TARGET_AMD64_ ULONGLONG uImageBase; - PRUNTIME_FUNCTION pFunctionEntry; + PT_RUNTIME_FUNCTION pFunctionEntry; pFunctionEntry = RtlLookupFunctionEntry((ULONGLONG)hlpFunc->pfnHelper, &uImageBase, NULL); if (pFunctionEntry != NULL) @@ -7080,7 +7080,7 @@ void InitJitHelperLogging() #ifdef _TARGET_AMD64_ ULONGLONG uImageBase; - PRUNTIME_FUNCTION pFunctionEntry; + PT_RUNTIME_FUNCTION pFunctionEntry; pFunctionEntry = RtlLookupFunctionEntry((ULONGLONG)hlpFunc->pfnHelper, &uImageBase, NULL); if (pFunctionEntry != NULL) diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp index 3247ccb100..46542482ba 100644 --- a/src/vm/jitinterface.cpp +++ b/src/vm/jitinterface.cpp @@ -6092,6 +6092,17 @@ void CEEInfo::getReadyToRunHelper( } /***********************************************************************/ +void CEEInfo::getReadyToRunDelegateCtorHelper( + CORINFO_RESOLVED_TOKEN * pTargetMethod, + CORINFO_CLASS_HANDLE delegateType, + CORINFO_CONST_LOOKUP * pLookup + ) +{ + LIMITED_METHOD_CONTRACT; + UNREACHABLE(); // only called during NGen +} + +/***********************************************************************/ // see code:Nullable#NullableVerification CORINFO_CLASS_HANDLE CEEInfo::getTypeForBox(CORINFO_CLASS_HANDLE cls) @@ -10467,7 +10478,7 @@ void CEEJitInfo::allocUnwindInfo ( _ASSERTE(m_usedUnwindInfos > 0); } - PRUNTIME_FUNCTION pRuntimeFunction = m_CodeHeader->GetUnwindInfo(m_usedUnwindInfos); + PT_RUNTIME_FUNCTION pRuntimeFunction = m_CodeHeader->GetUnwindInfo(m_usedUnwindInfos); m_usedUnwindInfos++; // Make sure that the RUNTIME_FUNCTION is aligned on a DWORD sized boundary @@ -10552,7 +10563,7 @@ void CEEJitInfo::allocUnwindInfo ( for (ULONG iUnwindInfo = 0; iUnwindInfo < m_usedUnwindInfos - 1; iUnwindInfo++) { - PRUNTIME_FUNCTION pOtherFunction = m_CodeHeader->GetUnwindInfo(iUnwindInfo); + PT_RUNTIME_FUNCTION pOtherFunction = m_CodeHeader->GetUnwindInfo(iUnwindInfo); _ASSERTE(( RUNTIME_FUNCTION__BeginAddress(pOtherFunction) >= RUNTIME_FUNCTION__EndAddress(pRuntimeFunction, baseAddress) || RUNTIME_FUNCTION__EndAddress(pOtherFunction, baseAddress) <= RUNTIME_FUNCTION__BeginAddress(pRuntimeFunction))); } @@ -13671,7 +13682,7 @@ LPVOID EECodeInfo::findNextFunclet (LPVOID pvFuncletStart, SIZE_T while (cbCode > 0) { - PRUNTIME_FUNCTION pFunctionEntry; + PT_RUNTIME_FUNCTION pFunctionEntry; ULONGLONG uImageBase; #ifdef FEATURE_PAL EECodeInfo codeInfo; @@ -13683,7 +13694,7 @@ LPVOID EECodeInfo::findNextFunclet (LPVOID pvFuncletStart, SIZE_T // This is GCStress debug only - use the slow OS APIs to enumerate funclets // - pFunctionEntry = (PRUNTIME_FUNCTION) RtlLookupFunctionEntry((ULONGLONG)pvFuncletStart, + pFunctionEntry = (PT_RUNTIME_FUNCTION) RtlLookupFunctionEntry((ULONGLONG)pvFuncletStart, &uImageBase AMD64_ARG(NULL) ); diff --git a/src/vm/jitinterface.h b/src/vm/jitinterface.h index 215ceda4b2..00edc6e212 100644 --- a/src/vm/jitinterface.h +++ b/src/vm/jitinterface.h @@ -538,6 +538,12 @@ public: CORINFO_CONST_LOOKUP * pLookup ); + void getReadyToRunDelegateCtorHelper( + CORINFO_RESOLVED_TOKEN * pTargetMethod, + CORINFO_CLASS_HANDLE delegateType, + CORINFO_CONST_LOOKUP * pLookup + ); + CorInfoInitClassResult initClass( CORINFO_FIELD_HANDLE field, CORINFO_METHOD_HANDLE method, diff --git a/src/vm/nativeformatreader.h b/src/vm/nativeformatreader.h index cfebb498ca..a410884626 100644 --- a/src/vm/nativeformatreader.h +++ b/src/vm/nativeformatreader.h @@ -44,7 +44,11 @@ namespace NativeFormat void ThrowBadImageFormatException() { _ASSERTE(false); - ThrowHR(COR_E_BADIMAGEFORMAT); + +#ifndef DACCESS_COMPILE + // Failfast instead of throwing, to avoid violating NOTHROW contracts of callers + EEPOLICY_HANDLE_FATAL_ERROR(COR_E_BADIMAGEFORMAT); +#endif } uint EnsureOffsetInRange(uint offset, uint lookAhead) diff --git a/src/vm/readytoruninfo.cpp b/src/vm/readytoruninfo.cpp index d00db7150f..158a23370f 100644 --- a/src/vm/readytoruninfo.cpp +++ b/src/vm/readytoruninfo.cpp @@ -84,7 +84,7 @@ BOOL ReadyToRunInfo::TryLookupTypeTokenFromName(NameHandle *pName, mdToken * pFo { GC_NOTRIGGER; NOTHROW; - SO_TOLERANT; + SO_INTOLERANT; SUPPORTS_DAC; PRECONDITION(!m_availableTypesHashtable.IsNull()); } @@ -429,8 +429,8 @@ ReadyToRunInfo::ReadyToRunInfo(Module * pModule, PEImageLayout * pLayout, READYT IMAGE_DATA_DIRECTORY * pRuntimeFunctionsDir = FindSection(READYTORUN_SECTION_RUNTIME_FUNCTIONS); if (pRuntimeFunctionsDir != NULL) { - m_pRuntimeFunctions = (RUNTIME_FUNCTION *)pLayout->GetDirectoryData(pRuntimeFunctionsDir); - m_nRuntimeFunctions = pRuntimeFunctionsDir->Size / sizeof(RUNTIME_FUNCTION); + m_pRuntimeFunctions = (T_RUNTIME_FUNCTION *)pLayout->GetDirectoryData(pRuntimeFunctionsDir); + m_nRuntimeFunctions = pRuntimeFunctionsDir->Size / sizeof(T_RUNTIME_FUNCTION); } else { diff --git a/src/vm/rtlfunctions.h b/src/vm/rtlfunctions.h index d08cd75699..9d1d46b6f8 100644 --- a/src/vm/rtlfunctions.h +++ b/src/vm/rtlfunctions.h @@ -20,7 +20,7 @@ enum EEDynamicFunctionTableType }; // Used by OutOfProcessFunctionTableCallback in DLLS\mscordbg\DebugSupport.cpp -// to figure out how to parse a dunamic function table that was registered +// to figure out how to parse a dynamic function table that was registered // with a callback. inline EEDynamicFunctionTableType IdentifyDynamicFunctionTableTypeFromContext (PVOID pvContext) @@ -65,7 +65,7 @@ inline VOID DeleteEEFunctionTable( PVOID pvTableID) { - RtlDeleteFunctionTable((PRUNTIME_FUNCTION)((ULONG64)pvTableID | 3)); + RtlDeleteFunctionTable((PT_RUNTIME_FUNCTION)((ULONG64)pvTableID | 3)); } #else // WIN64EXCEPTIONS && !DACCESS_COMPILE && !CROSSGEN_COMPILE && !FEATURE_PAL diff --git a/src/vm/stackwalk.cpp b/src/vm/stackwalk.cpp index 2250fd517a..3c2dfd7f84 100644 --- a/src/vm/stackwalk.cpp +++ b/src/vm/stackwalk.cpp @@ -596,7 +596,7 @@ PCODE Thread::VirtualUnwindCallFrame(T_CONTEXT* pContext, #if !defined(DACCESS_COMPILE) UINT_PTR uImageBase; - PRUNTIME_FUNCTION pFunctionEntry; + PT_RUNTIME_FUNCTION pFunctionEntry; if (pCodeInfo == NULL) { @@ -623,7 +623,7 @@ PCODE Thread::VirtualUnwindCallFrame(T_CONTEXT* pContext, #if defined(_DEBUG) && !defined(FEATURE_PAL) UINT_PTR uImageBaseFromOS; - PRUNTIME_FUNCTION pFunctionEntryFromOS; + PT_RUNTIME_FUNCTION pFunctionEntryFromOS; pFunctionEntryFromOS = RtlLookupFunctionEntry(uControlPc, ARM_ONLY((DWORD*))(&uImageBaseFromOS), @@ -679,7 +679,7 @@ PCODE Thread::VirtualUnwindLeafCallFrame(T_CONTEXT* pContext) #if defined(_DEBUG) && !defined(FEATURE_PAL) UINT_PTR uImageBase; - PRUNTIME_FUNCTION pFunctionEntry = RtlLookupFunctionEntry((UINT_PTR)GetIP(pContext), + PT_RUNTIME_FUNCTION pFunctionEntry = RtlLookupFunctionEntry((UINT_PTR)GetIP(pContext), ARM_ONLY((DWORD*))(&uImageBase), NULL); @@ -708,7 +708,7 @@ PCODE Thread::VirtualUnwindLeafCallFrame(T_CONTEXT* pContext) // static PCODE Thread::VirtualUnwindNonLeafCallFrame(T_CONTEXT* pContext, KNONVOLATILE_CONTEXT_POINTERS* pContextPointers, - PRUNTIME_FUNCTION pFunctionEntry, UINT_PTR uImageBase) + PT_RUNTIME_FUNCTION pFunctionEntry, UINT_PTR uImageBase) { CONTRACTL { diff --git a/src/vm/stublink.cpp b/src/vm/stublink.cpp index 92b4a15209..d1833260c5 100644 --- a/src/vm/stublink.cpp +++ b/src/vm/stublink.cpp @@ -1476,7 +1476,7 @@ bool StubLinker::EmitUnwindInfo(Stub* pStub, int globalsize) // // Fill in the RUNTIME_FUNCTION struct for this prologue. // - RUNTIME_FUNCTION *pCurFunction = &pUnwindInfoHeader->FunctionEntry; + PT_RUNTIME_FUNCTION pCurFunction = &pUnwindInfoHeader->FunctionEntry; _ASSERTE(IS_ALIGNED(pCurFunction, sizeof(ULONG))); S_UINT32 sBeginAddress = S_BYTEPTR(pCode) - S_BYTEPTR(pbBaseAddress); @@ -1499,7 +1499,7 @@ bool StubLinker::EmitUnwindInfo(Stub* pStub, int globalsize) // UNWIND_INFO *pUnwindInfo = &pUnwindInfoHeader->UnwindInfo; - RUNTIME_FUNCTION *pCurFunction = &pUnwindInfoHeader->FunctionEntry; + PT_RUNTIME_FUNCTION pCurFunction = &pUnwindInfoHeader->FunctionEntry; _ASSERTE(IS_ALIGNED(pCurFunction, sizeof(ULONG))); S_UINT32 sBeginAddress = S_BYTEPTR(pCode) - S_BYTEPTR(pbBaseAddress); diff --git a/src/vm/stublink.h b/src/vm/stublink.h index 8df3499b68..d7f0034587 100644 --- a/src/vm/stublink.h +++ b/src/vm/stublink.h @@ -349,7 +349,7 @@ protected: { if (m_nUnwindSlots == 0) return 0; - return sizeof(RUNTIME_FUNCTION) + offsetof(UNWIND_INFO, UnwindCode) + m_nUnwindSlots * sizeof(UNWIND_CODE); + return sizeof(T_RUNTIME_FUNCTION) + offsetof(UNWIND_INFO, UnwindCode) + m_nUnwindSlots * sizeof(UNWIND_CODE); } #endif // _TARGET_AMD64_ @@ -359,7 +359,7 @@ protected: // epilog. private: // Reserve fixed size block that's big enough to fit any unwind info we can have - static const int c_nUnwindInfoSize = sizeof(RUNTIME_FUNCTION) + sizeof(DWORD) + MAX_UNWIND_CODE_WORDS *4; + static const int c_nUnwindInfoSize = sizeof(T_RUNTIME_FUNCTION) + sizeof(DWORD) + MAX_UNWIND_CODE_WORDS *4; // // Returns total UnwindInfoSize, including RUNTIME_FUNCTION entry @@ -377,7 +377,7 @@ private: private: // Reserve fixed size block that's big enough to fit any unwind info we can have - static const int c_nUnwindInfoSize = sizeof(RUNTIME_FUNCTION) + sizeof(DWORD) + MAX_UNWIND_CODE_WORDS *4; + static const int c_nUnwindInfoSize = sizeof(T_RUNTIME_FUNCTION) + sizeof(DWORD) + MAX_UNWIND_CODE_WORDS *4; UINT UnwindInfoSize(UINT codeSize) { if (!m_fProlog) return 0; diff --git a/src/vm/threads.h b/src/vm/threads.h index 9cf309d70a..26477af2fc 100644 --- a/src/vm/threads.h +++ b/src/vm/threads.h @@ -3625,7 +3625,7 @@ public: static UINT_PTR VirtualUnwindCallFrame(PREGDISPLAY pRD, EECodeInfo * pCodeInfo = NULL); static PCODE VirtualUnwindLeafCallFrame(T_CONTEXT* pContext); static PCODE VirtualUnwindNonLeafCallFrame(T_CONTEXT* pContext, T_KNONVOLATILE_CONTEXT_POINTERS* pContextPointers = NULL, - PRUNTIME_FUNCTION pFunctionEntry = NULL, UINT_PTR uImageBase = NULL); + PT_RUNTIME_FUNCTION pFunctionEntry = NULL, UINT_PTR uImageBase = NULL); static UINT_PTR VirtualUnwindToFirstManagedCallFrame(T_CONTEXT* pContext); #endif // WIN64EXCEPTIONS diff --git a/src/vm/win32threadpool.cpp b/src/vm/win32threadpool.cpp index af7b26c1e2..fc25f4e7b9 100644 --- a/src/vm/win32threadpool.cpp +++ b/src/vm/win32threadpool.cpp @@ -305,11 +305,13 @@ DWORD GetDefaultMaxLimitWorkerThreads(DWORD minLimit) DWORD GetForceMinWorkerThreadsValue() { + WRAPPER_NO_CONTRACT; return Configuration::GetKnobDWORDValue(W("System.Threading.ThreadPool.MinThreads"), CLRConfig::INTERNAL_ThreadPool_ForceMinWorkerThreads); } DWORD GetForceMaxWorkerThreadsValue() { + WRAPPER_NO_CONTRACT; return Configuration::GetKnobDWORDValue(W("System.Threading.ThreadPool.MaxThreads"), CLRConfig::INTERNAL_ThreadPool_ForceMaxWorkerThreads); } diff --git a/src/zap/zapcode.cpp b/src/zap/zapcode.cpp index 2e7f21590a..ca1c023f20 100644 --- a/src/zap/zapcode.cpp +++ b/src/zap/zapcode.cpp @@ -1291,7 +1291,7 @@ ZapGCInfo * ZapGCInfoTable::GetGCInfo(PVOID pBlob, SIZE_T cbBlob) void ZapUnwindInfo::Save(ZapWriter * pZapWriter) { - RUNTIME_FUNCTION runtimeFunction; + T_RUNTIME_FUNCTION runtimeFunction; #if defined(_TARGET_ARM_) RUNTIME_FUNCTION__SetBeginAddress(&runtimeFunction, GetStartAddress()); diff --git a/src/zap/zapcode.h b/src/zap/zapcode.h index d68f9028c1..ed8cc2d807 100644 --- a/src/zap/zapcode.h +++ b/src/zap/zapcode.h @@ -427,7 +427,7 @@ public: virtual DWORD GetSize() { - return sizeof(RUNTIME_FUNCTION); + return sizeof(T_RUNTIME_FUNCTION); } virtual ZapNodeType GetType() diff --git a/src/zap/zapimport.cpp b/src/zap/zapimport.cpp index c1947a96f0..4e7b151d74 100644 --- a/src/zap/zapimport.cpp +++ b/src/zap/zapimport.cpp @@ -1791,13 +1791,20 @@ ZapImport * ZapImportTable::GetDynamicHelperCell(CORCOMPILE_FIXUP_BLOB_KIND kind return pImport; } -ZapImport * ZapImportTable::GetDynamicHelperCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken) +ZapImport * ZapImportTable::GetDynamicHelperCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, + CORINFO_CLASS_HANDLE delegateType /*=NULL*/) { SigBuilder sigBuilder; EncodeMethod((CORCOMPILE_FIXUP_BLOB_KIND)(kind & ~CORINFO_HELP_READYTORUN_ATYPICAL_CALLSITE), handle, &sigBuilder, pResolvedToken); + if (delegateType != NULL) + { + _ASSERTE((CORCOMPILE_FIXUP_BLOB_KIND)(kind & ~CORINFO_HELP_READYTORUN_ATYPICAL_CALLSITE) == ENCODE_DELEGATE_CTOR); + GetCompileInfo()->EncodeClass(m_pImage->GetModuleHandle(), delegateType, &sigBuilder, NULL, NULL); + } + return GetImportForSignature<ZapDynamicHelperCell, ZapNodeType_DynamicHelperCell>((void *)kind, &sigBuilder); } diff --git a/src/zap/zapimport.h b/src/zap/zapimport.h index 9d55e03531..9aa5e95f27 100644 --- a/src/zap/zapimport.h +++ b/src/zap/zapimport.h @@ -432,7 +432,8 @@ public: ZapImport * GetExternalMethodCell(CORINFO_METHOD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken); ZapImport * GetDynamicHelperCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_CLASS_HANDLE handle); - ZapImport * GetDynamicHelperCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken); + ZapImport * GetDynamicHelperCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, + CORINFO_CLASS_HANDLE delegateType = NULL); ZapImport * GetDynamicHelperCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_FIELD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken); #ifdef FEATURE_READYTORUN_COMPILER diff --git a/src/zap/zapinfo.cpp b/src/zap/zapinfo.cpp index c8a08a3cc6..cf8e9b7c7e 100644 --- a/src/zap/zapinfo.cpp +++ b/src/zap/zapinfo.cpp @@ -2667,7 +2667,7 @@ CORINFO_METHOD_HANDLE ZapInfo::GetDelegateCtor(CORINFO_METHOD_HANDLE methHnd, CORINFO_METHOD_HANDLE targetMethodHnd, DelegateCtorArgs * pCtorData) { - // For ReadyToRun, this optimization is done via ZapInfo::getReadyToRunHelper + // For ReadyToRun, this optimization is done via ZapInfo::getReadyToRunDelegateCtorHelper if (IsReadyToRunCompilation()) return methHnd; @@ -3410,11 +3410,6 @@ void ZapInfo::getReadyToRunHelper( } break; - case CORINFO_HELP_READYTORUN_DELEGATE_CTOR: - pImport = m_pImage->GetImportTable()->GetDynamicHelperCell( - (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_DELEGATE_CTOR | fAtypicalCallsite), pResolvedToken->hMethod, pResolvedToken); - break; - default: _ASSERTE(false); ThrowHR(E_NOTIMPL); @@ -3425,6 +3420,21 @@ void ZapInfo::getReadyToRunHelper( #endif } +void ZapInfo::getReadyToRunDelegateCtorHelper( + CORINFO_RESOLVED_TOKEN * pTargetMethod, + CORINFO_CLASS_HANDLE delegateType, + CORINFO_CONST_LOOKUP * pLookup + ) +{ +#ifdef FEATURE_READYTORUN_COMPILER + _ASSERTE(IsReadyToRunCompilation()); + + pLookup->accessType = IAT_PVALUE; + pLookup->addr = m_pImage->GetImportTable()->GetDynamicHelperCell( + (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_DELEGATE_CTOR), pTargetMethod->hMethod, pTargetMethod, delegateType); +#endif +} + // // ICorModuleInfo diff --git a/src/zap/zapinfo.h b/src/zap/zapinfo.h index 83528e9e7b..5fe3dcb76e 100644 --- a/src/zap/zapinfo.h +++ b/src/zap/zapinfo.h @@ -550,6 +550,12 @@ public: CORINFO_CONST_LOOKUP * pLookup ); + void getReadyToRunDelegateCtorHelper( + CORINFO_RESOLVED_TOKEN * pTargetMethod, + CORINFO_CLASS_HANDLE delegateType, + CORINFO_CONST_LOOKUP * pLookup + ); + CorInfoInitClassResult initClass( CORINFO_FIELD_HANDLE field, CORINFO_METHOD_HANDLE method, diff --git a/tests/src/readytorun/main.cs b/tests/src/readytorun/main.cs index 427ca42340..70157bc278 100644 --- a/tests/src/readytorun/main.cs +++ b/tests/src/readytorun/main.cs @@ -40,6 +40,15 @@ class InheritingFromGrowingBase : GrowingBase public int x; } + +static class OpenClosedDelegateExtension +{ + public static string OpenClosedDelegateTarget(this string x, string foo) + { + return x + ", " + foo; + } +} + class Program { static void TestVirtualMethodCalls() @@ -335,6 +344,18 @@ class Program Assert.AreEqual(o.ChildByte, (byte)67); } + static void TestOpenClosedDelegate() + { + // This test is verifying the the fixups for open vs. closed delegate created against the same target + // method are encoded correctly. + + Func<string, string, object> idOpen = OpenClosedDelegateExtension.OpenClosedDelegateTarget; + Assert.AreEqual(idOpen("World", "foo"), "World, foo"); + + Func<string, object> idClosed = "World".OpenClosedDelegateTarget; + Assert.AreEqual(idClosed("hey"), "World, hey"); + } + static void RunAllTests() { TestVirtualMethodCalls(); @@ -380,6 +401,8 @@ class Program TestCastClassCSE(); TestRangeCheckElimination(); + + TestOpenClosedDelegate(); } static int Main() |