X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmini-generic-sharing.c;h=5faf64957697fb047ffe544673c6e28e6244fde1;hb=HEAD;hp=6322cf8f4fb5a081daa9c0068cf5a01cdd87bf5c;hpb=d0b87d802e2e38ae06a24384e103ff08d0f64bbd;p=mono.git diff --git a/mono/mini/mini-generic-sharing.c b/mono/mini/mini-generic-sharing.c index 6322cf8f4fb..5faf6495769 100644 --- a/mono/mini/mini-generic-sharing.c +++ b/mono/mini/mini-generic-sharing.c @@ -1,5 +1,6 @@ -/* - * mini-generic-sharing.c: Support functions for generic sharing. +/** + * \file + * Support functions for generic sharing. * * Author: * Mark Probst (mark.probst@gmail.com) @@ -15,6 +16,8 @@ #include #include #include +#include +#include #include "mini.h" @@ -31,10 +34,19 @@ static void mono_class_unregister_image_generic_subclasses (MonoImage *image, gpointer user_data); /* Counters */ -static int num_templates_allocted; -static int num_templates_bytes; -static int num_oti_allocted; -static int num_oti_bytes; +static gint32 rgctx_template_num_allocated; +static gint32 rgctx_template_bytes_allocated; +static gint32 rgctx_oti_num_allocated; +static gint32 rgctx_oti_bytes_allocated; +static gint32 rgctx_oti_num_markers; +static gint32 rgctx_oti_num_data; +static gint32 rgctx_max_slot_number; +static gint32 rgctx_num_allocated; +static gint32 rgctx_num_arrays_allocated; +static gint32 rgctx_bytes_allocated; +static gint32 mrgctx_num_arrays_allocated; +static gint32 mrgctx_bytes_allocated; +static gint32 gsharedvt_num_trampolines; #define gshared_lock() mono_os_mutex_lock (&gshared_mutex) #define gshared_unlock() mono_os_mutex_unlock (&gshared_mutex) @@ -353,10 +365,10 @@ mono_class_unregister_image_generic_subclasses (MonoImage *image, gpointer user_ static MonoRuntimeGenericContextTemplate* alloc_template (MonoClass *klass) { - int size = sizeof (MonoRuntimeGenericContextTemplate); + gint32 size = sizeof (MonoRuntimeGenericContextTemplate); - num_templates_allocted++; - num_templates_bytes += size; + InterlockedIncrement (&rgctx_template_num_allocated); + InterlockedAdd(&rgctx_template_bytes_allocated, size); return (MonoRuntimeGenericContextTemplate *)mono_image_alloc0 (klass->image, size); } @@ -365,10 +377,10 @@ alloc_template (MonoClass *klass) static MonoRuntimeGenericContextInfoTemplate* alloc_oti (MonoImage *image) { - int size = sizeof (MonoRuntimeGenericContextInfoTemplate); + gint32 size = sizeof (MonoRuntimeGenericContextInfoTemplate); - num_oti_allocted++; - num_oti_bytes += size; + InterlockedIncrement (&rgctx_oti_num_allocated); + InterlockedAdd (&rgctx_oti_bytes_allocated, size); return (MonoRuntimeGenericContextInfoTemplate *)mono_image_alloc0 (image, size); } @@ -389,24 +401,24 @@ info_has_identity (MonoRgctxInfoType info_type) /* * LOCKING: loader lock */ +#if defined(HOST_ANDROID) && defined(TARGET_ARM) +/* work around for HW bug on Nexus9 when running on armv7 */ +#ifdef __clang__ +static __attribute__ ((optnone)) void +#else +/* gcc */ +static __attribute__ ((optimize("O0"))) void +#endif +#else static void +#endif rgctx_template_set_slot (MonoImage *image, MonoRuntimeGenericContextTemplate *template_, int type_argc, int slot, gpointer data, MonoRgctxInfoType info_type) { - static gboolean inited = FALSE; - static int num_markers = 0; - static int num_data = 0; - int i; MonoRuntimeGenericContextInfoTemplate *list = get_info_templates (template_, type_argc); MonoRuntimeGenericContextInfoTemplate **oti = &list; - if (!inited) { - mono_counters_register ("RGCTX oti num markers", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_markers); - mono_counters_register ("RGCTX oti num data", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_data); - inited = TRUE; - } - g_assert (slot >= 0); g_assert (data); @@ -425,10 +437,11 @@ rgctx_template_set_slot (MonoImage *image, MonoRuntimeGenericContextTemplate *te set_info_templates (image, template_, type_argc, list); + /* interlocked by loader lock (by definition) */ if (data == MONO_RGCTX_SLOT_USED_MARKER) - ++num_markers; + UnlockedIncrement (&rgctx_oti_num_markers); else - ++num_data; + UnlockedIncrement (&rgctx_oti_num_data); } /* @@ -482,14 +495,15 @@ mono_class_get_method_generic (MonoClass *klass, MonoMethod *method) mono_class_setup_methods (klass); if (mono_class_has_failure (klass)) return NULL; - for (i = 0; i < klass->method.count; ++i) { + int mcount = mono_class_get_method_count (klass); + for (i = 0; i < mcount; ++i) { m = klass->methods [i]; if (m == declaring) break; if (m->is_inflated && mono_method_get_declaring_generic_method (m) == declaring) break; } - if (i >= klass->method.count) + if (i >= mcount) return NULL; } @@ -531,6 +545,7 @@ inflate_info (MonoRuntimeGenericContextInfoTemplate *oti, MonoGenericContext *co case MONO_RGCTX_INFO_ARRAY_ELEMENT_SIZE: case MONO_RGCTX_INFO_VALUE_SIZE: case MONO_RGCTX_INFO_CLASS_BOX_TYPE: + case MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS: case MONO_RGCTX_INFO_MEMCPY: case MONO_RGCTX_INFO_BZERO: case MONO_RGCTX_INFO_LOCAL_OFFSET: @@ -869,7 +884,7 @@ class_get_rgctx_template_oti (MonoClass *klass, int type_argc, guint32 slot, gbo static gpointer class_type_info (MonoDomain *domain, MonoClass *klass, MonoRgctxInfoType info_type, MonoError *error) { - mono_error_init (error); + error_init (error); switch (info_type) { case MONO_RGCTX_INFO_STATIC_DATA: { @@ -912,6 +927,13 @@ class_type_info (MonoDomain *domain, MonoClass *klass, MonoRgctxInfoType info_ty return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_NULLABLE); else return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_VTYPE); + case MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS: + mono_class_init (klass); + /* Can't return 0 */ + if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg) || klass->has_references) + return GUINT_TO_POINTER (2); + else + return GUINT_TO_POINTER (1); case MONO_RGCTX_INFO_MEMCPY: case MONO_RGCTX_INFO_BZERO: { static MonoMethod *memcpy_method [17]; @@ -1183,16 +1205,16 @@ mini_get_gsharedvt_in_sig_wrapper (MonoMethodSignature *sig) MonoMethod *res, *cached; WrapperInfo *info; MonoMethodSignature *csig, *gsharedvt_sig; - int i, pindex, retval_var; + int i, pindex, retval_var = 0; static GHashTable *cache; // FIXME: Memory management sig = mini_get_underlying_signature (sig); // FIXME: Normal cache + gshared_lock (); if (!cache) cache = g_hash_table_new_full ((GHashFunc)mono_signature_hash, (GEqualFunc)mono_metadata_signature_equal, NULL, NULL); - gshared_lock (); res = g_hash_table_lookup (cache, sig); gshared_unlock (); if (res) { @@ -1294,9 +1316,9 @@ mini_get_gsharedvt_out_sig_wrapper (MonoMethodSignature *sig) sig = mini_get_underlying_signature (sig); // FIXME: Normal cache + gshared_lock (); if (!cache) cache = g_hash_table_new_full ((GHashFunc)mono_signature_hash, (GEqualFunc)mono_metadata_signature_equal, NULL, NULL); - gshared_lock (); res = g_hash_table_lookup (cache, sig); gshared_unlock (); if (res) { @@ -1398,6 +1420,171 @@ mini_get_gsharedvt_out_sig_wrapper (MonoMethodSignature *sig) return res; } +/* + * mini_get_interp_in_wrapper: + * + * Return a wrapper which can be used to transition from compiled code to the interpreter. + * The wrapper has the same signature as SIG. It is very similar to a gsharedvt_in wrapper, + * except the 'extra_arg' is passed in the rgctx reg, so this wrapper needs to be + * called through a static rgctx trampoline. + * FIXME: Move this elsewhere. + */ +MonoMethod* +mini_get_interp_in_wrapper (MonoMethodSignature *sig) +{ + MonoMethodBuilder *mb; + MonoMethod *res, *cached; + WrapperInfo *info; + MonoMethodSignature *csig, *entry_sig; + int i, pindex, retval_var = 0; + static GHashTable *cache; + const char *name; + gboolean generic = FALSE; + + sig = mini_get_underlying_signature (sig); + + gshared_lock (); + if (!cache) + cache = g_hash_table_new_full ((GHashFunc)mono_signature_hash, (GEqualFunc)mono_metadata_signature_equal, NULL, NULL); + res = g_hash_table_lookup (cache, sig); + gshared_unlock (); + if (res) { + g_free (sig); + return res; + } + + if (sig->param_count > 8) + /* Call the generic interpreter entry point, the specialized ones only handle a limited number of arguments */ + generic = TRUE; + + /* Create the signature for the wrapper */ + csig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + (sig->param_count * sizeof (MonoType*))); + memcpy (csig, sig, mono_metadata_signature_size (sig)); + + /* Create the signature for the callee callconv */ + if (generic) { + /* + * The called function has the following signature: + * interp_entry_general (gpointer this_arg, gpointer res, gpointer *args, gpointer rmethod) + */ + entry_sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + (4 * sizeof (MonoType*))); + entry_sig->ret = &mono_defaults.void_class->byval_arg; + entry_sig->param_count = 4; + entry_sig->params [0] = &mono_defaults.int_class->byval_arg; + entry_sig->params [1] = &mono_defaults.int_class->byval_arg; + entry_sig->params [2] = &mono_defaults.int_class->byval_arg; + entry_sig->params [3] = &mono_defaults.int_class->byval_arg; + name = "interp_in_generic"; + generic = TRUE; + } else { + /* + * The called function has the following signature: + * void entry(, , , ) + */ + entry_sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + ((sig->param_count + 2) * sizeof (MonoType*))); + memcpy (entry_sig, sig, mono_metadata_signature_size (sig)); + pindex = 0; + /* The return value is returned using an explicit vret argument */ + if (sig->ret->type != MONO_TYPE_VOID) { + entry_sig->params [pindex ++] = &mono_defaults.int_class->byval_arg; + entry_sig->ret = &mono_defaults.void_class->byval_arg; + } + for (i = 0; i < sig->param_count; i++) { + entry_sig->params [pindex] = sig->params [i]; + if (!sig->params [i]->byref) { + entry_sig->params [pindex] = mono_metadata_type_dup (NULL, entry_sig->params [pindex]); + entry_sig->params [pindex]->byref = 1; + } + pindex ++; + } + /* Extra arg */ + entry_sig->params [pindex ++] = &mono_defaults.int_class->byval_arg; + entry_sig->param_count = pindex; + name = sig->hasthis ? "interp_in" : "interp_in_static"; + } + + mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_UNKNOWN); + + /* This is needed to be able to unwind out of interpreted code */ + mb->method->save_lmf = 1; + +#ifndef DISABLE_JIT + if (sig->ret->type != MONO_TYPE_VOID) + retval_var = mono_mb_add_local (mb, sig->ret); + + /* Make the call */ + if (generic) { + /* Collect arguments */ + int args_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg); + + mono_mb_emit_icon (mb, sizeof (gpointer) * sig->param_count); + mono_mb_emit_byte (mb, CEE_PREFIX1); + mono_mb_emit_byte (mb, CEE_LOCALLOC); + mono_mb_emit_stloc (mb, args_var); + + for (i = 0; i < sig->param_count; i++) { + mono_mb_emit_ldloc (mb, args_var); + mono_mb_emit_icon (mb, sizeof (gpointer) * i); + mono_mb_emit_byte (mb, CEE_ADD); + if (sig->params [i]->byref) + mono_mb_emit_ldarg (mb, i + (sig->hasthis == TRUE)); + else + mono_mb_emit_ldarg_addr (mb, i + (sig->hasthis == TRUE)); + mono_mb_emit_byte (mb, CEE_STIND_I); + } + + if (sig->hasthis) + mono_mb_emit_ldarg (mb, 0); + else + mono_mb_emit_byte (mb, CEE_LDNULL); + if (sig->ret->type != MONO_TYPE_VOID) + mono_mb_emit_ldloc_addr (mb, retval_var); + else + mono_mb_emit_byte (mb, CEE_LDNULL); + mono_mb_emit_ldloc (mb, args_var); + } else { + if (sig->hasthis) + mono_mb_emit_ldarg (mb, 0); + if (sig->ret->type != MONO_TYPE_VOID) + mono_mb_emit_ldloc_addr (mb, retval_var); + for (i = 0; i < sig->param_count; i++) { + if (sig->params [i]->byref) + mono_mb_emit_ldarg (mb, i + (sig->hasthis == TRUE)); + else + mono_mb_emit_ldarg_addr (mb, i + (sig->hasthis == TRUE)); + } + } + /* Extra arg */ + mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); + mono_mb_emit_byte (mb, CEE_MONO_GET_RGCTX_ARG); + mono_mb_emit_icon (mb, sizeof (gpointer)); + mono_mb_emit_byte (mb, CEE_ADD); + mono_mb_emit_byte (mb, CEE_LDIND_I); + /* Method to call */ + mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); + mono_mb_emit_byte (mb, CEE_MONO_GET_RGCTX_ARG); + mono_mb_emit_byte (mb, CEE_LDIND_I); + mono_mb_emit_calli (mb, entry_sig); + if (sig->ret->type != MONO_TYPE_VOID) + mono_mb_emit_ldloc (mb, retval_var); + mono_mb_emit_byte (mb, CEE_RET); +#endif + + info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_INTERP_IN); + info->d.interp_in.sig = sig; + + res = mono_mb_create (mb, csig, sig->param_count + 16, info); + + 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; +} + MonoMethodSignature* mini_get_gsharedvt_out_sig_wrapper_signature (gboolean has_this, gboolean has_ret, int param_count) { @@ -1431,8 +1618,6 @@ mini_get_gsharedvt_out_sig_wrapper_signature (gboolean has_this, gboolean has_re gpointer mini_get_gsharedvt_wrapper (gboolean gsharedvt_in, gpointer addr, MonoMethodSignature *normal_sig, MonoMethodSignature *gsharedvt_sig, gint32 vcall_offset, gboolean calli) { - static gboolean inited = FALSE; - static int num_trampolines; MonoError error; gpointer res, info; MonoDomain *domain = mono_domain_get (); @@ -1440,11 +1625,6 @@ mini_get_gsharedvt_wrapper (gboolean gsharedvt_in, gpointer addr, MonoMethodSign GSharedVtTrampInfo *tramp_info; GSharedVtTrampInfo tinfo; - if (!inited) { - mono_counters_register ("GSHAREDVT arg trampolines", MONO_COUNTER_JIT | MONO_COUNTER_INT, &num_trampolines); - inited = TRUE; - } - if (mono_llvm_only) { MonoMethod *wrapper; @@ -1511,7 +1691,7 @@ mini_get_gsharedvt_wrapper (gboolean gsharedvt_in, gpointer addr, MonoMethodSign else addr = mono_arch_get_gsharedvt_arg_trampoline (mono_domain_get (), info, addr); - num_trampolines ++; + InterlockedIncrement (&gsharedvt_num_trampolines); /* Cache it */ tramp_info = (GSharedVtTrampInfo *)mono_domain_alloc0 (domain, sizeof (GSharedVtTrampInfo)); @@ -1537,7 +1717,7 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti gpointer data; gboolean temporary; - mono_error_init (error); + error_init (error); if (!oti->data) return NULL; @@ -1565,6 +1745,7 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti case MONO_RGCTX_INFO_ARRAY_ELEMENT_SIZE: case MONO_RGCTX_INFO_VALUE_SIZE: case MONO_RGCTX_INFO_CLASS_BOX_TYPE: + case MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS: case MONO_RGCTX_INFO_MEMCPY: case MONO_RGCTX_INFO_BZERO: case MONO_RGCTX_INFO_NULLABLE_CLASS_BOX: @@ -2006,6 +2187,7 @@ mono_rgctx_info_type_to_str (MonoRgctxInfoType type) case MONO_RGCTX_INFO_ARRAY_ELEMENT_SIZE: return "ARRAY_ELEMENT_SIZE"; case MONO_RGCTX_INFO_VALUE_SIZE: return "VALUE_SIZE"; case MONO_RGCTX_INFO_CLASS_BOX_TYPE: return "CLASS_BOX_TYPE"; + case MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS: return "CLASS_IS_REF_OR_CONTAINS_REFS"; case MONO_RGCTX_INFO_FIELD_OFFSET: return "FIELD_OFFSET"; case MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE: return "METHOD_GSHAREDVT_OUT_TRAMPOLINE"; case MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE_VIRT: return "METHOD_GSHAREDVT_OUT_TRAMPOLINE_VIRT"; @@ -2094,6 +2276,7 @@ info_equal (gpointer data1, gpointer data2, MonoRgctxInfoType info_type) case MONO_RGCTX_INFO_ARRAY_ELEMENT_SIZE: case MONO_RGCTX_INFO_VALUE_SIZE: case MONO_RGCTX_INFO_CLASS_BOX_TYPE: + case MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS: case MONO_RGCTX_INFO_MEMCPY: case MONO_RGCTX_INFO_BZERO: case MONO_RGCTX_INFO_NULLABLE_CLASS_BOX: @@ -2147,6 +2330,7 @@ mini_rgctx_info_type_to_patch_info_type (MonoRgctxInfoType info_type) case MONO_RGCTX_INFO_ARRAY_ELEMENT_SIZE: case MONO_RGCTX_INFO_VALUE_SIZE: case MONO_RGCTX_INFO_CLASS_BOX_TYPE: + case MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS: case MONO_RGCTX_INFO_MEMCPY: case MONO_RGCTX_INFO_BZERO: case MONO_RGCTX_INFO_NULLABLE_CLASS_BOX: @@ -2165,9 +2349,6 @@ static int lookup_or_register_info (MonoClass *klass, int type_argc, gpointer data, MonoRgctxInfoType info_type, MonoGenericContext *generic_context) { - static gboolean inited = FALSE; - static int max_slot = 0; - MonoRuntimeGenericContextTemplate *rgctx_template = mono_class_get_runtime_generic_context_template (klass); MonoRuntimeGenericContextInfoTemplate *oti_list, *oti; @@ -2200,14 +2381,11 @@ lookup_or_register_info (MonoClass *klass, int type_argc, gpointer data, MonoRgc /* We haven't found the info */ i = register_info (klass, type_argc, data, info_type); - mono_loader_unlock (); + /* interlocked by loader lock */ + if (i > UnlockedRead (&rgctx_max_slot_number)) + UnlockedWrite (&rgctx_max_slot_number, i); - if (!inited) { - mono_counters_register ("RGCTX max slot number", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &max_slot); - inited = TRUE; - } - if (i > max_slot) - max_slot = i; + mono_loader_unlock (); return i; } @@ -2277,29 +2455,16 @@ mono_class_rgctx_get_array_size (int n, gboolean mrgctx) static gpointer* alloc_rgctx_array (MonoDomain *domain, int n, gboolean is_mrgctx) { - static gboolean inited = FALSE; - static int rgctx_num_alloced = 0; - static int rgctx_bytes_alloced = 0; - static int mrgctx_num_alloced = 0; - static int mrgctx_bytes_alloced = 0; - - int size = mono_class_rgctx_get_array_size (n, is_mrgctx) * sizeof (gpointer); + gint32 size = mono_class_rgctx_get_array_size (n, is_mrgctx) * sizeof (gpointer); gpointer *array = (gpointer *)mono_domain_alloc0 (domain, size); - if (!inited) { - mono_counters_register ("RGCTX num arrays alloced", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &rgctx_num_alloced); - mono_counters_register ("RGCTX bytes alloced", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &rgctx_bytes_alloced); - mono_counters_register ("MRGCTX num arrays alloced", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &mrgctx_num_alloced); - mono_counters_register ("MRGCTX bytes alloced", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &mrgctx_bytes_alloced); - inited = TRUE; - } - + /* interlocked by domain lock (by definition) */ if (is_mrgctx) { - mrgctx_num_alloced++; - mrgctx_bytes_alloced += size; + UnlockedIncrement (&mrgctx_num_arrays_allocated); + UnlockedAdd (&mrgctx_bytes_allocated, size); } else { - rgctx_num_alloced++; - rgctx_bytes_alloced += size; + UnlockedIncrement (&rgctx_num_arrays_allocated); + UnlockedAdd (&rgctx_bytes_allocated, size); } return array; @@ -2319,7 +2484,7 @@ fill_runtime_generic_context (MonoVTable *class_vtable, MonoRuntimeGenericContex int rgctx_index; gboolean do_free; - mono_error_init (error); + error_init (error); g_assert (rgctx); @@ -2364,6 +2529,7 @@ fill_runtime_generic_context (MonoVTable *class_vtable, MonoRuntimeGenericContex method_inst ? method_inst->type_argc : 0, slot, TRUE, TRUE, &do_free); /* This might take the loader lock */ info = instantiate_info (domain, &oti, &context, klass, error); + return_val_if_nok (error, NULL); g_assert (info); /* @@ -2399,27 +2565,19 @@ fill_runtime_generic_context (MonoVTable *class_vtable, MonoRuntimeGenericContex gpointer mono_class_fill_runtime_generic_context (MonoVTable *class_vtable, guint32 slot, MonoError *error) { - static gboolean inited = FALSE; - static int num_alloced = 0; - MonoDomain *domain = class_vtable->domain; MonoRuntimeGenericContext *rgctx; gpointer info; - mono_error_init (error); + error_init (error); mono_domain_lock (domain); - if (!inited) { - mono_counters_register ("RGCTX num alloced", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_alloced); - inited = TRUE; - } - rgctx = class_vtable->runtime_generic_context; if (!rgctx) { rgctx = alloc_rgctx_array (domain, 0, FALSE); class_vtable->runtime_generic_context = rgctx; - num_alloced++; + UnlockedIncrement (&rgctx_num_allocated); /* interlocked by domain lock */ } mono_domain_unlock (domain); @@ -2671,7 +2829,7 @@ mini_method_is_open (MonoMethod *method) } /* 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 (iasync_state_machine, "System.Runtime.CompilerServices", "IAsyncStateMachine") static G_GNUC_UNUSED gboolean is_async_state_machine_class (MonoClass *klass) @@ -2837,7 +2995,8 @@ mono_method_needs_static_rgctx_invoke (MonoMethod *method, gboolean allow_type_v return TRUE; return ((method->flags & METHOD_ATTRIBUTE_STATIC) || - method->klass->valuetype) && + method->klass->valuetype || + MONO_CLASS_IS_INTERFACE (method->klass)) && (mono_class_is_ginst (method->klass) || mono_class_is_gtd (method->klass)); } @@ -3040,7 +3199,7 @@ mini_get_basic_type_from_generic (MonoType *type) return type; else if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) { MonoType *constraint = type->data.generic_param->gshared_constraint; - /* The gparam serial encodes the type this gparam can represent */ + /* The gparam constraint encodes the type this gparam can represent */ if (!constraint) { return &mono_defaults.object_class->byval_arg; } else { @@ -3058,7 +3217,7 @@ mini_get_basic_type_from_generic (MonoType *type) /* * mini_type_get_underlying_type: * - * Return the underlying type of TYPE, taking into account enums, byref, bool, char and generic + * Return the underlying type of TYPE, taking into account enums, byref, bool, char, ref types and generic * sharing. */ MonoType* @@ -3077,6 +3236,9 @@ mini_type_get_underlying_type (MonoType *type) case MONO_TYPE_CHAR: return &mono_defaults.uint16_class->byval_arg; case MONO_TYPE_STRING: + case MONO_TYPE_CLASS: + case MONO_TYPE_ARRAY: + case MONO_TYPE_SZARRAY: return &mono_defaults.object_class->byval_arg; default: return type; @@ -3132,10 +3294,19 @@ mini_type_stack_size_full (MonoType *t, guint32 *align, gboolean pinvoke) void mono_generic_sharing_init (void) { - mono_counters_register ("RGCTX template num allocted", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_templates_allocted); - mono_counters_register ("RGCTX template bytes allocted", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_templates_bytes); - mono_counters_register ("RGCTX oti num allocted", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_oti_allocted); - mono_counters_register ("RGCTX oti bytes allocted", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_oti_bytes); + mono_counters_register ("RGCTX template num allocated", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &rgctx_template_num_allocated); + mono_counters_register ("RGCTX template bytes allocated", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &rgctx_template_bytes_allocated); + mono_counters_register ("RGCTX oti num allocated", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &rgctx_oti_num_allocated); + mono_counters_register ("RGCTX oti bytes allocated", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &rgctx_oti_bytes_allocated); + mono_counters_register ("RGCTX oti num markers", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &rgctx_oti_num_markers); + mono_counters_register ("RGCTX oti num data", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &rgctx_oti_num_data); + mono_counters_register ("RGCTX max slot number", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &rgctx_max_slot_number); + mono_counters_register ("RGCTX num allocated", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &rgctx_num_allocated); + mono_counters_register ("RGCTX num arrays allocated", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &rgctx_num_arrays_allocated); + mono_counters_register ("RGCTX bytes allocated", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &rgctx_bytes_allocated); + mono_counters_register ("MRGCTX num arrays allocated", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &mrgctx_num_arrays_allocated); + mono_counters_register ("MRGCTX bytes allocated", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &mrgctx_bytes_allocated); + mono_counters_register ("GSHAREDVT num trampolines", MONO_COUNTER_JIT | MONO_COUNTER_INT, &gsharedvt_num_trampolines); mono_install_image_unload_hook (mono_class_unregister_image_generic_subclasses, NULL); @@ -3314,6 +3485,7 @@ mini_get_shared_gparam (MonoType *t, MonoType *constraint) copy = (MonoGSharedGenericParam *)mono_image_alloc0 (image, sizeof (MonoGSharedGenericParam)); memcpy (©->param, par, sizeof (MonoGenericParamFull)); copy->param.info.pklass = NULL; + constraint = mono_metadata_type_dup (image, constraint); name = get_shared_gparam_name (constraint->type, ((MonoGenericParamFull*)copy)->info.name); copy->param.info.name = mono_image_strdup (image, name); g_free (name); @@ -3575,7 +3747,9 @@ static gboolean gsharedvt_supported; void mono_set_generic_sharing_vt_supported (gboolean supported) { - gsharedvt_supported = supported; + /* ensure we do not disable gsharedvt once it's been enabled */ + if (!gsharedvt_supported && supported) + gsharedvt_supported = TRUE; } #ifdef MONO_ARCH_GSHAREDVT_SUPPORTED