2010-01-08 Rodrigo Kumpera <rkumpera@novell.com>
[mono.git] / mono / metadata / marshal.c
index cd443aa7b5784c4c0f429a31b3b6176749f4c431..ba098c26e077725f2e73e3917a3542ac2c531595 100644 (file)
@@ -2603,7 +2603,7 @@ mono_mb_emit_restore_result (MonoMethodBuilder *mb, MonoType *return_type)
                mono_mb_emit_byte (mb, mono_type_to_ldind (return_type));
                break;
        case MONO_TYPE_GENERICINST:
-               if (!mono_type_generic_inst_is_valuetype (return_type))
+               if (!mono_type_generic_inst_is_valuetype (t))
                        break;
                /* fall through */
        case MONO_TYPE_VALUETYPE: {
@@ -4200,6 +4200,8 @@ mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual)
        if (need_direct_wrapper) {
                /* Already searched at the start */
        } else {
+               MonoMethodSignature *tmp_sig;
+
                callsig = mono_marshal_get_runtime_invoke_sig (callsig);
 
                cache = get_cache (&target_klass->image->runtime_invoke_cache, 
@@ -4216,7 +4218,10 @@ mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual)
                        return res;
                }
 
-               // FIXME: When to free callsig ?
+               /* Make a copy of the signature from the image mempool */
+               tmp_sig = callsig;
+               callsig = mono_metadata_signature_dup_full (target_klass->image, callsig);
+               g_free (tmp_sig);
        }
 
        /* to make it work with our special string constructors */
@@ -4297,6 +4302,7 @@ mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual)
                        continue;
                }
 
+               /*FIXME 'this doesn't handle generic enums. Shouldn't we?*/
                type = sig->params [i]->type;
 handle_enum:
                switch (type) {
@@ -4468,6 +4474,8 @@ handle_enum:
        mono_mb_emit_ldloc (mb, 0);
        mono_mb_emit_byte (mb, CEE_RET);
 
+       g_free (tmp_nullable_locals);
+
        if (need_direct_wrapper) {
                mb->skip_visibility = 1;
                res = mono_mb_create_and_cache (cache, method, mb, csig, sig->param_count + 16);
@@ -5585,10 +5593,6 @@ emit_marshal_vtype (EmitMarshalContext *m, int argnum, MonoType *t,
 
        switch (action) {
        case MARSHAL_ACTION_CONV_IN:
-               if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
-                       klass->blittable || klass->enumtype)
-                       break;
-
                if (klass == date_time_class) {
                        /* Convert it to an OLE DATE type */
                        static MonoMethod *to_oadate;
@@ -5618,6 +5622,10 @@ emit_marshal_vtype (EmitMarshalContext *m, int argnum, MonoType *t,
                        break;
                }
 
+               if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
+                       klass->blittable || klass->enumtype)
+                       break;
+
                conv_arg = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
                        
                /* store the address of the source into local variable 0 */
@@ -5690,10 +5698,6 @@ emit_marshal_vtype (EmitMarshalContext *m, int argnum, MonoType *t,
                break;
 
        case MARSHAL_ACTION_CONV_OUT:
-               if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
-                       klass->blittable || klass->enumtype)
-                       break;
-
                if (klass == date_time_class) {
                        /* Convert from an OLE DATE type */
                        static MonoMethod *from_oadate;
@@ -5714,6 +5718,10 @@ emit_marshal_vtype (EmitMarshalContext *m, int argnum, MonoType *t,
                        break;
                }
 
+               if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
+                       klass->blittable || klass->enumtype)
+                       break;
+
                if (t->byref) {
                        /* dst = argument */
                        mono_mb_emit_ldarg (mb, argnum);