*
* 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);
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);
{
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;
}
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);
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) {
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);
}
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);
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_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;
MonoMethod *res;
int kind;
char *name;
-
+ const char *param_names [16];
guint32 b1, b2, b3;
int aklass, vklass, vtable, uiid;
int array_slot_addr;
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);
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 ();