From 435a69a9aca037f348a09e00dffef8a0888682a7 Mon Sep 17 00:00:00 2001 From: Noah Falk Date: Thu, 7 Jun 2018 12:53:08 -0700 Subject: [PATCH] Allow ILCodeVersion to fallback to default IL (#18322) For compat with profilers that used our APIs in unexpected ways we can allow the ILCodeVersion to fallback to the default IL code when no IL was explicitly given. --- src/debug/daccess/dacdbiimpl.cpp | 10 +++++----- src/vm/codeversion.cpp | 31 +++++++++++++++++++++++-------- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/debug/daccess/dacdbiimpl.cpp b/src/debug/daccess/dacdbiimpl.cpp index a85cfa9f32c9..e5cc45beb79c 100644 --- a/src/debug/daccess/dacdbiimpl.cpp +++ b/src/debug/daccess/dacdbiimpl.cpp @@ -7249,11 +7249,11 @@ HRESULT DacDbiInterfaceImpl::GetILCodeVersionNodeData(VMPTR_ILCodeVersionNode vm { DD_ENTER_MAY_THROW; #ifdef FEATURE_REJIT - ILCodeVersionNode* pILCodeVersionNode = vmILCodeVersionNode.GetDacPtr(); - pData->m_state = pILCodeVersionNode->GetRejitState(); - pData->m_pbIL = PTR_TO_CORDB_ADDRESS(dac_cast(pILCodeVersionNode->GetIL())); - pData->m_dwCodegenFlags = pILCodeVersionNode->GetJitFlags(); - const InstrumentedILOffsetMapping* pMapping = pILCodeVersionNode->GetInstrumentedILMap(); + ILCodeVersion ilCode(vmILCodeVersionNode.GetDacPtr()); + pData->m_state = ilCode.GetRejitState(); + pData->m_pbIL = PTR_TO_CORDB_ADDRESS(dac_cast(ilCode.GetIL())); + pData->m_dwCodegenFlags = ilCode.GetJitFlags(); + const InstrumentedILOffsetMapping* pMapping = ilCode.GetInstrumentedILMap(); if (pMapping) { pData->m_cInstrumentedMapEntries = (ULONG)pMapping->GetCount(); diff --git a/src/vm/codeversion.cpp b/src/vm/codeversion.cpp index 7406d1910985..cf756e14f9d9 100644 --- a/src/vm/codeversion.cpp +++ b/src/vm/codeversion.cpp @@ -773,23 +773,38 @@ PTR_COR_ILMETHOD ILCodeVersion::GetIL() const } CONTRACTL_END + PTR_COR_ILMETHOD pIL = NULL; if (m_storageKind == StorageKind::Explicit) { - return AsNode()->GetIL(); + pIL = AsNode()->GetIL(); } - else + + // For the default code version we always fetch the globally stored default IL for a method + // + // In the non-default code version we assume NULL is the equivalent of explicitly requesting to + // re-use the default IL. Ideally there would be no reason to create a new version that re-uses + // the default IL (just use the default code version for that) but we do it here for compat. We've + // got some profilers that use ReJIT to create a new code version and then instead of calling + // ICorProfilerFunctionControl::SetILFunctionBody they call ICorProfilerInfo::SetILFunctionBody. + // This mutates the default IL so that it is now correct for their new code version. Of course this + // also overwrote the previous default IL so now the default code version GetIL() is out of sync + // with the jitted code. In the majority of cases we never re-read the IL after the initial + // jitting so this issue goes unnoticed. + // + // If changing the default IL after it is in use becomes more problematic in the future we would + // need to add enforcement that prevents profilers from using ICorProfilerInfo::SetILFunctionBody + // that way + coordinate with them because it is a breaking change for any profiler currently doing it. + if(pIL == NULL) { PTR_Module pModule = GetModule(); PTR_MethodDesc pMethodDesc = dac_cast(pModule->LookupMethodDef(GetMethodDef())); - if (pMethodDesc == NULL) + if (pMethodDesc != NULL) { - return NULL; - } - else - { - return dac_cast(pMethodDesc->GetILHeader(TRUE)); + pIL = dac_cast(pMethodDesc->GetILHeader(TRUE)); } } + + return pIL; } PTR_COR_ILMETHOD ILCodeVersion::GetILNoThrow() const