Merge pull request #3749 from BrzVlad/fix-mips-fix
[mono.git] / mono / metadata / marshal.c
index 599a7c82c13caf7f9a332be3ef11c6e858b558f3..d771d22d2ee6833810f31e5b6bbb39fbbf3fdc93 100644 (file)
 #include <string.h>
 #include <errno.h>
 
+#if defined(HOST_WIN32)
+#include <objbase.h>
+#endif
+
 /* #define DEBUG_RUNTIME_CODE */
 
 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
@@ -95,7 +99,7 @@ static void
 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object);
 
 static void
-emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object, MonoMarshalNative string_encoding);
+emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object, int offset_of_first_child_field, MonoMarshalNative string_encoding);
 
 static void 
 mono_struct_delete_old (MonoClass *klass, char *ptr);
@@ -778,7 +782,7 @@ mono_free_lparray (MonoArray *array, gpointer* nativeArray)
        if (klass->element_class->byval_arg.type == MONO_TYPE_CLASS) {
                for(i = 0; i < array->max_length; ++i)
                        mono_marshal_free_ccw (mono_array_get (array, MonoObject*, i));
-               free(nativeArray);
+               g_free (nativeArray);
        }
 #endif
 }
@@ -1937,15 +1941,26 @@ emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv
        }
 }
 
+static int offset_of_first_nonstatic_field(MonoClass *klass)
+{
+       int i;
+       for (i = 0; i < klass->field.count; i++) {
+               if (!(klass->fields[i].type->attrs & FIELD_ATTRIBUTE_STATIC) && !mono_field_is_deleted (&klass->fields[i]))
+                       return klass->fields[i].offset - sizeof (MonoObject);
+       }
+
+       return 0;
+}
+
 static void
 emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object,
-                                          MonoMarshalNative string_encoding)
+                                               int offset_of_first_child_field, MonoMarshalNative string_encoding)
 {
        MonoMarshalType *info;
        int i;
 
        if (klass->parent)
-               emit_struct_conv(mb, klass->parent, to_object);
+               emit_struct_conv_full (mb, klass->parent, to_object, offset_of_first_nonstatic_field (klass), string_encoding);
 
        info = mono_marshal_load_type_info (klass);
 
@@ -1953,16 +1968,21 @@ emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_obje
                return;
 
        if (klass->blittable) {
-               int msize = mono_class_value_size (klass, NULL);
-               g_assert (msize == info->native_size);
+               int usize = mono_class_value_size (klass, NULL);
+               g_assert (usize == info->native_size);
                mono_mb_emit_ldloc (mb, 1);
                mono_mb_emit_ldloc (mb, 0);
-               mono_mb_emit_icon (mb, msize);
+               mono_mb_emit_icon (mb, usize);
                mono_mb_emit_byte (mb, CEE_PREFIX1);
                mono_mb_emit_byte (mb, CEE_CPBLK);
 
-               mono_mb_emit_add_to_local (mb, 0, msize);
-               mono_mb_emit_add_to_local (mb, 1, msize);
+               if (to_object) {
+                       mono_mb_emit_add_to_local (mb, 0, usize);
+                       mono_mb_emit_add_to_local (mb, 1, offset_of_first_child_field);
+               } else {
+                       mono_mb_emit_add_to_local (mb, 0, offset_of_first_child_field);
+                       mono_mb_emit_add_to_local (mb, 1, usize);
+               }
                return;
        }
 
@@ -2166,7 +2186,7 @@ emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_obje
 static void
 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
 {
-       emit_struct_conv_full (mb, klass, to_object, (MonoMarshalNative)-1);
+       emit_struct_conv_full (mb, klass, to_object, 0, (MonoMarshalNative)-1);
 }
 
 static void
@@ -2675,6 +2695,11 @@ mono_marshal_method_from_wrapper (MonoMethod *wrapper)
                        return info->d.runtime_invoke.method;
                else
                        return NULL;
+       case MONO_WRAPPER_DELEGATE_INVOKE:
+               if (info)
+                       return info->d.delegate_invoke.method;
+               else
+                       return NULL;
        default:
                return NULL;
        }
@@ -6342,7 +6367,7 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t,
                                mono_mb_emit_stloc (mb, 1);
 
                                /* emit valuetype conversion code */
-                               emit_struct_conv_full (mb, eklass, FALSE, eklass == mono_defaults.char_class ? encoding : (MonoMarshalNative)-1);
+                               emit_struct_conv_full (mb, eklass, FALSE, 0, eklass == mono_defaults.char_class ? encoding : (MonoMarshalNative)-1);
                        }
 
                        mono_mb_emit_add_to_local (mb, index_var, 1);
@@ -6487,7 +6512,7 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t,
                                        mono_mb_emit_stloc (mb, 1);
 
                                        /* emit valuetype conversion code */
-                                       emit_struct_conv_full (mb, eklass, TRUE, eklass == mono_defaults.char_class ? encoding : (MonoMarshalNative)-1);
+                                       emit_struct_conv_full (mb, eklass, TRUE, 0, eklass == mono_defaults.char_class ? encoding : (MonoMarshalNative)-1);
                                }
 
                                if (need_free) {
@@ -9344,7 +9369,8 @@ mono_marshal_get_synchronized_wrapper (MonoMethod *method)
 #endif
 
        if (method->klass->valuetype && !(method->flags & MONO_METHOD_ATTR_STATIC)) {
-               mono_class_set_failure (method->klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
+               /* FIXME Is this really the best way to signal an error here?  Isn't this called much later after class setup? -AK */
+               mono_class_set_type_load_failure (method->klass, "");
 #ifndef DISABLE_JIT
                /* This will throw the type load exception when the wrapper is compiled */
                mono_mb_emit_byte (mb, CEE_LDNULL);
@@ -10510,7 +10536,7 @@ mono_marshal_alloc (gulong size, MonoError *error)
 #else
        res = g_try_malloc ((gulong)size);
        if (!res)
-               mono_error_set_out_of_memory (error, "Could not allocate %i bytes", size);
+               mono_error_set_out_of_memory (error, "Could not allocate %lu bytes", size);
 #endif
        return res;
 }
@@ -11307,6 +11333,9 @@ mono_marshal_load_type_info (MonoClass* klass)
                j++;
        }
 
+       if (klass->byval_arg.type == MONO_TYPE_PTR)
+               info->native_size = sizeof (gpointer);
+
        if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT) {
                info->native_size = MAX (native_size, info->native_size);
                /*