static void
delegate_hash_table_remove (MonoDelegate *d)
{
-#ifdef HAVE_MOVING_COLLECTOR
- guint32 gchandle;
-#endif
+ guint32 gchandle = 0;
+
mono_marshal_lock ();
if (delegate_hash_table == NULL)
delegate_hash_table = delegate_hash_table_new ();
-#ifdef HAVE_MOVING_COLLECTOR
- gchandle = GPOINTER_TO_UINT (g_hash_table_lookup (delegate_hash_table, d->delegate_trampoline));
-#endif
+ if (mono_gc_is_moving ())
+ gchandle = GPOINTER_TO_UINT (g_hash_table_lookup (delegate_hash_table, d->delegate_trampoline));
g_hash_table_remove (delegate_hash_table, d->delegate_trampoline);
mono_marshal_unlock ();
-#ifdef HAVE_MOVING_COLLECTOR
- mono_gchandle_free (gchandle);
-#endif
+ if (mono_gc_is_moving ())
+ mono_gchandle_free (gchandle);
}
static void
delegate_hash_table_add (MonoDelegate *d)
{
-#ifdef HAVE_MOVING_COLLECTOR
- guint32 gchandle = mono_gchandle_new_weakref ((MonoObject*)d, FALSE);
+ guint32 gchandle;
guint32 old_gchandle;
-#endif
+
mono_marshal_lock ();
if (delegate_hash_table == NULL)
delegate_hash_table = delegate_hash_table_new ();
-#ifdef HAVE_MOVING_COLLECTOR
- old_gchandle = GPOINTER_TO_UINT (g_hash_table_lookup (delegate_hash_table, d->delegate_trampoline));
- g_hash_table_insert (delegate_hash_table, d->delegate_trampoline, GUINT_TO_POINTER (gchandle));
- if (old_gchandle)
- mono_gchandle_free (old_gchandle);
-#else
- g_hash_table_insert (delegate_hash_table, d->delegate_trampoline, d);
-#endif
+ if (mono_gc_is_moving ()) {
+ gchandle = mono_gchandle_new_weakref ((MonoObject*)d, FALSE);
+ old_gchandle = GPOINTER_TO_UINT (g_hash_table_lookup (delegate_hash_table, d->delegate_trampoline));
+ g_hash_table_insert (delegate_hash_table, d->delegate_trampoline, GUINT_TO_POINTER (gchandle));
+ if (old_gchandle)
+ mono_gchandle_free (old_gchandle);
+ } else {
+ g_hash_table_insert (delegate_hash_table, d->delegate_trampoline, d);
+ }
mono_marshal_unlock ();
}
* construct it.
*/
cinfo = mono_custom_attrs_from_class (klass);
- if (cinfo) {
+ if (cinfo && !mono_runtime_get_no_exec ()) {
attr = (MonoReflectionUnmanagedFunctionPointerAttribute*)mono_custom_attrs_get_attr (cinfo, UnmanagedFunctionPointerAttribute);
if (attr) {
piinfo->piflags = (attr->call_conv << 8) | (attr->charset ? (attr->charset - 1) * 2 : 1) | attr->set_last_error;
MonoDelegate*
mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn)
{
-#ifdef HAVE_MOVING_COLLECTOR
guint32 gchandle;
-#endif
MonoDelegate *d;
if (ftn == NULL)
if (delegate_hash_table == NULL)
delegate_hash_table = delegate_hash_table_new ();
-#ifdef HAVE_MOVING_COLLECTOR
- gchandle = GPOINTER_TO_UINT (g_hash_table_lookup (delegate_hash_table, ftn));
- mono_marshal_unlock ();
- if (gchandle)
- d = (MonoDelegate*)mono_gchandle_get_target (gchandle);
- else
- d = NULL;
-#else
- d = g_hash_table_lookup (delegate_hash_table, ftn);
- mono_marshal_unlock ();
-#endif
+ if (mono_gc_is_moving ()) {
+ gchandle = GPOINTER_TO_UINT (g_hash_table_lookup (delegate_hash_table, ftn));
+ mono_marshal_unlock ();
+ if (gchandle)
+ d = (MonoDelegate*)mono_gchandle_get_target (gchandle);
+ else
+ d = NULL;
+ } else {
+ d = g_hash_table_lookup (delegate_hash_table, ftn);
+ mono_marshal_unlock ();
+ }
if (d == NULL) {
/* This is a native function, so construct a delegate for it */
MonoMethodSignature *sig;
items_written = mono_stringbuilder_capacity (sb);
if (!error) {
- if (! sb->str || sb->str == sb->cached_str) {
+ if (! sb->str || sb->str == sb->cached_str)
MONO_OBJECT_SETREF (sb, str, mono_string_new_size (mono_domain_get (), items_written));
- sb->cached_str = NULL;
- }
memcpy (mono_string_chars (sb->str), ut, items_written * 2);
sb->length = items_written;
+ sb->cached_str = NULL;
} else
g_error_free (error);
break;
}
case MONO_TYPE_OBJECT: {
+#ifndef DISABLE_COM
mono_init_com_types ();
if (to_object) {
static MonoMethod *variant_clear = NULL;
mono_mb_emit_byte(mb, CEE_LDIND_REF);
mono_mb_emit_ldloc (mb, 1);
mono_mb_emit_managed_call (mb, get_native_variant_for_object, NULL);
- }
+ }
+#else
+ char *msg = g_strdup_printf ("COM support was disabled at compilation time.");
+ mono_mb_emit_exception_marshal_directive (mb, msg);
+#endif
break;
}
case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK:
case MONO_WRAPPER_XDOMAIN_INVOKE:
case MONO_WRAPPER_SYNCHRONIZED:
+ case MONO_WRAPPER_UNBOX:
res = mono_marshal_get_wrapper_info (wrapper);
if (res == NULL)
return wrapper;
return method;
/* this seems to be the best plase to put this, as all remoting invokes seem to get filtered through here */
+#ifndef DISABLE_COM
if (method->klass->is_com_object || method->klass == mono_defaults.com_object_class) {
MonoVTable *vtable = mono_class_vtable (mono_domain_get (), method->klass);
g_assert (vtable); /*FIXME do proper error handling*/
if (!vtable->remote) {
-#ifndef DISABLE_COM
return mono_cominterop_get_invoke (method);
-#else
- g_assert_not_reached ();
-#endif
}
}
+#endif
sig = mono_signature_no_pinvoke (method);
gboolean callvirt = FALSE;
gboolean closed_over_null = FALSE;
gboolean static_method_with_first_arg_bound = FALSE;
+ MonoGenericContext *ctx = NULL;
+ MonoGenericContainer *container = NULL;
+ MonoMethod *orig_method = NULL;
/*
* If the delegate target is null, and the target method is not static, a virtual
static_method_with_first_arg_bound = TRUE;
}
- if (callvirt || static_method_with_first_arg_bound) {
+ /*
+ * For generic delegates, create a generic wrapper, and returns an instance to help AOT.
+ */
+ if (method->is_inflated && !callvirt && !static_method_with_first_arg_bound) {
+ orig_method = method;
+ ctx = &((MonoMethodInflated*)method)->context;
+ method = ((MonoMethodInflated*)method)->declaring;
+
+ container = mono_method_get_generic_container (method);
+ if (!container)
+ container = method->klass->generic_container;
+ g_assert (container);
+
+ invoke_sig = sig = mono_signature_no_pinvoke (method);
+ }
+
+ /*
+ * Check cache
+ */
+ if (ctx) {
+ MonoMethod *def, *inst;
+
+ /*
+ * Look for the instance
+ */
+ cache = get_cache (&method->klass->image->delegate_invoke_generic_cache, mono_aligned_addr_hash, NULL);
+ res = mono_marshal_find_in_cache (cache, orig_method->klass);
+ if (res)
+ return res;
+
+ /*
+ * Look for the definition
+ */
+ def = mono_marshal_find_in_cache (cache, method->klass);
+ if (def) {
+ inst = mono_class_inflate_generic_method (def, ctx);
+ /* Cache it */
+ mono_memory_barrier ();
+ mono_marshal_lock ();
+ res = g_hash_table_lookup (cache, orig_method->klass);
+ if (!res) {
+ g_hash_table_insert (cache, orig_method->klass, inst);
+ res = inst;
+ }
+ mono_marshal_unlock ();
+ return res;
+ }
+ } else if (callvirt || static_method_with_first_arg_bound) {
GHashTable **cache_ptr;
if (static_method_with_first_arg_bound)
cache_ptr = &method->klass->image->delegate_bound_static_invoke_cache;
cache = get_cache (&method->klass->image->delegate_invoke_cache,
(GHashFunc)mono_signature_hash,
(GCompareFunc)mono_metadata_signature_equal);
- if ((res = mono_marshal_find_in_cache (cache, sig)))
+ res = mono_marshal_find_in_cache (cache, sig);
+ if (res)
return res;
}
invoke_sig = static_sig;
name = mono_signature_to_name (sig, "invoke");
- mb = mono_mb_new (get_wrapper_target_class (method->klass->image), name, MONO_WRAPPER_DELEGATE_INVOKE);
+ if (ctx)
+ mb = mono_mb_new (method->klass, name, MONO_WRAPPER_DELEGATE_INVOKE);
+ else
+ mb = mono_mb_new (get_wrapper_target_class (method->klass->image), name, MONO_WRAPPER_DELEGATE_INVOKE);
g_free (name);
/* allocate local 0 (object) */
mono_mb_emit_ldloc (mb, local_prev);
for (i = 0; i < sig->param_count; i++)
mono_mb_emit_ldarg (mb, i + 1);
- mono_mb_emit_op (mb, CEE_CALLVIRT, method);
+ if (ctx)
+ mono_mb_emit_op (mb, CEE_CALLVIRT, mono_class_inflate_generic_method (method, &container->context));
+ else
+ mono_mb_emit_op (mb, CEE_CALLVIRT, method);
if (sig->ret->type != MONO_TYPE_VOID)
mono_mb_emit_byte (mb, CEE_POP);
mono_mb_emit_byte (mb, CEE_RET);
- if (static_method_with_first_arg_bound || callvirt) {
+ mb->skip_visibility = 1;
+
+ if (ctx) {
+ MonoMethod *def, *inst;
+
+ /*
+ * We use the same cache for the generic definition and the instances.
+ */
+ def = mono_mb_create_and_cache (cache, method->klass, mb, sig, sig->param_count + 16);
+
+ inst = mono_class_inflate_generic_method (def, ctx);
+ mono_memory_barrier ();
+ mono_marshal_lock ();
+ res = g_hash_table_lookup (cache, orig_method->klass);
+ if (!res) {
+ g_hash_table_insert (cache, orig_method->klass, inst);
+ res = inst;
+ }
+ mono_marshal_unlock ();
+ } else if (static_method_with_first_arg_bound || callvirt) {
// From mono_mb_create_and_cache
- mb->skip_visibility = 1;
newm = mono_mb_create_method (mb, sig, sig->param_count + 16);
/*We perform double checked locking, so must fence before publishing*/
mono_memory_barrier ();
mono_free_method (newm);
}
} else {
- mb->skip_visibility = 1;
res = mono_mb_create_and_cache (cache, sig, mb, sig, sig->param_count + 16);
}
mono_mb_free (mb);
if (sig->hasthis) {
if (method->string_ctor) {
- mono_mb_emit_ptr (mb, string_dummy);
+ if (mono_gc_is_moving ()) {
+ mono_mb_emit_ptr (mb, &string_dummy);
+ mono_mb_emit_byte (mb, CEE_LDIND_REF);
+ } else {
+ mono_mb_emit_ptr (mb, string_dummy);
+ }
} else {
mono_mb_emit_ldarg (mb, 0);
}
return conv_arg;
}
+
+#ifndef DISABLE_COM
+
static int
emit_marshal_variant (EmitMarshalContext *m, int argnum, MonoType *t,
MonoMarshalSpec *spec,
return conv_arg;
}
+#endif /* DISABLE_COM */
+
static gboolean
mono_pinvoke_is_unicode (MonoMethodPInvoke *piinfo)
{
/* Ensure that we have marshalling info for this param */
mono_marshal_load_type_info (mono_class_from_mono_type (t));
-#ifdef DISABLE_JIT
- /* Not JIT support, no need to generate correct IL */
- return conv_arg;
-#else
if (spec && spec->native == MONO_NATIVE_CUSTOM)
return emit_marshal_custom (m, argnum, t, spec, conv_arg, conv_arg_type, action);
return emit_marshal_string (m, argnum, t, spec, conv_arg, conv_arg_type, action);
case MONO_TYPE_CLASS:
case MONO_TYPE_OBJECT:
+#ifndef DISABLE_COM
if (spec && spec->native == MONO_NATIVE_STRUCT)
return emit_marshal_variant (m, argnum, t, spec, conv_arg, conv_arg_type, action);
-#ifndef DISABLE_COM
if (spec && (spec->native == MONO_NATIVE_IUNKNOWN ||
spec->native == MONO_NATIVE_IDISPATCH ||
spec->native == MONO_NATIVE_INTERFACE))
else
return emit_marshal_object (m, argnum, t, spec, conv_arg, conv_arg_type, action);
}
-#endif
return conv_arg;
}
return ret;
}
+/*
+ * mono_marshal_get_gsharedvt_in_wrapper:
+ *
+ * This wrapper handles calls from normal code to gsharedvt code.
+ *
+ * The wrapper info for the wrapper is a WrapperInfo structure.
+ */
+MonoMethod*
+mono_marshal_get_gsharedvt_in_wrapper (void)
+{
+ static MonoMethod* ret = NULL;
+ MonoMethodSignature *sig;
+ MonoMethodBuilder *mb;
+ WrapperInfo *info;
+
+ if (ret)
+ return ret;
+
+ mb = mono_mb_new (mono_defaults.object_class, "gsharedvt_in", MONO_WRAPPER_UNKNOWN);
+
+ sig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
+ sig->ret = &mono_defaults.void_class->byval_arg;
+
+ /*
+ * The body is generated by the JIT, we use a wrapper instead of a trampoline so EH works.
+ */
+ mono_mb_emit_byte (mb, CEE_RET);
+
+ ret = mono_mb_create_method (mb, sig, 4);
+ mono_mb_free (mb);
+
+ info = mono_wrapper_info_create (ret, WRAPPER_SUBTYPE_GSHAREDVT_IN);
+ mono_marshal_set_wrapper_info (ret, info);
+
+ return ret;
+}
+
+/*
+ * mono_marshal_get_gsharedvt_out_wrapper:
+ *
+ * This wrapper handles calls from gsharedvt code to normal code.
+ *
+ * The wrapper info for the wrapper is a WrapperInfo structure.
+ */
+MonoMethod*
+mono_marshal_get_gsharedvt_out_wrapper (void)
+{
+ static MonoMethod* ret = NULL;
+ MonoMethodSignature *sig;
+ MonoMethodBuilder *mb;
+ WrapperInfo *info;
+
+ if (ret)
+ return ret;
+
+ mb = mono_mb_new (mono_defaults.object_class, "gsharedvt_out", MONO_WRAPPER_UNKNOWN);
+
+ sig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
+ sig->ret = &mono_defaults.void_class->byval_arg;
+
+ /*
+ * The body is generated by the JIT, we use a wrapper instead of a trampoline so EH works.
+ */
+ mono_mb_emit_byte (mb, CEE_RET);
+
+ ret = mono_mb_create_method (mb, sig, 4);
+ mono_mb_free (mb);
+
+ info = mono_wrapper_info_create (ret, WRAPPER_SUBTYPE_GSHAREDVT_OUT);
+ mono_marshal_set_wrapper_info (ret, info);
+
+ return ret;
+}
+
typedef struct {
int rank;
int elem_size;
mono_marshal_unlock ();
}
-/*
- * mono_marshal_free_inflated_wrappers:
- *
- * Free wrappers of the inflated method METHOD.
- */
-
static gboolean
signature_method_pair_matches_signature (gpointer key, gpointer value, gpointer user_data)
{
return mono_metadata_signature_equal (pair->sig, sig);
}
+/*
+ * mono_marshal_free_inflated_wrappers:
+ *
+ * Free wrappers of the inflated method METHOD.
+ */
void
mono_marshal_free_inflated_wrappers (MonoMethod *method)
{