return res;
}
-static MonoMethodSignature*
-signature_no_pinvoke (MonoMethod *method)
+MonoMethodSignature*
+mono_signature_no_pinvoke (MonoMethod *method)
{
MonoMethodSignature *sig = mono_method_signature (method);
if (sig->pinvoke) {
g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
!strcmp (method->name, "BeginInvoke"));
- sig = signature_no_pinvoke (method);
+ sig = mono_signature_no_pinvoke (method);
cache = get_cache (&method->klass->image->delegate_begin_invoke_cache,
(GHashFunc)mono_signature_hash,
method = mono_class_get_method_from_name (klass, "EndInvoke", -1);
g_assert (method != NULL);
- sig = signature_no_pinvoke (method);
+ sig = mono_signature_no_pinvoke (method);
msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
!strcmp (method->name, "EndInvoke"));
- sig = signature_no_pinvoke (method);
+ sig = mono_signature_no_pinvoke (method);
cache = get_cache (&method->klass->image->delegate_end_invoke_cache,
(GHashFunc)mono_signature_hash,
if ((res = mono_marshal_find_in_cache (cache, method)))
return res;
- sig = signature_no_pinvoke (method);
+ sig = mono_signature_no_pinvoke (method);
/* we cant remote methods without this pointer */
if (!sig->hasthis)
#endif
}
- sig = signature_no_pinvoke (method);
+ sig = mono_signature_no_pinvoke (method);
/* we cant remote methods without this pointer */
if (!sig->hasthis)
if ((res = mono_marshal_remoting_find_in_cache (method, MONO_WRAPPER_XDOMAIN_INVOKE)))
return res;
- sig = signature_no_pinvoke (method);
+ sig = mono_signature_no_pinvoke (method);
mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_XDOMAIN_INVOKE);
mb->method->save_lmf = 1;
if ((res = mono_marshal_remoting_find_in_cache (method, MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)))
return res;
- sig = signature_no_pinvoke (method);
+ sig = mono_signature_no_pinvoke (method);
mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK);
g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
!strcmp (method->name, "Invoke"));
- sig = signature_no_pinvoke (method);
+ sig = mono_signature_no_pinvoke (method);
if (callvirt) {
/* We need to cache the signature+method pair */
return callsig;
}
-static inline MonoType*
-get_basic_type (MonoType *t)
+static MonoType*
+get_runtime_invoke_type (MonoType *t)
{
+ if (t->byref)
+ return &mono_defaults.int_class->byval_arg;
+
switch (t->type) {
case MONO_TYPE_U1:
return &mono_defaults.sbyte_class->byval_arg;
else
return t;
default:
+ if (MONO_TYPE_IS_REFERENCE (t))
+ return &mono_defaults.object_class->byval_arg;
return t;
}
}
-static inline gboolean
-runtime_invoke_type_equal (MonoType *t1, MonoType *t2)
-{
- if (MONO_TYPE_IS_REFERENCE (t1) && MONO_TYPE_IS_REFERENCE (t2))
- return TRUE;
- else if (t1->byref != t2->byref)
- return FALSE;
- else if (t1->byref && t2->byref)
- return TRUE;
- else if (t1->type == MONO_TYPE_PTR && t2->type == MONO_TYPE_PTR)
- return TRUE;
- else {
- t1 = get_basic_type (t1);
- t2 = get_basic_type (t2);
-
- return mono_metadata_type_equal (t1, t2);
- }
-}
-
-static inline guint
-runtime_invoke_type_hash (MonoType *t1)
-{
- if (MONO_TYPE_IS_REFERENCE (t1))
- return 0;
- else if (t1->byref)
- return 1;
- else if (t1->type == MONO_TYPE_PTR)
- return 2;
- else
- return mono_metadata_type_hash (get_basic_type (t1));
-}
-
/*
- * runtime_invoke_signature_equal:
+ * mono_marshal_get_runtime_invoke_sig:
*
- * Same as mono_metadata_signature_equal, but consider reference types equal.
+ * Return a common signature used for sharing runtime invoke wrappers.
*/
-static gboolean
-runtime_invoke_signature_equal (MonoMethodSignature *sig1, MonoMethodSignature *sig2)
+static MonoMethodSignature*
+mono_marshal_get_runtime_invoke_sig (MonoMethodSignature *sig)
{
+ MonoMethodSignature *res = mono_metadata_signature_dup (sig);
int i;
- if (sig1->hasthis != sig2->hasthis || sig1->param_count != sig2->param_count)
- return FALSE;
-
- if (sig1->generic_param_count != sig2->generic_param_count)
- return FALSE;
-
- /*
- * We're just comparing the signatures of two methods here:
- *
- * If we have two generic methods `void Foo<U> (U u)' and `void Bar<V> (V v)',
- * U and V are equal here.
- *
- * That's what the `signature_only' argument of do_mono_metadata_type_equal() is for.
- */
-
- for (i = 0; i < sig1->param_count; i++) {
- MonoType *p1 = sig1->params[i];
- MonoType *p2 = sig2->params[i];
-
- /* if (p1->attrs != p2->attrs)
- return FALSE;
- */
- if (!runtime_invoke_type_equal (p1, p2))
- return FALSE;
- }
+ res->ret = get_runtime_invoke_type (sig->ret);
+ for (i = 0; i < res->param_count; ++i)
+ res->params [i] = get_runtime_invoke_type (sig->params [i]);
- /* Can't share wrappers which return a vtype since it needs to be boxed */
- if (sig1->ret == sig2->ret)
- return TRUE;
- else if (MONO_TYPE_IS_REFERENCE (sig1->ret) && MONO_TYPE_IS_REFERENCE (sig2->ret))
- return TRUE;
- else
- return FALSE;
+ return res;
}
-static guint
-runtime_invoke_signature_hash (MonoMethodSignature *sig)
+static gboolean
+runtime_invoke_signature_equal (MonoMethodSignature *sig1, MonoMethodSignature *sig2)
{
- guint i, res = sig->ret->type;
-
- for (i = 0; i < sig->param_count; i++)
- res = (res << 5) - res + runtime_invoke_type_hash (sig->params[i]);
-
- return res;
+ /* Can't share wrappers which return a vtype since it needs to be boxed */
+ if (sig1->ret != sig2->ret && !(MONO_TYPE_IS_REFERENCE (sig1->ret) && MONO_TYPE_IS_REFERENCE (sig2->ret)))
+ return FALSE;
+ else
+ return mono_metadata_signature_equal (sig1, sig2);
}
/*
if (need_direct_wrapper) {
cache = get_cache (&target_klass->image->runtime_invoke_direct_cache, mono_aligned_addr_hash, NULL);
res = mono_marshal_find_in_cache (cache, method);
+ if (res)
+ return res;
} else {
+ callsig = mono_marshal_get_runtime_invoke_sig (callsig);
+
cache = get_cache (&target_klass->image->runtime_invoke_cache,
- (GHashFunc)runtime_invoke_signature_hash,
+ (GHashFunc)mono_signature_hash,
(GCompareFunc)runtime_invoke_signature_equal);
/* from mono_marshal_find_in_cache */
mono_marshal_lock ();
res = g_hash_table_lookup (cache, callsig);
mono_marshal_unlock ();
- }
- if (res) {
- return res;
+ if (res) {
+ g_free (callsig);
+ return res;
+ }
+
+ // FIXME: When to free callsig ?
}
/* to make it work with our special string constructors */
mono_mb_emit_byte (mb, CEE_RET);
- res = mono_mb_create_method (mb, signature_no_pinvoke (stoptr), 0);
+ res = mono_mb_create_method (mb, mono_signature_no_pinvoke (stoptr), 0);
mono_mb_free (mb);
klass->marshal_info->str_to_ptr = res;
MonoMethod *
mono_marshal_get_synchronized_wrapper (MonoMethod *method)
{
- static MonoMethod *enter_method, *exit_method;
+ static MonoMethod *enter_method, *exit_method, *gettypefromhandle_method;
MonoMethodSignature *sig;
MonoExceptionClause *clause;
MonoMethodHeader *header;
enter_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
g_assert (enter_method);
mono_method_desc_free (desc);
+
desc = mono_method_desc_new ("Monitor:Exit", FALSE);
exit_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
g_assert (exit_method);
mono_method_desc_free (desc);
+
+ desc = mono_method_desc_new ("Type:GetTypeFromHandle", FALSE);
+ gettypefromhandle_method = mono_method_desc_search_in_class (desc, mono_defaults.monotype_class->parent);
+ g_assert (gettypefromhandle_method);
+ mono_method_desc_free (desc);
}
/* Push this or the type object */
if (method->flags & METHOD_ATTRIBUTE_STATIC) {
- /*
- * GetTypeFromHandle isn't called as a managed method because it has
- * a funky calling sequence, e.g. ldtoken+GetTypeFromHandle gets
- * transformed into something else by the JIT.
- */
- mono_mb_emit_ptr (mb, &method->klass->byval_arg);
- mono_mb_emit_icall (mb, type_from_handle);
+ /* We have special handling for this in the JIT */
+ int index = mono_mb_add_data (mb, method->klass);
+ mono_mb_add_data (mb, mono_defaults.typehandle_class);
+ mono_mb_emit_byte (mb, CEE_LDTOKEN);
+ mono_mb_emit_i4 (mb, index);
+
+ mono_mb_emit_managed_call (mb, gettypefromhandle_method, NULL);
}
else
mono_mb_emit_ldarg (mb, 0);