diff --git a/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs index 358dab7f43674d..fc80b8b229f19c 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs @@ -535,11 +535,13 @@ private static bool InternalEqualMethodHandles(Delegate left, Delegate right) internal static IntPtr AdjustTarget(object target, IntPtr methodPtr) { - return AdjustTarget(ObjectHandleOnStack.Create(ref target), methodPtr); + IntPtr result = AdjustTarget(RuntimeHelpers.GetMethodTable(target), methodPtr); + GC.KeepAlive(target); + return result; } [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "Delegate_AdjustTarget")] - private static partial IntPtr AdjustTarget(ObjectHandleOnStack target, IntPtr methodPtr); + private static partial IntPtr AdjustTarget(MethodTable* targetMT, IntPtr methodPtr); internal void InitializeVirtualCallStub(IntPtr methodPtr) { diff --git a/src/coreclr/debug/ee/funceval.cpp b/src/coreclr/debug/ee/funceval.cpp index 263beaa911bbfc..45723c4a9b8ae2 100644 --- a/src/coreclr/debug/ee/funceval.cpp +++ b/src/coreclr/debug/ee/funceval.cpp @@ -2099,6 +2099,7 @@ void GatherFuncEvalMethodInfo(DebuggerEval *pDE, // if ((pDE->m_evalType != DB_IPCE_FET_NEW_OBJECT) && !pDE->m_md->IsStatic() && pDE->m_md->IsUnboxingStub()) { + GCX_PREEMP(); *ppUnboxedMD = pDE->m_md->GetMethodTable()->GetUnboxedEntryPointMD(pDE->m_md); } @@ -2213,13 +2214,19 @@ void GatherFuncEvalMethodInfo(DebuggerEval *pDE, // Now, find the proper MethodDesc for this interface method based on the object we're invoking the // method on. // - pDE->m_targetCodeAddr = pDE->m_md->GetCallTarget(&objRef, pDE->m_ownerTypeHandle); + { + GCX_PREEMP(); + pDE->m_targetCodeAddr = pDE->m_md->GetCallTarget(&objRef, pDE->m_ownerTypeHandle); + } GCPROTECT_END(); } else { - pDE->m_targetCodeAddr = pDE->m_md->GetCallTarget(NULL, pDE->m_ownerTypeHandle); + { + GCX_PREEMP(); + pDE->m_targetCodeAddr = pDE->m_md->GetCallTarget(NULL, pDE->m_ownerTypeHandle); + } } // diff --git a/src/coreclr/vm/amd64/cgenamd64.cpp b/src/coreclr/vm/amd64/cgenamd64.cpp index 70ebf04fa7fc1c..5d2bf853b51755 100644 --- a/src/coreclr/vm/amd64/cgenamd64.cpp +++ b/src/coreclr/vm/amd64/cgenamd64.cpp @@ -24,9 +24,7 @@ #include "clrtocomcall.h" #endif // FEATURE_COMINTEROP -#ifdef FEATURE_PERFMAP #include "perfmap.h" -#endif void UpdateRegDisplayFromCalleeSavedRegisters(REGDISPLAY * pRD, CalleeSavedRegisters * pRegs) { @@ -607,17 +605,11 @@ DWORD GetOffsetAtEndOfFunction(ULONGLONG uImageBase, size_t rxOffset = pStartRX - pStart; \ BYTE * p = pStart; -#ifdef FEATURE_PERFMAP #define BEGIN_DYNAMIC_HELPER_EMIT(size) \ BEGIN_DYNAMIC_HELPER_EMIT_WORKER(size) \ PerfMap::LogStubs(__FUNCTION__, "DynamicHelper", (PCODE)p, size, PerfMapStubType::Individual); -#else -#define BEGIN_DYNAMIC_HELPER_EMIT(size) BEGIN_DYNAMIC_HELPER_EMIT_WORKER(size) -#endif #define END_DYNAMIC_HELPER_EMIT() \ - _ASSERTE(pStart + cb == p); \ - while (p < pStart + cbAligned) *p++ = X86_INSTR_INT3; \ ClrFlushInstructionCache(pStartRX, cbAligned); \ return (PCODE)pStartRX diff --git a/src/coreclr/vm/arm/stubs.cpp b/src/coreclr/vm/arm/stubs.cpp index 815ab68867a005..5d1f5d2ad60633 100644 --- a/src/coreclr/vm/arm/stubs.cpp +++ b/src/coreclr/vm/arm/stubs.cpp @@ -25,9 +25,7 @@ #include "ecall.h" #include "threadsuspend.h" -#ifdef FEATURE_PERFMAP #include "perfmap.h" -#endif // target write barriers EXTERN_C void JIT_WriteBarrier(Object **dst, Object *ref); @@ -1505,13 +1503,9 @@ void MovRegImm(BYTE* p, int reg, TADDR imm) size_t rxOffset = pStartRX - pStart; \ BYTE * p = pStart; -#ifdef FEATURE_PERFMAP #define BEGIN_DYNAMIC_HELPER_EMIT(size) \ BEGIN_DYNAMIC_HELPER_EMIT_WORKER(size) \ PerfMap::LogStubs(__FUNCTION__, "DynamicHelper", (PCODE)p, size, PerfMapStubType::Individual); -#else -#define BEGIN_DYNAMIC_HELPER_EMIT(size) BEGIN_DYNAMIC_HELPER_EMIT_WORKER(size) -#endif #define END_DYNAMIC_HELPER_EMIT() \ diff --git a/src/coreclr/vm/arm64/stubs.cpp b/src/coreclr/vm/arm64/stubs.cpp index ba9a29ff4bcde5..0e123c42e7ed9f 100644 --- a/src/coreclr/vm/arm64/stubs.cpp +++ b/src/coreclr/vm/arm64/stubs.cpp @@ -13,9 +13,7 @@ #include "ecall.h" #include "writebarriermanager.h" -#ifdef FEATURE_PERFMAP #include "perfmap.h" -#endif #ifndef DACCESS_COMPILE //----------------------------------------------------------------------- @@ -951,13 +949,9 @@ void StubLinkerCPU::EmitCallManagedMethod(MethodDesc *pMD, BOOL fTailCall) size_t rxOffset = pStartRX - pStart; \ BYTE * p = pStart; -#ifdef FEATURE_PERFMAP #define BEGIN_DYNAMIC_HELPER_EMIT(size) \ BEGIN_DYNAMIC_HELPER_EMIT_WORKER(size) \ PerfMap::LogStubs(__FUNCTION__, "DynamicHelper", (PCODE)p, size, PerfMapStubType::Individual); -#else -#define BEGIN_DYNAMIC_HELPER_EMIT(size) BEGIN_DYNAMIC_HELPER_EMIT_WORKER(size) -#endif #define END_DYNAMIC_HELPER_EMIT() \ diff --git a/src/coreclr/vm/assembly.cpp b/src/coreclr/vm/assembly.cpp index 5f2526172d941d..7bd7c0ae0217a6 100644 --- a/src/coreclr/vm/assembly.cpp +++ b/src/coreclr/vm/assembly.cpp @@ -1156,7 +1156,11 @@ static void RunMainInternal(Param* pParam) StrArgArray = *pParam->stringArgs; pParam->pFD->EnsureActive(); - PCODE entryPoint = pParam->pFD->GetSingleCallableAddrOfCode(); + PCODE entryPoint; + { + GCX_PREEMP(); + entryPoint = pParam->pFD->GetSingleCallableAddrOfCode(); + } BOOL hasReturnValue = !pParam->pFD->IsVoid(); PTRARRAYREF* pArgument = (pParam->EntryType == EntryManagedMain) ? &StrArgArray : NULL; diff --git a/src/coreclr/vm/callhelpers.cpp b/src/coreclr/vm/callhelpers.cpp index 2568a1483d5714..b2160b1ac6bfd3 100644 --- a/src/coreclr/vm/callhelpers.cpp +++ b/src/coreclr/vm/callhelpers.cpp @@ -559,11 +559,17 @@ void CallDefaultConstructor(OBJECTREF ref) GCPROTECT_BEGIN (ref); - MethodDesc *pMD = pMT->GetDefaultConstructor(); + + PCODE methodEntry; + { + GCX_PREEMP(); + MethodDesc *pMD = pMT->GetDefaultConstructor(); + methodEntry = pMD->GetSingleCallableAddrOfCode(); + } UnmanagedCallersOnlyCaller defaultCtorInvoker{METHOD__RUNTIME_HELPERS__CALL_DEFAULT_CONSTRUCTOR}; - defaultCtorInvoker.InvokeThrowing(&ref, pMD->GetSingleCallableAddrOfCode()); + defaultCtorInvoker.InvokeThrowing(&ref, methodEntry); GCPROTECT_END (); } diff --git a/src/coreclr/vm/callhelpers.h b/src/coreclr/vm/callhelpers.h index a91f65078c271c..5630d73b12a67e 100644 --- a/src/coreclr/vm/callhelpers.h +++ b/src/coreclr/vm/callhelpers.h @@ -104,178 +104,9 @@ class MethodDescCallSite } #endif // _DEBUG - void DefaultInit(OBJECTREF* porProtectedThis) - { - CONTRACTL - { - MODE_ANY; - GC_TRIGGERS; - THROWS; - } - CONTRACTL_END; - -#ifdef _DEBUG - // - // Make sure we are passing in a 'this' if and only if it is required - // - if (m_pMD->IsVtableMethod()) - { - CONSISTENCY_CHECK_MSG(NULL != porProtectedThis, "You did not pass in the 'this' object for a vtable method"); - } - else - { - if (NULL != porProtectedThis) - { - if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_AssertOnUnneededThis)) - { - CONSISTENCY_CHECK_MSG(NULL == porProtectedThis, "You passed in a 'this' object to a non-vtable method."); - } - else - { - LogWeakAssert(); - } - - } - } -#endif // _DEBUG - - m_pCallTarget = m_pMD->GetCallTarget(porProtectedThis); - - m_argIt.ForceSigWalk(); - } - - void DefaultInit(TypeHandle th) - { - CONTRACTL - { - MODE_ANY; - GC_TRIGGERS; - THROWS; - } - CONTRACTL_END; - - m_pCallTarget = m_pMD->GetCallTarget(NULL, th); - - m_argIt.ForceSigWalk(); -} - void CallTargetWorker(const ARG_SLOT *pArguments, ARG_SLOT *pReturnValue, int cbReturnValue); public: - // Used to avoid touching metadata for CoreLib methods. - // instance methods must pass in the 'this' object - // static methods must pass null - MethodDescCallSite(BinderMethodID id, OBJECTREF* porProtectedThis = NULL) : - m_pMD( - CoreLibBinder::GetMethod(id) - ), - m_methodSig(id), - m_argIt(&m_methodSig) - { - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - } - CONTRACTL_END; - DefaultInit(porProtectedThis); - } - - // Used to avoid touching metadata for CoreLib methods. - // instance methods must pass in the 'this' object - // static methods must pass null - MethodDescCallSite(BinderMethodID id, OBJECTHANDLE hThis) : - m_pMD( - CoreLibBinder::GetMethod(id) - ), - m_methodSig(id), - m_argIt(&m_methodSig) - { - WRAPPER_NO_CONTRACT; - - DefaultInit((OBJECTREF*)hThis); - } - - // instance methods must pass in the 'this' object - // static methods must pass null - MethodDescCallSite(MethodDesc* pMD, OBJECTREF* porProtectedThis = NULL) : - m_pMD(pMD), - m_methodSig(pMD), - m_argIt(&m_methodSig) - { - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - } - CONTRACTL_END; - - if (porProtectedThis == NULL) - { - // We don't have a "this" pointer - ensure that we have activated the containing module - m_pMD->EnsureActive(); - } - - DefaultInit(porProtectedThis); - } - - // instance methods must pass in the 'this' object - // static methods must pass null - MethodDescCallSite(MethodDesc* pMD, OBJECTHANDLE hThis) : - m_pMD(pMD), - m_methodSig(pMD), - m_argIt(&m_methodSig) - { - WRAPPER_NO_CONTRACT; - - if (hThis == NULL) - { - // We don't have a "this" pointer - ensure that we have activated the containing module - m_pMD->EnsureActive(); - } - - DefaultInit((OBJECTREF*)hThis); - } - - // instance methods must pass in the 'this' object - // static methods must pass null - MethodDescCallSite(MethodDesc* pMD, LPHARDCODEDMETASIG pwzSignature, OBJECTREF* porProtectedThis = NULL) : - m_pMD(pMD), - m_methodSig(pwzSignature), - m_argIt(&m_methodSig) - { - WRAPPER_NO_CONTRACT; - - if (porProtectedThis == NULL) - { - // We don't have a "this" pointer - ensure that we have activated the containing module - m_pMD->EnsureActive(); - } - - DefaultInit(porProtectedThis); - } - - MethodDescCallSite(MethodDesc* pMD, TypeHandle th) : - m_pMD(pMD), - m_methodSig(pMD, th), - m_argIt(&m_methodSig) - { - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - } - CONTRACTL_END; - - // We don't have a "this" pointer - ensure that we have activated the containing module - m_pMD->EnsureActive(); - - DefaultInit(th); - } - // // Only use this constructor if you're certain you know where // you're going and it cannot be affected by generics/virtual diff --git a/src/coreclr/vm/ceemain.cpp b/src/coreclr/vm/ceemain.cpp index 70867dd457e08c..a5239863d6da44 100644 --- a/src/coreclr/vm/ceemain.cpp +++ b/src/coreclr/vm/ceemain.cpp @@ -194,9 +194,7 @@ #include "profilinghelper.h" #endif // PROFILING_SUPPORTED -#ifdef FEATURE_PERFMAP #include "perfmap.h" -#endif #include "diagnosticserveradapter.h" #include "eventpipeadapter.h" diff --git a/src/coreclr/vm/class.cpp b/src/coreclr/vm/class.cpp index 551c456691954b..4e228cbd4c4fef 100644 --- a/src/coreclr/vm/class.cpp +++ b/src/coreclr/vm/class.cpp @@ -1709,6 +1709,7 @@ void TypeHandle::NotifyDebuggerUnload() const MethodDesc* MethodTable::GetBoxedEntryPointMD(MethodDesc *pMD) { CONTRACT (MethodDesc *) { + MODE_PREEMPTIVE; THROWS; GC_TRIGGERS; INJECT_FAULT(COMPlusThrowOM();); @@ -1732,6 +1733,7 @@ MethodDesc* MethodTable::GetBoxedEntryPointMD(MethodDesc *pMD) MethodDesc* MethodTable::GetUnboxedEntryPointMD(MethodDesc *pMD) { CONTRACT (MethodDesc *) { + MODE_PREEMPTIVE; THROWS; GC_TRIGGERS; INJECT_FAULT(COMPlusThrowOM();); diff --git a/src/coreclr/vm/codeman.cpp b/src/coreclr/vm/codeman.cpp index 0ae31afb30ebef..24abe374d3fffe 100644 --- a/src/coreclr/vm/codeman.cpp +++ b/src/coreclr/vm/codeman.cpp @@ -41,9 +41,7 @@ #include "../debug/daccess/fntableaccess.h" #endif // HOST_64BIT -#ifdef FEATURE_PERFMAP #include "perfmap.h" -#endif // Default number of jump stubs in a jump stub block #define DEFAULT_JUMPSTUBS_PER_BLOCK 32 @@ -6237,9 +6235,7 @@ PCODE ExecutionManager::getNextJumpStub(MethodDesc* pMD, PCODE target, emitBackToBackJump(jumpStub, jumpStubRW, (void*) target); -#ifdef FEATURE_PERFMAP PerfMap::LogStubs(__FUNCTION__, "emitBackToBackJump", (PCODE)jumpStub, BACK_TO_BACK_JUMP_ALLOCATE_SIZE, PerfMapStubType::IndividualWithinBlock); -#endif // We always add the new jumpstub to the jumpStubCache // diff --git a/src/coreclr/vm/codeman.h b/src/coreclr/vm/codeman.h index dca673f271c172..8ec4e541a5c6e7 100644 --- a/src/coreclr/vm/codeman.h +++ b/src/coreclr/vm/codeman.h @@ -152,6 +152,12 @@ void ReportStubBlock(void* start, size_t size, StubCodeBlockKind kind); #ifndef FEATURE_PERFMAP inline void ReportStubBlock(void* start, size_t size, StubCodeBlockKind kind) { + CONTRACTL + { + GC_NOTRIGGER; + MODE_PREEMPTIVE; + } + CONTRACTL_END; } #endif diff --git a/src/coreclr/vm/comcallablewrapper.cpp b/src/coreclr/vm/comcallablewrapper.cpp index 3bd5be1351ff10..070e92139a95d3 100644 --- a/src/coreclr/vm/comcallablewrapper.cpp +++ b/src/coreclr/vm/comcallablewrapper.cpp @@ -2836,7 +2836,7 @@ namespace { THROWS; GC_NOTRIGGER; - MODE_ANY; + MODE_PREEMPTIVE; INJECT_FAULT(COMPlusThrowOM()); } CONTRACTL_END; diff --git a/src/coreclr/vm/comconnectionpoints.cpp b/src/coreclr/vm/comconnectionpoints.cpp index f4c60e20ea451e..09e2cef87c7196 100644 --- a/src/coreclr/vm/comconnectionpoints.cpp +++ b/src/coreclr/vm/comconnectionpoints.cpp @@ -556,14 +556,24 @@ void ConnectionPoint::InvokeProviderMethod( OBJECTREF pProvider, OBJECTREF pSubs { UnmanagedCallersOnlyCaller invokeConnectionPointProviderMethod(METHOD__STUBHELPERS__INVOKE_CONNECTION_POINT_PROVIDER_METHOD); + PCODE pProvCode; + PCODE pDlgCtorCode; + PCODE pEventMethodCode; + { + GCX_PREEMP(); + pProvCode = pProvMethodDesc->GetSingleCallableAddrOfCode(); + pDlgCtorCode = pDlgCtorMD->GetSingleCallableAddrOfCode(); + pEventMethodCode = pEventMethodDesc->GetMultiCallableAddrOfCode(); + } + // Using GetMultiCallableAddrOfCode() for the event target since it is stored for future invokes. invokeConnectionPointProviderMethod.InvokeThrowing( &pProvider, - pProvMethodDesc->GetSingleCallableAddrOfCode(), + pProvCode, &pDelegate, - pDlgCtorMD->GetSingleCallableAddrOfCode(), + pDlgCtorCode, &pSubscriber, - pEventMethodDesc->GetMultiCallableAddrOfCode()); + pEventMethodCode); } GCPROTECT_END(); } diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index ffa068c905d405..4a5c7e8da58319 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -967,7 +967,7 @@ static PCODE GetVirtualCallStub(MethodDesc *method, TypeHandle scopeType) { THROWS; GC_TRIGGERS; - MODE_ANY; + MODE_PREEMPTIVE; INJECT_FAULT(COMPlusThrowOM()); // from MetaSig::SizeOfArgStack } CONTRACTL_END; @@ -1145,13 +1145,16 @@ extern "C" BOOL QCALLTYPE Delegate_BindToMethodInfo(QCall::ObjectHandleOnStack d _ASSERTE(pInvokeMeth); // See the comment in BindToMethodName - method = - MethodDesc::FindOrCreateAssociatedMethodDesc(method, - pMethMT, - (!method->IsStatic() && pMethMT->IsValueType()), - method->GetMethodInstantiation(), - false /* do not allow code with a shared-code calling convention to be returned */, - true /* Ensure that methods on generic interfaces are returned as instantiated method descs */); + { + GCX_PREEMP(); + method = + MethodDesc::FindOrCreateAssociatedMethodDesc(method, + pMethMT, + (!method->IsStatic() && pMethMT->IsValueType()), + method->GetMethodInstantiation(), + false /* do not allow code with a shared-code calling convention to be returned */, + true /* Ensure that methods on generic interfaces are returned as instantiated method descs */); + } bool fIsOpenDelegate; if (COMDelegate::IsMethodDescCompatible((gc.refFirstArg == NULL) ? TypeHandle() : gc.refFirstArg->GetTypeHandle(), @@ -1240,33 +1243,41 @@ void COMDelegate::BindToMethod(DELEGATEREF *pRefThis, // Since this is an open delegate over a virtual method we cannot virtualize the call target now. So the shuffle thunk // needs to jump to another stub (this time provided by the VirtualStubManager) that will virtualize the call at // runtime. - PCODE pTargetCall = GetVirtualCallStub(pTargetMethod, TypeHandle(pExactMethodType)); + PCODE pTargetCall; + { + GCX_PREEMP(); + pTargetCall = GetVirtualCallStub(pTargetMethod, TypeHandle(pExactMethodType)); + } refRealDelegate->SetMethodPtrAux(pTargetCall); refRealDelegate->SetInvocationCount((INT_PTR)(void *)pTargetMethod); } else { - // Reflection or the code in BindToMethodName will pass us the unboxing stub for non-static methods on value types. But - // for open invocation on value type methods the actual reference will be passed so we need the unboxed method desc - // instead. - if (pTargetMethod->IsUnboxingStub()) + PCODE pTargetCode; { - // We want a MethodDesc which is not an unboxing stub, but is an instantiating stub if needed. - pTargetMethod = MethodDesc::FindOrCreateAssociatedMethodDesc( - pTargetMethod, - pExactMethodType, - FALSE /* don't want unboxing entry point */, - pTargetMethod->GetMethodInstantiation(), - FALSE /* don't want MD that requires inst. arguments */, - true /* Ensure that methods on generic interfaces are returned as instantiated method descs */); - } + GCX_PREEMP(); + // Reflection or the code in BindToMethodName will pass us the unboxing stub for non-static methods on value types. But + // for open invocation on value type methods the actual reference will be passed so we need the unboxed method desc + // instead. + if (pTargetMethod->IsUnboxingStub()) + { + // We want a MethodDesc which is not an unboxing stub, but is an instantiating stub if needed. + pTargetMethod = MethodDesc::FindOrCreateAssociatedMethodDesc( + pTargetMethod, + pExactMethodType, + FALSE /* don't want unboxing entry point */, + pTargetMethod->GetMethodInstantiation(), + FALSE /* don't want MD that requires inst. arguments */, + true /* Ensure that methods on generic interfaces are returned as instantiated method descs */); + } - // The method must not require any extra hidden instantiation arguments. - _ASSERTE(!pTargetMethod->RequiresInstArg()); + // The method must not require any extra hidden instantiation arguments. + _ASSERTE(!pTargetMethod->RequiresInstArg()); - // Note that it is important to cache pTargetCode in local variable to avoid GC hole. - // GetMultiCallableAddrOfCode() can trigger GC. - PCODE pTargetCode = pTargetMethod->GetMultiCallableAddrOfCode(); + // Note that it is important to cache pTargetCode in local variable to avoid GC hole. + // GetMultiCallableAddrOfCode() can trigger GC. + pTargetCode = pTargetMethod->GetMultiCallableAddrOfCode(); + } refRealDelegate->SetMethodPtrAux(pTargetCode); } } @@ -1284,16 +1295,19 @@ void COMDelegate::BindToMethod(DELEGATEREF *pRefThis, && *pRefFirstArg != NULL && pTargetMethod->GetMethodTable() != (*pRefFirstArg)->GetMethodTable()) { + GCX_PREEMP(); pTargetCode = pTargetMethod->GetMultiCallableAddrOfVirtualizedCode(pRefFirstArg, pTargetMethod->GetMethodTable()); } #ifdef HAS_THISPTR_RETBUF_PRECODE else if (pTargetMethod->IsStatic() && pTargetMethod->HasRetBuffArg() && IsRetBuffPassedAsFirstArg()) { + GCX_PREEMP(); pTargetCode = pTargetMethod->GetLoaderAllocator()->GetFuncPtrStubs()->GetFuncPtrStub(pTargetMethod, PRECODE_THISPTR_RETBUF); } #endif // HAS_THISPTR_RETBUF_PRECODE else { + GCX_PREEMP(); pTargetCode = pTargetMethod->GetMultiCallableAddrOfCode(); } _ASSERTE(pTargetCode); @@ -1354,6 +1368,7 @@ LPVOID COMDelegate::ConvertToCallback(OBJECTREF pDelegateObj) InteropSyncBlockInfo* pInteropInfo = pSyncBlock->GetInteropInfo(); + GCX_PREEMP(); pUMEntryThunk = pInteropInfo->GetUMEntryThunk(); if (!pUMEntryThunk) @@ -1363,8 +1378,6 @@ LPVOID COMDelegate::ConvertToCallback(OBJECTREF pDelegateObj) if (!pUMThunkMarshInfo) { - GCX_PREEMP(); - pUMThunkMarshInfo = (UMThunkMarshInfo*)(void*)pMT->GetLoaderAllocator()->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(DelegateUMThunkMarshInfo))); new (pUMThunkMarshInfo) DelegateUMThunkMarshInfo(pInvokeMeth); @@ -1381,15 +1394,22 @@ LPVOID COMDelegate::ConvertToCallback(OBJECTREF pDelegateObj) _ASSERTE(pUMThunkMarshInfo == pClass->m_pUMThunkMarshInfo); pUMEntryThunk = UMEntryThunkData::CreateUMEntryThunk(); + Holder umHolder; umHolder.Assign(pUMEntryThunk); - // multicast. go thru Invoke - OBJECTHANDLE objhnd = GetAppDomain()->CreateLongWeakHandle(pDelegate); - _ASSERTE(objhnd != NULL); + OBJECTHANDLE objhnd; + PCODE pManagedTargetForDiagnostics; + { + GCX_COOP(); - // This target should not ever be used. We are storing it in the thunk for better diagnostics of "call on collected delegate" crashes. - PCODE pManagedTargetForDiagnostics = (pDelegate->GetMethodPtrAux() != (PCODE)NULL) ? pDelegate->GetMethodPtrAux() : pDelegate->GetMethodPtr(); + // multicast. go thru Invoke + objhnd = GetAppDomain()->CreateLongWeakHandle(pDelegate); + _ASSERTE(objhnd != NULL); + + // This target should not ever be used. We are storing it in the thunk for better diagnostics of "call on collected delegate" crashes. + pManagedTargetForDiagnostics = (pDelegate->GetMethodPtrAux() != (PCODE)NULL) ? pDelegate->GetMethodPtrAux() : pDelegate->GetMethodPtr(); + } // MethodDesc is passed in for profiling to know the method desc of target pUMEntryThunk->LoadTimeInit( @@ -1589,13 +1609,13 @@ extern "C" void QCALLTYPE Delegate_InitializeVirtualCallStub(QCall::ObjectHandle BEGIN_QCALL; - GCX_COOP(); - MethodDesc *pMeth = NonVirtualEntry2MethodDesc((PCODE)method); _ASSERTE(pMeth); _ASSERTE(!pMeth->IsStatic() && pMeth->IsVirtual()); PCODE target = GetVirtualCallStub(pMeth, TypeHandle(pMeth->GetMethodTable())); + GCX_COOP(); + DELEGATEREF refThis = (DELEGATEREF)d.Get(); refThis->SetMethodPtrAux(target); refThis->SetInvocationCount((INT_PTR)(void*)pMeth); @@ -1603,18 +1623,12 @@ extern "C" void QCALLTYPE Delegate_InitializeVirtualCallStub(QCall::ObjectHandle END_QCALL; } -extern "C" PCODE QCALLTYPE Delegate_AdjustTarget(QCall::ObjectHandleOnStack target, PCODE method) +extern "C" PCODE QCALLTYPE Delegate_AdjustTarget(MethodTable* pMTTarg, PCODE method) { QCALL_CONTRACT; BEGIN_QCALL; - GCX_COOP(); - - _ASSERTE(method); - - MethodTable* pMTTarg = target.Get()->GetMethodTable(); - MethodDesc *pMeth = NonVirtualEntry2MethodDesc(method); _ASSERTE(pMeth); _ASSERTE(!pMeth->IsStatic()); @@ -1745,7 +1759,11 @@ extern "C" void QCALLTYPE Delegate_Construct(QCall::ObjectHandleOnStack _this, Q // set the ptr aux according to what is needed, if virtual need to call make virtual stub dispatch if (!pMeth->IsStatic() && pMeth->IsVirtual() && !pMeth->GetMethodTable()->IsValueType()) { - PCODE pTargetCall = GetVirtualCallStub(pMeth, TypeHandle(pMeth->GetMethodTable())); + PCODE pTargetCall; + { + GCX_PREEMP(); + pTargetCall = GetVirtualCallStub(pMeth, TypeHandle(pMeth->GetMethodTable())); + } refThis->SetMethodPtrAux(pTargetCall); refThis->SetInvocationCount((INT_PTR)(void *)pMeth); } @@ -1780,6 +1798,7 @@ extern "C" void QCALLTYPE Delegate_Construct(QCall::ObjectHandleOnStack _this, Q && (pMTMeth != g_pObjectClass)) { pMeth->CheckRestore(); + GCX_PREEMP(); pMeth = pMTTarg->GetBoxedEntryPointMD(pMeth); _ASSERTE(pMeth != NULL); } @@ -1789,6 +1808,7 @@ extern "C" void QCALLTYPE Delegate_Construct(QCall::ObjectHandleOnStack _this, Q // so we don't have to do all this mucking about. if (pMeth != pMethOrig) { + GCX_PREEMP(); method = pMeth->GetMultiCallableAddrOfCode(); } } @@ -2133,7 +2153,10 @@ extern "C" void QCALLTYPE Delegate_FindMethodHandle(QCall::ObjectHandleOnStack d GCX_COOP(); MethodDesc* pMD = COMDelegate::GetMethodDesc(d.Get()); - pMD = MethodDesc::FindOrCreateAssociatedMethodDescForReflection(pMD, TypeHandle(pMD->GetMethodTable()), pMD->GetMethodInstantiation()); + { + GCX_PREEMP(); + pMD = MethodDesc::FindOrCreateAssociatedMethodDescForReflection(pMD, TypeHandle(pMD->GetMethodTable()), pMD->GetMethodInstantiation()); + } retMethodInfo.Set(pMD->AllocateStubMethodInfo()); END_QCALL; diff --git a/src/coreclr/vm/comdelegate.h b/src/coreclr/vm/comdelegate.h index 1c95811d017131..a742d281ae5dcb 100644 --- a/src/coreclr/vm/comdelegate.h +++ b/src/coreclr/vm/comdelegate.h @@ -99,7 +99,7 @@ extern "C" void QCALLTYPE Delegate_Construct(QCall::ObjectHandleOnStack _this, Q extern "C" PCODE QCALLTYPE Delegate_GetMulticastInvokeSlow(MethodTable* pDelegateMT); -extern "C" PCODE QCALLTYPE Delegate_AdjustTarget(QCall::ObjectHandleOnStack target, PCODE method); +extern "C" PCODE QCALLTYPE Delegate_AdjustTarget(MethodTable* pMTTarg, PCODE method); extern "C" void QCALLTYPE Delegate_InitializeVirtualCallStub(QCall::ObjectHandleOnStack d, PCODE method); diff --git a/src/coreclr/vm/comutilnative.cpp b/src/coreclr/vm/comutilnative.cpp index 8db3217f1cb855..64723383a2ad6e 100644 --- a/src/coreclr/vm/comutilnative.cpp +++ b/src/coreclr/vm/comutilnative.cpp @@ -775,19 +775,23 @@ extern "C" void* QCALLTYPE GCInterface_GetNextFinalizableObject(QCall::ObjectHan BEGIN_QCALL; - GCX_COOP(); - - OBJECTREF target = FinalizerThread::GetNextFinalizableObject(); - - if (target != NULL) + MethodTable *pTargetMT = NULL; { - pObj.Set(target); + GCX_COOP(); - MethodTable* pMT = target->GetMethodTable(); + OBJECTREF target = FinalizerThread::GetNextFinalizableObject(); - funcPtr = pMT->GetRestoredSlot(g_pObjectFinalizerMD->GetSlot()); + if (target != NULL) + { + pObj.Set(target); + + pTargetMT = target->GetMethodTable(); + } } + if (pTargetMT != NULL) + funcPtr = pTargetMT->GetRestoredSlot(g_pObjectFinalizerMD->GetSlot()); + END_QCALL; return (void*)funcPtr; diff --git a/src/coreclr/vm/corhost.cpp b/src/coreclr/vm/corhost.cpp index 7a67425b885f75..3315af1bd20774 100644 --- a/src/coreclr/vm/corhost.cpp +++ b/src/coreclr/vm/corhost.cpp @@ -430,7 +430,11 @@ HRESULT CorHost2::ExecuteInDefaultAppDomain(LPCWSTR pwzAssemblyPath, UnmanagedCallersOnlyCaller executeInDefaultAppDomain(METHOD__ENVIRONMENT__EXECUTE_IN_DEFAULT_APP_DOMAIN); pMethodMD->EnsureActive(); - PCODE entryPoint = pMethodMD->GetSingleCallableAddrOfCode(); + PCODE entryPoint; + { + GCX_PREEMP(); + entryPoint = pMethodMD->GetSingleCallableAddrOfCode(); + } INT32 retval = executeInDefaultAppDomain.InvokeThrowing_Ret( static_cast(entryPoint), diff --git a/src/coreclr/vm/customattribute.cpp b/src/coreclr/vm/customattribute.cpp index 59c3d87f73b3d2..c505bec2b167a9 100644 --- a/src/coreclr/vm/customattribute.cpp +++ b/src/coreclr/vm/customattribute.cpp @@ -915,7 +915,15 @@ extern "C" void QCALLTYPE CustomAttribute_CreateCustomAttributeInstance( MethodDesc* pCtorMD = ((REFLECTMETHODREF)pMethod.Get())->GetMethod(); TypeHandle th = ((REFLECTCLASSBASEREF)pCaType.Get())->GetType(); - MethodDescCallSite ctorCallSite(pCtorMD, th); + PCODE pCallTarget; + + { + GCX_PREEMP(); + pCtorMD->EnsureActive(); + pCallTarget = pCtorMD->GetCallTarget(NULL, th); + } + + MethodDescCallSite ctorCallSite(pCtorMD, pCallTarget); MetaSig* pSig = ctorCallSite.GetMetaSig(); BYTE* pBlob = *ppBlob; diff --git a/src/coreclr/vm/dispatchinfo.cpp b/src/coreclr/vm/dispatchinfo.cpp index 388c4366d2e74d..fe840a99ea99c5 100644 --- a/src/coreclr/vm/dispatchinfo.cpp +++ b/src/coreclr/vm/dispatchinfo.cpp @@ -2514,13 +2514,12 @@ BOOL DispatchInfo::SynchWithManagedView() // Determine if this is the first time we synch. BOOL bFirstSynch = (m_pFirstMemberInfo == NULL); + GCX_PREEMP(); + // This method needs to be synchronized to make sure two threads don't try and // add members at the same time. CrstHolder ch(&m_lock); { - // Make sure we switch to cooperative mode before we start. - GCX_COOP(); - // Go through the list of member info's and find the end. DispatchMemberInfo **ppNextMember = &m_pFirstMemberInfo; while (*ppNextMember) @@ -2529,6 +2528,9 @@ BOOL DispatchInfo::SynchWithManagedView() // Retrieve the member info map. pMemberMap = GetMemberInfoMap(); + // Make sure we switch to cooperative mode before we start. + GCX_COOP(); + for (int cPhase = 0; cPhase < 3; cPhase++) { PTRARRAYREF MemberArrayObj = NULL; @@ -2837,13 +2839,12 @@ ComMTMemberInfoMap *DispatchInfo::GetMemberInfoMap() { THROWS; GC_TRIGGERS; - MODE_COOPERATIVE; + MODE_PREEMPTIVE; INJECT_FAULT(COMPlusThrowOM()); POSTCONDITION(CheckPointer(RETVAL)); } CONTRACT_END; - // Create the member info map. NewHolder pMemberInfoMap (new ComMTMemberInfoMap(m_pMT)); diff --git a/src/coreclr/vm/dllimportcallback.cpp b/src/coreclr/vm/dllimportcallback.cpp index e4cb9206c9160f..5c08f190499e49 100644 --- a/src/coreclr/vm/dllimportcallback.cpp +++ b/src/coreclr/vm/dllimportcallback.cpp @@ -19,9 +19,7 @@ #include "stubgen.h" #include "appdomain.inl" -#ifdef FEATURE_PERFMAP #include "perfmap.h" -#endif class UMEntryThunkFreeList { @@ -122,7 +120,7 @@ UMEntryThunkData *UMEntryThunkCache::GetUMEntryThunk(MethodDesc *pMD) { THROWS; GC_TRIGGERS; - MODE_ANY; + MODE_PREEMPTIVE; PRECONDITION(CheckPointer(pMD)); POSTCONDITION(CheckPointer(RETVAL)); } @@ -270,7 +268,7 @@ UMEntryThunkData* UMEntryThunkData::CreateUMEntryThunk() { THROWS; GC_NOTRIGGER; - MODE_ANY; + MODE_PREEMPTIVE; INJECT_FAULT(COMPlusThrowOM()); POSTCONDITION(CheckPointer(RETVAL)); } @@ -293,9 +291,7 @@ UMEntryThunkData* UMEntryThunkData::CreateUMEntryThunk() #else // !FEATURE_PORTABLE_ENTRYPOINTS pThunk = (UMEntryThunk*)pamTracker->Track(pLoaderAllocator->GetNewStubPrecodeHeap()->AllocStub()); #endif // FEATURE_PORTABLE_ENTRYPOINTS -#ifdef FEATURE_PERFMAP PerfMap::LogStubs(__FUNCTION__, "UMEntryThunk", (PCODE)pThunk, sizeof(UMEntryThunk), PerfMapStubType::IndividualWithinBlock); -#endif pData->m_pUMEntryThunk = pThunk; pThunk->Init(pThunk, dac_cast(pData), NULL, dac_cast(PRECODE_UMENTRY_THUNK)); pamTracker->SuppressRelease(); diff --git a/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h b/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h index c2d4ab066c76a9..49ce12e5b0dd3f 100644 --- a/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h +++ b/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h @@ -15,9 +15,7 @@ #include #include #include -#ifdef FEATURE_PERFMAP #include "perfmap.h" -#endif #undef DS_LOG_ALWAYS_0 #define DS_LOG_ALWAYS_0(msg) STRESS_LOG0(LF_DIAGNOSTICS_PORT, LL_ALWAYS, msg "\n") @@ -233,7 +231,9 @@ static uint32_t ds_rt_enable_perfmap (uint32_t type) { - LIMITED_METHOD_CONTRACT; + CONTRACTL{ + MODE_PREEMPTIVE; + } CONTRACTL_END; #ifdef FEATURE_PERFMAP PerfMap::PerfMapType perfMapType = (PerfMap::PerfMapType)type; diff --git a/src/coreclr/vm/fptrstubs.cpp b/src/coreclr/vm/fptrstubs.cpp index cf3f4db379f92b..f0e3a466df6bf0 100644 --- a/src/coreclr/vm/fptrstubs.cpp +++ b/src/coreclr/vm/fptrstubs.cpp @@ -78,6 +78,7 @@ PCODE FuncPtrStubs::GetFuncPtrStub(MethodDesc * pMD, PrecodeType type) { return pPrecode->GetEntryPoint(); } + GCX_PREEMP(); PCODE target = (PCODE)NULL; bool setTargetAfterAddingToHashTable = false; @@ -151,8 +152,6 @@ PCODE FuncPtrStubs::GetFuncPtrStub(MethodDesc * pMD, PrecodeType type) if (setTargetAfterAddingToHashTable) { - GCX_PREEMP(); - _ASSERTE(pMD->IsVersionableWithVtableSlotBackpatch()); PCODE temporaryEntryPoint = pMD->GetTemporaryEntryPoint(); diff --git a/src/coreclr/vm/genericdict.cpp b/src/coreclr/vm/genericdict.cpp index e9d15c0fa6bb63..ce2cfd806363f8 100644 --- a/src/coreclr/vm/genericdict.cpp +++ b/src/coreclr/vm/genericdict.cpp @@ -674,6 +674,7 @@ Dictionary::PopulateEntry( Module * pModule /* = NULL */) { CONTRACTL { + MODE_PREEMPTIVE; THROWS; GC_TRIGGERS; } CONTRACTL_END; diff --git a/src/coreclr/vm/genmeth.cpp b/src/coreclr/vm/genmeth.cpp index 62f413ada24e67..008e7cafc2dc57 100644 --- a/src/coreclr/vm/genmeth.cpp +++ b/src/coreclr/vm/genmeth.cpp @@ -170,6 +170,7 @@ static MethodDesc * FindTightlyBoundWrappedMethodDesc(MethodDesc * pMD) { CONTRACTL { + MODE_ANY; NOTHROW; GC_NOTRIGGER; PRECONDITION(CheckPointer(pMD)); @@ -326,6 +327,7 @@ InstantiatedMethodDesc::NewInstantiatedMethodDesc(MethodTable *pExactMT, { CONTRACT(InstantiatedMethodDesc*) { + MODE_PREEMPTIVE; THROWS; GC_TRIGGERS; INJECT_FAULT(COMPlusThrowOM();); @@ -545,45 +547,6 @@ InstantiatedMethodDesc::NewInstantiatedMethodDesc(MethodTable *pExactMT, RETURN pNewMD; } - -// Calling this method is equivalent to -// FindOrCreateAssociatedMethodDesc(pCanonicalMD, pExactMT, FALSE, Instantiation(), FALSE, TRUE) -// except that it also creates InstantiatedMethodDescs based on shared class methods. This is -// convenient for interop where, unlike ordinary managed methods, marshaling stubs for say Foo -// and Foo look very different and need separate representation. -InstantiatedMethodDesc* -InstantiatedMethodDesc::FindOrCreateExactClassMethod(MethodTable *pExactMT, - MethodDesc *pCanonicalMD) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - PRECONDITION(!pExactMT->IsSharedByGenericInstantiations()); - PRECONDITION(pCanonicalMD->IsSharedByGenericInstantiations()); - } - CONTRACTL_END; - - InstantiatedMethodDesc *pInstMD = FindLoadedInstantiatedMethodDesc(pExactMT, - pCanonicalMD->GetMemberDef(), - Instantiation(), - FALSE, - pCanonicalMD->IsAsyncVariantMethod()); - - if (pInstMD == NULL) - { - // create a new MD if not found - pInstMD = NewInstantiatedMethodDesc(pExactMT, - pCanonicalMD, - pCanonicalMD, - Instantiation(), - FALSE); - } - - return pInstMD; -} - #endif // !DACCESS_COMPILE // N.B. it is not guarantee that the returned InstantiatedMethodDesc is restored. @@ -756,6 +719,7 @@ MethodDesc::FindOrCreateAssociatedMethodDesc(MethodDesc* pDefMD, CONTRACT(MethodDesc*) { THROWS; + if (allowCreate) { MODE_PREEMPTIVE; } else { MODE_ANY; } if (allowCreate) { GC_TRIGGERS; } else { GC_NOTRIGGER; } if (!allowCreate) { SUPPORTS_DAC; } INJECT_FAULT(COMPlusThrowOM();); @@ -1271,6 +1235,7 @@ MethodDesc::FindOrCreateAssociatedMethodDesc(MethodDesc* pDefMD, Instantiation methodInst) { CONTRACTL { + MODE_PREEMPTIVE; THROWS; GC_TRIGGERS; // Because allowCreate is TRUE PRECONDITION(CheckPointer(pMethod)); diff --git a/src/coreclr/vm/i386/cgenx86.cpp b/src/coreclr/vm/i386/cgenx86.cpp index 8068a7ed4f1a70..fa234e073cc976 100644 --- a/src/coreclr/vm/i386/cgenx86.cpp +++ b/src/coreclr/vm/i386/cgenx86.cpp @@ -37,9 +37,7 @@ #include "stublink.inl" -#ifdef FEATURE_PERFMAP #include "perfmap.h" -#endif void UpdateRegDisplayFromCalleeSavedRegisters(REGDISPLAY * pRD, CalleeSavedRegisters * regs) { @@ -565,13 +563,9 @@ void ResumeAtJit(PCONTEXT pContext, LPVOID oldESP) size_t rxOffset = pStartRX - pStart; \ BYTE * p = pStart; -#ifdef FEATURE_PERFMAP #define BEGIN_DYNAMIC_HELPER_EMIT(size) \ BEGIN_DYNAMIC_HELPER_EMIT_WORKER(size) \ PerfMap::LogStubs(__FUNCTION__, "DynamicHelper", (PCODE)p, size, PerfMapStubType::Individual); -#else -#define BEGIN_DYNAMIC_HELPER_EMIT(size) BEGIN_DYNAMIC_HELPER_EMIT_WORKER(size) -#endif #define END_DYNAMIC_HELPER_EMIT() \ _ASSERTE(pStart + cb == p); \ diff --git a/src/coreclr/vm/interpexec.cpp b/src/coreclr/vm/interpexec.cpp index 4ef4ad40c9617f..2654d118d0de9f 100644 --- a/src/coreclr/vm/interpexec.cpp +++ b/src/coreclr/vm/interpexec.cpp @@ -3141,6 +3141,7 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr // miss, resolve the virtual method and cache it targetMethod = CallWithSEHWrapper( [&pMD, &pThisArg]() { + GCX_PREEMP(); return pMD->GetMethodDescOfVirtualizedCode(pThisArg, pMD->GetMethodTable()); }); g_InterpDispatchCache.Insert(dispatchToken, pObjMT, targetMethod, (uint16_t)dispatchTokenHash); @@ -3308,6 +3309,7 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr NULL_CHECK(*pThisArg); targetMethod = CallWithSEHWrapper( [&targetMethod, &pThisArg]() { + GCX_PREEMP(); return targetMethod->GetMethodDescOfVirtualizedCode(pThisArg, targetMethod->GetMethodTable()); }); } diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp index a71a92fc5519e4..f600727c4c238b 100644 --- a/src/coreclr/vm/jithelpers.cpp +++ b/src/coreclr/vm/jithelpers.cpp @@ -724,6 +724,7 @@ extern "C" PCODE QCALLTYPE ResolveVirtualFunctionPointer(QCall::ObjectHandleOnSt } else { + GCX_PREEMP(); // This is the new way of resolving a virtual call, including generic virtual methods. // The code is now also used by reflection, remoting etc. addr = pStaticMD->GetMultiCallableAddrOfVirtualizedCode(&objRef, staticTH); diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index c0ec22f3e75a8f..0f0e10f2572ac5 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -52,9 +52,7 @@ #endif // HAVE_GCCOVER #include "debugdebugger.h" -#ifdef FEATURE_PERFMAP #include "perfmap.h" -#endif #ifdef FEATURE_PGO #include "pgo.h" diff --git a/src/coreclr/vm/loongarch64/stubs.cpp b/src/coreclr/vm/loongarch64/stubs.cpp index fc5a820e0aca07..096d160695d435 100644 --- a/src/coreclr/vm/loongarch64/stubs.cpp +++ b/src/coreclr/vm/loongarch64/stubs.cpp @@ -14,9 +14,7 @@ #include "jitinterface.h" #include "ecall.h" -#ifdef FEATURE_PERFMAP #include "perfmap.h" -#endif #ifndef DACCESS_COMPILE //----------------------------------------------------------------------- @@ -961,13 +959,9 @@ void StubLinkerCPU::EmitCallManagedMethod(MethodDesc *pMD, BOOL fTailCall) size_t rxOffset = pStartRX - pStart; \ BYTE * p = pStart; -#ifdef FEATURE_PERFMAP #define BEGIN_DYNAMIC_HELPER_EMIT(size) \ BEGIN_DYNAMIC_HELPER_EMIT_WORKER(size) \ PerfMap::LogStubs(__FUNCTION__, "DynamicHelper", (PCODE)p, size, PerfMapStubType::Individual); -#else -#define BEGIN_DYNAMIC_HELPER_EMIT(size) BEGIN_DYNAMIC_HELPER_EMIT_WORKER(size) -#endif #define END_DYNAMIC_HELPER_EMIT() \ _ASSERTE(pStart + cb == p); \ diff --git a/src/coreclr/vm/method.cpp b/src/coreclr/vm/method.cpp index a71ea6efd1a0c2..ac0d91b15957e8 100644 --- a/src/coreclr/vm/method.cpp +++ b/src/coreclr/vm/method.cpp @@ -619,7 +619,7 @@ PCODE MethodDesc::GetMethodEntryPoint() { THROWS; GC_NOTRIGGER; - MODE_ANY; + MODE_PREEMPTIVE; SUPPORTS_DAC; } CONTRACTL_END; @@ -1602,7 +1602,6 @@ MethodDesc *MethodDesc::GetExistingWrappedMethodDesc() { THROWS; GC_NOTRIGGER; - MODE_ANY; } CONTRACTL_END; @@ -1937,6 +1936,7 @@ MethodDesc* MethodDesc::ResolveGenericVirtualMethod(OBJECTREF *orThis) { CONTRACT(MethodDesc *) { + MODE_PREEMPTIVE; THROWS; GC_TRIGGERS; @@ -1949,7 +1949,12 @@ MethodDesc* MethodDesc::ResolveGenericVirtualMethod(OBJECTREF *orThis) CONTRACT_END; // Method table of target (might be instantiated) - MethodTable *pObjMT = (*orThis)->GetMethodTable(); + MethodTable *pObjMT; + + { + GCX_COOP(); + pObjMT = (*orThis)->GetMethodTable(); + } // This is the static method descriptor describing the call. // It is not the destination of the call, which we must compute. @@ -2007,7 +2012,7 @@ PCODE MethodDesc::GetSingleCallableAddrOfCodeForUnmanagedCallersOnly() { THROWS; GC_NOTRIGGER; - MODE_ANY; + MODE_PREEMPTIVE; PRECONDITION(HasUnmanagedCallersOnlyAttribute()); } CONTRACTL_END; @@ -2028,16 +2033,22 @@ PCODE MethodDesc::GetSingleCallableAddrOfCodeForUnmanagedCallersOnly() //******************************************************************************* PCODE MethodDesc::GetSingleCallableAddrOfVirtualizedCode(OBJECTREF *orThis, TypeHandle staticTH) { - WRAPPER_NO_CONTRACT; - PRECONDITION(IsVtableMethod()); + CONTRACTL + { + THROWS; // Resolving a generic virtual method can throw + GC_TRIGGERS; + MODE_PREEMPTIVE; + } + CONTRACTL_END; - MethodTable *pObjMT = (*orThis)->GetMethodTable(); + PRECONDITION(IsVtableMethod()); + if (HasMethodInstantiation()) { CheckRestore(); MethodDesc *pResultMD = ResolveGenericVirtualMethod(orThis); - + // If we're remoting this call we can't call directly on the returned // method desc, we need to go through a stub that guarantees we end up // in the remoting handler. The stub we use below is normally just for @@ -2045,16 +2056,21 @@ PCODE MethodDesc::GetSingleCallableAddrOfVirtualizedCode(OBJECTREF *orThis, Type // where we could end up bypassing the remoting system), but it serves // our purpose here (basically pushes our correctly instantiated, // resolved method desc on the stack and calls the remoting code). - + return pResultMD->GetSingleCallableAddrOfCode(); } - + if (IsInterface()) { MethodDesc * pTargetMD = MethodTable::GetMethodDescForInterfaceMethodAndServer(staticTH,this,orThis); return pTargetMD->GetSingleCallableAddrOfCode(); } - + + MethodTable *pObjMT; + { + GCX_COOP(); + pObjMT = (*orThis)->GetMethodTable(); + } return pObjMT->GetRestoredSlot(GetSlot()); } @@ -2062,6 +2078,7 @@ MethodDesc* MethodDesc::GetMethodDescOfVirtualizedCode(OBJECTREF *orThis, TypeHa { CONTRACT(MethodDesc*) { + MODE_PREEMPTIVE; THROWS; GC_TRIGGERS; @@ -2070,8 +2087,6 @@ MethodDesc* MethodDesc::GetMethodDescOfVirtualizedCode(OBJECTREF *orThis, TypeHa POSTCONDITION(RETVAL != NULL); } CONTRACT_END; - // Method table of target (might be instantiated) - MethodTable *pObjMT = (*orThis)->GetMethodTable(); // This is the static method descriptor describing the call. // It is not the destination of the call, which we must compute. @@ -2088,6 +2103,12 @@ MethodDesc* MethodDesc::GetMethodDescOfVirtualizedCode(OBJECTREF *orThis, TypeHa RETURN(MethodTable::GetMethodDescForInterfaceMethodAndServer(staticTH, pStaticMD, orThis)); } + // Method table of target (might be instantiated) + MethodTable *pObjMT; + { + GCX_COOP(); + pObjMT = (*orThis)->GetMethodTable(); + } RETURN(pObjMT->GetMethodDescForSlot(pStaticMD->GetSlot())); } @@ -2099,6 +2120,7 @@ PCODE MethodDesc::GetMultiCallableAddrOfVirtualizedCode(OBJECTREF *orThis, TypeH { CONTRACT(PCODE) { + MODE_PREEMPTIVE; THROWS; GC_TRIGGERS; POSTCONDITION(RETVAL != NULL); @@ -2294,7 +2316,7 @@ PCODE MethodDesc::GetCallTarget(OBJECTREF* pThisObj, TypeHandle ownerType) { THROWS; // Resolving a generic virtual method can throw GC_TRIGGERS; - MODE_COOPERATIVE; + MODE_PREEMPTIVE; } CONTRACTL_END @@ -2789,7 +2811,7 @@ PCODE MethodDesc::GetTemporaryEntryPoint() { THROWS; GC_NOTRIGGER; - MODE_ANY; + MODE_PREEMPTIVE; } CONTRACTL_END; @@ -2864,7 +2886,7 @@ void MethodDesc::EnsureTemporaryEntryPointCore(AllocMemTracker *pamTracker) { THROWS; GC_NOTRIGGER; - MODE_ANY; + MODE_PREEMPTIVE; } CONTRACTL_END; diff --git a/src/coreclr/vm/method.hpp b/src/coreclr/vm/method.hpp index dc0c6b3cef2b08..efd3707e0a89d9 100644 --- a/src/coreclr/vm/method.hpp +++ b/src/coreclr/vm/method.hpp @@ -3891,9 +3891,6 @@ class InstantiatedMethodDesc final : public MethodDesc WORD m_wNumGenericArgs; public: - static InstantiatedMethodDesc *FindOrCreateExactClassMethod(MethodTable *pExactMT, - MethodDesc *pCanonicalMD); - static InstantiatedMethodDesc* FindLoadedInstantiatedMethodDesc(MethodTable *pMT, mdMethodDef methodDef, Instantiation methodInst, diff --git a/src/coreclr/vm/methodtable.cpp b/src/coreclr/vm/methodtable.cpp index 50e628b85b0cec..3ac2b398542e9c 100644 --- a/src/coreclr/vm/methodtable.cpp +++ b/src/coreclr/vm/methodtable.cpp @@ -475,7 +475,7 @@ PTR_MethodTable InterfaceInfo_t::GetApproxMethodTable(Module * pContainingModule { THROWS; GC_TRIGGERS; - MODE_COOPERATIVE; + MODE_PREEMPTIVE; PRECONDITION(CheckPointer(pItfMD)); PRECONDITION(pItfMD->IsInterface()); PRECONDITION(!ownerType.IsNull()); @@ -483,14 +483,23 @@ PTR_MethodTable InterfaceInfo_t::GetApproxMethodTable(Module * pContainingModule POSTCONDITION(CheckPointer(RETVAL)); } CONTRACT_END; - VALIDATEOBJECTREF(*pServer); +#ifdef DEBUG + { + GCX_COOP(); + VALIDATEOBJECTREF(*pServer); + } +#endif #ifdef _DEBUG MethodTable * pItfMT = ownerType.GetMethodTable(); _ASSERTE(pItfMT != NULL); #endif // _DEBUG - MethodTable *pServerMT = (*pServer)->GetMethodTable(); + MethodTable *pServerMT; + { + GCX_COOP(); + pServerMT = (*pServer)->GetMethodTable(); + } _ASSERTE(pServerMT != NULL); #ifdef FEATURE_COMINTEROP @@ -516,15 +525,19 @@ PTR_MethodTable InterfaceInfo_t::GetApproxMethodTable(Module * pContainingModule && !TypeHandle(pServerMT).CanCastTo(ownerType)) // we need to make sure object doesn't implement this interface in a natural way { TypeHandle implTypeHandle; - OBJECTREF obj = *pServer; + { + GCX_COOP(); - GCPROTECT_BEGIN(obj); - OBJECTREF implTypeRef = DynamicInterfaceCastable::GetInterfaceImplementation(&obj, ownerType); - _ASSERTE(implTypeRef != NULL); + OBJECTREF obj = *pServer; - ReflectClassBaseObject *implTypeObj = ((ReflectClassBaseObject *)OBJECTREFToObject(implTypeRef)); - implTypeHandle = implTypeObj->GetType(); - GCPROTECT_END(); + GCPROTECT_BEGIN(obj); + OBJECTREF implTypeRef = DynamicInterfaceCastable::GetInterfaceImplementation(&obj, ownerType); + _ASSERTE(implTypeRef != NULL); + + ReflectClassBaseObject *implTypeObj = ((ReflectClassBaseObject *)OBJECTREFToObject(implTypeRef)); + implTypeHandle = implTypeObj->GetType(); + GCPROTECT_END(); + } RETURN(implTypeHandle.GetMethodTable()->GetMethodDescForInterfaceMethod(ownerType, pItfMD, TRUE /* throwOnConflict */)); } @@ -542,7 +555,7 @@ MethodDesc *MethodTable::GetMethodDescForComInterfaceMethod(MethodDesc *pItfMD) { THROWS; GC_TRIGGERS; - MODE_COOPERATIVE; + MODE_PREEMPTIVE; PRECONDITION(CheckPointer(pItfMD)); PRECONDITION(pItfMD->IsInterface()); PRECONDITION(IsComObjectType()); @@ -3537,7 +3550,11 @@ BOOL MethodTable::RunClassInitEx(OBJECTREF *pThrowable) MethodTable * pCanonMT = GetCanonicalMethodTable(); // Call the code method without touching MethodDesc if possible - PCODE pCctorCode = pCanonMT->GetRestoredSlot(pCanonMT->GetClassConstructorSlot()); + PCODE pCctorCode; + { + GCX_PREEMP(); + pCctorCode = pCanonMT->GetRestoredSlot(pCanonMT->GetClassConstructorSlot()); + } MethodTable* instantiatingArg = pCanonMT->IsSharedByGenericInstantiations() ? this : nullptr; UnmanagedCallersOnlyCaller caller(METHOD__INITHELPERS__CALLCLASSCONSTRUCTOR); caller.InvokeThrowing(pCctorCode, instantiatingArg); @@ -7782,7 +7799,7 @@ PCODE MethodTable::GetRestoredSlot(DWORD slotNumber) CONTRACTL { THROWS; GC_NOTRIGGER; - MODE_ANY; + MODE_PREEMPTIVE; SUPPORTS_DAC; } CONTRACTL_END; diff --git a/src/coreclr/vm/methodtable.inl b/src/coreclr/vm/methodtable.inl index 5bd6ddf711b680..e6b343e86a2e63 100644 --- a/src/coreclr/vm/methodtable.inl +++ b/src/coreclr/vm/methodtable.inl @@ -407,7 +407,7 @@ inline MethodDesc* MethodTable::GetMethodDescForSlot(DWORD slot) { THROWS; GC_NOTRIGGER; - MODE_ANY; + MODE_PREEMPTIVE; } CONTRACTL_END; diff --git a/src/coreclr/vm/perfmap.h b/src/coreclr/vm/perfmap.h index 4dc23f65e107db..7e2012b07d7caa 100644 --- a/src/coreclr/vm/perfmap.h +++ b/src/coreclr/vm/perfmap.h @@ -19,6 +19,52 @@ enum class PerfMapStubType Individual }; +#ifndef FEATURE_PERFMAP + +class PerfMap +{ +public: + static bool IsEnabled() + { +#ifdef DEBUG + return true; +#else + return false; +#endif + } + static void LogJITCompiledMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize, PrepareCodeConfig *pConfig) + { + CONTRACTL + { + THROWS; + MODE_PREEMPTIVE; + } + CONTRACTL_END; + } + + static void LogPreCompiledMethod(MethodDesc * pMethod, PCODE pCode) + { + CONTRACTL + { + THROWS; + MODE_PREEMPTIVE; + } + CONTRACTL_END; + } + + static void LogStubs(const char* stubType, const char* stubOwner, PCODE pCode, size_t codeSize, PerfMapStubType stubAllocationType) + { + CONTRACTL + { + GC_NOTRIGGER; + MODE_PREEMPTIVE; + } + CONTRACTL_END; + } +}; + +#else // FEATURE_PERFMAP + class PerfMap { private: @@ -112,4 +158,5 @@ class PerfMap static bool LowGranularityStubs() { return !s_IndividualAllocationStubReporting; } }; +#endif // FEATURE_PERFMAP #endif // PERFPID_H diff --git a/src/coreclr/vm/precode.cpp b/src/coreclr/vm/precode.cpp index 6b72dee83957bc..e62556c72e9bda 100644 --- a/src/coreclr/vm/precode.cpp +++ b/src/coreclr/vm/precode.cpp @@ -15,9 +15,7 @@ #include #endif // FEATURE_INTERPRETER -#ifdef FEATURE_PERFMAP #include "perfmap.h" -#endif InterleavedLoaderHeapConfig s_stubPrecodeHeapConfig; #ifdef HAS_FIXUP_PRECODE @@ -253,9 +251,7 @@ InterpreterPrecode* Precode::AllocateInterpreterPrecode(PCODE byteCode, FlushCacheForDynamicMappedStub(pPrecode, sizeof(InterpreterPrecode)); -#ifdef FEATURE_PERFMAP PerfMap::LogStubs(__FUNCTION__, "UMEntryThunk", (PCODE)pPrecode, sizeof(InterpreterPrecode), PerfMapStubType::IndividualWithinBlock); -#endif return pPrecode; } #endif // FEATURE_INTERPRETER @@ -288,9 +284,7 @@ Precode* Precode::Allocate(PrecodeType t, MethodDesc* pMD, // to see the actual final Target (which doesn't require any further synchronization), or we'll hit the memory // barrier in the second portion of the FixupPrecodeThunk and find that the MethodDesc/PrecodeFixupThunk are // properly set. See FixupPrecode::GenerateDataPage for the code to fill in the target. -#ifdef FEATURE_PERFMAP PerfMap::LogStubs(__FUNCTION__, "FixupPrecode", (PCODE)pPrecode, sizeof(FixupPrecode), PerfMapStubType::IndividualWithinBlock); -#endif } #ifdef HAS_THISPTR_RETBUF_PRECODE else if (t == PRECODE_THISPTR_RETBUF) @@ -302,9 +296,7 @@ Precode* Precode::Allocate(PrecodeType t, MethodDesc* pMD, FlushCacheForDynamicMappedStub(pPrecode, sizeof(ThisPtrRetBufPrecode)); -#ifdef FEATURE_PERFMAP PerfMap::LogStubs(__FUNCTION__, "ThisPtrRetBuf", (PCODE)pPrecode, sizeof(ThisPtrRetBufPrecodeData), PerfMapStubType::IndividualWithinBlock); -#endif } #endif // HAS_THISPTR_RETBUF_PRECODE else @@ -315,9 +307,7 @@ Precode* Precode::Allocate(PrecodeType t, MethodDesc* pMD, FlushCacheForDynamicMappedStub(pPrecode, sizeof(StubPrecode)); -#ifdef FEATURE_PERFMAP PerfMap::LogStubs(__FUNCTION__, t == PRECODE_STUB ? "StubPrecode" : "PInvokeImportPrecode", (PCODE)pPrecode, sizeof(StubPrecode), PerfMapStubType::IndividualWithinBlock); -#endif } return pPrecode; diff --git a/src/coreclr/vm/prestub.cpp b/src/coreclr/vm/prestub.cpp index d4220ae0185414..e3b6e43edaab1e 100644 --- a/src/coreclr/vm/prestub.cpp +++ b/src/coreclr/vm/prestub.cpp @@ -33,9 +33,7 @@ #include "clrtocomcall.h" #endif -#ifdef FEATURE_PERFMAP #include "perfmap.h" -#endif #include "methoddescbackpatchinfo.h" @@ -371,10 +369,8 @@ PCODE MethodDesc::PrepareCode(PrepareCodeConfig* pConfig) pCode = GetPrecompiledCode(pConfig, shouldTier); } -#ifdef FEATURE_PERFMAP if (pCode != (PCODE)NULL) PerfMap::LogPreCompiledMethod(this, pCode); -#endif } if (pConfig->IsForMulticoreJit() && pCode == (PCODE)NULL && pConfig->ReadyToRunRejectedPrecompiledCode()) @@ -876,10 +872,8 @@ PCODE MethodDesc::JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, J } #endif // PROFILING_SUPPORTED -#ifdef FEATURE_PERFMAP // Save the JIT'd method information so that perf can resolve JIT'd call frames. PerfMap::LogJITCompiledMethod(this, pCode, sizeOfCode, pConfig); -#endif // The notification will only occur if someone has registered for this method. DACNotifyCompilationFinished(this, pCode); @@ -2871,14 +2865,12 @@ EXTERN_C PCODE STDCALL ExternalMethodFixupWorker(TransitionBlock * pTransitionBl if (fVirtual) { - GCX_COOP_THREAD_EXISTS(CURRENT_THREAD); - // Get the stub manager for this module VirtualCallStubManager *pMgr = pModule->GetLoaderAllocator()->GetVirtualCallStubManager(); OBJECTREF *protectedObj = pEMFrame->GetThisPtr(); _ASSERTE(protectedObj != NULL); - if (*protectedObj == NULL) { + if (!*protectedObj) { COMPlusThrow(kNullReferenceException); } @@ -2917,6 +2909,8 @@ EXTERN_C PCODE STDCALL ExternalMethodFixupWorker(TransitionBlock * pTransitionBl #endif } + GCX_COOP_THREAD_EXISTS(CURRENT_THREAD); + // We lost the race or the R2R image was generated without cached interface dispatch support, simply do the resolution in pure C++ DispatchToken token; if (pMT->IsInterface()) @@ -2942,6 +2936,7 @@ EXTERN_C PCODE STDCALL ExternalMethodFixupWorker(TransitionBlock * pTransitionBl token = pMT->GetLoaderAllocator()->GetDispatchToken(pMT->GetTypeID(), slot); StubCallSite callSite(pIndirection, pEMFrame->GetReturnAddress()); + GCX_COOP_THREAD_EXISTS(CURRENT_THREAD); pCode = pMgr->ResolveWorker(&callSite, protectedObj, token, STUB_CODE_BLOCK_VSD_LOOKUP_STUB); } else @@ -3764,6 +3759,8 @@ extern "C" SIZE_T STDCALL DynamicHelperWorker(TransitionBlock * pTransitionBlock if (objRef == NULL) COMPlusThrow(kNullReferenceException); + GCX_PREEMP(); + // Duplicated logic from JIT_VirtualFunctionPointer_Framed if (!pMD->IsVtableMethod()) { diff --git a/src/coreclr/vm/qcall.h b/src/coreclr/vm/qcall.h index 079f93780d40df..6cf2a33975c226 100644 --- a/src/coreclr/vm/qcall.h +++ b/src/coreclr/vm/qcall.h @@ -194,6 +194,12 @@ class QCall { Object** m_ppObject; + bool IsNull() const + { + LIMITED_METHOD_CONTRACT; + return *m_ppObject == NULL; + } + OBJECTREF Get() { LIMITED_METHOD_CONTRACT; diff --git a/src/coreclr/vm/readytoruninfo.cpp b/src/coreclr/vm/readytoruninfo.cpp index ee9ca4fd3dec65..444e6afea845d2 100644 --- a/src/coreclr/vm/readytoruninfo.cpp +++ b/src/coreclr/vm/readytoruninfo.cpp @@ -20,9 +20,7 @@ #include "ilstubcache.h" #include "sigbuilder.h" -#ifdef FEATURE_PERFMAP #include "perfmap.h" -#endif #ifndef DACCESS_COMPILE extern "C" PCODE g_pMethodWithSlotAndModule; @@ -2533,9 +2531,7 @@ PCODE CreateDynamicHelperPrecode(LoaderAllocator *pAllocator, AllocMemTracker *p FlushCacheForDynamicMappedStub(pPrecode, sizeof(StubPrecode)); -#ifdef FEATURE_PERFMAP PerfMap::LogStubs(__FUNCTION__, "DynamicHelper", (PCODE)pPrecode, size, PerfMapStubType::IndividualWithinBlock); -#endif return ((Precode*)pPrecode)->GetEntryPoint(); } diff --git a/src/coreclr/vm/reflectioninvocation.cpp b/src/coreclr/vm/reflectioninvocation.cpp index 3b0b32dd32ec20..2b623fb397ae22 100644 --- a/src/coreclr/vm/reflectioninvocation.cpp +++ b/src/coreclr/vm/reflectioninvocation.cpp @@ -443,13 +443,16 @@ extern "C" void QCALLTYPE RuntimeMethodHandle_InvokeMethod( // This is duplicated logic from MethodDesc::GetCallTarget PCODE pTarget; - if (pMeth->IsVtableMethod()) { - pTarget = pMeth->GetSingleCallableAddrOfVirtualizedCode(&gc.target, ownerType); - } - else - { - pTarget = pMeth->GetSingleCallableAddrOfCode(); + GCX_PREEMP(); + if (pMeth->IsVtableMethod()) + { + pTarget = pMeth->GetSingleCallableAddrOfVirtualizedCode(&gc.target, ownerType); + } + else + { + pTarget = pMeth->GetSingleCallableAddrOfCode(); + } } callDescrData.pTarget = pTarget; diff --git a/src/coreclr/vm/riscv64/stubs.cpp b/src/coreclr/vm/riscv64/stubs.cpp index 9064d3f844f5fd..10571d08e5ca19 100644 --- a/src/coreclr/vm/riscv64/stubs.cpp +++ b/src/coreclr/vm/riscv64/stubs.cpp @@ -14,9 +14,7 @@ #include "jitinterface.h" #include "ecall.h" -#ifdef FEATURE_PERFMAP #include "perfmap.h" -#endif #ifndef DACCESS_COMPILE //----------------------------------------------------------------------- @@ -1027,13 +1025,9 @@ void StubLinkerCPU::EmitCallManagedMethod(MethodDesc *pMD, BOOL fTailCall) size_t rxOffset = pStartRX - pStart; \ BYTE * p = pStart; -#ifdef FEATURE_PERFMAP #define BEGIN_DYNAMIC_HELPER_EMIT(size) \ BEGIN_DYNAMIC_HELPER_EMIT_WORKER(size) \ PerfMap::LogStubs(__FUNCTION__, "DynamicHelper", (PCODE)p, size, PerfMapStubType::Individual); -#else -#define BEGIN_DYNAMIC_HELPER_EMIT(size) BEGIN_DYNAMIC_HELPER_EMIT_WORKER(size) -#endif #define END_DYNAMIC_HELPER_EMIT() \ _ASSERTE(pStart + cb == p); \ diff --git a/src/coreclr/vm/runtimehandles.cpp b/src/coreclr/vm/runtimehandles.cpp index 1e1fb0c0222cae..0857ebee305668 100644 --- a/src/coreclr/vm/runtimehandles.cpp +++ b/src/coreclr/vm/runtimehandles.cpp @@ -1947,22 +1947,23 @@ extern "C" MethodDesc* QCALLTYPE RuntimeMethodHandle_GetStubIfNeededSlow(MethodD BEGIN_QCALL; - GCX_COOP(); + TypeHandle* inst = NULL; + DWORD ntypars = 0; + if (pMethod->IsAsyncVariantMethod()) { // do not report async variants to reflection. pMethod = pMethod->GetOrdinaryVariant(/*allowInstParam*/ false); } - + TypeHandle instType = declaringTypeHandle.AsTypeHandle(); - - TypeHandle* inst = NULL; - DWORD ntypars = 0; - + // Construct TypeHandle array for instantiation. - if (methodInstantiation.Get() != NULL) + if (!methodInstantiation.IsNull()) { + GCX_COOP(); + ntypars = ((PTRARRAYREF)methodInstantiation.Get())->GetNumComponents(); size_t size = ntypars * sizeof(TypeHandle); @@ -2037,7 +2038,10 @@ extern "C" void QCALLTYPE RuntimeMethodHandle_GetMethodBody(MethodDesc* pMethod, { MethodDesc* pMethodIL = pMethod; if (pMethod->IsWrapperStub()) + { + GCX_PREEMP(); pMethodIL = pMethod->GetWrappedMethodDesc(); + } pILHeader = pMethodIL->GetILHeader(); } diff --git a/src/coreclr/vm/stublink.cpp b/src/coreclr/vm/stublink.cpp index 972d5d487007ca..86c24647bb6aaa 100644 --- a/src/coreclr/vm/stublink.cpp +++ b/src/coreclr/vm/stublink.cpp @@ -16,9 +16,7 @@ #include "rtlfunctions.h" -#ifdef FEATURE_PERFMAP #include "perfmap.h" -#endif #define S_BYTEPTR(x) S_SIZE_T((SIZE_T)(x)) @@ -579,9 +577,7 @@ Stub *StubLinker::Link(LoaderHeap *pHeap, DWORD flags, const char *stubType) EmitStub(pStub, globalsize, size, pHeap); -#ifdef FEATURE_PERFMAP PerfMap::LogStubs(__FUNCTION__, stubType, pStub->GetEntryPoint(), pStub->GetNumCodeBytes(), PerfMapStubType::Individual); -#endif return pStub.Detach(); } diff --git a/src/coreclr/vm/threads.cpp b/src/coreclr/vm/threads.cpp index e820c8678586e0..1fa70acc931304 100644 --- a/src/coreclr/vm/threads.cpp +++ b/src/coreclr/vm/threads.cpp @@ -51,9 +51,7 @@ #include #endif -#ifdef FEATURE_PERFMAP #include "perfmap.h" -#endif #include "exinfo.h" @@ -1028,13 +1026,13 @@ void InitThreadManagerPerfMapData() GC_TRIGGERS; } CONTRACTL_END; -#ifdef FEATURE_PERFMAP +#ifndef FEATURE_PORTABLE_HELPERS if (IsWriteBarrierCopyEnabled()) { size_t writeBarrierSize = (BYTE*)JIT_PatchedCodeLast - (BYTE*)JIT_PatchedCodeStart; PerfMap::LogStubs(__FUNCTION__, "JIT_CopiedWriteBarriers", (PCODE)s_barrierCopy, writeBarrierSize, PerfMapStubType::Individual); } -#endif +#endif // !FEATURE_PORTABLE_HELPERS } //--------------------------------------------------------------------------- diff --git a/src/coreclr/vm/virtualcallstub.cpp b/src/coreclr/vm/virtualcallstub.cpp index e4e616315e9e3f..7404ca72acbd92 100644 --- a/src/coreclr/vm/virtualcallstub.cpp +++ b/src/coreclr/vm/virtualcallstub.cpp @@ -10,9 +10,7 @@ #include "comdelegate.h" #include -#ifdef FEATURE_PERFMAP #include "perfmap.h" -#endif #ifndef DACCESS_COMPILE @@ -100,11 +98,23 @@ struct CachedIndirectionCellBlockListNode BYTE* GenerateDispatchStubCellEntryMethodDesc(LoaderAllocator *pLoaderAllocator, TypeHandle ownerType, MethodDesc *pMD, LCGMethodResolver *pResolver) { + CONTRACTL { + THROWS; + GC_TRIGGERS; + MODE_PREEMPTIVE; + } CONTRACTL_END; + return GenerateDispatchStubCellEntrySlot(pLoaderAllocator, ownerType, pMD->GetSlot(), pResolver); } BYTE* GenerateDispatchStubCellEntrySlot(LoaderAllocator *pLoaderAllocator, TypeHandle ownerType, int methodSlot, LCGMethodResolver *pResolver) { + CONTRACTL { + THROWS; + GC_TRIGGERS; + MODE_PREEMPTIVE; + } CONTRACTL_END; + VirtualCallStubManager * pMgr = pLoaderAllocator->GetVirtualCallStubManager(); DispatchToken token = VirtualCallStubManager::GetTokenFromOwnerAndSlot(ownerType, methodSlot); @@ -994,7 +1004,7 @@ DispatchToken VirtualCallStubManager::GetTokenFromOwnerAndSlot(TypeHandle ownerT { THROWS; GC_TRIGGERS; - MODE_ANY; + MODE_PREEMPTIVE; INJECT_FAULT(COMPlusThrowOM();); } CONTRACTL_END @@ -1017,7 +1027,7 @@ PCODE VirtualCallStubManager::GetCallStub(TypeHandle ownerType, MethodDesc *pMD) CONTRACTL { THROWS; GC_TRIGGERS; - MODE_ANY; + MODE_PREEMPTIVE; PRECONDITION(CheckPointer(pMD)); PRECONDITION(!pMD->IsInterface() || ownerType.GetMethodTable()->HasSameTypeDefAs(pMD->GetMethodTable())); INJECT_FAULT(COMPlusThrowOM();); @@ -1051,7 +1061,19 @@ PCODE VirtualCallStubManager::GetCallStub(DispatchToken token) { if ((stub = (PCODE)(lookups->Find(&probeL))) == CALL_STUB_EMPTY_ENTRY) { - LookupHolder *pLookupHolder = GenerateLookupStub(addrOfResolver, token.To_SIZE_T()); + LookupHolder *pLookupHolder; + bool reenteredCooperativeGCMode = PerfMap::IsEnabled(); + { + GCX_MAYBE_PREEMP(reenteredCooperativeGCMode); + pLookupHolder = GenerateLookupStub(addrOfResolver, token.To_SIZE_T()); + } + + if (reenteredCooperativeGCMode) + { + // The prober may have been invalidated by reentering cooperative GC mode, reset it + BOOL success = lookups->SetUpProber(token.To_SIZE_T(), 0, &probeL); + _ASSERTE(success); + } stub = (PCODE) (lookups->Add((size_t)(pLookupHolder->stub()->entryPoint()), &probeL)); } } @@ -1082,7 +1104,20 @@ PCODE VirtualCallStubManager::GetVTableCallStub(DWORD slot) { if ((stub = (PCODE)(vtableCallers->Find(&probe))) == CALL_STUB_EMPTY_ENTRY) { - VTableCallHolder *pHolder = GenerateVTableCallStub(slot); + VTableCallHolder *pHolder; + + bool reenteredCooperativeGCMode = PerfMap::IsEnabled(); + { + GCX_MAYBE_PREEMP(reenteredCooperativeGCMode); + pHolder = GenerateVTableCallStub(slot); + } + + if (reenteredCooperativeGCMode) + { + // The prober may have been invalidated by reentering cooperative GC mode, reset it + BOOL success = vtableCallers->SetUpProber(DispatchToken::CreateDispatchToken(slot).To_SIZE_T(), 0, &probe); + _ASSERTE(success); + } stub = (PCODE)(vtableCallers->Add((size_t)(pHolder->stub()->entryPoint()), &probe)); } } @@ -1115,9 +1150,7 @@ VTableCallHolder* VirtualCallStubManager::GenerateVTableCallStub(DWORD slot) LOG((LF_STUBS, LL_INFO10000, "GenerateVTableCallStub for slot " FMT_ADDR "at" FMT_ADDR "\n", DBG_ADDR(slot), DBG_ADDR(pHolder->stub()))); -#ifdef FEATURE_PERFMAP PerfMap::LogStubs(__FUNCTION__, "GenerateVTableCallStub", (PCODE)pHolder->stub(), pHolder->stub()->size(), PerfMapStubType::IndividualWithinBlock); -#endif RETURN(pHolder); } @@ -1461,7 +1494,12 @@ extern "C" PCODE CID_VirtualOpenDelegateDispatchWorker(TransitionBlock * pTransi GCStress::MaybeTriggerAndProtect(pObj); - DispatchToken token = VirtualCallStubManager::GetTokenFromOwnerAndSlot(TypeHandle(pTargetMD->GetMethodTable()), pTargetMD->GetSlot()); + DispatchToken token; + + { + GCX_PREEMP(); + token = VirtualCallStubManager::GetTokenFromOwnerAndSlot(TypeHandle(pTargetMD->GetMethodTable()), pTargetMD->GetSlot()); + } target = CachedInterfaceDispatchResolveWorker(NULL, protectedObj, token); #if _DEBUG @@ -2054,14 +2092,24 @@ PCODE VirtualCallStubManager::ResolveWorker(StubCallSite* pCallSite, } #endif // TARGET_X86 && !UNIX_X86_ABI - pResolveHolder = GenerateResolveStub(pResolverFcn, - pBackPatchFcn, - token.To_SIZE_T() + bool reenteredCooperativeGCMode = PerfMap::IsEnabled(); + { + GCX_MAYBE_PREEMP(reenteredCooperativeGCMode); + pResolveHolder = GenerateResolveStub(pResolverFcn, + pBackPatchFcn, + token.To_SIZE_T() #if defined(TARGET_X86) && !defined(UNIX_X86_ABI) - , stackArgumentsSize + , stackArgumentsSize #endif ); + } + if (reenteredCooperativeGCMode) + { + // The prober may have been invalidated by reentering cooperative GC mode, reset it + BOOL success = resolvers->SetUpProber(token.To_SIZE_T(), 0, &probeR); + _ASSERTE(success); + } // Add the resolve entrypoint into the cache. //@TODO: Can we store a pointer to the holder rather than the entrypoint? resolvers->Add((size_t)(pResolveHolder->stub()->resolveEntryPoint()), &probeR); @@ -2095,9 +2143,12 @@ PCODE VirtualCallStubManager::ResolveWorker(StubCallSite* pCallSite, if (addrOfDispatch == CALL_STUB_EMPTY_ENTRY) { PCODE addrOfFail = pResolveHolder->stub()->failEntryPoint(); - bool reenteredCooperativeGCMode = false; - pDispatchHolder = GenerateDispatchStub( - target, addrOfFail, objectType, token.To_SIZE_T(), &reenteredCooperativeGCMode); + bool reenteredCooperativeGCMode = PerfMap::IsEnabled(); + { + GCX_MAYBE_PREEMP(reenteredCooperativeGCMode); + pDispatchHolder = GenerateDispatchStub( + target, addrOfFail, objectType, token.To_SIZE_T(), &reenteredCooperativeGCMode); + } if (reenteredCooperativeGCMode) { // The prober may have been invalidated by reentering cooperative GC mode, reset it @@ -2208,9 +2259,12 @@ PCODE VirtualCallStubManager::ResolveWorker(StubCallSite* pCallSite, // so we may have to create it now ResolveHolder* pResolveHolder = ResolveHolder::FromResolveEntry(pCallSite->GetSiteTarget()); PCODE addrOfFail = pResolveHolder->stub()->failEntryPoint(); - bool reenteredCooperativeGCMode = false; - pDispatchHolder = GenerateDispatchStub( - target, addrOfFail, objectType, token.To_SIZE_T(), &reenteredCooperativeGCMode); + bool reenteredCooperativeGCMode = PerfMap::IsEnabled(); + { + GCX_MAYBE_PREEMP(reenteredCooperativeGCMode); + pDispatchHolder = GenerateDispatchStub( + target, addrOfFail, objectType, token.To_SIZE_T(), &reenteredCooperativeGCMode); + } if (reenteredCooperativeGCMode) { // The prober may have been invalidated by reentering cooperative GC mode, reset it @@ -2799,7 +2853,6 @@ DispatchHolder *VirtualCallStubManager::GenerateDispatchStub(PCODE ad PRECONDITION(addrOfFail != NULL); PRECONDITION(CheckPointer(pMTExpected)); PRECONDITION(pMayHaveReenteredCooperativeGCMode != nullptr); - PRECONDITION(!*pMayHaveReenteredCooperativeGCMode); POSTCONDITION(CheckPointer(RETVAL)); } CONTRACT_END; @@ -2862,9 +2915,7 @@ DispatchHolder *VirtualCallStubManager::GenerateDispatchStub(PCODE ad LOG((LF_STUBS, LL_INFO10000, "GenerateDispatchStub for token" FMT_ADDR "and pMT" FMT_ADDR "at" FMT_ADDR "\n", DBG_ADDR(dispatchToken), DBG_ADDR(pMTExpected), DBG_ADDR(holder->stub()))); -#ifdef FEATURE_PERFMAP PerfMap::LogStubs(__FUNCTION__, "GenerateDispatchStub", (PCODE)holder->stub(), holder->stub()->size(), PerfMapStubType::IndividualWithinBlock); -#endif RETURN (holder); } @@ -2888,7 +2939,6 @@ DispatchHolder *VirtualCallStubManager::GenerateDispatchStubLong(PCODE PRECONDITION(addrOfFail != NULL); PRECONDITION(CheckPointer(pMTExpected)); PRECONDITION(pMayHaveReenteredCooperativeGCMode != nullptr); - PRECONDITION(!*pMayHaveReenteredCooperativeGCMode); POSTCONDITION(CheckPointer(RETVAL)); } CONTRACT_END; @@ -2923,9 +2973,7 @@ DispatchHolder *VirtualCallStubManager::GenerateDispatchStubLong(PCODE LOG((LF_STUBS, LL_INFO10000, "GenerateDispatchStub for token" FMT_ADDR "and pMT" FMT_ADDR "at" FMT_ADDR "\n", DBG_ADDR(dispatchToken), DBG_ADDR(pMTExpected), DBG_ADDR(holder->stub()))); -#ifdef FEATURE_PERFMAP PerfMap::LogStubs(__FUNCTION__, "GenerateDispatchStub", (PCODE)holder->stub(), holder->stub()->size(), PerfMapStubType::IndividualWithinBlock); -#endif RETURN (holder); } @@ -3021,9 +3069,7 @@ ResolveHolder *VirtualCallStubManager::GenerateResolveStub(PCODE addr LOG((LF_STUBS, LL_INFO10000, "GenerateResolveStub for token" FMT_ADDR "at" FMT_ADDR "\n", DBG_ADDR(dispatchToken), DBG_ADDR(holder->stub()))); -#ifdef FEATURE_PERFMAP PerfMap::LogStubs(__FUNCTION__, "GenerateResolveStub", (PCODE)holder->stub(), holder->stub()->size(), PerfMapStubType::IndividualWithinBlock); -#endif RETURN (holder); } @@ -3054,9 +3100,7 @@ LookupHolder *VirtualCallStubManager::GenerateLookupStub(PCODE addrOfResolver, s LOG((LF_STUBS, LL_INFO10000, "GenerateLookupStub for token" FMT_ADDR "at" FMT_ADDR "\n", DBG_ADDR(dispatchToken), DBG_ADDR(holder->stub()))); -#ifdef FEATURE_PERFMAP PerfMap::LogStubs(__FUNCTION__, "GenerateLookupStub", (PCODE)holder->stub(), holder->stub()->size(), PerfMapStubType::IndividualWithinBlock); -#endif RETURN (holder); } @@ -3084,8 +3128,12 @@ ResolveCacheElem *VirtualCallStubManager::GenerateResolveCacheElem(void *addrOfC CONSISTENCY_CHECK(CheckPointer(pMTExpected)); //allocate from the requisite heap and set the appropriate fields - ResolveCacheElem *e = (ResolveCacheElem*) (void*) + ResolveCacheElem *e; + { + GCX_NOTRIGGER(); + e = (ResolveCacheElem*) (void*) cache_entry_heap->AllocAlignedMem(sizeof(ResolveCacheElem), CODE_SIZE_ALIGN); + } e->pMT = pMTExpected; e->token = token;