//
virtual void GetCallRefMap(
CORINFO_METHOD_HANDLE hMethod,
- GCRefMapBuilder * pBuilder) = 0;
+ GCRefMapBuilder * pBuilder,
+ bool isDispatchCell) = 0;
// Returns a compressed block of debug information
//
}
}
-void CEECompileInfo::GetCallRefMap(CORINFO_METHOD_HANDLE hMethod, GCRefMapBuilder * pBuilder)
+void CEECompileInfo::GetCallRefMap(CORINFO_METHOD_HANDLE hMethod, GCRefMapBuilder * pBuilder, bool isDispatchCell)
{
#ifdef _DEBUG
DWORD dwInitialLength = pBuilder->GetBlobLength();
MethodDesc *pMD = (MethodDesc *)hMethod;
- MetaSig msig(pMD);
+ SigTypeContext typeContext(pMD);
+ PCCOR_SIGNATURE pSig;
+ DWORD cbSigSize;
+ pMD->GetSig(&pSig, &cbSigSize);
+ MetaSig msig(pSig, cbSigSize, pMD->GetModule(), &typeContext);
+
+ //
+ // Shared default interface methods (i.e. virtual interface methods with an implementation) require
+ // an instantiation argument. But if we're in a situation where we haven't resolved the method yet
+ // we need to pretent that unresolved default interface methods are like any other interface
+ // methods and don't have an instantiation argument.
+ // See code:CEEInfo::getMethodSigInternal
+ //
+ assert(!isDispatchCell || !pMD->RequiresInstArg() || pMD->GetMethodTable()->IsInterface());
+ if (pMD->RequiresInstArg() && !isDispatchCell)
+ {
+ msig.SetHasParamTypeArg();
+ }
+
ArgIterator argit(&msig);
UINT nStackBytes = argit.SizeOfFrameArgumentArray();
SString &result);
void GetCallRefMap(CORINFO_METHOD_HANDLE hMethod,
- GCRefMapBuilder * pBuilder);
+ GCRefMapBuilder * pBuilder,
+ bool isDispatchCell);
void CompressDebugInfo(
IN ICorDebugInfo::OffsetMapping * pOffsetMapping,
//If not "vararg" calling convention, assume "default" calling convention
if (!MetaSig::IsVarArg(pFunction->GetModule(), callSignature))
{
- MetaSig msig(pFunction);
+ SigTypeContext typeContext(pFunction);
+ PCCOR_SIGNATURE pSig;
+ DWORD cbSigSize;
+ pFunction->GetSig(&pSig, &cbSigSize);
+
+ MetaSig msig(pSig, cbSigSize, pFunction->GetModule(), &typeContext);
+
+ if (pFunction->RequiresInstArg() && !SuppressParamTypeArg())
+ msig.SetHasParamTypeArg();
+
PromoteCallerStackHelper (fn, sc, pFunction, &msig);
}
else
//---------------------------------------------------------------
PTR_VOID GetParamTypeArg();
+ //---------------------------------------------------------------
+ // Gets value indicating whether the generic parameter type
+ // argument should be supressed.
+ //---------------------------------------------------------------
+ virtual BOOL SuppressParamTypeArg()
+ {
+ return FALSE;
+ }
+
protected: // we don't want people using this directly
//---------------------------------------------------------------
// Get the address of the "this" object. WARNING!!! Whether or not "this"
Interception GetInterception();
+ virtual BOOL SuppressParamTypeArg()
+ {
+ //
+ // Shared default interface methods (i.e. virtual interface methods with an implementation) require
+ // an instantiation argument. But if we're in the stub dispatch frame, we haven't actually resolved
+ // the method yet (we could end up in class's override of this method, for example).
+ //
+ // So we need to pretent that unresolved default interface methods are like any other interface
+ // methods and don't have an instantiation argument.
+ //
+ // See code:CEEInfo::getMethodSigInternal
+ //
+ assert(GetFunction()->GetMethodTable()->IsInterface());
+ return TRUE;
+ }
+
private:
friend class VirtualCallStubManager;
//-----------------------------------------------------------------------------
// Determine whether we should report the generic parameter context
//
-// This is meant to detect the situation where a ThreadAbortException is raised
+// This is meant to detect following situations:
+//
+// When a ThreadAbortException is raised
// in the prolog of a managed method, before the location for the generics
// context has been initialized; when such a TAE is raised, we are open to a
// race with the GC (e.g. while creating the managed object for the TAE).
// The long term solution is to avoid raising TAEs in any non-GC safe points,
// and to additionally ensure that we do not expose the runtime to TAE
// starvation.
+//
+// When we're in the process of resolution of an interface method and the
+// interface method happens to have a default implementation. Normally,
+// such methods require a generic context, but since we didn't resolve the
+// method to an implementation yet, we don't have the right context (in fact,
+// there's no context provided by the caller).
+// See code:CEEInfo::getMethodSigInternal
+//
inline bool SafeToReportGenericParamContext(CrawlFrame* pCF)
{
LIMITED_METHOD_CONTRACT;
+
+ if (!pCF->IsFrameless() && pCF->GetFrame()->GetVTablePtr() == StubDispatchFrame::GetMethodFrameVPtr())
+ {
+ return !((StubDispatchFrame*)pCF->GetFrame())->SuppressParamTypeArg();
+ }
+
if (!pCF->IsFrameless() || !(pCF->IsActiveFrame() || pCF->IsInterrupted()))
{
return true;
paramContextType = GENERIC_PARAM_CONTEXT_METHODTABLE;
}
- if (SafeToReportGenericParamContext(pCF))
+ if (paramContextType != GENERIC_PARAM_CONTEXT_NONE && SafeToReportGenericParamContext(pCF))
{
// Handle the case where the method is a static shared generic method and we need to keep the type
// of the generic parameters alive
m_pImage->GetImportTable()->PlaceImportBlob(pCell);
- m_pGCRefMapTable->Append(pCell->GetMethod());
+ m_pGCRefMapTable->Append(pCell->GetMethod(), true);
}
//
// GCRefMapTable is used to encode for GC references locations for lazily resolved calls
//
-void ZapGCRefMapTable::Append(CORINFO_METHOD_HANDLE handle)
+void ZapGCRefMapTable::Append(CORINFO_METHOD_HANDLE handle, bool isDispatchCell)
{
- m_pImage->GetCompileInfo()->GetCallRefMap(handle, &m_GCRefMapBuilder);
+ m_pImage->GetCompileInfo()->GetCallRefMap(handle, &m_GCRefMapBuilder, isDispatchCell);
m_nCount++;
}
{
}
- void Append(CORINFO_METHOD_HANDLE handle);
+ void Append(CORINFO_METHOD_HANDLE handle, bool isDispatchCell = false);
virtual DWORD GetSize();
<OutputType>Exe</OutputType>
<CLRTestKind>BuildAndRun</CLRTestKind>
<CLRTestPriority>0</CLRTestPriority>
-
- <!-- Hitting failures in GCStress: https://github.com/dotnet/coreclr/issues/16376 -->
- <GCStressIncompatible>true</GCStressIncompatible>
</PropertyGroup>
<ItemGroup>
<OutputType>Exe</OutputType>
<CLRTestKind>BuildAndRun</CLRTestKind>
<CLRTestPriority>0</CLRTestPriority>
-
- <!-- Hitting failures in GCStress: https://github.com/dotnet/coreclr/issues/16376 -->
- <GCStressIncompatible>true</GCStressIncompatible>
</PropertyGroup>
<ItemGroup>
<OutputType>Exe</OutputType>
<CLRTestKind>BuildAndRun</CLRTestKind>
<CLRTestPriority>0</CLRTestPriority>
-
- <!-- Fails GCStress: https://github.com/dotnet/coreclr/issues/16898 -->
- <GCStressIncompatible>true</GCStressIncompatible>
</PropertyGroup>
<ItemGroup>
<OutputType>Exe</OutputType>
<CLRTestKind>BuildAndRun</CLRTestKind>
<CLRTestPriority>0</CLRTestPriority>
-
- <!-- Issue 21044, https://github.com/dotnet/coreclr/issues/21044 -->
- <GCStressIncompatible>true</GCStressIncompatible>
</PropertyGroup>
<ItemGroup>
<OutputType>Exe</OutputType>
<CLRTestKind>BuildAndRun</CLRTestKind>
<CLRTestPriority>0</CLRTestPriority>
-
- <!-- Issue 21044, https://github.com/dotnet/coreclr/issues/21044 -->
- <GCStressIncompatible>true</GCStressIncompatible>
</PropertyGroup>
<ItemGroup>
<OutputType>Exe</OutputType>
<CLRTestKind>BuildAndRun</CLRTestKind>
<CLRTestPriority>0</CLRTestPriority>
-
- <!-- Issue 21044, https://github.com/dotnet/coreclr/issues/21044 -->
- <GCStressIncompatible>true</GCStressIncompatible>
</PropertyGroup>
<ItemGroup>