*
* 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)
*
*/
#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>
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);
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);
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);
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);
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);
{
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;
}
*((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)
{
return mono_mb_emit_branch (mb, branch_code);
}
+/*
+ * mono_mb_emit_exception_marshal_directive:
+ *
+ * This function assumes ownership of MSG, which should be malloc-ed.
+ */
static void
-mono_mb_emit_exception_marshal_directive (MonoMethodBuilder *mb, const char *msg)
+mono_mb_emit_exception_marshal_directive (MonoMethodBuilder *mb, char *msg)
{
- mono_mb_emit_exception_full (mb, "System.Runtime.InteropServices", "MarshalDirectiveException", msg);
+ char *s;
+
+ if (!mb->dynamic) {
+ s = mono_image_strdup (mb->method->klass->image, msg);
+ g_free (msg);
+ } else {
+ s = g_strdup (msg);
+ }
+ mono_mb_emit_exception_full (mb, "System.Runtime.InteropServices", "MarshalDirectiveException", s);
}
guint
char *msg = g_strdup_printf ("marshaling conversion %d not implemented", conv);
mono_mb_emit_exception_marshal_directive (mb, msg);
- g_free (msg);
break;
}
}
return mono_marshal_string_to_utf16;
case MONO_MARSHAL_CONV_LPWSTR_STR:
return mono_string_from_utf16;
+ 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:
}
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;
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;
}
}
+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)
{
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;
*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;
return *var;
}
+static GHashTable*
+get_cache_full (GHashTable **var, GHashFunc hash_func, GCompareFunc equal_func, GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
+{
+ if (!(*var)) {
+ mono_marshal_lock ();
+ if (!(*var)) {
+ GHashTable *cache =
+ g_hash_table_new_full (hash_func, equal_func, key_destroy_func, value_destroy_func);
+ mono_memory_barrier ();
+ *var = cache;
+ }
+ mono_marshal_unlock ();
+ }
+ return *var;
+}
+
GHashTable*
mono_marshal_get_cache (GHashTable **var, GHashFunc hash_func, GCompareFunc equal_func)
{
{
MonoMethod **res = NULL;
MonoRemotingMethods *wrps;
- GHashTable *cache = get_cache (&key->klass->image->remoting_invoke_cache, mono_aligned_addr_hash, NULL);
+ GHashTable *cache = get_cache_full (&key->klass->image->remoting_invoke_cache, mono_aligned_addr_hash, NULL, NULL, g_free);
mono_marshal_lock ();
wrps = g_hash_table_lookup (cache, key);
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 ();
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;
}
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);
csig->params [1] = &mono_defaults.int_class->byval_arg;
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) {
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;
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);
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) {
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));
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);
if (t->data.klass->flags & TYPE_ATTRIBUTE_ABSTRACT){
mono_mb_emit_byte (mb, CEE_POP);
- mono_mb_emit_exception_marshal_directive (mb, "Returned SafeHandles should not be abstract");
+ mono_mb_emit_exception_marshal_directive (mb, g_strdup ("Returned SafeHandles should not be abstract"));
break;
}
*conv_arg_type = intptr_type;
if (t->byref){
- mono_mb_emit_exception_marshal_directive (mb,
- "HandleRefs can not be returned from unmanaged code (or passed by ref)");
+ char *msg = g_strdup ("HandleRefs can not be returned from unmanaged code (or passed by ref)");
+ mono_mb_emit_exception_marshal_directive (mb, msg);
break;
}
mono_mb_emit_ldarg_addr (mb, argnum);
}
case MARSHAL_ACTION_CONV_RESULT: {
- mono_mb_emit_exception_marshal_directive (mb,
- "HandleRefs can not be returned from unmanaged code (or passed by ref)");
+ char *msg = g_strdup ("HandleRefs can not be returned from unmanaged code (or passed by ref)");
+ mono_mb_emit_exception_marshal_directive (mb, msg);
break;
}
}
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);
}
/* 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;
return conv_arg;
}
+static gboolean
+mono_pinvoke_is_unicode (MonoMethodPInvoke *piinfo)
+{
+ switch (piinfo->piflags & PINVOKE_ATTRIBUTE_CHAR_SET_MASK) {
+ case PINVOKE_ATTRIBUTE_CHAR_SET_ANSI:
+ return FALSE;
+ case PINVOKE_ATTRIBUTE_CHAR_SET_UNICODE:
+ return TRUE;
+ case PINVOKE_ATTRIBUTE_CHAR_SET_AUTO:
+ default:
+#ifdef TARGET_WIN32
+ return TRUE;
+#else
+ return FALSE;
+#endif
+ }
+}
+
static int
emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t,
MonoMarshalSpec *spec,
if (is_string)
esize = sizeof (gpointer);
+ else if (eklass == mono_defaults.char_class) /*can't call mono_marshal_type_size since it causes all sorts of asserts*/
+ esize = mono_pinvoke_is_unicode (m->piinfo) ? 2 : 1;
else
esize = mono_class_native_size (eklass, NULL);
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);
eklass = klass->element_class;
if ((eklass == mono_defaults.stringbuilder_class) || (eklass == mono_defaults.string_class))
esize = sizeof (gpointer);
+ else if (eklass == mono_defaults.char_class)
+ esize = mono_pinvoke_is_unicode (m->piinfo) ? 2 : 1;
else
esize = mono_class_native_size (eklass, NULL);
src_ptr = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
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) {
if (is_string)
esize = sizeof (gpointer);
+ else if (eklass == mono_defaults.char_class)
+ esize = mono_pinvoke_is_unicode (m->piinfo) ? 2 : 1;
else
esize = mono_class_native_size (eklass, NULL);
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:
/*
* 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)
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);
}
}
/*
- * This does the equivalent of mono_object_variant_castclass.
+ * This does the equivalent of mono_object_castclass_with_cache.
*/
MonoMethod *
mono_marshal_get_castclass_with_cache (void)
mono_mb_emit_stloc (mb, 0);
/* *cache */
- mono_mb_emit_ldarg (mb, 1);
+ mono_mb_emit_ldarg (mb, 2);
mono_mb_emit_byte (mb, CEE_LDIND_I);
mono_mb_emit_ldloc (mb, 0);
invalid_cast_pos = mono_mb_emit_branch (mb, CEE_BRFALSE);
/**cache = obj_vtable;*/
- mono_mb_emit_ldarg (mb, 1);
+ mono_mb_emit_ldarg (mb, 2);
mono_mb_emit_ldloc (mb, 0);
mono_mb_emit_byte (mb, CEE_STIND_I);
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);
}
/*
- * This does the equivalent of mono_object_variant_isinst.
+ * This does the equivalent of mono_object_isinst_with_cache.
*/
MonoMethod *
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;
mono_mb_emit_stloc (mb, 0);
/* cached_vtable = *cache*/
- mono_mb_emit_ldarg (mb, 1);
+ mono_mb_emit_ldarg (mb, 2);
mono_mb_emit_byte (mb, CEE_LDIND_I);
mono_mb_emit_stloc (mb, 1);
not_an_instance_pos = mono_mb_emit_branch (mb, CEE_BRFALSE);
/**cache = obj_vtable;*/
- mono_mb_emit_ldarg (mb, 1);
+ mono_mb_emit_ldarg (mb, 2);
mono_mb_emit_ldloc (mb, 0);
mono_mb_emit_byte (mb, CEE_STIND_I);
/*not an instance*/
mono_mb_patch_branch (mb, not_an_instance_pos);
/* *cache = (gpointer)(obj_vtable | 0x1);*/
- mono_mb_emit_ldarg (mb, 1);
+ mono_mb_emit_ldarg (mb, 2);
/*obj_vtable | 0x1*/
- mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_ldloc (mb, 0);
mono_mb_emit_byte(mb, CEE_LDC_I4_1);
mono_mb_emit_byte (mb, CEE_CONV_U);
mono_mb_emit_byte (mb, CEE_OR);
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);
GHashTable *cache;
MonoMethod *res;
int pos_failed, pos_end;
- char *name;
+ char *name, *klass_name;
MonoMethod *can_cast_to;
MonoMethodDesc *desc;
MonoMethodBuilder *mb;
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;
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;
MonoMethodBuilder *mb;
MonoMethod *res;
int kind;
-
+ char *name;
+ const char *param_names [16];
guint32 b1, b2, b3;
int aklass, vklass, vtable, uiid;
int array_slot_addr;
if (cached_methods [kind])
return cached_methods [kind];
- mb = mono_mb_new_no_dup_name (mono_defaults.object_class, g_strdup_printf ("virt_stelemref_%s", strelemref_wrapper_name [kind]), MONO_WRAPPER_STELEMREF);
+ name = g_strdup_printf ("virt_stelemref_%s", strelemref_wrapper_name [kind]);
+ 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);
mono_mb_emit_ldloc (mb, uiid);
mono_mb_emit_ldloc (mb, vtable);
mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoVTable, max_interface_id));
- mono_mb_emit_byte (mb, CEE_LDIND_I);
+ mono_mb_emit_byte (mb, CEE_LDIND_U2);
b2 = mono_mb_emit_branch (mb, CEE_BGT_UN);
/* if (!(vt->interface_bitmap [(uiid) >> 3] & (1 << ((uiid)&7)))) */
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*
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;
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
}
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
}
{
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
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;
}
* 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))) {
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 ();