Fix creation of pointer arrays (#79433)
authorMichal Strehovský <MichalStrehovsky@users.noreply.github.com>
Fri, 9 Dec 2022 09:16:51 +0000 (18:16 +0900)
committerGitHub <noreply@github.com>
Fri, 9 Dec 2022 09:16:51 +0000 (18:16 +0900)
Creation of pointer arrays is on a similar plan to multi-dim arrays - we create them from a template type, but the template is slightly wrong. Previously, EETypeCreator would massage the bits into the correct shape, but now we mostly just copy the bits from the template. Use a more precise template for pointer arrays.

Without this, the base size and element type of pointer arrays was slightly wrong.

I'm also deleting the duplicated "use a special template for this one" logic.

src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/EETypeCreator.cs
src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilderState.cs

index f9b419a..d848d2d 100644 (file)
@@ -658,14 +658,6 @@ namespace Internal.Runtime.TypeLoader
 
                 pTemplateEEType = templateTypeHandle.ToEETypePtr();
             }
-            else if (type.IsMdArray || (type.IsSzArray && ((ArrayType)type).ElementType.IsPointer))
-            {
-                // Multidimensional arrays and szarrays of pointers don't implement generic interfaces and
-                // we don't need to do much for them in terms of type building. We can pretty much just take
-                // the MethodTable for any of those, massage the bits that matter (GCDesc, element type,
-                // component size,...) to be of the right shape and we're done.
-                pTemplateEEType = typeof(object[,]).TypeHandle.ToEETypePtr();
-            }
             else
             {
                 Debug.Assert(state.TemplateType != null && !state.TemplateType.RuntimeTypeHandle.IsNull());
index 7cf922f..38ca0c0 100644 (file)
@@ -56,9 +56,9 @@ namespace Internal.Runtime.TypeLoader
             {
                 if (!_templateComputed)
                 {
-                    // Multidimensional arrays and szarrays of pointers don't implement generic interfaces and are special cases. They use
+                    // Multidimensional arrays don't implement generic interfaces and are special cases. They use
                     // typeof(object[,]) as their template.
-                    if (TypeBeingBuilt.IsMdArray || (TypeBeingBuilt.IsSzArray && ((ArrayType)TypeBeingBuilt).ElementType.IsPointer))
+                    if (TypeBeingBuilt.IsMdArray)
                     {
                         _templateType = TypeBeingBuilt.Context.ResolveRuntimeTypeHandle(typeof(object[,]).TypeHandle);
                         _templateTypeLoaderNativeLayout = false;
@@ -67,6 +67,17 @@ namespace Internal.Runtime.TypeLoader
                         return _templateType;
                     }
 
+                    // Arrays of pointers don't implement generic interfaces and are special cases. They use
+                    // typeof(char*[]) as their template.
+                    if (TypeBeingBuilt.IsSzArray && ((ArrayType)TypeBeingBuilt).ElementType.IsPointer)
+                    {
+                        _templateType = TypeBeingBuilt.Context.ResolveRuntimeTypeHandle(typeof(char*[]).TypeHandle);
+                        _templateTypeLoaderNativeLayout = false;
+                        _nativeLayoutComputed = _nativeLayoutTokenComputed = _templateComputed = true;
+
+                        return _templateType;
+                    }
+
                     // Locate the template type and native layout info
                     _templateType = TemplateLocator.TryGetTypeTemplate(TypeBeingBuilt, ref _nativeLayoutInfo);
                     Debug.Assert(_templateType == null || !_templateType.RuntimeTypeHandle.IsNull());