[runtime] New profiler API.
[mono.git] / mono / metadata / class.c
index 3bf7a840b6ae40832bd9422119066d41baa8828a..cd3f8bf703b433073663ebb089962c6306f760cf 100644 (file)
@@ -614,7 +614,6 @@ mono_type_get_full_name (MonoClass *klass)
 /**
  * mono_type_get_name:
  * \param type a type
- *
  * \returns The string representation for type as it would be represented in IL code.
  */
 char*
@@ -623,11 +622,10 @@ mono_type_get_name (MonoType *type)
        return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
 }
 
-/*
+/**
  * mono_type_get_underlying_type:
- * @type: a type
- *
- * Returns: The MonoType for the underlying integer type if @type
+ * \param type a type
+ * \returns The \c MonoType for the underlying integer type if \p type
  * is an enum and byref is false, otherwise the type itself.
  */
 MonoType*
@@ -870,18 +868,17 @@ mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type,
        return inflated;
 }
 
-/*
+/**
  * mono_class_inflate_generic_type:
- * @type: a type
- * @context: a generics context
+ * \param type a type
+ * \param context a generics context
+ * \deprecated Please use \c mono_class_inflate_generic_type_checked instead
  *
- * If @type is a generic type and @context is not NULL, instantiate it using the 
- * generics context @context.
+ * If \p type is a generic type and \p context is not NULL, instantiate it using the 
+ * generics context \p context.
  *
- * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
+ * \returns The instantiated type or a copy of \p type. The returned \c MonoType is allocated
  * on the heap and is owned by the caller. Returns NULL on error.
- *
- * @deprecated Please use mono_class_inflate_generic_type_checked instead
  */
 MonoType*
 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
@@ -982,14 +979,14 @@ fail:
        return res;
 }
 
-/*
+/**
  * mono_class_inflate_generic_method:
- * @method: a generic method
- * @context: a generics context
+ * \param method a generic method
+ * \param context a generics context
  *
- * Instantiate the generic method @method using the generics context @context.
+ * Instantiate the generic method \p method using the generics context \p context.
  *
- * Returns: The new instantiated method
+ * \returns The new instantiated method
  */
 MonoMethod *
 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
@@ -1605,6 +1602,11 @@ mono_class_setup_fields (MonoClass *klass)
                        g_assert (field->type);
                }
 
+               if (!mono_type_get_underlying_type (field->type)) {
+                       mono_class_set_type_load_failure (klass, "Field '%s' is an enum type with a bad underlying type", field->name);
+                       break;
+               }
+
                if (mono_field_is_deleted (field))
                        continue;
                if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
@@ -1629,8 +1631,7 @@ mono_class_setup_fields (MonoClass *klass)
                        char *class_name = mono_type_get_full_name (klass);
                        char *type_name = mono_type_full_name (field->type);
 
-                       mono_class_set_type_load_failure (klass, "");
-                       g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
+                       mono_class_set_type_load_failure (klass, "Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
                        g_free (class_name);
                        g_free (type_name);
                        break;
@@ -3690,7 +3691,7 @@ is_wcf_hack_disabled (void)
        static gboolean disabled;
        static gboolean inited = FALSE;
        if (!inited) {
-               disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
+               disabled = g_hasenv ("MONO_DISABLE_WCF_HACK");
                inited = TRUE;
        }
        return disabled;
@@ -4037,6 +4038,32 @@ mono_class_need_stelemref_method (MonoClass *klass)
        return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
 }
 
+static int
+apply_override (MonoClass *klass, MonoMethod **vtable, MonoMethod *decl, MonoMethod *override)
+{
+       int dslot;
+       dslot = mono_method_get_vtable_slot (decl);
+       if (dslot == -1) {
+               mono_class_set_type_load_failure (klass, "");
+               return FALSE;
+       }
+
+       dslot += mono_class_interface_offset (klass, decl->klass);
+       vtable [dslot] = override;
+       if (!MONO_CLASS_IS_INTERFACE (override->klass)) {
+               /*
+                * If override from an interface, then it is an override of a default interface method,
+                * don't override its slot.
+                */
+               vtable [dslot]->slot = dslot;
+       }
+
+       if (mono_security_core_clr_enabled ())
+               mono_security_core_clr_check_override (klass, vtable [dslot], decl);
+
+       return TRUE;
+}
+
 /*
  * LOCKING: this is supposed to be called with the loader lock held.
  */
@@ -4194,29 +4221,48 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o
        }
 
        TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
+
+       /* Process overrides from interface default methods */
+       // FIXME: Ordering between interfaces
+       for (int ifindex = 0; ifindex < klass->interface_offsets_count; ifindex++) {
+               ic = klass->interfaces_packed [ifindex];
+
+               mono_class_setup_methods (ic);
+               if (mono_class_has_failure (ic))
+                       goto fail;
+
+               MonoMethod **iface_overrides;
+               int iface_onum;
+               gboolean ok = mono_class_get_overrides_full (ic->image, ic->type_token, &iface_overrides, &iface_onum, mono_class_get_context (ic));
+               if (ok) {
+                       for (int i = 0; i < iface_onum; i++) {
+                               MonoMethod *decl = iface_overrides [i*2];
+                               MonoMethod *override = iface_overrides [i*2 + 1];
+                               if (!apply_override (klass, vtable, decl, override))
+                                       goto fail;
+
+                               if (!override_map)
+                                       override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
+                               g_hash_table_insert (override_map, decl, override);
+                       }
+                       g_free (iface_overrides);
+               }
+       }
+
        /* override interface methods */
        for (i = 0; i < onum; i++) {
                MonoMethod *decl = overrides [i*2];
+               MonoMethod *override = overrides [i*2 + 1];
                if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
-                       int dslot;
-                       dslot = mono_method_get_vtable_slot (decl);
-                       if (dslot == -1) {
-                               mono_class_set_type_load_failure (klass, "");
+                       if (!apply_override (klass, vtable, decl, override))
                                goto fail;
-                       }
 
-                       dslot += mono_class_interface_offset (klass, decl->klass);
-                       vtable [dslot] = overrides [i*2 + 1];
-                       vtable [dslot]->slot = dslot;
                        if (!override_map)
                                override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
-
-                       g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
-
-                       if (mono_security_core_clr_enabled ())
-                               mono_security_core_clr_check_override (klass, vtable [dslot], decl);
+                       g_hash_table_insert (override_map, decl, override);
                }
        }
+
        TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
        TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
 
@@ -4322,6 +4368,13 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o
                                                TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
                                        }
                                }
+
+                               if (vtable [im_slot] == NULL) {
+                                       if (!(im->flags & METHOD_ATTRIBUTE_ABSTRACT)) {
+                                               TRACE_INTERFACE_VTABLE (printf ("    Using default iface method %s.\n", mono_method_full_name (im, 1)));
+                                               vtable [im_slot] = im;
+                                       }
+                               }
                        } else {
                                g_assert (vtable [im_slot] == override_im);
                        }
@@ -4786,12 +4839,12 @@ concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
 
 /**
  * mono_class_init:
- * \param klass: the class to initialize
+ * \param klass the class to initialize
  *
- * Compute the instance_size, class_size and other infos that cannot be 
- * computed at mono_class_get() time. Also compute vtable_size if possible. 
+ * Compute the \c instance_size, \c class_size and other infos that cannot be 
+ * computed at \c mono_class_get time. Also compute vtable_size if possible. 
  * Initializes the following fields in \p klass:
- * - all the fields initialized by mono_class_init_sizes ()
+ * - all the fields initialized by \c mono_class_init_sizes
  * - has_cctor
  * - ghcimpl
  * - inited
@@ -5508,7 +5561,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError
        klass->name = name;
        klass->name_space = nspace;
 
-       mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
+       MONO_PROFILER_RAISE (class_loading, (klass));
 
        klass->image = image;
        klass->type_token = type_token;
@@ -5525,6 +5578,9 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError
                generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
                context = &generic_container->context;
                mono_class_set_generic_container (klass, generic_container);
+               MonoType *canonical_inst = &((MonoClassGtd*)klass)->canonical_inst;
+               canonical_inst->type = MONO_TYPE_GENERICINST;
+               canonical_inst->data.generic_class = mono_metadata_lookup_generic_class (klass, context->class_inst, FALSE);
                enable_gclass_recording ();
        }
 
@@ -5579,7 +5635,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError
                        /*FIXME implement a mono_class_set_failure_from_mono_error */
                        mono_class_set_type_load_failure (klass, "%s",  mono_error_get_message (error));
                        mono_loader_unlock ();
-                       mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
+                       MONO_PROFILER_RAISE (class_failed, (klass));
                        return NULL;
                }
        }
@@ -5636,7 +5692,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError
 
                        mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
                        mono_loader_unlock ();
-                       mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
+                       MONO_PROFILER_RAISE (class_failed, (klass));
                        return NULL;
                }
 
@@ -5686,7 +5742,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError
                        klass->cast_class = klass->element_class = mono_defaults.int32_class;
                        mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
                        mono_loader_unlock ();
-                       mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
+                       MONO_PROFILER_RAISE (class_failed, (klass));
                        return NULL;
                }
                klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
@@ -5700,7 +5756,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError
        if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
                mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
                mono_loader_unlock ();
-               mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
+               MONO_PROFILER_RAISE (class_failed, (klass));
                return NULL;
        }
 
@@ -5714,7 +5770,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError
 
        mono_loader_unlock ();
 
-       mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
+       MONO_PROFILER_RAISE (class_loaded, (klass));
 
        return klass;
 
@@ -5724,7 +5780,7 @@ parent_failure:
 
        mono_class_setup_mono_type (klass);
        mono_loader_unlock ();
-       mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
+       MONO_PROFILER_RAISE (class_failed, (klass));
        return NULL;
 }
 
@@ -5861,7 +5917,7 @@ mono_generic_class_get_class (MonoGenericClass *gclass)
        if (mono_class_is_nullable (klass))
                klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
 
-       mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
+       MONO_PROFILER_RAISE (class_loading, (klass));
 
        mono_generic_class_setup_parent (klass, gklass);
 
@@ -5871,7 +5927,7 @@ mono_generic_class_get_class (MonoGenericClass *gclass)
        mono_memory_barrier ();
        gclass->cached_class = klass;
 
-       mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
+       MONO_PROFILER_RAISE (class_loaded, (klass));
 
        ++class_ginst_count;
        inflated_classes_size += sizeof (MonoClassGenericInst);
@@ -5957,7 +6013,7 @@ make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
                CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
        }
 
-       mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
+       MONO_PROFILER_RAISE (class_loading, (klass));
 
        // Count non-NULL items in pinfo->constraints
        count = 0;
@@ -6173,9 +6229,9 @@ mono_class_from_generic_parameter_internal (MonoGenericParam *param)
 
        /* FIXME: Should this go inside 'make_generic_param_klass'? */
        if (klass2)
-               mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
+               MONO_PROFILER_RAISE (class_failed, (klass2));
        else
-               mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
+               MONO_PROFILER_RAISE (class_loaded, (klass));
 
        return klass;
 }
@@ -6192,6 +6248,9 @@ mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GN
        return mono_class_from_generic_parameter_internal (param);
 }
 
+/**
+ * mono_ptr_class_get:
+ */
 MonoClass *
 mono_ptr_class_get (MonoType *type)
 {
@@ -6224,7 +6283,7 @@ mono_ptr_class_get (MonoType *type)
        result->class_kind = MONO_CLASS_POINTER;
        g_free (name);
 
-       mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
+       MONO_PROFILER_RAISE (class_loading, (result));
 
        result->image = el_class->image;
        result->inited = TRUE;
@@ -6244,7 +6303,7 @@ mono_ptr_class_get (MonoType *type)
                MonoClass *result2;
                if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
                        mono_image_unlock (image);
-                       mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
+                       MONO_PROFILER_RAISE (class_failed, (result));
                        return result2;
                }
        } else {
@@ -6253,7 +6312,7 @@ mono_ptr_class_get (MonoType *type)
        g_hash_table_insert (image->ptr_cache, el_class, result);
        mono_image_unlock (image);
 
-       mono_profiler_class_loaded (result, MONO_PROFILE_OK);
+       MONO_PROFILER_RAISE (class_loaded, (result));
 
        return result;
 }
@@ -6302,7 +6361,7 @@ mono_fnptr_class_get (MonoMethodSignature *sig)
                return cached;
        }
 
-       mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
+       MONO_PROFILER_RAISE (class_loading, (result));
 
        classes_size += sizeof (MonoClassPointer);
        ++class_pointer_count;
@@ -6311,7 +6370,7 @@ mono_fnptr_class_get (MonoMethodSignature *sig)
 
        mono_loader_unlock ();
 
-       mono_profiler_class_loaded (result, MONO_PROFILE_OK);
+       MONO_PROFILER_RAISE (class_loaded, (result));
 
        return result;
 }
@@ -6319,7 +6378,7 @@ mono_fnptr_class_get (MonoMethodSignature *sig)
 /**
  * mono_class_from_mono_type:
  * \param type describes the type to return
- * \returns a MonoClass for the specified MonoType, the value is never NULL.
+ * \returns a \c MonoClass for the specified \c MonoType, the value is never NULL.
  */
 MonoClass *
 mono_class_from_mono_type (MonoType *type)
@@ -6442,7 +6501,6 @@ mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGeneri
  * \param element_class element class 
  * \param rank the dimension of the array class
  * \param bounded whenever the array has non-zero bounds
- *
  * \returns A class object describing the array with element type \p element_type and 
  * dimension \p rank.
  */
@@ -6631,7 +6689,7 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
                return cached;
        }
 
-       mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
+       MONO_PROFILER_RAISE (class_loading, (klass));
 
        classes_size += sizeof (MonoClassArray);
        ++class_array_count;
@@ -6647,7 +6705,7 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
 
        mono_loader_unlock ();
 
-       mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
+       MONO_PROFILER_RAISE (class_loaded, (klass));
 
        return klass;
 }
@@ -6656,7 +6714,6 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
  * mono_array_class_get:
  * \param element_class element class 
  * \param rank the dimension of the array class
- *
  * \returns A class object describing the array with element type \p element_type and 
  * dimension \p rank.
  */
@@ -6668,7 +6725,7 @@ mono_array_class_get (MonoClass *eclass, guint32 rank)
 
 /**
  * mono_class_instance_size:
- * \param klass: a class 
+ * \param klass a class
  *
  * Use to get the size of a class in bytes.
  *
@@ -6795,7 +6852,7 @@ mono_class_get_field_idx (MonoClass *klass, int idx)
  * \param class the class to lookup the field.
  * \param field_token the field token
  *
- * \returns A MonoClassField representing the type and offset of
+ * \returns A \c MonoClassField representing the type and offset of
  * the field, or a NULL value if the field does not belong to this
  * class.
  */
@@ -6811,12 +6868,12 @@ mono_class_get_field (MonoClass *klass, guint32 field_token)
 
 /**
  * mono_class_get_field_from_name:
- * \param klass: the class to lookup the field.
- * \param name: the field name
+ * \param klass the class to lookup the field.
+ * \param name the field name
  *
  * Search the class \p klass and its parents for a field with the name \p name.
  * 
- * \returns The MonoClassField pointer of the named field or NULL
+ * \returns The \c MonoClassField pointer of the named field or NULL
  */
 MonoClassField *
 mono_class_get_field_from_name (MonoClass *klass, const char *name)
@@ -7003,6 +7060,9 @@ mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def
        return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
 }
 
+/**
+ * mono_class_get_event_token:
+ */
 guint32
 mono_class_get_event_token (MonoEvent *event)
 {
@@ -7030,7 +7090,7 @@ mono_class_get_event_token (MonoEvent *event)
  * \param name name of the property to lookup in the specified class
  *
  * Use this method to lookup a property in a class
- * \returns the MonoProperty with the given name, or NULL if the property
+ * \returns the \c MonoProperty with the given name, or NULL if the property
  * does not exist on the \p klass.
  */
 MonoProperty*
@@ -7076,6 +7136,9 @@ mono_class_get_property_token (MonoProperty *prop)
        return 0;
 }
 
+/**
+ * mono_class_name_from_token:
+ */
 char *
 mono_class_name_from_token (MonoImage *image, guint32 type_token)
 {
@@ -7196,9 +7259,8 @@ mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
  * \param image the image where the class resides
  * \param type_token the token for the class
  * \param context the generic context used to evaluate generic instantiations in
- * \param deprecated Functions that expose MonoGenericContext are going away in mono 4.0
- *
- * \returns The MonoClass that represents \p type_token in \p image
+ * \deprecated Functions that expose \c MonoGenericContext are going away in mono 4.0
+ * \returns The \c MonoClass that represents \p type_token in \p image
  */
 MonoClass *
 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
@@ -7344,7 +7406,7 @@ mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext
  * mono_class_get:
  * \param image image where the class token will be looked up.
  * \param type_token a type token from the image
- * \returns the MonoClass with the given \p type_token on the \p image
+ * \returns the \c MonoClass with the given \p type_token on the \p image
  */
 MonoClass *
 mono_class_get (MonoImage *image, guint32 type_token)
@@ -7454,6 +7516,9 @@ mono_image_init_name_cache (MonoImage *image)
 }
 
 /*FIXME Only dynamic assemblies should allow this operation.*/
+/**
+ * mono_image_add_to_name_cache:
+ */
 void
 mono_image_add_to_name_cache (MonoImage *image, const char *nspace, 
                                                          const char *name, guint32 index)
@@ -7501,8 +7566,8 @@ find_nocase (gpointer key, gpointer value, gpointer user_data)
  * \param name the type short name.
  * \deprecated use the mono_class_from_name_case_checked variant instead.
  *
- * Obtains a MonoClass with a given namespace and a given name which
- * is located in the given MonoImage.   The namespace and name
+ * Obtains a \c MonoClass with a given namespace and a given name which
+ * is located in the given \c MonoImage.   The namespace and name
  * lookups are case insensitive.
  */
 MonoClass *
@@ -7793,16 +7858,16 @@ mono_class_from_name_checked (MonoImage *image, const char* name_space, const ch
 
 /**
  * mono_class_from_name:
- * \param image The MonoImage where the type is looked up in
+ * \param image The \c MonoImage where the type is looked up in
  * \param name_space the type namespace
  * \param name the type short name.
  *
- * Obtains a MonoClass with a given namespace and a given name which
- * is located in the given MonoImage.
+ * Obtains a \c MonoClass with a given namespace and a given name which
+ * is located in the given \c MonoImage.
  *
  * To reference nested classes, use the "/" character as a separator.
- * For example use "Foo/Bar" to reference the class Bar that is nested
- * inside Foo, like this: "class Foo { class Bar {} }".
+ * For example use \c "Foo/Bar" to reference the class \c Bar that is nested
+ * inside \c Foo, like this: "class Foo { class Bar {} }".
  */
 MonoClass *
 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
@@ -7878,11 +7943,11 @@ mono_class_try_load_from_name (MonoImage *image, const char* name_space, const c
  * this method return TRUE if the \p klass implements the interface or
  * if \p klass is an interface, if one of its base classes is \p klass.
  *
- * If \p check_interfaces is false then, then if \p klass is not an interface
- * then it returns TRUE if the \p klass is a subclass of \p klassc.
+ * If \p check_interfaces is false, then if \p klass is not an interface,
+ * it returns TRUE if the \p klass is a subclass of \p klassc.
  *
- * if \p klass is an interface and \p klassc is System.Object, then this function
- * return true.
+ * if \p klass is an interface and \p klassc is \c System.Object, then this function
+ * returns TRUE.
  *
  */
 gboolean
@@ -8121,8 +8186,8 @@ mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
  * \param klass the class to be assigned to
  * \param oklass the source class
  *
- * \returns TRUE if an instance of object oklass can be assigned to an
- * instance of object \p klass
+ * \returns TRUE if an instance of class \p oklass can be assigned to an
+ * instance of class \p klass
  */
 gboolean
 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
@@ -8576,6 +8641,9 @@ mono_array_element_size (MonoClass *ac)
        return ac->sizes.element_size;
 }
 
+/**
+ * mono_ldtoken:
+ */
 gpointer
 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
              MonoGenericContext *context)
@@ -8728,7 +8796,7 @@ mono_class_get_image (MonoClass *klass)
 
 /**
  * mono_class_get_element_class:
- * \param klass the MonoClass to act on
+ * \param klass the \c MonoClass to act on
  *
  * Use this function to get the element class of an array.
  *
@@ -8747,7 +8815,7 @@ mono_class_get_element_class (MonoClass *klass)
  * Use this method to determine if the provided \c MonoClass* represents a value type,
  * or a reference type.
  *
- * \returns TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
+ * \returns TRUE if the \c MonoClass represents a \c ValueType, FALSE if it represents a reference type.
  */
 gboolean
 mono_class_is_valuetype (MonoClass *klass)
@@ -8771,7 +8839,7 @@ mono_class_is_enum (MonoClass *klass)
 
 /**
  * mono_class_enum_basetype:
- * \param klass: the \c MonoClass to act on
+ * \param klass the \c MonoClass to act on
  *
  * Use this function to get the underlying type for an enumeration value.
  * 
@@ -8855,7 +8923,7 @@ mono_class_get_namespace (MonoClass *klass)
  * mono_class_get_type:
  * \param klass the \c MonoClass to act on
  *
- * This method returns the internal Type representation for the class.
+ * This method returns the internal \c MonoType representation for the class.
  *
  * \returns The \c MonoType from the class.
  */
@@ -8949,11 +9017,11 @@ mono_class_num_events (MonoClass *klass)
  *
  * This routine is an iterator routine for retrieving the fields in a class.
  *
- * You must pass a gpointer that points to zero and is treated as an opaque handle to
+ * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
  * iterate over all of the elements.  When no more values are
  * available, the return value is NULL.
  *
- * Returns: a \c MonoClassField* on each iteration, or NULL when no more fields are available.
+ * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
  */
 MonoClassField*
 mono_class_get_fields (MonoClass* klass, gpointer *iter)
@@ -8984,16 +9052,16 @@ mono_class_get_fields (MonoClass* klass, gpointer *iter)
 }
 
 /**
- * mono_class_get_methods
+ * mono_class_get_methods:
  * \param klass the \c MonoClass to act on
  *
  * This routine is an iterator routine for retrieving the fields in a class.
  *
- * You must pass a gpointer that points to zero and is treated as an opaque handle to
+ * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
  * iterate over all of the elements.  When no more values are
  * available, the return value is NULL.
  *
- * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
+ * \returns a \c MonoMethod on each iteration or NULL when no more methods are available.
  */
 MonoMethod*
 mono_class_get_methods (MonoClass* klass, gpointer *iter)
@@ -9038,10 +9106,25 @@ mono_class_get_methods (MonoClass* klass, gpointer *iter)
 static MonoMethod*
 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
 {
-       MonoMethod** method;
+       gboolean static_iter = FALSE;
+
        if (!iter)
                return NULL;
-       if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
+
+       /*
+        * If the lowest bit of the iterator is 1, this is an iterator for static metadata,
+        * and the upper bits contain an index. Otherwise, the iterator is a pointer into
+        * klass->methods.
+        */
+       if ((gsize)(*iter) & 1)
+               static_iter = TRUE;
+       /* Use the static metadata only if klass->methods is not yet initialized */
+       if (!static_iter && !(klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)))
+               static_iter = TRUE;
+
+       if (!static_iter) {
+               MonoMethod** methodptr;
+
                if (!*iter) {
                        mono_class_setup_methods (klass);
                        /*
@@ -9051,20 +9134,22 @@ mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
                        if (!klass->methods)
                                return NULL;
                        /* start from the first */
-                       method = &klass->methods [0];
+                       methodptr = &klass->methods [0];
                } else {
-                       method = (MonoMethod **)*iter;
-                       method++;
+                       methodptr = (MonoMethod **)*iter;
+                       methodptr++;
                }
+               if (*iter)
+                       g_assert ((guint64)(*iter) > 0x100);
                int mcount = mono_class_get_method_count (klass);
-               while (method < &klass->methods [mcount]) {
-                       if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
+               while (methodptr < &klass->methods [mcount]) {
+                       if (*methodptr && ((*methodptr)->flags & METHOD_ATTRIBUTE_VIRTUAL))
                                break;
-                       method ++;
+                       methodptr ++;
                }
-               if (method < &klass->methods [mcount]) {
-                       *iter = method;
-                       return *method;
+               if (methodptr < &klass->methods [mcount]) {
+                       *iter = methodptr;
+                       return *methodptr;
                } else {
                        return NULL;
                }
@@ -9076,7 +9161,7 @@ mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
                if (!*iter) {
                        start_index = 0;
                } else {
-                       start_index = GPOINTER_TO_UINT (*iter);
+                       start_index = GPOINTER_TO_UINT (*iter) >> 1;
                }
 
                int first_idx = mono_class_get_first_method_idx (klass);
@@ -9097,7 +9182,7 @@ mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
                        mono_error_cleanup (&error); /* FIXME don't swallow the error */
 
                        /* Add 1 here so the if (*iter) check fails */
-                       *iter = GUINT_TO_POINTER (i + 1);
+                       *iter  = GUINT_TO_POINTER (((i + 1) << 1) | 1);
                        return res;
                } else {
                        return NULL;
@@ -9151,7 +9236,7 @@ mono_class_get_properties (MonoClass* klass, gpointer *iter)
  *
  * This routine is an iterator routine for retrieving the properties in a class.
  *
- * You must pass a gpointer that points to zero and is treated as an opaque handle to
+ * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
  * iterate over all of the elements.  When no more values are
  * available, the return value is NULL.
  *
@@ -9191,11 +9276,11 @@ mono_class_get_events (MonoClass* klass, gpointer *iter)
  *
  * This routine is an iterator routine for retrieving the interfaces implemented by this class.
  *
- * You must pass a gpointer that points to zero and is treated as an opaque handle to
+ * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
  * iterate over all of the elements.  When no more values are
  * available, the return value is NULL.
  *
- * \returns a \c Monoclass* on each invocation, or NULL when no more are available.
+ * \returns a \c MonoClass* on each invocation, or NULL when no more are available.
  */
 MonoClass*
 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
@@ -9290,7 +9375,7 @@ setup_nested_types (MonoClass *klass)
  * This routine is an iterator routine for retrieving the nested types of a class.
  * This works only if \p klass is non-generic, or a generic type definition.
  *
- * You must pass a gpointer that points to zero and is treated as an opaque handle to
+ * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
  * iterate over all of the elements.  When no more values are
  * available, the return value is NULL.
  *
@@ -9367,7 +9452,6 @@ mono_field_get_name (MonoClassField *field)
 /**
  * mono_field_get_type:
  * \param field the \c MonoClassField to act on
- *
  * \returns \c MonoType of the field.
  */
 MonoType*
@@ -9413,12 +9497,12 @@ mono_field_get_parent (MonoClassField *field)
 
 /**
  * mono_field_get_flags;
- * @field: the MonoClassField to act on
+ * \param field the \c MonoClassField to act on
  *
  * The metadata flags for a field are encoded using the
- * FIELD_ATTRIBUTE_* constants.  See the tabledefs.h file for details.
+ * \c FIELD_ATTRIBUTE_* constants.  See the \c tabledefs.h file for details.
  *
- * Returns: The flags for the field.
+ * \returns The flags for the field.
  */
 guint32
 mono_field_get_flags (MonoClassField *field)
@@ -9493,9 +9577,8 @@ mono_field_get_data (MonoClassField *field)
 
 /**
  * mono_property_get_name: 
- * @prop: the MonoProperty to act on
- *
- * Returns: The name of the property
+ * \param prop the \c MonoProperty to act on
+ * \returns The name of the property
  */
 const char*
 mono_property_get_name (MonoProperty *prop)
@@ -9506,8 +9589,7 @@ mono_property_get_name (MonoProperty *prop)
 /**
  * mono_property_get_set_method
  * \param prop the \c MonoProperty to act on.
- *
- * \returns The setter method of the property (A MonoMethod)
+ * \returns The setter method of the property, a \c MonoMethod.
  */
 MonoMethod*
 mono_property_get_set_method (MonoProperty *prop)
@@ -9518,8 +9600,7 @@ mono_property_get_set_method (MonoProperty *prop)
 /**
  * mono_property_get_get_method
  * \param prop the MonoProperty to act on.
- *
- * \returns The setter method of the property (A \c MonoMethod)
+ * \returns The getter method of the property (A \c MonoMethod)
  */
 MonoMethod*
 mono_property_get_get_method (MonoProperty *prop)
@@ -9529,8 +9610,7 @@ mono_property_get_get_method (MonoProperty *prop)
 
 /**
  * mono_property_get_parent:
- * \param prop the MonoProperty to act on.
- *
+ * \param prop the \c MonoProperty to act on.
  * \returns The \c MonoClass where the property was defined.
  */
 MonoClass*
@@ -9544,7 +9624,7 @@ mono_property_get_parent (MonoProperty *prop)
  * \param prop the \c MonoProperty to act on.
  *
  * The metadata flags for a property are encoded using the
- * \c PROPERTY_ATTRIBUTE_* constants.  See the tabledefs.h file for details.
+ * \c PROPERTY_ATTRIBUTE_* constants.  See the \c tabledefs.h file for details.
  *
  * \returns The flags for the property.
  */
@@ -9557,7 +9637,6 @@ mono_property_get_flags (MonoProperty *prop)
 /**
  * mono_event_get_name:
  * \param event the MonoEvent to act on
- *
  * \returns The name of the event.
  */
 const char*
@@ -9569,8 +9648,7 @@ mono_event_get_name (MonoEvent *event)
 /**
  * mono_event_get_add_method:
  * \param event The \c MonoEvent to act on.
- *
- * \returns The \c add method for the event (a \c MonoMethod).
+ * \returns The \c add method for the event, a \c MonoMethod.
  */
 MonoMethod*
 mono_event_get_add_method (MonoEvent *event)
@@ -9581,8 +9659,7 @@ mono_event_get_add_method (MonoEvent *event)
 /**
  * mono_event_get_remove_method:
  * \param event The \c MonoEvent to act on.
- *
- * \returns The \c remove method for the event (a \c MonoMethod).
+ * \returns The \c remove method for the event, a \c MonoMethod.
  */
 MonoMethod*
 mono_event_get_remove_method (MonoEvent *event)
@@ -9593,8 +9670,7 @@ mono_event_get_remove_method (MonoEvent *event)
 /**
  * mono_event_get_raise_method:
  * \param event The \c MonoEvent to act on.
- *
- * \returns The \c raise method for the event (a \c MonoMethod).
+ * \returns The \c raise method for the event, a \c MonoMethod.
  */
 MonoMethod*
 mono_event_get_raise_method (MonoEvent *event)
@@ -9618,7 +9694,7 @@ mono_event_get_parent (MonoEvent *event)
  * \param event the \c MonoEvent to act on.
  *
  * The metadata flags for an event are encoded using the
- * \c EVENT_* constants.  See the tabledefs.h file for details.
+ * \c EVENT_* constants.  See the \c tabledefs.h file for details.
  *
  * \returns The flags for the event.
  */
@@ -9634,7 +9710,7 @@ mono_event_get_flags (MonoEvent *event)
  * \param name name of the method
  * \param param_count number of parameters. -1 for any number.
  *
- * Obtains a MonoMethod with a given name and number of parameters.
+ * Obtains a \c MonoMethod with a given name and number of parameters.
  * It only works if there are no multiple signatures for any given method name.
  */
 MonoMethod *
@@ -9973,7 +10049,7 @@ can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
                /* Be conservative with checks */
                if (!friend_->name)
                        continue;
-               if (strcmp (accessing->aname.name, friend_->name))
+               if (g_ascii_strcasecmp (accessing->aname.name, friend_->name))
                        continue;
                if (friend_->public_key_token [0]) {
                        if (!accessing->aname.public_key_token [0])