X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fmetadata.c;h=b24838da7b8ec6dc601c33872d830b2a37d6f5e5;hb=07e742b4fe7519428d788a39f51bee556d681273;hp=8295d5a98210db6f987233387bbdafb926e83c17;hpb=f5eea78af0b7aaef150a3582d52678e19e2aafbc;p=mono.git diff --git a/mono/metadata/metadata.c b/mono/metadata/metadata.c index 8295d5a9821..b24838da7b8 100644 --- a/mono/metadata/metadata.c +++ b/mono/metadata/metadata.c @@ -9,7 +9,7 @@ */ #include -#include +#include #include #include #include @@ -22,16 +22,15 @@ #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); -GHashTable *mono_generic_params_with_ambiguous_names; - /* * This enumeration is used to describe the data types in the metadata * tables @@ -93,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" }, */ @@ -103,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" }, */ @@ -128,296 +125,313 @@ 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, + +#define EVENT_POINTER_SCHEMA_OFFSET EVENT_SCHEMA_OFFSET + 4 + MONO_MT_TABLE_IDX, /* "Event" }, */ + MONO_MT_END, -const static unsigned char ExportedTypeSchema [] = { +#define EXPORTED_TYPE_SCHEMA_OFFSET EVENT_POINTER_SCHEMA_OFFSET + 2 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, + +#define FIELD_POINTER_SCHEMA_OFFSET FIELD_RVA_SCHEMA_OFFSET + 3 + MONO_MT_TABLE_IDX, /* "Field" }, */ + MONO_MT_END, -const static unsigned char FileSchema [] = { +#define FILE_SCHEMA_OFFSET FIELD_POINTER_SCHEMA_OFFSET + 2 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, + +#define METHOD_POINTER_SCHEMA_OFFSET METHOD_SEMA_SCHEMA_OFFSET + 4 + MONO_MT_TABLE_IDX, /* "Method" }, */ + MONO_MT_END, -const static unsigned char ModuleSchema [] = { +#define MODULE_SCHEMA_OFFSET METHOD_POINTER_SCHEMA_OFFSET + 2 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 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 -}; + MONO_MT_END, + +#define PROPERTY_POINTER_SCHEMA_OFFSET PROPERTY_SCHEMA_OFFSET + 4 + MONO_MT_TABLE_IDX, /* "Property" }, */ + MONO_MT_END, -const static unsigned char PropertyMapSchema [] = { +#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 -}; + 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, + FIELD_POINTER_SCHEMA_OFFSET, + FIELD_SCHEMA_OFFSET, + METHOD_POINTER_SCHEMA_OFFSET, + METHOD_SCHEMA_OFFSET, + PARAM_POINTER_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, + EVENT_POINTER_SCHEMA_OFFSET, + EVENT_SCHEMA_OFFSET, + PROPERTY_MAP_SCHEMA_OFFSET, + PROPERTY_POINTER_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 @@ -427,10 +441,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 @@ -467,7 +485,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){ @@ -514,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 */ @@ -524,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; @@ -539,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): @@ -969,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 @@ -1002,7 +1036,6 @@ mono_metadata_decode_blob_size (const char *xptr, const char **rptr) return size; } - /** * mono_metadata_decode_value: * @ptr: pointer to decode from @@ -1039,6 +1072,114 @@ 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; +} + +/* + * 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. @@ -1095,14 +1236,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); @@ -1116,7 +1259,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; @@ -1296,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 @@ -1317,10 +1474,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; @@ -1363,12 +1522,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)); } @@ -1400,35 +1558,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) @@ -1436,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 @@ -1444,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* @@ -1464,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); } /* @@ -1491,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* @@ -1498,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; @@ -1535,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 * @@ -1559,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; @@ -1583,9 +1787,12 @@ mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *c method->generic_param_count = gen_param_count; if (call_convention != 0xa) { - method->ret = mono_metadata_parse_type_full ( - m, (MonoGenericContext *) container, MONO_PARSE_RET, - pattrs ? pattrs [0] : 0, 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); } @@ -1593,16 +1800,25 @@ 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++; } - method->params [i] = mono_metadata_parse_type_full ( - m, (MonoGenericContext *) container, MONO_PARSE_PARAM, - pattrs ? pattrs [i+1] : 0, ptr, &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)) @@ -1629,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 * @@ -1642,16 +1860,19 @@ 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]); + } } /* @@ -1723,6 +1944,9 @@ mono_metadata_inflate_generic_inst (MonoGenericInst *ginst, MonoGenericContext * 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); @@ -1743,7 +1967,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; @@ -1755,8 +1979,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); @@ -1770,8 +1999,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; @@ -1797,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); @@ -1804,11 +2035,15 @@ do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericC count = mono_metadata_decode_value (ptr, &ptr); - gclass->inst = mono_metadata_parse_generic_inst (m, generic_context, count, 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 @@ -1829,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); @@ -1838,6 +2073,7 @@ do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericC sizeof (MonoGenericContext) + gclass->inst->type_argc * sizeof (MonoType); } + return TRUE; } /* @@ -1855,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; } @@ -1915,12 +2148,14 @@ mono_metadata_parse_generic_param (MonoImage *m, MonoGenericContainer *generic_c * 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) { - MonoGenericContainer *container = generic_context ? generic_context->container : NULL; + gboolean ok = TRUE; type->type = mono_metadata_decode_value (ptr, &ptr); switch (type->type){ @@ -1948,29 +2183,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: 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: case MONO_TYPE_VAR: 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); @@ -1978,13 +2219,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) @@ -2013,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 @@ -2079,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; @@ -2128,10 +2372,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; @@ -2145,7 +2391,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; @@ -2153,7 +2399,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; @@ -2208,13 +2454,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; @@ -2239,7 +2489,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; } /* @@ -2252,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 */ } /* @@ -2532,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 @@ -2553,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 (); @@ -2581,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 (); @@ -2596,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 @@ -2603,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; @@ -2630,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; - 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; } @@ -2652,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 @@ -2780,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; @@ -2852,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; @@ -2923,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; @@ -2957,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); @@ -3056,6 +3359,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) { @@ -3159,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 @@ -3212,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; @@ -3268,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) { @@ -3335,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]; @@ -3409,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; @@ -3478,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 */ @@ -3566,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 */ @@ -3603,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; @@ -3613,62 +3994,6 @@ mono_metadata_implmap_from_method (MonoImage *meta, guint32 method_idx) return loc.result + 1; } -/** - * @ptr: MonoType to unwrap - * - * Recurses in array/szarray to get the element type. - * Returns the element MonoType or the @ptr itself if its not an array/szarray. - */ -static MonoType* -unwrap_arrays (MonoType *ptr) -{ - for (;;) { - if (ptr->type == MONO_TYPE_ARRAY) - ptr = &ptr->data.array->eklass->byval_arg; - else if (ptr->type == MONO_TYPE_SZARRAY) - ptr = &ptr->data.klass->byval_arg; - else - return ptr; - } -} - -/** - * @inst: MonoGenericClass to search in - * @prefer_mvar: Whether to try harder to find an MVAR - * - * Return some occurance of a generic parameter in this instantiation, if any. Return NULL otherwise. - * If @prefer_mvar is set, it tries to find if there's an MVAR generic parameter, and returns that - * in preference to any VAR generic parameter. - */ -static MonoType * -find_generic_param (MonoGenericClass *gclass, gboolean prefer_mvar) -{ - int i = 0, count = gclass->inst->type_argc; - MonoType **ptr = gclass->inst->type_argv; - MonoType *fallback = NULL; - - g_assert (gclass->inst->is_open); - - for (i = 0; i < count; i++) { - MonoType *ctype = unwrap_arrays (ptr [i]); - - if (ctype->type == MONO_TYPE_GENERICINST && ctype->data.generic_class->inst->is_open) - ctype = find_generic_param (ctype->data.generic_class, prefer_mvar); - - if (ctype->type == MONO_TYPE_MVAR) - return ctype; - - if (ctype->type == MONO_TYPE_VAR) { - if (prefer_mvar) - fallback = ctype; - else - return ctype; - } - } - - return fallback; -} - /** * @image: context where the image is created * @type_spec: typespec token @@ -3677,80 +4002,43 @@ find_generic_param (MonoGenericClass *gclass, gboolean prefer_mvar) * 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; - gboolean cache_type = TRUE; - MonoGenericContainer *gc = generic_context ? generic_context->container : NULL; mono_loader_lock (); type = g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec)); - - if (type && type->type == MONO_TYPE_GENERICINST && type->data.generic_class->inst->is_open) { - MonoType *gtype = find_generic_param (type->data.generic_class, gc ? gc->is_method : FALSE); - gc = select_container (gc, gtype->type); - if (gtype->data.generic_param->owner != gc) - type = NULL; - } - - if (type && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) { - gc = select_container (gc, type->type); - if (gc) { - /* Use the one already cached in the container, if it exists. Otherwise, ensure that it's created */ - type = gc->types ? gc->types [type->data.generic_param->num] : NULL; - - /* Either way, some other variant of this generic-parameter is already in the typespec cache. */ - cache_type = FALSE; - } else if (type->data.generic_param->owner) { - /* - * We need a null-owner generic-parameter, but the one in the cache has an owner. - * Ensure that the null-owner generic-parameter goes into the cache. - * - * Together with the 'cache_type = FALSE;' line in the other arm of this condition, - * this ensures that a null-owner generic-parameter, once created, doesn't need to be re-created. - * The generic-parameters with owners are cached in their respective owners, and thus don't - * need to be re-created either. - */ - type = NULL; - } - } - 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); type = g_new0 (MonoType, 1); - if (cache_type) - g_hash_table_insert (image->typespec_cache, GUINT_TO_POINTER (type_spec), type); + 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 ((type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) && type->data.generic_param->owner) { - MonoGenericContainer *container = type->data.generic_param->owner; - - if (!container->types) - container->types = g_new0 (MonoType*, container->type_argc); - - container->types [type->data.generic_param->num] = type; + 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 (); @@ -3758,12 +4046,6 @@ mono_type_create_from_typespec_full (MonoImage *image, MonoGenericContext *gener 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) { @@ -3941,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; @@ -4020,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; @@ -4030,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); @@ -4058,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; @@ -4093,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; } /** @@ -4123,14 +4420,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) { @@ -4219,8 +4520,7 @@ mono_metadata_load_generic_param_constraints (MonoImage *image, guint32 token, 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->context); + get_constraints (image, start_row + i, &container->type_params [i].constraints, container); } /* @@ -4246,16 +4546,12 @@ mono_metadata_load_generic_params (MonoImage *image, guint32 token, MonoGenericC guint32 i, owner = 0, n; MonoGenericContainer *container; MonoGenericParam *params; - gpointer *p; - GSList *dup_list = NULL, *l; - GHashTable *table = NULL; 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; - table = g_hash_table_new (g_str_hash, g_str_equal); container = g_new0 (MonoGenericContainer, 1); do { n++; @@ -4266,28 +4562,12 @@ 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 ((p = g_hash_table_lookup (table, params [n - 1].name))) - dup_list = g_slist_prepend (g_slist_prepend (dup_list, GUINT_TO_POINTER (n)), p); - else - g_hash_table_insert (table, params [n - 1].name, GUINT_TO_POINTER (n)); params [n - 1].constraints = NULL; if (++i > tdef->rows) break; mono_metadata_decode_row (tdef, i - 1, cols, MONO_GENERICPARAM_SIZE); } while (cols [MONO_GENERICPARAM_OWNER] == owner); - if (dup_list) { - if (!mono_generic_params_with_ambiguous_names) - mono_generic_params_with_ambiguous_names = g_hash_table_new (NULL, NULL); - for (l = dup_list; l; l = l->next) { - int param = GPOINTER_TO_UINT (l->data); - g_hash_table_insert (mono_generic_params_with_ambiguous_names, ¶ms [param-1], ¶ms [param-1]); - } - g_slist_free (dup_list); - } - g_hash_table_destroy (table); - table = NULL; - container->type_argc = n; container->type_params = params; container->parent = parent_container; @@ -4333,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) {