[NativeAOT] simpler ObjectHasComponentSize (#83374)
authorVladimir Sadov <vsadov@microsoft.com>
Tue, 14 Mar 2023 19:47:48 +0000 (12:47 -0700)
committerGitHub <noreply@github.com>
Tue, 14 Mar 2023 19:47:48 +0000 (12:47 -0700)
* simplified ObjectHasComponentSize

* removes EETypePtr.ComponentSize and EETypePtr.IsAbstract

* call entire GetUninitializedObject on nullable underlying type (for static ctors)

src/coreclr/nativeaot/System.Private.CoreLib/src/System/Array.NativeAot.cs
src/coreclr/nativeaot/System.Private.CoreLib/src/System/EETypePtr.cs
src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.NativeAot.cs
src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs
src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs

index 3ca6538..5db1d3e 100644 (file)
@@ -759,11 +759,11 @@ namespace System
             if (array == null)
                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
 
-            EETypePtr eeType = array.GetEETypePtr();
-            nuint totalByteLength = eeType.ComponentSize * array.NativeLength;
+            MethodTable* mt = array.GetMethodTable();
+            nuint totalByteLength = mt->ComponentSize * array.NativeLength;
             ref byte pStart = ref MemoryMarshal.GetArrayDataReference(array);
 
-            if (!eeType.ContainsGCPointers)
+            if (!mt->ContainsGCPointers)
             {
                 SpanHelpers.ClearWithoutReferences(ref pStart, totalByteLength);
             }
@@ -782,10 +782,10 @@ namespace System
             ref byte p = ref Unsafe.As<RawArrayData>(array).Data;
             int lowerBound = 0;
 
-            EETypePtr eeType = array.GetEETypePtr();
-            if (!eeType.IsSzArray)
+            MethodTable* mt = array.GetMethodTable();
+            if (!mt->IsSzArray)
             {
-                int rank = eeType.ArrayRank;
+                int rank = mt->ArrayRank;
                 lowerBound = Unsafe.Add(ref Unsafe.As<byte, int>(ref p), rank);
                 p = ref Unsafe.Add(ref p, 2 * sizeof(int) * rank); // skip the bounds
             }
@@ -795,12 +795,12 @@ namespace System
             if (index < lowerBound || offset < 0 || length < 0 || (uint)(offset + length) > array.NativeLength)
                 ThrowHelper.ThrowIndexOutOfRangeException();
 
-            nuint elementSize = eeType.ComponentSize;
+            nuint elementSize = mt->ComponentSize;
 
             ref byte ptr = ref Unsafe.AddByteOffset(ref p, (uint)offset * elementSize);
             nuint byteLength = (uint)length * elementSize;
 
-            if (eeType.ContainsGCPointers)
+            if (mt->ContainsGCPointers)
             {
                 Debug.Assert(byteLength % (nuint)sizeof(IntPtr) == 0);
                 SpanHelpers.ClearWithReferences(ref Unsafe.As<byte, IntPtr>(ref ptr), byteLength / (uint)sizeof(IntPtr));
@@ -1037,11 +1037,11 @@ namespace System
         //
         // Return storage size of an individual element in bytes.
         //
-        internal nuint ElementSize
+        internal unsafe nuint ElementSize
         {
             get
             {
-                return this.GetEETypePtr().ComponentSize;
+                return this.GetMethodTable()->ComponentSize;
             }
         }
 
index 5e51645..70b85c6 100644 (file)
@@ -231,14 +231,6 @@ namespace System
             }
         }
 
-        internal bool IsAbstract
-        {
-            get
-            {
-                return _value->IsAbstract;
-            }
-        }
-
         internal bool IsByRefLike
         {
             get
@@ -318,14 +310,6 @@ namespace System
             }
         }
 
-        internal ushort ComponentSize
-        {
-            get
-            {
-                return _value->ComponentSize;
-            }
-        }
-
         internal uint BaseSize
         {
             get
index fffb184..7516c5b 100644 (file)
@@ -242,10 +242,9 @@ namespace System.Runtime.CompilerServices
         // Returns true iff the object has a component size;
         // i.e., is variable length like System.String or Array.
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal static bool ObjectHasComponentSize(object obj)
+        internal static unsafe bool ObjectHasComponentSize(object obj)
         {
-            Debug.Assert(obj != null);
-            return obj.GetEETypePtr().ComponentSize != 0;
+            return GetMethodTable(obj)->HasComponentSize;
         }
 
         public static void PrepareMethod(RuntimeMethodHandle method)
@@ -286,7 +285,7 @@ namespace System.Runtime.CompilerServices
             Justification = "We keep class constructors of all types with an MethodTable")]
         [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2072:UnrecognizedReflectionPattern",
             Justification = "Constructed MethodTable of a Nullable forces a constructed MethodTable of the element type")]
-        public static object GetUninitializedObject(
+        public static unsafe object GetUninitializedObject(
             // This API doesn't call any constructors, but the type needs to be seen as constructed.
             // A type is seen as constructed if a constructor is kept.
             // This obviously won't cover a type with no constructor. Reference types with no
@@ -320,37 +319,38 @@ namespace System.Runtime.CompilerServices
                 throw new NotSupportedException(SR.NotSupported_ManagedActivation);
             }
 
-            EETypePtr eeTypePtr = type.TypeHandle.ToEETypePtr();
+            MethodTable* mt = type.TypeHandle.ToMethodTable();
 
-            if (eeTypePtr.ElementType == Internal.Runtime.EETypeElementType.Void)
+            if (mt->ElementType == Internal.Runtime.EETypeElementType.Void)
             {
                 throw new ArgumentException(SR.Argument_InvalidValue);
             }
 
             // Don't allow strings (we already checked for arrays above)
-            if (eeTypePtr.ComponentSize != 0)
+            if (mt->HasComponentSize)
             {
                 throw new ArgumentException(SR.Argument_NoUninitializedStrings);
             }
 
-            if (RuntimeImports.AreTypesAssignable(eeTypePtr, EETypePtr.EETypePtrOf<Delegate>()))
+            if (RuntimeImports.AreTypesAssignable(mt, MethodTable.Of<Delegate>()))
             {
                 throw new MemberAccessException();
             }
 
-            if (eeTypePtr.IsAbstract)
+            if (mt->IsAbstract)
             {
                 throw new MemberAccessException(SR.Acc_CreateAbst);
             }
 
-            if (eeTypePtr.IsByRefLike)
+            if (mt->IsByRefLike)
             {
                 throw new NotSupportedException(SR.NotSupported_ByRefLike);
             }
 
-            if (eeTypePtr.IsNullable)
+            if (mt->IsNullable)
             {
-                return GetUninitializedObject(Type.GetTypeFromEETypePtr(eeTypePtr.NullableType));
+                mt = mt->NullableType;
+                return GetUninitializedObject(Type.GetTypeFromEETypePtr(new EETypePtr(mt)));
             }
 
             // Triggering the .cctor here is slightly different than desktop/CoreCLR, which
@@ -358,7 +358,7 @@ namespace System.Runtime.CompilerServices
             // in MethodTable just for this API to behave slightly differently.
             RunClassConstructor(type.TypeHandle);
 
-            return RuntimeImports.RhNewObject(eeTypePtr);
+            return RuntimeImports.RhNewObject(mt);
         }
     }
 
index 650d992..e0e9ecf 100644 (file)
@@ -305,7 +305,7 @@ namespace System.Runtime
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [RuntimeImport(RuntimeLibrary, "RhTypeCast_AreTypesAssignable")]
-        private static extern unsafe bool AreTypesAssignable(MethodTable* pSourceType, MethodTable* pTargetType);
+        internal static extern unsafe bool AreTypesAssignable(MethodTable* pSourceType, MethodTable* pTargetType);
 
         internal static unsafe bool AreTypesAssignable(EETypePtr pSourceType, EETypePtr pTargetType)
             => AreTypesAssignable(pSourceType.ToPointer(), pTargetType.ToPointer());
@@ -351,7 +351,7 @@ namespace System.Runtime
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [RuntimeImport(RuntimeLibrary, "RhNewObject")]
-        private static extern unsafe object RhNewObject(MethodTable* pEEType);
+        internal static extern unsafe object RhNewObject(MethodTable* pEEType);
 
         internal static unsafe object RhNewObject(EETypePtr pEEType)
             => RhNewObject(pEEType.ToPointer());
index 433ecd5..ffd6d9d 100644 (file)
@@ -118,6 +118,12 @@ namespace System
             return new EETypePtr(_value);
         }
 
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal MethodTable* ToMethodTable()
+        {
+            return (MethodTable*)_value;
+        }
+
         internal bool IsNull
         {
             get