Checking if a type is a reference must be gsharing aware.
authorRodrigo Kumpera <kumpera@gmail.com>
Thu, 3 Mar 2011 21:56:14 +0000 (22:56 +0100)
committerRodrigo Kumpera <kumpera@gmail.com>
Thu, 3 Mar 2011 22:09:07 +0000 (23:09 +0100)
*  mini-generic-sharing.c: Add mini_type_is_reference
that returns true for VAR and MVAR if compiling under
gsharing.

* method-to-ir.c: Replace usage of mono_type_is_reference
with mini_type_is_reference.

* mini-gc.c: Ditto.

* mini.c: Ditto.

With the old behavior, the JIT could interpret a (M)VAR
variable and not been a reference type. This is an issue
for sgen as we could forgot to emit some write barriers
or generate the proper stack map.

mono/mini/method-to-ir.c
mono/mini/mini-gc.c
mono/mini/mini-generic-sharing.c
mono/mini/mini.c
mono/mini/mini.h

index c782f257ff84f5ee67974355a5b6b7998ae1ee9a..74e10a30e43a8847bf20ff971fc634aa28ee73f1 100644 (file)
@@ -2615,7 +2615,7 @@ get_memcpy_method (void)
 }
 
 static void
-create_write_barrier_bitmap (MonoClass *klass, unsigned *wb_bitmap, int offset)
+create_write_barrier_bitmap (MonoCompile *cfg, MonoClass *klass, unsigned *wb_bitmap, int offset)
 {
        MonoClassField *field;
        gpointer iter = NULL;
@@ -2626,14 +2626,13 @@ create_write_barrier_bitmap (MonoClass *klass, unsigned *wb_bitmap, int offset)
                if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
                        continue;
                foffset = klass->valuetype ? field->offset - sizeof (MonoObject): field->offset;
-               if (mono_type_is_reference (field->type)) {
+               if (mini_type_is_reference (cfg, mono_field_get_type (field))) {
                        g_assert ((foffset % SIZEOF_VOID_P) == 0);
                        *wb_bitmap |= 1 << ((offset + foffset) / SIZEOF_VOID_P);
                } else {
-                       /*FIXME support nested value types so this works for: struct X { Y y; int z;} struct Y { object a,b; }*/
                        MonoClass *field_class = mono_class_from_mono_type (field->type);
                        if (field_class->has_references)
-                               create_write_barrier_bitmap (field_class, wb_bitmap, offset + foffset);
+                               create_write_barrier_bitmap (cfg, field_class, wb_bitmap, offset + foffset);
                }
        }
 }
@@ -2724,7 +2723,7 @@ mono_emit_wb_aware_memcpy (MonoCompile *cfg, MonoClass *klass, MonoInst *iargs[4
        if (size > 32 * SIZEOF_VOID_P)
                return FALSE;
 
-       create_write_barrier_bitmap (klass, &need_wb, 0);
+       create_write_barrier_bitmap (cfg, klass, &need_wb, 0);
 
        /* We don't unroll more than 5 stores to avoid code bloat. */
        if (size > 5 * SIZEOF_VOID_P) {
@@ -3338,7 +3337,7 @@ handle_box (MonoCompile *cfg, MonoInst *val, MonoClass *klass, int context_used)
 
 
 static gboolean
-mini_class_has_reference_variant_generic_argument (MonoClass *klass, int context_used)
+mini_class_has_reference_variant_generic_argument (MonoCompile *cfg, MonoClass *klass, int context_used)
 {
        int i;
        MonoGenericContainer *container;
@@ -3359,10 +3358,7 @@ mini_class_has_reference_variant_generic_argument (MonoClass *klass, int context
                if (!(mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT)))
                        continue;
                type = ginst->type_argv [i];
-               if (MONO_TYPE_IS_REFERENCE (type))
-                       return TRUE;
-
-               if (context_used && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR))
+               if (mini_type_is_reference (cfg, type))
                        return TRUE;
        }
        return FALSE;
@@ -3385,7 +3381,7 @@ handle_castclass (MonoCompile *cfg, MonoClass *klass, MonoInst *src, int context
        if (context_used) {
                MonoInst *args [3];
 
-               if(mini_class_has_reference_variant_generic_argument (klass, context_used)) {
+               if(mini_class_has_reference_variant_generic_argument (cfg, klass, context_used)) {
                        MonoMethod *mono_castclass = mono_marshal_get_castclass_with_cache ();
                        MonoInst *cache_ins;
 
@@ -3479,7 +3475,7 @@ handle_isinst (MonoCompile *cfg, MonoClass *klass, MonoInst *src, int context_us
        if (context_used) {
                MonoInst *args [3];
 
-               if(mini_class_has_reference_variant_generic_argument (klass, context_used)) {
+               if(mini_class_has_reference_variant_generic_argument (cfg, klass, context_used)) {
                        MonoMethod *mono_isinst = mono_marshal_get_isinst_with_cache ();
                        MonoInst *cache_ins;
 
@@ -4631,7 +4627,7 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
 #ifdef MONO_ARCH_HAVE_ATOMIC_CAS
                if ((strcmp (cmethod->name, "CompareExchange") == 0)) {
                        int size = 0;
-                       gboolean is_ref = MONO_TYPE_IS_REFERENCE (fsig->params [1]);
+                       gboolean is_ref = mini_type_is_reference (cfg, fsig->params [1]);
                        if (fsig->params [1]->type == MONO_TYPE_I4)
                                size = 4;
                        else if (is_ref || fsig->params [1]->type == MONO_TYPE_I)
@@ -5407,13 +5403,7 @@ set_exception_object (MonoCompile *cfg, MonoException *exception)
 static gboolean
 generic_class_is_reference_type (MonoCompile *cfg, MonoClass *klass)
 {
-       MonoType *type;
-
-       if (cfg->generic_sharing_context)
-               type = mini_get_basic_type_from_generic (cfg->generic_sharing_context, &klass->byval_arg);
-       else
-               type = &klass->byval_arg;
-       return MONO_TYPE_IS_REFERENCE (type);
+       return mini_type_is_reference (cfg, &klass->byval_arg);
 }
 
 static void
@@ -5459,9 +5449,7 @@ emit_optimized_ldloca_ir (MonoCompile *cfg, unsigned char *ip, unsigned char *en
                token = read32 (ip + 2);
                klass = mini_get_class (cfg->current_method, token, cfg->generic_context);
                CHECK_TYPELOAD (klass);
-               if (generic_class_is_reference_type (cfg, klass)) {
-                       MONO_EMIT_NEW_PCONST (cfg, cfg->locals [local]->dreg, NULL);
-               } else if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
+               if (mini_type_is_reference (cfg, &klass->byval_arg)) {
                        MONO_EMIT_NEW_PCONST (cfg, cfg->locals [local]->dreg, NULL);
                } else if (MONO_TYPE_ISSTRUCT (&klass->byval_arg)) {
                        MONO_EMIT_NEW_VZERO (cfg, cfg->locals [local]->dreg, klass);
@@ -8214,7 +8202,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (cfg->generic_sharing_context)
                                context_used = mono_class_check_context_used (klass);
 
-                       if (!context_used && mini_class_has_reference_variant_generic_argument (klass, context_used)) {
+                       if (!context_used && mini_class_has_reference_variant_generic_argument (cfg, klass, context_used)) {
                                MonoMethod *mono_castclass = mono_marshal_get_castclass_with_cache ();
                                MonoInst *args [3];
 
@@ -8277,7 +8265,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        if (cfg->generic_sharing_context)
                                context_used = mono_class_check_context_used (klass);
 
-                       if (!context_used && mini_class_has_reference_variant_generic_argument (klass, context_used)) {
+                       if (!context_used && mini_class_has_reference_variant_generic_argument (cfg, klass, context_used)) {
                                MonoMethod *mono_isinst = mono_marshal_get_isinst_with_cache ();
                                MonoInst *args [3];
 
@@ -8339,7 +8327,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                        if (generic_class_is_reference_type (cfg, klass)) {
                                /* CASTCLASS FIXME kill this huge slice of duplicated code*/
-                               if (!context_used && mini_class_has_reference_variant_generic_argument (klass, context_used)) {
+                               if (!context_used && mini_class_has_reference_variant_generic_argument (cfg, klass, context_used)) {
                                        MonoMethod *mono_castclass = mono_marshal_get_castclass_with_cache ();
                                        MonoInst *args [3];
 
index 3972f5730972f70359077abf0ee3aa51bedd0ed5..cc5a4a2f39fce9ee88e454f4d345881e1c7e2d4c 100644 (file)
@@ -1493,7 +1493,7 @@ process_variables (MonoCompile *cfg)
                        if (byref)
                                slot_type = SLOT_PIN;
                        else
-                               slot_type = MONO_TYPE_IS_REFERENCE (t) ? SLOT_REF : SLOT_NOREF;
+                               slot_type = mini_type_is_reference (cfg, t) ? SLOT_REF : SLOT_NOREF;
 
                        if (slot_type == SLOT_PIN) {
                                /* These have no live interval, be conservative */
@@ -1651,7 +1651,7 @@ process_variables (MonoCompile *cfg)
 
                t = mini_type_get_underlying_type (NULL, t);
 
-               if (!MONO_TYPE_IS_REFERENCE (t)) {
+               if (!mini_type_is_reference (cfg, t)) {
                        set_slot_everywhere (gcfg, pos, SLOT_NOREF);
                        if (cfg->verbose_level > 1)
                                printf ("\tnoref at %s0x%x(fp) (R%d, slot = %d): %s\n", ins->inst_offset < 0 ? "-" : "", (ins->inst_offset < 0) ? -(int)ins->inst_offset : (int)ins->inst_offset, vmv->vreg, pos, mono_type_full_name (ins->inst_vtype));
@@ -1712,12 +1712,12 @@ sp_offset_to_fp_offset (MonoCompile *cfg, int sp_offset)
 }
 
 static GCSlotType
-type_to_gc_slot_type (MonoType *t)
+type_to_gc_slot_type (MonoCompile *cfg, MonoType *t)
 {
        if (t->byref)
                return SLOT_PIN;
        t = mini_type_get_underlying_type (NULL, t);
-       if (MONO_TYPE_IS_REFERENCE (t))
+       if (mini_type_is_reference (cfg, t))
                return SLOT_REF;
        else {
                if (MONO_TYPE_ISSTRUCT (t)) {
@@ -1781,7 +1781,7 @@ process_param_area_slots (MonoCompile *cfg)
                        int sp_offset = def->inst_offset;
                        int fp_offset = sp_offset_to_fp_offset (cfg, sp_offset);
                        int slot = fp_offset_to_slot (cfg, fp_offset);
-                       GCSlotType type = type_to_gc_slot_type (t);
+                       GCSlotType type = type_to_gc_slot_type (cfg, t);
 
                        /* The slot is live between the def instruction and the call */
                        set_slot_in_range (gcfg, slot, def->backend.pc_offset, callsite->pc_offset + 1, type);
index f00e60167b69da444fc67f4248d1673c296a4eb3..8706fa3c31adaf4ce1c469cc0927a6ff94bebc72 100644 (file)
@@ -1878,3 +1878,14 @@ mono_generic_sharing_cleanup (void)
        if (generic_subclass_hash)
                g_hash_table_destroy (generic_subclass_hash);
 }
+
+gboolean
+mini_type_is_reference (MonoCompile *cfg, MonoType *type)
+{
+       if (mono_type_is_reference (type))
+               return TRUE;
+       if (!cfg->generic_sharing_context)
+               return FALSE;
+       /*FIXME the probably needs better handle under partial sharing*/
+       return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
+}
index 03ab3e0a6c35bfae90139e7d4b13596438cf52eb..71035c4e12e26bfacd7d5af8105d271d5c5f3d3c 100644 (file)
@@ -1123,7 +1123,7 @@ mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode,
                        mono_mark_vreg_as_mp (cfg, vreg);
                } else {
                        MonoType *t = mini_type_get_underlying_type (NULL, type);
-                       if ((MONO_TYPE_ISSTRUCT (t) && inst->klass->has_references) || MONO_TYPE_IS_REFERENCE (t)) {
+                       if ((MONO_TYPE_ISSTRUCT (t) && inst->klass->has_references) || mini_type_is_reference (cfg, t)) {
                                inst->flags |= MONO_INST_GC_TRACK;
                                mono_mark_vreg_as_ref (cfg, vreg);
                        }
index c6a77bfe22d00c03252f8694616577104cad61bc..480306f03e7ef431049fe1f8513a406d40620b73 100644 (file)
@@ -2296,6 +2296,8 @@ guint mono_type_to_regmove (MonoCompile *cfg, MonoType *type) MONO_INTERNAL;
 void mono_cfg_add_try_hole (MonoCompile *cfg, MonoExceptionClause *clause, guint8 *start, MonoBasicBlock *bb) MONO_INTERNAL;
 
 void mono_cfg_set_exception (MonoCompile *cfg, int type) MONO_INTERNAL;
+gboolean mini_type_is_reference (MonoCompile *cfg, MonoType *type) MONO_INTERNAL;
+
 
 /* wapihandles.c */
 int mini_wapi_hps (int argc, char **argv) MONO_INTERNAL;