Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

R2R ilstubs #24823

Merged
merged 20 commits into from Jun 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
0e1aba4
Basic support for precompiled pinvoke stubs
davidwrighton May 26, 2019
0f27342
Generate R2R file with multiple references to same IL stub (one per m…
davidwrighton May 26, 2019
cf8760f
Protect cast to Module* in ZapSig
davidwrighton May 28, 2019
08436bf
Not all il stubs are p/invokes. Don't fail when they aren't.
davidwrighton May 28, 2019
2183091
Consistently use IsDynamicScope and GetModule to avoid unsafe memory …
davidwrighton May 28, 2019
da3abb4
Restrict IL Stub to safe in all contexts instructions
davidwrighton May 29, 2019
56481cf
Enable full p/invoke il stubs when compiling System.Private.Corelib
davidwrighton May 29, 2019
a4123b3
Merge branch 'master' of https://github.com/dotnet/coreclr into r2r_i…
davidwrighton May 29, 2019
94dfbfc
Fix build break caused by merge
davidwrighton May 29, 2019
f6609f9
Tweaks for profiler handling and such
davidwrighton May 30, 2019
3cb779b
Increase correctness of which stubs may be compiled
davidwrighton May 30, 2019
cdb62d2
Fix oops where value wasn't returned from MyUsePrecompiledILStub
davidwrighton May 30, 2019
ed4aaf3
Actually make IL stubs in non CoreLib modules work
davidwrighton May 30, 2019
ecf827c
Merge branch 'master' of https://github.com/dotnet/coreclr into r2r_i…
davidwrighton May 31, 2019
488bfe5
Remove all ilstubs logic intended for use outside of R2R
davidwrighton Jun 5, 2019
b62d14e
Merge branch 'master' of https://github.com/dotnet/coreclr into r2r_i…
davidwrighton Jun 5, 2019
eb1e6e2
Disable IL Stub generation in crossgen for ARM32.
davidwrighton Jun 7, 2019
734608b
ISPinvokeILStub is insufficient to isolate for p/invoke IL stubs. Als…
davidwrighton Jun 8, 2019
55f8845
Address feedback
davidwrighton Jun 11, 2019
441a16b
Change variable to be called unused
davidwrighton Jun 11, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/inc/corcompile.h
Expand Up @@ -1756,6 +1756,11 @@ class ICorCompileInfo
virtual int GetVersionResilientTypeHashCode(CORINFO_MODULE_HANDLE moduleHandle, mdToken token) = 0;

virtual int GetVersionResilientMethodHashCode(CORINFO_METHOD_HANDLE methodHandle) = 0;

virtual BOOL EnumMethodsForStub(CORINFO_METHOD_HANDLE hMethod, void** enumerator) = 0;
AaronRobinsonMSFT marked this conversation as resolved.
Show resolved Hide resolved
virtual BOOL EnumNextMethodForStub(void * enumerator, CORINFO_METHOD_HANDLE *hMethod) = 0;
virtual void EnumCloseForStubEnumerator(void *enumerator) = 0;

#endif

virtual BOOL HasCustomAttribute(CORINFO_METHOD_HANDLE method, LPCSTR customAttributeName) = 0;
Expand Down
114 changes: 111 additions & 3 deletions src/vm/compile.cpp
Expand Up @@ -69,9 +69,13 @@
#include "versionresilienthashcode.h"
#include "inlinetracking.h"
#include "jithost.h"
#include "stubgen.h"

#ifdef CROSSGEN_COMPILE
CompilationDomain * theDomain;
#ifdef FEATURE_READYTORUN_COMPILER
MapSHash<CORINFO_METHOD_HANDLE, CORINFO_METHOD_HANDLE> s_stubMethodsOfMethod;
AaronRobinsonMSFT marked this conversation as resolved.
Show resolved Hide resolved
#endif // FEATURE_READYTORUN_COMPILER
#endif

VerboseLevel g_CorCompileVerboseLevel = CORCOMPILE_NO_LOG;
Expand Down Expand Up @@ -6192,11 +6196,17 @@ void CEEPreloader::GenerateMethodStubs(
MethodDesc* pMD = GetMethod(hMethod);
MethodDesc* pStubMD = NULL;

// Do not generate IL stubs when generating ReadyToRun images
// Do not generate IL stubs when generating ReadyToRun images except for System.Private.Corelib
// This prevents versionability concerns around IL stubs exposing internal
// implementation details of the CLR.
if (IsReadyToRunCompilation() && (!GetAppDomain()->ToCompilationDomain()->GetTargetModule()->IsSystem() || !pMD->IsNDirect()))
return;

#if defined(_TARGET_ARM_) && defined(FEATURE_PAL)
// Cross-bitness compilation of il stubs does not work. Disable here.
if (IsReadyToRunCompilation())
return;
#endif // defined(_TARGET_ARM_) && defined(FEATURE_PAL)

DWORD dwNGenStubFlags = NDIRECTSTUB_FL_NGENEDSTUB;

Expand Down Expand Up @@ -6285,8 +6295,14 @@ void CEEPreloader::GenerateMethodStubs(
// that we can recover the stub MethodDesc at prestub time, do the fixups, and wire up the native code
if (pStubMD != NULL)
{
SetStubMethodDescOnInteropMethodDesc(pMD, pStubMD, false /* fReverseStub */);
pStubMD = NULL;
#ifdef FEATURE_READYTORUN_COMPILER
if (IsReadyToRunCompilation())
{
s_stubMethodsOfMethod.Add(CORINFO_METHOD_HANDLE(pStubMD), CORINFO_METHOD_HANDLE(pMD));
}
#endif // FEATURE_READYTORUN_COMPILER
SetStubMethodDescOnInteropMethodDesc(pMD, pStubMD, false /* fReverseStub */);
pStubMD = NULL;
}

}
Expand All @@ -6297,6 +6313,10 @@ void CEEPreloader::GenerateMethodStubs(
}
EX_END_CATCH(RethrowTransientExceptions);

// Only P/Invoke stubs are eligible to be created in R2R
if (IsReadyToRunCompilation())
return;

//
// Now take care of reverse P/Invoke stubs for delegates
//
Expand Down Expand Up @@ -7290,6 +7310,94 @@ HRESULT CompilationDomain::SetPlatformWinmdPaths(LPCWSTR pwzPlatformWinmdPaths)

return S_OK;
}

#ifdef FEATURE_READYTORUN_COMPILER

class MethodsForStubEnumerator
{
SHash<NoRemoveSHashTraits<MapSHashTraits<CORINFO_METHOD_HANDLE, CORINFO_METHOD_HANDLE>>>::KeyIterator current;
SHash<NoRemoveSHashTraits<MapSHashTraits<CORINFO_METHOD_HANDLE, CORINFO_METHOD_HANDLE>>>::KeyIterator end;
bool started = false;
bool complete = false;

public:
MethodsForStubEnumerator(CORINFO_METHOD_HANDLE hMethod) :
current(s_stubMethodsOfMethod.Begin(hMethod)),
end(s_stubMethodsOfMethod.End(hMethod))
{
complete = current == end;
}

bool Next()
{
if (complete)
return false;

if (started)
{
++current;
}
else
{
started = true;
}

if (current == end)
{
complete = true;
return false;
}
return true;
}

CORINFO_METHOD_HANDLE Current()
{
return current->Value();
}
};
#endif // FEATURE_READYTORUN_COMPILER

BOOL CEECompileInfo::EnumMethodsForStub(CORINFO_METHOD_HANDLE hMethod, void** enumerator)
{
#ifdef FEATURE_READYTORUN_COMPILER
*enumerator = NULL;
if (s_stubMethodsOfMethod.LookupPtr(hMethod) == NULL)
return FALSE;

*enumerator = new MethodsForStubEnumerator(hMethod);
AaronRobinsonMSFT marked this conversation as resolved.
Show resolved Hide resolved
return TRUE;
#else
return FALSE;
#endif // FEATURE_READYTORUN_COMPILER
}

BOOL CEECompileInfo::EnumNextMethodForStub(void * enumerator, CORINFO_METHOD_HANDLE *hMethod)
{
*hMethod = NULL;
#ifdef FEATURE_READYTORUN_COMPILER
auto stubEnum = (MethodsForStubEnumerator*)enumerator;
if (stubEnum->Next())
{
*hMethod = stubEnum->Current();
return TRUE;
}
else
{
return FALSE;
}
#else
return FALSE;
#endif // FEATURE_READYTORUN_COMPILER
}

void CEECompileInfo::EnumCloseForStubEnumerator(void *enumerator)
{
#ifdef FEATURE_READYTORUN_COMPILER
auto stubEnum = (MethodsForStubEnumerator*)enumerator;
delete stubEnum;
#endif // FEATURE_READYTORUN_COMPILER
}

#endif // CROSSGEN_COMPILE


Expand Down
4 changes: 4 additions & 0 deletions src/vm/compile.h
Expand Up @@ -372,6 +372,10 @@ class CEECompileInfo : public ICorCompileInfo
int GetVersionResilientTypeHashCode(CORINFO_MODULE_HANDLE moduleHandle, mdToken token);

int GetVersionResilientMethodHashCode(CORINFO_METHOD_HANDLE methodHandle);

BOOL EnumMethodsForStub(CORINFO_METHOD_HANDLE hMethod, void** enumerator);
BOOL EnumNextMethodForStub(void * enumerator, CORINFO_METHOD_HANDLE *hMethod);
void EnumCloseForStubEnumerator(void *enumerator);
#endif

BOOL HasCustomAttribute(CORINFO_METHOD_HANDLE method, LPCSTR customAttributeName);
Expand Down
30 changes: 13 additions & 17 deletions src/vm/dllimport.cpp
Expand Up @@ -801,7 +801,7 @@ class ILStubState : public StubState
DWORD dwMethodDescLocalNum = (DWORD)-1;

// Notify the profiler of call out of the runtime
if (!SF_IsReverseCOMStub(m_dwStubFlags) && (CORProfilerTrackTransitions() || SF_IsNGENedStubForProfiling(m_dwStubFlags)))
if (!SF_IsReverseCOMStub(m_dwStubFlags) && (CORProfilerTrackTransitions() || (!IsReadyToRunCompilation() && SF_IsNGENedStubForProfiling(m_dwStubFlags))))
{
dwMethodDescLocalNum = m_slIL.EmitProfilerBeginTransitionCallback(pcsDispatch, m_dwStubFlags);
_ASSERTE(dwMethodDescLocalNum != (DWORD)-1);
Expand Down Expand Up @@ -2295,27 +2295,23 @@ void NDirectStubLinker::DoNDirect(ILCodeStream *pcsEmit, DWORD dwStubFlags, Meth
#endif // FEATURE_COMINTEROP
{
EmitLoadStubContext(pcsEmit, dwStubFlags);
// pcsEmit->EmitCALL(METHOD__STUBHELPERS__GET_NDIRECT_TARGET, 1, 1);
pcsEmit->EmitLDC(offsetof(NDirectMethodDesc, ndirect.m_pWriteableData));
pcsEmit->EmitADD();

if (decltype(NDirectMethodDesc::ndirect.m_pWriteableData)::isRelative)
{
// Perf: inline the helper for now
//pcsEmit->EmitCALL(METHOD__STUBHELPERS__GET_NDIRECT_TARGET, 1, 1);
pcsEmit->EmitLDC(offsetof(NDirectMethodDesc, ndirect.m_pWriteableData));
pcsEmit->EmitADD();

if (decltype(NDirectMethodDesc::ndirect.m_pWriteableData)::isRelative)
{
pcsEmit->EmitDUP();
}
pcsEmit->EmitDUP();
}

pcsEmit->EmitLDIND_I();
pcsEmit->EmitLDIND_I();

if (decltype(NDirectMethodDesc::ndirect.m_pWriteableData)::isRelative)
{
pcsEmit->EmitADD();
}

pcsEmit->EmitLDIND_I();
if (decltype(NDirectMethodDesc::ndirect.m_pWriteableData)::isRelative)
{
pcsEmit->EmitADD();
}

pcsEmit->EmitLDIND_I();
}
#ifdef FEATURE_COMINTEROP
else
Expand Down
6 changes: 5 additions & 1 deletion src/vm/ilstubresolver.cpp
Expand Up @@ -233,6 +233,11 @@ bool ILStubResolver::IsNativeToCLRInteropStub()
return (m_type == NativeToCLRInteropStub);
}

bool ILStubResolver::IsCLRToNativeInteropStub()
{
return (m_type == CLRToNativeInteropStub);
}

void ILStubResolver::SetStubType(ILStubType stubType)
{
LIMITED_METHOD_CONTRACT;
Expand Down Expand Up @@ -393,7 +398,6 @@ COR_ILMETHOD_SECT_EH* ILStubResolver::AllocEHSect(size_t nClauses)
}
}


void ILStubResolver::FreeCompileTimeState()
{
CONTRACTL
Expand Down
1 change: 1 addition & 0 deletions src/vm/ilstubresolver.h
Expand Up @@ -47,6 +47,7 @@ class ILStubResolver : DynamicResolver
// ILStubResolver-specific methods
// -----------------------------------
bool IsNativeToCLRInteropStub();
bool IsCLRToNativeInteropStub();
MethodDesc* GetStubMethodDesc();
MethodDesc* GetStubTargetMethodDesc();
void SetStubTargetMethodDesc(MethodDesc* pStubTargetMD);
Expand Down
52 changes: 49 additions & 3 deletions src/vm/prestub.cpp
Expand Up @@ -358,14 +358,60 @@ PCODE MethodDesc::PrepareCode(PrepareCodeConfig* pConfig)
return PrepareILBasedCode(pConfig);
}

bool MayUsePrecompiledILStub()
{
if (g_pConfig->InteropValidatePinnedObjects())
return false;

if (CORProfilerTrackTransitions())
return false;

if (g_pConfig->InteropLogArguments())
return false;

return true;
}

PCODE MethodDesc::PrepareILBasedCode(PrepareCodeConfig* pConfig)
{
STANDARD_VM_CONTRACT;
PCODE pCode = NULL;

if (pConfig->MayUsePrecompiledCode())
{
pCode = GetPrecompiledCode(pConfig);
#ifdef FEATURE_READYTORUN
if (this->IsDynamicMethod() && GetLoaderModule()->IsSystem() && MayUsePrecompiledILStub())
{
DynamicMethodDesc *stubMethodDesc = this->AsDynamicMethodDesc();
if (stubMethodDesc->IsILStub() && stubMethodDesc->IsPInvokeStub())
{
ILStubResolver *pStubResolver = stubMethodDesc->GetILStubResolver();
if (pStubResolver->IsCLRToNativeInteropStub())
{
MethodDesc *pTargetMD = stubMethodDesc->GetILStubResolver()->GetStubTargetMethodDesc();
if (pTargetMD != NULL)
{
pCode = pTargetMD->GetPrecompiledR2RCode(pConfig);
if (pCode != NULL)
{
LOG((LF_ZAP, LL_INFO10000,
"ZAP: Using R2R precompiled code" FMT_ADDR " for %s.%s sig=\"%s\" (token %x).\n",
DBG_ADDR(pCode),
m_pszDebugClassName,
m_pszDebugMethodName,
m_pszDebugMethodSignature,
GetMemberDef()));

pConfig->SetNativeCode(pCode, &pCode);
}
}
}
}
}
#endif // FEATURE_READYTORUN

if (pCode == NULL)
pCode = GetPrecompiledCode(pConfig);
}

if (pCode == NULL)
Expand Down Expand Up @@ -412,7 +458,7 @@ PCODE MethodDesc::GetPrecompiledCode(PrepareCodeConfig* pConfig)
if (pCode != NULL)
{
LOG((LF_ZAP, LL_INFO10000,
"ZAP: Using R2R precompiled code" FMT_ADDR "for %s.%s sig=\"%s\" (token %x).\n",
"ZAP: Using R2R precompiled code" FMT_ADDR " for %s.%s sig=\"%s\" (token %x).\n",
DBG_ADDR(pCode),
m_pszDebugClassName,
m_pszDebugMethodName,
Expand Down Expand Up @@ -471,7 +517,7 @@ PCODE MethodDesc::GetPrecompiledNgenCode(PrepareCodeConfig* pConfig)
if (pCode != NULL)
{
LOG((LF_ZAP, LL_INFO10000,
"ZAP: Using NGEN precompiled code" FMT_ADDR "for %s.%s sig=\"%s\" (token %x).\n",
"ZAP: Using NGEN precompiled code " FMT_ADDR " for %s.%s sig=\"%s\" (token %x).\n",
DBG_ADDR(pCode),
m_pszDebugClassName,
m_pszDebugMethodName,
Expand Down
2 changes: 1 addition & 1 deletion src/vm/stubgen.cpp
Expand Up @@ -2921,4 +2921,4 @@ void ILCodeStream::ClearCode()
{
LIMITED_METHOD_CONTRACT;
m_uCurInstrIdx = 0;
}
}