2009-08-12 Mark Probst <mark.probst@gmail.com>
[mono.git] / mono / metadata / marshal.c
index d0b23b08908ea420301fc59a9ec7d674d8e0b4ce..fac7cb83b23e6ba1f4928c9ea68dec2a2b2f10f2 100644 (file)
@@ -170,7 +170,7 @@ signature_dup (MonoImage *image, MonoMethodSignature *sig)
        int sigsize;
 
        res = mono_metadata_signature_alloc (image, sig->param_count);
-       sigsize = sizeof (MonoMethodSignature) + ((sig->param_count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType *));
+       sigsize = MONO_SIZEOF_METHOD_SIGNATURE + sig->param_count * sizeof (MonoType *);
        memcpy (res, sig, sigsize);
 
        return res;
@@ -213,6 +213,7 @@ mono_marshal_init (void)
                register_icall (mono_string_builder_to_utf16, "mono_string_builder_to_utf16", "ptr object", FALSE);
                register_icall (mono_array_to_savearray, "mono_array_to_savearray", "ptr object", FALSE);
                register_icall (mono_array_to_lparray, "mono_array_to_lparray", "ptr object", FALSE);
+               register_icall (mono_free_lparray, "mono_free_lparray", "void object ptr", FALSE);
                register_icall (mono_byvalarray_to_array, "mono_byvalarray_to_array", "void object ptr ptr int32", FALSE);
                register_icall (mono_array_to_byvalarray, "mono_array_to_byvalarray", "void ptr object ptr int32", FALSE);
                register_icall (mono_delegate_to_ftnptr, "mono_delegate_to_ftnptr", "ptr object", FALSE);
@@ -244,7 +245,7 @@ mono_marshal_init (void)
                register_icall (mono_context_set, "mono_context_set", "void object", FALSE);
                register_icall (mono_upgrade_remote_class_wrapper, "mono_upgrade_remote_class_wrapper", "void object object", FALSE);
                register_icall (type_from_handle, "type_from_handle", "object ptr", FALSE);
-               register_icall (mono_gc_wbarrier_generic_store, "wb_generic", "void ptr object", FALSE);
+               register_icall (mono_gc_wbarrier_generic_nostore, "wb_generic", "void ptr", FALSE);
                register_icall (runtime_invoke_reset_abort, "runtime_invoke_reset_abort", "void object", FALSE);
 
                mono_cominterop_init ();
@@ -545,13 +546,81 @@ mono_array_to_savearray (MonoArray *array)
 gpointer
 mono_array_to_lparray (MonoArray *array)
 {
+       gpointer *nativeArray = NULL;
+       int nativeArraySize = 0;
+
+       int i = 0;
+       MonoClass *klass;
+
        if (!array)
                return NULL;
 
-       /* fixme: maybe we need to make a copy */
+       klass = array->obj.vtable->klass;
+
+       switch (klass->element_class->byval_arg.type) {
+       case MONO_TYPE_VOID:
+               g_assert_not_reached ();
+               break;
+       case MONO_TYPE_CLASS:
+               nativeArraySize = array->max_length;
+               nativeArray = malloc(sizeof(gpointer) * nativeArraySize);
+               for(i = 0; i < nativeArraySize; ++i)    
+                       nativeArray[i] = ves_icall_System_Runtime_InteropServices_Marshal_GetIUnknownForObjectInternal(((gpointer*)array->vector)[i]);
+               return nativeArray;
+       case MONO_TYPE_U1:
+       case MONO_TYPE_BOOLEAN:
+       case MONO_TYPE_I1:
+       case MONO_TYPE_U2:
+       case MONO_TYPE_CHAR:
+       case MONO_TYPE_I2:
+       case MONO_TYPE_I:
+       case MONO_TYPE_U:
+       case MONO_TYPE_I4:
+       case MONO_TYPE_U4:
+       case MONO_TYPE_U8:
+       case MONO_TYPE_I8:
+       case MONO_TYPE_R4:
+       case MONO_TYPE_R8:
+       case MONO_TYPE_VALUETYPE:
+               /* nothing to do */
+               break;
+       case MONO_TYPE_GENERICINST:
+       case MONO_TYPE_PTR:
+       case MONO_TYPE_OBJECT:
+       case MONO_TYPE_ARRAY: 
+       case MONO_TYPE_SZARRAY:
+       case MONO_TYPE_STRING:
+       default:
+               g_warning ("type 0x%x not handled", klass->element_class->byval_arg.type);
+               g_assert_not_reached ();
+       }
+
        return array->vector;
 }
 
+void
+mono_free_lparray (MonoArray *array, gpointer* nativeArray)
+{
+       MonoClass *klass;
+       int i = 0;
+
+       if (!array)
+               return;
+
+       if (!nativeArray)
+               return;
+
+       klass = array->obj.vtable->klass;
+
+       switch (klass->element_class->byval_arg.type) {
+               case MONO_TYPE_CLASS:
+                       for(i = 0; i < array->max_length; ++i)  
+                               mono_marshal_free_ccw(nativeArray[i]);
+                       free(nativeArray);
+               break;
+       }               
+}
+
 static void
 mono_byvalarray_to_array (MonoArray *arr, gpointer native_arr, MonoClass *elclass, guint32 elnum)
 {
@@ -1338,6 +1407,8 @@ conv_to_icall (MonoMarshalConv conv)
                return mono_array_to_savearray;
        case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
                return mono_array_to_lparray;
+       case MONO_MARSHAL_FREE_LPARRAY:
+               return mono_free_lparray;
        case MONO_MARSHAL_CONV_DEL_FTN:
                return mono_delegate_to_ftnptr;
        case MONO_MARSHAL_CONV_FTN_DEL:
@@ -3758,7 +3829,7 @@ signature_dup_add_this (MonoMethodSignature *sig, MonoClass *klass)
        int i;
 
        res = mono_metadata_signature_alloc (klass->image, sig->param_count + 1);
-       memcpy (res, sig, sizeof (MonoMethodSignature));
+       memcpy (res, sig, MONO_SIZEOF_METHOD_SIGNATURE);
        res->param_count = sig->param_count + 1;
        res->hasthis = FALSE;
        for (i = sig->param_count - 1; i >= 0; i --)
@@ -6707,6 +6778,15 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t,
                        mono_mb_patch_branch (mb, label1);
                        mono_mb_patch_branch (mb, label3);
                }
+               
+               if (klass->element_class->blittable) {
+                       /* free memory allocated (if any) by MONO_MARSHAL_CONV_ARRAY_LPARRAY */
+
+                       mono_mb_emit_ldarg (mb, argnum);
+                       mono_mb_emit_ldloc (mb, conv_arg);
+                       mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_FREE_LPARRAY));
+               }
+
                break;
 
        case MARSHAL_ACTION_PUSH:
@@ -9923,7 +10003,7 @@ mono_marshal_load_type_info (MonoClass* klass)
        layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
 
        /* The mempool is protected by the loader lock */
-       info = mono_image_alloc0 (klass->image, sizeof (MonoMarshalType) + sizeof (MonoMarshalField) * count);
+       info = mono_image_alloc0 (klass->image, MONO_SIZEOF_MARSHAL_TYPE + sizeof (MonoMarshalField) * count);
        info->num_fields = count;
        
        /* Try to find a size for this type in metadata */
@@ -10478,7 +10558,7 @@ mono_marshal_get_thunk_invoke_wrapper (MonoMethod *method)
 
        /* dup & extend signature */
        csig = mono_metadata_signature_alloc (image, param_count);
-       sig_size = sizeof (MonoMethodSignature) + ((sig->param_count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType *));
+       sig_size = MONO_SIZEOF_METHOD_SIGNATURE + sig->param_count * sizeof (MonoType *);
        memcpy (csig, sig, sig_size);
        csig->param_count = param_count;
        csig->hasthis = 0;