From 3d531ba62551abca0ca0d679ae0d4e8a31cf1b67 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Sun, 2 Jul 2017 02:08:44 -0400 Subject: [jit] Use the right type when handling shared versions of RuntimeHelpers.IsReferenceOrContainsReferences (). The previous version only worked by accident. (#5160) --- mono/mini/generics.cs | 21 +++++++++++++++++++++ mono/mini/gshared.cs | 24 ++++++++++++++++++++++++ mono/mini/method-to-ir.c | 14 ++++++++++---- 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/mono/mini/generics.cs b/mono/mini/generics.cs index e9b41a64e08..eafbd1c0e54 100644 --- a/mono/mini/generics.cs +++ b/mono/mini/generics.cs @@ -1314,6 +1314,13 @@ class Tests return RuntimeHelpers.IsReferenceOrContainsReferences (); } + class IsRefClass { + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public bool is_ref () { + return RuntimeHelpers.IsReferenceOrContainsReferences (); + } + } + [MethodImplAttribute (MethodImplOptions.NoInlining)] public static bool is_ref_or_contains_refs_gen_ref () { return RuntimeHelpers.IsReferenceOrContainsReferences> (); @@ -1343,6 +1350,12 @@ class Tests int i; } + struct AStruct3 { + T1 t1; + T2 t2; + T3 t3; + } + public static int test_0_isreference_intrins () { if (RuntimeHelpers.IsReferenceOrContainsReferences ()) return 1; @@ -1368,6 +1381,14 @@ class Tests if (is_ref_or_contains_refs_gen_noref ()) return 10; + // Complex type from shared class method + var c1 = new IsRefClass> (); + if (c1.is_ref ()) + return 11; + var c2 = new IsRefClass> (); + if (!c2.is_ref ()) + return 12; + return 0; } } diff --git a/mono/mini/gshared.cs b/mono/mini/gshared.cs index 29943694c72..61402f7a4ec 100644 --- a/mono/mini/gshared.cs +++ b/mono/mini/gshared.cs @@ -1972,6 +1972,30 @@ public class Tests gsharedvt_vphi (0); return 0; } + + struct AStruct3 { + T1 t1; + T2 t2; + T3 t3; + } + + interface IFaceIsRef { + bool is_ref (); + } + + class ClassIsRef : IFaceIsRef { + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public bool is_ref () { + return RuntimeHelpers.IsReferenceOrContainsReferences (); + } + } + + public static int test_0_isreference_intrins () { + IFaceIsRef iface = new ClassIsRef (); + Console.WriteLine ("X: " + iface.is_ref> ()); + Console.WriteLine ("X: " + iface.is_ref> ()); + return 0; + } } // #13191 diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index 770bd88ea48..326e6c1f9d2 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -5407,11 +5407,15 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign g_assert (ctx); g_assert (ctx->method_inst); g_assert (ctx->method_inst->type_argc == 1); - MonoType *t = mini_get_underlying_type (ctx->method_inst->type_argv [0]); - MonoClass *klass = mono_class_from_mono_type (t); + MonoType *arg_type = ctx->method_inst->type_argv [0]; + MonoType *t; + MonoClass *klass; ins = NULL; + /* Resolve the argument class as possible so we can handle common cases fast */ + t = mini_get_underlying_type (arg_type); + klass = mono_class_from_mono_type (t); mono_class_init (klass); if (MONO_TYPE_IS_REFERENCE (t)) EMIT_NEW_ICONST (cfg, ins, 1); @@ -5424,10 +5428,12 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign else { g_assert (cfg->gshared); - int context_used = mini_class_check_context_used (cfg, klass); + /* Have to use the original argument class here */ + MonoClass *arg_class = mono_class_from_mono_type (arg_type); + int context_used = mini_class_check_context_used (cfg, arg_class); /* This returns 1 or 2 */ - MonoInst *info = mini_emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS); + MonoInst *info = mini_emit_get_rgctx_klass (cfg, context_used, arg_class, MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS); int dreg = alloc_ireg (cfg); EMIT_NEW_BIALU_IMM (cfg, ins, OP_ISUB_IMM, dreg, info->dreg, 1); } -- cgit v1.2.3