From 3914bd8b6869f31c22609d0f28a93a9051ccbf1f Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Tue, 9 Mar 2021 20:40:55 -0500 Subject: [PATCH] [mono] Fix the emission of EnumEqualityComparer instances into the corlib AOT image. Add a few dummy enums to the Mono namespace in corlib, and use them to create valid EnumEqualityComparer instances. Also make sure the instances are actually emitted and not replaced by gsharedvt instances. Fixes https://github.com/dotnet/runtime/issues/49229. --- .../src/ILLink/ILLink.Descriptors.xml | 9 ++++++ .../src/Mono/RuntimeStructs.cs | 32 +++++++++++++++++++ src/mono/mono/mini/aot-compiler.c | 29 +++++++++++++---- 3 files changed, 63 insertions(+), 7 deletions(-) diff --git a/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml b/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml index a327adba23fc3..f066b8f010d43 100644 --- a/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml +++ b/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml @@ -618,6 +618,15 @@ + + + + + + + + + diff --git a/src/mono/System.Private.CoreLib/src/Mono/RuntimeStructs.cs b/src/mono/System.Private.CoreLib/src/Mono/RuntimeStructs.cs index e566558967218..b327ae3733f9e 100644 --- a/src/mono/System.Private.CoreLib/src/Mono/RuntimeStructs.cs +++ b/src/mono/System.Private.CoreLib/src/Mono/RuntimeStructs.cs @@ -118,6 +118,38 @@ internal struct ValueTuple public T5 Item5; } + internal enum I8Enum : byte + { + } + + internal enum UI8Enum : sbyte + { + } + + internal enum I16Enum : short + { + } + + internal enum UI16Enum : ushort + { + } + + internal enum I32Enum : int + { + } + + internal enum UI32Enum : uint + { + } + + internal enum I64Enum : long + { + } + + internal enum UI64Enum : ulong + { + } + internal class NullByRefReturnException : Exception { public NullByRefReturnException() diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 6d97bf9c859bf..b30835fc288fb 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -5185,6 +5185,19 @@ is_vt_inst (MonoGenericInst *inst) return FALSE; } +static gboolean +is_vt_inst_no_enum (MonoGenericInst *inst) +{ + int i; + + for (i = 0; i < inst->type_argc; ++i) { + MonoType *t = inst->type_argv [i]; + if (MONO_TYPE_ISSTRUCT (t)) + return TRUE; + } + return FALSE; +} + static gboolean method_has_type_vars (MonoMethod *method) { @@ -5338,7 +5351,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth, * WASM only since other platforms depend on the * previous behavior. */ - if ((acfg->jit_opts & MONO_OPT_GSHAREDVT) && mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->context.class_inst && is_vt_inst (mono_class_get_generic_class (klass)->context.class_inst)) { + if ((acfg->jit_opts & MONO_OPT_GSHAREDVT) && mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->context.class_inst && is_vt_inst_no_enum (mono_class_get_generic_class (klass)->context.class_inst)) { use_gsharedvt = TRUE; use_gsharedvt_for_array = TRUE; } @@ -5758,17 +5771,19 @@ add_generic_instances (MonoAotCompile *acfg) /* Add instances of EnumEqualityComparer which are created by EqualityComparer for enums */ { - MonoClass *enum_comparer; + MonoClass *k, *enum_comparer; MonoType *insts [16]; int ninsts; + const char *enum_names [] = { "I8Enum", "I16Enum", "I32Enum", "I64Enum", "UI8Enum", "UI16Enum", "UI32Enum", "UI64Enum" }; ninsts = 0; - insts [ninsts ++] = int32_type; - insts [ninsts ++] = uint32_type; - insts [ninsts ++] = uint16_type; - insts [ninsts ++] = byte_type; + for (int i = 0; i < G_N_ELEMENTS (enum_names); ++i) { + k = mono_class_try_load_from_name (acfg->image, "Mono", enum_names [i]); + g_assert (k); + insts [ninsts ++] = m_class_get_byval_arg (k); + } enum_comparer = mono_class_load_from_name (mono_defaults.corlib, "System.Collections.Generic", "EnumEqualityComparer`1"); - add_instances_of (acfg, enum_comparer, insts, ninsts, FALSE); + add_instances_of (acfg, enum_comparer, insts, ninsts, TRUE); } /* Add instances of the array generic interfaces for primitive types */