From 0be3889fd32ecc43c3111bddecd765b6da1ad993 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Tue, 25 Jul 2023 17:26:43 -0400 Subject: [PATCH] [mono] Disable gsharing when Unsafe.ReadUnaligned/WriteUnaligned () is used with generic structures. (#89417) Fixes https://github.com/dotnet/runtime/issues/89398. For a method like ``` static void Write(ref byte b, T value) => Unsafe.WriteUnaligned(ref b, value); ``` And an instance ```Write>```, generic sharing will create a ```Write``` instance where T_INST is constrained to GStruct. The JIT currently calls ```mini_get_underlying_type ()``` in many places which transform T_INST into GStruct. This causes problems at runtime in the generic sharing code, which expects to find T_INST. I.e. ```inflate_info ()``` can inflate ```T_INST``` to ```GStruct```, but it can't inflate ```GStruct``` to ```GStruct```. As a workaround, disable gsharing in (some) of these cases. --- src/mono/mono/mini/intrinsics.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/mono/mono/mini/intrinsics.c b/src/mono/mono/mini/intrinsics.c index 68dc78bd22bc4..0230105303a83 100644 --- a/src/mono/mono/mini/intrinsics.c +++ b/src/mono/mono/mini/intrinsics.c @@ -554,6 +554,8 @@ MONO_RESTORE_WARNING t = ctx->method_inst->type_argv [0]; t = mini_get_underlying_type (t); + if (cfg->gshared && t != ctx->method_inst->type_argv [0] && MONO_TYPE_ISSTRUCT (t) && mono_class_check_context_used (mono_class_from_mono_type_internal (t))) + cfg->prefer_instances = TRUE; return mini_emit_memory_load (cfg, t, args [0], 0, MONO_INST_UNALIGNED); } else if (!strcmp (cmethod->name, "WriteUnaligned")) { g_assert (ctx); @@ -562,7 +564,10 @@ MONO_RESTORE_WARNING g_assert (fsig->param_count == 2); t = ctx->method_inst->type_argv [0]; + t = mini_get_underlying_type (t); + if (cfg->gshared && t != ctx->method_inst->type_argv [0] && MONO_TYPE_ISSTRUCT (t) && mono_class_check_context_used (mono_class_from_mono_type_internal (t))) + cfg->prefer_instances = TRUE; mini_emit_memory_store (cfg, t, args [0], args [1], MONO_INST_UNALIGNED); MONO_INST_NEW (cfg, ins, OP_NOP); MONO_ADD_INS (cfg->cbb, ins);