X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fmetadata.c;h=b24838da7b8ec6dc601c33872d830b2a37d6f5e5;hb=07e742b4fe7519428d788a39f51bee556d681273;hp=f37cb1abb59f790d9a03b96130e5c48567b2761a;hpb=b2be0f24c77b8b7b0b38be7ccc65bc2c9cf222b1;p=mono.git diff --git a/mono/metadata/metadata.c b/mono/metadata/metadata.c index f37cb1abb59..b24838da7b8 100644 --- a/mono/metadata/metadata.c +++ b/mono/metadata/metadata.c @@ -27,6 +27,7 @@ static gboolean do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoG static gboolean do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only); static gboolean mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only); +static gboolean mono_metadata_fnptr_equal (MonoMethodSignature *s1, MonoMethodSignature *s2, gboolean signature_only); static gboolean _mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2, gboolean signature_only); @@ -174,7 +175,11 @@ const static unsigned char TableSchemas [] = { MONO_MT_TABLE_IDX, /* "EventType" }, TypeDef or TypeRef */ MONO_MT_END, -#define EXPORTED_TYPE_SCHEMA_OFFSET EVENT_SCHEMA_OFFSET + 4 +#define EVENT_POINTER_SCHEMA_OFFSET EVENT_SCHEMA_OFFSET + 4 + MONO_MT_TABLE_IDX, /* "Event" }, */ + MONO_MT_END, + +#define EXPORTED_TYPE_SCHEMA_OFFSET EVENT_POINTER_SCHEMA_OFFSET + 2 MONO_MT_UINT32, /* "Flags" }, */ MONO_MT_TABLE_IDX, /* "TypeDefId" }, */ MONO_MT_STRING_IDX, /* "TypeName" }, */ @@ -203,7 +208,11 @@ const static unsigned char TableSchemas [] = { MONO_MT_TABLE_IDX, /* "Field:Field" }, */ MONO_MT_END, -#define FILE_SCHEMA_OFFSET FIELD_RVA_SCHEMA_OFFSET + 3 +#define FIELD_POINTER_SCHEMA_OFFSET FIELD_RVA_SCHEMA_OFFSET + 3 + MONO_MT_TABLE_IDX, /* "Field" }, */ + MONO_MT_END, + +#define FILE_SCHEMA_OFFSET FIELD_POINTER_SCHEMA_OFFSET + 2 MONO_MT_UINT32, /* "Flags" }, */ MONO_MT_STRING_IDX, /* "Name" }, */ MONO_MT_BLOB_IDX, /* "Value" }, */ @@ -255,7 +264,11 @@ const static unsigned char TableSchemas [] = { MONO_MT_HS_IDX, /* "Association" }, */ MONO_MT_END, -#define MODULE_SCHEMA_OFFSET METHOD_SEMA_SCHEMA_OFFSET + 4 +#define METHOD_POINTER_SCHEMA_OFFSET METHOD_SEMA_SCHEMA_OFFSET + 4 + MONO_MT_TABLE_IDX, /* "Method" }, */ + MONO_MT_END, + +#define MODULE_SCHEMA_OFFSET METHOD_POINTER_SCHEMA_OFFSET + 2 MONO_MT_UINT16, /* "Generation" }, */ MONO_MT_STRING_IDX, /* "Name" }, */ MONO_MT_GUID_IDX, /* "MVID" }, */ @@ -278,13 +291,21 @@ const static unsigned char TableSchemas [] = { MONO_MT_STRING_IDX, /* "Name" }, */ MONO_MT_END, -#define PROPERTY_SCHEMA_OFFSET PARAM_SCHEMA_OFFSET + 4 +#define PARAM_POINTER_SCHEMA_OFFSET PARAM_SCHEMA_OFFSET + 4 + MONO_MT_TABLE_IDX, /* "Param" }, */ + MONO_MT_END, + +#define PROPERTY_SCHEMA_OFFSET PARAM_POINTER_SCHEMA_OFFSET + 2 MONO_MT_UINT16, /* "Flags" }, */ MONO_MT_STRING_IDX, /* "Name" }, */ MONO_MT_BLOB_IDX, /* "Type" }, */ MONO_MT_END, -#define PROPERTY_MAP_SCHEMA_OFFSET PROPERTY_SCHEMA_OFFSET + 4 +#define PROPERTY_POINTER_SCHEMA_OFFSET PROPERTY_SCHEMA_OFFSET + 4 + MONO_MT_TABLE_IDX, /* "Property" }, */ + MONO_MT_END, + +#define PROPERTY_MAP_SCHEMA_OFFSET PROPERTY_POINTER_SCHEMA_OFFSET + 2 MONO_MT_TABLE_IDX, /* "Parent:TypeDef" }, */ MONO_MT_TABLE_IDX, /* "PropertyList:Property" }, */ MONO_MT_END, @@ -339,11 +360,11 @@ table_description [] = { MODULE_SCHEMA_OFFSET, TYPEREF_SCHEMA_OFFSET, TYPEDEF_SCHEMA_OFFSET, - NULL_SCHEMA_OFFSET, + FIELD_POINTER_SCHEMA_OFFSET, FIELD_SCHEMA_OFFSET, - NULL_SCHEMA_OFFSET, + METHOD_POINTER_SCHEMA_OFFSET, METHOD_SCHEMA_OFFSET, - NULL_SCHEMA_OFFSET, + PARAM_POINTER_SCHEMA_OFFSET, PARAM_SCHEMA_OFFSET, IFACEMAP_SCHEMA_OFFSET, MEMBERREF_SCHEMA_OFFSET, /* 0xa */ @@ -355,10 +376,10 @@ table_description [] = { FIELD_LAYOUT_SCHEMA_OFFSET, /* 0x10 */ STDALON_SIG_SCHEMA_OFFSET, EVENTMAP_SCHEMA_OFFSET, - NULL_SCHEMA_OFFSET, + EVENT_POINTER_SCHEMA_OFFSET, EVENT_SCHEMA_OFFSET, PROPERTY_MAP_SCHEMA_OFFSET, - NULL_SCHEMA_OFFSET, + PROPERTY_POINTER_SCHEMA_OFFSET, PROPERTY_SCHEMA_OFFSET, METHOD_SEMA_SCHEMA_OFFSET, METHOD_IMPL_SCHEMA_OFFSET, @@ -511,6 +532,9 @@ mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bit field_size = MAX (idx_size (MONO_TABLE_TYPEDEF), idx_size(MONO_TABLE_TYPEREF)); field_size = MAX (field_size, idx_size(MONO_TABLE_TYPESPEC)); break; + case MONO_TABLE_EVENT_POINTER: + g_assert (i == 0); + field_size = idx_size (MONO_TABLE_EVENT); break; case MONO_TABLE_EXPORTEDTYPE: g_assert (i == 1); /* the index is in another metadata file, so it must be 4 */ @@ -521,6 +545,9 @@ mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bit case MONO_TABLE_FIELDRVA: g_assert (i == 1); field_size = idx_size (MONO_TABLE_FIELD); break; + case MONO_TABLE_FIELD_POINTER: + g_assert (i == 0); + field_size = idx_size (MONO_TABLE_FIELD); break; case MONO_TABLE_IMPLMAP: g_assert (i == 3); field_size = idx_size (MONO_TABLE_MODULEREF); break; @@ -536,14 +563,23 @@ mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bit case MONO_TABLE_METHODSEMANTICS: g_assert (i == 1); field_size = idx_size (MONO_TABLE_METHOD); break; + case MONO_TABLE_METHOD_POINTER: + g_assert (i == 0); + field_size = idx_size (MONO_TABLE_METHOD); break; case MONO_TABLE_NESTEDCLASS: g_assert (i == 0 || i == 1); field_size = idx_size (MONO_TABLE_TYPEDEF); break; + case MONO_TABLE_PARAM_POINTER: + g_assert (i == 0); + field_size = idx_size (MONO_TABLE_PARAM); break; case MONO_TABLE_PROPERTYMAP: g_assert (i == 0 || i == 1); field_size = i ? idx_size (MONO_TABLE_PROPERTY): idx_size(MONO_TABLE_TYPEDEF); break; + case MONO_TABLE_PROPERTY_POINTER: + g_assert (i == 0); + field_size = idx_size (MONO_TABLE_PROPERTY); break; case MONO_TABLE_TYPEDEF: g_assert (i == 4 || i == 5); field_size = i == 4 ? idx_size (MONO_TABLE_FIELD): @@ -966,6 +1002,7 @@ mono_metadata_decode_row_col (const MonoTableInfo *t, int idx, guint col) } return 0; } + /** * mono_metadata_decode_blob_size: * @ptr: pointer to a blob object @@ -1067,6 +1104,82 @@ mono_metadata_decode_signed_value (const char *ptr, const char **rptr) return ival - 0x20000000; } +/* + * Translates the given 1-based index into the Method, Field, Event, or Param tables + * using the *Ptr tables in uncompressed metadata, if they are available. + * + * FIXME: The caller is not forced to call this function, which is error-prone, since + * forgetting to call it would only show up as a bug on uncompressed metadata. + */ +guint32 +mono_metadata_translate_token_index (MonoImage *image, int table, guint32 idx) +{ + if (!image->uncompressed_metadata) + return idx; + + switch (table) { + case MONO_TABLE_METHOD: + if (image->tables [MONO_TABLE_METHOD_POINTER].rows) + return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD_POINTER], idx - 1, MONO_METHOD_POINTER_METHOD); + else + return idx; + case MONO_TABLE_FIELD: + if (image->tables [MONO_TABLE_FIELD_POINTER].rows) + return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_FIELD_POINTER], idx - 1, MONO_FIELD_POINTER_FIELD); + else + return idx; + case MONO_TABLE_EVENT: + if (image->tables [MONO_TABLE_EVENT_POINTER].rows) + return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_EVENT_POINTER], idx - 1, MONO_EVENT_POINTER_EVENT); + else + return idx; + case MONO_TABLE_PROPERTY: + if (image->tables [MONO_TABLE_PROPERTY_POINTER].rows) + return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_PROPERTY_POINTER], idx - 1, MONO_PROPERTY_POINTER_PROPERTY); + else + return idx; + case MONO_TABLE_PARAM: + if (image->tables [MONO_TABLE_PARAM_POINTER].rows) + return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_PARAM_POINTER], idx - 1, MONO_PARAM_POINTER_PARAM); + else + return idx; + default: + return idx; + } +} + +/** + * mono_metadata_decode_table_row: + * + * Same as mono_metadata_decode_row, but takes an IMAGE+TABLE ID pair, and takes + * uncompressed metadata into account, so it should be used to access the + * Method, Field, Param and Event tables when the access is made from metadata, i.e. + * IDX is retrieved from a metadata table, like MONO_TYPEDEF_FIELD_LIST. + */ +void +mono_metadata_decode_table_row (MonoImage *image, int table, int idx, guint32 *res, int res_size) +{ + if (image->uncompressed_metadata) + idx = mono_metadata_translate_token_index (image, table, idx + 1) - 1; + + mono_metadata_decode_row (&image->tables [table], idx, res, res_size); +} + +/** + * mono_metadata_decode_table_row_col: + * + * Same as mono_metadata_decode_row_col, but takes an IMAGE+TABLE ID pair, and takes + * uncompressed metadata into account, so it should be used to access the + * Method, Field, Param and Event tables. + */ +guint32 mono_metadata_decode_table_row_col (MonoImage *image, int table, int idx, guint col) +{ + if (image->uncompressed_metadata) + idx = mono_metadata_translate_token_index (image, table, idx + 1) - 1; + + return mono_metadata_decode_row_col (&image->tables [table], idx, col); +} + /* * mono_metadata_parse_typedef_or_ref: * @m: a metadata context. @@ -1326,6 +1439,20 @@ mono_metadata_init (void) g_hash_table_insert (type_cache, (gpointer) &builtin_types [i], (gpointer) &builtin_types [i]); } +/** + * mono_metadata_cleanup: + * + * Free all resources used by this module. + * This is a Mono runtime internal function. + */ +void +mono_metadata_cleanup (void) +{ + g_hash_table_destroy (type_cache); + g_hash_table_destroy (generic_inst_cache); + g_hash_table_destroy (generic_class_cache); +} + /** * mono_metadata_parse_type: * @m: metadata context @@ -1347,6 +1474,8 @@ mono_metadata_init (void) * this MonoGenericContainer. * This is a Mono runtime internal function. * + * LOCKING: Assumes the loader lock is held. + * * Returns: a #MonoType structure representing the decoded type. */ MonoType* @@ -1393,7 +1522,7 @@ mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, Mo } if (count) { - type = g_malloc0 (sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod)); + type = mono_mempool_alloc0 (m->mempool, sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod)); type->num_mods = count; if (count > 64) g_warning ("got more than 64 modifiers in type"); @@ -1438,11 +1567,7 @@ mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, Mo if (rptr) *rptr = ptr; - - /* FIXME: remove the != MONO_PARSE_PARAM condition, this accounts for - * almost 10k (about 2/3rds) of all MonoType's we create. - */ - if (mode != MONO_PARSE_PARAM && !type->num_mods) { + if (!type->num_mods) { /* no need to free type here, because it is on the stack */ if ((type->type == MONO_TYPE_CLASS || type->type == MONO_TYPE_VALUETYPE) && !type->pinned && !type->attrs) { MonoType *ret = type->byref ? &type->data.klass->this_arg : &type->data.klass->byval_arg; @@ -1473,13 +1598,18 @@ mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, Mo return cached; } - /*printf ("%x%c %s\n", type->attrs, type->pinned ? 'p' : ' ', mono_type_full_name (type));*/ + /* printf ("%x %x %c %s\n", type->attrs, type->num_mods, type->pinned ? 'p' : ' ', mono_type_full_name (type)); */ - if (type == &stype) - type = g_memdup (&stype, sizeof (MonoType)); + if (type == &stype) { + type = mono_mempool_alloc (m->mempool, sizeof (MonoType)); + memcpy (type, &stype, sizeof (MonoType)); + } return type; } +/* + * LOCKING: Assumes the loader lock is held. + */ MonoType* mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs, const char *ptr, const char **rptr) @@ -1487,6 +1617,39 @@ mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs, return mono_metadata_parse_type_full (m, NULL, mode, opt_attrs, ptr, rptr); } +/* + * mono_metadata_get_param_attrs: + * + * Return the parameter attributes for the method whose MethodDef index is DEF. The + * returned memory needs to be freed by the caller. If all the param attributes are + * 0, then NULL is returned. + */ +int* +mono_metadata_get_param_attrs (MonoImage *m, int def) +{ + MonoTableInfo *paramt = &m->tables [MONO_TABLE_PARAM]; + MonoTableInfo *methodt = &m->tables [MONO_TABLE_METHOD]; + guint32 cols [MONO_PARAM_SIZE]; + guint lastp, i, param_index = mono_metadata_decode_row_col (&m->tables [MONO_TABLE_METHOD], def - 1, MONO_METHOD_PARAMLIST); + int *pattrs = NULL; + + if (def < methodt->rows) + lastp = mono_metadata_decode_row_col (&m->tables [MONO_TABLE_METHOD], def, MONO_METHOD_PARAMLIST); + else + lastp = paramt->rows + 1; + + for (i = param_index; i < lastp; ++i) { + mono_metadata_decode_row (&m->tables [MONO_TABLE_PARAM], i - 1, cols, MONO_PARAM_SIZE); + if (cols [MONO_PARAM_FLAGS]) { + if (!pattrs) + pattrs = g_new0 (int, 1 + (lastp - param_index)); + pattrs [cols [MONO_PARAM_SEQUENCE]] = cols [MONO_PARAM_FLAGS]; + } + } + + return pattrs; +} + /* * mono_metadata_parse_signature_full: * @image: metadata context @@ -1495,6 +1658,8 @@ mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs, * * Decode a method signature stored in the STANDALONESIG table * + * LOCKING: Assumes the loader lock is held. + * * Returns: a MonoMethodSignature describing the signature. */ MonoMethodSignature* @@ -1515,7 +1680,7 @@ mono_metadata_parse_signature_full (MonoImage *image, MonoGenericContainer *gene ptr = mono_metadata_blob_heap (image, sig); mono_metadata_decode_blob_size (ptr, &ptr); - return mono_metadata_parse_method_signature_full (image, generic_container, FALSE, ptr, NULL); + return mono_metadata_parse_method_signature_full (image, generic_container, 0, ptr, NULL); } /* @@ -1542,6 +1707,8 @@ mono_metadata_parse_signature (MonoImage *image, guint32 token) * The return type and the params types need to be filled later. * This is a Mono runtime internal function. * + * LOCKING: Assumes the loader lock is held. + * * Returns: the new MonoMethodSignature structure. */ MonoMethodSignature* @@ -1549,8 +1716,7 @@ mono_metadata_signature_alloc (MonoImage *m, guint32 nparams) { MonoMethodSignature *sig; - /* later we want to allocate signatures with mempools */ - sig = g_malloc0 (sizeof (MonoMethodSignature) + ((gint32)nparams - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*)); + sig = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodSignature) + ((gint32)nparams - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*)); sig->param_count = nparams; sig->sentinelpos = -1; @@ -1586,6 +1752,8 @@ mono_metadata_signature_dup (MonoMethodSignature *sig) * Decode a method signature stored at @ptr. * This is a Mono runtime internal function. * + * LOCKING: Assumes the loader lock is held. + * * Returns: a MonoMethodSignature describing the signature. */ MonoMethodSignature * @@ -1610,23 +1778,8 @@ mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *c gen_param_count = mono_metadata_decode_value (ptr, &ptr); param_count = mono_metadata_decode_value (ptr, &ptr); - if (def) { - MonoTableInfo *paramt = &m->tables [MONO_TABLE_PARAM]; - MonoTableInfo *methodt = &m->tables [MONO_TABLE_METHOD]; - guint32 cols [MONO_PARAM_SIZE]; - guint lastp, param_index = mono_metadata_decode_row_col (methodt, def - 1, MONO_METHOD_PARAMLIST); - - if (def < methodt->rows) - lastp = mono_metadata_decode_row_col (methodt, def, MONO_METHOD_PARAMLIST); - else - lastp = paramt->rows + 1; - - pattrs = g_new0 (int, 1 + param_count); - for (i = param_index; i < lastp; ++i) { - mono_metadata_decode_row (paramt, i - 1, cols, MONO_PARAM_SIZE); - pattrs [cols [MONO_PARAM_SEQUENCE]] = cols [MONO_PARAM_FLAGS]; - } - } + if (def) + pattrs = mono_metadata_get_param_attrs (m, def); method = mono_metadata_signature_alloc (m, param_count); method->hasthis = hasthis; method->explicit_this = explicit_this; @@ -1647,6 +1800,8 @@ mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *c if (*ptr == MONO_TYPE_SENTINEL) { if (method->call_convention != MONO_CALL_VARARG || def) g_error ("found sentinel for methoddef or no vararg method"); + if (method->sentinelpos >= 0) + g_error ("found sentinel twice in the same signature"); method->sentinelpos = i; ptr++; } @@ -1660,6 +1815,10 @@ mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *c is_open = mono_class_is_open_constructed_type (method->params [i]); } + /* The sentinel could be missing if the caller does not pass any additional arguments */ + if (!def && method->call_convention == MONO_CALL_VARARG && method->sentinelpos < 0) + method->sentinelpos = method->param_count; + method->has_type_parameters = is_open; if (def && (method->call_convention == MONO_CALL_VARARG)) @@ -1686,6 +1845,8 @@ mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *c * Decode a method signature stored at @ptr. * This is a Mono runtime internal function. * + * LOCKING: Assumes the loader lock is held. + * * Returns: a MonoMethodSignature describing the signature. */ MonoMethodSignature * @@ -1712,8 +1873,6 @@ mono_metadata_free_method_signature (MonoMethodSignature *sig) if (sig->params [i]) mono_metadata_free_type (sig->params [i]); } - - g_free (sig); } /* @@ -1840,7 +1999,7 @@ mono_metadata_parse_generic_inst (MonoImage *m, MonoGenericContainer *container, return mono_metadata_lookup_generic_inst (ginst); } -static void +static gboolean do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericContainer *container, const char *ptr, const char **rptr) { @@ -1867,6 +2026,8 @@ do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericC igclass->klass = g_new0 (MonoClass, 1); gtype = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr); + if (gtype == NULL) + return FALSE; gclass->container_class = gklass = mono_class_from_mono_type (gtype); g_assert (gklass->generic_container); @@ -1879,6 +2040,10 @@ do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericC if (rptr) *rptr = ptr; + /* If we failed to parse, return, the error has been flagged. */ + if (gclass->inst == NULL) + return FALSE; + /* * We may be called multiple times on different metadata to create the same * instantiated type. This happens for instance if we're part of a method or @@ -1899,7 +2064,7 @@ do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericC g_free (gclass); type->data.generic_class = cached; - return; + return TRUE; } else { g_hash_table_insert (generic_class_cache, gclass, gclass); @@ -1908,6 +2073,7 @@ do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericC sizeof (MonoGenericContext) + gclass->inst->type_argc * sizeof (MonoType); } + return TRUE; } /* @@ -1925,17 +2091,14 @@ select_container (MonoGenericContainer *gc, MonoTypeEnum type) g_assert (is_var || type == MONO_TYPE_MVAR); - if (is_var && gc->parent) - /* - * The current MonoGenericContainer is a generic method -> its `parent' - * points to the containing class'es container. - */ - gc = gc->parent; - - /* - * Ensure that we have the correct type of GenericContainer. - */ - g_assert (is_var == !gc->is_method); + if (is_var) { + if (gc->is_method || gc->parent) + /* + * The current MonoGenericContainer is a generic method -> its `parent' + * points to the containing class'es container. + */ + return gc->parent; + } return gc; } @@ -1992,6 +2155,7 @@ static gboolean do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container, const char *ptr, const char **rptr) { + gboolean ok = TRUE; type->type = mono_metadata_decode_value (ptr, &ptr); switch (type->type){ @@ -2047,7 +2211,7 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer type->data.generic_param = mono_metadata_parse_generic_param (m, container, type->type, ptr, &ptr); break; case MONO_TYPE_GENERICINST: - do_mono_metadata_parse_generic_class (type, m, container, ptr, &ptr); + ok = do_mono_metadata_parse_generic_class (type, m, container, ptr, &ptr); break; default: g_error ("type 0x%02x not handled in do_mono_metadata_parse_type", type->type); @@ -2055,14 +2219,15 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer if (rptr) *rptr = ptr; - return TRUE; + return ok; } /* * mono_metadata_free_type: * @type: type to free * - * Free the memory allocated for type @type. + * Free the memory allocated for type @type which is assumed to be created by + * mono_metadata_parse_type (). */ void mono_metadata_free_type (MonoType *type) @@ -2091,7 +2256,8 @@ mono_metadata_free_type (MonoType *type) mono_metadata_free_array (type->data.array); break; } - g_free (type); + + /* Allocated from a mempool, no need to free it */ } #if 0 @@ -2157,7 +2323,7 @@ parse_section_data (MonoImage *m, MonoMethodHeader *mh, const unsigned char *ptr int i; mh->num_clauses = is_fat ? sect_data_len / 24: sect_data_len / 12; /* we could just store a pointer if we don't need to byteswap */ - mh->clauses = g_new0 (MonoExceptionClause, mh->num_clauses); + mh->clauses = mono_mempool_alloc0 (m->mempool, sizeof (MonoExceptionClause) * mh->num_clauses); for (i = 0; i < mh->num_clauses; ++i) { MonoExceptionClause *ec = &mh->clauses [i]; guint32 tof_value; @@ -2206,7 +2372,9 @@ parse_section_data (MonoImage *m, MonoMethodHeader *mh, const unsigned char *ptr * info about local variables and optional exception tables. * This is a Mono runtime internal function. * - * Returns: a MonoMethodHeader. + * LOCKING: Assumes the loader lock is held. + * + * Returns: a MonoMethodHeader allocated from the image mempool. */ MonoMethodHeader * mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, const char *ptr) @@ -2223,7 +2391,7 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons switch (format) { case METHOD_HEADER_TINY_FORMAT: - mh = g_new0 (MonoMethodHeader, 1); + mh = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodHeader)); ptr++; mh->max_stack = 8; local_var_sig_tok = 0; @@ -2231,7 +2399,7 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons mh->code = ptr; return mh; case METHOD_HEADER_TINY_FORMAT1: - mh = g_new0 (MonoMethodHeader, 1); + mh = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodHeader)); ptr++; mh->max_stack = 8; local_var_sig_tok = 0; @@ -2286,18 +2454,17 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons g_warning ("wrong signature for locals blob"); locals_ptr++; len = mono_metadata_decode_value (locals_ptr, &locals_ptr); - mh = g_malloc0 (sizeof (MonoMethodHeader) + (len - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*)); + mh = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodHeader) + (len - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*)); mh->num_locals = len; for (i = 0; i < len; ++i) { mh->locals [i] = mono_metadata_parse_type_full ( m, container, MONO_PARSE_LOCAL, 0, locals_ptr, &locals_ptr); if (!mh->locals [i]) { - g_free (mh); return NULL; } } } else { - mh = g_new0 (MonoMethodHeader, 1); + mh = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodHeader)); } mh->code = code; mh->code_size = code_size; @@ -2322,7 +2489,15 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons MonoMethodHeader * mono_metadata_parse_mh (MonoImage *m, const char *ptr) { - return mono_metadata_parse_mh_full (m, NULL, ptr); + MonoMethodHeader *res; + + mono_loader_lock (); + + res = mono_metadata_parse_mh_full (m, NULL, ptr); + + mono_loader_unlock (); + + return res; } /* @@ -2335,11 +2510,7 @@ mono_metadata_parse_mh (MonoImage *m, const char *ptr) void mono_metadata_free_mh (MonoMethodHeader *mh) { - int i; - for (i = 0; i < mh->num_locals; ++i) - mono_metadata_free_type (mh->locals[i]); - g_free (mh->clauses); - g_free (mh); + /* Allocated from the mempool */ } /* @@ -2615,6 +2786,30 @@ declsec_locator (const void *a, const void *b) return 1; } +/** + * search_ptr_table: + * + * Return the 1-based row index in TABLE, which must be one of the *Ptr tables, + * which contains IDX. + */ +static guint32 +search_ptr_table (MonoImage *image, int table, int idx) +{ + MonoTableInfo *ptrdef = &image->tables [table]; + int i; + + /* Use a linear search to find our index in the table */ + for (i = 0; i < ptrdef->rows; i ++) + /* All the Ptr tables have the same structure */ + if (mono_metadata_decode_row_col (ptrdef, i, 0) == idx) + break; + + if (i < ptrdef->rows) + return i + 1; + else + return idx; +} + /** * mono_metadata_typedef_from_field: * @meta: metadata context @@ -2636,6 +2831,9 @@ mono_metadata_typedef_from_field (MonoImage *meta, guint32 index) loc.col_idx = MONO_TYPEDEF_FIELD_LIST; loc.t = tdef; + 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)) g_assert_not_reached (); @@ -2664,6 +2862,9 @@ mono_metadata_typedef_from_method (MonoImage *meta, guint32 index) loc.col_idx = MONO_TYPEDEF_METHOD_LIST; loc.t = tdef; + 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)) g_assert_not_reached (); @@ -2679,6 +2880,8 @@ mono_metadata_typedef_from_method (MonoImage *meta, guint32 index) * The array of interfaces that the @index typedef token implements is returned in * @interfaces. The number of elemnts in the array is returned in @count. * + * LOCKING: Assumes the loader lock is held. + * * Returns: TRUE on success, FALSE on failure. */ gboolean @@ -2686,7 +2889,7 @@ mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, Mono { MonoTableInfo *tdef = &meta->tables [MONO_TABLE_INTERFACEIMPL]; locator_t loc; - guint32 start, i; + guint32 start, pos; guint32 cols [MONO_INTERFACEIMPL_SIZE]; MonoClass **result; @@ -2713,18 +2916,31 @@ mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, Mono else break; } - result = NULL; - i = 0; - while (start < tdef->rows) { - mono_metadata_decode_row (tdef, start, cols, MONO_INTERFACEIMPL_SIZE); + pos = start; + while (pos < tdef->rows) { + mono_metadata_decode_row (tdef, pos, cols, MONO_INTERFACEIMPL_SIZE); + if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx) + break; + ++pos; + } + + result = mono_mempool_alloc0 (meta->mempool, sizeof (MonoClass*) * (pos - start)); + + pos = start; + while (pos < tdef->rows) { + MonoClass *iface; + + mono_metadata_decode_row (tdef, pos, cols, MONO_INTERFACEIMPL_SIZE); if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx) break; - result = g_renew (MonoClass*, result, i + 1); - result [i] = mono_class_get_full ( + iface = mono_class_get_full ( meta, mono_metadata_token_from_dor (cols [MONO_INTERFACEIMPL_INTERFACE]), context); - *count = ++i; - ++start; + if (iface == NULL) + return FALSE; + result [pos - start] = iface; + ++pos; } + *count = pos - start; *interfaces = result; return TRUE; } @@ -2735,7 +2951,9 @@ mono_metadata_interfaces_from_typedef (MonoImage *meta, guint32 index, guint *co MonoClass **interfaces; gboolean rv; + mono_loader_lock (); rv = mono_metadata_interfaces_from_typedef_full (meta, index, &interfaces, count, NULL); + mono_loader_unlock (); if (rv) return interfaces; else @@ -2863,6 +3081,8 @@ mono_metadata_custom_attrs_from_index (MonoImage *meta, guint32 index) loc.col_idx = MONO_CUSTOM_ATTR_PARENT; loc.t = tdef; + /* FIXME: Index translation */ + if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) return 0; @@ -2935,7 +3155,7 @@ mono_backtrace (int limit) * type in memory */ int -mono_type_size (MonoType *t, gint *align) +mono_type_size (MonoType *t, int *align) { if (!t) { *align = 1; @@ -3006,8 +3226,8 @@ mono_type_size (MonoType *t, gint *align) MonoClass *container_class; gclass = mono_get_inflated_generic_class (t->data.generic_class); - g_assert (!gclass->generic_class.inst->is_open); - g_assert (!gclass->klass->generic_container); + // g_assert (!gclass->generic_class.inst->is_open); + // g_assert (!gclass->klass->generic_container); container_class = gclass->generic_class.container_class; @@ -3040,9 +3260,9 @@ mono_type_size (MonoType *t, gint *align) * type on the runtime stack */ int -mono_type_stack_size (MonoType *t, gint *align) +mono_type_stack_size (MonoType *t, int *align) { - int tmp; + guint32 tmp; g_assert (t != NULL); @@ -3249,6 +3469,37 @@ mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only return FALSE; } +static gboolean +mono_metadata_fnptr_equal (MonoMethodSignature *s1, MonoMethodSignature *s2, gboolean signature_only) +{ + gpointer iter1 = 0, iter2 = 0; + + if (s1 == s2) + return TRUE; + if (s1->call_convention != s2->call_convention) + return FALSE; + if (s1->sentinelpos != s2->sentinelpos) + return FALSE; + if (s1->hasthis != s2->hasthis) + return FALSE; + if (s1->explicit_this != s2->explicit_this) + return FALSE; + if (! do_mono_metadata_type_equal (s1->ret, s2->ret, signature_only)) + return FALSE; + if (s1->param_count != s2->param_count) + return FALSE; + + while (TRUE) { + MonoType *t1 = mono_signature_get_params (s1, &iter1); + MonoType *t2 = mono_signature_get_params (s2, &iter2); + + if (t1 == NULL || t2 == NULL) + return (t1 == t2); + if (! do_mono_metadata_type_equal (t1, t2, signature_only)) + return FALSE; + } +} + /* * mono_metadata_type_equal: * @t1: a type @@ -3302,6 +3553,8 @@ do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only case MONO_TYPE_MVAR: return mono_metadata_generic_param_equal ( t1->data.generic_param, t2->data.generic_param, signature_only); + case MONO_TYPE_FNPTR: + return mono_metadata_fnptr_equal (t1->data.method, t2->data.method, signature_only); default: g_error ("implement type compare for %0x!", t1->type); return FALSE; @@ -3358,6 +3611,31 @@ mono_metadata_signature_equal (MonoMethodSignature *sig1, MonoMethodSignature *s return TRUE; } +/** + * mono_metadata_type_dup_mp: + * @image: image type is defined in + * @original: type to duplicate + * + * Returns: copy of type allocated from mempool. + */ +MonoType * +mono_metadata_type_dup_mp (MonoImage *image, const MonoType *original) +{ + MonoType *r = NULL; + mono_loader_lock (); + r = mono_mempool_alloc0 (image->mempool, sizeof(MonoType)); + mono_loader_unlock (); + *r = *original; + /* FIXME: we don't handle these yet because they need to duplicate memory + * but the current routines used are not using the mempools + */ + if (original->type == MONO_TYPE_PTR || + original->type == MONO_TYPE_ARRAY || + original->type == MONO_TYPE_FNPTR) + g_assert_not_reached (); + return r; +} + guint mono_signature_hash (MonoMethodSignature *sig) { @@ -3425,6 +3703,9 @@ mono_metadata_field_info (MonoImage *meta, guint32 index, guint32 *offset, guint locator_t loc; loc.idx = index + 1; + if (meta->uncompressed_metadata) + loc.idx = search_ptr_table (meta, MONO_TABLE_FIELD_POINTER, loc.idx); + if (offset) { tdef = &meta->tables [MONO_TABLE_FIELDLAYOUT]; @@ -3499,6 +3780,8 @@ mono_metadata_get_constant_index (MonoImage *meta, guint32 token, guint32 hint) loc.col_idx = MONO_CONSTANT_PARENT; loc.t = tdef; + /* FIXME: Index translation */ + if ((hint > 0) && (hint < tdef->rows) && (mono_metadata_decode_row_col (tdef, hint - 1, MONO_CONSTANT_PARENT) == index)) return hint; @@ -3568,6 +3851,9 @@ mono_metadata_methods_from_event (MonoImage *meta, guint32 index, guint *end_i if (!msemt->base) return 0; + if (meta->uncompressed_metadata) + index = search_ptr_table (meta, MONO_TABLE_EVENT_POINTER, index + 1) - 1; + loc.t = msemt; loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION; loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT; /* Method association coded index */ @@ -3656,6 +3942,9 @@ mono_metadata_methods_from_property (MonoImage *meta, guint32 index, guint *en if (!msemt->base) return 0; + if (meta->uncompressed_metadata) + index = search_ptr_table (meta, MONO_TABLE_PROPERTY_POINTER, index + 1) - 1; + loc.t = msemt; loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION; loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY; /* Method association coded index */ @@ -3693,6 +3982,8 @@ mono_metadata_implmap_from_method (MonoImage *meta, guint32 method_idx) if (!tdef->base) return 0; + /* No index translation seems to be needed */ + loc.t = tdef; loc.col_idx = MONO_IMPLMAP_MEMBER; loc.idx = ((method_idx + 1) << MONO_MEMBERFORWD_BITS) | MONO_MEMBERFORWD_METHODDEF; @@ -3932,7 +4223,10 @@ handle_enum: if (mspec) { switch (mspec->native) { case MONO_NATIVE_BYVALARRAY: - *conv = MONO_MARSHAL_CONV_ARRAY_BYVALARRAY; + if ((type->data.klass->element_class == mono_defaults.char_class) && !unicode) + *conv = MONO_MARSHAL_CONV_ARRAY_BYVALCHARARRAY; + else + *conv = MONO_MARSHAL_CONV_ARRAY_BYVALARRAY; return MONO_NATIVE_BYVALARRAY; case MONO_NATIVE_SAFEARRAY: *conv = MONO_MARSHAL_CONV_ARRAY_SAVEARRAY; @@ -4011,6 +4305,8 @@ mono_metadata_get_marshal_info (MonoImage *meta, guint32 idx, gboolean is_field) loc.col_idx = MONO_FIELD_MARSHAL_PARENT; loc.idx = ((idx + 1) << MONO_HAS_FIELD_MARSHAL_BITS) | (is_field? MONO_HAS_FIELD_MARSHAL_FIELDSREF: MONO_HAS_FIELD_MARSHAL_PARAMDEF); + /* FIXME: Index translation */ + if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) return NULL; @@ -4021,6 +4317,7 @@ static MonoMethod* method_from_method_def_or_ref (MonoImage *m, guint32 tok, MonoGenericContext *context) { guint32 idx = tok >> MONO_METHODDEFORREF_BITS; + switch (tok & MONO_METHODDEFORREF_MASK) { case MONO_METHODDEFORREF_METHODDEF: return mono_get_method_full (m, MONO_TOKEN_METHOD_DEF | idx, NULL, context); @@ -4049,7 +4346,8 @@ mono_class_get_overrides_full (MonoImage *image, guint32 type_token, MonoMethod gint32 i, num; guint32 cols [MONO_METHODIMPL_SIZE]; MonoMethod **result; - + gint32 ok = TRUE; + *overrides = NULL; if (num_overrides) *num_overrides = 0; @@ -4084,17 +4382,25 @@ mono_class_get_overrides_full (MonoImage *image, guint32 type_token, MonoMethod num = end - start; result = g_new (MonoMethod*, num * 2); for (i = 0; i < num; ++i) { + MonoMethod *method; + mono_metadata_decode_row (tdef, start + i, cols, MONO_METHODIMPL_SIZE); - result [i * 2] = method_from_method_def_or_ref ( + method = method_from_method_def_or_ref ( image, cols [MONO_METHODIMPL_DECLARATION], generic_context); - result [i * 2 + 1] = method_from_method_def_or_ref ( + if (method == NULL) + ok = FALSE; + result [i * 2] = method; + method = method_from_method_def_or_ref ( image, cols [MONO_METHODIMPL_BODY], generic_context); + if (method == NULL) + ok = FALSE; + result [i * 2 + 1] = method; } *overrides = result; if (num_overrides) *num_overrides = num; - return TRUE; + return ok; } /** @@ -4307,6 +4613,13 @@ mono_type_get_array_type (MonoType *type) return type->data.array; } +/* For MONO_TYPE_PTR */ +MonoType* +mono_type_get_ptr_type (MonoType *type) +{ + return type->data.type; +} + MonoClass* mono_type_get_modifiers (MonoType *type, gboolean *is_required, gpointer *iter) {