};
#endif
+/* This mutex protects the various marshalling related caches in MonoImage */
+static CRITICAL_SECTION marshal_mutex;
+
+void
+mono_marshal_init (void)
+{
+ InitializeCriticalSection (&marshal_mutex);
+}
+
gpointer
mono_delegate_to_ftnptr (MonoDelegate *delegate)
{
void
mono_mb_emit_ldstr (MonoMethodBuilder *mb, char *str)
{
- mono_mb_emit_byte (mb, CEE_LDSTR);
+ mono_mb_emit_byte (mb, CEE_LDSTR);
mono_mb_emit_i4 (mb, mono_mb_add_data (mb, str));
}
g_assert_not_reached ();
}
- if (eclass->valuetype)
- esize = mono_class_native_size (eclass, NULL);
- else
- esize = sizeof (gpointer);
+ if (eclass->valuetype)
+ esize = mono_class_native_size (eclass, NULL);
+ else
+ esize = sizeof (gpointer);
if (!usize)
break;
return result;
}
+static inline MonoMethod*
+mono_marshal_find_in_cache (GHashTable *cache, gpointer key)
+{
+ MonoMethod *res;
+
+ EnterCriticalSection (&marshal_mutex);
+ res = g_hash_table_lookup (cache, key);
+ LeaveCriticalSection (&marshal_mutex);
+ return res;
+}
+
+/* Create the method from the builder and place it in the cache */
+static inline MonoMethod*
+mono_mb_create_and_cache (GHashTable *cache, gpointer key,
+ MonoMethodBuilder *mb, MonoMethodSignature *sig,
+ int max_stack)
+{
+ MonoMethod *res;
+
+ EnterCriticalSection (&marshal_mutex);
+ res = g_hash_table_lookup (cache, key);
+ if (!res) {
+ /* This does not acquire any locks */
+ res = mono_mb_create_method (mb, sig, max_stack);
+ g_hash_table_insert (cache, key, res);
+ }
+ else
+ /* Somebody created it before us */
+ ;
+ LeaveCriticalSection (&marshal_mutex);
+
+ return res;
+}
+
MonoMethod *
mono_marshal_get_delegate_begin_invoke (MonoMethod *method)
{
sig = method->signature;
cache = method->klass->image->delegate_begin_invoke_cache;
- if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
+ if ((res = mono_marshal_find_in_cache (cache, sig)))
return res;
g_assert (sig->hasthis);
mono_mb_emit_native_call (mb, csig, mono_delegate_begin_invoke);
mono_mb_emit_byte (mb, CEE_RET);
- res = mono_mb_create_method (mb, sig, sig->param_count + 16);
+ res = mono_mb_create_and_cache (cache, sig, mb, sig, sig->param_count + 16);
mono_mb_free (mb);
- g_hash_table_insert (cache, sig, res);
return res;
}
sig = method->signature;
cache = method->klass->image->delegate_end_invoke_cache;
- if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
+ if ((res = mono_marshal_find_in_cache (cache, sig)))
return res;
g_assert (sig->hasthis);
} else
mono_mb_emit_restore_result (mb, sig->ret);
- res = mono_mb_create_method (mb, sig, sig->param_count + 16);
+ res = mono_mb_create_and_cache (cache, sig,
+ mb, sig, sig->param_count + 16);
mono_mb_free (mb);
- g_hash_table_insert (cache, sig, res);
return res;
}
return method;
cache = method->klass->image->remoting_invoke_cache;
- if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
+ if ((res = mono_marshal_find_in_cache (cache, method)))
return res;
if (!csig) {
mono_mb_emit_restore_result (mb, sig->ret);
}
- res = mono_mb_create_method (mb, sig, sig->param_count + 16);
+ res = mono_mb_create_and_cache (cache, method, mb, sig, sig->param_count + 16);
mono_mb_free (mb);
- g_hash_table_insert (cache, method, res);
+
return res;
}
g_assert (sig->hasthis);
cache = method->klass->image->remoting_invoke_cache;
- if ((res = (MonoMethod *)g_hash_table_lookup (cache, (char *)method + 1)))
+ if ((res = mono_marshal_find_in_cache (cache, (char *)method + 1)))
return res;
mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK);
mono_mb_emit_managed_call (mb, method, method->signature);
mono_mb_emit_byte (mb, CEE_RET);
- res = mono_mb_create_method (mb, sig, sig->param_count + 16);
+ res = mono_mb_create_and_cache (cache, (char*)method + 1,
+ mb, sig, sig->param_count + 16);
mono_mb_free (mb);
- g_hash_table_insert (cache, (char *)method + 1, res);
+
return res;
}
sig = method->signature;
cache = method->klass->image->delegate_invoke_cache;
- if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
+ if ((res = mono_marshal_find_in_cache (cache, sig)))
return res;
sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
mono_mb_emit_byte (mb, CEE_RET);
- res = mono_mb_create_method (mb, sig, sig->param_count + 16);
+ res = mono_mb_create_and_cache (cache, sig,
+ mb, sig, sig->param_count + 16);
mono_mb_free (mb);
- g_hash_table_insert (cache, sig, res);
-
return res;
}
g_assert (method);
cache = method->klass->image->runtime_invoke_cache;
- if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
+ if ((res = mono_marshal_find_in_cache (cache, method)))
return res;
/* to make it work with our special string constructors */
mono_mb_emit_ldloc (mb, 0);
mono_mb_emit_byte (mb, CEE_RET);
- res = mono_mb_create_method (mb, csig, sig->param_count + 16);
+ res = mono_mb_create_and_cache (cache, method,
+ mb, csig, sig->param_count + 16);
mono_mb_free (mb);
header = ((MonoMethodNormal *)res)->header;
header->num_clauses = 1;
header->clauses = clause;
- g_hash_table_insert (cache, method, res);
-
return res;
}
g_assert (!method->signature->pinvoke);
cache = method->klass->image->managed_wrapper_cache;
- if (!this && (res = (MonoMethod *)g_hash_table_lookup (cache, method)))
+ if (!this && (res = mono_marshal_find_in_cache (cache, method)))
return res;
if (this) {
mono_mb_emit_byte (mb, CEE_RET);
}
- res = mono_mb_create_method (mb, csig, sig->param_count + 16);
- mono_mb_free (mb);
-
if (!this)
- g_hash_table_insert (cache, method, res);
+ res = mono_mb_create_and_cache (cache, method,
+ mb, csig, sig->param_count + 16);
+ else
+ res = mono_mb_create_method (mb, csig, sig->param_count + 16);
+ mono_mb_free (mb);
return res;
}
char *name;
int t, pos0, pos1;
- if (!ldfld_hash)
- ldfld_hash = g_hash_table_new (NULL, NULL);
-
-
t = type->type;
if (!type->byref) {
klass = mono_defaults.int_class;
}
- if ((res = g_hash_table_lookup (ldfld_hash, klass)))
+ EnterCriticalSection (&marshal_mutex);
+ if (!ldfld_hash)
+ ldfld_hash = g_hash_table_new (NULL, NULL);
+ res = g_hash_table_lookup (ldfld_hash, klass);
+ LeaveCriticalSection (&marshal_mutex);
+ if (res)
return res;
name = g_strdup_printf ("__ldfld_wrapper_%s.%s", klass->name_space, klass->name);
mono_mb_emit_byte (mb, CEE_RET);
- res = mono_mb_create_method (mb, sig, sig->param_count + 16);
+ res = mono_mb_create_and_cache (ldfld_hash, klass,
+ mb, sig, sig->param_count + 16);
mono_mb_free (mb);
- g_hash_table_insert (ldfld_hash, klass, res);
-
return res;
}
char *name;
int t, pos;
- if (!stfld_hash)
- stfld_hash = g_hash_table_new (NULL, NULL);
-
t = type->type;
if (!type->byref) {
klass = mono_defaults.int_class;
}
- if ((res = g_hash_table_lookup (stfld_hash, klass)))
+ EnterCriticalSection (&marshal_mutex);
+ if (!stfld_hash)
+ stfld_hash = g_hash_table_new (NULL, NULL);
+ res = g_hash_table_lookup (stfld_hash, klass);
+ LeaveCriticalSection (&marshal_mutex);
+ if (res)
return res;
name = g_strdup_printf ("__stfld_wrapper_%s.%s", klass->name_space, klass->name);
mono_mb_emit_byte (mb, CEE_RET);
- res = mono_mb_create_method (mb, sig, sig->param_count + 16);
+ res = mono_mb_create_and_cache (stfld_hash, klass,
+ mb, sig, sig->param_count + 16);
mono_mb_free (mb);
- g_hash_table_insert (stfld_hash, klass, res);
-
return res;
}
/*
* generates IL code for the pinvoke wrapper (the generated method
- * calls the unamnage code in method->addr)
+ * calls the unmanaged code in method->addr)
*/
MonoMethod *
mono_marshal_get_native_wrapper (MonoMethod *method)
g_assert (method->signature->pinvoke);
cache = method->klass->image->native_wrapper_cache;
- if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
+ if ((res = mono_marshal_find_in_cache (cache, method)))
return res;
sig = method->signature;
mono_mb_emit_exception (mb);
csig = g_memdup (sig, sigsize);
csig->pinvoke = 0;
- res = mono_mb_create_method (mb, csig, csig->param_count + 16);
+ res = mono_mb_create_and_cache (cache, method,
+ mb, csig, csig->param_count + 16);
mono_mb_free (mb);
- g_hash_table_insert (cache, method, res);
return res;
}
csig = g_memdup (csig, sigsize);
csig->pinvoke = 0;
- res = mono_mb_create_method (mb, csig, csig->param_count + 16);
+ res = mono_mb_create_and_cache (cache, method,
+ mb, csig, csig->param_count + 16);
mono_mb_free (mb);
- g_hash_table_insert (cache, method, res);
return res;
}
csig = g_memdup (sig, sigsize);
csig->pinvoke = 0;
- res = mono_mb_create_method (mb, csig, csig->param_count + 16);
+ res = mono_mb_create_and_cache (cache, method,
+ mb, csig, csig->param_count + 16);
mono_mb_free (mb);
- g_hash_table_insert (cache, method, res);
-
for (i = sig->param_count; i >= 0; i--)
g_free (mspecs [i]);
g_free (mspecs);
return method;
cache = method->klass->image->synchronized_cache;
- if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
+ if ((res = mono_marshal_find_in_cache (cache, method)))
return res;
sig = method->signature;
mono_mb_emit_ldloc (mb, ret_local);
mono_mb_emit_byte (mb, CEE_RET);
- res = mono_mb_create_method (mb, sig, sig->param_count + 16);
+ res = mono_mb_create_and_cache (cache, method,
+ mb, sig, sig->param_count + 16);
mono_mb_free (mb);
header = ((MonoMethodNormal *)res)->header;
header->num_clauses = 1;
header->clauses = clause;
- g_hash_table_insert (cache, method, res);
-
return res;
}
info->fields [j].field = &klass->fields [i];
+ if ((klass->field.count == 1) && (klass->instance_size == sizeof (MonoObject)) &&
+ (strcmp (klass->fields [i].name, "$PRIVATE$") == 0)) {
+ /* This field is a hack inserted by MCS to empty structures */
+ continue;
+ }
+
switch (layout) {
case TYPE_ATTRIBUTE_AUTO_LAYOUT:
case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT: