static MonoMethodSignature*
signature_dup (MonoImage *image, MonoMethodSignature *sig)
{
- return mono_metadata_signature_dup_full (image, sig);
+ MonoMethodSignature *res;
+ int sigsize;
+
+ res = mono_metadata_signature_alloc (image, sig->param_count);
+ sigsize = MONO_SIZEOF_METHOD_SIGNATURE + sig->param_count * sizeof (MonoType *);
+ memcpy (res, sig, sigsize);
+
+ return res;
}
MonoMethodSignature*
case MONO_TYPE_R4:
case MONO_TYPE_R8:
case MONO_TYPE_VALUETYPE:
+ case MONO_TYPE_PTR:
/* nothing to do */
break;
case MONO_TYPE_GENERICINST:
- case MONO_TYPE_PTR:
case MONO_TYPE_OBJECT:
case MONO_TYPE_ARRAY:
case MONO_TYPE_SZARRAY:
* Return the hash table pointed to by VAR, lazily creating it if neccesary.
*/
static GHashTable*
-get_cache_full (GHashTable **var, GHashFunc hash_func, GCompareFunc equal_func,
- GDestroyNotify key_destroy_func,
- GDestroyNotify value_destroy_func)
+get_cache (GHashTable **var, GHashFunc hash_func, GCompareFunc equal_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);
+ g_hash_table_new (hash_func, equal_func);
mono_memory_barrier ();
*var = cache;
}
return *var;
}
-static GHashTable*
-get_cache (GHashTable **var, GHashFunc hash_func, GCompareFunc equal_func)
-{
- return get_cache_full (var, hash_func, equal_func, NULL, NULL);
-}
-
GHashTable*
mono_marshal_get_cache (GHashTable **var, GHashFunc hash_func, GCompareFunc equal_func)
{
mono_marshal_method_from_wrapper (MonoMethod *wrapper)
{
gpointer res;
+ int wrapper_type = wrapper->wrapper_type;
- if (wrapper->wrapper_type == MONO_WRAPPER_NONE || wrapper->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD)
+ if (wrapper_type == MONO_WRAPPER_NONE || wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD)
return wrapper;
- res = mono_method_get_wrapper_data (wrapper, 1);
- if (res == NULL)
- return wrapper;
- return res;
+ switch (wrapper_type) {
+ case MONO_WRAPPER_REMOTING_INVOKE:
+ case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK:
+ case MONO_WRAPPER_XDOMAIN_INVOKE:
+ case MONO_WRAPPER_SYNCHRONIZED:
+ case MONO_WRAPPER_MANAGED_TO_NATIVE:
+ case MONO_WRAPPER_RUNTIME_INVOKE:
+ res = mono_method_get_wrapper_data (wrapper, 1);
+ if (res == NULL)
+ return wrapper;
+ return res;
+ default:
+ return NULL;
+ }
}
/*
MonoMethod *target_method = NULL;
MonoClass *target_class = NULL;
gboolean callvirt = FALSE;
+ gboolean closed_over_null = FALSE;
/*
* If the delegate target is null, and the target method is not static, a virtual
sig = mono_signature_no_pinvoke (method);
+ if (callvirt)
+ closed_over_null = sig->param_count == mono_method_signature (del->method)->param_count;
+
if (callvirt) {
/* We need to cache the signature+method pair */
mono_marshal_lock ();
mono_mb_patch_branch (mb, pos0);
if (callvirt) {
- mono_mb_emit_ldarg (mb, 1);
- mono_mb_emit_op (mb, CEE_CASTCLASS, target_class);
- for (i = 1; i < sig->param_count; ++i)
- mono_mb_emit_ldarg (mb, i + 1);
- mono_mb_emit_op (mb, CEE_CALLVIRT, target_method);
+ if (!closed_over_null) {
+ mono_mb_emit_ldarg (mb, 1);
+ mono_mb_emit_op (mb, CEE_CASTCLASS, target_class);
+ for (i = 1; i < sig->param_count; ++i)
+ mono_mb_emit_ldarg (mb, i + 1);
+ mono_mb_emit_op (mb, CEE_CALLVIRT, target_method);
+ } else {
+ mono_mb_emit_byte (mb, CEE_LDNULL);
+ for (i = 0; i < sig->param_count; ++i)
+ mono_mb_emit_ldarg (mb, i + 1);
+ mono_mb_emit_op (mb, CEE_CALL, target_method);
+ }
} else {
for (i = 0; i < sig->param_count; ++i)
mono_mb_emit_ldarg (mb, i + 1);
/* allocate local 1 (object) exc */
mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
- /* cond set *exc to null */
- mono_mb_emit_byte (mb, CEE_LDARG_2);
- mono_mb_emit_byte (mb, CEE_BRFALSE_S);
- mono_mb_emit_byte (mb, 3);
- mono_mb_emit_byte (mb, CEE_LDARG_2);
- mono_mb_emit_byte (mb, CEE_LDNULL);
- mono_mb_emit_byte (mb, CEE_STIND_REF);
-
emit_thread_force_interrupt_checkpoint (mb);
if (virtual) {
case MONO_TYPE_STRING:
switch (string_encoding) {
case MONO_NATIVE_LPWSTR:
- return mono_string_to_utf16 ((MonoString*)o);
+ return mono_marshal_string_to_utf16_copy ((MonoString*)o);
break;
case MONO_NATIVE_LPSTR:
return mono_string_to_lpstr ((MonoString*)o);
}
}
-/*
- * free_wrapper:
- *
- * Wrappers of generic instances need to be dynamic, since they cannot be freed when their
- * image is unloaded, since the generic instance they are based on does not belong to any
- * image. This function should be the value dtor of caches holding such wrappers.
- */
-static void
-free_wrapper (MonoMethod *method)
-{
- if (method->dynamic)
- mono_free_method (method);
-}
-
MonoMethod *
mono_marshal_get_generic_array_helper (MonoClass *class, MonoClass *iface, gchar *name, MonoMethod *method)
{
MonoMethodBuilder *mb;
MonoMethod *res;
int i;
- GHashTable *cache;
- cache = get_cache_full (&method->klass->image->generic_array_helper_cache, mono_aligned_addr_hash, NULL, NULL, (GDestroyNotify)free_wrapper);
-
- if ((res = mono_marshal_find_in_cache (cache, method)))
- return res;
-
- mb = mono_mb_new (class, name, MONO_WRAPPER_MANAGED_TO_MANAGED);
+ mb = mono_mb_new_no_dup_name (class, name, MONO_WRAPPER_MANAGED_TO_MANAGED);
mb->method->slot = -1;
- mb->dynamic = TRUE;
mb->method->flags = METHOD_ATTRIBUTE_PRIVATE | METHOD_ATTRIBUTE_VIRTUAL |
METHOD_ATTRIBUTE_NEW_SLOT | METHOD_ATTRIBUTE_HIDE_BY_SIG | METHOD_ATTRIBUTE_FINAL;
sig = mono_method_signature (method);
- csig = signature_dup (NULL, sig);
+ csig = signature_dup (method->klass->image, sig);
csig->generic_param_count = 0;
mono_mb_emit_ldarg (mb, 0);
/* We can corlib internal methods */
mb->skip_visibility = TRUE;
- res = mono_mb_create_and_cache (cache, method, mb, csig, csig->param_count + 16);
+ res = mono_mb_create_method (mb, csig, csig->param_count + 16);
mono_mb_free (mb);
g_hash_table_remove (method->klass->image->cominterop_wrapper_cache, method);
if (method->klass->image->thunk_invoke_cache)
g_hash_table_remove (method->klass->image->thunk_invoke_cache, method);
- if (method->klass->image->generic_array_helper_cache)
- g_hash_table_remove (method->klass->image->generic_array_helper_cache, method);
mono_marshal_unlock ();
}