Merge pull request #2408 from tastywheattasteslikechicken/MoreInterfaceSupport
[mono.git] / mono / metadata / marshal.c
index acf4e390fee995fdeb12b02a67ffddc9b989d0c2..a9674cc1aaf944357e8575c05b6d6a84de87b4a0 100644 (file)
@@ -82,6 +82,8 @@ static MonoNativeTlsKey load_type_info_tls_id;
 
 static gboolean use_aot_wrappers;
 
+static int class_marshal_info_count;
+
 static void ftnptr_eh_callback_default (guint32 gchandle);
 
 static MonoFtnPtrEHCallback ftnptr_eh_callback = ftnptr_eh_callback_default;
@@ -352,6 +354,10 @@ mono_marshal_init (void)
 
                mono_cominterop_init ();
                mono_remoting_init ();
+
+               mono_counters_register ("MonoClass::class_marshal_info_count count",
+                                                               MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_marshal_info_count);
+
        }
 }
 
@@ -1964,7 +1970,7 @@ emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_obje
        }
 
        if (klass != mono_class_try_get_safehandle_class ()) {
-               if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
+               if (mono_class_is_auto_layout (klass)) {
                        char *msg = g_strdup_printf ("Type %s which is passed to unmanaged code must have a StructLayout attribute.",
                                                                                 mono_type_full_name (&klass->byval_arg));
                        mono_mb_emit_exception_marshal_directive (mb, msg);
@@ -1999,7 +2005,7 @@ emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_obje
                         * the layout to the managed structure as well.
                         */
                        
-                       if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) && (usize == 0)) {
+                       if (mono_class_is_explicit_layout (klass) && (usize == 0)) {
                                if (MONO_TYPE_IS_REFERENCE (info->fields [i].field->type) ||
                                    ((!last_field && MONO_TYPE_IS_REFERENCE (info->fields [i + 1].field->type))))
                                        g_error ("Type %s which has an [ExplicitLayout] attribute cannot have a "
@@ -2877,6 +2883,7 @@ cache_generic_delegate_wrapper (GHashTable *cache, MonoMethod *orig_method, Mono
 {
        MonoError error;
        MonoMethod *inst, *res;
+       WrapperInfo *ginfo, *info;
 
        /*
         * We use the same cache for the generic definition and the instances.
@@ -2884,6 +2891,16 @@ cache_generic_delegate_wrapper (GHashTable *cache, MonoMethod *orig_method, Mono
        inst = mono_class_inflate_generic_method_checked (def, ctx, &error);
        g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
 
+       ginfo = mono_marshal_get_wrapper_info (def);
+       if (ginfo) {
+               info = (WrapperInfo *)mono_image_alloc0 (def->klass->image, sizeof (WrapperInfo));
+               info->subtype = ginfo->subtype;
+               if (info->subtype == WRAPPER_SUBTYPE_NONE) {
+                       info->d.delegate_invoke.method = mono_class_inflate_generic_method_checked (ginfo->d.delegate_invoke.method, ctx, &error);
+                       mono_error_assert_ok (&error);
+               }
+       }
+
        mono_memory_barrier ();
        mono_marshal_lock ();
        res = (MonoMethod *)g_hash_table_lookup (cache, orig_method->klass);
@@ -3253,7 +3270,7 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt
        MonoMethod *res;
        GHashTable *cache;
        gpointer cache_key = NULL;
-       SignaturePointerPair key;
+       SignaturePointerPair key = { NULL, NULL };
        SignaturePointerPair *new_key;
        int local_i, local_len, local_delegates, local_d, local_target, local_res;
        int pos0, pos1, pos2;
@@ -3311,7 +3328,7 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt
 
                container = mono_method_get_generic_container (method);
                if (!container)
-                       container = method->klass->generic_container;
+                       container = mono_class_try_get_generic_container (method->klass); //FIXME is this a case of a try?
                g_assert (container);
 
                invoke_sig = sig = mono_signature_no_pinvoke (method);
@@ -3554,7 +3571,7 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt
 #endif /* DISABLE_JIT */
 
        info = mono_wrapper_info_create (mb, subtype);
-       info->d.delegate_invoke.method = orig_method;
+       info->d.delegate_invoke.method = method;
 
        if (ctx) {
                MonoMethod *def;
@@ -4927,8 +4944,7 @@ 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)
+               if (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype)
                        break;
 
                conv_arg = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
@@ -4974,8 +4990,7 @@ emit_marshal_vtype (EmitMarshalContext *m, int argnum, MonoType *t,
                        /* Have to change the signature since the vtype is passed byref */
                        m->csig->params [argnum - m->csig->hasthis] = &mono_defaults.int_class->byval_arg;
 
-                       if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
-                               klass->blittable || klass->enumtype)
+                       if (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype)
                                mono_mb_emit_ldarg_addr (mb, argnum);
                        else
                                mono_mb_emit_ldloc (mb, conv_arg);
@@ -4990,8 +5005,7 @@ 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) {
+               if (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype) {
                        mono_mb_emit_ldarg (mb, argnum);
                        break;
                }                       
@@ -5023,8 +5037,7 @@ 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)
+               if (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype)
                        break;
 
                if (t->byref) {
@@ -5052,8 +5065,7 @@ emit_marshal_vtype (EmitMarshalContext *m, int argnum, MonoType *t,
                break;
 
        case MARSHAL_ACTION_CONV_RESULT:
-               if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
-                       klass->blittable) {
+               if (mono_class_is_explicit_layout (klass) || klass->blittable) {
                        mono_mb_emit_stloc (mb, 3);
                        break;
                }
@@ -5072,8 +5084,7 @@ emit_marshal_vtype (EmitMarshalContext *m, int argnum, MonoType *t,
                break;
 
        case MARSHAL_ACTION_MANAGED_CONV_IN:
-               if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
-                       klass->blittable || klass->enumtype) {
+               if (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype) {
                        conv_arg = 0;
                        break;
                }
@@ -5105,11 +5116,8 @@ emit_marshal_vtype (EmitMarshalContext *m, int argnum, MonoType *t,
                break;
 
        case MARSHAL_ACTION_MANAGED_CONV_OUT:
-               if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
-                       klass->blittable || klass->enumtype) {
+               if (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype)
                        break;
-               }
-
                if (t->byref && (t->attrs & PARAM_ATTRIBUTE_IN) && !(t->attrs & PARAM_ATTRIBUTE_OUT))
                        break;
 
@@ -5132,8 +5140,7 @@ emit_marshal_vtype (EmitMarshalContext *m, int argnum, MonoType *t,
                break;
 
        case MARSHAL_ACTION_MANAGED_CONV_RESULT:
-               if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
-                       klass->blittable || klass->enumtype) {
+               if (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype) {
                        mono_mb_emit_stloc (mb, 3);
                        m->retobj_var = 0;
                        break;
@@ -5465,7 +5472,7 @@ emit_marshal_safehandle (EmitMarshalContext *m, int argnum, MonoType *t,
                MonoMethod *ctor = NULL;
                int intptr_handle_slot;
                
-               if (t->data.klass->flags & TYPE_ATTRIBUTE_ABSTRACT){
+               if (mono_class_is_abstract (t->data.klass)) {
                        mono_mb_emit_byte (mb, CEE_POP);
                        mono_mb_emit_exception_marshal_directive (mb, g_strdup ("Returned SafeHandles should not be abstract"));
                        break;
@@ -5924,7 +5931,7 @@ emit_marshal_object (EmitMarshalContext *m, int argnum, MonoType *t,
                }
 
                /* The class can not have an automatic layout */
-               if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
+               if (mono_class_is_auto_layout (klass)) {
                        mono_mb_emit_auto_layout_exception (mb, klass);
                        break;
                }
@@ -6044,7 +6051,7 @@ emit_marshal_object (EmitMarshalContext *m, int argnum, MonoType *t,
                }
 
                /* The class can not have an automatic layout */
-               if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
+               if (mono_class_is_auto_layout (klass)) {
                        mono_mb_emit_auto_layout_exception (mb, klass);
                        break;
                }
@@ -6678,7 +6685,8 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t,
                        mono_mb_emit_icon (mb, esize);
                        mono_mb_emit_byte (mb, CEE_MUL);
                        mono_mb_emit_byte (mb, CEE_PREFIX1);
-                       mono_mb_emit_byte (mb, CEE_CPBLK);                      
+                       mono_mb_emit_byte (mb, CEE_CPBLK);
+                       mono_mb_patch_branch (mb, label1);
                        break;
                }
 
@@ -7504,7 +7512,7 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM
        if (MONO_TYPE_ISSTRUCT (sig->ret)) {
                MonoClass *klass = mono_class_from_mono_type (sig->ret);
                mono_class_init (klass);
-               if (!(((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable)) {
+               if (!(mono_class_is_explicit_layout (klass) || klass->blittable)) {
                        /* This is used by emit_marshal_vtype (), but it needs to go right before the call */
                        mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
                        mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
@@ -8243,7 +8251,7 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i
        if (MONO_TYPE_ISSTRUCT (sig->ret)) {
                MonoClass *klass = mono_class_from_mono_type (sig->ret);
                mono_class_init (klass);
-               if (!(((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable)) {
+               if (!(mono_class_is_explicit_layout (klass) || klass->blittable)) {
                        /* This is used by emit_marshal_vtype (), but it needs to go right before the call */
                        mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
                        mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
@@ -9268,7 +9276,7 @@ mono_marshal_get_synchronized_inner_wrapper (MonoMethod *method)
                method = ((MonoMethodInflated*)method)->declaring;
                container = mono_method_get_generic_container (method);
                if (!container)
-                       container = method->klass->generic_container;
+                       container = mono_class_try_get_generic_container (method->klass); //FIXME is this a case of a try?
                g_assert (container);
        }
 
@@ -9322,7 +9330,7 @@ mono_marshal_get_synchronized_wrapper (MonoMethod *method)
                method = ((MonoMethodInflated*)method)->declaring;
                container = mono_method_get_generic_container (method);
                if (!container)
-                       container = method->klass->generic_container;
+                       container = mono_class_try_get_generic_container (method->klass); //FIXME is this a case of a try?
                g_assert (container);
        }
 
@@ -9549,7 +9557,7 @@ is_monomorphic_array (MonoClass *klass)
                return FALSE;
 
        element_class = klass->element_class;
-       return (element_class->flags & TYPE_ATTRIBUTE_SEALED) || element_class->valuetype;
+       return mono_class_is_sealed (element_class) || element_class->valuetype;
 }
 
 static int
@@ -9569,7 +9577,7 @@ get_virtual_stelemref_kind (MonoClass *element_class)
        /*Arrays are sealed but are covariant on their element type, We can't use any of the fast paths.*/
        if (mono_class_is_marshalbyref (element_class) || element_class->rank || mono_class_has_variant_generic_params (element_class))
                return STELEMREF_COMPLEX;
-       if (element_class->flags & TYPE_ATTRIBUTE_SEALED)
+       if (mono_class_is_sealed (element_class))
                return STELEMREF_SEALED_CLASS;
        return STELEMREF_CLASS;
 }
@@ -9928,14 +9936,14 @@ get_virtual_stelemref_wrapper (int kind)
                /* uiid = klass->interface_id; */
                mono_mb_emit_ldloc (mb, aklass);
                mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoClass, interface_id));
-               mono_mb_emit_byte (mb, CEE_LDIND_U2);
+               mono_mb_emit_byte (mb, CEE_LDIND_U4);
                mono_mb_emit_stloc (mb, uiid);
 
                /*if (uiid > vt->max_interface_id)*/
                mono_mb_emit_ldloc (mb, uiid);
                mono_mb_emit_ldloc (mb, vtable);
                mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoVTable, max_interface_id));
-               mono_mb_emit_byte (mb, CEE_LDIND_U2);
+               mono_mb_emit_byte (mb, CEE_LDIND_U4);
                b2 = mono_mb_emit_branch (mb, CEE_BGT_UN);
 
                /* if (!(vt->interface_bitmap [(uiid) >> 3] & (1 << ((uiid)&7)))) */
@@ -10786,7 +10794,7 @@ ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rty
                return 0;
        }
 
-       layout = (klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK);
+       layout = (mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK);
 
        if (type->type == MONO_TYPE_PTR || type->type == MONO_TYPE_FNPTR) {
                return sizeof (gpointer);
@@ -11265,7 +11273,7 @@ mono_marshal_load_type_info (MonoClass* klass)
                count++;
        }
 
-       layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
+       layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
 
        /* The mempool is protected by the loader lock */
        info = (MonoMarshalType *)mono_image_alloc0 (klass->image, MONO_SIZEOF_MARSHAL_TYPE + sizeof (MonoMarshalField) * count);
@@ -11371,6 +11379,7 @@ mono_marshal_load_type_info (MonoClass* klass)
                /*We do double-checking locking on marshal_info */
                mono_memory_barrier ();
                klass->marshal_info = info;
+               ++class_marshal_info_count;
        }
        mono_marshal_unlock ();
 
@@ -11632,11 +11641,10 @@ mono_marshal_asany (MonoObject *o, MonoMarshalNative string_encoding, int param_
 
                klass = t->data.klass;
 
-               if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT)
+               if (mono_class_is_auto_layout (klass))
                        break;
 
-               if (klass->valuetype && (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
-                       klass->blittable || klass->enumtype))
+               if (klass->valuetype && (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype))
                        return mono_object_unbox (o);
 
                res = mono_marshal_alloc (mono_class_native_size (klass, NULL), &error);
@@ -11697,8 +11705,7 @@ mono_marshal_free_asany (MonoObject *o, gpointer ptr, MonoMarshalNative string_e
        case MONO_TYPE_VALUETYPE: {
                klass = t->data.klass;
 
-               if (klass->valuetype && (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
-                                                                klass->blittable || klass->enumtype))
+               if (klass->valuetype && (mono_class_is_explicit_layout (klass) || klass->blittable || klass->enumtype))
                        break;
 
                if (param_attrs & PARAM_ATTRIBUTE_OUT) {