X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fmetadata.c;h=fc8d5cb09ed3e87e84a37acf570e6e5a85ca7740;hb=35936f12888a927b7f6482f11b78447a3903bc85;hp=e718382302ac350e73c4ae0bc5489274a33757a7;hpb=1a0c75ac0c90477120952f6892060b4fe5dd3e9b;p=mono.git diff --git a/mono/metadata/metadata.c b/mono/metadata/metadata.c index e718382302a..fc8d5cb09ed 100644 --- a/mono/metadata/metadata.c +++ b/mono/metadata/metadata.c @@ -9,7 +9,7 @@ */ #include -#include +#include #include #include #include @@ -22,11 +22,12 @@ #include "class-internals.h" #include "class.h" -static void do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContext *generic_context, +static gboolean do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container, const char *ptr, const char **rptr); 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); @@ -91,7 +92,8 @@ enum { MONO_MT_RS_IDX }; -const static unsigned char AssemblySchema [] = { +const static unsigned char TableSchemas [] = { +#define ASSEMBLY_SCHEMA_OFFSET 0 MONO_MT_UINT32, /* "HashId" }, */ MONO_MT_UINT16, /* "Major" }, */ MONO_MT_UINT16, /* "Minor" }, */ @@ -101,22 +103,19 @@ const static unsigned char AssemblySchema [] = { MONO_MT_BLOB_IDX, /* "PublicKey" }, */ MONO_MT_STRING_IDX, /* "Name" }, */ MONO_MT_STRING_IDX, /* "Culture" }, */ - MONO_MT_END -}; - -const static unsigned char AssemblyOSSchema [] = { + MONO_MT_END, + +#define ASSEMBLYOS_SCHEMA_OFFSET ASSEMBLY_SCHEMA_OFFSET + 10 MONO_MT_UINT32, /* "OSPlatformID" }, */ MONO_MT_UINT32, /* "OSMajor" }, */ MONO_MT_UINT32, /* "OSMinor" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char AssemblyProcessorSchema [] = { +#define ASSEMBLYPROC_SCHEMA_OFFSET ASSEMBLYOS_SCHEMA_OFFSET + 4 MONO_MT_UINT32, /* "Processor" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char AssemblyRefSchema [] = { +#define ASSEMBLYREF_SCHEMA_OFFSET ASSEMBLYPROC_SCHEMA_OFFSET + 2 MONO_MT_UINT16, /* "Major" }, */ MONO_MT_UINT16, /* "Minor" }, */ MONO_MT_UINT16, /* "Build" }, */ @@ -126,296 +125,293 @@ const static unsigned char AssemblyRefSchema [] = { MONO_MT_STRING_IDX, /* "Name" }, */ MONO_MT_STRING_IDX, /* "Culture" }, */ MONO_MT_BLOB_IDX, /* "HashValue" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char AssemblyRefOSSchema [] = { +#define ASSEMBLYREFOS_SCHEMA_OFFSET ASSEMBLYREF_SCHEMA_OFFSET + 10 MONO_MT_UINT32, /* "OSPlatformID" }, */ MONO_MT_UINT32, /* "OSMajorVersion" }, */ MONO_MT_UINT32, /* "OSMinorVersion" }, */ MONO_MT_TABLE_IDX, /* "AssemblyRef:AssemblyRef" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char AssemblyRefProcessorSchema [] = { +#define ASSEMBLYREFPROC_SCHEMA_OFFSET ASSEMBLYREFOS_SCHEMA_OFFSET + 5 MONO_MT_UINT32, /* "Processor" }, */ MONO_MT_TABLE_IDX, /* "AssemblyRef:AssemblyRef" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char ClassLayoutSchema [] = { +#define CLASS_LAYOUT_SCHEMA_OFFSET ASSEMBLYREFPROC_SCHEMA_OFFSET + 3 MONO_MT_UINT16, /* "PackingSize" }, */ MONO_MT_UINT32, /* "ClassSize" }, */ MONO_MT_TABLE_IDX, /* "Parent:TypeDef" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char ConstantSchema [] = { +#define CONSTANT_SCHEMA_OFFSET CLASS_LAYOUT_SCHEMA_OFFSET + 4 MONO_MT_UINT8, /* "Type" }, */ MONO_MT_UINT8, /* "PaddingZero" }, */ MONO_MT_CONST_IDX, /* "Parent" }, */ MONO_MT_BLOB_IDX, /* "Value" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char CustomAttributeSchema [] = { +#define CUSTOM_ATTR_SCHEMA_OFFSET CONSTANT_SCHEMA_OFFSET + 5 MONO_MT_HASCAT_IDX, /* "Parent" }, */ MONO_MT_CAT_IDX, /* "Type" }, */ MONO_MT_BLOB_IDX, /* "Value" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char DeclSecuritySchema [] = { +#define DECL_SEC_SCHEMA_OFFSET CUSTOM_ATTR_SCHEMA_OFFSET + 4 MONO_MT_UINT16, /* "Action" }, */ MONO_MT_HASDEC_IDX, /* "Parent" }, */ MONO_MT_BLOB_IDX, /* "PermissionSet" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char EventMapSchema [] = { +#define EVENTMAP_SCHEMA_OFFSET DECL_SEC_SCHEMA_OFFSET + 4 MONO_MT_TABLE_IDX, /* "Parent:TypeDef" }, */ MONO_MT_TABLE_IDX, /* "EventList:Event" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char EventSchema [] = { +#define EVENT_SCHEMA_OFFSET EVENTMAP_SCHEMA_OFFSET + 3 MONO_MT_UINT16, /* "EventFlags#EventAttribute" }, */ MONO_MT_STRING_IDX, /* "Name" }, */ MONO_MT_TABLE_IDX, /* "EventType" }, TypeDef or TypeRef */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char ExportedTypeSchema [] = { +#define EXPORTED_TYPE_SCHEMA_OFFSET EVENT_SCHEMA_OFFSET + 4 MONO_MT_UINT32, /* "Flags" }, */ MONO_MT_TABLE_IDX, /* "TypeDefId" }, */ MONO_MT_STRING_IDX, /* "TypeName" }, */ MONO_MT_STRING_IDX, /* "TypeNameSpace" }, */ MONO_MT_IMPL_IDX, /* "Implementation" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char FieldSchema [] = { +#define FIELD_SCHEMA_OFFSET EXPORTED_TYPE_SCHEMA_OFFSET + 6 MONO_MT_UINT16, /* "Flags" }, */ MONO_MT_STRING_IDX, /* "Name" }, */ MONO_MT_BLOB_IDX, /* "Signature" }, */ - MONO_MT_END -}; -const static unsigned char FieldLayoutSchema [] = { + MONO_MT_END, + +#define FIELD_LAYOUT_SCHEMA_OFFSET FIELD_SCHEMA_OFFSET + 4 MONO_MT_UINT32, /* "Offset" }, */ MONO_MT_TABLE_IDX, /* "Field:Field" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char FieldMarshalSchema [] = { +#define FIELD_MARSHAL_SCHEMA_OFFSET FIELD_LAYOUT_SCHEMA_OFFSET + 3 MONO_MT_HFM_IDX, /* "Parent" }, */ MONO_MT_BLOB_IDX, /* "NativeType" }, */ - MONO_MT_END -}; -const static unsigned char FieldRVASchema [] = { + MONO_MT_END, + +#define FIELD_RVA_SCHEMA_OFFSET FIELD_MARSHAL_SCHEMA_OFFSET + 3 MONO_MT_UINT32, /* "RVA" }, */ MONO_MT_TABLE_IDX, /* "Field:Field" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char FileSchema [] = { +#define FILE_SCHEMA_OFFSET FIELD_RVA_SCHEMA_OFFSET + 3 MONO_MT_UINT32, /* "Flags" }, */ MONO_MT_STRING_IDX, /* "Name" }, */ MONO_MT_BLOB_IDX, /* "Value" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char ImplMapSchema [] = { +#define IMPLMAP_SCHEMA_OFFSET FILE_SCHEMA_OFFSET + 4 MONO_MT_UINT16, /* "MappingFlag" }, */ MONO_MT_MF_IDX, /* "MemberForwarded" }, */ MONO_MT_STRING_IDX, /* "ImportName" }, */ MONO_MT_TABLE_IDX, /* "ImportScope:ModuleRef" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char InterfaceImplSchema [] = { +#define IFACEMAP_SCHEMA_OFFSET IMPLMAP_SCHEMA_OFFSET + 5 MONO_MT_TABLE_IDX, /* "Class:TypeDef" }, */ MONO_MT_TDOR_IDX, /* "Interface=TypeDefOrRef" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char ManifestResourceSchema [] = { +#define MANIFEST_SCHEMA_OFFSET IFACEMAP_SCHEMA_OFFSET + 3 MONO_MT_UINT32, /* "Offset" }, */ MONO_MT_UINT32, /* "Flags" }, */ MONO_MT_STRING_IDX, /* "Name" }, */ MONO_MT_IMPL_IDX, /* "Implementation" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char MemberRefSchema [] = { +#define MEMBERREF_SCHEMA_OFFSET MANIFEST_SCHEMA_OFFSET + 5 MONO_MT_MRP_IDX, /* "Class" }, */ MONO_MT_STRING_IDX, /* "Name" }, */ MONO_MT_BLOB_IDX, /* "Signature" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char MethodSchema [] = { +#define METHOD_SCHEMA_OFFSET MEMBERREF_SCHEMA_OFFSET + 4 MONO_MT_UINT32, /* "RVA" }, */ MONO_MT_UINT16, /* "ImplFlags#MethodImplAttributes" }, */ MONO_MT_UINT16, /* "Flags#MethodAttribute" }, */ MONO_MT_STRING_IDX, /* "Name" }, */ MONO_MT_BLOB_IDX, /* "Signature" }, */ MONO_MT_TABLE_IDX, /* "ParamList:Param" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char MethodImplSchema [] = { +#define METHOD_IMPL_SCHEMA_OFFSET METHOD_SCHEMA_OFFSET + 7 MONO_MT_TABLE_IDX, /* "Class:TypeDef" }, */ MONO_MT_MDOR_IDX, /* "MethodBody" }, */ MONO_MT_MDOR_IDX, /* "MethodDeclaration" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char MethodSemanticsSchema [] = { +#define METHOD_SEMA_SCHEMA_OFFSET METHOD_IMPL_SCHEMA_OFFSET + 4 MONO_MT_UINT16, /* "MethodSemantic" }, */ MONO_MT_TABLE_IDX, /* "Method:Method" }, */ MONO_MT_HS_IDX, /* "Association" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char ModuleSchema [] = { +#define MODULE_SCHEMA_OFFSET METHOD_SEMA_SCHEMA_OFFSET + 4 MONO_MT_UINT16, /* "Generation" }, */ MONO_MT_STRING_IDX, /* "Name" }, */ MONO_MT_GUID_IDX, /* "MVID" }, */ MONO_MT_GUID_IDX, /* "EncID" }, */ MONO_MT_GUID_IDX, /* "EncBaseID" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char ModuleRefSchema [] = { +#define MODULEREF_SCHEMA_OFFSET MODULE_SCHEMA_OFFSET + 6 MONO_MT_STRING_IDX, /* "Name" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char NestedClassSchema [] = { +#define NESTED_CLASS_SCHEMA_OFFSET MODULEREF_SCHEMA_OFFSET + 2 MONO_MT_TABLE_IDX, /* "NestedClass:TypeDef" }, */ MONO_MT_TABLE_IDX, /* "EnclosingClass:TypeDef" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char ParamSchema [] = { +#define PARAM_SCHEMA_OFFSET NESTED_CLASS_SCHEMA_OFFSET + 3 MONO_MT_UINT16, /* "Flags" }, */ MONO_MT_UINT16, /* "Sequence" }, */ MONO_MT_STRING_IDX, /* "Name" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char PropertySchema [] = { +#define PROPERTY_SCHEMA_OFFSET PARAM_SCHEMA_OFFSET + 4 MONO_MT_UINT16, /* "Flags" }, */ MONO_MT_STRING_IDX, /* "Name" }, */ MONO_MT_BLOB_IDX, /* "Type" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char PropertyMapSchema [] = { +#define PROPERTY_MAP_SCHEMA_OFFSET PROPERTY_SCHEMA_OFFSET + 4 MONO_MT_TABLE_IDX, /* "Parent:TypeDef" }, */ MONO_MT_TABLE_IDX, /* "PropertyList:Property" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char StandaloneSigSchema [] = { +#define STDALON_SIG_SCHEMA_OFFSET PROPERTY_MAP_SCHEMA_OFFSET + 3 MONO_MT_BLOB_IDX, /* "Signature" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char TypeDefSchema [] = { +#define TYPEDEF_SCHEMA_OFFSET STDALON_SIG_SCHEMA_OFFSET + 2 MONO_MT_UINT32, /* "Flags" }, */ MONO_MT_STRING_IDX, /* "Name" }, */ MONO_MT_STRING_IDX, /* "Namespace" }, */ MONO_MT_TDOR_IDX, /* "Extends" }, */ MONO_MT_TABLE_IDX, /* "FieldList:Field" }, */ MONO_MT_TABLE_IDX, /* "MethodList:Method" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char TypeRefSchema [] = { +#define TYPEREF_SCHEMA_OFFSET TYPEDEF_SCHEMA_OFFSET + 7 MONO_MT_RS_IDX, /* "ResolutionScope=ResolutionScope" }, */ MONO_MT_STRING_IDX, /* "Name" }, */ MONO_MT_STRING_IDX, /* "Namespace" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char TypeSpecSchema [] = { +#define TYPESPEC_SCHEMA_OFFSET TYPEREF_SCHEMA_OFFSET + 4 MONO_MT_BLOB_IDX, /* "Signature" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char GenericParamSchema [] = { +#define GENPARAM_SCHEMA_OFFSET TYPESPEC_SCHEMA_OFFSET + 2 MONO_MT_UINT16, /* "Number" }, */ MONO_MT_UINT16, /* "Flags" }, */ MONO_MT_TABLE_IDX, /* "Owner" }, TypeDef or MethodDef */ MONO_MT_STRING_IDX, /* "Name" }, */ + MONO_MT_END, - MONO_MT_END -}; - -const static unsigned char MethodSpecSchema [] = { +#define METHOD_SPEC_SCHEMA_OFFSET GENPARAM_SCHEMA_OFFSET + 5 MONO_MT_MDOR_IDX, /* "Method" }, */ MONO_MT_BLOB_IDX, /* "Signature" }, */ - MONO_MT_END -}; + MONO_MT_END, -const static unsigned char GenericParamConstraintSchema [] = { +#define GEN_CONSTRAINT_SCHEMA_OFFSET METHOD_SPEC_SCHEMA_OFFSET + 3 MONO_MT_TABLE_IDX, /* "GenericParam" }, */ MONO_MT_TDOR_IDX, /* "Constraint" }, */ + MONO_MT_END, + +#define NULL_SCHEMA_OFFSET GEN_CONSTRAINT_SCHEMA_OFFSET + 3 MONO_MT_END }; -const static struct { - const unsigned char *description; - const char *name; -} tables [] = { - /* 0 */ { ModuleSchema, "Module" }, - /* 1 */ { TypeRefSchema, "TypeRef" }, - /* 2 */ { TypeDefSchema, "TypeDef" }, - /* 3 */ { NULL, NULL }, - /* 4 */ { FieldSchema, "Field" }, - /* 5 */ { NULL, NULL }, - /* 6 */ { MethodSchema, "Method" }, - /* 7 */ { NULL, NULL }, - /* 8 */ { ParamSchema, "Param" }, - /* 9 */ { InterfaceImplSchema, "InterfaceImpl" }, - /* A */ { MemberRefSchema, "MemberRef" }, - /* B */ { ConstantSchema, "Constant" }, - /* C */ { CustomAttributeSchema, "CustomAttribute" }, - /* D */ { FieldMarshalSchema, "FieldMarshal" }, - /* E */ { DeclSecuritySchema, "DeclSecurity" }, - /* F */ { ClassLayoutSchema, "ClassLayout" }, - /* 10 */ { FieldLayoutSchema, "FieldLayout" }, - /* 11 */ { StandaloneSigSchema, "StandaloneSig" }, - /* 12 */ { EventMapSchema, "EventMap" }, - /* 13 */ { NULL, NULL }, - /* 14 */ { EventSchema, "Event" }, - /* 15 */ { PropertyMapSchema, "PropertyMap" }, - /* 16 */ { NULL, NULL }, - /* 17 */ { PropertySchema, "PropertyTable" }, - /* 18 */ { MethodSemanticsSchema, "MethodSemantics" }, - /* 19 */ { MethodImplSchema, "MethodImpl" }, - /* 1A */ { ModuleRefSchema, "ModuleRef" }, - /* 1B */ { TypeSpecSchema, "TypeSpec" }, - /* 1C */ { ImplMapSchema, "ImplMap" }, - /* 1D */ { FieldRVASchema, "FieldRVA" }, - /* 1E */ { NULL, NULL }, - /* 1F */ { NULL, NULL }, - /* 20 */ { AssemblySchema, "Assembly" }, - /* 21 */ { AssemblyProcessorSchema, "AssemblyProcessor" }, - /* 22 */ { AssemblyOSSchema, "AssemblyOS" }, - /* 23 */ { AssemblyRefSchema, "AssemblyRef" }, - /* 24 */ { AssemblyRefProcessorSchema, "AssemblyRefProcessor" }, - /* 25 */ { AssemblyRefOSSchema, "AssemblyRefOS" }, - /* 26 */ { FileSchema, "File" }, - /* 27 */ { ExportedTypeSchema, "ExportedType" }, - /* 28 */ { ManifestResourceSchema, "ManifestResource" }, - /* 29 */ { NestedClassSchema, "NestedClass" }, - /* 2A */ { GenericParamSchema, "GenericParam" }, - /* 2B */ { MethodSpecSchema, "MethodSpec" }, - /* 2C */ { GenericParamConstraintSchema, "GenericParamConstraint" }, +/* Must be the same order as MONO_TABLE_* */ +const static unsigned char +table_description [] = { + MODULE_SCHEMA_OFFSET, + TYPEREF_SCHEMA_OFFSET, + TYPEDEF_SCHEMA_OFFSET, + NULL_SCHEMA_OFFSET, + FIELD_SCHEMA_OFFSET, + NULL_SCHEMA_OFFSET, + METHOD_SCHEMA_OFFSET, + NULL_SCHEMA_OFFSET, + PARAM_SCHEMA_OFFSET, + IFACEMAP_SCHEMA_OFFSET, + MEMBERREF_SCHEMA_OFFSET, /* 0xa */ + CONSTANT_SCHEMA_OFFSET, + CUSTOM_ATTR_SCHEMA_OFFSET, + FIELD_MARSHAL_SCHEMA_OFFSET, + DECL_SEC_SCHEMA_OFFSET, + CLASS_LAYOUT_SCHEMA_OFFSET, + FIELD_LAYOUT_SCHEMA_OFFSET, /* 0x10 */ + STDALON_SIG_SCHEMA_OFFSET, + EVENTMAP_SCHEMA_OFFSET, + NULL_SCHEMA_OFFSET, + EVENT_SCHEMA_OFFSET, + PROPERTY_MAP_SCHEMA_OFFSET, + NULL_SCHEMA_OFFSET, + PROPERTY_SCHEMA_OFFSET, + METHOD_SEMA_SCHEMA_OFFSET, + METHOD_IMPL_SCHEMA_OFFSET, + MODULEREF_SCHEMA_OFFSET, /* 0x1a */ + TYPESPEC_SCHEMA_OFFSET, + IMPLMAP_SCHEMA_OFFSET, + FIELD_RVA_SCHEMA_OFFSET, + NULL_SCHEMA_OFFSET, + NULL_SCHEMA_OFFSET, + ASSEMBLY_SCHEMA_OFFSET, /* 0x20 */ + ASSEMBLYPROC_SCHEMA_OFFSET, + ASSEMBLYOS_SCHEMA_OFFSET, + ASSEMBLYREF_SCHEMA_OFFSET, + ASSEMBLYREFPROC_SCHEMA_OFFSET, + ASSEMBLYREFOS_SCHEMA_OFFSET, + FILE_SCHEMA_OFFSET, + EXPORTED_TYPE_SCHEMA_OFFSET, + MANIFEST_SCHEMA_OFFSET, + NESTED_CLASS_SCHEMA_OFFSET, + GENPARAM_SCHEMA_OFFSET, /* 0x2a */ + METHOD_SPEC_SCHEMA_OFFSET, + GEN_CONSTRAINT_SCHEMA_OFFSET +}; + +#ifdef HAVE_ARRAY_ELEM_INIT +#define MSGSTRFIELD(line) MSGSTRFIELD1(line) +#define MSGSTRFIELD1(line) str##line +static const struct msgstr_t { +#define TABLEDEF(a,b) char MSGSTRFIELD(__LINE__) [sizeof (b)]; +#include "mono/cil/tables.def" +#undef TABLEDEF +} tablestr = { +#define TABLEDEF(a,b) b, +#include "mono/cil/tables.def" +#undef TABLEDEF +}; +static const gint16 tableidx [] = { +#define TABLEDEF(a,b) [a] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)), +#include "mono/cil/tables.def" +#undef TABLEDEF +}; + +#else +#define TABLEDEF(a,b) b, +static const char* const +mono_tables_names [] = { +#include "mono/cil/tables.def" + NULL }; +#endif + /** * mono_meta_table_name: * @table: table index @@ -425,10 +421,14 @@ const static struct { const char * mono_meta_table_name (int table) { - if ((table < 0) || (table > 0x2c)) + if ((table < 0) || (table > MONO_TABLE_LAST)) return ""; - - return tables [table].name; + +#ifdef HAVE_ARRAY_ELEM_INIT + return (const char*)&tablestr + tableidx [table]; +#else + return mono_tables_names [table]; +#endif } /* The guy who wrote the spec for this should not be allowed near a @@ -465,7 +465,7 @@ mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bit int size = 0, field_size = 0; int i, n, code; int shift = 0; - const unsigned char *description = tables [tableindex].description; + const unsigned char *description = TableSchemas + table_description [tableindex]; for (i = 0; (code = description [i]) != MONO_MT_END; i++){ switch (code){ @@ -1000,7 +1000,6 @@ mono_metadata_decode_blob_size (const char *xptr, const char **rptr) return size; } - /** * mono_metadata_decode_value: * @ptr: pointer to decode from @@ -1037,6 +1036,38 @@ mono_metadata_decode_value (const char *_ptr, const char **rptr) return len; } +/** + * mono_metadata_decode_signed_value: + * @ptr: pointer to decode from + * @rptr: the new position of the pointer + * + * This routine decompresses 32-bit signed values + * (not specified in the spec) + * + * Returns: the decoded value + */ +gint32 +mono_metadata_decode_signed_value (const char *ptr, const char **rptr) +{ + guint32 uval = mono_metadata_decode_value (ptr, rptr); + gint32 ival = uval >> 1; + if (!(uval & 1)) + return ival; + /* ival is a truncated 2's complement negative number. */ + if (ival < 0x40) + /* 6 bits = 7 bits for compressed representation (top bit is '0') - 1 sign bit */ + return ival - 0x40; + if (ival < 0x2000) + /* 13 bits = 14 bits for compressed representation (top bits are '10') - 1 sign bit */ + return ival - 0x2000; + if (ival < 0x10000000) + /* 28 bits = 29 bits for compressed representation (top bits are '110') - 1 sign bit */ + return ival - 0x10000000; + g_assert (ival < 0x20000000); + g_warning ("compressed signed value appears to use 29 bits for compressed representation: %x (raw: %8x)", ival, uval); + return ival - 0x20000000; +} + /* * mono_metadata_parse_typedef_or_ref: * @m: a metadata context. @@ -1093,14 +1124,16 @@ mono_metadata_parse_custom_mod (MonoImage *m, MonoCustomMod *dest, const char *p * and dimensions. */ MonoArrayType * -mono_metadata_parse_array_full (MonoImage *m, MonoGenericContext *generic_context, +mono_metadata_parse_array_full (MonoImage *m, MonoGenericContainer *container, const char *ptr, const char **rptr) { int i; MonoArrayType *array = g_new0 (MonoArrayType, 1); MonoType *etype; - etype = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_TYPE, 0, ptr, &ptr); + etype = mono_metadata_parse_type_full (m, container, MONO_PARSE_TYPE, 0, ptr, &ptr); + if (!etype) + return NULL; array->eklass = mono_class_from_mono_type (etype); array->rank = mono_metadata_decode_value (ptr, &ptr); @@ -1114,7 +1147,7 @@ mono_metadata_parse_array_full (MonoImage *m, MonoGenericContext *generic_contex if (array->numlobounds) array->lobounds = g_new0 (int, array->numlobounds); for (i = 0; i < array->numlobounds; ++i) - array->lobounds [i] = mono_metadata_decode_value (ptr, &ptr); + array->lobounds [i] = mono_metadata_decode_signed_value (ptr, &ptr); if (rptr) *rptr = ptr; @@ -1294,6 +1327,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 @@ -1315,10 +1362,12 @@ 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* -mono_metadata_parse_type_full (MonoImage *m, MonoGenericContext *generic_context, MonoParseTypeMode mode, +mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, MonoParseTypeMode mode, short opt_attrs, const char *ptr, const char **rptr) { MonoType *type, *cached; @@ -1361,12 +1410,11 @@ mono_metadata_parse_type_full (MonoImage *m, MonoGenericContext *generic_context } 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"); - } - else { + } else { type = &stype; memset (type, 0, sizeof (MonoType)); } @@ -1398,35 +1446,58 @@ mono_metadata_parse_type_full (MonoImage *m, MonoGenericContext *generic_context type->byref = byref; type->pinned = pinned ? 1 : 0; - do_mono_metadata_parse_type (type, m, generic_context, ptr, &ptr); + if (!do_mono_metadata_parse_type (type, m, container, ptr, &ptr)) { + if (type != &stype) + g_free (type); + return NULL; + } 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) { - if (type->byref) - return &type->data.klass->this_arg; - else - return &type->data.klass->byval_arg; + MonoType *ret = type->byref ? &type->data.klass->this_arg : &type->data.klass->byval_arg; + + /* Consider the case: + + class Foo { class Bar {} } + class Test : Foo.Bar {} + + When Foo is being expanded, 'Test' isn't yet initialized. It's actually in + a really pristine state: it doesn't even know whether 'Test' is a reference or a value type. + + We ensure that the MonoClass is in a state that we can canonicalize to: + + klass->byval_arg.data.klass == klass + klass->this_arg.data.klass == klass + + If we can't canonicalize 'type', it doesn't matter, since later users of 'type' will do it. + + LOCKING: even though we don't explicitly hold a lock, in the problematic case 'ret' is a field + of a MonoClass which currently holds the loader lock. 'type' is local. + */ + if (ret->data.klass == type->data.klass) + return ret; } /* No need to use locking since nobody is modifying the hash table */ if ((cached = g_hash_table_lookup (type_cache, type))) 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) @@ -1434,14 +1505,49 @@ 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 (methodt, def - 1, MONO_METHOD_PARAMLIST); + int *pattrs = NULL; + + if (def < methodt->rows) + lastp = mono_metadata_decode_row_col (methodt, def, MONO_METHOD_PARAMLIST); + else + lastp = paramt->rows + 1; + + for (i = param_index; i < lastp; ++i) { + mono_metadata_decode_row (paramt, 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 - * @generic_context: generics context + * @generic_container: generic container * @toke: metadata token * * Decode a method signature stored in the STANDALONESIG table * + * LOCKING: Assumes the loader lock is held. + * * Returns: a MonoMethodSignature describing the signature. */ MonoMethodSignature* @@ -1462,7 +1568,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); } /* @@ -1489,6 +1595,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* @@ -1496,8 +1604,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; @@ -1518,14 +1625,14 @@ mono_metadata_signature_dup (MonoMethodSignature *sig) { int sigsize; - sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *); + sigsize = sizeof (MonoMethodSignature) + (sig->param_count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType *); return g_memdup (sig, sigsize); } /* * mono_metadata_parse_method_signature: * @m: metadata context - * @generic_context: generics context + * @generic_container: generics container * @def: the MethodDef index or 0 for Ref signatures. * @ptr: pointer to the signature metadata representation * @rptr: pointer updated to match the end of the decoded stream @@ -1533,18 +1640,19 @@ 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 * -mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *generic_container, +mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *container, int def, const char *ptr, const char **rptr) { MonoMethodSignature *method; - int i, ret_attrs = 0, *pattrs = NULL; + int i, *pattrs = NULL; guint32 hasthis = 0, explicit_this = 0, call_convention, param_count; guint32 gen_param_count = 0; gboolean is_open = FALSE; - MonoGenericContainer *container; if (*ptr & 0x10) gen_param_count = 1; @@ -1557,77 +1665,48 @@ mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *g if (gen_param_count) gen_param_count = mono_metadata_decode_value (ptr, &ptr); param_count = mono_metadata_decode_value (ptr, &ptr); - pattrs = g_new0 (int, param_count); - - 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; - for (i = param_index; i < lastp; ++i) { - mono_metadata_decode_row (paramt, i - 1, cols, MONO_PARAM_SIZE); - if (!cols [MONO_PARAM_SEQUENCE]) - ret_attrs = cols [MONO_PARAM_FLAGS]; - else - pattrs [cols [MONO_PARAM_SEQUENCE] - 1] = 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; method->call_convention = call_convention; method->generic_param_count = gen_param_count; - if (gen_param_count) - method->has_type_parameters = 1; - - if (gen_param_count && (!generic_container || !generic_container->is_method)) { - container = g_new0 (MonoGenericContainer, 1); - - container->parent = generic_container; - container->is_signature = 1; - - container->context.container = container; - - container->type_argc = gen_param_count; - container->type_params = g_new0 (MonoGenericParam, gen_param_count); - - for (i = 0; i < gen_param_count; i++) { - container->type_params [i].owner = container; - container->type_params [i].num = i; - } - } else { - container = generic_container; - } - if (call_convention != 0xa) { - method->ret = mono_metadata_parse_type_full (m, (MonoGenericContext *) container, MONO_PARSE_RET, ret_attrs, ptr, &ptr); + method->ret = mono_metadata_parse_type_full (m, container, MONO_PARSE_RET, pattrs ? pattrs [0] : 0, ptr, &ptr); + if (!method->ret) { + mono_metadata_free_method_signature (method); + g_free (pattrs); + return NULL; + } is_open = mono_class_is_open_constructed_type (method->ret); } - if (method->param_count) { - method->sentinelpos = -1; - - for (i = 0; i < method->param_count; ++i) { - if (*ptr == MONO_TYPE_SENTINEL) { - if (method->call_convention != MONO_CALL_VARARG || def) - g_error ("found sentinel for methoddef or no vararg method"); - method->sentinelpos = i; - ptr++; - } - method->params [i] = mono_metadata_parse_type_full ( - m, (MonoGenericContext *) container, MONO_PARSE_PARAM, - pattrs [i], ptr, &ptr); - if (!is_open) - is_open = mono_class_is_open_constructed_type (method->params [i]); + for (i = 0; i < method->param_count; ++i) { + 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++; } + method->params [i] = mono_metadata_parse_type_full (m, container, MONO_PARSE_PARAM, pattrs ? pattrs [i+1] : 0, ptr, &ptr); + if (!method->params [i]) { + mono_metadata_free_method_signature (method); + g_free (pattrs); + return NULL; + } + if (!is_open) + 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)) @@ -1654,6 +1733,8 @@ mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *g * 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 * @@ -1667,18 +1748,33 @@ mono_metadata_parse_method_signature (MonoImage *m, int def, const char *ptr, co * @sig: signature to destroy * * Free the memory allocated in the signature @sig. + * This method needs to be robust and work also on partially-built + * signatures, so it does extra checks. */ void mono_metadata_free_method_signature (MonoMethodSignature *sig) { int i; - mono_metadata_free_type (sig->ret); - for (i = 0; i < sig->param_count; ++i) - mono_metadata_free_type (sig->params [i]); - - g_free (sig); + if (sig->ret) + mono_metadata_free_type (sig->ret); + for (i = 0; i < sig->param_count; ++i) { + if (sig->params [i]) + mono_metadata_free_type (sig->params [i]); + } } +/* + * mono_metadata_lookup_generic_inst: + * + * Check whether the newly created generic instantiation @ginst already exists + * in the cache and return the cached value in this case. Otherwise insert + * it into the cache. + * + * Use this method each time you create a new `MonoGenericInst' to ensure + * proper caching. Only use the returned value as the argument passed to this + * method may be freed. + * + */ MonoGenericInst * mono_metadata_lookup_generic_inst (MonoGenericInst *ginst) { @@ -1700,6 +1796,17 @@ mono_metadata_lookup_generic_inst (MonoGenericInst *ginst) return ginst; } +/* + * mono_metadata_lookup_generic_class: + * + * Check whether the newly created generic class @gclass already exists + * in the cache and return the cached value in this case. Otherwise insert + * it into the cache and return NULL. + * + * Returns: the previosly cached generic class or NULL if it has been newly + * inserted into the cache. + * + */ MonoGenericClass * mono_metadata_lookup_generic_class (MonoGenericClass *gclass) { @@ -1713,12 +1820,21 @@ mono_metadata_lookup_generic_class (MonoGenericClass *gclass) return NULL; } +/* + * mono_metadata_inflate_generic_inst: + * + * Instantiate the generic instance @ginst with the context @context. + * + */ MonoGenericInst * mono_metadata_inflate_generic_inst (MonoGenericInst *ginst, MonoGenericContext *context) { MonoGenericInst *nginst; int i; + if (!ginst->is_open) + return ginst; + nginst = g_new0 (MonoGenericInst, 1); nginst->type_argc = ginst->type_argc; nginst->type_argv = g_new0 (MonoType*, nginst->type_argc); @@ -1739,7 +1855,7 @@ mono_metadata_inflate_generic_inst (MonoGenericInst *ginst, MonoGenericContext * } MonoGenericInst * -mono_metadata_parse_generic_inst (MonoImage *m, MonoGenericContext *generic_context, +mono_metadata_parse_generic_inst (MonoImage *m, MonoGenericContainer *container, int count, const char *ptr, const char **rptr) { MonoGenericInst *ginst; @@ -1751,8 +1867,13 @@ mono_metadata_parse_generic_inst (MonoImage *m, MonoGenericContext *generic_cont ginst->is_reference = 1; for (i = 0; i < ginst->type_argc; i++) { - MonoType *t = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_TYPE, 0, ptr, &ptr); + MonoType *t = mono_metadata_parse_type_full (m, container, MONO_PARSE_TYPE, 0, ptr, &ptr); + if (!t) { + g_free (ginst->type_argv); + g_free (ginst); + return NULL; + } ginst->type_argv [i] = t; if (!ginst->is_open) ginst->is_open = mono_class_is_open_constructed_type (t); @@ -1766,8 +1887,8 @@ mono_metadata_parse_generic_inst (MonoImage *m, MonoGenericContext *generic_cont return mono_metadata_lookup_generic_inst (ginst); } -static void -do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericContext *generic_context, +static gboolean +do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericContainer *container, const char *ptr, const char **rptr) { MonoInflatedGenericClass *igclass; @@ -1785,25 +1906,32 @@ do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericC gclass->context = g_new0 (MonoGenericContext, 1); gclass->context->gclass = gclass; - igclass->klass = g_new0 (MonoClass, 1); - - gtype = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_TYPE, 0, ptr, &ptr); - gclass->container_class = gklass = mono_class_from_mono_type (gtype); - - g_assert ((gclass->context->container = gklass->generic_container) != NULL); - count = mono_metadata_decode_value (ptr, &ptr); - /* * Create the klass before parsing the type arguments. * This is required to support "recursive" definitions. * See mcs/tests/gen-23.cs for an example. */ + 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); - gclass->inst = mono_metadata_parse_generic_inst (m, generic_context, count, ptr, &ptr); + g_assert (gklass->generic_container); + gclass->context->container = gklass->generic_container; + + count = mono_metadata_decode_value (ptr, &ptr); + + gclass->inst = mono_metadata_parse_generic_inst (m, container, count, ptr, &ptr); 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 @@ -1824,7 +1952,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); @@ -1833,52 +1961,62 @@ do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericC sizeof (MonoGenericContext) + gclass->inst->type_argc * sizeof (MonoType); } + return TRUE; +} + +/* + * select_container: + * @gc: The generic container to normalize + * @type: The kind of generic parameters the resulting generic-container should contain + */ + +static MonoGenericContainer * +select_container (MonoGenericContainer *gc, MonoTypeEnum type) +{ + gboolean is_var = (type == MONO_TYPE_VAR); + if (!gc) + return NULL; + + g_assert (is_var || type == MONO_TYPE_MVAR); + + 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; } /* - * do_mono_metadata_parse_generic_param: + * mono_metadata_parse_generic_param: * @generic_container: Our MonoClass's or MonoMethodNormal's MonoGenericContainer; * see mono_metadata_parse_type_full() for details. * Internal routine to parse a generic type parameter. */ static MonoGenericParam * -mono_metadata_parse_generic_param (MonoImage *m, MonoGenericContext *generic_context, - gboolean is_mvar, const char *ptr, const char **rptr) +mono_metadata_parse_generic_param (MonoImage *m, MonoGenericContainer *generic_container, + MonoTypeEnum type, const char *ptr, const char **rptr) { - MonoGenericContainer *generic_container; - int index; - - index = mono_metadata_decode_value (ptr, &ptr); + int index = mono_metadata_decode_value (ptr, &ptr); if (rptr) *rptr = ptr; - g_assert (generic_context); - if (generic_context->gmethod) - generic_container = generic_context->gmethod->container; - else if (generic_context->gclass) - generic_container = generic_context->gclass->container_class->generic_container; - else - generic_container = generic_context->container; - - if (!is_mvar) { - g_assert (generic_container); - if (generic_container->parent) { - /* - * The current MonoGenericContainer is a generic method -> its `parent' - * points to the containing class'es container. - */ - generic_container = generic_container->parent; - } - g_assert (generic_container && !generic_container->is_method); - g_assert (index < generic_container->type_argc); - - return &generic_container->type_params [index]; - } else { - g_assert (generic_container && (generic_container->is_method || generic_container->is_signature)); - g_assert (index < generic_container->type_argc); + generic_container = select_container (generic_container, type); + if (!generic_container) { + /* Create dummy MonoGenericParam */ + MonoGenericParam *param = g_new0 (MonoGenericParam, 1); + param->name = g_strdup_printf ("%d", index); + param->num = index; - return &generic_container->type_params [index]; + return param; } + + g_assert (index < generic_container->type_argc); + return &generic_container->type_params [index]; } /* @@ -1898,11 +2036,14 @@ mono_metadata_parse_generic_param (MonoImage *m, MonoGenericContext *generic_con * mono_metadata_parse_field_type * * This extracts a Type as specified in Partition II (22.2.12) + * + * Returns: FALSE if the type could not be loaded */ -static void -do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContext *generic_context, +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){ @@ -1930,33 +2071,35 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContext *g guint32 token; token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr); type->data.klass = mono_class_get (m, token); + if (!type->data.klass) + return FALSE; break; } case MONO_TYPE_SZARRAY: { - MonoType *etype = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr); + MonoType *etype = mono_metadata_parse_type_full (m, container, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr); + if (!etype) + return FALSE; type->data.klass = mono_class_from_mono_type (etype); mono_metadata_free_type (etype); break; } case MONO_TYPE_PTR: - type->data.type = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr); + type->data.type = mono_metadata_parse_type_full (m, container, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr); + if (!type->data.type) + return FALSE; break; - case MONO_TYPE_FNPTR: { - MonoGenericContainer *container = generic_context ? generic_context->container : NULL; + case MONO_TYPE_FNPTR: type->data.method = mono_metadata_parse_method_signature_full (m, container, 0, ptr, &ptr); break; - } case MONO_TYPE_ARRAY: - type->data.array = mono_metadata_parse_array_full (m, generic_context, ptr, &ptr); + type->data.array = mono_metadata_parse_array_full (m, container, ptr, &ptr); break; case MONO_TYPE_MVAR: - type->data.generic_param = mono_metadata_parse_generic_param (m, generic_context, TRUE, ptr, &ptr); - break; case MONO_TYPE_VAR: - type->data.generic_param = mono_metadata_parse_generic_param (m, generic_context, FALSE, ptr, &ptr); + 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, generic_context, 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); @@ -1964,13 +2107,15 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContext *g if (rptr) *rptr = ptr; + 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) @@ -1999,7 +2144,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 @@ -2065,7 +2211,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; @@ -2114,10 +2260,12 @@ 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, MonoGenericContext *generic_context, const char *ptr) +mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, const char *ptr) { MonoMethodHeader *mh; unsigned char flags = *(const unsigned char *) ptr; @@ -2131,7 +2279,7 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContext *generic_context, 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; @@ -2139,7 +2287,7 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContext *generic_context, 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; @@ -2194,13 +2342,17 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContext *generic_context, 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) + for (i = 0; i < len; ++i) { mh->locals [i] = mono_metadata_parse_type_full ( - m, generic_context, MONO_PARSE_LOCAL, 0, locals_ptr, &locals_ptr); + m, container, MONO_PARSE_LOCAL, 0, locals_ptr, &locals_ptr); + if (!mh->locals [i]) { + return NULL; + } + } } else { - mh = g_new0 (MonoMethodHeader, 1); + mh = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodHeader)); } mh->code = code; mh->code_size = code_size; @@ -2225,7 +2377,15 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContext *generic_context, 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; } /* @@ -2238,11 +2398,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 */ } /* @@ -2582,6 +2738,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 @@ -2589,7 +2747,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; @@ -2616,18 +2774,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; - result = g_renew (MonoClass*, result, i + 1); - result [i] = mono_class_get_full ( + ++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; + 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; } @@ -2638,7 +2809,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 @@ -2836,6 +3009,7 @@ mono_backtrace (int limit) * * Returns: the number of bytes required to hold an instance of this * type in memory + * FIXME: This should really use 'guint32*' for the align parameter. */ int mono_type_size (MonoType *t, gint *align) @@ -2909,8 +3083,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; @@ -2941,6 +3115,7 @@ mono_type_size (MonoType *t, gint *align) * * Returns: the number of bytes required to hold an instance of this * type on the runtime stack + * FIXME: This should really use 'guint32*' for the align parameter. */ int mono_type_stack_size (MonoType *t, gint *align) @@ -3042,6 +3217,13 @@ mono_type_stack_size (MonoType *t, gint *align) return 0; } +gboolean +mono_type_generic_inst_is_valuetype (MonoType *type) +{ + g_assert (type->type == MONO_TYPE_GENERICINST); + return type->data.generic_class->container_class->valuetype; +} + gboolean mono_metadata_generic_class_is_valuetype (MonoGenericClass *gclass) { @@ -3115,7 +3297,6 @@ mono_metadata_generic_param_equal (MonoGenericParam *p1, MonoGenericParam *p2, g if (p1->num != p2->num) return FALSE; - g_assert (p1->owner && p2->owner); if (p1->owner == p2->owner) return TRUE; @@ -3136,7 +3317,7 @@ mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only return _mono_metadata_generic_class_equal (c1->generic_class, c2->generic_class, signature_only); if ((c1->byval_arg.type == MONO_TYPE_VAR) && (c2->byval_arg.type == MONO_TYPE_VAR)) return mono_metadata_generic_param_equal ( - c1->byval_arg.data.generic_param, c2->byval_arg.data.generic_param, FALSE); + c1->byval_arg.data.generic_param, c2->byval_arg.data.generic_param, signature_only); if ((c1->byval_arg.type == MONO_TYPE_MVAR) && (c2->byval_arg.type == MONO_TYPE_MVAR)) return mono_metadata_generic_param_equal ( c1->byval_arg.data.generic_param, c2->byval_arg.data.generic_param, signature_only); @@ -3146,6 +3327,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 @@ -3199,6 +3411,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; @@ -3255,6 +3469,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) { @@ -3608,24 +3847,25 @@ mono_metadata_implmap_from_method (MonoImage *meta, guint32 method_idx) * token. */ MonoType * -mono_type_create_from_typespec_full (MonoImage *image, MonoGenericContext *generic_context, guint32 type_spec) +mono_type_create_from_typespec (MonoImage *image, guint32 type_spec) { guint32 idx = mono_metadata_token_index (type_spec); MonoTableInfo *t; - guint32 cols [MONO_TYPESPEC_SIZE]; + guint32 cols [MONO_TYPESPEC_SIZE]; const char *ptr; guint32 len; MonoType *type; mono_loader_lock (); - if ((type = g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec)))) { + type = g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec)); + if (type) { mono_loader_unlock (); return type; } t = &image->tables [MONO_TABLE_TYPESPEC]; - + mono_metadata_decode_row (t, idx-1, cols, MONO_TYPESPEC_SIZE); ptr = mono_metadata_blob_heap (image, cols [MONO_TYPESPEC_SIGNATURE]); len = mono_metadata_decode_value (ptr, &ptr); @@ -3635,23 +3875,22 @@ mono_type_create_from_typespec_full (MonoImage *image, MonoGenericContext *gener g_hash_table_insert (image->typespec_cache, GUINT_TO_POINTER (type_spec), type); if (*ptr == MONO_TYPE_BYREF) { - type->byref = 1; + type->byref = 1; ptr++; } - do_mono_metadata_parse_type (type, image, generic_context, ptr, &ptr); + if (!do_mono_metadata_parse_type (type, image, NULL, ptr, &ptr)) { + g_hash_table_remove (image->typespec_cache, GUINT_TO_POINTER (type_spec)); + g_free (type); + mono_loader_unlock (); + return NULL; + } mono_loader_unlock (); return type; } -MonoType * -mono_type_create_from_typespec (MonoImage *image, guint32 type_spec) -{ - return mono_type_create_from_typespec_full (image, NULL, type_spec); -} - MonoMarshalSpec * mono_metadata_parse_marshal_spec (MonoImage *image, const char *ptr) { @@ -3829,7 +4068,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; @@ -3946,7 +4188,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; @@ -3981,17 +4224,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; } /** @@ -4011,14 +4262,18 @@ mono_guid_to_string (const guint8 *guid) } static gboolean -get_constraints (MonoImage *image, int owner, MonoClass ***constraints, MonoGenericContext *context) +get_constraints (MonoImage *image, int owner, MonoClass ***constraints, MonoGenericContainer *container) { MonoTableInfo *tdef = &image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT]; guint32 cols [MONO_GENPARCONSTRAINT_SIZE]; guint32 i, token, found; MonoClass *klass, **res; GList *cons = NULL, *tmp; - + MonoGenericContext *context = &container->context; + + /* FIXME: !container->klass => this is probably monodis */ + g_assert (!container->klass || context->gclass || context->gmethod); + *constraints = NULL; found = 0; for (i = 0; i < tdef->rows; ++i) { @@ -4045,65 +4300,98 @@ get_constraints (MonoImage *image, int owner, MonoClass ***constraints, MonoGene return TRUE; } -gboolean -mono_metadata_has_generic_params (MonoImage *image, guint32 token) +/* + * mono_metadata_get_generic_param_row: + * + * @image: + * @token: TypeOrMethodDef token, owner for GenericParam + * @owner: coded token, set on return + * + * Returns: 1-based row-id in the GenericParam table whose + * owner is @token. 0 if not found. + */ +guint32 +mono_metadata_get_generic_param_row (MonoImage *image, guint32 token, guint32 *owner) { MonoTableInfo *tdef = &image->tables [MONO_TABLE_GENERICPARAM]; guint32 cols [MONO_GENERICPARAM_SIZE]; - guint32 i, owner = 0; + guint32 i; + + g_assert (owner); + if (!tdef->base) + return 0; if (mono_metadata_token_table (token) == MONO_TABLE_TYPEDEF) - owner = MONO_TYPEORMETHOD_TYPE; + *owner = MONO_TYPEORMETHOD_TYPE; else if (mono_metadata_token_table (token) == MONO_TABLE_METHOD) - owner = MONO_TYPEORMETHOD_METHOD; + *owner = MONO_TYPEORMETHOD_METHOD; else { - g_error ("wrong token %x to load_generics_params", token); - return FALSE; + g_error ("wrong token %x to get_generic_param_row", token); + return 0; } - owner |= mono_metadata_token_index (token) << MONO_TYPEORMETHOD_BITS; - if (!tdef->base) - return FALSE; + *owner |= mono_metadata_token_index (token) << MONO_TYPEORMETHOD_BITS; for (i = 0; i < tdef->rows; ++i) { mono_metadata_decode_row (tdef, i, cols, MONO_GENERICPARAM_SIZE); - if (cols [MONO_GENERICPARAM_OWNER] == owner) - break; + if (cols [MONO_GENERICPARAM_OWNER] == *owner) + return i + 1; } - if (i >= tdef->rows) - return FALSE; - return TRUE; + return 0; } +gboolean +mono_metadata_has_generic_params (MonoImage *image, guint32 token) +{ + guint32 owner; + return mono_metadata_get_generic_param_row (image, token, &owner); +} + +/* + * mono_metadata_load_generic_param_constraints: + * + * Load the generic parameter constraints for the newly created generic type or method + * represented by @token and @container. The @container is the new container which has + * been returned by a call to mono_metadata_load_generic_params() with this @token. + */ +void +mono_metadata_load_generic_param_constraints (MonoImage *image, guint32 token, + MonoGenericContainer *container) +{ + guint32 start_row, i, owner; + if (! (start_row = mono_metadata_get_generic_param_row (image, token, &owner))) + return; + for (i = 0; i < container->type_argc; i++) + get_constraints (image, start_row + i, &container->type_params [i].constraints, container); +} + +/* + * mono_metadata_load_generic_params: + * + * Load the type parameters from the type or method definition @token. + * + * Use this method after parsing a type or method definition to figure out whether it's a generic + * type / method. When parsing a method definition, @parent_container points to the generic container + * of the current class, if any. + * + * Note: This method does not load the constraints: for typedefs, this has to be done after fully + * creating the type. + * + * Returns: NULL if @token is not a generic type or method definition or the new generic container. + * + */ MonoGenericContainer * mono_metadata_load_generic_params (MonoImage *image, guint32 token, MonoGenericContainer *parent_container) { MonoTableInfo *tdef = &image->tables [MONO_TABLE_GENERICPARAM]; guint32 cols [MONO_GENERICPARAM_SIZE]; - guint32 i, owner = 0, last_num, n; + guint32 i, owner = 0, n; MonoGenericContainer *container; MonoGenericParam *params; - if (mono_metadata_token_table (token) == MONO_TABLE_TYPEDEF) - owner = MONO_TYPEORMETHOD_TYPE; - else if (mono_metadata_token_table (token) == MONO_TABLE_METHOD) - owner = MONO_TYPEORMETHOD_METHOD; - else { - g_error ("wrong token %x to load_generics_params", token); - return NULL; - } - owner |= mono_metadata_token_index (token) << MONO_TYPEORMETHOD_BITS; - if (!tdef->base) - return NULL; - - for (i = 0; i < tdef->rows; ++i) { - mono_metadata_decode_row (tdef, i, cols, MONO_GENERICPARAM_SIZE); - if (cols [MONO_GENERICPARAM_OWNER] == owner) - break; - } - last_num = i; - if (i >= tdef->rows) + if (!(i = mono_metadata_get_generic_param_row (image, token, &owner))) return NULL; + mono_metadata_decode_row (tdef, i - 1, cols, MONO_GENERICPARAM_SIZE); params = NULL; n = 0; container = g_new0 (MonoGenericContainer, 1); @@ -4116,9 +4404,10 @@ mono_metadata_load_generic_params (MonoImage *image, guint32 token, MonoGenericC params [n - 1].flags = cols [MONO_GENERICPARAM_FLAGS]; params [n - 1].num = cols [MONO_GENERICPARAM_NUMBER]; params [n - 1].name = mono_metadata_string_heap (image, cols [MONO_GENERICPARAM_NAME]); - if (++i >= tdef->rows) + params [n - 1].constraints = NULL; + if (++i > tdef->rows) break; - mono_metadata_decode_row (tdef, i, cols, MONO_GENERICPARAM_SIZE); + mono_metadata_decode_row (tdef, i - 1, cols, MONO_GENERICPARAM_SIZE); } while (cols [MONO_GENERICPARAM_OWNER] == owner); container->type_argc = n; @@ -4130,9 +4419,6 @@ mono_metadata_load_generic_params (MonoImage *image, guint32 token, MonoGenericC container->context.container = container; - for (i = 0; i < n; i++) - get_constraints (image, last_num + i + 1, ¶ms [i].constraints, &container->context); - return container; }