private static bool TryConvertPointer(object srcObject, [NotNullWhen(true)] out object? dstPtr)
{
- if (srcObject is IntPtr)
+ if (srcObject is IntPtr or UIntPtr)
{
dstPtr = srcObject;
return true;
}
- if (srcObject is UIntPtr)
- {
- dstPtr = (IntPtr)(UIntPtr)srcObject;
- return true;
- }
-
// The source pointer should already have been converted to an IntPtr.
Debug.Assert(srcObject is not Pointer);
if (parameterType.IsPointer)
{
- il.Emit(OpCodes.Unbox_Any, typeof(IntPtr));
+ Unbox(il, typeof(IntPtr));
}
else if (parameterType.IsValueType)
{
- il.Emit(OpCodes.Unbox_Any, parameterType);
+ Unbox(il, parameterType);
}
}
if (parameterType.IsPointer)
{
- il.Emit(OpCodes.Unbox_Any, typeof(IntPtr));
+ Unbox(il, typeof(IntPtr));
}
else if (parameterType.IsValueType)
{
- il.Emit(OpCodes.Unbox_Any, parameterType);
+ Unbox(il, parameterType);
}
}
return (InvokeFunc_RefArgs)dm.CreateDelegate(typeof(InvokeFunc_RefArgs), target: null);
}
+ private static void Unbox(ILGenerator il, Type parameterType)
+ {
+ // Unbox without using OpCodes.Unbox\UnboxAny to avoid a type check since that was already done by reflection.
+ // Also required for unboxing true nullables created by reflection since that is not necessarily a valid CLI operation.
+ Debug.Assert(parameterType.IsValueType);
+ il.Emit(OpCodes.Call, Methods.Object_GetRawData());
+ il.Emit(OpCodes.Ldobj, parameterType);
+ }
+
private static void EmitCallAndReturnHandling(ILGenerator il, MethodBase method, bool emitNew, bool backwardsCompat)
{
// For CallStack reasons, don't inline target method.
public static MethodInfo ThrowHelper_Throw_NullReference_InvokeNullRefReturned() =>
s_ThrowHelper_Throw_NullReference_InvokeNullRefReturned ??= typeof(ThrowHelper).GetMethod(nameof(ThrowHelper.Throw_NullReference_InvokeNullRefReturned))!;
+ private static MethodInfo? s_Object_GetRawData;
+ public static MethodInfo Object_GetRawData() =>
+ s_Object_GetRawData ??= typeof(RuntimeHelpers).GetMethod(nameof(RuntimeHelpers.GetRawData), BindingFlags.NonPublic | BindingFlags.Static)!;
+
private static MethodInfo? s_Pointer_Box;
public static MethodInfo Pointer_Box() =>
s_Pointer_Box ??= typeof(Pointer).GetMethod(nameof(Pointer.Box), new[] { typeof(void*), typeof(Type) })!;
bool copyBack = false;
Span<bool> shouldCopyBack = new(ref copyBack);
- CheckArguments(parametersSpan, copyOfArgs, shouldCopyBack, binder, culture, invokeAttr);
-
object? ret;
if ((_strategy & InvokerStrategy.StrategyDetermined_ObjSpanArgs) == 0)
{
DetermineStrategy_ObjSpanArgs(ref _strategy, ref _invokeFunc_ObjSpanArgs, _method, _needsByRefStrategy, backwardsCompat: true);
}
+ CheckArguments(parametersSpan, copyOfArgs, shouldCopyBack, binder, culture, invokeAttr);
+
if (_invokeFunc_ObjSpanArgs is not null)
{
try
{
throw new TargetInvocationException(e);
}
-
- CopyBack(parameters, copyOfArgs, shouldCopyBack);
- return ret;
+ }
+ else
+ {
+ ret = InvokeDirectByRefWithFewArgs(obj, copyOfArgs, invokeAttr);
}
- ret = InvokeDirectByRefWithFewArgs(obj, copyOfArgs, invokeAttr);
CopyBack(parameters, copyOfArgs, shouldCopyBack);
return ret;
}
Span<object?> copyOfArgs = stackArgStorage._args.AsSpan(_argCount);
Span<bool> shouldCopyBack = stackArgStorage._shouldCopyBack.AsSpan(_argCount);
- CheckArguments(parameters, copyOfArgs, shouldCopyBack, binder, culture, invokeAttr);
-
object? ret;
if ((_strategy & InvokerStrategy.StrategyDetermined_ObjSpanArgs) == 0)
{
DetermineStrategy_ObjSpanArgs(ref _strategy, ref _invokeFunc_ObjSpanArgs, _method, _needsByRefStrategy, backwardsCompat: true);
}
+ CheckArguments(parameters, copyOfArgs, shouldCopyBack, binder, culture, invokeAttr);
+
if (_invokeFunc_ObjSpanArgs is not null)
{
try
{
throw new TargetInvocationException(e);
}
-
- CopyBack(parameters, copyOfArgs, shouldCopyBack);
- return ret;
}
+ else
+ {
+ ret = InvokeDirectByRefWithFewArgs(obj, copyOfArgs, invokeAttr);
+
+ }
- ret = InvokeDirectByRefWithFewArgs(obj, copyOfArgs, invokeAttr);
CopyBack(parameters, copyOfArgs, shouldCopyBack);
return ret;
}
}
else if (!ReferenceEquals(arg.GetType(), sigType))
{
- // Determine if we can use the fast path for byref types
+ // Determine if we can use the fast path for byref types.
if (TryByRefFastPath(sigType, ref arg))
{
// Fast path when the value's type matches the signature type of a byref parameter.
}
else
{
-#if !MONO // Temporary until Mono can unbox a true Nullable<T>
if (RuntimeFeature.IsDynamicCodeSupported)
{
invokeFunc_ObjSpanArgs = CreateInvokeDelegate_ObjSpanArgs(method, backwardsCompat);
}
-#endif
+
strategy |= InvokerStrategy.StrategyDetermined_ObjSpanArgs;
}
}
}
else
{
-#if !MONO // Temporary until Mono can unbox a true Nullable<T>
if (RuntimeFeature.IsDynamicCodeSupported)
{
invokeFunc_Obj4Args = CreateInvokeDelegate_Obj4Args(method, backwardsCompat);
}
-#endif
+
strategy |= InvokerStrategy.StrategyDetermined_Obj4Args;
}
}
}
else if (IsPointer)
{
- Type? vtype = value.GetType();
- if (vtype == typeof(IntPtr) || vtype == typeof(UIntPtr))
+ if (value is IntPtr or UIntPtr)
return CheckValueStatus.Success;
+
if (value is Pointer pointer)
{
Type pointerType = pointer.GetPointerType();