Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZoltan Varga <vargaz@gmail.com>2017-07-02 09:08:44 +0300
committerZoltan Varga <vargaz@gmail.com>2017-07-03 18:52:40 +0300
commit3d531ba62551abca0ca0d679ae0d4e8a31cf1b67 (patch)
tree1b112d8e23395e60fdbc2958a38a0349a37607b5
parent7df343579deac9299710f21340ae81d542e892c3 (diff)
[jit] Use the right type when handling shared versions of RuntimeHelpers.IsReferenceOrContainsReferences (). The previous version only worked by accident. (#5160)mono-5.2.0.209
-rw-r--r--mono/mini/generics.cs21
-rw-r--r--mono/mini/gshared.cs24
-rw-r--r--mono/mini/method-to-ir.c14
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<T> ();
}
+ class IsRefClass<T> {
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public bool is_ref () {
+ return RuntimeHelpers.IsReferenceOrContainsReferences<T> ();
+ }
+ }
+
[MethodImplAttribute (MethodImplOptions.NoInlining)]
public static bool is_ref_or_contains_refs_gen_ref<T> () {
return RuntimeHelpers.IsReferenceOrContainsReferences<GenStruct<T>> ();
@@ -1343,6 +1350,12 @@ class Tests
int i;
}
+ struct AStruct3<T1, T2, T3> {
+ T1 t1;
+ T2 t2;
+ T3 t3;
+ }
+
public static int test_0_isreference_intrins () {
if (RuntimeHelpers.IsReferenceOrContainsReferences<int> ())
return 1;
@@ -1368,6 +1381,14 @@ class Tests
if (is_ref_or_contains_refs_gen_noref<string> ())
return 10;
+ // Complex type from shared class method
+ var c1 = new IsRefClass<AStruct3<int, int, int>> ();
+ if (c1.is_ref ())
+ return 11;
+ var c2 = new IsRefClass<AStruct3<string, int, int>> ();
+ 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, T2, T3> {
+ T1 t1;
+ T2 t2;
+ T3 t3;
+ }
+
+ interface IFaceIsRef {
+ bool is_ref<T> ();
+ }
+
+ class ClassIsRef : IFaceIsRef {
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public bool is_ref<T> () {
+ return RuntimeHelpers.IsReferenceOrContainsReferences<T> ();
+ }
+ }
+
+ public static int test_0_isreference_intrins () {
+ IFaceIsRef iface = new ClassIsRef ();
+ Console.WriteLine ("X: " + iface.is_ref<AStruct3<int, int, int>> ());
+ Console.WriteLine ("X: " + iface.is_ref<AStruct3<string, int, int>> ());
+ 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);
}