X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fmetadata.c;h=aafcbb55e121991306c9cc99078ec3dfe264769c;hb=6963bb4a65b95aa2716bce869696cde13abb8732;hp=23b2341561d956457efbd9f423ee1c219476e56f;hpb=8a2908ade348be32cc0506770d82ae103998b8ae;p=mono.git diff --git a/mono/metadata/metadata.c b/mono/metadata/metadata.c index 23b2341561d..aafcbb55e12 100644 --- a/mono/metadata/metadata.c +++ b/mono/metadata/metadata.c @@ -36,7 +36,7 @@ typedef struct { MonoGenericContext context; } MonoInflatedMethodSignature; -static gboolean do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container, +static gboolean do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container, gboolean transient, const char *ptr, const char **rptr); static gboolean do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only); @@ -1245,27 +1245,29 @@ mono_metadata_parse_custom_mod (MonoImage *m, MonoCustomMod *dest, const char *p } /* - * mono_metadata_parse_array_full: + * mono_metadata_parse_array_internal: * @m: a metadata context. + * @transient: whenever to allocate data from the heap * @ptr: a pointer to an encoded array description. * @rptr: pointer updated to match the end of the decoded stream * * Decodes the compressed array description found in the metadata @m at @ptr. * * Returns: a #MonoArrayType structure describing the array type - * and dimensions. Memory is allocated from the image mempool. + * and dimensions. Memory is allocated from the heap or from the image mempool, depending + * on the value of @transient. * * LOCKING: Acquires the loader lock */ -MonoArrayType * -mono_metadata_parse_array_full (MonoImage *m, MonoGenericContainer *container, - const char *ptr, const char **rptr) +static MonoArrayType * +mono_metadata_parse_array_internal (MonoImage *m, MonoGenericContainer *container, + gboolean transient, const char *ptr, const char **rptr) { int i; MonoArrayType *array; MonoType *etype; - array = mono_image_alloc0 (m, sizeof (MonoArrayType)); + array = transient ? g_malloc0 (sizeof (MonoArrayType)) : mono_image_alloc0 (m, sizeof (MonoArrayType)); etype = mono_metadata_parse_type_full (m, container, MONO_PARSE_TYPE, 0, ptr, &ptr); if (!etype) return NULL; @@ -1274,13 +1276,13 @@ mono_metadata_parse_array_full (MonoImage *m, MonoGenericContainer *container, array->numsizes = mono_metadata_decode_value (ptr, &ptr); if (array->numsizes) - array->sizes = mono_image_alloc0 (m, sizeof (int) * array->numsizes); + array->sizes = transient ? g_malloc0 (sizeof (int) * array->numsizes) : mono_image_alloc0 (m, sizeof (int) * array->numsizes); for (i = 0; i < array->numsizes; ++i) array->sizes [i] = mono_metadata_decode_value (ptr, &ptr); array->numlobounds = mono_metadata_decode_value (ptr, &ptr); if (array->numlobounds) - array->lobounds = mono_image_alloc0 (m, sizeof (int) * array->numlobounds); + array->lobounds = transient ? g_malloc0 (sizeof (int) * array->numlobounds) : mono_image_alloc0 (m, sizeof (int) * array->numlobounds); for (i = 0; i < array->numlobounds; ++i) array->lobounds [i] = mono_metadata_decode_signed_value (ptr, &ptr); @@ -1289,6 +1291,13 @@ mono_metadata_parse_array_full (MonoImage *m, MonoGenericContainer *container, return array; } +MonoArrayType * +mono_metadata_parse_array_full (MonoImage *m, MonoGenericContainer *container, + const char *ptr, const char **rptr) +{ + return mono_metadata_parse_array_internal (m, container, FALSE, ptr, rptr); +} + MonoArrayType * mono_metadata_parse_array (MonoImage *m, const char *ptr, const char **rptr) { @@ -1409,12 +1418,14 @@ mono_generic_inst_equal_full (const MonoGenericInst *a, const MonoGenericInst *b { int i; +#ifndef MONO_SMALL_CONFIG if (a->id && b->id) { if (a->id == b->id) return TRUE; if (!signature_only) return FALSE; } +#endif if (a->is_open != b->is_open || a->type_argc != b->type_argc) return FALSE; @@ -1493,6 +1504,7 @@ mono_metadata_cleanup (void) * @opt_attrs: optional attributes to store in the returned type * @ptr: pointer to the type representation * @rptr: pointer updated to match the end of the decoded stream + * @transient: whenever to allocate the result from the heap or from a mempool * * Decode a compressed type description found at @ptr in @m. * @mode can be one of MONO_PARSE_MOD_TYPE, MONO_PARSE_PARAM, MONO_PARSE_RET, @@ -1502,18 +1514,17 @@ mono_metadata_cleanup (void) * * To parse a generic type, `generic_container' points to the current class'es * (the `generic_container' field in the MonoClass) or the current generic method's - * (the `generic_container' field in the MonoMethodNormal) generic container. + * (stored in image->property_hash) generic container. * When we encounter any MONO_TYPE_VAR or MONO_TYPE_MVAR's, they're looked up in * this MonoGenericContainer. - * This is a Mono runtime internal function. * * LOCKING: Acquires the loader lock. * * Returns: a #MonoType structure representing the decoded type. */ -MonoType* -mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, MonoParseTypeMode mode, - short opt_attrs, const char *ptr, const char **rptr) +static MonoType* +mono_metadata_parse_type_internal (MonoImage *m, MonoGenericContainer *container, MonoParseTypeMode mode, + short opt_attrs, gboolean transient, const char *ptr, const char **rptr) { MonoType *type, *cached; MonoType stype; @@ -1555,7 +1566,10 @@ mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, Mo } if (count) { - type = mono_image_alloc0 (m, MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod)); + int size; + + size = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod); + type = transient ? g_malloc0 (size) : mono_image_alloc0 (m, size); type->num_mods = count; if (count > 64) g_warning ("got more than 64 modifiers in type"); @@ -1591,14 +1605,14 @@ mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, Mo type->byref = byref; type->pinned = pinned ? 1 : 0; - if (!do_mono_metadata_parse_type (type, m, container, ptr, &ptr)) { + if (!do_mono_metadata_parse_type (type, m, container, transient, ptr, &ptr)) { return NULL; } if (rptr) *rptr = ptr; - if (!type->num_mods) { + if (!type->num_mods && !transient) { /* 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; @@ -1634,12 +1648,19 @@ mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, Mo /* printf ("%x %x %c %s\n", type->attrs, type->num_mods, type->pinned ? 'p' : ' ', mono_type_full_name (type)); */ if (type == &stype) { - type = mono_image_alloc (m, MONO_SIZEOF_TYPE); + type = transient ? g_malloc (MONO_SIZEOF_TYPE) : mono_image_alloc (m, MONO_SIZEOF_TYPE); memcpy (type, &stype, MONO_SIZEOF_TYPE); } return type; } +MonoType* +mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, MonoParseTypeMode mode, + short opt_attrs, const char *ptr, const char **rptr) +{ + return mono_metadata_parse_type_internal (m, container, mode, opt_attrs, FALSE, ptr, rptr); +} + /* * LOCKING: Acquires the loader lock. */ @@ -2587,8 +2608,7 @@ free_inflated_method (MonoMethodInflated *imethod) mono_metadata_free_inflated_signature (method->signature); if (!((method->flags & METHOD_ATTRIBUTE_ABSTRACT) || (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))) { - MonoMethodNormal* mn = (MonoMethodNormal*) method; - MonoMethodHeader *header = mn->header; + MonoMethodHeader *header = imethod->header; if (header) { /* Allocated in inflate_generic_header () */ @@ -2639,10 +2659,22 @@ free_generic_class_dependents (MonoGenericClass *gclass) /* Allocated in mono_class_init () */ g_free (class->methods); - if (class->ext) + if (class->ext) { g_free (class->ext->properties); + g_free (class->ext->field_def_values); + } + /* Allocated in mono_class_setup_fields () */ + g_free (class->fields); + /* Allocated in mono_class_setup_vtable_general () */ + g_free (class->vtable); /* Allocated in mono_generic_class_get_class () */ g_free (class->interfaces); + /* Allocated in setup_interface_offsets () */ + g_free (class->interfaces_packed); + g_free (class->interface_offsets_packed); + g_free (class->interface_bitmap); + /* Allocated in mono_class_setup_supertypes () */ + g_free (class->supertypes); l = g_slist_prepend (l, class); } else if (gclass->is_dynamic) { MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass *)gclass; @@ -2771,7 +2803,9 @@ mono_metadata_get_generic_inst (int type_argc, MonoType **type_argv) is_open = (i < type_argc); ginst = alloca (size); +#ifndef MONO_SMALL_CONFIG ginst->id = 0; +#endif ginst->is_open = is_open; ginst->type_argc = type_argc; memcpy (ginst->type_argv, type_argv, type_argc * sizeof (MonoType *)); @@ -2789,7 +2823,9 @@ mono_metadata_get_generic_inst (int type_argc, MonoType **type_argv) ginst = g_hash_table_lookup (set->ginst_cache, ginst); if (!ginst) { ginst = g_malloc (size); +#ifndef MONO_SMALL_CONFIG ginst->id = ++next_generic_inst_id; +#endif ginst->is_open = is_open; ginst->type_argc = type_argc; @@ -3002,7 +3038,7 @@ select_container (MonoGenericContainer *gc, MonoTypeEnum type) /* * mono_metadata_parse_generic_param: - * @generic_container: Our MonoClass's or MonoMethodNormal's MonoGenericContainer; + * @generic_container: Our MonoClass's or MonoMethod's MonoGenericContainer; * see mono_metadata_parse_type_full() for details. * Internal routine to parse a generic type parameter. * LOCKING: Acquires the loader lock @@ -3070,6 +3106,7 @@ mono_metadata_get_shared_type (MonoType *type) * @type: MonoType to be filled in with the return value * @m: image context * @generic_context: generics_context + * @transient: whenever to allocate data from the heap * @ptr: pointer to the encoded type * @rptr: pointer where the end of the encoded type is saved * @@ -3087,7 +3124,7 @@ mono_metadata_get_shared_type (MonoType *type) */ static gboolean do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container, - const char *ptr, const char **rptr) + gboolean transient, const char *ptr, const char **rptr) { gboolean ok = TRUE; type->type = mono_metadata_decode_value (ptr, &ptr); @@ -3131,7 +3168,7 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer break; } case MONO_TYPE_PTR: - type->data.type = mono_metadata_parse_type_full (m, container, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr); + type->data.type = mono_metadata_parse_type_internal (m, container, MONO_PARSE_MOD_TYPE, 0, transient, ptr, &ptr); if (!type->data.type) return FALSE; break; @@ -3141,7 +3178,7 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer return FALSE; break; case MONO_TYPE_ARRAY: - type->data.array = mono_metadata_parse_array_full (m, container, ptr, &ptr); + type->data.array = mono_metadata_parse_array_internal (m, container, transient, ptr, &ptr); if (!type->data.array) return FALSE; break; @@ -3227,16 +3264,16 @@ hex_dump (const char *buffer, int base, int count) #endif /** - * @mh: The Method header * @ptr: Points to the beginning of the Section Data (25.3) */ -static void -parse_section_data (MonoImage *m, MonoMethodHeader *mh, const unsigned char *ptr) +static MonoExceptionClause* +parse_section_data (MonoImage *m, int *num_clauses, const unsigned char *ptr) { unsigned char sect_data_flags; const unsigned char *sptr; int is_fat; guint32 sect_data_len; + MonoExceptionClause* clauses = NULL; while (1) { /* align on 32-bit boundary */ @@ -3263,11 +3300,11 @@ parse_section_data (MonoImage *m, MonoMethodHeader *mh, const unsigned char *ptr if (sect_data_flags & METHOD_HEADER_SECTION_EHTABLE) { const unsigned char *p = dword_align (ptr); int i; - mh->num_clauses = is_fat ? sect_data_len / 24: sect_data_len / 12; + *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 = mono_image_alloc0 (m, sizeof (MonoExceptionClause) * mh->num_clauses); - for (i = 0; i < mh->num_clauses; ++i) { - MonoExceptionClause *ec = &mh->clauses [i]; + clauses = g_malloc0 (sizeof (MonoExceptionClause) * (*num_clauses)); + for (i = 0; i < *num_clauses; ++i) { + MonoExceptionClause *ec = &clauses [i]; guint32 tof_value; if (is_fat) { ec->flags = read32 (p); @@ -3300,7 +3337,7 @@ parse_section_data (MonoImage *m, MonoMethodHeader *mh, const unsigned char *ptr if (sect_data_flags & METHOD_HEADER_SECTION_MORE_SECTS) ptr += sect_data_len - 4; /* LAMESPEC: it seems the size includes the header */ else - return; + return clauses; } } @@ -3333,8 +3370,8 @@ mono_method_get_header_summary (MonoMethod *method, MonoMethodHeaderSummary *sum if ((method->flags & METHOD_ATTRIBUTE_ABSTRACT) || (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) return FALSE; - if (method->klass->image->dynamic || ((MonoMethodNormal*) method)->header) { - MonoMethodHeader *header = mono_method_get_header (method); + if (method->wrapper_type != MONO_WRAPPER_NONE || method->sre_method) { + MonoMethodHeader *header = ((MonoMethodWrapper *)method)->header; if (!header) return FALSE; summary->code_size = header->code_size; @@ -3387,7 +3424,7 @@ mono_method_get_header_summary (MonoMethod *method, MonoMethodHeaderSummary *sum * * LOCKING: Acquires the loader lock. * - * Returns: a MonoMethodHeader allocated from the image mempool. + * Returns: a transient MonoMethodHeader allocated from the heap. */ MonoMethodHeader * mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, const char *ptr) @@ -3398,15 +3435,19 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons guint16 fat_flags; guint32 local_var_sig_tok, max_stack, code_size, init_locals; const unsigned char *code; - int hsize; - + MonoExceptionClause* clauses = NULL; + int hsize, num_clauses = 0; + MonoTableInfo *t = &m->tables [MONO_TABLE_STANDALONESIG]; + guint32 cols [MONO_STAND_ALONE_SIGNATURE_SIZE]; + g_return_val_if_fail (ptr != NULL, NULL); switch (format) { case METHOD_HEADER_TINY_FORMAT: - mh = mono_image_alloc0 (m, MONO_SIZEOF_METHOD_HEADER); + mh = g_malloc0 (MONO_SIZEOF_METHOD_HEADER); ptr++; mh->max_stack = 8; + mh->is_transient = TRUE; local_var_sig_tok = 0; mh->code_size = flags >> 2; mh->code = (unsigned char*)ptr; @@ -3440,17 +3481,21 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons default: return NULL; } - - if (local_var_sig_tok) { - MonoTableInfo *t = &m->tables [MONO_TABLE_STANDALONESIG]; - const char *locals_ptr; - guint32 cols [MONO_STAND_ALONE_SIGNATURE_SIZE]; - int len=0, i, bsize; - mono_metadata_decode_row (t, (local_var_sig_tok & 0xffffff)-1, cols, 1); + if (local_var_sig_tok) { + int idx = (local_var_sig_tok & 0xffffff)-1; + if (idx >= t->rows) + return NULL; + mono_metadata_decode_row (t, idx, cols, 1); if (!mono_verifier_verify_standalone_signature (m, cols [MONO_STAND_ALONE_SIGNATURE], NULL)) return NULL; + } + if (fat_flags & METHOD_HEADER_MORE_SECTS) + clauses = parse_section_data (m, &num_clauses, (const unsigned char*)ptr); + if (local_var_sig_tok) { + const char *locals_ptr; + int len=0, i, bsize; locals_ptr = mono_metadata_blob_heap (m, cols [MONO_STAND_ALONE_SIGNATURE]); bsize = mono_metadata_decode_blob_size (locals_ptr, &locals_ptr); @@ -3458,24 +3503,32 @@ 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 = mono_image_alloc0 (m, MONO_SIZEOF_METHOD_HEADER + len * sizeof (MonoType*)); + mh = g_malloc0 (MONO_SIZEOF_METHOD_HEADER + len * sizeof (MonoType*) + num_clauses * sizeof (MonoExceptionClause)); 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); + mh->locals [i] = mono_metadata_parse_type_internal (m, container, + MONO_PARSE_LOCAL, 0, TRUE, locals_ptr, &locals_ptr); if (!mh->locals [i]) { + g_free (clauses); + g_free (mh); return NULL; } } } else { - mh = mono_image_alloc0 (m, MONO_SIZEOF_METHOD_HEADER); + mh = g_malloc0 (MONO_SIZEOF_METHOD_HEADER + num_clauses * sizeof (MonoExceptionClause)); } mh->code = code; mh->code_size = code_size; mh->max_stack = max_stack; + mh->is_transient = TRUE; mh->init_locals = init_locals; - if (fat_flags & METHOD_HEADER_MORE_SECTS) - parse_section_data (m, mh, (const unsigned char*)ptr); + if (clauses) { + MonoExceptionClause* clausesp = (MonoExceptionClause*)&mh->locals [mh->num_locals]; + memcpy (clausesp, clauses, num_clauses * sizeof (MonoExceptionClause)); + g_free (clauses); + mh->clauses = clausesp; + mh->num_clauses = num_clauses; + } return mh; } @@ -3509,12 +3562,21 @@ mono_metadata_parse_mh (MonoImage *m, const char *ptr) * @mh: a method header * * Free the memory allocated for the method header. - * This is a Mono runtime internal function. */ void mono_metadata_free_mh (MonoMethodHeader *mh) { - /* Allocated from the mempool */ + int i; + + /* If it is not transient it means it's part of a wrapper method, + * or a SRE-generated method, so the lifetime in that case is + * dictated by the method's own lifetime + */ + if (mh->is_transient) { + for (i = 0; i < mh->num_locals; ++i) + mono_metadata_free_type (mh->locals [i]); + g_free (mh); + } } /* @@ -4492,9 +4554,20 @@ mono_metadata_type_hash (MonoType *t1) switch (t1->type) { case MONO_TYPE_VALUETYPE: case MONO_TYPE_CLASS: - case MONO_TYPE_SZARRAY: - /* check if the distribution is good enough */ - return ((hash << 5) - hash) ^ mono_metadata_str_hash (t1->data.klass->name); + case MONO_TYPE_SZARRAY: { + MonoClass *class = t1->data.klass; + /* + * Dynamic classes must not be hashed on their type since it can change + * during runtime. For example, if we hash a reference type that is + * later made into a valuetype. + * + * This is specially problematic with generic instances since they are + * inserted in a bunch of hash tables before been finished. + */ + if (class->image->dynamic) + return (t1->byref << 6) | mono_metadata_str_hash (class->name); + return ((hash << 5) - hash) ^ mono_metadata_str_hash (class->name); + } case MONO_TYPE_PTR: return ((hash << 5) - hash) ^ mono_metadata_type_hash (t1->data.type); case MONO_TYPE_ARRAY: @@ -5170,7 +5243,7 @@ mono_type_create_from_typespec (MonoImage *image, guint32 type_spec) ptr++; } - if (!do_mono_metadata_parse_type (type, image, NULL, ptr, &ptr)) { + if (!do_mono_metadata_parse_type (type, image, NULL, FALSE, ptr, &ptr)) { mono_loader_unlock (); return NULL; }