예제 #1
0
파일: Delegate.cs 프로젝트: tomi-kr/corert
        protected virtual object DynamicInvokeImpl(object[] args)
        {
            if (IsDynamicDelegate())
            {
                // DynamicDelegate case
                object result = ((Func <object[], object>)m_helperObject)(args);
                DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
                return(result);
            }
            else
            {
                IntPtr invokeThunk = this.GetThunk(DelegateInvokeThunk);
#if PROJECTN
                object result = InvokeUtils.CallDynamicInvokeMethod(this.m_firstParameter, this.m_functionPointer, this, invokeThunk, IntPtr.Zero, this, args, binderBundle: null, wrapInTargetInvocationException: true);
#else
                IntPtr genericDictionary = IntPtr.Zero;
                if (FunctionPointerOps.IsGenericMethodPointer(invokeThunk))
                {
                    unsafe
                    {
                        GenericMethodDescriptor *descriptor = FunctionPointerOps.ConvertToGenericDescriptor(invokeThunk);
                        genericDictionary = descriptor->InstantiationArgument;
                        invokeThunk       = descriptor->MethodFunctionPointer;
                    }
                }

                object result = InvokeUtils.CallDynamicInvokeMethod(this.m_firstParameter, this.m_functionPointer, null, invokeThunk, genericDictionary, this, args, binderBundle: null, wrapInTargetInvocationException: true, invokeMethodHelperIsThisCall: false);
#endif
                DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
                return(result);
            }
        }
예제 #2
0
파일: Delegate.cs 프로젝트: tomi-kr/corert
        public object DynamicInvoke(params object[] args)
        {
            object result = DynamicInvokeImpl(args);

            DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
            return(result);
        }
예제 #3
0
        public static unsafe T CreateInstance <[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] T>()
        {
            // Grab the pointer to the default constructor of the type. If T doesn't have a default
            // constructor, the intrinsic returns a marker pointer that we check for.
            IntPtr defaultConstructor = DefaultConstructorOf <T>();

            // Check if we got the marker back.
            //
            // TODO: might want to disambiguate the different cases for abstract class, interface, etc.
            if (defaultConstructor == (IntPtr)(delegate * < Guid >) & MissingConstructorMethod)
            {
                throw new MissingMethodException(SR.Format(SR.MissingConstructor_Name, typeof(T)));
            }

            T t;

            try
            {
                // Call the default constructor on the allocated instance.
                if (RuntimeHelpers.IsReference <T>())
                {
                    // Grab a pointer to the optimized allocator for the type and call it.
                    IntPtr allocator = AllocatorOf <T>();
                    t = RawCalliHelper.Call <T>(allocator, EETypePtr.EETypePtrOf <T>().RawValue);
                    RawCalliHelper.Call(defaultConstructor, t);

                    // Debugger goo so that stepping in works. Only affects debug info generation.
                    // The call gets optimized away.
                    DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
                }
                else
                {
                    t = default !;
예제 #4
0
        private unsafe ref byte InvokeWithManyArguments(
            IntPtr methodToCall, ref byte thisArg, ref byte ret,
            object?[] parameters, BinderBundle binderBundle, bool wrapInTargetInvocationException)
        {
            int argCount = _argumentCount;

            // We don't check a max stack size since we are invoking a method which
            // naturally requires a stack size that is dependent on the arg count\size.
            IntPtr *pStorage = stackalloc IntPtr[2 * argCount];

            NativeMemory.Clear(pStorage, (nuint)(2 * argCount) * (nuint)sizeof(IntPtr));

            ByReference *pByRefStorage = (ByReference *)(pStorage + argCount);

            RuntimeImports.GCFrameRegistration regArgStorage   = new(pStorage, (uint)argCount, areByRefs : false);
            RuntimeImports.GCFrameRegistration regByRefStorage = new(pByRefStorage, (uint)argCount, areByRefs : true);

            try
            {
                RuntimeImports.RhRegisterForGCReporting(&regArgStorage);
                RuntimeImports.RhRegisterForGCReporting(&regByRefStorage);

                CheckArguments(ref Unsafe.As <IntPtr, object>(ref *pStorage), pByRefStorage, parameters, binderBundle);

                try
                {
                    ret = ref RawCalliHelper.Call(InvokeThunk, (void *)methodToCall, ref thisArg, ref ret, pByRefStorage);
                    DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
                }
                catch (Exception e) when(wrapInTargetInvocationException)
                {
                    throw new TargetInvocationException(e);
                }
                finally
                {
                    if (_needsCopyBack)
                    {
                        CopyBack(ref Unsafe.As <IntPtr, object>(ref *pStorage), parameters);
                    }
                }
            }
            finally
            {
                RuntimeImports.RhUnregisterForGCReporting(&regByRefStorage);
                RuntimeImports.RhUnregisterForGCReporting(&regArgStorage);
            }

            return(ref ret);
        }
예제 #5
0
 protected virtual object DynamicInvokeImpl(object[] args)
 {
     if (IsDynamicDelegate())
     {
         // DynamicDelegate case
         object result = ((Func <object[], object>)m_helperObject)(args);
         DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
         return(result);
     }
     else
     {
         IntPtr invokeThunk = this.GetThunk(DelegateInvokeThunk);
         object result      = System.InvokeUtils.CallDynamicInvokeMethod(this.m_firstParameter, this.m_functionPointer, this, invokeThunk, IntPtr.Zero, this, args, binderBundle: null);
         DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
         return(result);
     }
 }
예제 #6
0
        protected virtual object?DynamicInvokeImpl(object?[]?args)
        {
            if (IsDynamicDelegate())
            {
                // DynamicDelegate case
                object?result = ((Func <object?[]?, object?>)m_helperObject)(args);
                DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
                return(result);
            }
            else
            {
                DynamicInvokeInfo dynamicInvokeInfo = ReflectionAugments.ReflectionCoreCallbacks.GetDelegateDynamicInvokeInfo(GetType());

                object?result = dynamicInvokeInfo.Invoke(m_firstParameter, m_functionPointer,
                                                         args, binderBundle: null, wrapInTargetInvocationException: true);
                DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
                return(result);
            }
        }
예제 #7
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;
            }
        }
예제 #8
0
        public static T CreateInstance <T>()
        {
            T t = default(T);

            bool missingDefaultConstructor = false;

            EETypePtr eetype = EETypePtr.EETypePtrOf <T>();

            if (!RuntimeHelpers.IsReference <T>())
            {
                // Early out for valuetypes since we don't support default constructors anyway.
                // This lets codegens that expand IsReference<T> optimize away the rest of this code.
            }
            else if (eetype.ComponentSize != 0)
            {
                // ComponentSize > 0 indicates an array-like type (e.g. string, array, etc).
                // Allocating this using the normal allocator would result in silent heap corruption.
                missingDefaultConstructor = true;
            }
            else if (eetype.IsInterface)
            {
                // Do not attempt to allocate interface types either
                missingDefaultConstructor = true;
            }
            else
            {
                bool oldValueOfMissingDefaultCtorMarkerBool = s_createInstanceMissingDefaultConstructor;

                try
                {
                    t = (T)(RuntimeImports.RhNewObject(eetype));

                    // Run the default constructor. If the default constructor was missing, codegen
                    // will expand DefaultConstructorOf to ClassWithMissingConstructor::.ctor
                    // and we detect that later.
                    IntPtr defaultConstructor = DefaultConstructorOf <T>();
                    RawCalliHelper.Call(defaultConstructor, t);
                    DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
                }
                catch (Exception e)
                {
                    throw new TargetInvocationException(e);
                }

                if (s_createInstanceMissingDefaultConstructor != oldValueOfMissingDefaultCtorMarkerBool)
                {
                    missingDefaultConstructor = true;

                    // We didn't call the real .ctor (because there wasn't one), but we still allocated
                    // an uninitialized object. If it has a finalizer, it would run - prevent that.
                    GC.SuppressFinalize(t);
                }
            }

            if (missingDefaultConstructor)
            {
                throw new MissingMethodException(SR.Format(SR.MissingConstructor_Name, typeof(T)));
            }

            return(t);
        }
예제 #9
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;
            }
        }
예제 #10
0
        public unsafe object?Invoke(
            object?thisPtr,
            IntPtr methodToCall,
            object?[]?parameters,
            BinderBundle?binderBundle,
            bool wrapInTargetInvocationException)
        {
            int argCount = parameters?.Length ?? 0;

            if (argCount != _argumentCount)
            {
                if (_argumentCount < 0)
                {
                    if (_argumentCount == ArgumentCount_NotSupported_ByRefLike)
                    {
                        throw new NotSupportedException(SR.NotSupported_ByRefLike);
                    }
                    throw new NotSupportedException();
                }

                throw new TargetParameterCountException(SR.Arg_ParmCnt);
            }

            object?returnObject = null;

            scoped ref byte thisArg = ref Unsafe.NullRef <byte>();

            if (!_isStatic)
            {
                // The caller is expected to validate this
                Debug.Assert(thisPtr != null);

                // See TODO comment in DynamicInvokeMethodThunk.NormalizeSignature
                // if (_isValueTypeInstanceMethod)
                // {
                //     // thisArg is a raw data byref for valuetype instance methods
                //     thisArg = ref thisPtr.GetRawData();
                // }
                // else
                {
                    thisArg = ref Unsafe.As <object?, byte>(ref thisPtr);
                }
            }

            scoped ref byte ret = ref Unsafe.As <object?, byte>(ref returnObject);

            if ((_returnTransform & Transform.AllocateReturnBox) != 0)
            {
                returnObject = RuntimeImports.RhNewObject(
                    (_returnTransform & Transform.Pointer) != 0 ?
                    EETypePtr.EETypePtrOf <IntPtr>() : _returnType);
                ret = ref returnObject.GetRawData();
            }

            if (argCount == 0)
            {
                try
                {
                    ret = ref RawCalliHelper.Call(InvokeThunk, (void *)methodToCall, ref thisArg, ref ret, null);
                    DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
                }
                catch (Exception e) when(wrapInTargetInvocationException)
                {
                    throw new TargetInvocationException(e);
                }
            }
            else if (argCount > MaxStackAllocArgCount)
            {
                ret = ref InvokeWithManyArguments(methodToCall, ref thisArg, ref ret,
                                                  parameters, binderBundle, wrapInTargetInvocationException);
            }
            else
            {
                StackAllocedArguments argStorage   = default;
                StackAllocatedByRefs  byrefStorage = default;

                CheckArguments(ref argStorage._arg0 !, (ByReference *)&byrefStorage, parameters, binderBundle);

                try
                {
                    ret = ref RawCalliHelper.Call(InvokeThunk, (void *)methodToCall, ref thisArg, ref ret, &byrefStorage);
                    DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
                }
                catch (Exception e) when(wrapInTargetInvocationException)
                {
                    throw new TargetInvocationException(e);
                }
                finally
                {
                    if (_needsCopyBack)
                    {
                        CopyBack(ref argStorage._arg0 !, parameters);
                    }
                }
            }

            return(((_returnTransform & (Transform.Nullable | Transform.Pointer | Transform.ByRef)) != 0) ?
                   ReturnTransform(ref ret, wrapInTargetInvocationException) : returnObject);
        }