[runtime] New profiler API.
[mono.git] / mono / metadata / class.c
index 0c735910d9b23776be40546bb52eaf14197378e3..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,19 +4839,20 @@ 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. 
- * Returns TRUE on success or FALSE if there was a problem in loading
- * the type (incorrect assemblies, missing assemblies, methods, etc).
- * Initializes the following fields in \param klass:
- * - all the fields initialized by mono_class_init_sizes ()
+ * 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 \c mono_class_init_sizes
  * - has_cctor
  * - ghcimpl
  * - inited
  *
  * LOCKING: Acquires the loader lock.
+ *
+ * \returns TRUE on success or FALSE if there was a problem in loading
+ * the type (incorrect assemblies, missing assemblies, methods, etc).
  */
 gboolean
 mono_class_init (MonoClass *klass)
@@ -5507,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;
@@ -5524,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 ();
        }
 
@@ -5578,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;
                }
        }
@@ -5635,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;
                }
 
@@ -5685,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);
@@ -5699,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;
        }
 
@@ -5713,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;
 
@@ -5723,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;
 }
 
@@ -5860,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);
 
@@ -5870,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);
@@ -5956,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;
@@ -6172,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;
 }
@@ -6191,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)
 {
@@ -6223,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;
@@ -6243,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 {
@@ -6252,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;
 }
@@ -6301,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;
@@ -6310,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;
 }
@@ -6318,8 +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,8 +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)
@@ -7455,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)
@@ -7502,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 *
@@ -7794,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)
@@ -7879,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
@@ -8122,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)
@@ -8505,8 +8569,7 @@ mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
  * mono_class_array_element_size:
  * \param klass
  *
- * \returns The number of bytes an element of type \p klass
- * uses when stored into an array.
+ * \returns The number of bytes an element of type \p klass uses when stored into an array.
  */
 gint32
 mono_class_array_element_size (MonoClass *klass)
@@ -8578,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)
@@ -8730,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.
  *
@@ -8749,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)
@@ -8773,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.
  * 
@@ -8857,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.
  */
@@ -8951,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)
@@ -8986,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)
@@ -9040,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);
                        /*
@@ -9053,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;
                }
@@ -9078,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);
@@ -9099,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;
@@ -9153,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.
  *
@@ -9193,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)
@@ -9292,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.
  *
@@ -9369,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*
@@ -9415,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)
@@ -9495,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)
@@ -9508,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)
@@ -9520,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)
@@ -9531,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*
@@ -9546,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.
  */
@@ -9559,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*
@@ -9571,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)
@@ -9583,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)
@@ -9595,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)
@@ -9606,9 +9680,8 @@ mono_event_get_raise_method (MonoEvent *event)
 
 /**
  * mono_event_get_parent:
- * @event: the MonoEvent to act on.
- *
- * Returns: The MonoClass where the event is defined.
+ * \param event the MonoEvent to act on.
+ * \returns The \c MonoClass where the event is defined.
  */
 MonoClass*
 mono_event_get_parent (MonoEvent *event)
@@ -9618,12 +9691,12 @@ mono_event_get_parent (MonoEvent *event)
 
 /**
  * mono_event_get_flags
- * @event: the MonoEvent to act on.
+ * \param event the \c MonoEvent to act on.
  *
  * The metadata flags for an event are encoded using the
- * 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.
+ * \returns The flags for the event.
  */
 guint32
 mono_event_get_flags (MonoEvent *event)
@@ -9633,11 +9706,11 @@ mono_event_get_flags (MonoEvent *event)
 
 /**
  * mono_class_get_method_from_name:
- * @klass: where to look for the method
- * @name: name of the method
- * @param_count: number of parameters. -1 for any number.
+ * \param klass where to look for the method
+ * \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 *
@@ -9691,12 +9764,12 @@ find_method_in_metadata (MonoClass *klass, const char *name, int param_count, in
 
 /**
  * mono_class_get_method_from_name_flags:
- * @klass: where to look for the method
- * @name_space: name of the method
- * @param_count: number of parameters. -1 for any number.
- * @flags: flags which must be set in the method
+ * \param klass where to look for the method
+ * \param name_space name of the method
+ * \param param_count number of parameters. -1 for any number.
+ * \param flags flags which must be set in the method
  *
- * 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 *
@@ -9749,9 +9822,9 @@ mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int p
 
 /**
  * mono_class_set_failure:
- * @klass: class in which the failure was detected
- * @ex_type: the kind of exception/error to be thrown (later)
- * @ex_data: exception data (specific to each type of exception/error)
+ * \param klass class in which the failure was detected
+ * \param ex_type the kind of exception/error to be thrown (later)
+ * \param ex_data exception data (specific to each type of exception/error)
  *
  * Keep a detected failure informations in the class for later processing.
  * Note that only the first failure is kept.
@@ -9784,16 +9857,16 @@ mono_class_has_failure (const MonoClass *klass)
 
 /**
  * mono_class_set_type_load_failure:
- * @klass: class in which the failure was detected
- * @fmt: Printf-style error message string.
+ * \param klass class in which the failure was detected
+ * \param fmt \c printf -style error message string.
  *
  * Collect detected failure informaion in the class for later processing.
- * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class ()
+ * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class()
  * Note that only the first failure is kept.
  *
- * Returns FALSE if a failure was already set on the class, or TRUE otherwise.
- *
  * LOCKING: Acquires the loader lock.
+ *
+ * \returns FALSE if a failure was already set on the class, or TRUE otherwise.
  */
 gboolean
 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
@@ -9867,9 +9940,9 @@ mono_classes_cleanup (void)
 
 /**
  * mono_class_get_exception_for_failure:
- * @klass: class in which the failure was detected
+ * \param klass class in which the failure was detected
  *
- * Return a constructed MonoException than the caller can then throw
+ * \returns a constructed MonoException than the caller can then throw
  * using mono_raise_exception - or NULL if no failure is present (or
  * doesn't result in an exception).
  */
@@ -9976,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])
@@ -10156,12 +10229,12 @@ can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass*
 
 /**
  * mono_method_can_access_field:
- * @method: Method that will attempt to access the field
- * @field: the field to access
+ * \param method Method that will attempt to access the field
+ * \param field the field to access
  *
  * Used to determine if a method is allowed to access the specified field.
  *
- * Returns: TRUE if the given @method is allowed to access the @field while following
+ * \returns TRUE if the given \p method is allowed to access the \p field while following
  * the accessibility rules of the CLI.
  */
 gboolean
@@ -10183,12 +10256,12 @@ mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
 
 /**
  * mono_method_can_access_method:
- * @method: Method that will attempt to access the other method
- * @called: the method that we want to probe for accessibility.
+ * \param method Method that will attempt to access the other method
+ * \param called the method that we want to probe for accessibility.
  *
- * Used to determine if the @method is allowed to access the specified @called method.
+ * Used to determine if the \p method is allowed to access the specified \p called method.
  *
- * Returns: TRUE if the given @method is allowed to invoke the @called while following
+ * \returns TRUE if the given \p method is allowed to invoke the \p called while following
  * the accessibility rules of the CLI.
  */
 gboolean
@@ -10321,9 +10394,8 @@ mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
 
 /**
  * mono_type_is_valid_enum_basetype:
- * @type: The MonoType to check
- *
- * Returns: TRUE if the type can be used as the basetype of an enum
+ * \param type The MonoType to check
+ * \returns TRUE if the type can be used as the basetype of an enum
  */
 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
        switch (type->type) {
@@ -10347,15 +10419,15 @@ gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
 
 /**
  * mono_class_is_valid_enum:
- * @klass: An enum class to be validated
+ * \param klass An enum class to be validated
  *
  * This method verify the required properties an enum should have.
- *  
- * Returns: TRUE if the informed enum class is valid 
  *
  * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
  * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
  * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
+ *
+ * \returns TRUE if the informed enum class is valid 
  */
 gboolean
 mono_class_is_valid_enum (MonoClass *klass)
@@ -10572,7 +10644,7 @@ mono_field_resolve_flags (MonoClassField *field)
 
 /**
  * mono_class_get_fields_lazy:
- * @klass: the MonoClass to act on
+ * \param klass the MonoClass to act on
  *
  * This routine is an iterator routine for retrieving the fields in a class.
  * Only minimal information about fields are loaded. Accessors must be used
@@ -10582,7 +10654,7 @@ mono_field_resolve_flags (MonoClassField *field)
  * iterate over all of the elements.  When no more values are
  * available, the return value is NULL.
  *
- * Returns: a @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_lazy (MonoClass* klass, gpointer *iter)
@@ -10623,17 +10695,17 @@ GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, "System.Runtime.InteropServices",
 
 /**
  * mono_method_get_base_method:
- * @method: a method
- * @definition: if true, get the definition
- * @error: set on failure
+ * \param method a method
+ * \param definition if true, get the definition
+ * \param 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
+ * method from an ancestor.  If \p definition is FALSE, returns the method in the
+ * superclass of the given method.  If \p 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.
+ * and sets \p error.
  */
 MonoMethod*
 mono_method_get_base_method (MonoMethod *method, gboolean definition, MonoError *error)