Skip to content

Commit afe0540

Browse files
huoyaoyuanAaronRobinsonMSFTjkotas
authored
Remove MethodDescCallSite in comutilnative.cpp (#123986)
Contributes to #123864. Adds support for returning value. --------- Co-authored-by: Aaron R Robinson <arobins@microsoft.com> Co-authored-by: Jan Kotas <jkotas@microsoft.com>
1 parent 964b374 commit afe0540

5 files changed

Lines changed: 130 additions & 75 deletions

File tree

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

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,8 +257,45 @@ private bool CanSetRemoteStackTrace()
257257
return true;
258258
}
259259

260+
#if FEATURE_COMINTEROP
260261
// used by vm
261-
internal string? GetHelpContext(out uint helpContext)
262+
[UnmanagedCallersOnly]
263+
internal static unsafe IntPtr GetDescriptionBstr(Exception* obj, Exception* pException)
264+
{
265+
try
266+
{
267+
string message = obj->Message;
268+
if (string.IsNullOrEmpty(message))
269+
message = obj->GetClassName();
270+
271+
// Allocate the description BSTR.
272+
return Marshal.StringToBSTR(message);
273+
}
274+
catch (Exception ex)
275+
{
276+
*pException = ex;
277+
return IntPtr.Zero;
278+
}
279+
}
280+
281+
// used by vm
282+
[UnmanagedCallersOnly]
283+
internal static unsafe IntPtr GetSourceBstr(Exception* obj, Exception* pException)
284+
{
285+
try
286+
{
287+
string? source = obj->Source;
288+
289+
return Marshal.StringToBSTR(source);
290+
}
291+
catch (Exception ex)
292+
{
293+
*pException = ex;
294+
return IntPtr.Zero;
295+
}
296+
}
297+
298+
private string? GetHelpContext(out uint helpContext)
262299
{
263300
helpContext = 0;
264301
string? helpFile = HelpLink;
@@ -283,5 +320,23 @@ private bool CanSetRemoteStackTrace()
283320

284321
return helpFile;
285322
}
323+
324+
// used by vm
325+
[UnmanagedCallersOnly]
326+
internal static unsafe void GetHelpContextBstr(Exception* obj, IntPtr* bstr, uint* helpContext, Exception* pException)
327+
{
328+
*bstr = IntPtr.Zero;
329+
try
330+
{
331+
string? helpFile = obj->GetHelpContext(out *helpContext);
332+
333+
*bstr = Marshal.StringToBSTR(helpFile);
334+
}
335+
catch (Exception ex)
336+
{
337+
*pException = ex;
338+
}
339+
}
340+
#endif
286341
}
287342
}

src/coreclr/vm/callhelpers.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,57 @@ class UnmanagedCallersOnlyCaller final
746746

747747
GCPROTECT_END();
748748
}
749+
750+
template<typename Ret, typename... Args>
751+
Ret InvokeThrowing_Ret(Args... args)
752+
{
753+
CONTRACTL
754+
{
755+
THROWS;
756+
GC_TRIGGERS;
757+
MODE_COOPERATIVE;
758+
}
759+
CONTRACTL_END;
760+
761+
// Sanity check - UnmanagedCallersOnly methods must be in CoreLib.
762+
// See below load level override.
763+
_ASSERTE(_pMD->GetModule()->IsSystem());
764+
765+
// We're invoking an CoreLib method, so lift the restriction on type load limits. These calls are
766+
// limited to CoreLib and only into UnmanagedCallersOnly methods.
767+
OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED);
768+
769+
Ret ret;
770+
771+
struct
772+
{
773+
OBJECTREF Exception;
774+
} gc;
775+
gc.Exception = NULL;
776+
GCPROTECT_BEGIN(gc);
777+
778+
{
779+
GCX_PREEMP();
780+
781+
PCODE methodEntry = _pMD->GetSingleCallableAddrOfCodeForUnmanagedCallersOnly();
782+
_ASSERTE(methodEntry != (PCODE)NULL);
783+
784+
// Cast the function pointer to the appropriate type.
785+
// Note that we append the exception handle argument.
786+
auto fptr = reinterpret_cast<Ret(*)(Args..., OBJECTREF*)>(methodEntry);
787+
788+
// The last argument is the implied exception handle for any exceptions.
789+
ret = fptr(args..., &gc.Exception);
790+
}
791+
792+
// If an exception was thrown, propagate it
793+
if (gc.Exception != NULL)
794+
COMPlusThrow(gc.Exception);
795+
796+
GCPROTECT_END();
797+
798+
return ret;
799+
}
749800
};
750801

751802
#endif //!DACCESS_COMPILE

src/coreclr/vm/comutilnative.cpp

Lines changed: 14 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -124,30 +124,6 @@ extern "C" void QCALLTYPE ExceptionNative_GetFrozenStackTrace(QCall::ObjectHandl
124124

125125
#ifdef FEATURE_COMINTEROP
126126

127-
static BSTR BStrFromString(STRINGREF s)
128-
{
129-
CONTRACTL
130-
{
131-
THROWS;
132-
}
133-
CONTRACTL_END;
134-
135-
WCHAR *wz;
136-
int cch;
137-
BSTR bstr;
138-
139-
if (s == NULL)
140-
return NULL;
141-
142-
s->RefInterpretGetStringValuesDangerousForGC(&wz, &cch);
143-
144-
bstr = SysAllocString(wz);
145-
if (bstr == NULL)
146-
COMPlusThrowOM();
147-
148-
return bstr;
149-
}
150-
151127
static BSTR GetExceptionDescription(OBJECTREF objException)
152128
{
153129
CONTRACTL
@@ -161,31 +137,12 @@ static BSTR GetExceptionDescription(OBJECTREF objException)
161137

162138
BSTR bstrDescription;
163139

164-
STRINGREF MessageString = NULL;
165-
GCPROTECT_BEGIN(MessageString)
166140
GCPROTECT_BEGIN(objException)
167141
{
168-
// read Exception.Message property
169-
MethodDescCallSite getMessage(METHOD__EXCEPTION__GET_MESSAGE, &objException);
170-
171-
ARG_SLOT GetMessageArgs[] = { ObjToArgSlot(objException)};
172-
MessageString = getMessage.Call_RetSTRINGREF(GetMessageArgs);
173-
174-
// if the message string is empty then use the exception classname.
175-
if (MessageString == NULL || MessageString->GetStringLength() == 0) {
176-
// call GetClassName
177-
MethodDescCallSite getClassName(METHOD__EXCEPTION__GET_CLASS_NAME, &objException);
178-
ARG_SLOT GetClassNameArgs[] = { ObjToArgSlot(objException)};
179-
MessageString = getClassName.Call_RetSTRINGREF(GetClassNameArgs);
180-
_ASSERTE(MessageString != NULL && MessageString->GetStringLength() != 0);
181-
}
182-
183-
// Allocate the description BSTR.
184-
int DescriptionLen = MessageString->GetStringLength();
185-
bstrDescription = SysAllocStringLen(MessageString->GetBuffer(), DescriptionLen);
142+
UnmanagedCallersOnlyCaller getDescriptionBstr(METHOD__EXCEPTION__GET_DESCRIPTION_BSTR);
143+
bstrDescription = getDescriptionBstr.InvokeThrowing_Ret<BSTR>(&objException);
186144
}
187145
GCPROTECT_END();
188-
GCPROTECT_END();
189146

190147
return bstrDescription;
191148
}
@@ -200,19 +157,17 @@ static BSTR GetExceptionSource(OBJECTREF objException)
200157
PRECONDITION( IsException(objException->GetMethodTable()) );
201158
}
202159
CONTRACTL_END;
160+
161+
BSTR bstrSource;
203162

204-
STRINGREF refRetVal;
205163
GCPROTECT_BEGIN(objException)
206-
207-
// read Exception.Source property
208-
MethodDescCallSite getSource(METHOD__EXCEPTION__GET_SOURCE, &objException);
209-
210-
ARG_SLOT GetSourceArgs[] = { ObjToArgSlot(objException)};
211-
212-
refRetVal = getSource.Call_RetSTRINGREF(GetSourceArgs);
213-
164+
{
165+
UnmanagedCallersOnlyCaller getSourceBstr(METHOD__EXCEPTION__GET_SOURCE_BSTR);
166+
bstrSource = getSourceBstr.InvokeThrowing_Ret<BSTR>(&objException);
167+
}
214168
GCPROTECT_END();
215-
return BStrFromString(refRetVal);
169+
170+
return bstrSource;
216171
}
217172

218173
static void GetExceptionHelp(OBJECTREF objException, BSTR *pbstrHelpFile, DWORD *pdwHelpContext)
@@ -229,20 +184,11 @@ static void GetExceptionHelp(OBJECTREF objException, BSTR *pbstrHelpFile, DWORD
229184
}
230185
CONTRACTL_END;
231186

232-
*pdwHelpContext = 0;
233-
234-
GCPROTECT_BEGIN(objException);
235-
236-
// call managed code to parse help context
237-
MethodDescCallSite getHelpContext(METHOD__EXCEPTION__GET_HELP_CONTEXT, &objException);
238-
239-
ARG_SLOT GetHelpContextArgs[] =
187+
GCPROTECT_BEGIN(objException)
240188
{
241-
ObjToArgSlot(objException),
242-
PtrToArgSlot(pdwHelpContext)
243-
};
244-
*pbstrHelpFile = BStrFromString(getHelpContext.Call_RetSTRINGREF(GetHelpContextArgs));
245-
189+
UnmanagedCallersOnlyCaller getHelpContextBstr(METHOD__EXCEPTION__GET_HELP_CONTEXT_BSTR);
190+
getHelpContextBstr.InvokeThrowing(&objException, pbstrHelpFile, pdwHelpContext);
191+
}
246192
GCPROTECT_END();
247193
}
248194

src/coreclr/vm/corelib.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -301,11 +301,11 @@ DEFINE_FIELD_U(_xcode, ExceptionObject, _xcode)
301301
DEFINE_FIELD_U(_HResult, ExceptionObject, _HResult)
302302
DEFINE_CLASS(EXCEPTION, System, Exception)
303303
DEFINE_METHOD(EXCEPTION, INTERNAL_PRESERVE_STACK_TRACE, InternalPreserveStackTrace, IM_RetVoid)
304-
// Following Exception members are only used when FEATURE_COMINTEROP
305-
DEFINE_METHOD(EXCEPTION, GET_CLASS_NAME, GetClassName, IM_RetStr)
306-
DEFINE_PROPERTY(EXCEPTION, MESSAGE, Message, Str)
307-
DEFINE_PROPERTY(EXCEPTION, SOURCE, Source, Str)
308-
DEFINE_METHOD(EXCEPTION, GET_HELP_CONTEXT, GetHelpContext, IM_RefUInt_RetStr)
304+
#ifdef FEATURE_COMINTEROP
305+
DEFINE_METHOD(EXCEPTION, GET_DESCRIPTION_BSTR, GetDescriptionBstr, SM_PtrException_PtrException_RetIntPtr)
306+
DEFINE_METHOD(EXCEPTION, GET_SOURCE_BSTR, GetSourceBstr, SM_PtrException_PtrException_RetIntPtr)
307+
DEFINE_METHOD(EXCEPTION, GET_HELP_CONTEXT_BSTR, GetHelpContextBstr, SM_PtrException_PtrIntPtr_PtrUInt_PtrException_RetVoid)
308+
#endif // FEATURE_COMINTEROP
309309

310310

311311
DEFINE_CLASS(SYSTEM_EXCEPTION, System, SystemException)

src/coreclr/vm/metasig.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,10 @@ DEFINE_METASIG_T(SM(IntPtr_RetRuntimeType, I , C(CLASS)))
399399
DEFINE_METASIG_T(IM(RuntimeArgumentHandle_PtrVoid_RetVoid, g(ARGUMENT_HANDLE) P(v), v))
400400

401401
// Exception
402-
DEFINE_METASIG(IM(RefUInt_RetStr, r(K), s))
402+
#ifdef FEATURE_COMINTEROP
403+
DEFINE_METASIG_T(SM(PtrException_PtrException_RetIntPtr, P(C(EXCEPTION)) P(C(EXCEPTION)), I))
404+
DEFINE_METASIG_T(SM(PtrException_PtrIntPtr_PtrUInt_PtrException_RetVoid, P(C(EXCEPTION)) P(I) P(K) P(C(EXCEPTION)), v))
405+
#endif //FEATURE_COMINTEROP
403406

404407
#ifdef FEATURE_COMINTEROP
405408
// The signature of the method System.Runtime.InteropServices.ICustomQueryInterface.GetInterface

0 commit comments

Comments
 (0)