*
* Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
* Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
*/
#include <config.h>
#ifdef HAVE_ALLOCA_H
#include <mono/utils/mono-string.h>
#include <mono/utils/mono-error-internals.h>
#include <mono/utils/mono-logger-internal.h>
+#include <mono/utils/mono-memory-model.h>
MonoStats mono_stats;
gboolean mono_print_vtable = FALSE;
static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
static guint32 mono_field_resolve_flags (MonoClassField *field);
static void mono_class_setup_vtable_full (MonoClass *class, GList *in_setup);
+static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
void (*mono_debugger_class_init_func) (MonoClass *klass) = NULL;
void (*mono_debugger_class_loaded_methods_func) (MonoClass *klass) = NULL;
+
+/*
+We use gclass recording to allow recursive system f types to be referenced by a parent.
+
+Given the following type hierarchy:
+
+class TextBox : TextBoxBase<TextBox> {}
+class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
+class TextInput<T> : Input<T> where T: TextInput<T> {}
+class Input<T> {}
+
+The runtime tries to load TextBoxBase<>.
+To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
+To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
+To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
+
+At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
+at this point, iow, both are registered in the type map and both and a NULL parent. This means
+that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
+
+To fix that what we do is to record all generic instantes created while resolving the parent of
+any generic type definition and, after resolved, correct the parent field if needed.
+
+*/
+static int record_gclass_instantiation;
+static GSList *gclass_recorded_list;
+typedef gboolean (*gclass_record_func) (MonoClass*, void*);
+
+/*
+ * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
+*/
+static void
+enable_gclass_recording (void)
+{
+ ++record_gclass_instantiation;
+}
+
+/*
+ * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
+*/
+static void
+disable_gclass_recording (gclass_record_func func, void *user_data)
+{
+ GSList **head = &gclass_recorded_list;
+
+ g_assert (record_gclass_instantiation > 0);
+ --record_gclass_instantiation;
+
+ while (*head) {
+ GSList *node = *head;
+ if (func ((MonoClass*)node->data, user_data)) {
+ *head = node->next;
+ g_slist_free_1 (node);
+ } else {
+ head = &node->next;
+ }
+ }
+
+ /* We automatically discard all recorded gclasses when disabled. */
+ if (!record_gclass_instantiation && gclass_recorded_list) {
+ g_slist_free (gclass_recorded_list);
+ gclass_recorded_list = NULL;
+ }
+}
+
/*
* mono_class_from_typeref:
* @image: a MonoImage
}
}
+/*
+This is a simple function to catch the most common bad instances of generic types.
+Specially those that might lead to further failures in the runtime.
+*/
+static gboolean
+is_valid_generic_argument (MonoType *type)
+{
+ switch (type->type) {
+ case MONO_TYPE_VOID:
+ //case MONO_TYPE_TYPEDBYREF:
+ return FALSE;
+ }
+ return TRUE;
+}
+
static MonoType*
inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
{
return NULL;
}
+ if (!is_valid_generic_argument (inst->type_argv [num])) {
+ MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
+ mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
+ num, info ? info->name : "", inst->type_argv [num]->type);
+ return NULL;
+ }
/*
* Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
* while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
num, info ? info->name : "", inst->type_argc);
return NULL;
}
+ if (!is_valid_generic_argument (inst->type_argv [num])) {
+ MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
+ mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
+ num, info ? info->name : "", inst->type_argv [num]->type);
+ return NULL;
+ }
nt = mono_metadata_type_dup (image, inst->type_argv [num]);
nt->byref = type->byref;
nt->attrs = type->attrs;
MonoGenericContainer *container = NULL;
MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
- if (class->size_inited)
+ if (class->setup_fields_called)
return;
if (class->generic_class && class->generic_class->container_class->image->dynamic && !class->generic_class->container_class->wastypebuilder) {
explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
if (explicit_size) {
- g_assert ((packing_size & 0xfffffff0) == 0);
+ if ((packing_size & 0xfffffff0) != 0) {
+ char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", class->name, packing_size);
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
+ return;
+ }
class->packing_size = packing_size;
real_size += class->instance_size;
}
if (explicit_size && real_size) {
class->instance_size = MAX (real_size, class->instance_size);
}
- class->size_inited = 1;
class->blittable = blittable;
+ mono_memory_barrier ();
+ class->size_inited = 1;
+ class->fields_inited = 1;
return;
}
blittable = FALSE;
/* Prevent infinite loops if the class references itself */
- class->size_inited = 1;
+ class->setup_fields_called = 1;
if (class->generic_container) {
container = class->generic_container;
/*valuetypes can't be neither bigger than 1Mb or empty. */
if (class->valuetype && (class->instance_size <= 0 || class->instance_size > (0x100000 + sizeof (MonoObject))))
mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+
+ mono_memory_barrier ();
+ class->fields_inited = 1;
}
/**
* Initializes the class->fields array of fields.
* Aquires the loader lock.
*/
-static void
+void
mono_class_setup_fields_locking (MonoClass *class)
{
+ /* This can be checked without locks */
+ if (class->fields_inited)
+ return;
mono_loader_lock ();
mono_class_setup_fields (class);
mono_loader_unlock ();
*/
/* corlib is missing [StructLayout] directives in many places */
if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
- if (class->byval_arg.type != MONO_TYPE_VALUETYPE)
+ if (!class->valuetype)
gc_aware_layout = TRUE;
}
continue;
size = mono_type_size (field->type, &align);
+ align = class->packing_size ? MIN (class->packing_size, align): align;
class->min_align = MAX (align, class->min_align);
/*
real_size = MAX (real_size, size + field->offset);
}
class->instance_size = MAX (real_size, class->instance_size);
+ if (class->instance_size & (class->min_align - 1)) {
+ class->instance_size += class->min_align - 1;
+ class->instance_size &= ~(class->min_align - 1);
+ }
break;
}
class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
}
+ mono_memory_barrier ();
class->size_inited = 1;
/*
void
mono_unload_interface_id (MonoClass *class)
{
- if (class->interface_id) {
+ if (global_interface_bitset && class->interface_id) {
mono_loader_lock ();
mono_bitset_clear (global_interface_bitset, class->interface_id);
mono_loader_unlock ();
static MonoClass* generic_icollection_class = NULL;
static MonoClass* generic_ienumerable_class = NULL;
static MonoClass* generic_ienumerator_class = NULL;
+ static MonoClass* generic_ireadonlylist_class = NULL;
+ static MonoClass* generic_ireadonlycollection_class = NULL;
MonoClass *valuetype_types[2] = { NULL, NULL };
MonoClass **interfaces = NULL;
- int i, interface_count, real_count, original_rank;
+ int i, nifaces, interface_count, real_count, original_rank;
int all_interfaces;
gboolean internal_enumerator;
gboolean eclass_is_valuetype;
*/
eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
original_rank = eclass->rank;
- eclass = eclass->element_class;
+ if (!eclass->rank)
+ eclass = eclass->element_class;
internal_enumerator = TRUE;
*is_enumerator = TRUE;
} else {
"System.Collections.Generic", "IEnumerable`1");
generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
"System.Collections.Generic", "IEnumerator`1");
+ generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
+ "System.Collections.Generic", "IReadOnlyList`1");
+ generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
+ "System.Collections.Generic", "IReadOnlyCollection`1");
}
mono_class_init (eclass);
/*
* Arrays in 2.0 need to implement a number of generic interfaces
* (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
- * on the element class). We collect the types needed to build the
- * instantiations in interfaces at intervals of 3, because 3 are
+ * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
+ * We collect the types needed to build the
+ * instantiations in interfaces at intervals of 3/5, because 3/5 are
* the generic interfaces needed to implement.
*/
+ nifaces = generic_ireadonlylist_class ? 5 : 3;
if (eclass->valuetype) {
fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
- /* IList, ICollection, IEnumerable */
- real_count = interface_count = valuetype_types [1] ? 6 : 3;
+ /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
+ real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
if (internal_enumerator) {
++real_count;
if (valuetype_types [1])
interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
interfaces [0] = valuetype_types [0];
if (valuetype_types [1])
- interfaces [3] = valuetype_types [1];
+ interfaces [nifaces] = valuetype_types [1];
eclass_is_valuetype = TRUE;
} else {
if (valuetype_types [1])
++interface_count;
}
- /* IList, ICollection, IEnumerable */
- interface_count *= 3;
+ /* IList, ICollection, IEnumerable, IReadOnlyList */
+ interface_count *= nifaces;
real_count = interface_count;
if (internal_enumerator) {
real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
if (MONO_CLASS_IS_INTERFACE (eclass)) {
interfaces [0] = mono_defaults.object_class;
- j = 3;
+ j = nifaces;
} else {
j = 0;
for (i = 0; i < idepth; i++) {
mono_class_init (eclass->supertypes [i]);
interfaces [j] = eclass->supertypes [i];
- j += 3;
+ j += nifaces;
}
}
if (all_interfaces) {
for (i = 0; i < eclass->interface_offsets_count; i++) {
interfaces [j] = eclass->interfaces_packed [i];
- j += 3;
+ j += nifaces;
}
} else {
for (i = 0; i < eclass->interface_count; i++) {
interfaces [j] = eclass->interfaces [i];
- j += 3;
+ j += nifaces;
}
}
if (valuetype_types [1]) {
interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
- j += 3;
+ j += nifaces;
}
}
/* instantiate the generic interfaces */
- for (i = 0; i < interface_count; i += 3) {
+ for (i = 0; i < interface_count; i += nifaces) {
MonoClass *iface = interfaces [i];
interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
+ if (generic_ireadonlylist_class) {
+ interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
+ interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
+ }
}
if (internal_enumerator) {
int j;
* Return -1 on failure and set exception_type
*/
static int
-setup_interface_offsets (MonoClass *class, int cur_slot)
+setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
{
MonoError error;
MonoClass *k, *ic;
/*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, interface_offsets_full [ic->interface_id], class->interfaces [0]->name);*/
}
} else {
- int ilist_offset, icollection_offset, ienumerable_offset;
+ int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
int ilist_iface_idx = find_array_interface (class, "IList`1");
MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
+ int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
+ MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
+ int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
+ ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
+ ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
for (i = 0; i < num_array_interfaces; ++i) {
int offset;
offset = icollection_offset;
else if (strcmp (ic->name, "IEnumerable`1") == 0)
offset = ienumerable_offset;
+ else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
+ offset = ireadonlylist_offset;
+ else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
+ offset = ireadonlycollection_offset;
else
g_assert_not_reached ();
set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
}
/*
- * We might get called twice: once from mono_class_init () then once from
- * mono_class_setup_vtable ().
+ * We might get called multiple times:
+ * - mono_class_init ()
+ * - mono_class_setup_vtable ().
+ * - mono_class_setup_interface_offsets ().
+ * 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) {
+ if (class->interfaces_packed && !overwrite) {
g_assert (class->interface_offsets_count == interface_offsets_count);
} else {
uint8_t *bitmap;
{
mono_loader_lock ();
- setup_interface_offsets (class, 0);
+ setup_interface_offsets (class, 0, FALSE);
mono_loader_unlock ();
}
TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
return FALSE;
}
- if ((ic_name == NULL) || ((strcmp (ic_name, "IEnumerable`1") != 0) && (strcmp (ic_name, "ICollection`1") != 0) && (strcmp (ic_name, "IList`1") != 0))) {
+ if ((ic_name == NULL) || ((strcmp (ic_name, "IEnumerable`1") != 0) && (strcmp (ic_name, "ICollection`1") != 0) && (strcmp (ic_name, "IList`1") != 0) && (strcmp (ic_name, "IReadOnlyList`1") != 0) && (strcmp (ic_name, "IReadOnlyCollection`1") != 0))) {
TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
return FALSE;
}
/* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
- cur_slot = setup_interface_offsets (class, cur_slot);
+ cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
return;
mono_class_setup_vtable (method->klass);
if (method->klass->exception_type)
return -1;
+ if (method->slot == -1) {
+ MonoClass *gklass;
+ int i;
+
+ /* 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;
+ mono_class_setup_methods (method->klass);
+ g_assert (method->klass->methods);
+ for (i = 0; i < method->klass->method.count; ++i) {
+ if (method->klass->methods [i] == method)
+ break;
+ }
+ g_assert (i < method->klass->method.count);
+ g_assert (gklass->methods);
+ method->slot = gklass->methods [i]->slot;
+ }
g_assert (method->slot != -1);
}
return method->slot;
const char *mname, *iname;
gchar *name;
MonoMethod *m = tmp->data;
+ const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
+ const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
+
generic_array_method_info [i].array_method = m;
if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
iname = "System.Collections.Generic.ICollection`1.";
} else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
iname = "System.Collections.Generic.IEnumerable`1.";
mname = m->name + 27;
+ } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
+ iname = "System.Collections.Generic.IReadOnlyList`1.";
+ mname = m->name + strlen (ireadonlylist_prefix);
+ } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
+ iname = "System.Collections.Generic.IReadOnlyCollection`1.";
+ mname = m->name + strlen (ireadonlycollection_prefix);
} else if (!strncmp (m->name, "InternalArray__", 15)) {
iname = "System.Collections.Generic.IList`1.";
mname = m->name + 15;
first_iface_slot = class->parent->vtable_size;
if (mono_class_need_stelemref_method (class))
++first_iface_slot;
- setup_interface_offsets (class, first_iface_slot);
+ setup_interface_offsets (class, first_iface_slot, TRUE);
} else {
- setup_interface_offsets (class, 0);
+ setup_interface_offsets (class, 0, TRUE);
}
if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
}
+#ifndef DISABLE_COM
/*
* COM initialization (using mono_init_com_types) is delayed until needed.
* However when a [ComImport] attribute is present on a type it will trigger
/* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
mono_init_com_types ();
}
+#endif /*DISABLE_COM*/
/*
* LOCKING: this assumes the loader lock is held
if (!MONO_CLASS_IS_INTERFACE (class)) {
/* Imported COM Objects always derive from __ComObject. */
+#ifndef DISABLE_COM
if (MONO_CLASS_IS_IMPORT (class)) {
init_com_from_comimport (class);
if (parent == mono_defaults.object_class)
parent = mono_defaults.com_object_class;
}
+#endif
if (!parent) {
/* set the parent to something useful and safe, but mark the type as broken */
parent = mono_defaults.object_class;
class->valuetype = class->enumtype = 1;
}
/*class->enumtype = class->parent->enumtype; */
- mono_class_setup_supertypes (class);
} else {
/* initialize com types if COM interfaces are present */
+#ifndef DISABLE_COM
if (MONO_CLASS_IS_IMPORT (class))
init_com_from_comimport (class);
+#endif
class->parent = NULL;
}
mono_class_setup_supertypes (MonoClass *class)
{
int ms;
+ MonoClass **supertypes;
if (class->supertypes)
return;
class->idepth = 1;
ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
- class->supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
+ supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
if (class->parent) {
- class->supertypes [class->idepth - 1] = class;
- memcpy (class->supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
+ supertypes [class->idepth - 1] = class;
+ memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
} else {
- class->supertypes [0] = class;
+ supertypes [0] = class;
}
+
+ mono_atomic_store_release (&class->supertypes, supertypes);
+}
+
+static gboolean
+fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
+{
+ MonoClass *gtd = (MonoClass*)user_data;
+ /* Only try to fix generic instances of @gtd */
+ if (gclass->generic_class->container_class != gtd)
+ return FALSE;
+
+ /* Check if the generic instance has no parent. */
+ if (gtd->parent && !gclass->parent)
+ mono_generic_class_setup_parent (gclass, gtd);
+
+ return TRUE;
}
/**
context = &class->generic_container->context;
}
+ if (class->generic_container)
+ enable_gclass_recording ();
+
if (cols [MONO_TYPEDEF_EXTENDS]) {
MonoClass *tmp;
guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
/* uses ->valuetype, which is initialized by mono_class_setup_parent above */
mono_class_setup_mono_type (class);
+ if (class->generic_container)
+ disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
+
/*
* This might access class->byval_arg for recursion generated by generic constraints,
* so it has to come after setup_mono_type ().
return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
}
+static void
+mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
+{
+ if (gtd->parent) {
+ MonoError error;
+ MonoGenericClass *gclass = klass->generic_class;
+
+ klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
+ if (!mono_error_ok (&error)) {
+ /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
+ klass->parent = mono_defaults.object_class;
+ mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
+ mono_error_cleanup (&error);
+ }
+ }
+ if (klass->parent)
+ mono_class_setup_parent (klass, klass->parent);
+
+ if (klass->enumtype) {
+ klass->cast_class = gtd->cast_class;
+ klass->element_class = gtd->element_class;
+ }
+}
+
+
/*
* Create the `MonoClass' for an instantiation of a generic type.
* We only do this if we actually need it.
gklass = gclass->container_class;
+ if (record_gclass_instantiation > 0)
+ gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
+
if (gklass->nested_in) {
/* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
klass->nested_in = gklass->nested_in;
* We use the generic type definition to look for nested classes.
*/
- if (gklass->parent) {
- MonoError error;
- klass->parent = mono_class_inflate_generic_class_checked (gklass->parent, mono_generic_class_get_context (gclass), &error);
- if (!mono_error_ok (&error)) {
- /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
- klass->parent = mono_defaults.object_class;
- mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
- mono_error_cleanup (&error);
- }
- }
-
- if (klass->parent)
- mono_class_setup_parent (klass, klass->parent);
-
- if (klass->enumtype) {
- klass->cast_class = gklass->cast_class;
- klass->element_class = gklass->element_class;
- }
+ mono_generic_class_setup_parent (klass, gklass);
if (gclass->is_dynamic) {
klass->inited = 1;
*/
klass->instance_size = gklass->instance_size;
klass->sizes.class_size = gklass->sizes.class_size;
+ mono_memory_barrier ();
klass->size_inited = 1;
}
}
/*Init these fields to sane values*/
klass->min_align = 1;
klass->instance_size = sizeof (gpointer);
+ mono_memory_barrier ();
klass->size_inited = 1;
mono_class_setup_supertypes (klass);
if (klass->parent->exception_type)
mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
else
- setup_interface_offsets (klass, klass->parent->vtable_size);
+ setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
}
return klass;
static MonoClass *
get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar)
{
- int n = mono_generic_param_num (param);
+ int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
MonoImage *image = param->image;
GHashTable *ht;
static void
set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
{
- int n = mono_generic_param_num (param);
+ int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
MonoImage *image = param->image;
GHashTable *ht;
mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
gboolean check_interfaces)
{
- g_assert (klassc->idepth > 0);
if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
return TRUE;
if (target == mono_defaults.object_class)
return TRUE;
- /*setup_supertypes don't mono_class_init anything */
- mono_class_setup_supertypes (candidate);
- mono_class_setup_supertypes (target);
-
if (mono_class_has_parent (candidate, target))
return TRUE;
{
if (global_interface_bitset)
mono_bitset_free (global_interface_bitset);
+ global_interface_bitset = NULL;
}
/**
int i;
klass = mono_class_get_generic_type_definition (klass);
parent = mono_class_get_generic_type_definition (parent);
-
+ mono_class_setup_supertypes (klass);
+
for (i = 0; i < klass->idepth; ++i) {
if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
return TRUE;
return;
}
- if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY && mono_defaults.generic_ilist_class) {
+ if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
MonoType *args [1];
/* generic IList, ICollection, IEnumerable */
- klass->interface_count = 1;
+ klass->interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
klass->interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * klass->interface_count);
args [0] = &klass->element_class->byval_arg;
klass->interfaces [0] = mono_class_bind_generic_parameters (
mono_defaults.generic_ilist_class, 1, args, FALSE);
+ if (klass->interface_count > 1)
+ klass->interfaces [1] = mono_class_bind_generic_parameters (
+ mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
} else if (klass->generic_class) {
MonoClass *gklass = klass->generic_class->container_class;
g_assert (*sig == 0x06);
field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
if (!field->type) {
+ MonoLoaderError *lerror = mono_loader_get_last_error ();
+
mono_error_set_type_load_class (error, class, "Could not load field %s type", field->name);
- mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+ if (lerror)
+ set_failure_from_loader_error (class, lerror);
+ else
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
mono_loader_clear_error ();
}
}
}
return NULL;
}
+
+char*
+mono_class_full_name (MonoClass *klass)
+{
+ return mono_type_full_name (&klass->byval_arg);
+}
+