X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fmarshal.c;h=ed60cb7234a585f18c1362181c75e6f16dcbaebf;hb=6e71b433250972e822552dfa9d3669b2156f1910;hp=c5865558b2613e1dda196c8d453ab6ade1cb2c9f;hpb=08f0bcaad89540260323f24811cbf896cfe471ed;p=mono.git diff --git a/mono/metadata/marshal.c b/mono/metadata/marshal.c index c5865558b26..ed60cb7234a 100644 --- a/mono/metadata/marshal.c +++ b/mono/metadata/marshal.c @@ -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 #include @@ -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); @@ -86,6 +89,9 @@ delegate_hash_table_add (MonoDelegate *d); 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); + static void mono_struct_delete_old (MonoClass *klass, char *ptr); @@ -104,6 +110,9 @@ mono_string_utf8_to_builder2 (char *text); static MonoStringBuilder * mono_string_utf16_to_builder2 (gunichar2 *text); +static MonoString* +mono_string_new_len_wrapper (const char *text, guint length); + static void mono_byvalarray_to_array (MonoArray *arr, gpointer native_arr, MonoClass *eltype, guint32 elnum); @@ -195,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); @@ -204,6 +213,7 @@ mono_marshal_init (void) register_icall (mono_string_to_utf16, "mono_string_to_utf16", "ptr obj", FALSE); register_icall (mono_string_from_utf16, "mono_string_from_utf16", "obj ptr", FALSE); register_icall (mono_string_new_wrapper, "mono_string_new_wrapper", "obj ptr", FALSE); + register_icall (mono_string_new_len_wrapper, "mono_string_new_len_wrapper", "obj ptr int", FALSE); register_icall (mono_string_to_utf8, "mono_string_to_utf8", "ptr obj", FALSE); register_icall (mono_string_to_lpstr, "mono_string_to_lpstr", "ptr obj", FALSE); register_icall (mono_string_to_ansibstr, "mono_string_to_ansibstr", "ptr object", FALSE); @@ -256,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; } @@ -968,6 +978,12 @@ mono_string_to_byvalwstr (gpointer dst, MonoString *src, int size) *((gunichar2 *) dst + len) = 0; } +static MonoString* +mono_string_new_len_wrapper (const char *text, guint length) +{ + return mono_string_new_len (mono_domain_get (), text, length); +} + static int mono_mb_emit_proxy_check (MonoMethodBuilder *mb, int branch_code) { @@ -1424,12 +1440,14 @@ conv_to_icall (MonoMarshalConv conv) return mono_marshal_string_to_utf16; case MONO_MARSHAL_CONV_LPWSTR_STR: return mono_string_from_utf16; - case MONO_MARSHAL_CONV_LPSTR_STR: + case MONO_MARSHAL_CONV_LPTSTR_STR: #ifdef TARGET_WIN32 return mono_string_from_utf16; #else return mono_string_new_wrapper; #endif + case MONO_MARSHAL_CONV_LPSTR_STR: + return mono_string_new_wrapper; case MONO_MARSHAL_CONV_STR_LPTSTR: #ifdef TARGET_WIN32 return mono_marshal_string_to_utf16; @@ -1756,7 +1774,8 @@ emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv } static void -emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object) +emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object, + MonoMarshalNative string_encoding) { MonoMarshalType *info; int i; @@ -1859,8 +1878,18 @@ emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object) case MONO_TYPE_R8: mono_mb_emit_ldloc (mb, 1); mono_mb_emit_ldloc (mb, 0); - mono_mb_emit_byte (mb, mono_type_to_ldind (ftype)); - mono_mb_emit_byte (mb, mono_type_to_stind (ftype)); + if (t == MONO_TYPE_CHAR && ntype == MONO_NATIVE_U1 && string_encoding != MONO_NATIVE_LPWSTR) { + if (to_object) { + mono_mb_emit_byte (mb, CEE_LDIND_U1); + mono_mb_emit_byte (mb, CEE_STIND_I2); + } else { + mono_mb_emit_byte (mb, CEE_LDIND_U2); + mono_mb_emit_byte (mb, CEE_STIND_I1); + } + } else { + mono_mb_emit_byte (mb, mono_type_to_ldind (ftype)); + mono_mb_emit_byte (mb, mono_type_to_stind (ftype)); + } break; case MONO_TYPE_VALUETYPE: { int src_var, dst_var; @@ -1965,6 +1994,12 @@ emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object) } } +static void +emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object) +{ + emit_struct_conv_full (mb, klass, to_object, -1); +} + static void emit_struct_free (MonoMethodBuilder *mb, MonoClass *klass, int struct_var) { @@ -2187,6 +2222,7 @@ mono_marshal_get_string_to_ptr_conv (MonoMethodPInvoke *piinfo, MonoMarshalSpec case MONO_NATIVE_LPWSTR: return MONO_MARSHAL_CONV_STR_LPWSTR; case MONO_NATIVE_LPSTR: + case MONO_NATIVE_VBBYREFSTR: return MONO_MARSHAL_CONV_STR_LPSTR; case MONO_NATIVE_LPTSTR: return MONO_MARSHAL_CONV_STR_LPTSTR; @@ -2229,6 +2265,7 @@ mono_marshal_get_ptr_to_string_conv (MonoMethodPInvoke *piinfo, MonoMarshalSpec *need_free = FALSE; return MONO_MARSHAL_CONV_LPWSTR_STR; case MONO_NATIVE_LPSTR: + case MONO_NATIVE_VBBYREFSTR: return MONO_MARSHAL_CONV_LPSTR_STR; case MONO_NATIVE_LPTSTR: return MONO_MARSHAL_CONV_LPTSTR_STR; @@ -3991,6 +4028,8 @@ mono_marshal_get_delegate_invoke (MonoMethod *method, MonoDelegate *del) res = newm; new_key = g_new0 (SignatureMethodPair, 1); *new_key = key; + if (static_method_with_first_arg_bound) + new_key->sig = signature_dup (del->method->klass->image, key.sig); g_hash_table_insert (cache, new_key, res); mono_marshal_set_wrapper_info (res, new_key); mono_marshal_unlock (); @@ -4024,7 +4063,7 @@ signature_dup_add_this (MonoMethodSignature *sig, MonoClass *klass) res->hasthis = FALSE; for (i = sig->param_count - 1; i >= 0; i --) res->params [i + 1] = sig->params [i]; - res->params [0] = &mono_ptr_class_get (&klass->byval_arg)->byval_arg; + res->params [0] = klass->valuetype ? &klass->this_arg : &klass->byval_arg; return res; } @@ -4460,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); @@ -4572,11 +4612,21 @@ mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual) csig->params [2] = &mono_defaults.int_class->byval_arg; csig->params [3] = &mono_defaults.int_class->byval_arg; csig->pinvoke = 1; +#if TARGET_WIN32 + /* This is called from runtime code so it has to be cdecl */ + csig->call_convention = MONO_CALL_C; +#endif name = mono_signature_to_name (callsig, virtual ? "runtime_invoke_virtual" : "runtime_invoke"); 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) { @@ -5346,7 +5396,7 @@ emit_marshal_custom (EmitMarshalContext *m, int argnum, MonoType *t, static MonoClass *ICustomMarshaler = NULL; static MonoMethod *cleanup_native, *cleanup_managed; static MonoMethod *marshal_managed_to_native, *marshal_native_to_managed; - MonoMethod *get_instance; + MonoMethod *get_instance = NULL; MonoMethodBuilder *mb = m->mb; char *exception_msg = NULL; guint32 loc1; @@ -5354,7 +5404,10 @@ emit_marshal_custom (EmitMarshalContext *m, int argnum, MonoType *t, if (!ICustomMarshaler) { ICustomMarshaler = mono_class_from_name (mono_defaults.corlib, "System.Runtime.InteropServices", "ICustomMarshaler"); - g_assert (ICustomMarshaler); + if (!ICustomMarshaler) { + exception_msg = g_strdup ("Current profile doesn't support ICustomMarshaler"); + goto handle_exception; + } cleanup_native = mono_class_get_method_from_name (ICustomMarshaler, "CleanUpNativeData", 1); g_assert (cleanup_native); @@ -5386,6 +5439,7 @@ emit_marshal_custom (EmitMarshalContext *m, int argnum, MonoType *t, if (!get_instance) exception_msg = g_strdup_printf ("Custom marshaler '%s' does not implement a static GetInstance method that takes a single string parameter and returns an ICustomMarshaler.", mklass->name); +handle_exception: /* Throw exception and emit compensation code if neccesary */ if (exception_msg) { switch (action) { @@ -6010,7 +6064,27 @@ emit_marshal_string (EmitMarshalContext *m, int argnum, MonoType *t, break; } - if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT)) { + if (encoding == MONO_NATIVE_VBBYREFSTR) { + static MonoMethod *m; + + if (!m) { + m = mono_class_get_method_from_name_flags (mono_defaults.string_class, "get_Length", -1, 0); + g_assert (m); + } + + /* + * Have to allocate a new string with the same length as the original, and + * copy the contents of the buffer pointed to by CONV_ARG into it. + */ + g_assert (t->byref); + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_byte (mb, CEE_LDIND_I); + mono_mb_emit_managed_call (mb, m, NULL); + mono_mb_emit_icall (mb, mono_string_new_len_wrapper); + mono_mb_emit_byte (mb, CEE_STIND_REF); + } else if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT)) { mono_mb_emit_ldarg (mb, argnum); mono_mb_emit_ldloc (mb, conv_arg); mono_mb_emit_icall (mb, conv_to_icall (conv)); @@ -6027,7 +6101,7 @@ emit_marshal_string (EmitMarshalContext *m, int argnum, MonoType *t, break; case MARSHAL_ACTION_PUSH: - if (t->byref) + if (t->byref && encoding != MONO_NATIVE_VBBYREFSTR) mono_mb_emit_ldloc_addr (mb, conv_arg); else mono_mb_emit_ldloc (mb, conv_arg); @@ -6555,7 +6629,7 @@ emit_marshal_object (EmitMarshalContext *m, int argnum, MonoType *t, } mono_mb_emit_ldloc (mb, conv_arg); - mono_mb_emit_icall (mb, g_free); + mono_mb_emit_icall (mb, mono_marshal_free); mono_mb_patch_branch (mb, pos2); } @@ -6617,7 +6691,7 @@ emit_marshal_object (EmitMarshalContext *m, int argnum, MonoType *t, /* Free the pointer allocated by unmanaged code */ mono_mb_emit_ldloc (mb, loc); - mono_mb_emit_icall (mb, g_free); + mono_mb_emit_icall (mb, mono_marshal_free); mono_mb_patch_branch (mb, pos); } break; @@ -6924,13 +6998,12 @@ mono_pinvoke_is_unicode (MonoMethodPInvoke *piinfo) case PINVOKE_ATTRIBUTE_CHAR_SET_UNICODE: return TRUE; case PINVOKE_ATTRIBUTE_CHAR_SET_AUTO: + default: #ifdef TARGET_WIN32 return TRUE; #else return FALSE; #endif - default: - return FALSE; } } @@ -7058,7 +7131,7 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_stloc (mb, 1); /* emit valuetype conversion code */ - emit_struct_conv (mb, eklass, FALSE); + emit_struct_conv_full (mb, eklass, FALSE, eklass == mono_defaults.char_class ? encoding : -1); } mono_mb_emit_add_to_local (mb, index_var, 1); @@ -7176,7 +7249,7 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_stloc (mb, 1); /* emit valuetype conversion code */ - emit_struct_conv (mb, eklass, TRUE); + emit_struct_conv_full (mb, eklass, TRUE, eklass == mono_defaults.char_class ? encoding : -1); } if (need_free) { @@ -7816,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: @@ -8635,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) @@ -8769,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); } @@ -8948,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); @@ -8972,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; @@ -9062,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); @@ -9232,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; @@ -9247,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; @@ -9651,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; @@ -9721,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; @@ -9736,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); @@ -10073,10 +10172,18 @@ mono_marshal_get_virtual_stelemref (MonoClass *array_class) res = mono_mb_create_method (mb, signature, 4); res->flags |= METHOD_ATTRIBUTE_VIRTUAL; mono_marshal_set_wrapper_info (res, GUINT_TO_POINTER (kind + 1)); - cached_methods [kind] = res; + + mono_marshal_lock (); + if (!cached_methods [kind]) { + cached_methods [kind] = res; + mono_marshal_unlock (); + } else { + mono_marshal_unlock (); + mono_free_method (res); + } mono_mb_free (mb); - return res; + return cached_methods [kind]; } MonoMethod* @@ -10383,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; @@ -10461,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 } @@ -10471,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 } @@ -10713,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 @@ -11113,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; } @@ -11158,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))) { @@ -11262,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 ();