- So that `MethodDesc::GetNativeCode()` can retrieve the current native code entry point (instead of returning null as before), and code versioning can find a matching code version from the code start address
- Interface methods currently require having a precode, so the "method entry point" can't be used to directly store the native code entry point
- Reenabled a couple of default interface method tests under GCStress
- Other small cleanup
Fixes https://github.com/dotnet/coreclr/issues/25690
Commit migrated from https://github.com/dotnet/coreclr/commit/
98bf56a2cf19645563b41ab01f6972cbe83c9d44
// The DJI may already be populated in the cache, if so CreateInitAndAddJitInfo is a no-op and that is fine.
// CreateInitAndAddJitInfo takes a lock and checks the list again, which makes this thread-safe.
- CodeVersionManager::TableLockHolder lockHolder(fd->GetCodeVersionManager());
- CodeVersionManager *pCodeVersionManager = fd->GetCodeVersionManager();
- NativeCodeVersion nativeCodeVersion = pCodeVersionManager->GetNativeCodeVersion(fd, startAddr);
-
- // Some day we'll get EnC to use code versioning properly, but until then we'll get the right behavior treating all EnC versions as the default native code version.
- if (nativeCodeVersion.IsNull())
+ NativeCodeVersion nativeCodeVersion;
+ if (fd->IsVersionable())
+ {
+ CodeVersionManager::TableLockHolder lockHolder(fd->GetCodeVersionManager());
+ CodeVersionManager *pCodeVersionManager = fd->GetCodeVersionManager();
+ nativeCodeVersion = pCodeVersionManager->GetNativeCodeVersion(fd, startAddr);
+ if (nativeCodeVersion.IsNull())
+ {
+ return NULL;
+ }
+ }
+ else
{
+ // Some day we'll get EnC to use code versioning properly, but until then we'll get the right behavior treating all EnC versions as the default native code version.
nativeCodeVersion = NativeCodeVersion(fd);
}
#endif // HAVE_GCCOVER
NativeCodeVersion::NativeCodeVersion() :
- m_storageKind(StorageKind::Unknown)
+ m_storageKind(StorageKind::Unknown), m_pVersionNode(PTR_NULL)
{}
NativeCodeVersion::NativeCodeVersion(const NativeCodeVersion & rhs) :
ReJITID ilCodeId = 0;
NativeCodeVersion nativeCodeVersion;
#ifdef FEATURE_CODE_VERSIONING
- if (fGetCodeIds)
+ if (fGetCodeIds && pMD->IsVersionable())
{
CodeVersionManager *pCodeVersionManager = pMD->GetCodeVersionManager();
_ASSERTE(pCodeVersionManager->LockOwnedByCurrentThread());
return false;
}
- GCCoverageInfo *gcCover = codeInfo.GetNativeCodeVersion().GetGCCoverageInfo();
+ NativeCodeVersion nativeCodeVersion = codeInfo.GetNativeCodeVersion();
+ _ASSERTE(!nativeCodeVersion.IsNull());
+ GCCoverageInfo *gcCover = nativeCodeVersion.GetGCCoverageInfo();
if (gcCover == nullptr)
{
return false;
forceStack[1] = &pMD; // This is so I can see it fastchecked
forceStack[2] = &offset; // This is so I can see it fastchecked
- GCCoverageInfo* gcCover = codeInfo.GetNativeCodeVersion().GetGCCoverageInfo();
+ NativeCodeVersion nativeCodeVersion = codeInfo.GetNativeCodeVersion();
+ _ASSERTE(!nativeCodeVersion.IsNull());
+ GCCoverageInfo* gcCover = nativeCodeVersion.GetGCCoverageInfo();
forceStack[3] = &gcCover; // This is so I can see it fastchecked
if (gcCover == 0)
return(FALSE); // we aren't doing code gcCoverage on this function
}
#ifdef FEATURE_CODE_VERSIONING
- CodeVersionManager *pCodeVersionManager = pMD->GetCodeVersionManager();
- CodeVersionManager::TableLockHolder lockHolder(pCodeVersionManager);
- return pCodeVersionManager->GetNativeCodeVersion(pMD, PINSTRToPCODE(GetStartAddress()));
-#else
- return NativeCodeVersion(pMD);
+ if (pMD->IsVersionable())
+ {
+ CodeVersionManager *pCodeVersionManager = pMD->GetCodeVersionManager();
+ CodeVersionManager::TableLockHolder lockHolder(pCodeVersionManager);
+ return pCodeVersionManager->GetNativeCodeVersion(pMD, PINSTRToPCODE(GetStartAddress()));
+ }
#endif
+ return NativeCodeVersion(pMD);
}
#if defined(WIN64EXCEPTIONS)
{
WRAPPER_NO_CONTRACT;
SUPPORTS_DAC;
+ _ASSERTE(!IsDefaultInterfaceMethod() || HasNativeCodeSlot());
g_IBCLogger.LogMethodDescAccess(this);
_ASSERTE(IsIL());
- if ((IsInterface() && !IsStatic() && IsVirtual() && IsAbstract()) || IsWrapperStub() || ContainsGenericVariables() || IsAbstract())
+ if (IsWrapperStub() || ContainsGenericVariables() || IsAbstract())
{
return FALSE;
}
GC_NOTRIGGER;
} CONTRACTL_END;
+ _ASSERTE(!IsDefaultInterfaceMethod() || HasNativeCodeSlot());
+
if (HasNativeCodeSlot())
{
#ifdef _TARGET_ARM_
(TADDR&)value, (TADDR&)expected) == (TADDR&)expected;
}
- if (IsDefaultInterfaceMethod() && HasPrecode())
- {
- return GetPrecode()->SetTargetInterlocked(addr);
- }
-
_ASSERTE(pExpected == NULL);
return SetStableEntryPointInterlocked(addr);
}
}
#endif
+#ifdef FEATURE_DEFAULT_INTERFACES
+ if (IsInterface())
+ {
+ DWORD attrs = pMDMethod->GetDeclAttrs();
+ if (!IsMdStatic(attrs) && IsMdVirtual(attrs) && !IsMdAbstract(attrs))
+ {
+ // Default interface method. Since interface methods currently need to have a precode, the native code slot will be
+ // used to retrieve the native code entry point, instead of getting it from the precode, which is not reliable with
+ // debuggers setting breakpoints.
+ return TRUE;
+ }
+ }
+#endif
+
#if defined(FEATURE_JIT_PITCHING)
if ((CLRConfig::GetConfigValue(CLRConfig::INTERNAL_JitPitchEnabled) != 0) &&
(CLRConfig::GetConfigValue(CLRConfig::INTERNAL_JitPitchMemThreshold) != 0))
<OutputType>Exe</OutputType>
<CLRTestKind>BuildAndRun</CLRTestKind>
<CLRTestPriority>0</CLRTestPriority>
- <!-- See https://github.com/dotnet/coreclr/issues/25690 -->
- <GCStressIncompatible>true</GCStressIncompatible>
</PropertyGroup>
<PropertyGroup>
<DebugType>Full</DebugType>
<OutputType>Exe</OutputType>
<CLRTestKind>BuildAndRun</CLRTestKind>
<CLRTestPriority>0</CLRTestPriority>
- <!-- See https://github.com/dotnet/coreclr/issues/25690 -->
- <GCStressIncompatible>true</GCStressIncompatible>
</PropertyGroup>
<PropertyGroup>
<DebugType />