From 3a4c1eeb38a124b9a9c19533f773a16652a06ddc Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Sat, 19 Jan 2013 03:02:45 +0100 Subject: [PATCH] Add gsharedvt support functions to the generic sharing code. --- mono/mini/aot-compiler.c | 4 +- mono/mini/aot-runtime.c | 4 +- mono/mini/mini-generic-sharing.c | 147 +++++++++++++++++++++++++++++-- mono/mini/mini.c | 2 +- mono/mini/mini.h | 18 +++- 5 files changed, 160 insertions(+), 15 deletions(-) diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index 3b465ee2785..368b645a01b 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -3486,7 +3486,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth, iter = NULL; while ((method = mono_class_get_methods (klass, &iter))) { - if (mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE)) + if (mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE, FALSE)) /* Already added */ continue; @@ -3754,7 +3754,7 @@ add_generic_instances (MonoAotCompile *acfg) * If the method is fully sharable, it was already added in place of its * generic definition. */ - if (mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE)) + if (mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE, FALSE)) continue; /* diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index 196819437ad..417408bacee 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -3347,7 +3347,7 @@ mono_aot_get_method (MonoDomain *domain, MonoMethod *method) g_assert (klass->inited); /* Find method index */ - if (method->is_inflated && mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE)) { + if (method->is_inflated && mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE, FALSE)) { /* * For generic methods, we store the fully shared instance in place of the * original method. @@ -3447,7 +3447,7 @@ mono_aot_get_method (MonoDomain *domain, MonoMethod *method) return code; } - if (method_index == 0xffffff && method->is_inflated && mono_method_is_generic_sharable_impl_full (method, FALSE, TRUE)) { + if (method_index == 0xffffff && method->is_inflated && mono_method_is_generic_sharable_impl_full (method, FALSE, TRUE, FALSE)) { /* Partial sharing */ method_index = find_extra_method (mini_get_shared_method (method), &amodule); } diff --git a/mono/mini/mini-generic-sharing.c b/mono/mini/mini-generic-sharing.c index b250f10cbc6..b011211b09d 100644 --- a/mono/mini/mini-generic-sharing.c +++ b/mono/mini/mini-generic-sharing.c @@ -27,6 +27,9 @@ static void mono_class_unregister_image_generic_subclasses (MonoImage *image, gpointer user_data); +static MonoType* +mini_get_gsharedvt_alloc_type_gsctx (MonoGenericSharingContext *gsctx, MonoType *t); + static int type_check_context_used (MonoType *type, gboolean recursive) { @@ -672,6 +675,11 @@ get_shared_class (MonoClass *class) */ //g_assert_not_reached (); + /* The gsharedvt changes break this */ + if (ALLOW_PARTIAL_SHARING) + g_assert_not_reached (); + +#if 0 if (class->is_inflated) { MonoGenericContext *context = &class->generic_class->context; MonoGenericContext *container_context; @@ -701,6 +709,7 @@ get_shared_class (MonoClass *class) return class; } } +#endif return class_uninstantiated (class); } @@ -1527,6 +1536,7 @@ has_constraints (MonoGenericContainer *container) * @method: a method * @allow_type_vars: whether to regard type variables as reference types * @alloc_partial: whether to allow partial sharing + * @alloc_gsharedvt: whenever to allow sharing over valuetypes * * Returns TRUE iff the method is inflated or part of an inflated * class, its context is sharable and it has no constraints on its @@ -1534,11 +1544,14 @@ has_constraints (MonoGenericContainer *container) */ gboolean mono_method_is_generic_sharable_impl_full (MonoMethod *method, gboolean allow_type_vars, - gboolean allow_partial) + gboolean allow_partial, gboolean allow_gsharedvt) { if (!mono_method_is_generic_impl (method)) return FALSE; + if (allow_gsharedvt && mini_is_gsharedvt_sharable_method (method)) + return TRUE; + if (method->is_inflated) { MonoMethodInflated *inflated = (MonoMethodInflated*)method; MonoGenericContext *context = &inflated->context; @@ -1574,7 +1587,7 @@ mono_method_is_generic_sharable_impl_full (MonoMethod *method, gboolean allow_ty gboolean mono_method_is_generic_sharable_impl (MonoMethod *method, gboolean allow_type_vars) { - return mono_method_is_generic_sharable_impl_full (method, allow_type_vars, ALLOW_PARTIAL_SHARING); + return mono_method_is_generic_sharable_impl_full (method, allow_type_vars, ALLOW_PARTIAL_SHARING, TRUE); } gboolean @@ -1643,6 +1656,7 @@ mono_method_construct_object_context (MonoMethod *method) } static gboolean gshared_supported; +static gboolean gsharedvt_supported; void mono_set_generic_sharing_supported (gboolean supported) @@ -1650,6 +1664,12 @@ mono_set_generic_sharing_supported (gboolean supported) gshared_supported = supported; } +void +mono_set_generic_sharing_vt_supported (gboolean supported) +{ + gsharedvt_supported = supported; +} + /* * mono_class_generic_sharing_enabled: * @class: a class @@ -1842,10 +1862,15 @@ mini_class_get_context (MonoClass *class) MonoType* mini_get_basic_type_from_generic (MonoGenericSharingContext *gsctx, MonoType *type) { + /* FIXME: Some callers don't pass in a gsctx, like mono_dyn_call_prepare () */ + /* if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) g_assert (gsctx); - - return mono_type_get_basic_type_from_generic (type); + */ + if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) && mini_is_gsharedvt_type_gsctx (gsctx, type)) + return mini_get_gsharedvt_alloc_type_gsctx (gsctx, type); + else + return mono_type_get_basic_type_from_generic (type); } /* @@ -1859,7 +1884,7 @@ mini_type_get_underlying_type (MonoGenericSharingContext *gsctx, MonoType *type) { if (type->byref) return &mono_defaults.int_class->byval_arg; - return mono_type_get_basic_type_from_generic (mono_type_get_underlying_type (type)); + return mini_get_basic_type_from_generic (gsctx, mono_type_get_underlying_type (type)); } /* @@ -1884,13 +1909,21 @@ mini_type_stack_size (MonoGenericSharingContext *gsctx, MonoType *t, int *align) /* * mini_type_stack_size_full: * - * Same as mini_type_stack_size, but handle pinvoke data types as well. + * Same as mini_type_stack_size, but handle gsharedvt and pinvoke data types as well. */ int mini_type_stack_size_full (MonoGenericSharingContext *gsctx, MonoType *t, guint32 *align, gboolean pinvoke) { int size; + /* + if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) + g_assert (gsctx); + */ + + if (mini_is_gsharedvt_type_gsctx (gsctx, t)) + t = mini_get_gsharedvt_alloc_type_gsctx (gsctx, t); + if (pinvoke) { size = mono_type_native_stack_size (t, align); } else { @@ -1927,6 +1960,30 @@ mono_generic_sharing_cleanup (void) g_hash_table_destroy (generic_subclass_hash); } +/* + * mini_type_var_is_vt: + * + * Return whenever T is a type variable instantiated with a vtype. + */ +gboolean +mini_type_var_is_vt (MonoCompile *cfg, MonoType *type) +{ + if (type->type == MONO_TYPE_VAR) { + if (cfg->generic_sharing_context->var_is_vt && cfg->generic_sharing_context->var_is_vt [type->data.generic_param->num]) + return TRUE; + else + return FALSE; + } else if (type->type == MONO_TYPE_MVAR) { + if (cfg->generic_sharing_context->mvar_is_vt && cfg->generic_sharing_context->mvar_is_vt [type->data.generic_param->num]) + return TRUE; + else + return FALSE; + } else { + g_assert_not_reached (); + } + return FALSE; +} + gboolean mini_type_is_reference (MonoCompile *cfg, MonoType *type) { @@ -1935,5 +1992,81 @@ mini_type_is_reference (MonoCompile *cfg, MonoType *type) if (!cfg->generic_sharing_context) return FALSE; /*FIXME the probably needs better handle under partial sharing*/ - return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR; + return ((type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) && !mini_type_var_is_vt (cfg, type)); +} + +/* + * mini_method_get_rgctx: + * + * Return the RGCTX which needs to be passed to M when it is called. + */ +gpointer +mini_method_get_rgctx (MonoMethod *m) +{ + if (mini_method_get_context (m)->method_inst) + return mono_method_lookup_rgctx (mono_class_vtable (mono_domain_get (), m->klass), mini_method_get_context (m)->method_inst); + else + return mono_class_vtable (mono_domain_get (), m->klass); +} + +#ifdef MONOTOUCH + +#include "mini-generic-sharing-gshared.c" + +#else + +gboolean +mini_is_gsharedvt_type_gsctx (MonoGenericSharingContext *gsctx, MonoType *t) +{ + return FALSE; +} + +gboolean +mini_is_gsharedvt_type (MonoCompile *cfg, MonoType *t) +{ + return FALSE; } + +gboolean +mini_is_gsharedvt_klass (MonoCompile *cfg, MonoClass *klass) +{ + return FALSE; +} + +gboolean +mini_is_gsharedvt_signature (MonoCompile *cfg, MonoMethodSignature *sig) +{ + return FALSE; +} + +gboolean +mini_is_gsharedvt_variable_type (MonoCompile *cfg, MonoType *t) +{ + return FALSE; +} + +static MonoType* +mini_get_gsharedvt_alloc_type_gsctx (MonoGenericSharingContext *gsctx, MonoType *t) +{ + return NULL; +} + +MonoType* +mini_get_gsharedvt_alloc_type_for_type (MonoCompile *cfg, MonoType *t) +{ + return NULL; +} + +gboolean +mini_is_gsharedvt_sharable_method (MonoMethod *method) +{ + return FALSE; +} + +gboolean +mini_is_gsharedvt_variable_signature (MonoMethodSignature *sig) +{ + return FALSE; +} + +#endif /* !MONOTOUCH */ diff --git a/mono/mini/mini.c b/mono/mini/mini.c index a80150fa634..6fb87d3708d 100644 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -4230,7 +4230,7 @@ mini_get_shared_method (MonoMethod *method) shared_context = declaring_method->klass->generic_container->context; /* Handle partial sharing */ - if (method != declaring_method && method->is_inflated && !mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE)) { + if (method != declaring_method && method->is_inflated && !mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE, FALSE)) { MonoGenericContext *context = mono_method_get_context (method); MonoGenericInst *inst; MonoType **type_argv; diff --git a/mono/mini/mini.h b/mono/mini/mini.h index 0a3ee8b5515..50dafa85426 100644 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -2335,10 +2335,12 @@ MonoArray* ves_icall_System_Security_SecurityFrame_GetSecurityStack (gint32 skip /* Generic sharing */ - void mono_set_generic_sharing_supported (gboolean supported) MONO_INTERNAL; +void +mono_set_generic_sharing_vt_supported (gboolean supported) MONO_INTERNAL; + gboolean mono_class_generic_sharing_enabled (MonoClass *class) MONO_INTERNAL; @@ -2386,7 +2388,7 @@ gboolean mono_method_is_generic_sharable_impl (MonoMethod *method, gboolean allow_type_vars) MONO_INTERNAL; gboolean -mono_method_is_generic_sharable_impl_full (MonoMethod *method, gboolean allow_type_vars, gboolean allow_partial) MONO_INTERNAL; +mono_method_is_generic_sharable_impl_full (MonoMethod *method, gboolean allow_type_vars, gboolean allow_partial, gboolean allow_gsharedvt) MONO_INTERNAL; gboolean mono_is_partially_sharable_inst (MonoGenericInst *inst) MONO_INTERNAL; @@ -2423,7 +2425,17 @@ void mono_cfg_add_try_hole (MonoCompile *cfg, MonoExceptionClause *clause, guint void mono_cfg_set_exception (MonoCompile *cfg, int type) MONO_INTERNAL; gboolean mini_type_is_reference (MonoCompile *cfg, MonoType *type) MONO_INTERNAL; - +gboolean mini_type_var_is_vt (MonoCompile *cfg, MonoType *type) MONO_INTERNAL; +gboolean mini_is_gsharedvt_klass (MonoCompile *cfg, MonoClass *klass) MONO_INTERNAL; +gboolean mini_is_gsharedvt_type (MonoCompile *cfg, MonoType *t) MONO_INTERNAL; +gboolean mini_is_gsharedvt_signature (MonoCompile *cfg, MonoMethodSignature *sig) MONO_INTERNAL; +gboolean mini_is_gsharedvt_type_gsctx (MonoGenericSharingContext *gsctx, MonoType *t) MONO_INTERNAL; +gboolean mini_is_gsharedvt_variable_type (MonoCompile *cfg, MonoType *t) MONO_INTERNAL; +MonoType* mini_get_gsharedvt_alloc_type_for_type (MonoCompile *cfg, MonoType *t) MONO_INTERNAL; +gboolean mini_is_gsharedvt_sharable_method (MonoMethod *method) MONO_INTERNAL; +gboolean mini_is_gsharedvt_variable_signature (MonoMethodSignature *sig) MONO_INTERNAL; +gpointer mini_method_get_rgctx (MonoMethod *m) MONO_INTERNAL; +void mini_init_gsctx (MonoGenericContext *context, MonoGenericSharingContext *gsctx) MONO_INTERNAL; /* wapihandles.c */ int mini_wapi_hps (int argc, char **argv) MONO_INTERNAL; -- 2.25.1