diff options
Diffstat (limited to 'src/System.Private.CoreLib/src/System/InvokeUtils.cs')
-rw-r--r-- | src/System.Private.CoreLib/src/System/InvokeUtils.cs | 52 |
1 files changed, 44 insertions, 8 deletions
diff --git a/src/System.Private.CoreLib/src/System/InvokeUtils.cs b/src/System.Private.CoreLib/src/System/InvokeUtils.cs index 69435aee9..0a66ea6c2 100644 --- a/src/System.Private.CoreLib/src/System/InvokeUtils.cs +++ b/src/System.Private.CoreLib/src/System/InvokeUtils.cs @@ -12,6 +12,8 @@ using Internal.Reflection.Core.NonPortable; using Internal.Runtime.Augments; using Internal.Runtime.CompilerServices; +using Interlocked = System.Threading.Interlocked; + namespace System { [System.Runtime.CompilerServices.ReflectionBlocked] @@ -39,7 +41,7 @@ namespace System // This method is targeted by the Delegate ILTransformer. // // - public static Object CheckArgument(Object srcObject, RuntimeTypeHandle dstType, BinderBundle binderBundle) + public static object CheckArgument(object srcObject, RuntimeTypeHandle dstType, BinderBundle binderBundle) { EETypePtr dstEEType = dstType.ToEETypePtr(); return CheckArgument(srcObject, dstEEType, CheckArgumentSemantics.DynamicInvoke, binderBundle, getExactTypeForCustomBinder: null); @@ -53,12 +55,16 @@ namespace System SetFieldDirect, // Throws ArgumentException - other than that, like DynamicInvoke except that enums and integers cannot be intermingled, and null cannot substitute for default(valuetype). } - internal static Object CheckArgument(Object srcObject, EETypePtr dstEEType, CheckArgumentSemantics semantics, BinderBundle binderBundle, Func<Type> getExactTypeForCustomBinder = null) + internal static object CheckArgument(object srcObject, EETypePtr dstEEType, CheckArgumentSemantics semantics, BinderBundle binderBundle, Func<Type> getExactTypeForCustomBinder = null) { if (srcObject == null) { // null -> default(T) - if (dstEEType.IsValueType && !dstEEType.IsNullable) + if (dstEEType.IsPointer) + { + return default(IntPtr); + } + else if (dstEEType.IsValueType && !dstEEType.IsNullable) { if (semantics == CheckArgumentSemantics.SetFieldDirect) throw CreateChangeTypeException(CommonRuntimeTypes.Object.TypeHandle.ToEETypePtr(), dstEEType, semantics); @@ -412,9 +418,9 @@ namespace System s_curIndex = 0; s_targetMethodOrDelegate = targetMethodOrDelegate; + object result; try { - object result = null; if (invokeMethodHelperIsThisCall) { Debug.Assert(methodToCallIsThisCall == true); @@ -434,8 +440,6 @@ namespace System DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); } } - - return result; } catch (Exception e) when (wrapInTargetInvocationException && argSetupState.fComplete) { @@ -464,6 +468,11 @@ namespace System } } } + + if (result == NullByRefValueSentinel) + throw new NullReferenceException(SR.NullReference_InvokeNullRefReturned); + + return result; } finally { @@ -730,6 +739,15 @@ namespace System return finalObjectToReturn; } + internal static object DynamicInvokeUnmanagedPointerReturn(out DynamicInvokeParamLookupType paramLookupType, object boxedPointerType, int index, RuntimeTypeHandle type, DynamicInvokeParamType paramType) + { + object finalObjectToReturn = boxedPointerType; + + Debug.Assert(finalObjectToReturn is IntPtr); + paramLookupType = DynamicInvokeParamLookupType.ValuetypeObjectReturned; + return finalObjectToReturn; + } + public static object DynamicInvokeParamHelperCore(RuntimeTypeHandle type, out DynamicInvokeParamLookupType paramLookupType, out int index, DynamicInvokeParamType paramType) { index = s_curIndex++; @@ -790,17 +808,22 @@ namespace System incomingParam = InvokeUtils.CheckArgument(incomingParam, type.ToEETypePtr(), InvokeUtils.CheckArgumentSemantics.DynamicInvoke, s_binderBundle, s_getExactTypeForCustomBinder); if (s_binderBundle == null) { - System.Diagnostics.Debug.Assert(s_parameters[index] == null || Object.ReferenceEquals(incomingParam, s_parameters[index])); + System.Diagnostics.Debug.Assert(s_parameters[index] == null || object.ReferenceEquals(incomingParam, s_parameters[index])); } return DynamicInvokeBoxedValuetypeReturn(out paramLookupType, incomingParam, index, type, paramType); } + else if (type.ToEETypePtr().IsPointer) + { + incomingParam = InvokeUtils.CheckArgument(incomingParam, type.ToEETypePtr(), InvokeUtils.CheckArgumentSemantics.DynamicInvoke, s_binderBundle, s_getExactTypeForCustomBinder); + return DynamicInvokeUnmanagedPointerReturn(out paramLookupType, incomingParam, index, type, paramType); + } else { incomingParam = InvokeUtils.CheckArgument(incomingParam, widenAndCompareType.ToEETypePtr(), InvokeUtils.CheckArgumentSemantics.DynamicInvoke, s_binderBundle, s_getExactTypeForCustomBinder); paramLookupType = DynamicInvokeParamLookupType.IndexIntoObjectArrayReturned; if (s_binderBundle == null) { - System.Diagnostics.Debug.Assert(Object.ReferenceEquals(incomingParam, s_parameters[index])); + System.Diagnostics.Debug.Assert(object.ReferenceEquals(incomingParam, s_parameters[index])); return s_parameters; } else @@ -833,6 +856,19 @@ namespace System } } } + + private static volatile object _nullByRefValueSentinel; + public static object NullByRefValueSentinel + { + get + { + if (_nullByRefValueSentinel == null) + { + Interlocked.CompareExchange(ref _nullByRefValueSentinel, new object(), null); + } + return _nullByRefValueSentinel; + } + } } } |