diff --git a/mono/mini/generics.cs b/mono/mini/generics.cs index e9b41a64e08ab..eafbd1c0e541c 100644 --- a/mono/mini/generics.cs +++ b/mono/mini/generics.cs @@ -1314,6 +1314,13 @@ class ThrowClass where T: Exception { 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 @@ struct NoRefStruct { 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 @@ struct NoRefStruct { 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 29943694c72fa..61402f7a4eca4 100644 --- a/mono/mini/gshared.cs +++ b/mono/mini/gshared.cs @@ -1972,6 +1972,30 @@ void gsharedvt_try_at_offset_0 (ref T disposable) 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 770bd88ea486b..326e6c1f9d2a8 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); }