[jit] Fix memory leaks in the generic sharing code by making sure that values stored...
authorZoltan Varga <vargaz@gmail.com>
Thu, 19 Nov 2015 07:00:23 +0000 (02:00 -0500)
committerZoltan Varga <vargaz@gmail.com>
Thu, 19 Nov 2015 07:00:28 +0000 (02:00 -0500)
mono/mini/method-to-ir.c
mono/mini/mini-generic-sharing.c
mono/mini/mini.h

index fdbe5272fc8a0e6f17c24a6ab66fc41764ba0dd5..2f3d41924fe45b0f15f9764c5480d487e0ea280f 100644 (file)
@@ -4073,10 +4073,10 @@ handle_unbox_gsharedvt (MonoCompile *cfg, MonoClass *klass, MonoInst *obj)
        NEW_BBLOCK (cfg, is_nullable_bb);
        NEW_BBLOCK (cfg, end_bb);
        is_ref = emit_get_gsharedvt_info_klass (cfg, klass, MONO_RGCTX_INFO_CLASS_BOX_TYPE);
-       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, is_ref->dreg, 1);
+       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, is_ref->dreg, MONO_GSHAREDVT_BOX_TYPE_REF);
        MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBEQ, is_ref_bb);
 
-       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, is_ref->dreg, 2);
+       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, is_ref->dreg, MONO_GSHAREDVT_BOX_TYPE_NULLABLE);
        MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBEQ, is_nullable_bb);
 
        /* This will contain either the address of the unboxed vtype, or an address of the temporary where the ref is stored */
@@ -4269,10 +4269,10 @@ handle_box (MonoCompile *cfg, MonoInst *val, MonoClass *klass, int context_used)
                NEW_BBLOCK (cfg, is_nullable_bb);
                NEW_BBLOCK (cfg, end_bb);
                is_ref = emit_get_gsharedvt_info_klass (cfg, klass, MONO_RGCTX_INFO_CLASS_BOX_TYPE);
-               MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, is_ref->dreg, 1);
+               MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, is_ref->dreg, MONO_GSHAREDVT_BOX_TYPE_REF);
                MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBEQ, is_ref_bb);
 
-               MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, is_ref->dreg, 2);
+               MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, is_ref->dreg, MONO_GSHAREDVT_BOX_TYPE_NULLABLE);
                MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBEQ, is_nullable_bb);
 
                /* Non-ref case */
@@ -5130,9 +5130,12 @@ handle_constrained_gsharedvt_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMe
                        args [4] = ins;
 
                        if (mini_is_gsharedvt_type (fsig->params [0])) {
-                               int addr_reg;
+                               int addr_reg, deref_arg_reg;
 
-                               args [3] = emit_get_gsharedvt_info_klass (cfg, mono_class_from_mono_type (fsig->params [0]), MONO_RGCTX_INFO_CLASS_BOX_TYPE);
+                               ins = emit_get_gsharedvt_info_klass (cfg, mono_class_from_mono_type (fsig->params [0]), MONO_RGCTX_INFO_CLASS_BOX_TYPE);
+                               deref_arg_reg = alloc_preg (cfg);
+                               /* deref_arg = BOX_TYPE != MONO_GSHAREDVT_BOX_TYPE_VTYPE */
+                               EMIT_NEW_BIALU_IMM (cfg, args [3], OP_ISUB_IMM, deref_arg_reg, ins->dreg, 1);
 
                                EMIT_NEW_VARLOADA_VREG (cfg, ins, sp [1]->dreg, fsig->params [0]);
                                addr_reg = ins->dreg;
@@ -9063,7 +9066,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                NEW_BBLOCK (cfg, end_bb);
 
                                                box_type = emit_get_rgctx_virt_method (cfg, mono_class_check_context_used (constrained_class), constrained_class, cmethod, MONO_RGCTX_INFO_VIRT_METHOD_BOX_TYPE);
-                                               MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, box_type->dreg, 1);
+                                               MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, box_type->dreg, MONO_GSHAREDVT_BOX_TYPE_REF);
                                                MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBEQ, is_ref_bb);
 
                                                /* Non-ref case */
@@ -11078,6 +11081,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                context_used = mini_class_check_context_used (cfg, klass);
 
                                                offset_ins = emit_get_gsharedvt_info (cfg, field, MONO_RGCTX_INFO_FIELD_OFFSET);
+                                               /* The value is offset by 1 */
+                                               EMIT_NEW_BIALU_IMM (cfg, ins, OP_PSUB_IMM, offset_ins->dreg, offset_ins->dreg, 1);
                                                dreg = alloc_ireg_mp (cfg);
                                                EMIT_NEW_BIALU (cfg, ins, OP_PADD, dreg, sp [0]->dreg, offset_ins->dreg);
                                                /* The decomposition will call mini_emit_stobj () which will emit a wbarrier if needed */
@@ -11161,6 +11166,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                MonoInst *offset_ins;
 
                                                offset_ins = emit_get_gsharedvt_info (cfg, field, MONO_RGCTX_INFO_FIELD_OFFSET);
+                                               /* The value is offset by 1 */
+                                               EMIT_NEW_BIALU_IMM (cfg, ins, OP_PSUB_IMM, offset_ins->dreg, offset_ins->dreg, 1);
                                                EMIT_NEW_BIALU (cfg, ins, OP_PADD, dreg, sp [0]->dreg, offset_ins->dreg);
                                        } else {
                                                EMIT_NEW_BIALU_IMM (cfg, ins, OP_PADD_IMM, dreg, sp [0]->dreg, foffset);
@@ -11177,6 +11184,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                MonoInst *offset_ins;
 
                                                offset_ins = emit_get_gsharedvt_info (cfg, field, MONO_RGCTX_INFO_FIELD_OFFSET);
+                                               /* The value is offset by 1 */
+                                               EMIT_NEW_BIALU_IMM (cfg, ins, OP_PSUB_IMM, offset_ins->dreg, offset_ins->dreg, 1);
                                                dreg = alloc_ireg_mp (cfg);
                                                EMIT_NEW_BIALU (cfg, ins, OP_PADD, dreg, sp [0]->dreg, offset_ins->dreg);
                                                EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, load, field->type, dreg, 0);
@@ -11302,6 +11311,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        MonoInst *offset_ins;
 
                                        offset_ins = emit_get_rgctx_field (cfg, context_used, field, MONO_RGCTX_INFO_FIELD_OFFSET);
+                                       /* The value is offset by 1 */
+                                       EMIT_NEW_BIALU_IMM (cfg, ins, OP_PSUB_IMM, offset_ins->dreg, offset_ins->dreg, 1);
                                        dreg = alloc_ireg_mp (cfg);
                                        EMIT_NEW_BIALU (cfg, ins, OP_PADD, dreg, static_data->dreg, offset_ins->dreg);
                                } else if (field->offset == 0) {
index 394687186b8f5ca4ac9fcbf9649e10bbe843ebbb..6bec18405f58795a689385a065de24ab4315cfe7 100644 (file)
@@ -882,11 +882,11 @@ class_type_info (MonoDomain *domain, MonoClass *klass, MonoRgctxInfoType info_ty
                        return GUINT_TO_POINTER (mono_class_value_size (klass, NULL));
        case MONO_RGCTX_INFO_CLASS_BOX_TYPE:
                if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg))
-                       return GUINT_TO_POINTER (1);
+                       return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_REF);
                else if (mono_class_is_nullable (klass))
-                       return GUINT_TO_POINTER (2);
+                       return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_NULLABLE);
                else
-                       return GUINT_TO_POINTER (0);
+                       return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_VTYPE);
        case MONO_RGCTX_INFO_MEMCPY:
        case MONO_RGCTX_INFO_BZERO: {
                static MonoMethod *memcpy_method [17];
@@ -1231,11 +1231,11 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
 
                impl_class = method->klass;
                if (MONO_TYPE_IS_REFERENCE (&impl_class->byval_arg))
-                       return GUINT_TO_POINTER (1);
+                       return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_REF);
                else if (mono_class_is_nullable (impl_class))
-                       return GUINT_TO_POINTER (2);
+                       return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_NULLABLE);
                else
-                       return GUINT_TO_POINTER (0);
+                       return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_VTYPE);
        }
 #ifndef DISABLE_REMOTING
        case MONO_RGCTX_INFO_REMOTING_INVOKE_WITH_CHECK:
@@ -1248,10 +1248,11 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti
        case MONO_RGCTX_INFO_FIELD_OFFSET: {
                MonoClassField *field = data;
 
+               /* The value is offset by 1 */
                if (field->parent->valuetype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
-                       return GUINT_TO_POINTER (field->offset - sizeof (MonoObject));
+                       return GUINT_TO_POINTER (field->offset - sizeof (MonoObject) + 1);
                else
-                       return GUINT_TO_POINTER (field->offset);
+                       return GUINT_TO_POINTER (field->offset + 1);
        }
        case MONO_RGCTX_INFO_METHOD_RGCTX: {
                MonoMethodInflated *method = data;
@@ -1846,6 +1847,7 @@ fill_runtime_generic_context (MonoVTable *class_vtable, MonoRuntimeGenericContex
                                                                                method_inst ? method_inst->type_argc : 0, slot, TRUE, TRUE, &do_free);
        /* This might take the loader lock */
        info = instantiate_info (domain, &oti, &context, klass);
+       g_assert (info);
 
        /*
        if (method_inst)
index 327178eb8f6a2b8b3435d11b74681c4080df2f62..2c2702b418e4438a7311fe4fe65040f037178eef 100644 (file)
@@ -1148,6 +1148,13 @@ enum {
        MONO_GENERIC_CONTEXT_USED_METHOD = 2
 };
 
+enum {
+       /* Cannot be 0 since this is stored in rgctx slots, and 0 means an unitialized rgctx slot */
+       MONO_GSHAREDVT_BOX_TYPE_VTYPE = 1,
+       MONO_GSHAREDVT_BOX_TYPE_REF = 2,
+       MONO_GSHAREDVT_BOX_TYPE_NULLABLE = 3
+};
+
 typedef enum {
        MONO_RGCTX_INFO_STATIC_DATA,
        MONO_RGCTX_INFO_KLASS,
@@ -1165,6 +1172,7 @@ typedef enum {
        MONO_RGCTX_INFO_CAST_CACHE,
        MONO_RGCTX_INFO_ARRAY_ELEMENT_SIZE,
        MONO_RGCTX_INFO_VALUE_SIZE,
+       /* +1 to avoid zero values in rgctx slots */
        MONO_RGCTX_INFO_FIELD_OFFSET,
        /* Either the code for a gsharedvt method, or the address for a gsharedvt-out trampoline for the method */
        MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE,
@@ -1172,11 +1180,7 @@ typedef enum {
        MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE_VIRT,
        /* Same for calli, associated with a signature */
        MONO_RGCTX_INFO_SIG_GSHAREDVT_OUT_TRAMPOLINE_CALLI,
-       /*
-        * 0 - vtype
-        * 1 - ref
-        * 2 - gsharedvt type
-        */
+       /* One of MONO_GSHAREDVT_BOX_TYPE */
        MONO_RGCTX_INFO_CLASS_BOX_TYPE,
        /* Resolves to a MonoGSharedVtMethodRuntimeInfo */
        MONO_RGCTX_INFO_METHOD_GSHAREDVT_INFO,
@@ -1853,6 +1857,7 @@ enum {
 #define OP_DUMMY_PCONST OP_DUMMY_I8CONST
 #define OP_PADD OP_LADD
 #define OP_PADD_IMM OP_LADD_IMM
+#define OP_PSUB_IMM OP_LSUB_IMM
 #define OP_PAND_IMM OP_LAND_IMM
 #define OP_PSUB OP_LSUB
 #define OP_PMUL OP_LMUL
@@ -1877,6 +1882,7 @@ enum {
 #define OP_DUMMY_PCONST OP_DUMMY_ICONST
 #define OP_PADD OP_IADD
 #define OP_PADD_IMM OP_IADD_IMM
+#define OP_PSUB_IMM OP_ISUB_IMM
 #define OP_PAND_IMM OP_IAND_IMM
 #define OP_PSUB OP_ISUB
 #define OP_PMUL OP_IMUL