#include <mono/metadata/assembly.h>
#include <mono/metadata/metadata.h>
#include <mono/metadata/metadata-internals.h>
+#include <mono/metadata/profiler-private.h>
#include <mono/metadata/tabledefs.h>
#include <mono/metadata/tokentype.h>
#include <mono/metadata/class-internals.h>
/* We can't use context->class_inst directly, since it can have more elements */
inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context);
+ if (inst == container->context.class_inst)
+ return NULL;
+
gclass = mono_metadata_lookup_generic_class (klass, inst, klass->image->dynamic);
nt = mono_metadata_type_dup (NULL, type);
for (i = 0; i < class->method.count; ++i) {
int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | idx, class);
+ if (class->valuetype && methods [i]->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED && !(methods [i]->flags & MONO_METHOD_ATTR_STATIC))
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
}
}
}
}
+/* this won't be needed once bug #325495 is completely fixed
+ * though we'll need something similar to know which interfaces to allow
+ * in arrays when they'll be lazyly created
+ */
+static MonoClass**
+get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
+{
+ MonoClass *eclass = class->element_class;
+ static MonoClass* generic_icollection_class = NULL;
+ static MonoClass* generic_ienumerable_class = NULL;
+ static MonoClass* generic_ienumerator_class = NULL;
+ MonoClass *fclass = NULL;
+ MonoClass **interfaces = NULL;
+ int i, interface_count, real_count;
+ int all_interfaces;
+ gboolean internal_enumerator;
+ gboolean eclass_is_valuetype;
+
+ if (!mono_defaults.generic_ilist_class) {
+ *num = 0;
+ return NULL;
+ }
+ internal_enumerator = FALSE;
+ eclass_is_valuetype = FALSE;
+ if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
+ if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
+ /*
+ * For a Enumerator<T[]> we need to get the list of interfaces for T.
+ */
+ eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
+ eclass = eclass->element_class;
+ internal_enumerator = TRUE;
+ *is_enumerator = TRUE;
+ } else {
+ *num = 0;
+ return NULL;
+ }
+ }
+
+ /*
+ * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
+ * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
+ */
+ all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
+
+ if (!generic_icollection_class) {
+ generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
+ "System.Collections.Generic", "ICollection`1");
+ generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
+ "System.Collections.Generic", "IEnumerable`1");
+ generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
+ "System.Collections.Generic", "IEnumerator`1");
+ }
+
+ /*
+ * 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
+ * the generic interfaces needed to implement.
+ */
+ if (eclass->valuetype) {
+ if (eclass == mono_defaults.int16_class)
+ fclass = mono_defaults.uint16_class;
+ else if (eclass == mono_defaults.uint16_class)
+ fclass = mono_defaults.int16_class;
+ else if (eclass == mono_defaults.int32_class)
+ fclass = mono_defaults.uint32_class;
+ else if (eclass == mono_defaults.uint32_class)
+ fclass = mono_defaults.int32_class;
+ else if (eclass == mono_defaults.int64_class)
+ fclass = mono_defaults.uint64_class;
+ else if (eclass == mono_defaults.uint64_class)
+ fclass = mono_defaults.int64_class;
+ else if (eclass == mono_defaults.byte_class)
+ fclass = mono_defaults.sbyte_class;
+ else if (eclass == mono_defaults.sbyte_class)
+ fclass = mono_defaults.byte_class;
+ else {
+ /* No additional interfaces for other value types */
+ *num = 0;
+ return NULL;
+ }
+
+ /* IList, ICollection, IEnumerable */
+ real_count = interface_count = 3;
+ interfaces = g_malloc0 (sizeof (MonoClass*) * interface_count);
+ interfaces [0] = fclass;
+ eclass_is_valuetype = TRUE;
+ } else {
+ int j;
+ int idepth = eclass->idepth;
+ if (!internal_enumerator)
+ idepth--;
+ interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
+ /* we add object for interfaces and the supertypes for the other
+ * types. The last of the supertypes is the element class itself which we
+ * already created the explicit interfaces for (so we include it for IEnumerator
+ * and exclude it for arrays).
+ */
+ if (MONO_CLASS_IS_INTERFACE (eclass))
+ interface_count++;
+ else
+ interface_count += idepth;
+ /* IList, ICollection, IEnumerable */
+ interface_count *= 3;
+ real_count = interface_count;
+ if (internal_enumerator)
+ real_count += idepth;
+ interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
+ if (MONO_CLASS_IS_INTERFACE (eclass)) {
+ interfaces [0] = mono_defaults.object_class;
+ j = 3;
+ } else {
+ j = 0;
+ for (i = 0; i < idepth; i++) {
+ mono_class_init (eclass->supertypes [i]);
+ interfaces [j] = eclass->supertypes [i];
+ j += 3;
+ }
+ }
+ if (all_interfaces) {
+ for (i = 0; i < eclass->interface_offsets_count; i++) {
+ interfaces [j] = eclass->interfaces_packed [i];
+ j += 3;
+ }
+ } else {
+ for (i = 0; i < eclass->interface_count; i++) {
+ interfaces [j] = eclass->interfaces [i];
+ j += 3;
+ }
+ }
+ }
+
+ /* instantiate the generic interfaces */
+ for (i = 0; i < interface_count; i += 3) {
+ MonoType *args [1];
+ MonoClass *iface = interfaces [i];
+
+ args [0] = &iface->byval_arg;
+ interfaces [i] = mono_class_bind_generic_parameters (
+ mono_defaults.generic_ilist_class, 1, args, FALSE);
+ //g_print ("%s implements %s\n", class->name, mono_type_get_name_full (&interfaces [i]->byval_arg, 0));
+ args [0] = &iface->byval_arg;
+ interfaces [i + 1] = mono_class_bind_generic_parameters (
+ generic_icollection_class, 1, args, FALSE);
+ args [0] = &iface->byval_arg;
+ interfaces [i + 2] = mono_class_bind_generic_parameters (
+ generic_ienumerable_class, 1, args, FALSE);
+ //g_print ("%s implements %s\n", class->name, mono_type_get_name_full (&interfaces [i + 1]->byval_arg, 0));
+ //g_print ("%s implements %s\n", class->name, mono_type_get_name_full (&interfaces [i + 2]->byval_arg, 0));
+ }
+ if (internal_enumerator) {
+ int j;
+ /* instantiate IEnumerator<iface> */
+ for (i = 0; i < interface_count; i++) {
+ MonoType *args [1];
+ MonoClass *iface = interfaces [i];
+
+ args [0] = &iface->byval_arg;
+ interfaces [i] = mono_class_bind_generic_parameters (
+ generic_ienumerator_class, 1, args, FALSE);
+ /*g_print ("%s implements %s\n", class->name, mono_type_get_name_full (&interfaces [i]->byval_arg, 0));*/
+ }
+ if (!eclass_is_valuetype) {
+ j = interface_count;
+ for (i = 0; i < eclass->idepth; i++) {
+ MonoType *args [1];
+ args [0] = &eclass->supertypes [i]->byval_arg;
+ interfaces [j] = mono_class_bind_generic_parameters (
+ generic_ienumerator_class, 1, args, FALSE);
+ /*g_print ("%s implements %s\n", class->name, mono_type_get_name_full (&interfaces [i]->byval_arg, 0));*/
+ j ++;
+ }
+ }
+ }
+ *num = real_count;
+ return interfaces;
+}
+
/*
* LOCKING: this is supposed to be called with the loader lock held.
*/
int *interface_offsets_full;
GPtrArray *ifaces;
int interface_offsets_count;
+ MonoClass **array_interfaces;
+ int num_array_interfaces;
+ int is_enumerator = FALSE;
+
+ /*
+ * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
+ * implicit innterfaces have the property that they are assigned the same slot in the vtables
+ * for compatible interfaces
+ */
+ array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
/* compute maximum number of slots and maximum interface id */
max_iid = 0;
g_ptr_array_free (ifaces, TRUE);
}
}
+ for (i = 0; i < num_array_interfaces; ++i) {
+ ic = array_interfaces [i];
+ mono_class_init (ic);
+ if (max_iid < ic->interface_id)
+ max_iid = ic->interface_id;
+ }
if (MONO_CLASS_IS_INTERFACE (class)) {
if (max_iid < class->interface_id)
interface_offsets_full [class->interface_id] = cur_slot;
}
+ if (num_array_interfaces) {
+ if (is_enumerator) {
+ int ienumerator_offset;
+ g_assert (strcmp (class->interfaces [0]->name, "IEnumerator`1") == 0);
+ ienumerator_offset = interface_offsets_full [class->interfaces [0]->interface_id];
+ for (i = 0; i < num_array_interfaces; ++i) {
+ ic = array_interfaces [i];
+ interfaces_full [ic->interface_id] = ic;
+ if (strcmp (ic->name, "IEnumerator`1") == 0)
+ interface_offsets_full [ic->interface_id] = ienumerator_offset;
+ else
+ g_assert_not_reached ();
+ /*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;
+ g_assert (strcmp (class->interfaces [0]->name, "IList`1") == 0);
+ g_assert (strcmp (class->interfaces [0]->interfaces [0]->name, "ICollection`1") == 0);
+ g_assert (strcmp (class->interfaces [0]->interfaces [1]->name, "IEnumerable`1") == 0);
+ ilist_offset = interface_offsets_full [class->interfaces [0]->interface_id];
+ icollection_offset = interface_offsets_full [class->interfaces [0]->interfaces [0]->interface_id];
+ ienumerable_offset = interface_offsets_full [class->interfaces [0]->interfaces [1]->interface_id];
+ g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
+ for (i = 0; i < num_array_interfaces; ++i) {
+ ic = array_interfaces [i];
+ interfaces_full [ic->interface_id] = ic;
+ if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
+ interface_offsets_full [ic->interface_id] = ilist_offset;
+ else if (strcmp (ic->name, "ICollection`1") == 0)
+ interface_offsets_full [ic->interface_id] = icollection_offset;
+ else if (strcmp (ic->name, "IEnumerable`1") == 0)
+ interface_offsets_full [ic->interface_id] = ienumerable_offset;
+ else
+ g_assert_not_reached ();
+ /*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);*/
+ }
+ }
+ }
+
for (interface_offsets_count = 0, i = 0; i <= max_iid; i++) {
if (interface_offsets_full [i] != -1) {
interface_offsets_count ++;
class->interface_bitmap [i >> 3] |= (1 << (i & 7));
class->interfaces_packed [interface_offsets_count] = interfaces_full [i];
class->interface_offsets_packed [interface_offsets_count] = interface_offsets_full [i];
+ /*if (num_array_interfaces)
+ g_print ("type %s has %s offset at %d\n", mono_type_get_name_full (&class->byval_arg, 0), mono_type_get_name_full (&interfaces_full [i]->byval_arg, 0), interface_offsets_full [i]);*/
interface_offsets_count ++;
}
}
g_free (interfaces_full);
g_free (interface_offsets_full);
+ g_free (array_interfaces);
//printf ("JUST DONE: ");
//print_implemented_interfaces (class);
return n;
}
-static void
-setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, int pos)
-{
- MonoGenericContext tmp_context;
- int i;
+typedef struct {
+ MonoMethod *array_method;
+ char *name;
+} GenericArrayMethodInfo;
- tmp_context.class_inst = NULL;
- tmp_context.method_inst = iface->generic_class->context.class_inst;
+static int generic_array_method_num = 0;
+static GenericArrayMethodInfo *generic_array_method_info = NULL;
+static int
+generic_array_methods (MonoClass *class)
+{
+ int i, count_generic = 0;
+ GList *list = NULL, *tmp;
+ if (generic_array_method_num)
+ return generic_array_method_num;
for (i = 0; i < class->parent->method.count; i++) {
MonoMethod *m = class->parent->methods [i];
- MonoMethod *inflated;
+ if (!strncmp (m->name, "InternalArray__", 15)) {
+ count_generic++;
+ list = g_list_prepend (list, m);
+ }
+ }
+ list = g_list_reverse (list);
+ generic_array_method_info = g_malloc (sizeof (GenericArrayMethodInfo) * count_generic);
+ i = 0;
+ for (tmp = list; tmp; tmp = tmp->next) {
const char *mname, *iname;
gchar *name;
-
+ MonoMethod *m = tmp->data;
+ generic_array_method_info [i].array_method = m;
if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
iname = "System.Collections.Generic.ICollection`1.";
mname = m->name + 27;
iname = "System.Collections.Generic.IList`1.";
mname = m->name + 15;
} else {
- continue;
+ g_assert_not_reached ();
}
- name = mono_mempool_alloc (class->image->mempool, strlen (iname) + strlen (mname) + 1);
+ name = mono_mempool_alloc (mono_defaults.corlib->mempool, strlen (iname) + strlen (mname) + 1);
strcpy (name, iname);
strcpy (name + strlen (iname), mname);
+ generic_array_method_info [i].name = name;
+ i++;
+ }
+ /*g_print ("array generic methods: %d\n", count_generic);*/
+
+ generic_array_method_num = count_generic;
+ return generic_array_method_num;
+}
+
+static void
+setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, int pos)
+{
+ MonoGenericContext tmp_context;
+ int i;
+
+ tmp_context.class_inst = NULL;
+ tmp_context.method_inst = iface->generic_class->context.class_inst;
+ //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
+
+ for (i = 0; i < generic_array_method_num; i++) {
+ MonoMethod *m = generic_array_method_info [i].array_method;
+ MonoMethod *inflated;
inflated = mono_class_inflate_generic_method (m, &tmp_context);
- class->methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, name, inflated);
+ class->methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
}
}
class->method.count = 3 + (class->rank > 1? 2: 1);
if (class->interface_count) {
- for (i = 0; i < class->parent->method.count; i++) {
- MonoMethod *m = class->parent->methods [i];
- if (!strncmp (m->name, "InternalArray__", 15))
- count_generic++;
- }
+ count_generic = generic_array_methods (class);
first_generic = class->method.count;
class->method.count += class->interface_count * count_generic;
}
class->name = name;
class->name_space = nspace;
+ mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
+
class->image = image;
class->type_token = type_token;
class->flags = cols [MONO_TYPEDEF_FLAGS];
if (parent == NULL){
mono_internal_hash_table_remove (&image->class_cache, GUINT_TO_POINTER (type_token));
mono_loader_unlock ();
+ mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
return NULL;
}
}
if (!mono_metadata_interfaces_from_typedef_full (
image, type_token, &interfaces, &icount, context)){
mono_loader_unlock ();
+ mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
return NULL;
}
mono_loader_unlock ();
+ mono_profiler_class_loaded (class, MONO_PROFILE_OK);
+
return class;
}
mono_loader_lock ();
if (gclass->cached_class) {
mono_loader_unlock ();
- g_assert (!gclass->cached_class->generic_container);
return gclass->cached_class;
}
klass = param->pklass = mono_mempool_alloc0 (image->mempool, sizeof (MonoClass));
+ if (param->name)
+ klass->name = param->name;
+ else {
+ klass->name = mono_mempool_alloc0 (image->mempool, 16);
+ sprintf ((char*)klass->name, is_mvar ? "!!%d" : "!%d", param->num);
+ }
+ klass->name_space = "";
+ mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
+
for (count = 0, ptr = param->constraints; ptr && *ptr; ptr++, count++)
;
klass->interfaces [i - pos] = param->constraints [i];
}
- if (param->name)
- klass->name = param->name;
- else {
- klass->name = mono_mempool_alloc0 (image->mempool, 16);
- sprintf ((char*)klass->name, is_mvar ? "!!%d" : "!%d", param->num);
- }
-
- klass->name_space = "";
-
if (!image)
image = mono_defaults.corlib;
mono_class_setup_supertypes (klass);
mono_loader_unlock ();
-
+
+ mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
+
return klass;
}
name = g_strdup_printf ("%s*", el_class->name);
result->name = mono_mempool_strdup (image->mempool, name);
g_free (name);
+
+ mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
+
result->image = el_class->image;
result->inited = TRUE;
result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
mono_loader_unlock ();
+ mono_profiler_class_loaded (result, MONO_PROFILE_OK);
+
return result;
}
result->parent = NULL; /* no parent for PTR types */
result->name_space = "System";
result->name = "MonoFNPtrFakeClass";
+
+ mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
+
result->image = mono_defaults.corlib; /* need to fix... */
result->inited = TRUE;
result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
mono_loader_unlock ();
+ mono_profiler_class_loaded (result, MONO_PROFILE_OK);
+
return result;
}
name [nsize + rank + 1] = 0;
class->name = mono_mempool_strdup (image->mempool, name);
g_free (name);
+
+ mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
+
class->type_token = 0;
/* all arrays are marked serializable and sealed, bug #42779 */
class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED |
mono_class_setup_supertypes (class);
- if (mono_defaults.generic_ilist_class) {
- MonoClass *fclass = NULL;
- int i;
-
- if (eclass->valuetype) {
- if (eclass == mono_defaults.int16_class)
- fclass = mono_defaults.uint16_class;
- if (eclass == mono_defaults.uint16_class)
- fclass = mono_defaults.int16_class;
- if (eclass == mono_defaults.int32_class)
- fclass = mono_defaults.uint32_class;
- if (eclass == mono_defaults.uint32_class)
- fclass = mono_defaults.int32_class;
- if (eclass == mono_defaults.int64_class)
- fclass = mono_defaults.uint64_class;
- if (eclass == mono_defaults.uint64_class)
- fclass = mono_defaults.int64_class;
- if (eclass == mono_defaults.byte_class)
- fclass = mono_defaults.sbyte_class;
- if (eclass == mono_defaults.sbyte_class)
- fclass = mono_defaults.byte_class;
-
- class->interface_count = fclass ? 2 : 1;
- } else if (MONO_CLASS_IS_INTERFACE (eclass)) {
- class->interface_count = 2 + eclass->interface_count;
- } else {
- class->interface_count = eclass->idepth + eclass->interface_count;
- }
+ if (mono_defaults.generic_ilist_class && !bounded && rank == 1) {
+ MonoType *args [1];
+ /* generic IList, ICollection, IEnumerable */
+ class->interface_count = 1;
class->interfaces = mono_mempool_alloc0 (image->mempool, sizeof (MonoClass*) * class->interface_count);
- for (i = 0; i < class->interface_count; i++) {
- MonoType *args [1];
- MonoClass *iface;
-
- if (eclass->valuetype)
- iface = (i == 0) ? eclass : fclass;
- else if (MONO_CLASS_IS_INTERFACE (eclass)) {
- if (i == 0)
- iface = mono_defaults.object_class;
- else if (i == 1)
- iface = eclass;
- else
- iface = eclass->interfaces [i - 2];
- } else {
- if (i < eclass->idepth)
- iface = eclass->supertypes [i];
- else
- iface = eclass->interfaces [i - eclass->idepth];
- }
-
- args [0] = &iface->byval_arg;
-
- class->interfaces [i] = mono_class_bind_generic_parameters (
- mono_defaults.generic_ilist_class, 1, args, FALSE);
- }
+ args [0] = &eclass->byval_arg;
+ class->interfaces [0] = mono_class_bind_generic_parameters (
+ mono_defaults.generic_ilist_class, 1, args, FALSE);
}
if (eclass->generic_class)
mono_loader_unlock ();
+ mono_profiler_class_loaded (class, MONO_PROFILE_OK);
+
return class;
}
for (i = 1; i <= t->rows; ++i) {
mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
- /* nested types are accessed from the nesting name */
visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
- if (visib > TYPE_ATTRIBUTE_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_ASSEMBLY)
+ /*
+ * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
+ * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
+ */
+ if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
continue;
name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
/* add a cache if needed */
for (i = 1; i <= t->rows; ++i) {
mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
- /* nested types are accessed from the nesting name */
visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
- if (visib > TYPE_ATTRIBUTE_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_ASSEMBLY)
+ /*
+ * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
+ * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
+ */
+ if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
continue;
n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
mono_class_init (class);
return mono_class_get_field (class, token);
}
- case MONO_TOKEN_METHOD_DEF: {
+ case MONO_TOKEN_METHOD_DEF:
+ case MONO_TOKEN_METHOD_SPEC: {
MonoMethod *meth;
meth = mono_get_method_full (image, token, NULL, context);
if (handle_class)
return TRUE;
}
+
+gboolean
+mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
+{
+ return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
+}