Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CallConverterThunk.cs')
-rw-r--r--src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CallConverterThunk.cs36
1 files changed, 33 insertions, 3 deletions
diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CallConverterThunk.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CallConverterThunk.cs
index b9b8a9cff..f0f8256c7 100644
--- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CallConverterThunk.cs
+++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CallConverterThunk.cs
@@ -1114,11 +1114,12 @@ namespace Internal.Runtime.TypeLoader
#endif
}
}
- else if (conversionParams._conversionInfo.IsAnyDynamicInvokerThunk && thRetType.IsValueType())
+ else if (conversionParams._conversionInfo.IsAnyDynamicInvokerThunk &&
+ (thRetType.IsValueType() || thRetType.IsPointerType() || returnType == CorElementType.ELEMENT_TYPE_BYREF))
{
Debug.Assert(returnValueToCopy != null);
- if (conversionParams._calleeArgs.GetReturnType(out thDummy, out dummyBool) == CorElementType.ELEMENT_TYPE_VOID)
+ if (returnType == CorElementType.ELEMENT_TYPE_VOID)
{
// Invokers returning void need to return a null object
returnValueToCopy = null;
@@ -1128,8 +1129,37 @@ namespace Internal.Runtime.TypeLoader
if (!conversionParams._callerArgs.HasRetBuffArg() && conversionParams._calleeArgs.HasRetBuffArg())
returnValueToCopy = (void*)(new IntPtr(*((void**)returnValueToCopy)) + IntPtr.Size);
+ if (returnType == CorElementType.ELEMENT_TYPE_BYREF)
+ {
+ // If this is a byref return, we're going to dereference the result
+ returnValueToCopy = *(void**)returnValueToCopy;
+ }
+
+ RuntimeTypeHandle returnTypeRuntimeTypeHandle = thRetType.GetRuntimeTypeHandle();
+
// Need to box value type before returning it
- object returnValue = RuntimeAugments.Box(thRetType.GetRuntimeTypeHandle(), new IntPtr(returnValueToCopy));
+ object returnValue;
+ if (returnType == CorElementType.ELEMENT_TYPE_BYREF && returnValueToCopy == null)
+ {
+ // This is a byref return and dereferencing it would result in a NullReferenceException.
+ // Set the return value to a sentinel that InvokeUtils will recognize.
+ // Can't throw from here or we would wrap this in a TargetInvocationException.
+ returnValue = InvokeUtils.NullByRefValueSentinel;
+ }
+ else if (RuntimeAugments.IsUnmanagedPointerType(returnTypeRuntimeTypeHandle))
+ {
+ returnValue = System.Reflection.Pointer.Box(*(void**)returnValueToCopy, Type.GetTypeFromHandle(returnTypeRuntimeTypeHandle));
+ }
+ else if (RuntimeAugments.IsValueType(returnTypeRuntimeTypeHandle))
+ {
+ returnValue = RuntimeAugments.Box(returnTypeRuntimeTypeHandle, new IntPtr(returnValueToCopy));
+ }
+ else
+ {
+ // byref return of a reference type
+ Debug.Assert(returnType == CorElementType.ELEMENT_TYPE_BYREF);
+ returnValue = Unsafe.As<byte, object>(ref *(byte*)returnValueToCopy);
+ }
CallConversionParameters.s_pinnedGCHandles._returnObjectHandle.Target = returnValue;
pinnedResultObject = CallConversionParameters.s_pinnedGCHandles._returnObjectHandle.GetRawTargetAddress();
returnValueToCopy = (void*)&pinnedResultObject;