Reoder 4.x supported_runtimes versions to load correct mscorlib when <supportedRuntim...
[mono.git] / mono / metadata / marshal.c
index 0e6a259a4376a1f5abaf7352ece91310eae26458..ed60cb7234a585f18c1362181c75e6f16dcbaebf 100644 (file)
@@ -6,6 +6,7 @@
  *
  * Copyright 2002-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
  *
  */
 
@@ -35,6 +36,8 @@
 #include "mono/metadata/gc-internal.h"
 #include "mono/metadata/cominterop.h"
 #include "mono/utils/mono-counters.h"
+#include "mono/utils/mono-tls.h"
+#include "mono/utils/mono-memory-model.h"
 #include <string.h>
 #include <errno.h>
 
@@ -76,9 +79,9 @@ typedef struct _MonoRemotingMethods MonoRemotingMethods;
 static CRITICAL_SECTION marshal_mutex;
 static gboolean marshal_mutex_initialized;
 
-static guint32 last_error_tls_id;
+static MonoNativeTlsKey last_error_tls_id;
 
-static guint32 load_type_info_tls_id;
+static MonoNativeTlsKey load_type_info_tls_id;
 
 static void
 delegate_hash_table_add (MonoDelegate *d);
@@ -201,8 +204,8 @@ mono_marshal_init (void)
                module_initialized = TRUE;
                InitializeCriticalSection (&marshal_mutex);
                marshal_mutex_initialized = TRUE;
-               last_error_tls_id = TlsAlloc ();
-               load_type_info_tls_id = TlsAlloc ();
+               mono_native_tls_alloc (&last_error_tls_id, NULL);
+               mono_native_tls_alloc (&load_type_info_tls_id, NULL);
 
                register_icall (ves_icall_System_Threading_Thread_ResetAbort, "ves_icall_System_Threading_Thread_ResetAbort", "void", TRUE);
                register_icall (mono_marshal_string_to_utf16, "mono_marshal_string_to_utf16", "ptr obj", FALSE);
@@ -263,8 +266,8 @@ mono_marshal_cleanup (void)
 {
        mono_cominterop_cleanup ();
 
-       TlsFree (load_type_info_tls_id);
-       TlsFree (last_error_tls_id);
+       mono_native_tls_free (load_type_info_tls_id);
+       mono_native_tls_free (last_error_tls_id);
        DeleteCriticalSection (&marshal_mutex);
        marshal_mutex_initialized = FALSE;
 }
@@ -4496,6 +4499,7 @@ mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual)
        static MonoMethodSignature *cctor_signature = NULL;
        static MonoMethodSignature *finalize_signature = NULL;
        char *name;
+       const char *param_names [16];
        gboolean need_direct_wrapper = FALSE;
 
        g_assert (method);
@@ -4617,6 +4621,12 @@ mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual)
        mb = mono_mb_new (target_klass, name,  MONO_WRAPPER_RUNTIME_INVOKE);
        g_free (name);
 
+       param_names [0] = "this";
+       param_names [1] = "params";
+       param_names [2] = "exc";
+       param_names [3] = "method";
+       mono_mb_set_param_names (mb, param_names);
+
        emit_runtime_invoke_body (mb, target_klass, method, sig, callsig, virtual, need_direct_wrapper);
 
        if (need_direct_wrapper) {
@@ -7879,10 +7889,13 @@ emit_marshal_ptr (EmitMarshalContext *m, int argnum, MonoType *t,
 
        switch (action) {
        case MARSHAL_ACTION_CONV_IN:
+               /* MS seems to allow this in some cases, ie. bxc #158 */
+               /*
                if (MONO_TYPE_ISSTRUCT (t->data.type) && !mono_class_from_mono_type (t->data.type)->blittable) {
                        char *msg = g_strdup_printf ("Can not marshal 'parameter #%d': Pointers can not reference marshaled structures. Use byref instead.", argnum + 1);
                        mono_mb_emit_exception_marshal_directive (m->mb, msg);
                }
+               */
                break;
 
        case MARSHAL_ACTION_PUSH:
@@ -8698,6 +8711,7 @@ mono_marshal_set_callconv_from_modopt (MonoMethod *method, MonoMethodSignature *
 
 /*
  * generates IL code to call managed methods from unmanaged code 
+ * If target_handle==0, the wrapper info will be a NativeToManagedWrapperInfo structure.
  */
 MonoMethod *
 mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, uint32_t target_handle)
@@ -8832,10 +8846,17 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass,
 
        mono_marshal_emit_managed_wrapper (mb, invoke_sig, mspecs, &m, method, target_handle);
 
-       if (!target_handle)
+       if (!target_handle) {
+               NativeToManagedWrapperInfo *info;
+
                res = mono_mb_create_and_cache (cache, method,
                                                                                         mb, csig, sig->param_count + 16);
-       else {
+               // FIXME: Associate it with the method+delegate_klass pair
+               info = mono_image_alloc0 (method->klass->image, sizeof (NativeToManagedWrapperInfo));
+               info->method = method;
+               info->klass = delegate_klass;
+               mono_marshal_set_wrapper_info (res, info);
+       } else {
                mb->dynamic = 1;
                res = mono_mb_create_method (mb, csig, sig->param_count + 16);
        }
@@ -9011,6 +9032,8 @@ mono_marshal_get_castclass_with_cache (void)
        mono_mb_emit_byte (mb, CEE_RET);
 
        res = mono_mb_create_method (mb, sig, 8);
+       STORE_STORE_FENCE;
+
        if (InterlockedCompareExchangePointer ((volatile gpointer *)&cached, res, NULL)) {
                mono_free_method (res);
                mono_metadata_free_method_signature (sig);
@@ -9035,7 +9058,7 @@ mono_marshal_get_isinst_with_cache (void)
        if (cached)
                return cached;
 
-       mb = mono_mb_new (mono_defaults.object_class, "__isisnt_with_cache", MONO_WRAPPER_CASTCLASS);
+       mb = mono_mb_new (mono_defaults.object_class, "__isinst_with_cache", MONO_WRAPPER_CASTCLASS);
        sig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
        sig->params [0] = &mono_defaults.object_class->byval_arg;
        sig->params [1] = &mono_defaults.int_class->byval_arg;
@@ -9125,6 +9148,8 @@ mono_marshal_get_isinst_with_cache (void)
        mono_mb_emit_byte (mb, CEE_RET);
 
        res = mono_mb_create_method (mb, sig, 8);
+       STORE_STORE_FENCE;
+
        if (InterlockedCompareExchangePointer ((volatile gpointer *)&cached, res, NULL)) {
                mono_free_method (res);
                mono_metadata_free_method_signature (sig);
@@ -9295,7 +9320,7 @@ mono_marshal_get_proxy_cancast (MonoClass *klass)
        GHashTable *cache;
        MonoMethod *res;
        int pos_failed, pos_end;
-       char *name;
+       char *name, *klass_name;
        MonoMethod *can_cast_to;
        MonoMethodDesc *desc;
        MonoMethodBuilder *mb;
@@ -9310,9 +9335,11 @@ mono_marshal_get_proxy_cancast (MonoClass *klass)
                isint_sig->ret = &mono_defaults.object_class->byval_arg;
                isint_sig->pinvoke = 0;
        }
-       
-       name = g_strdup_printf ("__proxy_isinst_wrapper_%s", klass->name); 
+
+       klass_name = mono_type_full_name (&klass->byval_arg);
+       name = g_strdup_printf ("__proxy_isinst_wrapper_%s", klass_name); 
        mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_PROXY_ISINST);
+       g_free (klass_name);
        g_free (name);
        
        mb->method->save_lmf = 1;
@@ -9714,8 +9741,13 @@ get_virtual_stelemref_kind (MonoClass *element_class)
                return STELEMREF_OBJECT;
        if (is_monomorphic_array (element_class))
                return STELEMREF_SEALED_CLASS;
+       /* Compressed interface bitmaps require code that is quite complex, so don't optimize for it. */
        if (MONO_CLASS_IS_INTERFACE (element_class) && !mono_class_has_variant_generic_params (element_class))
+#ifdef COMPRESSED_INTERFACE_BITMAP
+               return STELEMREF_COMPLEX;
+#else
                return STELEMREF_INTERFACE;
+#endif
        /*Arrays are sealed but are covariant on their element type, We can't use any of the fast paths.*/
        if (element_class->marshalbyref || element_class->rank || mono_class_has_variant_generic_params (element_class))
                return STELEMREF_COMPLEX;
@@ -9784,7 +9816,7 @@ mono_marshal_get_virtual_stelemref (MonoClass *array_class)
        MonoMethod *res;
        int kind;
        char *name;
-
+       const char *param_names [16];
        guint32 b1, b2, b3;
        int aklass, vklass, vtable, uiid;
        int array_slot_addr;
@@ -9799,6 +9831,10 @@ mono_marshal_get_virtual_stelemref (MonoClass *array_class)
        mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_STELEMREF);
        g_free (name);
 
+       param_names [0] = "index";
+       param_names [1] = "value";
+       mono_mb_set_param_names (mb, param_names);
+
        if (!signature) {
                MonoMethodSignature *sig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
 
@@ -10454,6 +10490,7 @@ mono_marshal_get_array_address (int rank, int elem_size)
                elem_addr_cache [elem_addr_cache_next].rank = rank;
                elem_addr_cache [elem_addr_cache_next].elem_size = elem_size;
                elem_addr_cache [elem_addr_cache_next].method = ret;
+               elem_addr_cache_next ++;
 
                info = mono_image_alloc0 (mono_defaults.corlib, sizeof (ElementAddrWrapperInfo));
                info->rank = rank;
@@ -10532,9 +10569,9 @@ void
 mono_marshal_set_last_error (void)
 {
 #ifdef WIN32
-       TlsSetValue (last_error_tls_id, GINT_TO_POINTER (GetLastError ()));
+       mono_native_tls_set_value (last_error_tls_id, GINT_TO_POINTER (GetLastError ()));
 #else
-       TlsSetValue (last_error_tls_id, GINT_TO_POINTER (errno));
+       mono_native_tls_set_value (last_error_tls_id, GINT_TO_POINTER (errno));
 #endif
 }
 
@@ -10542,7 +10579,7 @@ static void
 mono_marshal_set_last_error_windows (int error)
 {
 #ifdef WIN32
-       TlsSetValue (last_error_tls_id, GINT_TO_POINTER (error));
+       mono_native_tls_set_value (last_error_tls_id, GINT_TO_POINTER (error));
 #endif
 }
 
@@ -10784,7 +10821,7 @@ ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
 {
        MONO_ARCH_SAVE_REGS;
 
-       return (GPOINTER_TO_INT (TlsGetValue (last_error_tls_id)));
+       return (GPOINTER_TO_INT (mono_native_tls_get_value (last_error_tls_id)));
 }
 
 guint32 
@@ -11184,7 +11221,7 @@ ves_icall_System_Runtime_InteropServices_Marshal_GetDelegateForFunctionPointerIn
 static gboolean
 mono_marshal_is_loading_type_info (MonoClass *klass)
 {
-       GSList *loads_list = TlsGetValue (load_type_info_tls_id);
+       GSList *loads_list = mono_native_tls_get_value (load_type_info_tls_id);
 
        return g_slist_find (loads_list, klass) != NULL;
 }
@@ -11229,9 +11266,9 @@ mono_marshal_load_type_info (MonoClass* klass)
         * under initialization in a TLS list.
         */
        g_assert (!mono_marshal_is_loading_type_info (klass));
-       loads_list = TlsGetValue (load_type_info_tls_id);
+       loads_list = mono_native_tls_get_value (load_type_info_tls_id);
        loads_list = g_slist_prepend (loads_list, klass);
-       TlsSetValue (load_type_info_tls_id, loads_list);
+       mono_native_tls_set_value (load_type_info_tls_id, loads_list);
        
        iter = NULL;
        while ((field = mono_class_get_fields (klass, &iter))) {
@@ -11333,9 +11370,9 @@ mono_marshal_load_type_info (MonoClass* klass)
                mono_marshal_load_type_info (klass->element_class);
        }
 
-       loads_list = TlsGetValue (load_type_info_tls_id);
+       loads_list = mono_native_tls_get_value (load_type_info_tls_id);
        loads_list = g_slist_remove (loads_list, klass);
-       TlsSetValue (load_type_info_tls_id, loads_list);
+       mono_native_tls_set_value (load_type_info_tls_id, loads_list);
 
        /*We do double-checking locking on marshal_info */
        mono_memory_barrier ();