[jit] Fix the Activator.CreateInstance () intrinsic for primitive types. (#38130)
authormonojenkins <jo.shields+jenkins@xamarin.com>
Sat, 20 Jun 2020 00:00:53 +0000 (20:00 -0400)
committerGitHub <noreply@github.com>
Sat, 20 Jun 2020 00:00:53 +0000 (20:00 -0400)
Fixes https://github.com/xamarin/xamarin-android/issues/4817.

Co-authored-by: vargaz <vargaz@users.noreply.github.com>
src/mono/mono/mini/iltests.il
src/mono/mono/mini/intrinsics.c
src/mono/mono/mini/method-to-ir.c
src/mono/mono/mini/mini.h

index 93076a9..12e7a84 100644 (file)
@@ -3845,4 +3845,29 @@ L3:
                ret
        }
 
+       .method public hidebysig static !!T     createinstance_intrins_primitive<.ctor T>() cil managed noinlining
+       {
+               .maxstack       8
+               call                     !!0 [mscorlib]System.Activator::CreateInstance<!!0>()
+               ret
+       }
+
+       .method public static int32 test_0_createinstance_intrins_primitive () cil managed
+       {
+               .maxstack       8
+               call                     !!0 Tests::createinstance_intrins_primitive<bool>()
+               ldc.i4.0
+               beq L1
+               ldc.i4.1
+               ret
+       L1:
+               call                     !!0 Tests::createinstance_intrins_primitive<int64>()
+               ldc.i8 0
+               beq L2
+               ldc.i4.2
+               ret
+       L2:
+               ldc.i4.0
+               ret
+       }
 }
index 3951ba5..6f6d93b 100644 (file)
@@ -1881,13 +1881,20 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                                method_context->method_inst->type_argc == 1 &&
                                cmethod->is_inflated &&
                                !mini_method_check_context_used (cfg, cmethod)) {
-                       MonoClass *arg0 = mono_class_from_mono_type_internal (method_context->method_inst->type_argv [0]);
+                       MonoType *t = method_context->method_inst->type_argv [0];
+                       MonoClass *arg0 = mono_class_from_mono_type_internal (t);
                        if (m_class_is_valuetype (arg0) && !mono_class_has_default_constructor (arg0, FALSE)) {
-                               MONO_INST_NEW (cfg, ins, MONO_CLASS_IS_SIMD (cfg, arg0) ? OP_XZERO : OP_VZERO);
-                               ins->dreg = mono_alloc_dreg (cfg, STACK_VTYPE);
-                               ins->type = STACK_VTYPE;
-                               ins->klass = arg0;
-                               MONO_ADD_INS (cfg->cbb, ins);
+                               if (m_class_is_primitive (arg0)) {
+                                       int dreg = alloc_dreg (cfg, mini_type_to_stack_type (cfg, t));
+                                       mini_emit_init_rvar (cfg, dreg, t);
+                                       ins = cfg->cbb->last_ins;
+                               } else {
+                                       MONO_INST_NEW (cfg, ins, MONO_CLASS_IS_SIMD (cfg, arg0) ? OP_XZERO : OP_VZERO);
+                                       ins->dreg = mono_alloc_dreg (cfg, STACK_VTYPE);
+                                       ins->type = STACK_VTYPE;
+                                       ins->klass = arg0;
+                                       MONO_ADD_INS (cfg->cbb, ins);
+                               }
                                return ins;
                        }
                }
index 9c0ce17..032d519 100644 (file)
@@ -1428,10 +1428,10 @@ type_from_stack_type (MonoInst *ins) {
        return NULL;
 }
 
-static G_GNUC_UNUSED int
-type_to_stack_type (MonoCompile *cfg, MonoType *t)
+MonoStackType
+mini_type_to_stack_type (MonoCompile *cfg, MonoType *t)
 {
-       t = mono_type_get_underlying_type (t);
+       t = mini_type_get_underlying_type (t);
        switch (t->type) {
        case MONO_TYPE_I1:
        case MONO_TYPE_U1:
@@ -1455,7 +1455,7 @@ type_to_stack_type (MonoCompile *cfg, MonoType *t)
        case MONO_TYPE_U8:
                return STACK_I8;
        case MONO_TYPE_R4:
-               return cfg->r4_stack_type;
+               return (MonoStackType)cfg->r4_stack_type;
        case MONO_TYPE_R8:
                return STACK_R8;
        case MONO_TYPE_VALUETYPE:
@@ -1471,7 +1471,7 @@ type_to_stack_type (MonoCompile *cfg, MonoType *t)
                g_assert_not_reached ();
        }
 
-       return -1;
+       return (MonoStackType)-1;
 }
 
 static MonoClass*
@@ -4409,8 +4409,8 @@ check_inline_caller_method_name_limit (MonoMethod *caller_method)
 }
 #endif
 
-static void
-emit_init_rvar (MonoCompile *cfg, int dreg, MonoType *rtype)
+void
+mini_emit_init_rvar (MonoCompile *cfg, int dreg, MonoType *rtype)
 {
        static double r8_0 = 0.0;
        static float r4_0 = 0.0;
@@ -4472,7 +4472,7 @@ emit_dummy_init_rvar (MonoCompile *cfg, int dreg, MonoType *rtype)
        } else if (((t == MONO_TYPE_VAR) || (t == MONO_TYPE_MVAR)) && mini_type_var_is_vt (rtype)) {
                MONO_EMIT_NEW_DUMMY_INIT (cfg, dreg, OP_DUMMY_VZERO);
        } else {
-               emit_init_rvar (cfg, dreg, rtype);
+               mini_emit_init_rvar (cfg, dreg, rtype);
        }
 }
 
@@ -4484,11 +4484,11 @@ emit_init_local (MonoCompile *cfg, int local, MonoType *type, gboolean init)
        if (COMPILE_SOFT_FLOAT (cfg)) {
                MonoInst *store;
                int reg = alloc_dreg (cfg, (MonoStackType)var->type);
-               emit_init_rvar (cfg, reg, type);
+               mini_emit_init_rvar (cfg, reg, type);
                EMIT_NEW_LOCSTORE (cfg, store, local, cfg->cbb->last_ins);
        } else {
                if (init)
-                       emit_init_rvar (cfg, var->dreg, type);
+                       mini_emit_init_rvar (cfg, var->dreg, type);
                else
                        emit_dummy_init_rvar (cfg, var->dreg, type);
        }
@@ -4678,7 +4678,7 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig,
                                        if (bb->last_ins && bb->last_ins->opcode == OP_NOT_REACHED) {
                                                cfg->cbb = bb;
 
-                                               emit_init_rvar (cfg, rvar->dreg, fsig->ret);
+                                               mini_emit_init_rvar (cfg, rvar->dreg, fsig->ret);
                                        }
                                }
                        }
@@ -4692,7 +4692,7 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig,
                         * set, so set it to a dummy value.
                         */
                        if (!ret_var_set)
-                               emit_init_rvar (cfg, rvar->dreg, fsig->ret);
+                               mini_emit_init_rvar (cfg, rvar->dreg, fsig->ret);
 
                        EMIT_NEW_TEMPLOAD (cfg, ins, rvar->inst_c0);
                        *sp++ = ins;
@@ -8797,7 +8797,7 @@ calli_end:
                        } else {
                                if (m_class_is_valuetype (cmethod->klass)) {
                                        iargs [0] = mono_compile_create_var (cfg, m_class_get_byval_arg (cmethod->klass), OP_LOCAL);
-                                       emit_init_rvar (cfg, iargs [0]->dreg, m_class_get_byval_arg (cmethod->klass));
+                                       mini_emit_init_rvar (cfg, iargs [0]->dreg, m_class_get_byval_arg (cmethod->klass));
                                        EMIT_NEW_TEMPLOADA (cfg, *sp, iargs [0]->inst_c0);
 
                                        alloc = NULL;
index 1d09d6d..1d76729 100644 (file)
@@ -2114,6 +2114,7 @@ guint     mono_type_to_load_membase         (MonoCompile *cfg, MonoType *type);
 guint     mono_type_to_store_membase        (MonoCompile *cfg, MonoType *type);
 guint32   mono_type_to_stloc_coerce         (MonoType *type);
 guint     mini_type_to_stind                (MonoCompile* cfg, MonoType *type);
+MonoStackType mini_type_to_stack_type       (MonoCompile *cfg, MonoType *t);
 MonoJitInfo* mini_lookup_method             (MonoDomain *domain, MonoMethod *method, MonoMethod *shared);
 guint32   mono_reverse_branch_op            (guint32 opcode);
 void      mono_disassemble_code             (MonoCompile *cfg, guint8 *code, int size, char *id);
@@ -2257,6 +2258,7 @@ void              mini_emit_memcpy (MonoCompile *cfg, int destreg, int doffset,
 void              mini_emit_memset (MonoCompile *cfg, int destreg, int offset, int size, int val, int align);
 void              mini_emit_stobj (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoClass *klass, gboolean native);
 void              mini_emit_initobj (MonoCompile *cfg, MonoInst *dest, const guchar *ip, MonoClass *klass);
+void              mini_emit_init_rvar (MonoCompile *cfg, int dreg, MonoType *rtype);
 int               mini_emit_sext_index_reg (MonoCompile *cfg, MonoInst *index);
 MonoInst*         mini_emit_ldelema_1_ins (MonoCompile *cfg, MonoClass *klass, MonoInst *arr, MonoInst *index, gboolean bcheck);
 MonoInst*         mini_emit_get_gsharedvt_info_klass (MonoCompile *cfg, MonoClass *klass, MonoRgctxInfoType rgctx_type);