*
* Copyright 2007-2011 Novell, Inc (http://www.novell.com)
* Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#include <config.h>
static int num_oti_allocted;
static int num_oti_bytes;
+#define gshared_lock() mono_os_mutex_lock (&gshared_mutex)
+#define gshared_unlock() mono_os_mutex_unlock (&gshared_mutex)
+static mono_mutex_t gshared_mutex;
+
static gboolean partial_supported = FALSE;
static inline gboolean
if (!m) {
mono_class_setup_methods (klass);
- if (klass->exception_type)
+ if (mono_class_has_failure (klass))
return NULL;
for (i = 0; i < klass->method.count; ++i) {
m = klass->methods [i];
case MONO_RGCTX_INFO_METHOD_DELEGATE_CODE: {
MonoMethod *method = (MonoMethod *)data;
MonoMethod *inflated_method;
- MonoType *inflated_type = mono_class_inflate_generic_type (&method->klass->byval_arg, context);
+ MonoType *inflated_type = mono_class_inflate_generic_type_checked (&method->klass->byval_arg, context, &error);
+ mono_error_assert_ok (&error); /* FIXME don't swallow the error */
+
MonoClass *inflated_class = mono_class_from_mono_type (inflated_type);
mono_metadata_free_type (inflated_type);
MonoJumpInfoGSharedVtCall *info = (MonoJumpInfoGSharedVtCall *)data;
MonoMethod *method = info->method;
MonoMethod *inflated_method;
- MonoType *inflated_type = mono_class_inflate_generic_type (&method->klass->byval_arg, context);
+ MonoType *inflated_type = mono_class_inflate_generic_type_checked (&method->klass->byval_arg, context, &error);
+ mono_error_assert_ok (&error); /* FIXME don't swallow the error */
+
MonoClass *inflated_class = mono_class_from_mono_type (inflated_type);
MonoJumpInfoGSharedVtCall *res;
MonoDomain *domain = mono_domain_get ();
case MONO_RGCTX_INFO_CLASS_FIELD:
case MONO_RGCTX_INFO_FIELD_OFFSET: {
+ MonoError error;
MonoClassField *field = (MonoClassField *)data;
- MonoType *inflated_type = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
+ MonoType *inflated_type = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, &error);
+ mono_error_assert_ok (&error); /* FIXME don't swallow the error */
+
MonoClass *inflated_class = mono_class_from_mono_type (inflated_type);
int i = field - field->parent->fields;
gpointer dummy = NULL;
// FIXME: Temporary
res = (MonoJumpInfoVirtMethod *)mono_domain_alloc0 (domain, sizeof (MonoJumpInfoVirtMethod));
- t = mono_class_inflate_generic_type (&info->klass->byval_arg, context);
+ t = mono_class_inflate_generic_type_checked (&info->klass->byval_arg, context, &error);
+ mono_error_assert_ok (&error); /* FIXME don't swallow the error */
+
res->klass = mono_class_from_mono_type (t);
mono_metadata_free_type (t);
case MONO_TYPE_PTR:
return &mono_defaults.int_class->byval_arg;
case MONO_TYPE_GENERICINST: {
+ MonoError error;
MonoClass *klass;
MonoGenericContext ctx;
MonoGenericContext *orig_ctx;
args [i] = get_wrapper_shared_type (inst->type_argv [i]);
ctx.method_inst = mono_metadata_get_generic_inst (inst->type_argc, args);
}
- klass = mono_class_inflate_generic_class (klass->generic_class->container_class, &ctx);
+ klass = mono_class_inflate_generic_class_checked (klass->generic_class->container_class, &ctx, &error);
+ mono_error_assert_ok (&error); /* FIXME don't swallow the error */
return &klass->byval_arg;
}
#if SIZEOF_VOID_P == 8
mini_get_gsharedvt_in_sig_wrapper (MonoMethodSignature *sig)
{
MonoMethodBuilder *mb;
- MonoMethod *res;
+ MonoMethod *res, *cached;
WrapperInfo *info;
MonoMethodSignature *csig, *gsharedvt_sig;
int i, pindex, retval_var;
// FIXME: Normal cache
if (!cache)
cache = g_hash_table_new_full ((GHashFunc)mono_signature_hash, (GEqualFunc)mono_metadata_signature_equal, NULL, NULL);
- // FIXME: Locking
+ gshared_lock ();
res = g_hash_table_lookup (cache, sig);
+ gshared_unlock ();
if (res) {
g_free (sig);
return res;
res = mono_mb_create (mb, csig, sig->param_count + 16, info);
- // FIXME: Locking
- g_hash_table_insert (cache, sig, res);
-
+ gshared_lock ();
+ cached = g_hash_table_lookup (cache, sig);
+ if (cached)
+ res = cached;
+ else
+ g_hash_table_insert (cache, sig, res);
+ gshared_unlock ();
return res;
}
mini_get_gsharedvt_out_sig_wrapper (MonoMethodSignature *sig)
{
MonoMethodBuilder *mb;
- MonoMethod *res;
+ MonoMethod *res, *cached;
WrapperInfo *info;
MonoMethodSignature *normal_sig, *csig;
int i, pindex, args_start, ldind_op, stind_op;
// FIXME: Normal cache
if (!cache)
cache = g_hash_table_new_full ((GHashFunc)mono_signature_hash, (GEqualFunc)mono_metadata_signature_equal, NULL, NULL);
- // FIXME: Locking
+ gshared_lock ();
res = g_hash_table_lookup (cache, sig);
+ gshared_unlock ();
if (res) {
g_free (sig);
return res;
res = mono_mb_create (mb, csig, sig->param_count + 16, info);
- // FIXME: Locking
- g_hash_table_insert (cache, sig, res);
-
+ gshared_lock ();
+ cached = g_hash_table_lookup (cache, sig);
+ if (cached)
+ res = cached;
+ else
+ g_hash_table_insert (cache, sig, res);
+ gshared_unlock ();
return res;
}
return mrgctx;
}
-
-static gboolean
-generic_inst_is_sharable (MonoGenericInst *inst, gboolean allow_type_vars,
- gboolean allow_partial);
-
static gboolean
type_is_sharable (MonoType *type, gboolean allow_type_vars, gboolean allow_partial)
{
if (allow_partial && !type->byref && type->type == MONO_TYPE_GENERICINST && MONO_TYPE_ISSTRUCT (type)) {
MonoGenericClass *gclass = type->data.generic_class;
- if (gclass->context.class_inst && !generic_inst_is_sharable (gclass->context.class_inst, allow_type_vars, allow_partial))
+ if (gclass->context.class_inst && !mini_generic_inst_is_sharable (gclass->context.class_inst, allow_type_vars, allow_partial))
return FALSE;
- if (gclass->context.method_inst && !generic_inst_is_sharable (gclass->context.method_inst, allow_type_vars, allow_partial))
+ if (gclass->context.method_inst && !mini_generic_inst_is_sharable (gclass->context.method_inst, allow_type_vars, allow_partial))
return FALSE;
if (mono_class_is_nullable (mono_class_from_mono_type (type)))
return FALSE;
return FALSE;
}
-static gboolean
-generic_inst_is_sharable (MonoGenericInst *inst, gboolean allow_type_vars,
+gboolean
+mini_generic_inst_is_sharable (MonoGenericInst *inst, gboolean allow_type_vars,
gboolean allow_partial)
{
int i;
{
g_assert (context->class_inst || context->method_inst);
- if (context->class_inst && !generic_inst_is_sharable (context->class_inst, allow_type_vars, allow_partial))
+ if (context->class_inst && !mini_generic_inst_is_sharable (context->class_inst, allow_type_vars, allow_partial))
return FALSE;
- if (context->method_inst && !generic_inst_is_sharable (context->method_inst, allow_type_vars, allow_partial))
+ if (context->method_inst && !mini_generic_inst_is_sharable (context->method_inst, allow_type_vars, allow_partial))
return FALSE;
return TRUE;
return FALSE;
}
+/* Lazy class loading functions */
+static GENERATE_TRY_GET_CLASS_WITH_CACHE (iasync_state_machine, System.Runtime.CompilerServices, IAsyncStateMachine)
+static GENERATE_TRY_GET_CLASS_WITH_CACHE (async_state_machine_attribute, System.Runtime.CompilerServices, AsyncStateMachineAttribute)
+
+
static G_GNUC_UNUSED gboolean
is_async_state_machine_class (MonoClass *klass)
{
- static MonoClass *iclass;
- static gboolean iclass_set;
+ MonoClass *iclass;
return FALSE;
- if (!iclass_set) {
- iclass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.CompilerServices", "IAsyncStateMachine");
- mono_memory_barrier ();
- iclass_set = TRUE;
- }
+ iclass = mono_class_try_get_iasync_state_machine_class ();
if (iclass && klass->valuetype && mono_class_is_assignable_from (iclass, klass))
return TRUE;
static G_GNUC_UNUSED gboolean
is_async_method (MonoMethod *method)
{
+ MonoError error;
MonoCustomAttrInfo *cattr;
MonoMethodSignature *sig;
gboolean res = FALSE;
- static MonoClass *attr_class;
- static gboolean attr_class_set;
+ MonoClass *attr_class;
return FALSE;
- if (!attr_class_set) {
- attr_class = mono_class_from_name (mono_defaults.corlib, "System.Runtime.CompilerServices", "AsyncStateMachineAttribute");
- mono_memory_barrier ();
- attr_class_set = TRUE;
- }
+ attr_class = mono_class_try_get_iasync_state_machine_class ();
/* Do less expensive checks first */
sig = mono_method_signature (method);
(sig->ret->type == MONO_TYPE_CLASS && !strcmp (sig->ret->data.generic_class->container_class->name, "Task")) ||
(sig->ret->type == MONO_TYPE_GENERICINST && !strcmp (sig->ret->data.generic_class->container_class->name, "Task`1")))) {
//printf ("X: %s\n", mono_method_full_name (method, TRUE));
- cattr = mono_custom_attrs_from_method (method);
+ cattr = mono_custom_attrs_from_method_checked (method, &error);
+ if (!is_ok (&error)) {
+ mono_error_cleanup (&error); /* FIXME don't swallow the error? */
+ return FALSE;
+ }
if (cattr) {
if (mono_custom_attrs_has_attr (cattr, attr_class))
res = TRUE;
}
static gboolean gshared_supported;
-static gboolean gsharedvt_supported;
void
mono_set_generic_sharing_supported (gboolean supported)
gshared_supported = supported;
}
-void
-mono_set_generic_sharing_vt_supported (gboolean supported)
-{
- gsharedvt_supported = supported;
-}
void
mono_set_partial_sharing_supported (gboolean supported)
/*
* mono_generic_sharing_init:
*
- * Register the generic sharing counters.
+ * Initialize the module.
*/
void
mono_generic_sharing_init (void)
mono_counters_register ("RGCTX oti bytes allocted", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_oti_bytes);
mono_install_image_unload_hook (mono_class_unregister_image_generic_subclasses, NULL);
+
+ mono_os_mutex_init_recursive (&gshared_mutex);
}
void
MonoTypeEnum ttype;
if (!type->byref && type->type == MONO_TYPE_GENERICINST && MONO_TYPE_ISSTRUCT (type)) {
+ MonoError error;
MonoGenericClass *gclass = type->data.generic_class;
MonoGenericContext context;
MonoClass *k;
if (gclass->context.method_inst)
context.method_inst = get_shared_inst (gclass->context.method_inst, gclass->container_class->generic_container->context.method_inst, NULL, FALSE, FALSE, TRUE);
- k = mono_class_inflate_generic_class (gclass->container_class, &context);
+ k = mono_class_inflate_generic_class_checked (gclass->container_class, &context, &error);
+ mono_error_assert_ok (&error); /* FIXME don't swallow the error */
return mini_get_shared_gparam (t, &k->byval_arg);
} else if (MONO_TYPE_ISSTRUCT (type)) {
if (all_vt || gsharedvt) {
type_argv [i] = get_gsharedvt_type (shared_inst->type_argv [i]);
} else {
- /* These types match the ones in generic_inst_is_sharable () */
+ /* These types match the ones in mini_generic_inst_is_sharable () */
type_argv [i] = get_shared_type (shared_inst->type_argv [i], inst->type_argv [i]);
}
}
return slot;
}
-
-#if defined(ENABLE_GSHAREDVT)
-
-#include "../../../mono-extensions/mono/mini/mini-generic-sharing-gsharedvt.c"
-
-#else
-
-gboolean
-mini_is_gsharedvt_type (MonoType *t)
-{
- return FALSE;
-}
-
-gboolean
-mini_is_gsharedvt_klass (MonoClass *klass)
-{
- return FALSE;
-}
-
-gboolean
-mini_is_gsharedvt_signature (MonoMethodSignature *sig)
-{
- return FALSE;
-}
-
-gboolean
-mini_is_gsharedvt_variable_type (MonoType *t)
-{
- return FALSE;
-}
-
-gboolean
-mini_is_gsharedvt_sharable_method (MonoMethod *method)
-{
- return FALSE;
-}
-
-gboolean
-mini_is_gsharedvt_variable_signature (MonoMethodSignature *sig)
-{
- return FALSE;
-}
-
-#endif /* !MONOTOUCH */