[jit] Finish support for valuetype based sharing in JIT mode, not enabled yet.
authorZoltan Varga <vargaz@gmail.com>
Fri, 13 Mar 2015 05:27:54 +0000 (01:27 -0400)
committerZoltan Varga <vargaz@gmail.com>
Fri, 13 Mar 2015 05:28:00 +0000 (01:28 -0400)
mono/mini/method-to-ir.c
mono/mini/mini-generic-sharing.c
mono/mini/mini.c

index bcecf0831f141206053f8496f5074b92948844e7..dee6f35c7ae21c0816aa00adcba9dd2060573b5e 100755 (executable)
@@ -4005,8 +4005,11 @@ handle_alloc (MonoCompile *cfg, MonoClass *klass, gboolean for_box, int context_
                }
 
                if (managed_alloc && !(cfg->opt & MONO_OPT_SHARED)) {
-                       if (known_instance_size)
-                               EMIT_NEW_ICONST (cfg, iargs [1], mono_gc_get_aligned_size_for_allocator (klass->instance_size));
+                       if (known_instance_size) {
+                               int size = mono_class_instance_size (klass);
+
+                               EMIT_NEW_ICONST (cfg, iargs [1], mono_gc_get_aligned_size_for_allocator (size));
+                       }
                        return mono_emit_method_call (cfg, managed_alloc, iargs, NULL);
                }
 
@@ -4039,8 +4042,10 @@ handle_alloc (MonoCompile *cfg, MonoClass *klass, gboolean for_box, int context_
 #endif
 
                if (managed_alloc) {
+                       int size = mono_class_instance_size (klass);
+
                        EMIT_NEW_VTABLECONST (cfg, iargs [0], vtable);
-                       EMIT_NEW_ICONST (cfg, iargs [1], mono_gc_get_aligned_size_for_allocator (klass->instance_size));
+                       EMIT_NEW_ICONST (cfg, iargs [1], mono_gc_get_aligned_size_for_allocator (size));
                        return mono_emit_method_call (cfg, managed_alloc, iargs, NULL);
                }
                alloc_ftn = mono_class_get_allocation_ftn (vtable, for_box, &pass_lw);
@@ -8750,6 +8755,16 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                cil_method = cmethod;
                                
                                if (constrained_class) {
+                                       if ((constrained_class->byval_arg.type == MONO_TYPE_VAR || constrained_class->byval_arg.type == MONO_TYPE_MVAR) && cfg->generic_sharing_context) {
+                                               if (!mini_is_gsharedvt_klass (cfg, constrained_class)) {
+                                                       g_assert (!cmethod->klass->valuetype);
+                                                       if (!mini_type_is_reference (cfg, &constrained_class->byval_arg)) {
+                                                               /* FIXME: gshared type constrained to a primitive type */
+                                                               GENERIC_SHARING_FAILURE (CEE_CALL);
+                                                       }
+                                               }
+                                       }
+
                                        if (method->wrapper_type != MONO_WRAPPER_NONE) {
                                                if (cfg->verbose_level > 2)
                                                        printf ("DM Constrained call to %s\n", mono_type_get_full_name (constrained_class));
index e88097e3532d9a6aa0d1477241d6f3a50195162c..a4b166d38796093f10f65fd54a4477ff5c5bef2a 100644 (file)
@@ -15,8 +15,8 @@
 
 #include "mini.h"
 
-#define ALLOW_PARTIAL_SHARING TRUE
-//#define ALLOW_PARTIAL_SHARING FALSE
+//#define ALLOW_PARTIAL_SHARING TRUE
+#define ALLOW_PARTIAL_SHARING FALSE
  
 #if 0
 #define DEBUG(...) __VA_ARGS__
@@ -707,31 +707,21 @@ generic_inst_is_sharable (MonoGenericInst *inst, gboolean allow_type_vars,
                                                  gboolean allow_partial)
 {
        int i;
-       gboolean has_ref = FALSE;
 
        for (i = 0; i < inst->type_argc; ++i) {
                MonoType *type = inst->type_argv [i];
 
-               if (MONO_TYPE_IS_REFERENCE (type) || (allow_type_vars && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR))) {
-                       has_ref = TRUE;
+               if (MONO_TYPE_IS_REFERENCE (type) || (allow_type_vars && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)))
                        continue;
-               }
  
-               /*
-                * Allow non ref arguments, if there is at least one ref argument
-                * (partial sharing).
-                * FIXME: Allow more types
-                */
-               if (allow_partial && !type->byref && (((type->type >= MONO_TYPE_BOOLEAN) && (type->type <= MONO_TYPE_R8)) || (type->type == MONO_TYPE_I) || (type->type == MONO_TYPE_U)))
+               /* Allow non ref arguments if they are primitive types or enums (partial sharing). */
+               if (allow_partial && !type->byref && (((type->type >= MONO_TYPE_BOOLEAN) && (type->type <= MONO_TYPE_R8)) || (type->type == MONO_TYPE_I) || (type->type == MONO_TYPE_U) || (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)))
                        continue;
 
                return FALSE;
        }
 
-       if (allow_partial)
-               return has_ref;
-       else
-               return TRUE;
+       return TRUE;
 }
 
 /*
@@ -2206,6 +2196,13 @@ mono_method_is_generic_sharable_full (MonoMethod *method, gboolean allow_type_va
        if (!partial_sharing_supported ())
                allow_partial = FALSE;
 
+       if (method->klass->image->dynamic)
+               /*
+                * Enabling this causes corlib test failures because the JIT encounters generic instances whose
+                * instance_size is 0.
+                */
+               allow_partial = FALSE;
+
        /*
         * Generic async methods have an associated state machine class which is a generic struct. This struct
         * is too large to be handled by gsharedvt so we make it visible to the AOT compiler by disabling sharing
@@ -2812,6 +2809,20 @@ get_shared_gparam (MonoType *t, MonoTypeEnum constraint)
        return res;
 }
 
+static MonoType*
+get_shared_type (MonoType *t, MonoType *type)
+{
+       MonoTypeEnum ttype;
+
+       g_assert (!type->byref && (((type->type >= MONO_TYPE_BOOLEAN) && (type->type <= MONO_TYPE_R8)) || (type->type == MONO_TYPE_I) || (type->type == MONO_TYPE_U) || (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)));
+
+       /* Create a type variable with a constraint which encodes which types can match it */
+       ttype = type->type;
+       if (type->type == MONO_TYPE_VALUETYPE)
+               ttype = mono_class_enum_basetype (type->data.klass)->type;
+       return get_shared_gparam (t, ttype);
+}
+
 static MonoType*
 get_gsharedvt_type (MonoType *t)
 {
@@ -2819,7 +2830,7 @@ get_gsharedvt_type (MonoType *t)
 }
 
 static MonoGenericInst*
-get_shared_inst (MonoGenericInst *inst, MonoGenericInst *shared_inst, MonoGenericContainer *container, gboolean all_vt, gboolean gsharedvt)
+get_shared_inst (MonoGenericInst *inst, MonoGenericInst *shared_inst, MonoGenericContainer *container, gboolean all_vt, gboolean gsharedvt, gboolean partial)
 {
        MonoGenericInst *res;
        MonoType **type_argv;
@@ -2829,6 +2840,9 @@ get_shared_inst (MonoGenericInst *inst, MonoGenericInst *shared_inst, MonoGeneri
        for (i = 0; i < inst->type_argc; ++i) {
                if (!all_vt && (MONO_TYPE_IS_REFERENCE (inst->type_argv [i]) || inst->type_argv [i]->type == MONO_TYPE_VAR || inst->type_argv [i]->type == MONO_TYPE_MVAR)) {
                        type_argv [i] = shared_inst->type_argv [i];
+               } else if (partial) {
+                       /* These types match the ones in generic_inst_is_sharable () */
+                       type_argv [i] = get_shared_type (shared_inst->type_argv [i], inst->type_argv [i]);
                } else if (all_vt) {
                        type_argv [i] = get_gsharedvt_type (shared_inst->type_argv [i]);
                } else if (gsharedvt) {
@@ -2894,14 +2908,14 @@ mini_get_shared_method_full (MonoMethod *method, gboolean all_vt, gboolean is_gs
                else
                        inst = shared_context.class_inst;
                if (inst)
-                       shared_context.class_inst = get_shared_inst (inst, shared_context.class_inst, class_container, all_vt, gsharedvt);
+                       shared_context.class_inst = get_shared_inst (inst, shared_context.class_inst, class_container, all_vt, gsharedvt, partial);
 
                if (context)
                        inst = context->method_inst;
                else
                        inst = shared_context.method_inst;
                if (inst)
-                       shared_context.method_inst = get_shared_inst (inst, shared_context.method_inst, method_container, all_vt, gsharedvt);
+                       shared_context.method_inst = get_shared_inst (inst, shared_context.method_inst, method_container, all_vt, gsharedvt, partial);
 
                partial = TRUE;
        }
index 9aae38133c4f8219b5f9083ebbec6e2b9617591e..8fd6de658ba3aeca114af70233c307878d644fab 100755 (executable)
@@ -3062,8 +3062,8 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
                        (opts & MONO_OPT_GSHARED) && mono_method_is_generic_sharable (method, FALSE);
 
        /*
-               if (try_generic_shared && !mono_debug_count ())
-                       try_generic_shared = FALSE;
+       if (try_generic_shared && !mono_debug_count ())
+               try_generic_shared = FALSE;
        */
 
        if (opts & MONO_OPT_GSHARED) {