MonoStats mono_stats;
gboolean mono_print_vtable = FALSE;
+gboolean mono_align_small_structs = FALSE;
/* Statistics */
guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
}
}
- g_assert (!mono_loader_get_last_error ());
+ mono_loader_assert_no_error ();
return res;
}
MonoType *nt;
int num = mono_type_get_generic_param_num (type);
MonoGenericInst *inst = context->method_inst;
- if (!inst || !inst->type_argv)
+ if (!inst)
return NULL;
if (num >= inst->type_argc) {
MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
MonoMethodInflated *iresult, *cached;
MonoMethodSignature *sig;
MonoGenericContext tmp_context;
- gboolean is_mb_open = FALSE;
mono_error_init (error);
(method->klass->generic_container && context->class_inst)))
return method;
- /*
- * The reason for this hack is to fix the behavior of inflating generic methods that come from a MethodBuilder.
- * What happens is that instantiating a generic MethodBuilder with its own arguments should create a diferent object.
- * This is opposite to the way non-SRE MethodInfos behave.
- *
- * This happens, for example, when we want to emit a recursive generic method. Given the following C# code:
- *
- * void Example<T> () {
- * Example<T> ();
- * }
- *
- * In Example, the method token must be encoded as: "void Example<!!0>()"
- *
- * The reference to the first generic argument, "!!0", must be explicit otherwise it won't be inflated
- * properly. To get that we need to inflate the MethodBuilder with its own arguments.
- *
- * On the other hand, inflating a non-SRE generic method with its own arguments should
- * return itself. For example:
- *
- * MethodInfo m = ... //m is a generic method definition
- * MethodInfo res = m.MakeGenericMethod (m.GetGenericArguments ());
- * res == m
- *
- * To allow such scenarios we must allow inflation of MethodBuilder to happen in a diferent way than
- * what happens with regular methods.
- *
- * There is one last touch to this madness, once a TypeBuilder is finished, IOW CreateType() is called,
- * everything should behave like a regular type or method.
- *
- */
- is_mb_open = method->is_generic &&
- image_is_dynamic (method->klass->image) && !method->klass->wastypebuilder && /* that is a MethodBuilder from an unfinished TypeBuilder */
- context->method_inst == mono_method_get_generic_container (method)->context.method_inst; /* and it's been instantiated with its own arguments. */
-
iresult = g_new0 (MonoMethodInflated, 1);
iresult->context = *context;
iresult->declaring = method;
- iresult->method.method.is_mb_open = is_mb_open;
if (!context->method_inst && method->is_generic)
iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
if (!iresult->declaring->klass->generic_container && !iresult->declaring->klass->generic_class)
iresult->context.class_inst = NULL;
- cached = mono_method_inflated_lookup (iresult, FALSE);
+ MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
+
+ // check cache
+ mono_image_set_lock (set);
+ cached = g_hash_table_lookup (set->gmethod_cache, iresult);
+ mono_image_set_unlock (set);
+
if (cached) {
g_free (iresult);
return (MonoMethod*)cached;
result->is_generic = FALSE;
result->sre_method = FALSE;
result->signature = NULL;
- result->is_mb_open = is_mb_open;
if (!context->method_inst) {
/* Set the generic_container of the result to the generic_container of method */
* is_generic_method_definition().
*/
- return (MonoMethod*)mono_method_inflated_lookup (iresult, TRUE);
+ // check cache
+ mono_image_set_lock (set);
+ cached = g_hash_table_lookup (set->gmethod_cache, iresult);
+ if (!cached) {
+ g_hash_table_insert (set->gmethod_cache, iresult, iresult);
+ iresult->owner = set;
+ cached = iresult;
+ }
+ mono_image_set_unlock (set);
+
+ return (MonoMethod*)cached;
fail:
g_free (iresult);
mono_error_set_type_load_class (error, class, "Could not find base type");
fail:
- g_assert (!mono_loader_get_last_error ());
+ mono_loader_assert_no_error ();
return NULL;
}
return;
}
- if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)
+ if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (class->image) && !strcmp (class->name_space, "System") && !strcmp (class->name, "ValueType")))
blittable = FALSE;
/* Prevent infinite loops if the class references itself */
return type;
}
+static gboolean
+type_has_references (MonoClass *klass, MonoType *ftype)
+{
+ if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
+ return TRUE;
+ if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
+ MonoGenericParam *gparam = ftype->data.generic_param;
+
+ if (gparam->gshared_constraint)
+ return mono_class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
+ }
+ return FALSE;
+}
+
/*
* mono_class_layout_fields:
* @class: a class
if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
ftype = mono_type_get_underlying_type (field->type);
ftype = mono_type_get_basic_type_from_generic (ftype);
- if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
+ if (type_has_references (class, ftype))
class->has_references = TRUE;
}
}
if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
ftype = mono_type_get_underlying_type (field->type);
ftype = mono_type_get_basic_type_from_generic (ftype);
- if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
+ if (type_has_references (class, ftype))
class->has_static_refs = TRUE;
}
}
ftype = mono_type_get_underlying_type (field->type);
ftype = mono_type_get_basic_type_from_generic (ftype);
- if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
+ if (type_has_references (class, ftype)) {
if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
class->has_static_refs = TRUE;
else
ftype = mono_type_get_underlying_type (field->type);
ftype = mono_type_get_basic_type_from_generic (ftype);
if (gc_aware_layout) {
- if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
+ if (type_has_references (class, ftype)) {
if (pass == 1)
continue;
} else {
/* if the field has managed references, we need to force-align it
* see bug #77788
*/
- if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
+ if (type_has_references (class, ftype))
align = MAX (align, sizeof (gpointer));
class->min_align = MAX (align, class->min_align);
field->offset += sizeof (MonoObject);
ftype = mono_type_get_underlying_type (field->type);
ftype = mono_type_get_basic_type_from_generic (ftype);
- if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
+ if (type_has_references (class, ftype)) {
if (field->offset % sizeof (gpointer)) {
mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
}
if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
/*
+ * This leads to all kinds of problems with nested structs, so only
+ * enable it when a MONO_DEBUG property is set.
+ *
* For small structs, set min_align to at least the struct size to improve
* performance, and since the JIT memset/memcpy code assumes this and generates
* unaligned accesses otherwise. See #78990 for a testcase.
*/
- if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
- class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
+ if (mono_align_small_structs) {
+ if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
+ class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
+ }
}
mono_memory_barrier ();
continue;
if (mono_field_is_deleted (field))
continue;
+ // Special static fields do not need a domain-level static slot
+ if (mono_class_field_is_special_static (field))
+ continue;
if (mono_type_has_exceptions (field->type)) {
mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
* mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
* means we have to overwrite those when called from other places (#4440).
*/
- if (class->interfaces_packed && !overwrite) {
- g_assert (class->interface_offsets_count == interface_offsets_count);
+ if (class->interfaces_packed) {
+ if (!overwrite)
+ g_assert (class->interface_offsets_count == interface_offsets_count);
} else {
uint8_t *bitmap;
int bsize;
}
static gboolean
-check_interface_method_override (MonoClass *class, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty, gboolean security_enabled) {
+check_interface_method_override (MonoClass *class, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
+{
MonoMethodSignature *cmsig, *imsig;
if (strcmp (im->name, cm->name) == 0) {
if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
return FALSE;
}
TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
- /* CAS - SecurityAction.InheritanceDemand on interface */
- if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
- mono_secman_inheritancedemand_method (cm, im);
- }
-
if (mono_security_core_clr_enabled ())
mono_security_core_clr_check_override (class, cm, im);
}
TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
- /* CAS - SecurityAction.InheritanceDemand on interface */
- if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
- mono_secman_inheritancedemand_method (cm, im);
- }
-
if (mono_security_core_clr_enabled ())
mono_security_core_clr_check_override (class, cm, im);
int i, max_vtsize = 0, max_iid, cur_slot = 0;
GPtrArray *ifaces = NULL;
GHashTable *override_map = NULL;
- gboolean security_enabled = mono_security_enabled ();
MonoMethod *cm;
#if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
int first_non_interface_slot;
for (l = virt_methods; l; l = l->next) {
cm = l->data;
TRACE_INTERFACE_VTABLE (printf (" For slot %d ('%s'.'%s':'%s'), trying method '%s'.'%s':'%s'... [EXPLICIT IMPLEMENTATION = %d][SLOT IS NULL = %d]", im_slot, ic->name_space, ic->name, im->name, cm->klass->name_space, cm->klass->name, cm->name, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL)));
- if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
+ if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
vtable [im_slot] = cm;
/* Why do we need this? */
MonoMethod *cm = parent->vtable [cm_index];
TRACE_INTERFACE_VTABLE ((cm != NULL) && printf (" For slot %d ('%s'.'%s':'%s'), trying (ancestor) method '%s'.'%s':'%s'... ", im_slot, ic->name_space, ic->name, im->name, cm->klass->name_space, cm->klass->name, cm->name));
- if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
+ if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE)) {
TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
vtable [im_slot] = cm;
/* Why do we need this? */
if (!strcmp(cm->name, m1->name) &&
mono_metadata_signature_equal (cmsig, m1sig)) {
- /* CAS - SecurityAction.InheritanceDemand */
- if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
- mono_secman_inheritancedemand_method (cm, m1);
- }
-
if (mono_security_core_clr_enabled ())
mono_security_core_clr_check_override (class, cm, m1);
MonoClass *gklass;
int i;
+ if (!method->klass->generic_class) {
+ g_assert (method->is_inflated);
+ return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
+ }
+
/* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
g_assert (method->klass->generic_class);
gklass = method->klass->generic_class->container_class;
}
}
- /* CAS - SecurityAction.InheritanceDemand */
- if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
- mono_secman_inheritancedemand_class (class, class->parent);
- }
-
mono_stats.initialized_class_count++;
if (class->generic_class && !class->generic_class->is_dynamic) {
if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
- g_assert (!mono_loader_get_last_error ());
+ mono_loader_assert_no_error ();
return NULL;
}
if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
mono_loader_unlock ();
- g_assert (!mono_loader_get_last_error ());
+ mono_loader_assert_no_error ();
return class;
}
mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
mono_loader_unlock ();
mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
- g_assert (!mono_loader_get_last_error ());
+ mono_loader_assert_no_error ();
return NULL;
}
}
mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
mono_loader_unlock ();
mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
- g_assert (!mono_loader_get_last_error ());
+ mono_loader_assert_no_error ();
return NULL;
}
class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not load generic parameter constrains due to %s", mono_error_get_message (error)));
mono_loader_unlock ();
mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
- g_assert (!mono_loader_get_last_error ());
+ mono_loader_assert_no_error ();
return NULL;
}
mono_loader_unlock ();
mono_profiler_class_loaded (class, MONO_PROFILE_OK);
- g_assert (!mono_loader_get_last_error ());
+ mono_loader_assert_no_error ();
return class;
mono_class_setup_mono_type (class);
mono_loader_unlock ();
mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
- g_assert (!mono_loader_get_last_error ());
+ mono_loader_assert_no_error ();
return NULL;
}
MonoType *inflated = inflate_generic_type (NULL, t, context, error);
if (!mono_error_ok (error)) {
- g_assert (!mono_loader_get_last_error ());
+ mono_loader_assert_no_error ();
return NULL;
}
MonoClass *class = mono_class_get_checked (image, type_token, error);
if (!class) {
- g_assert (!mono_loader_get_last_error ());
+ mono_loader_assert_no_error ();
return NULL;
}
type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
if (!type) {
- g_assert (!mono_loader_get_last_error ());
+ mono_loader_assert_no_error ();
return NULL;
}
const char *name;
const char *nspace;
guint32 i, visib, nspace_index;
- GHashTable *name_cache2, *nspace_table;
+ GHashTable *name_cache2, *nspace_table, *the_name_cache;
- mono_image_lock (image);
-
- if (image->name_cache) {
- mono_image_unlock (image);
+ if (image->name_cache)
return;
- }
- image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
+ the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
if (image_is_dynamic (image)) {
+ mono_image_lock (image);
+ if (image->name_cache) {
+ /* Somebody initialized it before us */
+ g_hash_table_destroy (the_name_cache);
+ } else {
+ mono_atomic_store_release (&image->name_cache, the_name_cache);
+ }
mono_image_unlock (image);
return;
}
nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
if (!nspace_table) {
nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
- g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
+ g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
nspace_table);
}
nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
if (!nspace_table) {
nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
- g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
+ g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
nspace_table);
}
}
g_hash_table_destroy (name_cache2);
+
+ mono_image_lock (image);
+ if (image->name_cache) {
+ /* Somebody initialized it before us */
+ g_hash_table_destroy (the_name_cache);
+ } else {
+ mono_atomic_store_release (&image->name_cache, the_name_cache);
+ }
mono_image_unlock (image);
}
GHashTable *name_cache;
guint32 old_index;
+ mono_image_init_name_cache (image);
mono_image_lock (image);
- if (!image->name_cache)
- mono_image_init_name_cache (image);
-
name_cache = image->name_cache;
if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
guint32 token = 0;
FindUserData user_data;
+ mono_image_init_name_cache (image);
mono_image_lock (image);
- if (!image->name_cache)
- mono_image_init_name_cache (image);
-
user_data.key = name_space;
user_data.value = NULL;
g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
return NULL;
}
-MonoClass *
-mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
+static MonoClass *
+mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, MonoError *error, GHashTable* visited_images)
{
GHashTable *nspace_table;
MonoImage *loaded_image;
mono_error_init (error);
+ // Checking visited images avoids stack overflows when cyclic references exist.
+ if (g_hash_table_lookup (visited_images, image))
+ return NULL;
+
+ g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
+
if ((nested = strchr (name, '/'))) {
int pos = nested - name;
int len = strlen (name);
}
}
+ mono_image_init_name_cache (image);
mono_image_lock (image);
- if (!image->name_cache)
- mono_image_init_name_cache (image);
-
nspace_table = g_hash_table_lookup (image->name_cache, name_space);
if (nspace_table)
loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
if (!loaded_image)
return NULL;
- class = mono_class_from_name (loaded_image, name_space, name);
+ class = mono_class_from_name_checked_aux (loaded_image, name_space, name, error, visited_images);
if (nested)
return return_nested_in (class, nested);
return class;
if (image->references [assembly_idx - 1] == (gpointer)-1)
return NULL;
else
- /* FIXME: Cycle detection */
- return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
+ return mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, error, visited_images);
} else {
g_error ("not yet implemented");
}
return class;
}
+MonoClass *
+mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
+{
+ MonoClass *klass;
+ GHashTable *visited_images;
+
+ visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ klass = mono_class_from_name_checked_aux (image, name_space, name, error, visited_images);
+
+ g_hash_table_destroy (visited_images);
+
+ return klass;
+}
+
/**
* mono_class_from_name:
* @image: The MonoImage where the type is looked up in
gpointer exception_data = mono_class_get_exception_data (klass);
switch (klass->exception_type) {
-#ifndef DISABLE_SECURITY
- case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
- MonoDomain *domain = mono_domain_get ();
- MonoSecurityManager* secman = mono_security_manager_get_methods ();
- MonoMethod *method = exception_data;
- guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
- MonoObject *exc = NULL;
- gpointer args [4];
-
- args [0] = &error;
- args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
- args [2] = mono_type_get_object (domain, &klass->byval_arg);
- args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
-
- mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
- return (MonoException*) exc;
- }
-#endif
case MONO_EXCEPTION_TYPE_LOAD: {
MonoString *name;
MonoException *ex;