* Disable loading of methods from r2r images in MulticoreJit thread, if they have NDirect methods inlined in them
NDirect methods can be inlined in other methods during aot compilation.
If such method is loaded in mcj thread, it results in NDirect method being loaded.
Additionally, there's no way to control inlining during aot from runtime side, because r2r ni.dll might already exist.
In order to fix this, runtime aborts loading if method has NDirect methods inlined in it and this all happens in mcj thread.
* Forbid inlining of pinvoke methods with SuppressGCTransitionAttribute in MulticoreJit thread
BOOL NativeImageDumper::HandleFixupForHistogram(PTR_CORCOMPILE_IMPORT_SECTION pSection,
SIZE_T fixupIndex,
- SIZE_T *fixupCell)
+ SIZE_T *fixupCell,
+ BOOL mayUsePrecompiledNDirectMethods)
{
COUNT_T nImportSections;
PTR_CORCOMPILE_IMPORT_SECTION pImportSections = m_decoder.GetNativeImportSections(&nImportSections);
return 0;
}
-BOOL NativeImageDumper::HandleFixupForMethodDump(PTR_CORCOMPILE_IMPORT_SECTION pSection, SIZE_T fixupIndex, SIZE_T *fixupCell)
+BOOL NativeImageDumper::HandleFixupForMethodDump(PTR_CORCOMPILE_IMPORT_SECTION pSection, SIZE_T fixupIndex, SIZE_T *fixupCell, BOOL mayUsePrecompiledNDirectMethods)
{
PTR_SIZE_T fixupPtr(TO_TADDR(fixupCell));
m_display->StartElement( "Fixup" );
IMetaDataAssemblyImport *m_manifestAssemblyImport;
//helper for ComputeMethodFixupHistogram
- BOOL HandleFixupForHistogram(PTR_CORCOMPILE_IMPORT_SECTION pSection, SIZE_T fixupIndex, SIZE_T *fixupCell);
+ BOOL HandleFixupForHistogram(PTR_CORCOMPILE_IMPORT_SECTION pSection, SIZE_T fixupIndex, SIZE_T *fixupCell, BOOL mayUsePrecompiledNDirectMethods = TRUE);
//helper for DumpMethodFixups
- BOOL HandleFixupForMethodDump(PTR_CORCOMPILE_IMPORT_SECTION pSection, SIZE_T fixupIndex, SIZE_T *fixupCell);
+ BOOL HandleFixupForMethodDump(PTR_CORCOMPILE_IMPORT_SECTION pSection, SIZE_T fixupIndex, SIZE_T *fixupCell, BOOL mayUsePrecompiledNDirectMethods = TRUE);
// Dependencies
//-----------------------------------------------------------------------------
-BOOL Module::FixupNativeEntry(CORCOMPILE_IMPORT_SECTION* pSection, SIZE_T fixupIndex, SIZE_T* fixupCell)
+BOOL Module::FixupNativeEntry(CORCOMPILE_IMPORT_SECTION* pSection, SIZE_T fixupIndex, SIZE_T* fixupCell, BOOL mayUsePrecompiledNDirectMethods)
{
CONTRACTL
{
{
PTR_DWORD pSignatures = dac_cast<PTR_DWORD>(GetNativeOrReadyToRunImage()->GetRvaData(pSection->Signatures));
- if (!LoadDynamicInfoEntry(this, pSignatures[fixupIndex], fixupCell))
+ if (!LoadDynamicInfoEntry(this, pSignatures[fixupIndex], fixupCell, mayUsePrecompiledNDirectMethods))
return FALSE;
_ASSERTE(*fixupCell != NULL);
if (CORCOMPILE_IS_FIXUP_TAGGED(fixup, pSection))
{
// Fixup has not been fixed up yet
- if (!LoadDynamicInfoEntry(this, (RVA)CORCOMPILE_UNTAG_TOKEN(fixup), fixupCell))
+ if (!LoadDynamicInfoEntry(this, (RVA)CORCOMPILE_UNTAG_TOKEN(fixup), fixupCell, mayUsePrecompiledNDirectMethods))
return FALSE;
_ASSERTE(!CORCOMPILE_IS_FIXUP_TAGGED(*fixupCell, pSection));
IMDInternalImport *GetNativeAssemblyImport(BOOL loadAllowed = TRUE);
IMDInternalImport *GetNativeAssemblyImportIfLoaded();
- BOOL FixupNativeEntry(CORCOMPILE_IMPORT_SECTION * pSection, SIZE_T fixupIndex, SIZE_T *fixup);
+ BOOL FixupNativeEntry(CORCOMPILE_IMPORT_SECTION * pSection, SIZE_T fixupIndex, SIZE_T *fixup, BOOL mayUsePrecompiledNDirectMethods = TRUE);
//this split exists to support new CLR Dump functionality in DAC. The
//template removes any indirections.
- BOOL FixupDelayList(TADDR pFixupList);
+ BOOL FixupDelayList(TADDR pFixupList, BOOL mayUsePrecompiledNDirectMethods = TRUE);
template<typename Ptr, typename FixupNativeEntryCallback>
BOOL FixupDelayListAux(TADDR pFixupList,
Ptr pThis, FixupNativeEntryCallback pfnCB,
PTR_CORCOMPILE_IMPORT_SECTION pImportSections, COUNT_T nImportSections,
- PEDecoder * pNativeImage);
+ PEDecoder * pNativeImage, BOOL mayUsePrecompiledNDirectMethods = TRUE);
void RunEagerFixups();
void RunEagerFixupsUnlocked();
#include "nibblestream.h"
-FORCEINLINE BOOL Module::FixupDelayList(TADDR pFixupList)
+FORCEINLINE BOOL Module::FixupDelayList(TADDR pFixupList, BOOL mayUsePrecompiledNDirectMethods)
{
WRAPPER_NO_CONTRACT;
COUNT_T nImportSections;
PTR_CORCOMPILE_IMPORT_SECTION pImportSections = GetImportSections(&nImportSections);
- return FixupDelayListAux(pFixupList, this, &Module::FixupNativeEntry, pImportSections, nImportSections, GetNativeOrReadyToRunImage());
+ return FixupDelayListAux(pFixupList, this, &Module::FixupNativeEntry, pImportSections, nImportSections, GetNativeOrReadyToRunImage(), mayUsePrecompiledNDirectMethods);
}
template<typename Ptr, typename FixupNativeEntryCallback>
BOOL Module::FixupDelayListAux(TADDR pFixupList,
Ptr pThis, FixupNativeEntryCallback pfnCB,
PTR_CORCOMPILE_IMPORT_SECTION pImportSections, COUNT_T nImportSections,
- PEDecoder * pNativeImage)
+ PEDecoder * pNativeImage, BOOL mayUsePrecompiledNDirectMethods)
{
CONTRACTL
{
{
CONSISTENCY_CHECK(fixupIndex * sizeof(TADDR) < cbData);
- if (!(pThis->*pfnCB)(pImportSection, fixupIndex, dac_cast<PTR_SIZE_T>(pData + fixupIndex * sizeof(TADDR))))
+ if (!(pThis->*pfnCB)(pImportSection, fixupIndex, dac_cast<PTR_SIZE_T>(pData + fixupIndex * sizeof(TADDR)), mayUsePrecompiledNDirectMethods))
return FALSE;
int delta = reader.ReadEncodedU32();
#endif
}
+ PrepareCodeConfig *config = GetThread()->GetCurrentPrepareCodeConfig();
+ if (config != nullptr && config->IsForMulticoreJit())
+ {
+ bool suppressGCTransition = false;
+ CorInfoCallConvExtension unmanagedCallConv = getUnmanagedCallConv(method, callSiteSig, &suppressGCTransition);
+
+ if (suppressGCTransition)
+ {
+ // MultiCoreJit thread can't inline PInvoke with SuppressGCTransitionAttribute,
+ // because it can't be resolved in mcj thread
+ result = TRUE;
+ }
+ }
+
EE_TO_JIT_TRANSITION();
return result;
BOOL LoadDynamicInfoEntry(Module *currentModule,
RVA fixupRva,
- SIZE_T *entry)
+ SIZE_T *entry,
+ BOOL mayUsePrecompiledNDirectMethods)
{
STANDARD_VM_CONTRACT;
case ENCODE_PINVOKE_TARGET:
{
- MethodDesc *pMethod = ZapSig::DecodeMethod(currentModule, pInfoModule, pBlob);
+ if (mayUsePrecompiledNDirectMethods)
+ {
+ MethodDesc *pMethod = ZapSig::DecodeMethod(currentModule, pInfoModule, pBlob);
- _ASSERTE(pMethod->IsNDirect());
- result = (size_t)(LPVOID)NDirectMethodDesc::ResolveAndSetNDirectTarget((NDirectMethodDesc*)pMethod);
+ _ASSERTE(pMethod->IsNDirect());
+ result = (size_t)(LPVOID)NDirectMethodDesc::ResolveAndSetNDirectTarget((NDirectMethodDesc*)pMethod);
+ }
+ else
+ {
+ return FALSE;
+ }
}
break;
BOOL LoadDynamicInfoEntry(Module *currentModule,
RVA fixupRva,
- SIZE_T *entry);
+ SIZE_T *entry,
+ BOOL mayUsePrecompiledNDirectMethods = TRUE);
//
// The legacy x86 monitor helpers do not need a state argument
FCDECL1(INT64, GetCompilationTimeInTicks, CLR_BOOL currentThread);
#endif // JITINTERFACE_H
-
#endif
}
+ if (pConfig->IsForMulticoreJit() && pCode == NULL && pConfig->ReadyToRunRejectedPrecompiledCode())
+ {
+ // Was unable to load code from r2r image in mcj thread, don't try to jit it, this method will be loaded later
+ return NULL;
+ }
+
if (pCode == NULL)
{
LOG((LF_CLASSLOADER, LL_INFO1000000,
if (fFixups)
{
- if (!m_pModule->FixupDelayList(dac_cast<TADDR>(GetImage()->GetBase()) + offset))
+ BOOL mayUsePrecompiledNDirectMethods = TRUE;
+#ifndef CROSSGEN_COMPILE
+ mayUsePrecompiledNDirectMethods = !pConfig->IsForMulticoreJit();
+#endif // CROSSGEN_COMPILE
+
+ if (!m_pModule->FixupDelayList(dac_cast<TADDR>(GetImage()->GetBase()) + offset, mayUsePrecompiledNDirectMethods))
{
#ifndef CROSSGEN_COMPILE
pConfig->SetReadyToRunRejectedPrecompiledCode();