Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[mono] When creating an array type, don't do full initialization of t…
…he element type (#85828) Consider code like this: ```csharp public class Node<T> { public Node<T>[][] Children; } Console.WriteLine (typeof(Node<int>)); ``` In this case, when we're JITing ``ldtoken class Node`1<int32>`` we first have to parse the type ``Node`1<int32>`` and initialize it. When we're initializing it, we need to resolve the types of all the fields in the class in order to to figure out if its instance size. To resolve the field types we have to parse the types of all the fields, and we eventually end up parsing the type ``Node`1<!0>[][]`` which ends up here: https://github.com/dotnet/runtime/blob/558345d16cf76525d0c7fdbafbfd3a2457142b39/src/mono/mono/metadata/metadata.c#L4023-L4027 When we get to line 4027 the second time (recursively), `etype` is ``Node`1<!0>`` as a `MonoType*`. And we want to set `type->data.klass` to its corresponding `MonoClass*`. That ends up calling `mono_class_from_mono_type_internal`, which does this: https://github.com/dotnet/runtime/blob/558345d16cf76525d0c7fdbafbfd3a2457142b39/src/mono/mono/metadata/class.c#L2214-L2215 When we call `mono_class_create_array` we end up here: https://github.com/dotnet/runtime/blob/558345d16cf76525d0c7fdbafbfd3a2457142b39/src/mono/mono/metadata/class-init.c#L1186-L1187 with `eclass` equal to ``Node`1<!0>` which we try to initialize and we get a TLE because we're going to try to initialize the same generic type definition ``Node`1`` twice. Compare with this other class: ```csharp public unsafe class Node2<T> { public Node2<T>[] Children; } ``` In this case we only end up calling `mono_class_from_mono_type_internal` on ``Node2`1<int32>`` (not an array). And that branch does not do any initialization - it just returns `type->data.klass` (for ``Node2`1<!0>`` - which is seen as a gtd at this point) or `mono_class_create_generic_inst (type->data.generic_class)` (for ``Node2`1<int32>`` which is seen later when `ldtoken` inflates the gtd)) - without any extra initialization. --- It seems the reason we get into trouble is because `mono_class_create_array` does more work than other `MonoClass` creation functions - it tries to initialize the `MonoClass` a little bit (for example by setting `MonoClass:has_references`) which needs at least a little bit of the element class to be initialized. But note that the code has this: https://github.com/dotnet/runtime/blob/558345d16cf76525d0c7fdbafbfd3a2457142b39/src/mono/mono/metadata/class-init.c#L1186-L1189 I feel fairly certain we don't need the full class initialization if we're going to immediately initialize the field size information. Fixes #85821
- Loading branch information