Merge pull request #913 from Daniel15/fix-catchall-routing-master
[mono.git] / mono / metadata / metadata.c
index 6d77ea5b33520768e41896fa85d22cdccc9707ec..e1452cb77b250e98b098afc08d8ab5ae98819933 100644 (file)
@@ -10,9 +10,6 @@
  */
 
 #include <config.h>
-#ifdef HAVE_ALLOCA_H
-#include <alloca.h>
-#endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -29,7 +26,8 @@
 #include "marshal.h"
 #include "debug-helpers.h"
 #include <mono/utils/mono-error-internals.h>
+#include <mono/utils/bsearch.h>
+
 /* Auxiliary structure used for caching inflated signatures */
 typedef struct {
        MonoMethodSignature *sig;
@@ -760,7 +758,6 @@ mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bit
                        n = MAX (n, meta->tables [MONO_TABLE_METHOD].rows);
                        n = MAX (n, meta->tables [MONO_TABLE_MODULEREF].rows);
                        n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
-                       n = MAX (n, meta->tables [MONO_TABLE_MEMBERREF].rows);
 
                        /* 3 bits to encode */
                        field_size = rtsize (n, 16 - 3);
@@ -886,6 +883,7 @@ mono_metadata_locate_token (MonoImage *meta, guint32 token)
 const char *
 mono_metadata_string_heap (MonoImage *meta, guint32 index)
 {
+       g_assert (index < meta->heap_strings.size);
        g_return_val_if_fail (index < meta->heap_strings.size, "");
        return meta->heap_strings.data + index;
 }
@@ -900,6 +898,7 @@ mono_metadata_string_heap (MonoImage *meta, guint32 index)
 const char *
 mono_metadata_user_string (MonoImage *meta, guint32 index)
 {
+       g_assert (index < meta->heap_us.size);
        g_return_val_if_fail (index < meta->heap_us.size, "");
        return meta->heap_us.data + index;
 }
@@ -914,6 +913,7 @@ mono_metadata_user_string (MonoImage *meta, guint32 index)
 const char *
 mono_metadata_blob_heap (MonoImage *meta, guint32 index)
 {
+       g_assert (index < meta->heap_blob.size);
        g_return_val_if_fail (index < meta->heap_blob.size, "");/*FIXME shouldn't we return NULL and check for index == 0?*/
        return meta->heap_blob.data + index;
 }
@@ -2431,15 +2431,18 @@ collect_inflated_signature_images (MonoInflatedMethodSignature *sig, CollectData
 static void
 collect_method_images (MonoMethodInflated *method, CollectData *data)
 {
+       MonoMethod *m = method->declaring;
+
        add_image (method->declaring->klass->image, data);
        if (method->context.class_inst)
                collect_ginst_images (method->context.class_inst, data);
        if (method->context.method_inst)
                collect_ginst_images (method->context.method_inst, data);
        /*
-       if (((MonoMethod*)method)->signature)
-               collect_signature_images (mono_method_signature ((MonoMethod*)method), data);
-       */
+        * Dynamic assemblies have no references, so the images they depend on can be unloaded before them.
+        */
+       if (m->klass->image->dynamic)
+               collect_signature_images (mono_method_signature (m), data);
 }
 
 static void
@@ -2606,11 +2609,11 @@ check_image_sets (MonoImage *image)
        }
 }
 
-GSList*
+void
 mono_metadata_clean_for_image (MonoImage *image)
 {
        CleanForImageUserData ginst_data, gclass_data;
-       GSList *l, *set_list, *free_list = NULL;
+       GSList *l, *set_list;
 
        //check_image_sets (image);
 
@@ -2650,8 +2653,6 @@ mono_metadata_clean_for_image (MonoImage *image)
        g_slist_free (set_list);
 
        mono_loader_unlock ();
-
-       return free_list;
 }
 
 static void
@@ -2696,6 +2697,8 @@ free_generic_class (MonoGenericClass *gclass)
        /* The gclass itself is allocated from the image set mempool */
        if (gclass->is_dynamic)
                mono_reflection_free_dynamic_generic_class (gclass);
+       if (gclass->cached_class && gclass->cached_class->interface_id)
+               mono_unload_interface_id (gclass->cached_class);
 }
 
 static void
@@ -2795,10 +2798,8 @@ mono_metadata_get_generic_inst (int type_argc, MonoType **type_argv)
                        break;
        is_open = (i < type_argc);
 
-       ginst = alloca (size);
-#ifndef MONO_SMALL_CONFIG
-       ginst->id = 0;
-#endif
+       ginst = g_alloca (size);
+       memset (ginst, 0, sizeof (MonoGenericInst));
        ginst->is_open = is_open;
        ginst->type_argc = type_argc;
        memcpy (ginst->type_argv, type_argv, type_argc * sizeof (MonoType *));
@@ -3095,6 +3096,23 @@ mono_metadata_get_shared_type (MonoType *type)
        return NULL;
 }
 
+static gboolean
+compare_type_literals (int class_type, int type_type)
+{
+       /* byval_arg.type can be zero if we're decoding a type that references a class been loading.
+        * See mcs/test/gtest-440. and #650936.
+        * FIXME This better be moved to the metadata verifier as it can catch more cases.
+        */
+       if (!class_type)
+               return TRUE;
+       /* NET 1.1 assemblies might encode string and object in a denormalized way.
+        * See #675464.
+        */
+       if (type_type == MONO_TYPE_CLASS && (class_type == MONO_TYPE_STRING || class_type == MONO_TYPE_OBJECT))
+               return TRUE;
+       return class_type == type_type;
+}
+
 /* 
  * do_mono_metadata_parse_type:
  * @type: MonoType to be filled in with the return value
@@ -3152,14 +3170,8 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer
                type->data.klass = class;
                if (!class)
                        return FALSE;
-               /* byval_arg.type can be zero if we're decoding a type that references a class been loading.
-                * See mcs/test/gtest-440. and #650936.
-                * FIXME This better be moved to the metadata verifier as it can catch more cases.
-                */
-               if (class->byval_arg.type && class->byval_arg.type != type->type) {
-                       printf ("me [%x] it [%x] -- '%s'\n", type->type, type->data.klass->byval_arg.type, mono_type_full_name (type));
+               if (!compare_type_literals (class->byval_arg.type, type->type))
                        return FALSE;
-               }
                break;
        }
        case MONO_TYPE_SZARRAY: {
@@ -3904,7 +3916,7 @@ mono_metadata_typedef_from_field (MonoImage *meta, guint32 index)
        if (meta->uncompressed_metadata)
                loc.idx = search_ptr_table (meta, MONO_TABLE_FIELD_POINTER, loc.idx);
 
-       if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
+       if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
                return 0;
 
        /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
@@ -3935,7 +3947,7 @@ mono_metadata_typedef_from_method (MonoImage *meta, guint32 index)
        if (meta->uncompressed_metadata)
                loc.idx = search_ptr_table (meta, MONO_TABLE_METHOD_POINTER, loc.idx);
 
-       if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
+       if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
                return 0;
 
        /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
@@ -3977,7 +3989,7 @@ mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, Mono
        loc.col_idx = MONO_INTERFACEIMPL_CLASS;
        loc.t = tdef;
 
-       if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
+       if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
                return TRUE;
 
        start = loc.result;
@@ -4058,7 +4070,7 @@ mono_metadata_interfaces_from_typedef (MonoImage *meta, guint32 index, guint *co
  * 
  * Returns: the 1-based index into the TypeDef table of the type
  * where the type described by @index is nested.
- * Retruns 0 if @index describes a non-nested type.
+ * Returns 0 if @index describes a non-nested type.
  */
 guint32
 mono_metadata_nested_in_typedef (MonoImage *meta, guint32 index)
@@ -4073,7 +4085,7 @@ mono_metadata_nested_in_typedef (MonoImage *meta, guint32 index)
        loc.col_idx = MONO_NESTED_CLASS_NESTED;
        loc.t = tdef;
 
-       if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
+       if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
                return 0;
 
        /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
@@ -4137,7 +4149,7 @@ mono_metadata_packing_from_typedef (MonoImage *meta, guint32 index, guint32 *pac
        loc.col_idx = MONO_CLASS_LAYOUT_PARENT;
        loc.t = tdef;
 
-       if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
+       if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
                return 0;
 
        mono_metadata_decode_row (tdef, loc.result, cols, MONO_CLASS_LAYOUT_SIZE);
@@ -4174,7 +4186,7 @@ mono_metadata_custom_attrs_from_index (MonoImage *meta, guint32 index)
 
        /* FIXME: Index translation */
 
-       if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
+       if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
                return 0;
 
        /* Find the first entry by searching backwards */
@@ -4207,7 +4219,7 @@ mono_metadata_declsec_from_index (MonoImage *meta, guint32 index)
        loc.col_idx = MONO_DECL_SECURITY_PARENT;
        loc.t = tdef;
 
-       if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, declsec_locator))
+       if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, declsec_locator))
                return -1;
 
        /* Find the first entry by searching backwards */
@@ -4233,10 +4245,7 @@ mono_backtrace (int limit)
 }
 #endif
 
-#ifndef __GNUC__
-/*#define __alignof__(a) sizeof(a)*/
-#define __alignof__(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
-#endif
+#define abi__alignof__(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
 
 /*
  * mono_type_size:
@@ -4253,7 +4262,7 @@ mono_type_size (MonoType *t, int *align)
                return 0;
        }
        if (t->byref) {
-               *align = __alignof__(gpointer);
+               *align = abi__alignof__(gpointer);
                return sizeof (gpointer);
        }
 
@@ -4262,40 +4271,40 @@ mono_type_size (MonoType *t, int *align)
                *align = 1;
                return 0;
        case MONO_TYPE_BOOLEAN:
-               *align = __alignof__(gint8);
+               *align = abi__alignof__(gint8);
                return 1;
        case MONO_TYPE_I1:
        case MONO_TYPE_U1:
-               *align = __alignof__(gint8);
+               *align = abi__alignof__(gint8);
                return 1;
        case MONO_TYPE_CHAR:
        case MONO_TYPE_I2:
        case MONO_TYPE_U2:
-               *align = __alignof__(gint16);
+               *align = abi__alignof__(gint16);
                return 2;               
        case MONO_TYPE_I4:
        case MONO_TYPE_U4:
-               *align = __alignof__(gint32);
+               *align = abi__alignof__(gint32);
                return 4;
        case MONO_TYPE_R4:
-               *align = __alignof__(float);
+               *align = abi__alignof__(float);
                return 4;
        case MONO_TYPE_I8:
        case MONO_TYPE_U8:
-               *align = __alignof__(gint64);
+               *align = abi__alignof__(gint64);
                return 8;               
        case MONO_TYPE_R8:
-               *align = __alignof__(double);
+               *align = abi__alignof__(double);
                return 8;               
        case MONO_TYPE_I:
        case MONO_TYPE_U:
-               *align = __alignof__(gpointer);
+               *align = abi__alignof__(gpointer);
                return sizeof (gpointer);
        case MONO_TYPE_STRING:
-               *align = __alignof__(gpointer);
+               *align = abi__alignof__(gpointer);
                return sizeof (gpointer);
        case MONO_TYPE_OBJECT:
-               *align = __alignof__(gpointer);
+               *align = abi__alignof__(gpointer);
                return sizeof (gpointer);
        case MONO_TYPE_VALUETYPE: {
                if (t->data.klass->enumtype)
@@ -4308,7 +4317,7 @@ mono_type_size (MonoType *t, int *align)
        case MONO_TYPE_PTR:
        case MONO_TYPE_FNPTR:
        case MONO_TYPE_ARRAY:
-               *align = __alignof__(gpointer);
+               *align = abi__alignof__(gpointer);
                return sizeof (gpointer);
        case MONO_TYPE_TYPEDBYREF:
                return mono_class_value_size (mono_defaults.typed_reference_class, (guint32*)align);
@@ -4324,14 +4333,14 @@ mono_type_size (MonoType *t, int *align)
                        else
                                return mono_class_value_size (mono_class_from_mono_type (t), (guint32*)align);
                } else {
-                       *align = __alignof__(gpointer);
+                       *align = abi__alignof__(gpointer);
                        return sizeof (gpointer);
                }
        }
        case MONO_TYPE_VAR:
        case MONO_TYPE_MVAR:
                /* FIXME: Martin, this is wrong. */
-               *align = __alignof__(gpointer);
+               *align = abi__alignof__(gpointer);
                return sizeof (gpointer);
        default:
                g_error ("mono_type_size: type 0x%02x unknown", t->type);
@@ -4358,7 +4367,7 @@ mono_type_stack_size_internal (MonoType *t, int *align, gboolean allow_open)
        int tmp;
 #if SIZEOF_VOID_P == SIZEOF_REGISTER
        int stack_slot_size = sizeof (gpointer);
-       int stack_slot_align = __alignof__ (gpointer);
+       int stack_slot_align = abi__alignof__ (gpointer);
 #elif SIZEOF_VOID_P < SIZEOF_REGISTER
        int stack_slot_size = SIZEOF_REGISTER;
        int stack_slot_align = SIZEOF_REGISTER;
@@ -4403,14 +4412,14 @@ mono_type_stack_size_internal (MonoType *t, int *align, gboolean allow_open)
                *align = stack_slot_align;
                return stack_slot_size * 3;
        case MONO_TYPE_R4:
-               *align = __alignof__(float);
+               *align = abi__alignof__(float);
                return sizeof (float);          
        case MONO_TYPE_I8:
        case MONO_TYPE_U8:
-               *align = __alignof__(gint64);
+               *align = abi__alignof__(gint64);
                return sizeof (gint64);         
        case MONO_TYPE_R8:
-               *align = __alignof__(double);
+               *align = abi__alignof__(double);
                return sizeof (double);
        case MONO_TYPE_VALUETYPE: {
                guint32 size;
@@ -4589,6 +4598,8 @@ mono_metadata_generic_param_equal (MonoGenericParam *p1, MonoGenericParam *p2, g
                return TRUE;
        if (mono_generic_param_num (p1) != mono_generic_param_num (p2))
                return FALSE;
+       if (p1->serial != p2->serial)
+               return FALSE;
 
        /*
         * We have to compare the image as well because if we didn't,
@@ -4634,6 +4645,9 @@ mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only
        if (signature_only &&
            (c1->byval_arg.type == MONO_TYPE_SZARRAY) && (c2->byval_arg.type == MONO_TYPE_SZARRAY))
                return mono_metadata_class_equal (c1->byval_arg.data.klass, c2->byval_arg.data.klass, signature_only);
+       if (signature_only &&
+           (c1->byval_arg.type == MONO_TYPE_ARRAY) && (c2->byval_arg.type == MONO_TYPE_ARRAY))
+               return do_mono_metadata_type_equal (&c1->byval_arg, &c2->byval_arg, signature_only);
        return FALSE;
 }
 
@@ -4919,7 +4933,7 @@ mono_metadata_field_info_full (MonoImage *meta, guint32 index, guint32 *offset,
                loc.col_idx = MONO_FIELD_LAYOUT_FIELD;
                loc.t = tdef;
 
-               if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
+               if (tdef->base && mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
                        *offset = mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_LAYOUT_OFFSET);
                } else {
                        *offset = (guint32)-1;
@@ -4931,7 +4945,7 @@ mono_metadata_field_info_full (MonoImage *meta, guint32 index, guint32 *offset,
                loc.col_idx = MONO_FIELD_RVA_FIELD;
                loc.t = tdef;
                
-               if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
+               if (tdef->base && mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
                        /*
                         * LAMESPEC: There is no signature, no nothing, just the raw data.
                         */
@@ -4992,7 +5006,7 @@ mono_metadata_get_constant_index (MonoImage *meta, guint32 token, guint32 hint)
        if ((hint > 0) && (hint < tdef->rows) && (mono_metadata_decode_row_col (tdef, hint - 1, MONO_CONSTANT_PARENT) == index))
                return hint;
 
-       if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
+       if (tdef->base && mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
                return loc.result + 1;
        }
        return 0;
@@ -5023,7 +5037,7 @@ mono_metadata_events_from_typedef (MonoImage *meta, guint32 index, guint *end_id
        loc.col_idx = MONO_EVENT_MAP_PARENT;
        loc.idx = index + 1;
 
-       if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
+       if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
                return 0;
        
        start = mono_metadata_decode_row_col (tdef, loc.result, MONO_EVENT_MAP_EVENTLIST);
@@ -5065,7 +5079,7 @@ mono_metadata_methods_from_event   (MonoImage *meta, guint32 index, guint *end_i
        loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
        loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT; /* Method association coded index */
 
-       if (!bsearch (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator))
+       if (!mono_binary_search (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator))
                return 0;
 
        start = loc.result;
@@ -5114,7 +5128,7 @@ mono_metadata_properties_from_typedef (MonoImage *meta, guint32 index, guint *en
        loc.col_idx = MONO_PROPERTY_MAP_PARENT;
        loc.idx = index + 1;
 
-       if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
+       if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
                return 0;
        
        start = mono_metadata_decode_row_col (tdef, loc.result, MONO_PROPERTY_MAP_PROPERTY_LIST);
@@ -5156,7 +5170,7 @@ mono_metadata_methods_from_property   (MonoImage *meta, guint32 index, guint *en
        loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
        loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY; /* Method association coded index */
 
-       if (!bsearch (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator))
+       if (!mono_binary_search (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator))
                return 0;
 
        start = loc.result;
@@ -5195,7 +5209,7 @@ mono_metadata_implmap_from_method (MonoImage *meta, guint32 method_idx)
        loc.col_idx = MONO_IMPLMAP_MEMBER;
        loc.idx = ((method_idx + 1) << MONO_MEMBERFORWD_BITS) | MONO_MEMBERFORWD_METHODDEF;
 
-       if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
+       if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
                return 0;
 
        return loc.result + 1;
@@ -5217,7 +5231,6 @@ mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
        const char *ptr;
        guint32 len;
        MonoType *type, *type2;
-       MonoType stack_type;
 
        mono_loader_lock ();
 
@@ -5239,15 +5252,8 @@ mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
 
        len = mono_metadata_decode_value (ptr, &ptr);
 
-       type = &stack_type;
-       memset (type, 0, MONO_SIZEOF_TYPE);
-
-       if (*ptr == MONO_TYPE_BYREF) {
-               type->byref = 1;
-               ptr++;
-       }
-
-       if (!do_mono_metadata_parse_type (type, image, NULL, FALSE, ptr, &ptr)) {
+       type = mono_metadata_parse_type_internal (image, NULL, MONO_PARSE_TYPE, 0, TRUE, ptr, &ptr);
+       if (!type) {
                mono_loader_unlock ();
                return NULL;
        }
@@ -5259,9 +5265,9 @@ mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
                return type2;
        }
 
-       type2 = mono_image_alloc (image, MONO_SIZEOF_TYPE);
-       memcpy (type2, type, MONO_SIZEOF_TYPE);
+       type2 = mono_metadata_type_dup (image, type);
        g_hash_table_insert (image->typespec_cache, GUINT_TO_POINTER (type_spec), type2);
+       mono_metadata_free_type (type);
 
        mono_loader_unlock ();
 
@@ -5421,7 +5427,17 @@ handle_enum:
                }
                *conv = MONO_MARSHAL_CONV_BOOL_I4;
                return MONO_NATIVE_BOOLEAN;
-       case MONO_TYPE_CHAR: return MONO_NATIVE_U2;
+       case MONO_TYPE_CHAR:
+               if (mspec) {
+                       switch (mspec->native) {
+                       case MONO_NATIVE_U2:
+                       case MONO_NATIVE_U1:
+                               return mspec->native;
+                       default:
+                               g_error ("cant marshal char to native type %02x", mspec->native);
+                       }
+               }
+               return unicode ? MONO_NATIVE_U2 : MONO_NATIVE_U1;
        case MONO_TYPE_I1: return MONO_NATIVE_I1;
        case MONO_TYPE_U1: return MONO_NATIVE_U1;
        case MONO_TYPE_I2: return MONO_NATIVE_I2;
@@ -5577,7 +5593,7 @@ mono_metadata_get_marshal_info (MonoImage *meta, guint32 idx, gboolean is_field)
 
        /* FIXME: Index translation */
 
-       if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
+       if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
                return NULL;
 
        return mono_metadata_blob_heap (meta, mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_MARSHAL_NATIVE_TYPE));
@@ -5630,7 +5646,7 @@ mono_class_get_overrides_full (MonoImage *image, guint32 type_token, MonoMethod
        loc.col_idx = MONO_METHODIMPL_CLASS;
        loc.idx = mono_metadata_token_index (type_token);
 
-       if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
+       if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
                return TRUE;
 
        start = loc.result;
@@ -5770,7 +5786,7 @@ mono_metadata_get_generic_param_row (MonoImage *image, guint32 token, guint32 *o
        loc.col_idx = MONO_GENERICPARAM_OWNER;
        loc.t = tdef;
 
-       if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
+       if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
                return 0;
 
        /* Find the first entry by searching backwards */
@@ -6185,6 +6201,21 @@ mono_signature_is_instance (MonoMethodSignature *sig)
        return sig->hasthis;
 }
 
+/**
+ * mono_signature_param_is_out
+ * @sig: the method signature inspected
+ * @param_num: the 0-based index of the inspected parameter
+ * 
+ * Returns: #TRUE if the parameter is an out parameter, #FALSE
+ * otherwise.
+ */
+mono_bool
+mono_signature_param_is_out (MonoMethodSignature *sig, int param_num)
+{
+       g_assert (param_num >= 0 && param_num < sig->param_count);
+       return (sig->params [param_num]->attrs & PARAM_ATTRIBUTE_OUT) != 0;
+}
+
 /**
  * mono_signature_explicit_this:
  * @sig: the method signature inspected