Skip to content

Commit 1555020

Browse files
am11jkotas
andauthored
Convert throw and thread helpers to UCO (#126582)
Contributes to prio3 from #123864 --------- Co-authored-by: Jan Kotas <jkotas@microsoft.com>
1 parent 2383f46 commit 1555020

File tree

11 files changed

+199
-150
lines changed

11 files changed

+199
-150
lines changed

src/coreclr/System.Private.CoreLib/src/System/GC.CoreCLR.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,8 @@ public static int GetGeneration(WeakReference wo)
312312
[RequiresUnsafe]
313313
private static unsafe partial void* GetNextFinalizeableObject(ObjectHandleOnStack target);
314314

315+
[UnmanagedCallersOnly]
316+
[RequiresUnsafe]
315317
private static unsafe uint RunFinalizers()
316318
{
317319
Thread currentThread = Thread.CurrentThread;
@@ -336,6 +338,7 @@ private static unsafe uint RunFinalizers()
336338
currentThread.ResetFinalizerThread();
337339
count++;
338340
}
341+
339342
return count;
340343
}
341344

src/coreclr/System.Private.CoreLib/src/System/Threading/Thread.CoreCLR.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,19 +112,20 @@ private unsafe void StartCore()
112112
[RequiresUnsafe]
113113
private static unsafe partial Interop.BOOL StartInternal(ThreadHandle t, int stackSize, int priority, Interop.BOOL isThreadPool, char* pThreadName, ObjectHandleOnStack exception);
114114

115-
// Called from the runtime
116-
private void StartCallback()
115+
[UnmanagedCallersOnly]
116+
[RequiresUnsafe]
117+
private static unsafe void StartCallback(Thread* pThread)
117118
{
118-
StartHelper? startHelper = _startHelper;
119+
StartHelper? startHelper = pThread->_startHelper;
119120
Debug.Assert(startHelper != null);
120-
_startHelper = null;
121+
pThread->_startHelper = null;
121122

122123
startHelper.Run();
123124

124125
// When this thread is about to exit, inform any subsystems that need to know.
125126
// For external threads that have been attached to the runtime, we'll call this
126127
// after the thread has been detached as it won't come through this path.
127-
OnThreadExited();
128+
pThread->OnThreadExited();
128129
}
129130

130131
// Max iterations to be done in SpinWait without switching GC modes.

src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionHandling.cs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -578,12 +578,18 @@ internal object ThrownException
578578
//
579579
// Called by RhpThrowHwEx
580580
//
581+
[StackTraceHidden]
581582
#if NATIVEAOT
582583
[RuntimeExport("RhThrowHwEx")]
583-
#endif
584-
[StackTraceHidden]
585584
public static void RhThrowHwEx(uint exceptionCode, ref ExInfo exInfo)
585+
#else
586+
[UnmanagedCallersOnly]
587+
internal static void RhThrowHwEx(uint exceptionCode, ExInfo* pExInfo)
588+
#endif
586589
{
590+
#if !NATIVEAOT
591+
ref ExInfo exInfo = ref *pExInfo;
592+
#endif
587593
#if NATIVEAOT
588594
// trigger a GC (only if gcstress) to ensure we can stackwalk at this point
589595
GCStress.TriggerGC();
@@ -661,12 +667,19 @@ public static void RhThrowHwEx(uint exceptionCode, ref ExInfo exInfo)
661667

662668
private const uint MaxTryRegionIdx = 0xFFFFFFFFu;
663669

670+
[StackTraceHidden]
664671
#if NATIVEAOT
665672
[RuntimeExport("RhThrowEx")]
666-
#endif
667-
[StackTraceHidden]
668673
public static void RhThrowEx(object exceptionObj, ref ExInfo exInfo)
674+
#else
675+
[UnmanagedCallersOnly]
676+
internal static void RhThrowEx(object* pExceptionObj, ExInfo* pExInfo)
677+
#endif
669678
{
679+
#if !NATIVEAOT
680+
object exceptionObj = *pExceptionObj;
681+
ref ExInfo exInfo = ref *pExInfo;
682+
#endif
670683
#if NATIVEAOT
671684

672685
#if TARGET_WINDOWS
@@ -694,12 +707,19 @@ public static void RhThrowEx(object exceptionObj, ref ExInfo exInfo)
694707
#endif
695708
}
696709

710+
[StackTraceHidden]
697711
#if NATIVEAOT
698712
[RuntimeExport("RhRethrow")]
699-
#endif
700-
[StackTraceHidden]
701713
public static void RhRethrow(ref ExInfo activeExInfo, ref ExInfo exInfo)
714+
#else
715+
[UnmanagedCallersOnly]
716+
internal static void RhRethrow(ExInfo* pActiveExInfo, ExInfo* pExInfo)
717+
#endif
702718
{
719+
#if !NATIVEAOT
720+
ref ExInfo activeExInfo = ref *pActiveExInfo;
721+
ref ExInfo exInfo = ref *pExInfo;
722+
#endif
703723
#if NATIVEAOT
704724

705725
#if TARGET_WINDOWS

src/coreclr/vm/callhelpers.h

Lines changed: 48 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -500,104 +500,6 @@ enum EEToManagedCallFlags
500500
/***********************************************************************/
501501

502502
#define ARGHOLDER_TYPE LPVOID
503-
#define OBJECTREF_TO_ARGHOLDER(x) (LPVOID)OBJECTREFToObject(x)
504-
#define STRINGREF_TO_ARGHOLDER(x) (LPVOID)STRINGREFToObject(x)
505-
#define PTR_TO_ARGHOLDER(x) (LPVOID)x
506-
#define DWORD_TO_ARGHOLDER(x) (LPVOID)(SIZE_T)x
507-
#define BOOL_TO_ARGHOLDER(x) DWORD_TO_ARGHOLDER(!!(x))
508-
509-
#define INIT_VARIABLES(count) \
510-
DWORD __numArgs = count; \
511-
BOOL __criticalDispatchCall = FALSE; \
512-
513-
#define PREPARE_NONVIRTUAL_CALLSITE(id) \
514-
static PCODE s_pAddr##id = 0; \
515-
PCODE __pSlot = VolatileLoad(&s_pAddr##id); \
516-
if ( __pSlot == 0 ) \
517-
{ \
518-
MethodDesc *pMeth = CoreLibBinder::GetMethod(id); \
519-
_ASSERTE(pMeth); \
520-
__pSlot = pMeth->GetMultiCallableAddrOfCode(); \
521-
VolatileStore(&s_pAddr##id, __pSlot); \
522-
}
523-
524-
#define PREPARE_NONVIRTUAL_CALLSITE_USING_CODE(pCode) \
525-
PCODE __pSlot = pCode;
526-
527-
#define CRITICAL_CALLSITE \
528-
__criticalDispatchCall = TRUE;
529-
530-
#define PERFORM_CALL \
531-
void * __retval = NULL; \
532-
__retval = DispatchCallSimple(__pArgs, \
533-
__numStackSlotsToCopy, \
534-
__pSlot, \
535-
__criticalDispatchCall); \
536-
537-
#ifdef CALLDESCR_ARGREGS
538-
539-
#if defined(TARGET_X86)
540-
541-
// Arguments on x86 are passed backward
542-
#define ARGNUM_0 1
543-
#define ARGNUM_1 0
544-
#define ARGNUM_N(n) (__numArgs - (n) + 1)
545-
546-
#else
547-
548-
#define ARGNUM_0 0
549-
#define ARGNUM_1 1
550-
#define ARGNUM_N(n) n
551-
552-
#endif
553-
554-
#define PRECALL_PREP(args) \
555-
DWORD __numStackSlotsToCopy = (__numArgs > NUM_ARGUMENT_REGISTERS) ? (__numArgs - NUM_ARGUMENT_REGISTERS) : 0; \
556-
SIZE_T * __pArgs = (SIZE_T *)args;
557-
558-
#define DECLARE_ARGHOLDER_ARRAY(arg, count) \
559-
INIT_VARIABLES(count) \
560-
ARGHOLDER_TYPE arg[(count <= NUM_ARGUMENT_REGISTERS ? NUM_ARGUMENT_REGISTERS : count)];
561-
562-
#else // CALLDESCR_ARGREGS
563-
564-
#define ARGNUM_0 0
565-
#define ARGNUM_1 1
566-
#define ARGNUM_N(n) n
567-
568-
#define PRECALL_PREP(args) \
569-
DWORD __numStackSlotsToCopy = (__numArgs > NUM_ARGUMENT_REGISTERS) ? __numArgs : NUM_ARGUMENT_REGISTERS; \
570-
SIZE_T * __pArgs = (SIZE_T *)args;
571-
572-
#define DECLARE_ARGHOLDER_ARRAY(arg, count) \
573-
INIT_VARIABLES(count) \
574-
ARGHOLDER_TYPE arg[(count <= NUM_ARGUMENT_REGISTERS ? NUM_ARGUMENT_REGISTERS : count)];
575-
576-
#endif // CALLDESCR_ARGREGS
577-
578-
579-
#define CALL_MANAGED_METHOD(ret, rettype, args) \
580-
PRECALL_PREP(args) \
581-
PERFORM_CALL \
582-
ret = *(rettype *)(&__retval);
583-
584-
#define CALL_MANAGED_METHOD_NORET(args) \
585-
PRECALL_PREP(args) \
586-
PERFORM_CALL
587-
588-
#define CALL_MANAGED_METHOD_RETREF(ret, reftype, args) \
589-
PRECALL_PREP(args) \
590-
PERFORM_CALL \
591-
ret = (reftype)ObjectToOBJECTREF((Object *)__retval);
592-
593-
#define ARGNUM_2 ARGNUM_N(2)
594-
#define ARGNUM_3 ARGNUM_N(3)
595-
#define ARGNUM_4 ARGNUM_N(4)
596-
#define ARGNUM_5 ARGNUM_N(5)
597-
#define ARGNUM_6 ARGNUM_N(6)
598-
#define ARGNUM_7 ARGNUM_N(7)
599-
#define ARGNUM_8 ARGNUM_N(8)
600-
601503

602504
void CallDefaultConstructor(OBJECTREF ref);
603505

@@ -742,6 +644,54 @@ class UnmanagedCallersOnlyCaller final
742644

743645
return ret;
744646
}
647+
648+
template<typename... Args>
649+
void InvokeDirect(Args... args)
650+
{
651+
CONTRACTL
652+
{
653+
THROWS;
654+
GC_TRIGGERS;
655+
MODE_COOPERATIVE;
656+
}
657+
CONTRACTL_END;
658+
659+
_ASSERTE(_pMD->GetModule()->IsSystem());
660+
661+
OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED);
662+
663+
GCX_PREEMP();
664+
665+
PCODE methodEntry = _pMD->GetSingleCallableAddrOfCodeForUnmanagedCallersOnly();
666+
_ASSERTE(methodEntry != (PCODE)NULL);
667+
668+
auto fptr = reinterpret_cast<void(*)(Args...)>(methodEntry);
669+
fptr(args...);
670+
}
671+
672+
template<typename Ret, typename... Args>
673+
Ret InvokeDirect_Ret(Args... args)
674+
{
675+
CONTRACTL
676+
{
677+
THROWS;
678+
GC_TRIGGERS;
679+
MODE_COOPERATIVE;
680+
}
681+
CONTRACTL_END;
682+
683+
_ASSERTE(_pMD->GetModule()->IsSystem());
684+
685+
OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED);
686+
687+
GCX_PREEMP();
688+
689+
PCODE methodEntry = _pMD->GetSingleCallableAddrOfCodeForUnmanagedCallersOnly();
690+
_ASSERTE(methodEntry != (PCODE)NULL);
691+
692+
auto fptr = reinterpret_cast<Ret(*)(Args...)>(methodEntry);
693+
return fptr(args...);
694+
}
745695
};
746696

747697
#endif //!DACCESS_COMPILE

src/coreclr/vm/comsynchronizable.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
#include "utilcode.h"
3232
#endif
3333

34+
MethodDesc* g_pThreadStartCallbackMethodDesc = nullptr;
35+
3436

3537
// For the following helpers, we make no attempt to synchronize. The app developer
3638
// is responsible for managing their own race conditions.
@@ -133,10 +135,13 @@ static void KickOffThread_Worker(LPVOID ptr)
133135
OBJECTREF exposedObj = GetThread()->GetExposedObjectRaw();
134136
GCPROTECT_BEGIN(exposedObj);
135137

136-
PREPARE_NONVIRTUAL_CALLSITE(METHOD__THREAD__START_CALLBACK);
137-
DECLARE_ARGHOLDER_ARRAY(args, 1);
138-
args[ARGNUM_0] = OBJECTREF_TO_ARGHOLDER(exposedObj);
139-
CALL_MANAGED_METHOD_NORET(args);
138+
if (g_pThreadStartCallbackMethodDesc == nullptr)
139+
{
140+
g_pThreadStartCallbackMethodDesc = CoreLibBinder::GetMethod(METHOD__THREAD__START_CALLBACK);
141+
}
142+
143+
UnmanagedCallersOnlyCaller startCallback(METHOD__THREAD__START_CALLBACK);
144+
startCallback.InvokeDirect(&exposedObj);
140145

141146
GCPROTECT_END();
142147
}

src/coreclr/vm/corelib.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -978,7 +978,7 @@ DEFINE_FIELD(EXECUTIONCONTEXT, DEFAULT_FLOW_SUPPRESSED, DefaultFlowSu
978978
DEFINE_CLASS(DIRECTONTHREADLOCALDATA, Threading, Thread+DirectOnThreadLocalData)
979979

980980
DEFINE_CLASS(THREAD, Threading, Thread)
981-
DEFINE_METHOD(THREAD, START_CALLBACK, StartCallback, IM_RetVoid)
981+
DEFINE_METHOD(THREAD, START_CALLBACK, StartCallback, SM_PtrThread_RetVoid)
982982
DEFINE_METHOD(THREAD, POLLGC, PollGC, NoSig)
983983
DEFINE_METHOD(THREAD, ON_THREAD_EXITING, OnThreadExited, SM_PtrThread_PtrException_RetVoid)
984984
#ifdef FOR_ILLINK
@@ -1405,9 +1405,9 @@ DEFINE_FIELD_U(module, GenericHandleArgs, module)
14051405
DEFINE_FIELD_U(dictionaryIndexAndSlot, GenericHandleArgs, dictionaryIndexAndSlot)
14061406

14071407
DEFINE_CLASS(EH, Runtime, EH)
1408-
DEFINE_METHOD(EH, RH_THROW_EX, RhThrowEx, SM_Obj_RefExInfo_RetVoid)
1409-
DEFINE_METHOD(EH, RH_THROWHW_EX, RhThrowHwEx, SM_UInt_RefExInfo_RetVoid)
1410-
DEFINE_METHOD(EH, RH_RETHROW, RhRethrow, SM_RefExInfo_RefExInfo_RetVoid)
1408+
DEFINE_METHOD(EH, RH_THROW_EX, RhThrowEx, SM_PtrObj_PtrExInfo_RetVoid)
1409+
DEFINE_METHOD(EH, RH_THROWHW_EX, RhThrowHwEx, SM_UInt_PtrExInfo_RetVoid)
1410+
DEFINE_METHOD(EH, RH_RETHROW, RhRethrow, SM_PtrExInfo_PtrExInfo_RetVoid)
14111411
DEFINE_CLASS(EXCEPTIONSERVICES_INTERNALCALLS, ExceptionServices, InternalCalls)
14121412
DEFINE_CLASS(STACKFRAMEITERATOR, Runtime, StackFrameIterator)
14131413

src/coreclr/vm/excep.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5646,15 +5646,12 @@ void HandleManagedFault(EXCEPTION_RECORD* pExceptionRecord, CONTEXT* pContext)
56465646
}
56475647

56485648
GCPROTECT_BEGIN(exInfo.m_exception);
5649-
PREPARE_NONVIRTUAL_CALLSITE(METHOD__EH__RH_THROWHW_EX);
5650-
DECLARE_ARGHOLDER_ARRAY(args, 2);
5651-
args[ARGNUM_0] = DWORD_TO_ARGHOLDER(exceptionCode);
5652-
args[ARGNUM_1] = PTR_TO_ARGHOLDER(&exInfo);
5649+
UnmanagedCallersOnlyCaller throwHwEx(METHOD__EH__RH_THROWHW_EX);
56535650

56545651
pThread->IncPreventAbort();
56555652

56565653
//Ex.RhThrowHwEx(exceptionCode, &exInfo)
5657-
CALL_MANAGED_METHOD_NORET(args)
5654+
throwHwEx.InvokeDirect(exceptionCode, &exInfo);
56585655

56595656
DispatchExSecondPass(&exInfo);
56605657

0 commit comments

Comments
 (0)