Skip to content

Commit d461cdb

Browse files
Convert GetMethodFromStackTrace to QCall (#105103)
* Convert GetMethodFromStackTrace to QCall
1 parent 31bc167 commit d461cdb

File tree

7 files changed

+57
-65
lines changed

7 files changed

+57
-65
lines changed

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

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -55,38 +55,28 @@ private IDictionary CreateDataContainer()
5555
[MethodImpl(MethodImplOptions.InternalCall)]
5656
private static extern bool IsImmutableAgileException(Exception e);
5757

58-
[MethodImpl(MethodImplOptions.InternalCall)]
59-
private static extern IRuntimeMethodInfo GetMethodFromStackTrace(object stackTrace);
58+
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ExceptionNative_GetMethodFromStackTrace")]
59+
private static partial void GetMethodFromStackTrace(ObjectHandleOnStack stackTrace, ObjectHandleOnStack method);
6060

6161
private MethodBase? GetExceptionMethodFromStackTrace()
6262
{
63-
Debug.Assert(_stackTrace != null, "_stackTrace shouldn't be null when this method is called");
64-
IRuntimeMethodInfo method = GetMethodFromStackTrace(_stackTrace!);
65-
66-
// Under certain race conditions when exceptions are re-used, this can be null
67-
if (method == null)
63+
object? stackTraceLocal = _stackTrace;
64+
if (stackTraceLocal == null)
65+
{
6866
return null;
67+
}
6968

70-
return RuntimeType.GetMethodBase(method);
69+
IRuntimeMethodInfo? methodInfo = null;
70+
GetMethodFromStackTrace(ObjectHandleOnStack.Create(ref stackTraceLocal), ObjectHandleOnStack.Create(ref methodInfo));
71+
Debug.Assert(methodInfo != null);
72+
73+
return RuntimeType.GetMethodBase(methodInfo);
7174
}
7275

7376
public MethodBase? TargetSite
7477
{
7578
[RequiresUnreferencedCode("Metadata for the method might be incomplete or removed")]
76-
get
77-
{
78-
if (_exceptionMethod != null)
79-
{
80-
return _exceptionMethod;
81-
}
82-
if (_stackTrace == null)
83-
{
84-
return null;
85-
}
86-
87-
_exceptionMethod = GetExceptionMethodFromStackTrace();
88-
return _exceptionMethod;
89-
}
79+
get => _exceptionMethod ??= GetExceptionMethodFromStackTrace();
9080
}
9181

9282
// This method will clear the _stackTrace of the exception object upon deserialization

src/coreclr/classlibnative/bcltype/system.cpp

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -88,43 +88,6 @@ FCIMPL0(INT32, SystemNative::GetExitCode)
8888
}
8989
FCIMPLEND
9090

91-
// Return a method info for the method were the exception was thrown
92-
FCIMPL1(ReflectMethodObject*, SystemNative::GetMethodFromStackTrace, ArrayBase* pStackTraceUNSAFE)
93-
{
94-
FCALL_CONTRACT;
95-
96-
// The pStackTraceUNSAFE can be either I1Array or Object[]. In the latter case, the first entry is the actual stack trace I1Array,
97-
// the rest are pointers to the method info objects. We only care about the first entry here.
98-
if (pStackTraceUNSAFE->GetArrayElementType() != ELEMENT_TYPE_I1)
99-
{
100-
PtrArray *combinedArray = (PtrArray*)pStackTraceUNSAFE;
101-
pStackTraceUNSAFE = (ArrayBase*)OBJECTREFToObject(combinedArray->GetAt(0));
102-
}
103-
I1ARRAYREF pArray(static_cast<I1Array *>(pStackTraceUNSAFE));
104-
StackTraceArray stackArray(pArray);
105-
106-
if (!stackArray.Size())
107-
return NULL;
108-
109-
// The managed stacktrace classes always returns typical method definition, so we don't need to bother providing exact instantiation.
110-
// Generics::GetExactInstantiationsOfMethodAndItsClassFromCallInformation(pElements[0].pFunc, pElements[0].pExactGenericArgsToken, pTypeHandle, &pMD);
111-
112-
MethodDesc* pFunc = stackArray[0].pFunc;
113-
114-
// Strip the instantiation to make sure that the reflection never gets a bad method desc back.
115-
REFLECTMETHODREF refRet = NULL;
116-
117-
HELPER_METHOD_FRAME_BEGIN_RET_0()
118-
pFunc = pFunc->LoadTypicalMethodDefinition();
119-
refRet = pFunc->GetStubMethodInfo();
120-
_ASSERTE(pFunc->IsRuntimeMethodHandle());
121-
122-
HELPER_METHOD_FRAME_END();
123-
124-
return (ReflectMethodObject*)OBJECTREFToObject(refRet);
125-
}
126-
FCIMPLEND
127-
12891
extern "C" INT32 QCALLTYPE Environment_GetProcessorCount()
12992
{
13093
QCALL_CONTRACT;

src/coreclr/classlibnative/bcltype/system.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,6 @@ class SystemNative
4444
static FCDECL0(INT32, GetExitCode);
4545

4646
static FCDECL0(FC_BOOL_RET, IsServerGC);
47-
48-
// Return a method info for the method were the exception was thrown
49-
static FCDECL1(ReflectMethodObject*, GetMethodFromStackTrace, ArrayBase* pStackTraceUNSAFE);
5047
};
5148

5249
extern "C" void QCALLTYPE Environment_Exit(INT32 exitcode);

src/coreclr/vm/comutilnative.cpp

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ FCIMPL1(Object *, ExceptionNative::GetFrozenStackTrace, Object* pExceptionObject
114114
{
115115
gc.result = gc.stackTrace.Get();
116116
}
117-
117+
118118
HELPER_METHOD_FRAME_END();
119119

120120
return OBJECTREFToObject(gc.result);
@@ -415,6 +415,46 @@ extern "C" void QCALLTYPE ExceptionNative_GetMessageFromNativeResources(Exceptio
415415
END_QCALL;
416416
}
417417

418+
extern "C" void QCALLTYPE ExceptionNative_GetMethodFromStackTrace(QCall::ObjectHandleOnStack stacktrace, QCall::ObjectHandleOnStack retMethodInfo)
419+
{
420+
QCALL_CONTRACT;
421+
422+
BEGIN_QCALL;
423+
424+
GCX_COOP();
425+
426+
MethodDesc* pMD = NULL;
427+
// See ExceptionObject::GetStackTrace() and ExceptionObject::SetStackTrace()
428+
// for details on the stacktrace array.
429+
{
430+
ARRAYBASEREF arrayBaseRef = (ARRAYBASEREF)stacktrace.Get();
431+
_ASSERTE(arrayBaseRef != NULL);
432+
433+
// The stacktrace can be either sbyte[] or Object[]. In the latter case,
434+
// the first entry is the actual stack trace sbyte[], the rest are pointers
435+
// to the method info objects. We only care about the first entry here.
436+
if (arrayBaseRef->GetArrayElementType() != ELEMENT_TYPE_I1)
437+
{
438+
_ASSERTE(arrayBaseRef->GetArrayElementType() == ELEMENT_TYPE_OBJECT);
439+
PTRARRAYREF ptrArrayRef = (PTRARRAYREF)arrayBaseRef;
440+
arrayBaseRef = (ARRAYBASEREF)OBJECTREFToObject(ptrArrayRef->GetAt(0));
441+
}
442+
443+
I1ARRAYREF arrayRef = (I1ARRAYREF)arrayBaseRef;
444+
StackTraceArray stackArray(arrayRef);
445+
_ASSERTE(stackArray.Size() > 0);
446+
pMD = stackArray[0].pFunc;
447+
}
448+
449+
// The managed stack trace classes always return typical method definition,
450+
// so we don't need to bother providing exact instantiation.
451+
MethodDesc* pMDTypical = pMD->LoadTypicalMethodDefinition();
452+
retMethodInfo.Set(pMDTypical->GetStubMethodInfo());
453+
_ASSERTE(pMDTypical->IsRuntimeMethodHandle());
454+
455+
END_QCALL;
456+
}
457+
418458
extern "C" void QCALLTYPE Buffer_Clear(void *dst, size_t length)
419459
{
420460
QCALL_CONTRACT;
@@ -1784,7 +1824,7 @@ extern "C" BOOL QCALLTYPE TypeHandle_CanCastTo_NoCacheLookup(void* fromTypeHnd,
17841824

17851825
TypeHandle fromTH = TypeHandle::FromPtr(fromTypeHnd);
17861826
TypeHandle toTH = TypeHandle::FromPtr(toTypeHnd);
1787-
1827+
17881828
if (fromTH.IsTypeDesc())
17891829
{
17901830
ret = fromTH.AsTypeDesc()->CanCastTo(toTH, NULL);

src/coreclr/vm/comutilnative.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ enum class ExceptionMessageKind {
6262
};
6363
extern "C" void QCALLTYPE ExceptionNative_GetMessageFromNativeResources(ExceptionMessageKind kind, QCall::StringHandleOnStack retMesg);
6464

65+
extern "C" void QCALLTYPE ExceptionNative_GetMethodFromStackTrace(QCall::ObjectHandleOnStack array, QCall::ObjectHandleOnStack retMethodInfo);
66+
6567
//
6668
// Buffer
6769
//

src/coreclr/vm/ecalllist.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ FCFuncEnd()
9292

9393
FCFuncStart(gExceptionFuncs)
9494
FCFuncElement("IsImmutableAgileException", ExceptionNative::IsImmutableAgileException)
95-
FCFuncElement("GetMethodFromStackTrace", SystemNative::GetMethodFromStackTrace)
9695
FCFuncElement("PrepareForForeignExceptionRaise", ExceptionNative::PrepareForForeignExceptionRaise)
9796
FCFuncElement("GetFrozenStackTrace", ExceptionNative::GetFrozenStackTrace)
9897
FCFuncElement("GetExceptionCount", ExceptionNative::GetExceptionCount)

src/coreclr/vm/qcallentrypoints.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ static const Entry s_QCall[] =
9898
DllImportEntry(Environment_FailFast)
9999
DllImportEntry(Environment_GetProcessorCount)
100100
DllImportEntry(ExceptionNative_GetMessageFromNativeResources)
101+
DllImportEntry(ExceptionNative_GetMethodFromStackTrace)
101102
DllImportEntry(RuntimeTypeHandle_CreateInstanceForAnotherGenericParameter)
102103
DllImportEntry(QCall_GetGCHandleForTypeHandle)
103104
DllImportEntry(QCall_FreeGCHandleForTypeHandle)

0 commit comments

Comments
 (0)