示例#1
0
        [MethodImpl(MethodImplOptions.AggressiveInlining)] // forced to ensure no perf drop for small memory buffers (hot path)
        internal static unsafe T[] AllocateUninitializedArray <T>(int length)
        {
            if (RuntimeHelpers.IsReferenceOrContainsReferences <T>())
            {
                return(new T[length]);
            }

            // for debug builds we always want to call AllocateNewArray to detect AllocateNewArray bugs
#if !DEBUG
            // small arrays are allocated using `new[]` as that is generally faster.
            if (length < 2048 / Unsafe.SizeOf <T>())
            {
                return(new T[length]);
            }
#endif
            // kept outside of the small arrays hot path to have inlining without big size growth
            return(AllocateNewUninitializedArray(length));

            T[] AllocateNewUninitializedArray(int length)
            {
                if (length < 0)
                {
                    throw new OverflowException();
                }

                T[] array = null;
                RuntimeImports.RhAllocateUninitializedArray(EETypePtr.EETypePtrOf <T[]>().RawValue, (uint)length, Unsafe.AsPointer(ref array));
                if (array == null)
                {
                    throw new OutOfMemoryException();
                }

                return(array);
            }
        }
示例#2
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 !;
示例#3
0
        internal static string FastAllocateString(int length)
        {
            // We allocate one extra char as an interop convenience so that our strings are null-
            // terminated, however, we don't pass the extra +1 to the string allocation because the base
            // size of this object includes the _firstChar field.
            string newStr = RuntimeImports.RhNewString(EETypePtr.EETypePtrOf <string>(), length);

            Debug.Assert(newStr._stringLength == length);
            return(newStr);
        }
示例#4
0
        public static T CreateInstance <T>()
        {
            T t = default(T);

            bool missingDefaultConstructor = false;

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

            // ProjectN:936613 - Early exit for variable sized types (strings, arrays, etc.) as we cannot call
            // CreateInstanceIntrinsic on them since the intrinsic will attempt to allocate an instance of these types
            // and that is verboten (it results in silent heap corruption!).
            if (eetype.ComponentSize != 0)
            {
                // ComponentSize > 0 indicates an array-like type (e.g. string, array, etc).
                missingDefaultConstructor = true;
            }
            else if (eetype.IsInterface)
            {
                // Do not attempt to allocate interface types either
                missingDefaultConstructor = true;
            }
            else
            {
                bool oldValueOfMissingDefaultCtorMarkerBool = s_createInstanceMissingDefaultConstructor;

                try
                {
                    t = CreateInstanceIntrinsic <T>();
                    System.Diagnostics.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);
        }
示例#5
0
文件: String.cs 项目: loqix/RoseOS
        static unsafe string Ctor(char *ptr, int index, int length)
        {
            var et = EETypePtr.EETypePtrOf <string>();

            var start = ptr + index;
            var data  = StartupCodeHelpers.RhpNewArray(et.Value, length);
            var s     = Unsafe.As <object, string>(ref data);

            fixed(char *c = &s._firstChar)
            {
                Platform.CopyMemory((IntPtr)c, (IntPtr)start, (ulong)length * sizeof(char));
                c[length] = '\0';
            }

            return(s);
        }
示例#6
0
        private static T CreateInstanceIntrinsic <T>()
        {
            // Fallback implementation for codegens that don't support this intrinsic.
            // This uses the type loader and doesn't have the kind of guarantees about it always working
            // as the intrinsic expansion has. Also, it's slower.

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

            // The default(T) check can be evaluated statically and will result in the body of this method
            // becoming empty for valuetype Ts. We still need a dynamic IsNullable check to cover Nullables though.
            // This will obviously need work once we start supporting default valuetype constructors.
            if (default(T) == null && !eetype.IsNullable)
            {
                object o = null;
                TypeLoaderExports.ActivatorCreateInstanceAny(ref o, eetype.RawValue);
                return((T)o);
            }

            return(default(T));
        }
示例#7
0
        // The following 2 methods and helper class implement the functionality of Activator.CreateInstance<T>()

        // This method is the public surface area. It wraps the CreateInstance intrinsic with the appropriate try/catch
        // block so that the correct exceptions are generated. Also, it handles the cases where the T type doesn't have
        // a default constructor. (Those result in running the ClassWithMissingConstructor's .ctor, which flips the magic
        // thread static to cause the CreateInstance<T> method to throw the right exception.)
        //
        public static T CreateInstance <T>()
        {
            T t = default(T);

            bool missingDefaultConstructor = false;

            // ProjectN:936613 - Early exit for variable sized types (strings, arrays, etc.) as we cannot call
            // CreateInstanceIntrinsic on them since the intrinsic will attempt to allocate an instance of these types
            // and that is verboten (it results in silent heap corruption!).
            if (EETypePtr.EETypePtrOf <T>().ComponentSize != 0)
            {
                // ComponentSize > 0 indicates an array-like type (e.g. string, array, etc).
                missingDefaultConstructor = true;
            }
            else
            {
                bool oldValueOfMissingDefaultCtorMarkerBool = s_createInstanceMissingDefaultConstructor;

                try
                {
                    t = CreateInstanceIntrinsic <T>();
                }
                catch (Exception e)
                {
                    throw new TargetInvocationException(e);
                }

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

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

            return(t);
        }
示例#8
0
        internal static unsafe T[] AllocateUninitializedArray <T>(int length)
        {
            if (RuntimeHelpers.IsReferenceOrContainsReferences <T>())
            {
                return(new T[length]);
            }

            if (length < 0)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.lengths, 0, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
            }
#if DEBUG
            // in DEBUG arrays of any length can be created uninitialized
#else
            // otherwise small arrays are allocated using `new[]` as that is generally faster.
            //
            // The threshold was derived from various simulations.
            // As it turned out the threshold depends on overal pattern of all allocations and is typically in 200-300 byte range.
            // The gradient around the number is shallow (there is no perf cliff) and the exact value of the threshold does not matter a lot.
            // So it is 256 bytes including array header.
            if (Unsafe.SizeOf <T>() * length < 256 - 3 * IntPtr.Size)
            {
                return(new T[length]);
            }
#endif

            var pEEType = EETypePtr.EETypePtrOf <T[]>();

            T[] array = null;
            RuntimeImports.RhAllocateUninitializedArray(pEEType.RawValue, (uint)length, Unsafe.AsPointer(ref array));

            if (array == null)
            {
                throw new OutOfMemoryException();
            }

            return(array);
        }
示例#9
0
        public static object ToObject(TypedReference value)
        {
            RuntimeTypeHandle typeHandle = value._typeHandle;

            if (typeHandle.IsNull)
            {
                throw new ArgumentNullException(); // For compatibility.
            }
            EETypePtr eeType = typeHandle.ToEETypePtr();

            if (eeType.IsValueType)
            {
                return(RuntimeImports.RhBox(eeType, ref value.Value));
            }
            else if (eeType.IsPointer)
            {
                return(RuntimeImports.RhBox(EETypePtr.EETypePtrOf <UIntPtr>(), ref value.Value));
            }
            else
            {
                return(Unsafe.As <byte, object>(ref value.Value));
            }
        }
示例#10
0
文件: GC.cs 项目: lvyitian/corert
            static T[] AllocateNewUninitializedArray(int length, bool pinned)
            {
                GC_ALLOC_FLAGS flags = GC_ALLOC_FLAGS.GC_ALLOC_ZEROING_OPTIONAL;

                if (pinned)
                {
                    flags |= GC_ALLOC_FLAGS.GC_ALLOC_PINNED_OBJECT_HEAP;
                }

                if (length < 0)
                {
                    throw new OverflowException();
                }

                T[] array = null;
                RuntimeImports.RhAllocateNewArray(EETypePtr.EETypePtrOf <T[]>().RawValue, (uint)length, (uint)flags, Unsafe.AsPointer(ref array));
                if (array == null)
                {
                    throw new OutOfMemoryException();
                }

                return(array);
            }
示例#11
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;
            }
        }
示例#12
0
文件: Array.cs 项目: z77ma/runtime
 private static unsafe MethodTable *GetSystemArrayEEType()
 {
     return(EETypePtr.EETypePtrOf <Array>().ToPointer());
 }
示例#13
0
文件: Buffer.cs 项目: tmds/corert
        public static unsafe void BlockCopy(Array src, int srcOffset,
                                            Array dst, int dstOffset,
                                            int count)
        {
            nuint uSrcLen;
            nuint uDstLen;

            if (src == null)
            {
                throw new ArgumentNullException(nameof(src));
            }
            if (dst == null)
            {
                throw new ArgumentNullException(nameof(dst));
            }

            // Use optimized path for byte arrays since this is the main scenario for Buffer::BlockCopy
            // We only need an unreliable comparison since the slow path can handle the byte[] case too.
            if (src.EETypePtr.FastEqualsUnreliable(EETypePtr.EETypePtrOf <byte[]>()))
            {
                uSrcLen = (nuint)src.Length;
            }
            else
            {
                RuntimeImports.RhCorElementTypeInfo srcCorElementTypeInfo = src.ElementEEType.CorElementTypeInfo;
                uSrcLen = ((nuint)src.Length) << srcCorElementTypeInfo.Log2OfSize;
                if (!srcCorElementTypeInfo.IsPrimitive)
                {
                    throw new ArgumentException(SR.Arg_MustBePrimArray, nameof(src));
                }
            }

            if (src != dst)
            {
                // Use optimized path for byte arrays since this is the main scenario for Buffer::BlockCopy
                // We only need an unreliable comparison since the slow path can handle the byte[] case too.
                if (dst.EETypePtr.FastEqualsUnreliable(EETypePtr.EETypePtrOf <byte[]>()))
                {
                    uDstLen = (nuint)dst.Length;
                }
                else
                {
                    RuntimeImports.RhCorElementTypeInfo dstCorElementTypeInfo = dst.ElementEEType.CorElementTypeInfo;
                    if (!dstCorElementTypeInfo.IsPrimitive)
                    {
                        throw new ArgumentException(SR.Arg_MustBePrimArray, nameof(dst));
                    }
                    uDstLen = ((nuint)dst.Length) << dstCorElementTypeInfo.Log2OfSize;
                }
            }
            else
            {
                uDstLen = uSrcLen;
            }

            if (srcOffset < 0)
            {
                throw new ArgumentOutOfRangeException(SR.ArgumentOutOfRange_MustBeNonNegInt32, nameof(srcOffset));
            }
            if (dstOffset < 0)
            {
                throw new ArgumentOutOfRangeException(SR.ArgumentOutOfRange_MustBeNonNegInt32, nameof(dstOffset));
            }
            if (count < 0)
            {
                throw new ArgumentOutOfRangeException(SR.ArgumentOutOfRange_MustBeNonNegInt32, nameof(count));
            }

            nuint uCount     = (nuint)count;
            nuint uSrcOffset = (nuint)srcOffset;
            nuint uDstOffset = (nuint)dstOffset;

            if (uSrcLen < uSrcOffset + uCount)
            {
                throw new ArgumentException(SR.Argument_InvalidOffLen);
            }
            if (uDstLen < uDstOffset + uCount)
            {
                throw new ArgumentException(SR.Argument_InvalidOffLen);
            }

            if (uCount != 0)
            {
                fixed(byte *pSrc = &src.GetRawArrayData(), pDst = &dst.GetRawArrayData())
                {
                    Buffer.Memmove(pDst + uDstOffset, pSrc + uSrcOffset, uCount);
                }
            }
        }
示例#14
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);
        }
示例#15
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;
            }
        }