X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Freflection.c;h=14b0ab443b6d52f6f0bf0ebfe187f34ac11e9652;hb=42a1173c3ffab9bbd5730ee8e7fcd7cdebafc28d;hp=0a381acb081da5fdfa1f5636a0e405b0f541f8bb;hpb=cf860d1ca5bdf991a58b01e59d59f511c70b102c;p=mono.git diff --git a/mono/metadata/reflection.c b/mono/metadata/reflection.c index 0a381acb081..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,7 +145,7 @@ 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); @@ -580,13 +582,17 @@ encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigB { int i; MonoGenericInst *class_inst; + MonoClass *klass; 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); + 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); @@ -636,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: @@ -1358,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; @@ -1373,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; @@ -1396,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; @@ -1411,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; @@ -1424,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; @@ -1435,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; @@ -1561,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); } @@ -2146,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: @@ -2160,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: @@ -2182,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); @@ -2220,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; @@ -2242,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 @@ -2428,7 +2461,6 @@ method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method) table = &assembly->tables [MONO_TABLE_METHODSPEC]; g_assert (method->is_inflated); - g_assert (!method->klass->generic_container); imethod = (MonoMethodInflated *) method; declaring = imethod->declaring; @@ -2528,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); @@ -2608,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) @@ -2641,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); @@ -3584,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 (); @@ -3766,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 */ @@ -4135,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 @@ -4152,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); @@ -4177,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)); @@ -4276,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; @@ -4329,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; } @@ -4358,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; @@ -4399,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); } @@ -5116,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)) @@ -5422,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; } @@ -5480,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); @@ -5571,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); } @@ -5654,6 +5725,50 @@ mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *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 @@ -5672,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; @@ -5707,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) { @@ -5734,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)); + } } @@ -5856,6 +5979,14 @@ 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) { @@ -5874,7 +6005,6 @@ mono_get_dbnull_object (MonoDomain *domain) return obj; } - static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types) { @@ -6400,6 +6530,39 @@ MonoType* 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) @@ -6409,7 +6572,10 @@ mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, GString *fullName; GList *mod; - type = mono_reflection_get_type_internal (rootimage, 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 ())) @@ -6433,30 +6599,8 @@ mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, 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 (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; - } - } - } + if (assembly->assembly->dynamic) + type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase); else type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, info, ignorecase); @@ -6540,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; @@ -7253,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; @@ -7267,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; @@ -7355,6 +7513,15 @@ 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; @@ -7498,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); } @@ -8157,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; @@ -8204,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 (); } @@ -8421,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 @@ -8431,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) || @@ -8659,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; } @@ -8682,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; } @@ -8747,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; } @@ -8851,7 +9025,6 @@ static MonoMethod * inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj) { MonoMethodInflated *imethod; - MonoGenericContext tmp_context; MonoGenericContext *context; MonoClass *klass; @@ -8859,14 +9032,6 @@ inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoO g_assert (klass->generic_class); context = mono_class_get_context (klass); - if (method->generic_container) { - g_assert (method->klass == klass->generic_class->container_class); - - tmp_context.class_inst = klass->generic_class->context.class_inst; - tmp_context.method_inst = method->generic_container->context.method_inst; - context = &tmp_context; - } - imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context); if (method->generic_container) { MOVING_GC_REGISTER (&imethod->reflection_info); @@ -8881,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); @@ -8910,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); @@ -9272,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) { @@ -9353,6 +9533,15 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb) 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); @@ -9378,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); @@ -9457,6 +9648,7 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb) { ReflectionMethodBuilder rmb; MonoMethodSignature *sig; + MonoClass *klass; GSList *l; int i; @@ -9497,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)); @@ -9509,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) { @@ -9548,23 +9741,32 @@ mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb) * 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; @@ -9574,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 || @@ -9582,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) { @@ -9603,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; @@ -9614,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; @@ -9629,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; @@ -9683,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 ();