Esempio n. 1
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 !;
Esempio n. 2
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);
        }
Esempio n. 3
0
        private static unsafe void RunFunctionWithConservativelyReportedBufferInternal <T>(int cbBuffer, IntPtr pfnTargetToInvoke, ref T context, ref RuntimeImports.ConservativelyReportedRegionDesc regionDesc)
        {
            fixed(RuntimeImports.ConservativelyReportedRegionDesc *pRegionDesc = &regionDesc)
            {
                int cbBufferAligned = (cbBuffer + (sizeof(IntPtr) - 1)) & ~(sizeof(IntPtr) - 1);
                // The conservative region must be IntPtr aligned, and a multiple of IntPtr in size
                void *region = stackalloc IntPtr[cbBufferAligned / sizeof(IntPtr)];

                RuntimeImports.RhInitializeConservativeReportingRegion(pRegionDesc, region, cbBufferAligned);

                RawCalliHelper.Call <T>(pfnTargetToInvoke, region, ref context);

                RuntimeImports.RhDisableConservativeReportingRegion(pRegionDesc);
            }
        }
Esempio n. 4
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);
        }
Esempio n. 5
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);
        }