示例#1
0
 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();
 }
示例#2
0
        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;
        }
示例#3
0
        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);
        }
示例#4
0
        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;
            }
        }
示例#5
0
        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;
        }
示例#6
0
        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);
            }
        }
示例#7
0
 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;
 }
示例#8
0
 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;
 }
示例#9
0
 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();
 }
示例#10
0
        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;
        }
示例#11
0
 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();
 }
示例#12
0
        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;
            }
        }
示例#13
0
 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);
 }
示例#14
0
 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);
 }
示例#15
0
        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;
            }
        }