init_sizes_with_info (MonoClass *klass, MonoCachedClassInfo *cached_info)
{
if (cached_info) {
+ mono_loader_lock ();
klass->instance_size = cached_info->instance_size;
klass->sizes.class_size = cached_info->class_size;
klass->packing_size = cached_info->packing_size;
klass->has_references = cached_info->has_references;
klass->has_static_refs = cached_info->has_static_refs;
klass->no_special_static_fields = cached_info->no_special_static_fields;
+ mono_loader_unlock ();
}
else {
if (!klass->size_inited)
}
}
-static MonoClass*
-inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
-{
- MonoType *args [1];
- args [0] = &arg0->byval_arg;
-
- return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
-}
-
-static MonoClass*
-array_class_get_if_rank (MonoClass *klass, guint rank)
-{
- return rank ? mono_array_class_get (klass, rank) : klass;
-}
-
-static void
-fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
-{
- valuetype_types [0] = eclass;
- if (eclass == mono_defaults.int16_class)
- valuetype_types [1] = mono_defaults.uint16_class;
- else if (eclass == mono_defaults.uint16_class)
- valuetype_types [1] = mono_defaults.int16_class;
- else if (eclass == mono_defaults.int32_class)
- valuetype_types [1] = mono_defaults.uint32_class;
- else if (eclass == mono_defaults.uint32_class)
- valuetype_types [1] = mono_defaults.int32_class;
- else if (eclass == mono_defaults.int64_class)
- valuetype_types [1] = mono_defaults.uint64_class;
- else if (eclass == mono_defaults.uint64_class)
- valuetype_types [1] = mono_defaults.int64_class;
- else if (eclass == mono_defaults.byte_class)
- valuetype_types [1] = mono_defaults.sbyte_class;
- else if (eclass == mono_defaults.sbyte_class)
- valuetype_types [1] = mono_defaults.byte_class;
- else if (eclass->enumtype && mono_class_enum_basetype (eclass))
- valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
-}
-
-static GENERATE_GET_CLASS_WITH_CACHE (generic_icollection, System.Collections.Generic, ICollection`1)
-static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerable, System.Collections.Generic, IEnumerable`1)
-static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerator, System.Collections.Generic, IEnumerator`1)
-static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlylist, System.Collections.Generic, IReadOnlyList`1)
-static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlycollection, System.Collections.Generic, IReadOnlyCollection`1)
-
-static int
-find_array_interface (MonoClass *klass, const char *name)
-{
- int i;
- for (i = 0; i < klass->interface_count; ++i) {
- if (strcmp (klass->interfaces [i]->name, name) == 0)
- return i;
- }
- return -1;
-}
-
/*
* Return the number of virtual methods.
* Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
}
}
-static int
-find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
-{
- int i = find_interface (num_ifaces, interfaces_full, ic);
- if (i >= 0)
- return interface_offsets_full [i];
- return -1;
-}
-
static mono_bool
set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
{
g_slist_free (virt_methods);
virt_methods = NULL;
+ g_assert (cur_slot <= max_vtsize);
+
/* Ensure that all vtable slots are filled with concrete instance methods */
if (!mono_class_is_abstract (klass)) {
for (i = 0; i < cur_slot; ++i) {
}
}
- mono_image_lock (klass->image);
-
+ mono_loader_lock ();
if (!klass->has_finalize_inited) {
klass->has_finalize = has_finalize ? 1 : 0;
mono_memory_barrier ();
klass->has_finalize_inited = TRUE;
}
-
- mono_image_unlock (klass->image);
+ mono_loader_unlock ();
return klass->has_finalize;
}
mono_error_cleanup (&error);
}
}
+ mono_loader_lock ();
if (klass->parent)
mono_class_setup_parent (klass, klass->parent);
klass->cast_class = gtd->cast_class;
klass->element_class = gtd->element_class;
}
+ mono_loader_unlock ();
}
gboolean
/*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
- MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
+ MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info_raw (candidate); /* FIXME use handles */
int j;
if (tb && tb->interfaces) {
for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
if (klass->nested_classes_inited)
return;
- if (!klass->type_token)
+ if (!klass->type_token) {
+ mono_loader_lock ();
klass->nested_classes_inited = TRUE;
+ mono_loader_unlock ();
+ return;
+ }
i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
classes = NULL;
interfaces = NULL;
}
- mono_image_lock (klass->image);
-
+ mono_loader_lock ();
if (!klass->interfaces_inited) {
klass->interface_count = interface_count;
klass->interfaces = interfaces;
klass->interfaces_inited = TRUE;
}
-
- mono_image_unlock (klass->image);
+ mono_loader_unlock ();
}
static void
MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
int field_idx = field - klass->fields;
-
if (gtd) {
MonoClassField *gfield = >d->fields [field_idx];
return mono_field_get_flags (gfield);
/* Declare all shared lazy type lookup functions */
GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)
+
+/**
+ * mono_method_get_base_method:
+ * @method: a method
+ * @definition: if true, get the definition
+ * @error: set on failure
+ *
+ * Given a virtual method associated with a subclass, return the corresponding
+ * method from an ancestor. If @definition is FALSE, returns the method in the
+ * superclass of the given method. If @definition is TRUE, return the method
+ * in the ancestor class where it was first declared. The type arguments will
+ * be inflated in the ancestor classes. If the method is not associated with a
+ * class, or isn't virtual, returns the method itself. On failure returns NULL
+ * and sets @error.
+ */
+MonoMethod*
+mono_method_get_base_method (MonoMethod *method, gboolean definition, MonoError *error)
+{
+ MonoClass *klass, *parent;
+ MonoGenericContext *generic_inst = NULL;
+ MonoMethod *result = NULL;
+ int slot;
+
+ if (method->klass == NULL)
+ return method;
+
+ if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
+ MONO_CLASS_IS_INTERFACE (method->klass) ||
+ method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
+ return method;
+
+ slot = mono_method_get_vtable_slot (method);
+ if (slot == -1)
+ return method;
+
+ klass = method->klass;
+ if (mono_class_is_ginst (klass)) {
+ generic_inst = mono_class_get_context (klass);
+ klass = mono_class_get_generic_class (klass)->container_class;
+ }
+
+retry:
+ if (definition) {
+ /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
+ for (parent = klass->parent; parent != NULL; parent = parent->parent) {
+ /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
+ or klass is the generic container class and generic_inst is the instantiation.
+
+ when we go to the parent, if the parent is an open constructed type, we need to
+ replace the type parameters by the definitions from the generic_inst, and then take it
+ apart again into the klass and the generic_inst.
+
+ For cases like this:
+ class C<T> : B<T, int> {
+ public override void Foo () { ... }
+ }
+ class B<U,V> : A<HashMap<U,V>> {
+ public override void Foo () { ... }
+ }
+ class A<X> {
+ public virtual void Foo () { ... }
+ }
+
+ if at each iteration the parent isn't open, we can skip inflating it. if at some
+ iteration the parent isn't generic (after possible inflation), we set generic_inst to
+ NULL;
+ */
+ MonoGenericContext *parent_inst = NULL;
+ if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
+ parent = mono_class_inflate_generic_class_checked (parent, generic_inst, error);
+ return_val_if_nok (error, NULL);
+ }
+ if (mono_class_is_ginst (parent)) {
+ parent_inst = mono_class_get_context (parent);
+ parent = mono_class_get_generic_class (parent)->container_class;
+ }
+
+ mono_class_setup_vtable (parent);
+ if (parent->vtable_size <= slot)
+ break;
+ klass = parent;
+ generic_inst = parent_inst;
+ }
+ } else {
+ klass = klass->parent;
+ if (!klass)
+ return method;
+ if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
+ klass = mono_class_inflate_generic_class_checked (klass, generic_inst, error);
+ return_val_if_nok (error, NULL);
+
+ generic_inst = NULL;
+ }
+ if (mono_class_is_ginst (klass)) {
+ generic_inst = mono_class_get_context (klass);
+ klass = mono_class_get_generic_class (klass)->container_class;
+ }
+
+ }
+
+ if (generic_inst) {
+ klass = mono_class_inflate_generic_class_checked (klass, generic_inst, error);
+ return_val_if_nok (error, NULL);
+ }
+
+ if (klass == method->klass)
+ return method;
+
+ /*This is possible if definition == FALSE.
+ * Do it here to be really sure we don't read invalid memory.
+ */
+ if (slot >= klass->vtable_size)
+ return method;
+
+ mono_class_setup_vtable (klass);
+
+ result = klass->vtable [slot];
+ if (result == NULL) {
+ /* It is an abstract method */
+ gboolean found = FALSE;
+ gpointer iter = NULL;
+ while ((result = mono_class_get_methods (klass, &iter))) {
+ if (result->slot == slot) {
+ found = TRUE;
+ break;
+ }
+ }
+ /* found might be FALSE if we looked in an abstract class
+ * that doesn't override an abstract method of its
+ * parent:
+ * abstract class Base {
+ * public abstract void Foo ();
+ * }
+ * abstract class Derived : Base { }
+ * class Child : Derived {
+ * public override void Foo () { }
+ * }
+ *
+ * if m was Child.Foo and we ask for the base method,
+ * then we get here with klass == Derived and found == FALSE
+ */
+ /* but it shouldn't be the case that if we're looking
+ * for the definition and didn't find a result; the
+ * loop above should've taken us as far as we could
+ * go! */
+ g_assert (!(definition && !found));
+ if (!found)
+ goto retry;
+ }
+
+ g_assert (result != NULL);
+ return result;
+}