internal static object Call( IntPtr dynamicInvokeHelperMethod, object thisPtr, IntPtr methodToCall, ref ArgSetupState argSetupState, bool isTargetThisCall) { // This method is implemented elsewhere in the toolchain throw new NotSupportedException(); }
internal static void DynamicInvokeArgSetupComplete(ref ArgSetupState argSetupState) { int parametersLength = s_parameters != null ? s_parameters.Length : 0; if (s_curIndex != parametersLength) { throw new System.Reflection.TargetParameterCountException(); } argSetupState.fComplete = true; argSetupState.nullableCopyBackObjects = s_nullableCopyBackObjects; s_nullableCopyBackObjects = null; }
internal static object DynamicInvokeCallTemplate(object thisPtr, IntPtr methodToCall, ref ArgSetupState argSetupState, bool targetIsThisCall) { // This function will look like // // !For each parameter to the method // !if (parameter is In Parameter) // localX is TypeOfParameterX& // ldtoken TypeOfParameterX // call DynamicInvokeParamHelperIn(RuntimeTypeHandle) // stloc localX // !else // localX is TypeOfParameter // ldtoken TypeOfParameterX // call DynamicInvokeParamHelperRef(RuntimeTypeHandle) // stloc localX // ldarg.2 // call DynamicInvokeArgSetupComplete(ref ArgSetupState) // !if (targetIsThisCall) // ldarg.0 // Load this pointer // !For each parameter // !if (parameter is In Parameter) // ldloc localX // ldobj TypeOfParameterX // !else // ldloc localX // ldarg.1 // calli ReturnType thiscall(TypeOfParameter1, ...) // !if ((ReturnType != void) && !(ReturnType is a byref) // ldnull // !else // box ReturnType // ret // !else // !For each parameter // !if (parameter is In Parameter) // ldloc localX // ldobj TypeOfParameterX // !else // ldloc localX // ldarg.1 // calli ReturnType (TypeOfParameter1, ...) // !if ((ReturnType != void) && !(ReturnType is a byref) // ldnull // !else // box ReturnType // ret return(null); }
internal static object CallDynamicInvokeMethod( object thisPtr, IntPtr methodToCall, object thisPtrDynamicInvokeMethod, IntPtr dynamicInvokeHelperMethod, IntPtr dynamicInvokeHelperGenericDictionary, object targetMethodOrDelegate, object[] parameters, BinderBundle binderBundle, bool wrapInTargetInvocationException, bool invokeMethodHelperIsThisCall = true, bool methodToCallIsThisCall = true) { // This assert is needed because we've double-purposed "targetMethodOrDelegate" (which is actually a MethodBase anytime a custom binder is used) // as a way of obtaining the true parameter type which we need to pass to Binder.ChangeType(). (The type normally passed to DynamicInvokeParamHelperCore // isn't always the exact type (byref stripped off, enums converted to int, etc.) Debug.Assert(!(binderBundle != null && !(targetMethodOrDelegate is MethodBase)), "The only callers that can pass a custom binder are those servicing MethodBase.Invoke() apis."); bool parametersNeedCopyBack = false; ArgSetupState argSetupState = default(ArgSetupState); // Capture state of thread static invoke helper statics object[] parametersOld = s_parameters; object[] nullableCopyBackObjectsOld = s_nullableCopyBackObjects; int curIndexOld = s_curIndex; object targetMethodOrDelegateOld = s_targetMethodOrDelegate; BinderBundle binderBundleOld = s_binderBundle; s_binderBundle = binderBundle; object[] customBinderProvidedParametersOld = s_customBinderProvidedParameters; s_customBinderProvidedParameters = null; try { // If the passed in array is not an actual object[] instance, we need to copy it over to an actual object[] // instance so that the rest of the code can safely create managed object references to individual elements. if (parameters != null && EETypePtr.EETypePtrOf <object[]>() != parameters.EETypePtr) { s_parameters = new object[parameters.Length]; Array.Copy(parameters, s_parameters, parameters.Length); parametersNeedCopyBack = true; } else { s_parameters = parameters; } s_nullableCopyBackObjects = null; s_curIndex = 0; s_targetMethodOrDelegate = targetMethodOrDelegate; try { object result = null; if (invokeMethodHelperIsThisCall) { Debug.Assert(methodToCallIsThisCall == true); result = CalliIntrinsics.Call(dynamicInvokeHelperMethod, thisPtrDynamicInvokeMethod, thisPtr, methodToCall, ref argSetupState); System.Diagnostics.DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); } else { if (dynamicInvokeHelperGenericDictionary != IntPtr.Zero) { result = CalliIntrinsics.Call(dynamicInvokeHelperMethod, dynamicInvokeHelperGenericDictionary, thisPtr, methodToCall, ref argSetupState, methodToCallIsThisCall); DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); } else { result = CalliIntrinsics.Call(dynamicInvokeHelperMethod, thisPtr, methodToCall, ref argSetupState, methodToCallIsThisCall); DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); } } return(result); } catch (Exception e) when(wrapInTargetInvocationException && argSetupState.fComplete) { throw new TargetInvocationException(e); } finally { if (parametersNeedCopyBack) { Array.Copy(s_parameters, parameters, parameters.Length); } if (argSetupState.fComplete) { // Nullable objects can't take advantage of the ability to update the boxed value on the heap directly, so perform // an update of the parameters array now. if (argSetupState.nullableCopyBackObjects != null) { for (int i = 0; i < argSetupState.nullableCopyBackObjects.Length; i++) { if (argSetupState.nullableCopyBackObjects[i] != null) { parameters[i] = DynamicInvokeBoxIntoNonNullable(argSetupState.nullableCopyBackObjects[i]); } } } } } } finally { // Restore state of thread static helper statics s_parameters = parametersOld; s_nullableCopyBackObjects = nullableCopyBackObjectsOld; s_curIndex = curIndexOld; s_targetMethodOrDelegate = targetMethodOrDelegateOld; s_binderBundle = binderBundleOld; s_customBinderProvidedParameters = customBinderProvidedParametersOld; } }
internal static object DynamicInvokeCallTemplate(object thisPtr, IntPtr methodToCall, ref ArgSetupState argSetupState, bool targetIsThisCall) { // This function will look like // // !For each parameter to the method // !if (parameter is In Parameter) // localX is TypeOfParameterX& // ldtoken TypeOfParameterX // call DynamicInvokeParamHelperIn(RuntimeTypeHandle) // stloc localX // !else // localX is TypeOfParameter // ldtoken TypeOfParameterX // call DynamicInvokeParamHelperRef(RuntimeTypeHandle) // stloc localX // ldarg.2 // call DynamicInvokeArgSetupComplete(ref ArgSetupState) // !if (targetIsThisCall) // ldarg.0 // Load this pointer // !For each parameter // !if (parameter is In Parameter) // ldloc localX // ldobj TypeOfParameterX // !else // ldloc localX // ldarg.1 // calli ReturnType thiscall(TypeOfParameter1, ...) // !if ((ReturnType != void) && !(ReturnType is a byref) // ldnull // !else // box ReturnType // ret // !else // !For each parameter // !if (parameter is In Parameter) // ldloc localX // ldobj TypeOfParameterX // !else // ldloc localX // ldarg.1 // calli ReturnType (TypeOfParameter1, ...) // !if ((ReturnType != void) && !(ReturnType is a byref) // ldnull // !else // box ReturnType // ret return null; }
internal static object?CheckArgument(object?srcObject, EETypePtr dstEEType, CheckArgumentSemantics semantics, BinderBundle?binderBundle, ref ArgSetupState argSetupState) { // Methods with ByRefLike types in signatures should be filtered out by the compiler Debug.Assert(!dstEEType.IsByRefLike); if (srcObject == null) { // null -> default(T) if (dstEEType.IsPointer) { return(default(IntPtr)); } else if (dstEEType.IsValueType && !dstEEType.IsNullable) { if (semantics == CheckArgumentSemantics.SetFieldDirect) { throw CreateChangeTypeException(typeof(object).TypeHandle.ToEETypePtr(), dstEEType, semantics); } return(Runtime.RuntimeImports.RhNewObject(dstEEType)); } else { return(null); } } else { EETypePtr srcEEType = srcObject.EETypePtr; if (RuntimeImports.AreTypesAssignable(srcEEType, dstEEType)) { return(srcObject); } if (dstEEType.IsInterface) { if (srcObject is Runtime.InteropServices.IDynamicInterfaceCastable castable && castable.IsInterfaceImplemented(new RuntimeTypeHandle(dstEEType), throwIfNotImplemented: false)) { return(srcObject); } } object dstObject; Exception exception = ConvertOrWidenPrimitivesEnumsAndPointersIfPossible(srcObject, srcEEType, dstEEType, semantics, out dstObject); if (exception == null) { return(dstObject); } if (binderBundle == null) { throw exception; } // Our normal coercion rules could not convert the passed in argument but we were supplied a custom binder. See if it can do it. Type exactDstType; if (Unsafe.IsNullRef(ref argSetupState)) { // We were called by someone other than DynamicInvokeParamHelperCore(). Those callers pass the correct dstEEType. exactDstType = Type.GetTypeFromHandle(new RuntimeTypeHandle(dstEEType)) !; } else { // We were called by DynamicInvokeParamHelperCore(). He passes a dstEEType that enums folded to int and possibly other adjustments. A custom binder // is app code however and needs the exact type. exactDstType = GetExactTypeForCustomBinder(argSetupState); } srcObject = binderBundle.ChangeType(srcObject, exactDstType); // For compat with desktop, the result of the binder call gets processed through the default rules again. dstObject = CheckArgument(srcObject, dstEEType, semantics, binderBundle: null, ref Unsafe.NullRef <ArgSetupState>()); return(dstObject); } }
internal static object CallIHelperThisCall(object thisPtr, IntPtr methodToCall, object thisPtrForDynamicInvokeHelperMethod, IntPtr dynamicInvokeHelperMethod, ref ArgSetupState argSetupState) { // Calli the dynamicInvokeHelper method with a bunch of parameters As this can't actually be defined in C# there is an IL transform that fills this in. return null; }
internal static object CallIHelperStaticCallWithInstantiation(object thisPtr, IntPtr methodToCall, IntPtr dynamicInvokeHelperMethod, ref ArgSetupState argSetupState, bool isTargetThisCall, IntPtr dynamicInvokeHelperGenericDictionary) { // Calli the dynamicInvokeHelper method with a bunch of parameters As this can't actually be defined in C# there is an IL transform that fills this in. return null; }
internal static object Call( IntPtr dynamicInvokeHelperMethod, IntPtr dynamicInvokeHelperGenericDictionary, object thisPtr, IntPtr methodToCall, ref ArgSetupState argSetupState, bool isTargetThisCall) { // This method is implemented elsewhere in the toolchain throw new PlatformNotSupportedException(); }
internal static object Call( IntPtr dynamicInvokeHelperMethod, object thisPtrForDynamicInvokeHelperMethod, object thisPtr, IntPtr methodToCall, ref ArgSetupState argSetupState) { // This method is implemented elsewhere in the toolchain throw new PlatformNotSupportedException(); }
internal static object CallDynamicInvokeMethod( object thisPtr, IntPtr methodToCall, object thisPtrDynamicInvokeMethod, IntPtr dynamicInvokeHelperMethod, IntPtr dynamicInvokeHelperGenericDictionary, object defaultParametersContext, object[] parameters, bool invokeMethodHelperIsThisCall = true, bool methodToCallIsThisCall = true) { bool fDontWrapInTargetInvocationException = false; bool parametersNeedCopyBack = false; ArgSetupState argSetupState = default(ArgSetupState); // Capture state of thread static invoke helper statics object[] parametersOld = s_parameters; object[] nullableCopyBackObjectsOld = s_nullableCopyBackObjects; int curIndexOld = s_curIndex; object defaultParametersContextOld = s_defaultParametersContext; try { // If the passed in array is not an actual object[] instance, we need to copy it over to an actual object[] // instance so that the rest of the code can safely create managed object references to individual elements. if (parameters != null && EETypePtr.EETypePtrOf <object[]>() != parameters.EETypePtr) { s_parameters = new object[parameters.Length]; Array.Copy(parameters, s_parameters, parameters.Length); parametersNeedCopyBack = true; } else { s_parameters = parameters; } s_nullableCopyBackObjects = null; s_curIndex = 0; s_defaultParametersContext = defaultParametersContext; try { object result = null; if (invokeMethodHelperIsThisCall) { Debug.Assert(methodToCallIsThisCall == true); result = CalliIntrinsics.Call(dynamicInvokeHelperMethod, thisPtrDynamicInvokeMethod, thisPtr, methodToCall, ref argSetupState); System.Diagnostics.DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); } else { if (dynamicInvokeHelperGenericDictionary != IntPtr.Zero) { result = CalliIntrinsics.Call(dynamicInvokeHelperMethod, dynamicInvokeHelperGenericDictionary, thisPtr, methodToCall, ref argSetupState, methodToCallIsThisCall); DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); } else { result = CalliIntrinsics.Call(dynamicInvokeHelperMethod, thisPtr, methodToCall, ref argSetupState, methodToCallIsThisCall); DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); } } return(result); } finally { if (parametersNeedCopyBack) { Array.Copy(s_parameters, parameters, parameters.Length); } if (!argSetupState.fComplete) { fDontWrapInTargetInvocationException = true; } else { // Nullable objects can't take advantage of the ability to update the boxed value on the heap directly, so perform // an update of the parameters array now. if (argSetupState.nullableCopyBackObjects != null) { for (int i = 0; i < argSetupState.nullableCopyBackObjects.Length; i++) { if (argSetupState.nullableCopyBackObjects[i] != null) { parameters[i] = DynamicInvokeBoxIntoNonNullable(argSetupState.nullableCopyBackObjects[i]); } } } } } } catch (Exception e) { if (fDontWrapInTargetInvocationException) { throw; } else { throw new System.Reflection.TargetInvocationException(e); } } finally { // Restore state of thread static helper statics s_parameters = parametersOld; s_nullableCopyBackObjects = nullableCopyBackObjectsOld; s_curIndex = curIndexOld; s_defaultParametersContext = defaultParametersContextOld; } }
internal static object CallIHelperStaticCallWithInstantiation(object thisPtr, IntPtr methodToCall, IntPtr dynamicInvokeHelperMethod, ref ArgSetupState argSetupState, bool isTargetThisCall, IntPtr dynamicInvokeHelperGenericDictionary) { // Calli the dynamicInvokeHelper method with a bunch of parameters As this can't actually be defined in C# there is an IL transform that fills this in. return(null); }
internal static object CallIHelperThisCall(object thisPtr, IntPtr methodToCall, object thisPtrForDynamicInvokeHelperMethod, IntPtr dynamicInvokeHelperMethod, ref ArgSetupState argSetupState) { // Calli the dynamicInvokeHelper method with a bunch of parameters As this can't actually be defined in C# there is an IL transform that fills this in. return(null); }
internal static object CallDynamicInvokeMethod(object thisPtr, IntPtr methodToCall, object thisPtrDynamicInvokeMethod, IntPtr dynamicInvokeHelperMethod, IntPtr dynamicInvokeHelperGenericDictionary, string defaultValueString, object[] parameters, bool invokeMethodHelperIsThisCall = true, bool methodToCallIsThisCall = true) { bool fDontWrapInTargetInvocationException = false; bool parametersNeedCopyBack = false; ArgSetupState argSetupState = default(ArgSetupState); // Capture state of thread static invoke helper statics object[] parametersOld = s_parameters; object[] nullableCopyBackObjectsOld = s_nullableCopyBackObjects; int curIndexOld = s_curIndex; string defaultValueStringOld = s_defaultValueString; try { // If the passed in array is not an actual object[] instance, we need to copy it over to an actual object[] // instance so that the rest of the code can safely create managed object references to individual elements. if (parameters != null && !typeof(object[]).TypeHandle.Equals(new RuntimeTypeHandle(parameters.EETypePtr))) { s_parameters = new object[parameters.Length]; Array.Copy(parameters, s_parameters, parameters.Length); parametersNeedCopyBack = true; } else { s_parameters = parameters; } s_nullableCopyBackObjects = null; s_curIndex = 0; s_defaultValueString = defaultValueString; try { if (invokeMethodHelperIsThisCall) { Debug.Assert(methodToCallIsThisCall == true); return(CallIHelperThisCall(thisPtr, methodToCall, thisPtrDynamicInvokeMethod, dynamicInvokeHelperMethod, ref argSetupState)); } else { if (dynamicInvokeHelperGenericDictionary != IntPtr.Zero) { return(CallIHelperStaticCallWithInstantiation(thisPtr, methodToCall, dynamicInvokeHelperMethod, ref argSetupState, methodToCallIsThisCall, dynamicInvokeHelperGenericDictionary)); } else { return(CallIHelperStaticCall(thisPtr, methodToCall, dynamicInvokeHelperMethod, ref argSetupState, methodToCallIsThisCall)); } } } finally { if (parametersNeedCopyBack) { Array.Copy(s_parameters, parameters, parameters.Length); } if (!argSetupState.fComplete) { fDontWrapInTargetInvocationException = true; } else { // Nullable objects can't take advantage of the ability to update the boxed value on the heap directly, so perform // an update of the parameters array now. if (argSetupState.nullableCopyBackObjects != null) { for (int i = 0; i < argSetupState.nullableCopyBackObjects.Length; i++) { if (argSetupState.nullableCopyBackObjects[i] != null) { parameters[i] = DynamicInvokeBoxIntoNonNullable(argSetupState.nullableCopyBackObjects[i]); } } } } } } catch (Exception e) { if (fDontWrapInTargetInvocationException) { throw; } else { throw new System.Reflection.TargetInvocationException(e); } } finally { // Restore state of thread static helper statics s_parameters = parametersOld; s_nullableCopyBackObjects = nullableCopyBackObjectsOld; s_curIndex = curIndexOld; s_defaultValueString = defaultValueStringOld; } }