X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Freflection.c;h=14b0ab443b6d52f6f0bf0ebfe187f34ac11e9652;hb=42a1173c3ffab9bbd5730ee8e7fcd7cdebafc28d;hp=b59233a139b22a680f5341d25fa5497e1aec6458;hpb=35566c80c20c0ef1e28ca0199e69cebd254125e0;p=mono.git diff --git a/mono/metadata/reflection.c b/mono/metadata/reflection.c index b59233a139b..14b0ab443b6 100644 --- a/mono/metadata/reflection.c +++ b/mono/metadata/reflection.c @@ -12,6 +12,7 @@ #include "mono/metadata/reflection.h" #include "mono/metadata/tabledefs.h" #include "mono/metadata/metadata-internals.h" +#include #include "mono/metadata/class-internals.h" #include "mono/metadata/gc-internal.h" #include "mono/metadata/tokentype.h" @@ -32,7 +33,7 @@ #include "cil-coff.h" #include "rawbuffer.h" #include "mono-endian.h" -#include +#include typedef struct { char *p; @@ -134,6 +135,7 @@ const unsigned char table_sizes [MONO_TABLE_NUM] = { static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb); static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb); static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type); +static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec); static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method); static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb); static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb); @@ -143,12 +145,12 @@ static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMa static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type); static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass); static void ensure_runtime_vtable (MonoClass *klass); -static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class); +static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context); static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf); static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types); static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob); -static inline MonoType *dup_type (const MonoType *original); static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t); +static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve); #define mono_reflection_lock() EnterCriticalSection (&reflection_mutex) #define mono_reflection_unlock() LeaveCriticalSection (&reflection_mutex) @@ -240,6 +242,21 @@ mp_g_malloc0 (MonoMemPool *mp, guint size) return g_malloc0 (size); } +/** + * mp_string_to_utf8: + * + * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate + * memory from the C heap. + */ +static char * +mp_string_to_utf8 (MonoMemPool *mp, MonoString *s) +{ + if (mp) + return mono_string_to_utf8_mp (mp, s); + else + return mono_string_to_utf8 (s); +} + #define mp_g_new(mp,struct_type, n_structs) \ ((struct_type *) mp_g_malloc (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs)))) @@ -553,7 +570,7 @@ default_class_from_mono_type (MonoType *type) case MONO_TYPE_STRING: return mono_defaults.string_class; default: - g_warning ("implement me 0x%02x\n", type->type); + g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type); g_assert_not_reached (); } @@ -564,17 +581,21 @@ static void encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf) { int i; + MonoGenericInst *class_inst; + MonoClass *klass; - if (!gclass) { - g_assert_not_reached (); - return; - } + g_assert (gclass); + + class_inst = gclass->context.class_inst; sigbuffer_add_value (buf, MONO_TYPE_GENERICINST); - encode_type (assembly, &gclass->container_class->byval_arg, buf); - sigbuffer_add_value (buf, gclass->inst->type_argc); - for (i = 0; i < gclass->inst->type_argc; ++i) - encode_type (assembly, gclass->inst->type_argv [i], buf); + klass = gclass->container_class; + sigbuffer_add_value (buf, klass->byval_arg.type); + sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE)); + + sigbuffer_add_value (buf, class_inst->type_argc); + for (i = 0; i < class_inst->type_argc; ++i) + encode_type (assembly, class_inst->type_argv [i], buf); } @@ -621,16 +642,22 @@ encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf) case MONO_TYPE_VALUETYPE: case MONO_TYPE_CLASS: { MonoClass *k = mono_class_from_mono_type (type); - /* - * Make sure we use the correct type. - */ - sigbuffer_add_value (buf, k->byval_arg.type); - /* - * ensure only non-byref gets passed to mono_image_typedef_or_ref(), - * otherwise two typerefs could point to the same type, leading to - * verification errors. - */ - sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg)); + + if (k->generic_container) { + MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE); + encode_generic_class (assembly, gclass, buf); + } else { + /* + * Make sure we use the correct type. + */ + sigbuffer_add_value (buf, k->byval_arg.type); + /* + * ensure only non-byref gets passed to mono_image_typedef_or_ref(), + * otherwise two typerefs could point to the same type, leading to + * verification errors. + */ + sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg)); + } break; } case MONO_TYPE_ARRAY: @@ -1066,11 +1093,21 @@ static GHashTable *dynamic_custom_attrs = NULL; static MonoCustomAttrInfo* lookup_custom_attr (void *member) { - MonoCustomAttrInfo *ainfo; + MonoCustomAttrInfo *ainfo, *res; + int size; + mono_reflection_lock (); ainfo = g_hash_table_lookup (dynamic_custom_attrs, member); mono_reflection_unlock (); - return ainfo; + + if (ainfo) { + /* Need to copy since it will be freed later */ + size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY); + res = g_malloc0 (size); + memcpy (res, ainfo, size); + return res; + } + return NULL; } static gboolean @@ -1333,6 +1370,8 @@ mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb) { + memset (rmb, 0, sizeof (ReflectionMethodBuilder)); + rmb->ilgen = mb->ilgen; rmb->rtype = mb->rtype; rmb->parameters = mb->parameters; @@ -1348,6 +1387,7 @@ reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, Mono rmb->name = mb->name; rmb->table_idx = &mb->table_idx; rmb->init_locals = mb->init_locals; + rmb->skip_visibility = FALSE; rmb->return_modreq = mb->return_modreq; rmb->return_modopt = mb->return_modopt; rmb->param_modreq = mb->param_modreq; @@ -1371,6 +1411,8 @@ reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoRe { const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor"; + memset (rmb, 0, sizeof (ReflectionMethodBuilder)); + rmb->ilgen = mb->ilgen; rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg); rmb->parameters = mb->parameters; @@ -1386,6 +1428,7 @@ reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoRe rmb->name = mono_string_new (mono_domain_get (), name); rmb->table_idx = &mb->table_idx; rmb->init_locals = mb->init_locals; + rmb->skip_visibility = FALSE; rmb->return_modreq = NULL; rmb->return_modopt = NULL; rmb->param_modreq = mb->param_modreq; @@ -1399,6 +1442,8 @@ reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoRe static void reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb) { + memset (rmb, 0, sizeof (ReflectionMethodBuilder)); + rmb->ilgen = mb->ilgen; rmb->rtype = mb->rtype; rmb->parameters = mb->parameters; @@ -1410,7 +1455,7 @@ reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, Mono rmb->iattrs = 0; rmb->call_conv = mb->call_conv; rmb->code = NULL; - rmb->type = NULL; + rmb->type = (MonoObject *) mb->owner; rmb->name = mb->name; rmb->table_idx = NULL; rmb->init_locals = mb->init_locals; @@ -1536,8 +1581,12 @@ type_get_qualified_name (MonoType *type, MonoAssembly *ass) { if (!klass) return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION); ta = klass->image->assembly; - if (ta->dynamic || (ta == ass)) - return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION); + if (ta->dynamic || (ta == ass)) { + if (klass->generic_class) + return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME); + else + return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION); + } return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED); } @@ -2121,6 +2170,9 @@ create_typespec (MonoDynamicImage *assembly, MonoType *type) guint32 token; SigBuffer buf; + if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type)))) + return token; + sigbuffer_init (&buf, 32); switch (type->type) { case MONO_TYPE_FNPTR: @@ -2135,11 +2187,11 @@ create_typespec (MonoDynamicImage *assembly, MonoType *type) case MONO_TYPE_CLASS: case MONO_TYPE_VALUETYPE: { MonoClass *k = mono_class_from_mono_type (type); - if (!k || !k->generic_class) { + if (!k || !k->generic_container) { sigbuffer_free (&buf); return 0; } - encode_generic_class (assembly, k->generic_class, &buf); + encode_type (assembly, type, &buf); break; } default: @@ -2157,26 +2209,23 @@ create_typespec (MonoDynamicImage *assembly, MonoType *type) sigbuffer_free (&buf); token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS); - g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token)); + g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token)); table->next_idx ++; return token; } -/* - * Despite the name, we handle also TypeSpec (with the above helper). - */ static guint32 -mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type) +mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec) { MonoDynamicTable *table; guint32 *values; guint32 token, scope, enclosing; MonoClass *klass; - token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type)); - if (token) + /* if the type requires a typespec, we must try that first*/ + if (try_typespec && (token = create_typespec (assembly, type))) return token; - token = create_typespec (assembly, type); + token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type)); if (token) return token; klass = my_mono_class_from_mono_type (type); @@ -2195,7 +2244,7 @@ mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type) } if (klass->nested_in) { - enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg); + enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE); /* get the typeref idx of the enclosing type */ enclosing >>= MONO_TYPEDEFORREF_BITS; scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF; @@ -2217,6 +2266,15 @@ mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type) return token; } +/* + * Despite the name, we handle also TypeSpec (with the above helper). + */ +static guint32 +mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type) +{ + return mono_image_typedef_or_ref_full (assembly, type, TRUE); +} + /* * Insert a memberef row into the metadata: the token that point to the memberref * is returned. Caching is done in the caller (mono_image_get_methodref_token() or @@ -2366,11 +2424,11 @@ mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField * } static guint32 -encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod) +encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context) { SigBuffer buf; int i; - guint32 nparams = gmethod->inst->type_argc; + guint32 nparams = context->method_inst->type_argc; guint32 idx; if (!assembly->save) @@ -2384,7 +2442,7 @@ encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmetho sigbuffer_add_value (&buf, nparams); for (i = 0; i < nparams; i++) - encode_type (assembly, gmethod->inst->type_argv [i], &buf); + encode_type (assembly, context->method_inst->type_argv [i], &buf); idx = sigbuffer_add_to_blob_cached (assembly, &buf); sigbuffer_free (&buf); @@ -2423,7 +2481,7 @@ method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method) g_assert_not_reached (); } - sig = encode_generic_method_sig (assembly, mono_method_get_context (method)->gmethod); + sig = encode_generic_method_sig (assembly, mono_method_get_context (method)); if (assembly->save) { alloc_table (table, table->rows + 1); @@ -2442,7 +2500,6 @@ static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method) { MonoMethodInflated *imethod; - MonoMethod *inflated; guint32 token; token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method)); @@ -2450,16 +2507,15 @@ mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method) return token; g_assert (method->is_inflated); - inflated = mono_get_inflated_method (method); - imethod = (MonoMethodInflated *) inflated; + imethod = (MonoMethodInflated *) method; if (mono_method_signature (imethod->declaring)->generic_param_count) { - token = method_encode_methodspec (assembly, inflated); + token = method_encode_methodspec (assembly, method); } else { guint32 sig = method_encode_signature ( assembly, mono_method_signature (imethod->declaring)); token = mono_image_get_memberref_token ( - assembly, &inflated->klass->byval_arg, inflated->name, sig); + assembly, &method->klass->byval_arg, method->name, sig); } g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token)); @@ -2472,8 +2528,6 @@ mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m) MonoMethodInflated *imethod = (MonoMethodInflated *) m; guint32 sig, token; - m = mono_get_inflated_method (m); - sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring)); token = mono_image_get_memberref_token ( assembly, &m->klass->byval_arg, m->name, sig); @@ -2506,8 +2560,13 @@ create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder * g_assert (tb->generic_params); klass = mono_class_from_mono_type (tb->type.type); + if (tb->generic_container) + mono_reflection_create_generic_class (tb); + sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST); - encode_type (assembly, &klass->byval_arg, &buf); + g_assert (klass->generic_container); + sigbuffer_add_value (&buf, klass->byval_arg.type); + sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE)); count = mono_array_length (tb->generic_params); sigbuffer_add_value (&buf, count); @@ -2586,7 +2645,7 @@ mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigH if (!assembly->save) return 0; - /* FIXME: */ + /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */ g_assert (helper->type == 2); if (helper->arguments) @@ -2619,7 +2678,17 @@ mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigH sigbuffer_add_value (&buf, nargs); encode_reflection_type (assembly, helper->return_type, &buf); for (i = 0; i < nargs; ++i) { - MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i); + MonoArray *modreqs = NULL; + MonoArray *modopts = NULL; + MonoReflectionType *pt; + + if (helper->modreqs && (i < mono_array_length (helper->modreqs))) + modreqs = mono_array_get (helper->modreqs, MonoArray*, i); + if (helper->modopts && (i < mono_array_length (helper->modopts))) + modopts = mono_array_get (helper->modopts, MonoArray*, i); + + encode_custom_modifiers (assembly, modreqs, modopts, &buf); + pt = mono_array_get (helper->arguments, MonoReflectionType*, i); encode_reflection_type (assembly, pt, &buf); } idx = sigbuffer_add_to_blob_cached (assembly, &buf); @@ -3562,7 +3631,8 @@ fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *asse MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field; g_assert (f->generic_info); continue; - } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) { + } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") || + !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) { continue; } else { g_assert_not_reached (); @@ -3744,6 +3814,10 @@ load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) { token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size); mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len); + assembly->public_key = g_malloc (len); + memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len); + assembly->public_key_len = len; + /* Special case: check for ECMA key (16 bytes) */ if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) { /* In this case we must reserve 128 bytes (1024 bits) for the signature */ @@ -4113,12 +4187,19 @@ mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, Mon * Get a token to insert in the IL code stream for the given MemberInfo. * @obj can be one of: * ConstructorBuilder - * MethodBuilder + * EnumBuilder * FieldBuilder + * GenericTypeParameterBuilder + * MethodBuilder + * MonoArrayMethod * MonoCMethod * MonoMethod * MonoField + * MonoGenericClass + * MonoGenericMethod + * MonoGenericCMethod * MonoType + * SignatureHelperxo * TypeBuilder */ guint32 @@ -4130,16 +4211,18 @@ mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean c klass = obj->vtable->klass; if (strcmp (klass->name, "MethodBuilder") == 0) { MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj; + MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type; - if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly) + if (tb->module->dynamic_image == assembly && !tb->generic_params) token = mb->table_idx | MONO_TOKEN_METHOD_DEF; else token = mono_image_get_methodbuilder_token (assembly, mb); /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/ } else if (strcmp (klass->name, "ConstructorBuilder") == 0) { MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj; + MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type; - if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly) + if (tb->module->dynamic_image == assembly && !tb->generic_params) token = mb->table_idx | MONO_TOKEN_METHOD_DEF; else token = mono_image_get_ctorbuilder_token (assembly, mb); @@ -4155,8 +4238,12 @@ mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean c } else if (strcmp (klass->name, "TypeBuilder") == 0) { MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj; token = tb->table_idx | MONO_TOKEN_TYPE_DEF; - } else if (strcmp (klass->name, "MonoType") == 0 || - strcmp (klass->name, "GenericTypeParameterBuilder") == 0) { + } else if (strcmp (klass->name, "MonoType") == 0) { + MonoReflectionType *tb = (MonoReflectionType *)obj; + MonoClass *mc = mono_class_from_mono_type (tb->type); + token = mono_metadata_token_from_dor ( + mono_image_typedef_or_ref_full (assembly, tb->type, mc->generic_container == NULL)); + } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) { MonoReflectionType *tb = (MonoReflectionType *)obj; token = mono_metadata_token_from_dor ( mono_image_typedef_or_ref (assembly, tb->type)); @@ -4254,7 +4341,9 @@ create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, c #else image = g_new0 (MonoDynamicImage, 1); #endif - + + mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD); + /*g_print ("created image %p\n", image);*/ /* keep in sync with image.c */ image->image.name = assembly_name; @@ -4307,6 +4396,8 @@ create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, c image->save = assembly->save; image->pe_kind = 0x1; /* ILOnly */ image->machine = 0x14c; /* I386 */ + + mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK); return image; } @@ -4336,6 +4427,8 @@ mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb) assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1); #endif + mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD); + assembly->assembly.ref_count = 1; assembly->assembly.dynamic = TRUE; assembly->assembly.corlib_internal = assemblyb->corlib_internal; @@ -4377,6 +4470,9 @@ mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb) mono_domain_assemblies_unlock (domain); register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly); + + mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK); + mono_assembly_invoke_load_hook ((MonoAssembly*)assembly); } @@ -4999,7 +5095,7 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) { } MonoReflectionModule * -mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName) +mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName) { char *name; MonoImage *image; @@ -5007,6 +5103,7 @@ mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName) MonoDynamicAssembly *assembly; guint32 module_count; MonoImage **new_modules; + gboolean *new_modules_loaded; name = mono_string_to_utf8 (fileName); @@ -5028,14 +5125,19 @@ mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName) module_count = image->assembly->image->module_count; new_modules = g_new0 (MonoImage *, module_count + 1); + new_modules_loaded = g_new0 (gboolean, module_count + 1); if (image->assembly->image->modules) memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *)); + if (image->assembly->image->modules_loaded) + memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean)); new_modules [module_count] = image; + new_modules_loaded [module_count] = TRUE; mono_image_addref (image); g_free (image->assembly->image->modules); image->assembly->image->modules = new_modules; + image->assembly->image->modules_loaded = new_modules_loaded; image->assembly->image->module_count ++; mono_assembly_load_references (image, &status); @@ -5088,9 +5190,7 @@ reflected_hash (gconstpointer a) { mono_domain_unlock (domain); \ } while (0) -#if HAVE_BOEHM_GC -#define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry)) -#elif HAVE_SGEN_GC +#ifndef HAVE_NULL_GC #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL) #else #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry)) @@ -5312,13 +5412,16 @@ mymono_metadata_type_equal (MonoType *t1, MonoType *t2) return t1->data.array->eklass == t2->data.array->eklass; case MONO_TYPE_GENERICINST: { int i; - if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc) + MonoGenericInst *i1 = t1->data.generic_class->context.class_inst; + MonoGenericInst *i2 = t2->data.generic_class->context.class_inst; + if (i1->type_argc != i2->type_argc) return FALSE; if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg, &t2->data.generic_class->container_class->byval_arg)) return FALSE; - for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) { - if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i])) + /* FIXME: we should probably just compare the instance pointers directly. */ + for (i = 0; i < i1->type_argc; ++i) { + if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i])) return FALSE; } return TRUE; @@ -5352,7 +5455,7 @@ mymono_metadata_type_hash (MonoType *t1) return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type); case MONO_TYPE_GENERICINST: { int i; - MonoGenericInst *inst = t1->data.generic_class->inst; + MonoGenericInst *inst = t1->data.generic_class->context.class_inst; hash += g_str_hash (t1->data.generic_class->container_class->name); hash *= 13; for (i = 0; i < inst->type_argc; ++i) { @@ -5391,10 +5494,9 @@ mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst) #endif res->type.type = geninst; - if (gklass->wastypebuilder && gklass->reflection_info) - MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info); - else - MONO_OBJECT_SETREF (res, generic_type, mono_type_get_object (domain, &gklass->byval_arg)); + g_assert (gklass->reflection_info); + g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder")); + MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info); return res; } @@ -5449,7 +5551,8 @@ mono_type_get_object (MonoDomain *domain, MonoType *type) mono_domain_unlock (domain); return res; } - if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) { + /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */ + if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) { res = (MonoReflectionType *)mono_generic_class_get_object (domain, type); mono_g_hash_table_insert (domain->type_hash, type, res); mono_domain_unlock (domain); @@ -5506,7 +5609,6 @@ mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refcl if (method->is_inflated) { MonoReflectionGenericMethod *gret; - method = mono_get_inflated_method (method); refclass = method->klass; CHECK_OBJECT (MonoReflectionMethod *, method, refclass); if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) { @@ -5541,7 +5643,6 @@ mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refcl } ret = (MonoReflectionMethod*)mono_object_new (domain, klass); ret->method = method; - MONO_OBJECT_SETREF (ret, name, mono_string_new (domain, method->name)); MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg)); CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass); } @@ -5559,11 +5660,12 @@ MonoReflectionField* mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field) { MonoReflectionField *res; - MonoClass *oklass; + static MonoClass *monofield_klass; CHECK_OBJECT (MonoReflectionField *, field, klass); - oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField"); - res = (MonoReflectionField *)mono_object_new (domain, oklass); + if (!monofield_klass) + monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField"); + res = (MonoReflectionField *)mono_object_new (domain, monofield_klass); res->klass = klass; res->field = field; MONO_OBJECT_SETREF (res, name, mono_string_new (domain, field->name)); @@ -5588,11 +5690,12 @@ MonoReflectionProperty* mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property) { MonoReflectionProperty *res; - MonoClass *oklass; + static MonoClass *monoproperty_klass; CHECK_OBJECT (MonoReflectionProperty *, property, klass); - oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty"); - res = (MonoReflectionProperty *)mono_object_new (domain, oklass); + if (!monoproperty_klass) + monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty"); + res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass); res->klass = klass; res->property = property; CACHE_OBJECT (MonoReflectionProperty *, property, res, klass); @@ -5611,16 +5714,61 @@ MonoReflectionEvent* mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event) { MonoReflectionEvent *res; - MonoClass *oklass; + static MonoClass *monoevent_klass; CHECK_OBJECT (MonoReflectionEvent *, event, klass); - oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent"); - res = (MonoReflectionEvent *)mono_object_new (domain, oklass); + if (!monoevent_klass) + monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent"); + res = (MonoReflectionEvent *)mono_object_new (domain, monoevent_klass); res->klass = klass; res->event = event; CACHE_OBJECT (MonoReflectionEvent *, event, res, klass); } +/** + * mono_get_reflection_missing_object: + * @domain: Domain where the object lives + * + * Returns the System.Reflection.Missing.Value singleton object + * (of type System.Reflection.Missing). + * + * Used as the value for ParameterInfo.DefaultValue when Optional + * is present + */ +static MonoObject * +mono_get_reflection_missing_object (MonoDomain *domain) +{ + MonoObject *obj; + static MonoClassField *missing_value_field = NULL; + + if (!missing_value_field) { + MonoClass *missing_klass; + missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing"); + mono_class_init (missing_klass); + missing_value_field = mono_class_get_field_from_name (missing_klass, "Value"); + g_assert (missing_value_field); + } + obj = mono_field_get_value_object (domain, missing_value_field, NULL); + g_assert (obj); + return obj; +} + +static MonoObject* +get_dbnull (MonoDomain *domain, MonoObject **dbnull) +{ + if (!*dbnull) + *dbnull = mono_get_dbnull_object (domain); + return *dbnull; +} + +static MonoObject* +get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing) +{ + if (!*reflection_missing) + *reflection_missing = mono_get_reflection_missing_object (domain); + return *reflection_missing; +} + /* * mono_param_get_objects: * @domain: an app domain @@ -5639,7 +5787,8 @@ mono_param_get_objects (MonoDomain *domain, MonoMethod *method) char **names, **blobs = NULL; guint32 *types = NULL; MonoType *type = NULL; - MonoObject *dbnull = mono_get_dbnull_object (domain); + MonoObject *dbnull = NULL; + MonoObject *missing = NULL; MonoMarshalSpec **mspecs; MonoMethodSignature *sig; int i; @@ -5674,7 +5823,10 @@ mono_param_get_objects (MonoDomain *domain, MonoMethod *method) param->AttrsImpl = sig->params [i]->attrs; if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) { - MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull); + if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL) + MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing)); + else + MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull)); } else { if (!blobs) { @@ -5701,8 +5853,12 @@ mono_param_get_objects (MonoDomain *domain, MonoMethod *method) MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i])); /* Type in the Constant table is MONO_TYPE_CLASS for nulls */ - if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) - MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull); + if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) { + if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL) + MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing)); + else + MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull)); + } } @@ -5823,17 +5979,25 @@ mono_method_body_get_object (MonoDomain *domain, MonoMethod *method) return ret; } +/** + * mono_get_dbnull_object: + * @domain: Domain where the object lives + * + * Returns the System.DBNull.Value singleton object + * + * Used as the value for ParameterInfo.DefaultValue + */ MonoObject * mono_get_dbnull_object (MonoDomain *domain) { MonoObject *obj; - MonoClass *klass; static MonoClassField *dbnull_value_field = NULL; if (!dbnull_value_field) { - klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull"); - mono_class_init (klass); - dbnull_value_field = mono_class_get_field_from_name (klass, "Value"); + MonoClass *dbnull_klass; + dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull"); + mono_class_init (dbnull_klass); + dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value"); g_assert (dbnull_value_field); } obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); @@ -5841,7 +6005,6 @@ mono_get_dbnull_object (MonoDomain *domain) return obj; } - static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types) { @@ -6043,6 +6206,7 @@ _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed, start = p = w = name; + //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse)) memset (&info->assembly, 0, sizeof (MonoAssemblyName)); info->name = info->name_space = NULL; info->nested = NULL; @@ -6243,6 +6407,7 @@ _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, { gboolean type_resolve = FALSE; MonoType *type; + MonoImage *rootimage = image; if (info->assembly.name) { MonoAssembly *assembly = mono_assembly_loaded (&info->assembly); @@ -6257,17 +6422,17 @@ _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, image = mono_defaults.corlib; } - type = mono_reflection_get_type (image, info, ignorecase, &type_resolve); + type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve); if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) { image = mono_defaults.corlib; - type = mono_reflection_get_type (image, info, ignorecase, &type_resolve); + type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve); } return type; } static MonoType* -mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase) +mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase) { MonoClass *klass; GList *mod; @@ -6316,7 +6481,7 @@ mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gb for (i = 0; i < info->type_arguments->len; i++) { MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i); - type_args [i] = _mono_reflection_get_type_from_info (subinfo, image, ignorecase); + type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase); if (!type_args [i]) { g_free (type_args); return NULL; @@ -6328,10 +6493,9 @@ mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gb instance = mono_reflection_bind_generic_parameters ( the_type, info->type_arguments->len, type_args); - if (!instance) { - g_free (type_args); + g_free (type_args); + if (!instance) return NULL; - } klass = mono_class_from_mono_type (instance); } @@ -6363,14 +6527,55 @@ mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gb */ MonoType* -mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) +mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) { + return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve); +} + +static MonoType* +mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase) +{ + MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly); + MonoType *type; + int i; + + g_assert (assembly->dynamic); + + /* Enumerate all modules */ + + type = NULL; + if (abuilder->modules) { + for (i = 0; i < mono_array_length (abuilder->modules); ++i) { + MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i); + type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase); + if (type) + break; + } + } + + if (!type && abuilder->loaded_modules) { + for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) { + MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i); + type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase); + if (type) + break; + } + } + + return type; +} + +MonoType* +mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) { MonoType *type; MonoReflectionAssembly *assembly; GString *fullName; GList *mod; - type = mono_reflection_get_type_internal (image, info, ignorecase); + if (image && image->dynamic) + type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase); + else + type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase); if (type) return type; if (!mono_domain_has_type_resolve (mono_domain_get ())) @@ -6394,40 +6599,18 @@ mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ig assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL); if (assembly) { - if (assembly->assembly->dynamic) { - /* Enumerate all modules */ - MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly; - int i; - - type = NULL; - if (abuilder->modules) { - for (i = 0; i < mono_array_length (abuilder->modules); ++i) { - MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i); - type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase); - if (type) - break; - } - } - - if (!type && abuilder->loaded_modules) { - for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) { - MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i); - type = mono_reflection_get_type_internal (mod->image, info, ignorecase); - if (type) - break; - } - } - } + if (assembly->assembly->dynamic) + type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase); else - type = mono_reflection_get_type_internal (assembly->assembly->image, + type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, info, ignorecase); } g_string_free (fullName, TRUE); return type; } -static void -free_type_info (MonoTypeNameParse *info) +void +mono_reflection_free_type_info (MonoTypeNameParse *info) { g_list_free (info->modifiers); g_list_free (info->nested); @@ -6438,7 +6621,9 @@ free_type_info (MonoTypeNameParse *info) for (i = 0; i < info->type_arguments->len; i++) { MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i); - free_type_info (subinfo); + mono_reflection_free_type_info (subinfo); + /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/ + g_free (subinfo); } g_ptr_array_free (info->type_arguments, TRUE); @@ -6471,7 +6656,7 @@ mono_reflection_type_from_name (char *name, MonoImage *image) } g_free (tmp); - free_type_info (&info); + mono_reflection_free_type_info (&info); return type; } @@ -6499,7 +6684,9 @@ mono_reflection_get_token (MonoObject *obj) token = mb->table_idx | MONO_TOKEN_METHOD_DEF; } else if (strcmp (klass->name, "FieldBuilder") == 0) { MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj; - token = fb->table_idx | MONO_TOKEN_FIELD_DEF; + + /* Call mono_image_create_token so the object gets added to the tokens hash table */ + token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE); } else if (strcmp (klass->name, "TypeBuilder") == 0) { MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj; token = tb->table_idx | MONO_TOKEN_TYPE_DEF; @@ -6658,6 +6845,9 @@ handle_type: int etype = *p; p ++; + if (etype == 0x51) + /* See Partition II, Appendix B3 */ + etype = MONO_TYPE_OBJECT; type = MONO_TYPE_SZARRAY; simple_type.type = etype; tklass = mono_class_from_mono_type (&simple_type); @@ -6975,7 +7165,6 @@ create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *dat { MonoArray *typedargs, *namedargs; MonoClass *attrklass; - static MonoClass *klass; static MonoMethod *ctor; MonoDomain *domain; MonoObject *attr; @@ -6985,16 +7174,14 @@ create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *dat void *params [3]; mono_class_init (method->klass); - - if (!klass) - klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData"); + if (!ctor) - ctor = mono_class_get_method_from_name (klass, ".ctor", 3); - + ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3); + domain = mono_domain_get (); if (len == 0) { /* This is for Attributes with no parameters */ - attr = mono_object_new (domain, klass); + attr = mono_object_new (domain, mono_defaults.customattribute_data_class); params [0] = mono_method_get_object (domain, method, NULL); params [1] = params [2] = NULL; mono_runtime_invoke (method, attr, params, NULL); @@ -7081,7 +7268,7 @@ create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *dat } g_free (name); } - attr = mono_object_new (domain, klass); + attr = mono_object_new (domain, mono_defaults.customattribute_data_class); params [0] = mono_method_get_object (domain, method, NULL); params [1] = typedargs; params [2] = namedargs; @@ -7093,12 +7280,10 @@ MonoArray* mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo) { MonoArray *result; - MonoClass *klass; MonoObject *attr; int i; - klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute"); - result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs); + result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs); for (i = 0; i < cinfo->num_attrs; ++i) { attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size); mono_array_setref (result, i, attr); @@ -7111,7 +7296,6 @@ mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_ { MonoArray *result; MonoObject *attr; - MonoClass *klass; int i, n; n = 0; @@ -7120,8 +7304,7 @@ mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_ n ++; } - klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute"); - result = mono_array_new (mono_domain_get (), klass, n); + result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, n); n = 0; for (i = 0; i < cinfo->num_attrs; ++i) { if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) { @@ -7137,14 +7320,10 @@ static MonoArray* mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo) { MonoArray *result; - static MonoClass *klass; MonoObject *attr; int i; - - if (!klass) - klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData"); - result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs); + result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs); for (i = 0; i < cinfo->num_attrs; ++i) { attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size); mono_array_setref (result, i, attr); @@ -7152,6 +7331,11 @@ mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo) return result; } +/** + * mono_custom_attrs_from_index: + * + * Returns: NULL if no attributes are found or if a loading error occurs. + */ MonoCustomAttrInfo* mono_custom_attrs_from_index (MonoImage *image, guint32 idx) { @@ -7195,8 +7379,12 @@ mono_custom_attrs_from_index (MonoImage *image, guint32 idx) break; } ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL); - if (!ainfo->attrs [i].ctor) - g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken); + if (!ainfo->attrs [i].ctor) { + g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken); + g_list_free (list); + g_free (ainfo); + return NULL; + } data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]); ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data); ainfo->attrs [i].data = (guchar*)data; @@ -7211,6 +7399,15 @@ mono_custom_attrs_from_method (MonoMethod *method) { MonoCustomAttrInfo *cinfo; guint32 idx; + + /* + * An instantiated method has the same cattrs as the generic method definition. + * + * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders + * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization + */ + if (method->is_inflated) + method = ((MonoMethodInflated *) method)->declaring; if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (method))) return cinfo; @@ -7225,6 +7422,9 @@ mono_custom_attrs_from_class (MonoClass *klass) { MonoCustomAttrInfo *cinfo; guint32 idx; + + if (klass->generic_class) + klass = klass->generic_class->container_class; if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (klass))) return cinfo; @@ -7313,11 +7513,29 @@ mono_custom_attrs_from_param (MonoMethod *method, guint32 param) MonoImage *image; MonoReflectionMethodAux *aux; + /* + * An instantiated method has the same cattrs as the generic method definition. + * + * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders + * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization + */ + if (method->is_inflated) + method = ((MonoMethodInflated *) method)->declaring; + if (method->klass->image->dynamic) { + MonoCustomAttrInfo *res, *ainfo; + int size; + aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method); if (!aux || !aux->param_cattr) return NULL; - return aux->param_cattr [param]; + + /* Need to copy since it will be freed later */ + ainfo = aux->param_cattr [param]; + size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY); + res = g_malloc0 (size); + memcpy (res, ainfo, size); + return res; } image = method->klass->image; @@ -7423,8 +7641,8 @@ mono_reflection_get_custom_attrs_info (MonoObject *obj) MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj; cinfo = mono_custom_attrs_from_method (rmethod->method); } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) { - MonoMethod *method = mono_get_inflated_method (((MonoReflectionMethod*)obj)->method); - cinfo = mono_custom_attrs_from_method (method); + MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj; + cinfo = mono_custom_attrs_from_method (rmethod->method); } else if (strcmp ("ParameterInfo", klass->name) == 0) { MonoReflectionParameter *param = (MonoReflectionParameter*)obj; MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl; @@ -7447,6 +7665,9 @@ mono_reflection_get_custom_attrs_info (MonoObject *obj) } else if (strcmp ("FieldBuilder", klass->name) == 0) { MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj; cinfo = mono_custom_attrs_from_builders (&((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs); + } else if (strcmp ("MonoGenericClass", klass->name) == 0) { + MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj; + cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type); } else { /* handle other types here... */ g_error ("get custom attrs not yet supported for %s", klass->name); } @@ -7460,7 +7681,8 @@ mono_reflection_get_custom_attrs_info (MonoObject *obj) * * Return an array with all the custom attributes defined of the * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes - * of that type are returned. The objects are fully build. + * of that type are returned. The objects are fully build. Return NULL if a loading error + * occurs. */ MonoArray* mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass) @@ -7477,9 +7699,9 @@ mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass if (!cinfo->cached) mono_custom_attrs_free (cinfo); } else { - MonoClass *klass; - klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute"); - result = mono_array_new (mono_domain_get (), klass, 0); + if (mono_loader_get_last_error ()) + return NULL; + result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, 0); } return result; @@ -7490,7 +7712,8 @@ mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass * @obj: a reflection object handle * * Return an array with all the custom attributes defined of the - * reflection handle @obj. The objects are fully build. + * reflection handle @obj. The objects are fully build. Return NULL if a loading error + * occurs. */ MonoArray* mono_reflection_get_custom_attrs (MonoObject *obj) @@ -7517,11 +7740,8 @@ mono_reflection_get_custom_attrs_data (MonoObject *obj) result = mono_custom_attrs_data_construct (cinfo); if (!cinfo->cached) mono_custom_attrs_free (cinfo); - } else { - MonoClass *klass; - klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData"); - result = mono_array_new (mono_domain_get (), klass, 0); - } + } else + result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0); return result; } @@ -7851,7 +8071,11 @@ handle_type: goto handle_enum; } else if (klass->rank == 1) { *p++ = 0x1D; - *p++ = klass->element_class->byval_arg.type; + if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT) + /* See Partition II, Appendix B3 */ + *p++ = 0x51; + else + *p++ = klass->element_class->byval_arg.type; encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL); break; } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) { @@ -8103,6 +8327,8 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb) klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace); klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx; klass->flags = tb->attrs; + + mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD); klass->element_class = klass; @@ -8150,6 +8376,8 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb) /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/ + mono_profiler_class_loaded (klass, MONO_PROFILE_OK); + mono_loader_unlock (); } @@ -8236,6 +8464,11 @@ mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb) fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0); + if (!mono_type_is_valid_enum_basetype (fb->type->type)) { + mono_loader_unlock (); + return; + } + klass->enum_basetype = fb->type->type; klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype); if (!klass->element_class) @@ -8362,8 +8595,6 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass, gboolean dynamic; int i; - g_assert (!klass->generic_class); - /* * Methods created using a MethodBuilder should have their memory allocated * inside the image mempool, while dynamic methods should have their memory @@ -8372,6 +8603,9 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass, dynamic = rmb->refs != NULL; mp = dynamic ? NULL : klass->image->mempool; + if (!dynamic) + g_assert (!klass->generic_class); + mono_loader_lock (); if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) || @@ -8384,10 +8618,11 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass, pm = (MonoMethodNormal*)m; + m->dynamic = dynamic; m->slot = -1; m->flags = rmb->attrs; m->iflags = rmb->iattrs; - m->name = dynamic ? mono_string_to_utf8 (rmb->name) : mono_string_to_utf8_mp (mp, rmb->name); + m->name = mp_string_to_utf8 (mp, rmb->name); m->klass = klass; m->signature = sig; m->skip_visibility = rmb->skip_visibility; @@ -8491,7 +8726,7 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass, container->parent = klass->generic_container; container->context.class_inst = klass->generic_container->context.class_inst; } - container->context.gmethod = mono_get_shared_generic_method (container); + container->context.method_inst = mono_get_shared_generic_inst (container); } if (rmb->refs) { @@ -8520,7 +8755,7 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass, if ((i > 0) && (pb->attrs)) { /* Make a copy since it might point to a shared type structure */ /* FIXME: Alloc this from a mempool */ - m->signature->params [i - 1] = g_memdup (m->signature->params [i - 1], sizeof (MonoType) + ((m->signature->params [i - 1]->num_mods - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod))); + m->signature->params [i - 1] = mono_metadata_type_dup (NULL, m->signature->params [i - 1]); m->signature->params [i - 1]->attrs = pb->attrs; } @@ -8546,7 +8781,7 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass, } if (pb->name) - method_aux->param_names [i] = dynamic ? mono_string_to_utf8 (pb->name) : mono_string_to_utf8_mp (mp, pb->name); + method_aux->param_names [i] = mp_string_to_utf8 (mp, pb->name); if (pb->cattrs) { if (!method_aux->param_cattr) method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1); @@ -8599,7 +8834,8 @@ ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb) mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig); mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs); - if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) { + /* If we are in a generic class, we might be called multiple times from inflate_method */ + if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) { /* ilgen is no longer needed */ mb->ilgen = NULL; } @@ -8622,7 +8858,8 @@ methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb) mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig); mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs); - if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) { + /* If we are in a generic class, we might be called multiple times from inflate_method */ + if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) { /* ilgen is no longer needed */ mb->ilgen = NULL; } @@ -8673,11 +8910,9 @@ mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc { MonoClass *klass; MonoReflectionTypeBuilder *tb = NULL; - MonoGenericClass *gclass, *cached; gboolean is_dynamic = FALSE; MonoDomain *domain; MonoClass *geninst; - int i; mono_loader_lock (); @@ -8689,11 +8924,8 @@ mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc is_dynamic = TRUE; } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) { MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type; - MonoReflectionType *rgt = rgi->generic_type; - - g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder")); - tb = (MonoReflectionTypeBuilder *) rgt; + tb = rgi->generic_type; is_dynamic = TRUE; } @@ -8713,157 +8945,37 @@ mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc is_dynamic = TRUE; } - if (is_dynamic) { - MonoDynamicGenericClass *dgclass = g_new0 (MonoDynamicGenericClass, 1); - gclass = &dgclass->generic_class; - gclass->is_dynamic = TRUE; - } else { - gclass = g_new0 (MonoGenericClass, 1); - } - - gclass->inst = g_new0 (MonoGenericInst, 1); - - gclass->inst->type_argc = type_argc; - gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc); - gclass->inst->is_reference = 1; - - for (i = 0; i < gclass->inst->type_argc; ++i) { - MonoType *t = dup_type (types [i]); - - if (!gclass->inst->is_open) - gclass->inst->is_open = mono_class_is_open_constructed_type (t); - if (gclass->inst->is_reference) - gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t); - gclass->inst->type_argv [i] = t; - } - - gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst); - - gclass->container_class = klass; - - cached = mono_metadata_lookup_generic_class (gclass); - if (cached) { - g_free (gclass); - gclass = cached; - } - mono_loader_unlock (); - geninst = mono_generic_class_get_class (gclass); + geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic); return &geninst->byval_arg; } -MonoType* -mono_class_bind_generic_parameters (MonoType *type, int type_argc, MonoType **types) +MonoClass* +mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic) { - MonoClass *klass; - MonoGenericClass *gclass, *cached; - MonoType *geninst; - int i; - - klass = mono_class_from_mono_type (type); - if (!klass->generic_container && !klass->generic_class && - !(klass->nested_in && klass->nested_in->generic_container)) - return NULL; - - mono_loader_lock (); - - gclass = g_new0 (MonoGenericClass, 1); - - gclass->inst = g_new0 (MonoGenericInst, 1); - gclass->inst->type_argc = type_argc; - gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc); - gclass->inst->is_reference = 1; - - for (i = 0; i < gclass->inst->type_argc; ++i) { - MonoType *t = dup_type (types [i]); - - if (!gclass->inst->is_open) - gclass->inst->is_open = mono_class_is_open_constructed_type (t); - if (gclass->inst->is_reference) - gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t); - - gclass->inst->type_argv [i] = t; - } - - gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst); - - gclass->container_class = klass; - - if (klass->generic_class) { - MonoGenericClass *kgclass = klass->generic_class; - MonoGenericClass *ogclass = gclass; - - gclass = g_new0 (MonoGenericClass, 1); - - gclass->inst = g_new0 (MonoGenericInst, 1); - gclass->inst->type_argc = kgclass->inst->type_argc; - gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc); - gclass->inst->is_reference = 1; - - for (i = 0; i < gclass->inst->type_argc; i++) { - MonoType *t = kgclass->inst->type_argv [i]; - - t = mono_class_inflate_generic_type (t, mono_generic_class_get_context (ogclass)); - - if (!gclass->inst->is_open) - gclass->inst->is_open = mono_class_is_open_constructed_type (t); - if (gclass->inst->is_reference) - gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t); - - gclass->inst->type_argv [i] = t; - } - - gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst); - - gclass->container_class = kgclass->container_class; - } - - geninst = g_new0 (MonoType, 1); - geninst->type = MONO_TYPE_GENERICINST; - - cached = mono_metadata_lookup_generic_class (gclass); - if (cached) { - g_free (gclass); - mono_loader_unlock (); - geninst->data.generic_class = cached; - return geninst; - } + MonoGenericClass *gclass; + MonoGenericInst *inst; - geninst->data.generic_class = gclass; + g_assert (klass->generic_container); - mono_loader_unlock (); + inst = mono_metadata_get_generic_inst (type_argc, types); + gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic); - return geninst; -} - -static inline MonoType* -dup_type (const MonoType *original) -{ - MonoType *r = g_new0 (MonoType, 1); - *r = *original; - r->attrs = original->attrs; - r->byref = original->byref; - if (original->type == MONO_TYPE_PTR) - r->data.type = dup_type (original->data.type); - else if (original->type == MONO_TYPE_ARRAY) - r->data.array = mono_dup_array_type (original->data.array); - else if (original->type == MONO_TYPE_FNPTR) - r->data.method = mono_metadata_signature_deep_dup (original->data.method); - mono_stats.generics_metadata_size += sizeof (MonoType); - return r; + return mono_generic_class_get_class (gclass); } MonoReflectionMethod* mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types) { + MonoClass *klass; MonoMethod *method, *inflated; + MonoMethodInflated *imethod; MonoReflectionMethodBuilder *mb = NULL; - MonoGenericContainer *container; - MonoGenericMethod *gmethod; - MonoGenericContext *context; + MonoGenericContext tmp_context; MonoGenericInst *ginst; + MonoType **type_argv; int count, i; MONO_ARCH_SAVE_REGS; @@ -8880,60 +8992,31 @@ mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, M method = rmethod->method; } - method = mono_get_inflated_method (method); + klass = method->klass; + + if (method->is_inflated) + method = ((MonoMethodInflated *) method)->declaring; count = mono_method_signature (method)->generic_param_count; if (count != mono_array_length (types)) return NULL; - container = method->generic_container; - g_assert (container); - - if (!container->method_hash) - container->method_hash = g_hash_table_new ( - (GHashFunc) mono_metadata_generic_method_hash, - (GCompareFunc) mono_metadata_generic_method_equal); - - ginst = g_new0 (MonoGenericInst,1 ); - ginst->type_argc = count; - ginst->type_argv = g_new0 (MonoType *, count); - ginst->is_reference = 1; + type_argv = g_new0 (MonoType *, count); for (i = 0; i < count; i++) { MonoReflectionType *garg = mono_array_get (types, gpointer, i); - ginst->type_argv [i] = dup_type (garg->type); - - if (!ginst->is_open) - ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]); - if (ginst->is_reference) - ginst->is_reference = MONO_TYPE_IS_REFERENCE (ginst->type_argv [i]); + type_argv [i] = garg->type; } - ginst = mono_metadata_lookup_generic_inst (ginst); + ginst = mono_metadata_get_generic_inst (count, type_argv); + g_free (type_argv); - gmethod = g_new0 (MonoGenericMethod, 1); - if (method->klass->generic_class) - gmethod->class_inst = method->klass->generic_class->inst; - gmethod->container = container; - gmethod->inst = ginst; + tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL; + tmp_context.method_inst = ginst; - inflated = g_hash_table_lookup (container->method_hash, gmethod); - if (inflated) { - g_free (gmethod); - - return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL); - } - - MOVING_GC_REGISTER (&gmethod->reflection_info); - gmethod->reflection_info = rmethod; - - context = g_new0 (MonoGenericContext, 1); - context->class_inst = gmethod->class_inst; - context->gmethod = gmethod; - - if (method->is_inflated) - method = ((MonoMethodInflated *) method)->declaring; + inflated = mono_class_inflate_generic_method (method, &tmp_context); + imethod = (MonoMethodInflated *) inflated; - inflated = mono_class_inflate_generic_method (method, context); - g_hash_table_insert (container->method_hash, gmethod, inflated); + MOVING_GC_REGISTER (&imethod->reflection_info); + imethod->reflection_info = rmethod; return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL); } @@ -8941,7 +9024,7 @@ mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, M static MonoMethod * inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj) { - MonoGenericMethod *gmethod = NULL; + MonoMethodInflated *imethod; MonoGenericContext *context; MonoClass *klass; @@ -8949,22 +9032,12 @@ inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoO g_assert (klass->generic_class); context = mono_class_get_context (klass); + imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context); if (method->generic_container) { - g_assert (method->klass == klass->generic_class->container_class); - - gmethod = g_new0 (MonoGenericMethod, 1); - gmethod->class_inst = klass->generic_class->inst; - gmethod->container = method->generic_container; - MOVING_GC_REGISTER (&gmethod->reflection_info); - gmethod->reflection_info = obj; - gmethod->inst = method->generic_container->context.gmethod->inst; - - context = g_new0 (MonoGenericContext, 1); - context->class_inst = klass->generic_class->inst; - context->gmethod = gmethod; + MOVING_GC_REGISTER (&imethod->reflection_info); + imethod->reflection_info = obj; } - - return mono_class_inflate_generic_method_full (method, klass, context); + return (MonoMethod *) imethod; } static MonoMethod * @@ -8973,7 +9046,7 @@ inflate_method (MonoReflectionGenericClass *type, MonoObject *obj) MonoMethod *method; MonoClass *gklass; - gklass = mono_class_from_mono_type (type->generic_type->type); + gklass = mono_class_from_mono_type (type->generic_type->type.type); if (!strcmp (obj->vtable->klass->name, "MethodBuilder")) method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj); @@ -9002,6 +9075,7 @@ mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, Mono MONO_ARCH_SAVE_REGS; klass = mono_class_from_mono_type (type->type.type); + g_assert (type->type.type->type == MONO_TYPE_GENERICINST); gclass = type->type.type->data.generic_class; g_assert (gclass->is_dynamic); @@ -9364,6 +9438,20 @@ typebuilder_setup_events (MonoClass *klass) } } +static gboolean +remove_instantiations_of (gpointer key, + gpointer value, + gpointer user_data) +{ + MonoType *type = (MonoType*)key; + MonoClass *klass = (MonoClass*)user_data; + + if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) + return TRUE; + else + return FALSE; +} + MonoReflectionType* mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb) { @@ -9443,11 +9531,25 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb) typebuilder_setup_properties (klass); typebuilder_setup_events (klass); - + klass->wastypebuilder = TRUE; + + /* + * If we are a generic TypeBuilder, there might be instantiations in the type cache + * which have type System.Reflection.MonoGenericClass, but after the type is created, + * we want to return normal System.MonoType objects, so clear these out from the cache. + */ + if (domain->type_hash && klass->generic_container) + mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass); + mono_loader_unlock (); mono_domain_unlock (domain); + if (klass->enumtype && !mono_class_is_valid_enum (klass)) { + mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL); + mono_raise_exception (mono_get_exception_type_load (tb->name, NULL)); + } + res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg); g_assert (res != (MonoReflectionType*)tb); @@ -9465,8 +9567,10 @@ mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam param = g_new0 (MonoGenericParam, 1); if (gparam->mbuilder) { - if (!gparam->mbuilder->generic_container) + if (!gparam->mbuilder->generic_container) { gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1); + gparam->mbuilder->generic_container->is_method = TRUE; + } param->owner = gparam->mbuilder->generic_container; } else if (gparam->tbuilder) { g_assert (gparam->tbuilder->generic_container); @@ -9544,6 +9648,7 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb) { ReflectionMethodBuilder rmb; MonoMethodSignature *sig; + MonoClass *klass; GSList *l; int i; @@ -9584,7 +9689,7 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb) } handle_class = mono_defaults.methodhandle_class; } else { - ref = resolve_object (mb->module->image, obj, &handle_class); + ref = resolve_object (mb->module->image, obj, &handle_class, NULL); if (!ref) { g_free (rmb.refs); mono_raise_exception (mono_get_exception_type_load (NULL, NULL)); @@ -9596,8 +9701,9 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb) rmb.refs [i + 1] = handle_class; } - /* FIXME: class */ - mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig); + klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class; + + mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig); /* Fix up refs entries pointing at us */ for (l = mb->referenced_by; l; l = l->next) { @@ -9621,27 +9727,46 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb) mb->ilgen = NULL; } +void +mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb) +{ + g_assert (mb); + + if (mb->mhandle) + mono_runtime_free_method ( + mono_object_get_domain ((MonoObject*)mb), mb->mhandle); +} + /** * mono_reflection_lookup_dynamic_token: * * Finish the Builder object pointed to by TOKEN and return the corresponding - * runtime structure. HANDLE_CLASS is set to the class required by - * mono_ldtoken. + * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by + * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object + * mapping table. */ gpointer -mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, MonoClass **handle_class) +mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context) { MonoDynamicImage *assembly = (MonoDynamicImage*)image; MonoObject *obj; + MonoClass *klass; obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token)); - g_assert (obj); + if (!obj) { + if (valid_token) + g_assert_not_reached (); + else + return NULL; + } - return resolve_object (image, obj, handle_class); + if (!handle_class) + handle_class = &klass; + return resolve_object (image, obj, handle_class, context); } static gpointer -resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class) +resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context) { gpointer result = NULL; @@ -9651,7 +9776,13 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class) g_assert (result); } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) { MonoReflectionType *tb = (MonoReflectionType*)obj; - result = mono_class_from_mono_type (tb->type); + if (context) { + MonoType *inflated = mono_class_inflate_generic_type (tb->type, context); + result = mono_class_from_mono_type (inflated); + mono_metadata_free_type (inflated); + } else { + result = mono_class_from_mono_type (tb->type); + } *handle_class = mono_defaults.typehandle_class; g_assert (result); } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 || @@ -9659,6 +9790,7 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class) strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 || strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) { result = ((MonoReflectionMethod*)obj)->method; + result = mono_class_inflate_generic_method (result, context); *handle_class = mono_defaults.methodhandle_class; g_assert (result); } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) { @@ -9680,6 +9812,7 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class) */ result = mb->mhandle; } + result = mono_class_inflate_generic_method (result, context); *handle_class = mono_defaults.methodhandle_class; } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) { MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj; @@ -9691,6 +9824,7 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class) mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb); result = cb->mhandle; } + result = mono_class_inflate_generic_method (result, context); *handle_class = mono_defaults.methodhandle_class; } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) { result = ((MonoReflectionField*)obj)->field; @@ -9706,6 +9840,14 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class) mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb); result = fb->handle; } + + if (fb->handle && fb->handle->parent->generic_container) { + MonoClass *klass = fb->handle->parent; + MonoClass *inflated = mono_class_from_mono_type (mono_class_inflate_generic_type (&klass->byval_arg, context)); + + result = mono_class_get_field_from_name (inflated, fb->handle->name); + g_assert (result); + } *handle_class = mono_defaults.fieldhandle_class; } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) { MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj; @@ -9760,6 +9902,16 @@ resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class) g_assert (method->mhandle); result = method->mhandle; *handle_class = mono_defaults.methodhandle_class; + } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) { + MonoReflectionType *tb = (MonoReflectionType*)obj; + result = mono_class_from_mono_type (mono_class_inflate_generic_type (tb->type, context)); + *handle_class = mono_defaults.typehandle_class; + g_assert (result); + } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) { + MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj; + result = mono_class_from_mono_type (mono_class_inflate_generic_type (ref->type.type, context)); + *handle_class = mono_defaults.typehandle_class; + g_assert (result); } else { g_print (obj->vtable->klass->name); g_assert_not_reached (); @@ -9799,12 +9951,17 @@ const static guint32 declsec_flags_map[] = { static guint32 mono_declsec_get_flags (MonoImage *image, guint32 token) { - guint32 index = mono_metadata_declsec_from_index (image, token); + int index = mono_metadata_declsec_from_index (image, token); MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY]; guint32 result = 0; guint32 action; int i; + /* HasSecurity can be present for other, not specially encoded, attributes, + e.g. SuppressUnmanagedCodeSecurityAttribute */ + if (index < 0) + return 0; + for (i = index; i < t->rows; i++) { guint32 cols [MONO_DECL_SECURITY_SIZE];