X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Floader.c;h=77ef3dff6ed32a0a05004532ecf08c2525a504a2;hb=d5fa8f0cdd8a42c7c5e0fd7a66a0ab0afcb5f9f6;hp=7737080a2e12244358ea07b7e9bfc7a898520d2c;hpb=89d0ba3968d36576553e0f483b0c69465f94e8ae;p=mono.git diff --git a/mono/metadata/loader.c b/mono/metadata/loader.c index 7737080a2e1..77ef3dff6ed 100644 --- a/mono/metadata/loader.c +++ b/mono/metadata/loader.c @@ -19,7 +19,6 @@ */ #include #include -#include #include #include #include @@ -36,6 +35,7 @@ #include #include #include +#include #include MonoDefaults mono_defaults; @@ -100,7 +100,7 @@ mono_loader_set_error_assembly_load (const char *assembly_name, gboolean ref_onl return; error = g_new0 (MonoLoaderError, 1); - error->kind = MONO_LOADER_ERROR_ASSEMBLY; + error->exception_type = MONO_EXCEPTION_FILE_NOT_FOUND; error->assembly_name = g_strdup (assembly_name); error->ref_only = ref_only; @@ -131,7 +131,7 @@ mono_loader_set_error_type_load (const char *class_name, const char *assembly_na return; error = g_new0 (MonoLoaderError, 1); - error->kind = MONO_LOADER_ERROR_TYPE; + error->exception_type = MONO_EXCEPTION_TYPE_LOAD; error->class_name = g_strdup (class_name); error->assembly_name = g_strdup (assembly_name); @@ -161,7 +161,7 @@ mono_loader_set_error_method_load (const char *class_name, const char *member_na return; error = g_new0 (MonoLoaderError, 1); - error->kind = MONO_LOADER_ERROR_METHOD; + error->exception_type = MONO_EXCEPTION_MISSING_METHOD; error->class_name = g_strdup (class_name); error->member_name = member_name; @@ -184,7 +184,7 @@ mono_loader_set_error_field_load (MonoClass *klass, const char *member_name) return; error = g_new0 (MonoLoaderError, 1); - error->kind = MONO_LOADER_ERROR_FIELD; + error->exception_type = MONO_EXCEPTION_MISSING_FIELD; error->klass = klass; error->member_name = member_name; @@ -214,8 +214,8 @@ mono_loader_clear_error (void) MonoLoaderError *ex = (MonoLoaderError*)TlsGetValue (loader_error_thread_id); if (ex) { - g_free (ex->class_name); - g_free (ex->assembly_name); + g_free (ex->class_name); + g_free (ex->assembly_name); g_free (ex); TlsSetValue (loader_error_thread_id, NULL); @@ -235,8 +235,8 @@ mono_loader_error_prepare_exception (MonoLoaderError *error) { MonoException *ex = NULL; - switch (error->kind) { - case MONO_LOADER_ERROR_TYPE: { + switch (error->exception_type) { + case MONO_EXCEPTION_TYPE_LOAD: { char *cname = g_strdup (error->class_name); char *aname = g_strdup (error->assembly_name); MonoString *class_name; @@ -250,7 +250,7 @@ mono_loader_error_prepare_exception (MonoLoaderError *error) g_free (aname); break; } - case MONO_LOADER_ERROR_METHOD: { + case MONO_EXCEPTION_MISSING_METHOD: { char *cname = g_strdup (error->class_name); char *aname = g_strdup (error->member_name); @@ -261,7 +261,7 @@ mono_loader_error_prepare_exception (MonoLoaderError *error) break; } - case MONO_LOADER_ERROR_FIELD: { + case MONO_EXCEPTION_MISSING_FIELD: { char *cnspace = g_strdup (*error->klass->name_space ? error->klass->name_space : ""); char *cname = g_strdup (error->klass->name); char *cmembername = g_strdup (error->member_name); @@ -278,17 +278,20 @@ mono_loader_error_prepare_exception (MonoLoaderError *error) break; } - case MONO_LOADER_ERROR_ASSEMBLY: { + case MONO_EXCEPTION_FILE_NOT_FOUND: { char *msg; + char *filename; if (error->ref_only) msg = g_strdup_printf ("Cannot resolve dependency to assembly '%s' because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event.", error->assembly_name); else msg = g_strdup_printf ("Could not load file or assembly '%s' or one of its dependencies.", error->assembly_name); - - ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), error->assembly_name)); + filename = g_strdup (error->assembly_name); + /* Has to call this before calling anything which might call mono_class_init () */ mono_loader_clear_error (); + ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), filename)); g_free (msg); + g_free (filename); break; } @@ -329,6 +332,19 @@ field_from_memberref (MonoImage *image, guint32 token, MonoClass **retklass, /* we may want to check the signature here... */ switch (class) { + case MONO_MEMBERREF_PARENT_TYPEDEF: + klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | nindex); + if (!klass) { + char *name = mono_class_name_from_token (image, MONO_TOKEN_TYPE_REF | nindex); + g_warning ("Missing field %s in class %s (typeref index %d)", fname, name, nindex); + g_free (name); + return NULL; + } + mono_class_init (klass); + if (retklass) + *retklass = klass; + field = mono_class_get_field_from_name (klass, fname); + break; case MONO_MEMBERREF_PARENT_TYPEREF: klass = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | nindex); if (!klass) { @@ -403,9 +419,9 @@ mono_field_from_token (MonoImage *image, guint32 token, MonoClass **retklass, if (!type) return NULL; k = mono_class_get (image, MONO_TOKEN_TYPE_DEF | type); - mono_class_init (k); if (!k) return NULL; + mono_class_init (k); if (retklass) *retklass = k; field = mono_class_get_field (k, token); @@ -454,7 +470,8 @@ find_method_in_class (MonoClass *in_class, const char *name, const char *qname, MonoMethod *m = in_class->methods [i]; if (!((fqname && !strcmp (m->name, fqname)) || - (qname && !strcmp (m->name, qname)) || !strcmp (m->name, name))) + (qname && !strcmp (m->name, qname)) || + (name && !strcmp (m->name, name)))) continue; if (sig->call_convention == MONO_CALL_VARARG) { @@ -508,8 +525,19 @@ find_method (MonoClass *in_class, MonoClass *ic, const char* name, MonoMethodSig for (i = 0; i < in_class->interface_count; i++) { MonoClass *ic = in_class->interfaces [i]; MonoClass *from_ic = from_class->interfaces [i]; + char *ic_qname, *ic_fqname, *ic_class_name; + + ic_class_name = mono_type_get_name_full (&ic->byval_arg, MONO_TYPE_NAME_FORMAT_IL); + ic_qname = g_strconcat (ic_class_name, ".", name, NULL); + if (ic->name_space && ic->name_space [0]) + ic_fqname = g_strconcat (ic->name_space, ".", ic_class_name, ".", name, NULL); + else + ic_fqname = NULL; - result = find_method_in_class (ic, name, qname, fqname, sig, from_ic); + result = find_method_in_class (ic, NULL, ic_qname, ic_fqname, sig, from_ic); + g_free (ic_class_name); + g_free (ic_fqname); + g_free (ic_qname); if (result) goto out; } @@ -573,6 +601,17 @@ inflate_generic_header (MonoMethodHeader *header, MonoGenericContext *context) res->clauses = header->clauses; for (i = 0; i < header->num_locals; ++i) res->locals [i] = mono_class_inflate_generic_type (header->locals [i], context); + if (res->num_clauses) { + res->clauses = g_memdup (header->clauses, sizeof (MonoExceptionClause) * res->num_clauses); + for (i = 0; i < header->num_clauses; ++i) { + MonoExceptionClause *clause = &res->clauses [i]; + MonoType *t; + if (clause->flags != MONO_EXCEPTION_CLAUSE_NONE) + continue; + t = mono_class_inflate_generic_type (&clause->data.catch_class->byval_arg, context); + clause->data.catch_class = mono_class_from_mono_type (t); + } + } return res; } @@ -616,8 +655,7 @@ mono_method_get_signature_full (MonoMethod *method, MonoImage *image, guint32 to ptr = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]); mono_metadata_decode_blob_size (ptr, &ptr); - sig = mono_metadata_parse_method_signature_full ( - image, context ? context->container : NULL, 0, ptr, NULL); + sig = mono_metadata_parse_method_signature (image, 0, ptr, NULL); mono_loader_lock (); prev_sig = g_hash_table_lookup (image->memberref_signatures, GUINT_TO_POINTER (token)); @@ -642,8 +680,22 @@ mono_method_get_signature (MonoMethod *method, MonoImage *image, guint32 token) return mono_method_get_signature_full (method, image, token, NULL); } +/* this is only for the typespec array methods */ +static MonoMethod* +search_in_array_class (MonoClass *klass, const char *name, MonoMethodSignature *sig) +{ + int i; + for (i = 0; i < klass->method.count; ++i) { + MonoMethod *method = klass->methods [i]; + if (strcmp (method->name, name) == 0 && sig->param_count == method->signature->param_count) + return method; + } + return NULL; +} + static MonoMethod * -method_from_memberref (MonoImage *image, guint32 idx, MonoGenericContext *typespec_context) +method_from_memberref (MonoImage *image, guint32 idx, MonoGenericContext *typespec_context, + gboolean *used_context) { MonoClass *klass = NULL; MonoMethod *method = NULL; @@ -662,6 +714,14 @@ method_from_memberref (MonoImage *image, guint32 idx, MonoGenericContext *typesp mname = mono_metadata_string_heap (image, cols [MONO_MEMBERREF_NAME]); + /* + * Whether we actually used the `typespec_context' or not. + * This is used to tell our caller whether or not it's safe to insert the returned + * method into a cache. + */ + if (used_context) + *used_context = class == MONO_MEMBERREF_PARENT_TYPESPEC; + switch (class) { case MONO_MEMBERREF_PARENT_TYPEREF: klass = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | nindex); @@ -736,38 +796,10 @@ method_from_memberref (MonoImage *image, guint32 idx, MonoGenericContext *typesp break; } - result = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1); - result->klass = klass; - result->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL; - result->flags = METHOD_ATTRIBUTE_PUBLIC; - result->signature = sig; - result->name = mname; - - if (!strcmp (mname, ".ctor")) { - /* we special-case this in the runtime. */ - return result; - } - - if (!strcmp (mname, "Set")) { - g_assert (sig->hasthis); - g_assert (type->data.array->rank + 1 == sig->param_count); - result->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME; - return result; - } - - if (!strcmp (mname, "Get")) { - g_assert (sig->hasthis); - g_assert (type->data.array->rank == sig->param_count); - result->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME; - return result; - } - - if (!strcmp (mname, "Address")) { - g_assert (sig->hasthis); - g_assert (type->data.array->rank == sig->param_count); - result->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME; + /* we're an array and we created these methods already in klass in mono_class_init () */ + result = search_in_array_class (klass, mname, sig); + if (result) return result; - } g_assert_not_reached (); break; @@ -803,10 +835,10 @@ static MonoMethod * method_from_methodspec (MonoImage *image, MonoGenericContext *context, guint32 idx) { MonoMethod *method, *inflated; + MonoClass *klass; MonoTableInfo *tables = image->tables; - MonoGenericContext *new_context = NULL; - MonoGenericMethod *gmethod; - MonoGenericContainer *container = NULL; + MonoGenericContext new_context; + MonoGenericInst *inst; const char *ptr; guint32 cols [MONO_METHODSPEC_SIZE]; guint32 token, nindex, param_count; @@ -851,22 +883,19 @@ method_from_methodspec (MonoImage *image, MonoGenericContext *context, guint32 i if ((token & MONO_METHODDEFORREF_MASK) == MONO_METHODDEFORREF_METHODDEF) method = mono_get_method_full (image, MONO_TOKEN_METHOD_DEF | nindex, NULL, context); else - method = method_from_memberref (image, nindex, context); + method = method_from_memberref (image, nindex, context, NULL); - method = mono_get_inflated_method (method); + klass = method->klass; - container = method->generic_container; - g_assert (container); + /* FIXME: Is this invalid metadata? Should we throw an exception instead? */ + g_assert (!klass->generic_container); - gmethod = g_new0 (MonoGenericMethod, 1); - gmethod->generic_class = method->klass->generic_class; - gmethod->container = container; + if (klass->generic_class) { + g_assert (method->is_inflated); + method = ((MonoMethodInflated *) method)->declaring; + } - new_context = g_new0 (MonoGenericContext, 1); - new_context->container = container; - new_context->gmethod = gmethod; - if (container->parent) - new_context->gclass = container->parent->context.gclass; + new_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL; /* * When parsing the methodspec signature, we're in the old context again: @@ -889,47 +918,31 @@ method_from_methodspec (MonoImage *image, MonoGenericContext *context, guint32 i * ie. instantiate the method as `Foo.Hello. */ - gmethod->inst = mono_metadata_parse_generic_inst (image, context ? context->container : NULL, param_count, ptr, &ptr); + inst = mono_metadata_parse_generic_inst (image, NULL, param_count, ptr, &ptr); - if (context && gmethod->inst->is_open) - gmethod->inst = mono_metadata_inflate_generic_inst (gmethod->inst, context); + if (context && inst->is_open) + inst = mono_metadata_inflate_generic_inst (inst, context); - if (!container->method_hash) - container->method_hash = g_hash_table_new ( - (GHashFunc)mono_metadata_generic_method_hash, (GEqualFunc)mono_metadata_generic_method_equal); + new_context.method_inst = inst; - inflated = g_hash_table_lookup (container->method_hash, gmethod); - if (inflated) { - g_free (gmethod); - g_free (new_context); - return inflated; - } - - context = new_context; - - mono_stats.generics_metadata_size += sizeof (MonoGenericMethod) + - sizeof (MonoGenericContext) + param_count * sizeof (MonoType); - - inflated = mono_class_inflate_generic_method_full (method, method->klass, new_context); - g_hash_table_insert (container->method_hash, gmethod, inflated); + inflated = mono_class_inflate_generic_method_full (method, klass, &new_context); return inflated; } -typedef struct MonoDllMap MonoDllMap; - -struct MonoDllMap { - char *name; - char *target; +struct _MonoDllMap { char *dll; + char *target; + char *func; + char *target_func; MonoDllMap *next; }; -static GHashTable *global_dll_map; +static MonoDllMap *global_dll_map; static int -mono_dllmap_lookup_hash (GHashTable *dll_map, const char *dll, const char* func, const char **rdll, const char **rfunc) { - MonoDllMap *map, *tmp; +mono_dllmap_lookup_list (MonoDllMap *dll_map, const char *dll, const char* func, const char **rdll, const char **rfunc) { + int found = 0; *rdll = dll; @@ -938,25 +951,33 @@ mono_dllmap_lookup_hash (GHashTable *dll_map, const char *dll, const char* func, mono_loader_lock (); - map = g_hash_table_lookup (dll_map, dll); - if (!map) { - mono_loader_unlock (); - return 0; - } - *rdll = map->target? map->target: dll; - - for (tmp = map->next; tmp; tmp = tmp->next) { - if (strcmp (func, tmp->name) == 0) { - *rfunc = tmp->name; - if (tmp->dll) - *rdll = tmp->dll; - mono_loader_unlock (); - return 1; + /* + * we use the first entry we find that matches, since entries from + * the config file are prepended to the list and we document that the + * later entries win. + */ + for (; dll_map; dll_map = dll_map->next) { + if (dll_map->dll [0] == 'i' && dll_map->dll [1] == ':') { + if (g_ascii_strcasecmp (dll_map->dll + 2, dll)) + continue; + } else if (strcmp (dll_map->dll, dll)) { + continue; + } + if (!found && dll_map->target) { + *rdll = dll_map->target; + found = 1; + /* we don't quit here, because we could find a full + * entry that matches also function and that has priority. + */ + } + if (dll_map->func && strcmp (dll_map->func, func) == 0) { + *rfunc = dll_map->target_func; + break; } } - *rfunc = func; + mono_loader_unlock (); - return 1; + return found; } static int @@ -964,50 +985,61 @@ mono_dllmap_lookup (MonoImage *assembly, const char *dll, const char* func, cons { int res; if (assembly && assembly->dll_map) { - res = mono_dllmap_lookup_hash (assembly->dll_map, dll, func, rdll, rfunc); + res = mono_dllmap_lookup_list (assembly->dll_map, dll, func, rdll, rfunc); if (res) return res; } - return mono_dllmap_lookup_hash (global_dll_map, dll, func, rdll, rfunc); + return mono_dllmap_lookup_list (global_dll_map, dll, func, rdll, rfunc); } void mono_dllmap_insert (MonoImage *assembly, const char *dll, const char *func, const char *tdll, const char *tfunc) { - MonoDllMap *map, *entry; - GHashTable *dll_map = NULL; + MonoDllMap *entry; mono_loader_lock (); if (!assembly) { - if (!global_dll_map) - global_dll_map = g_hash_table_new (g_str_hash, g_str_equal); - dll_map = global_dll_map; + entry = g_malloc0 (sizeof (MonoDllMap)); + entry->dll = dll? g_strdup (dll): NULL; + entry->target = tdll? g_strdup (tdll): NULL; + entry->func = func? g_strdup (func): NULL; + entry->target_func = tfunc? g_strdup (tfunc): NULL; + entry->next = global_dll_map; + global_dll_map = entry; } else { - if (!assembly->dll_map) - assembly->dll_map = g_hash_table_new (g_str_hash, g_str_equal); - dll_map = assembly->dll_map; + MonoMemPool *mpool = assembly->mempool; + entry = mono_mempool_alloc0 (mpool, sizeof (MonoDllMap)); + entry->dll = dll? mono_mempool_strdup (mpool, dll): NULL; + entry->target = tdll? mono_mempool_strdup (mpool, tdll): NULL; + entry->func = func? mono_mempool_strdup (mpool, func): NULL; + entry->target_func = tfunc? mono_mempool_strdup (mpool, tfunc): NULL; + entry->next = assembly->dll_map; + assembly->dll_map = entry; } - map = g_hash_table_lookup (dll_map, dll); - if (!map) { - map = g_new0 (MonoDllMap, 1); - map->dll = g_strdup (dll); - if (tdll) - map->target = g_strdup (tdll); - g_hash_table_insert (dll_map, map->dll, map); - } - if (func) { - entry = g_new0 (MonoDllMap, 1); - entry->name = g_strdup (func); - if (tfunc) - entry->target = g_strdup (tfunc); - if (tdll && map->target && strcmp (map->target, tdll)) - entry->dll = g_strdup (tdll); - entry->next = map->next; - map->next = entry; - } + mono_loader_unlock (); +} +static GHashTable *global_module_map; + +static MonoDl* +cached_module_load (const char *name, int flags, char **err) +{ + MonoDl *res; + mono_loader_lock (); + if (!global_module_map) + global_module_map = g_hash_table_new (g_str_hash, g_str_equal); + res = g_hash_table_lookup (global_module_map, name); + if (res) { + *err = NULL; + mono_loader_unlock (); + return res; + } + res = mono_dl_open (name, flags, err); + if (res) + g_hash_table_insert (global_module_map, g_strdup (name), res); mono_loader_unlock (); + return res; } gpointer @@ -1023,9 +1055,10 @@ mono_lookup_pinvoke_call (MonoMethod *method, const char **exc_class, const char const char *import = NULL; const char *orig_scope; const char *new_scope; + char *error_msg; char *full_name, *file_name; int i; - GModule *gmodule = NULL; + MonoDl *module = NULL; g_assert (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL); @@ -1066,7 +1099,7 @@ mono_lookup_pinvoke_call (MonoMethod *method, const char **exc_class, const char /* we allow a special name to dlopen from the running process namespace */ if (strcmp (new_scope, "__Internal") == 0) - gmodule = g_module_open (NULL, G_MODULE_BIND_LAZY); + module = mono_dl_open (NULL, MONO_DL_LAZY, &error_msg); /* * Try loading the module using a variety of names @@ -1108,53 +1141,64 @@ mono_lookup_pinvoke_call (MonoMethod *method, const char **exc_class, const char #endif } - if (!gmodule) { - full_name = g_module_build_path (NULL, file_name); - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, - "DllImport loading location: '%s'.", full_name); - gmodule = g_module_open (full_name, G_MODULE_BIND_LAZY); - if (!gmodule) { + if (!module) { + void *iter = NULL; + while ((full_name = mono_dl_build_path (NULL, file_name, &iter))) { mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, - "DllImport error loading library: '%s'.", - g_module_error ()); + "DllImport loading location: '%s'.", full_name); + module = cached_module_load (full_name, MONO_DL_LAZY, &error_msg); + if (!module) { + mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, + "DllImport error loading library: '%s'.", + error_msg); + g_free (error_msg); + } + g_free (full_name); + if (module) + break; } - g_free (full_name); } - if (!gmodule) { - full_name = g_module_build_path (".", file_name); - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, - "DllImport loading library: '%s'.", full_name); - gmodule = g_module_open (full_name, G_MODULE_BIND_LAZY); - if (!gmodule) { + if (!module) { + void *iter = NULL; + while ((full_name = mono_dl_build_path (".", file_name, &iter))) { mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, + "DllImport loading library: '%s'.", full_name); + module = cached_module_load (full_name, MONO_DL_LAZY, &error_msg); + if (!module) { + mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "DllImport error loading library '%s'.", - g_module_error ()); + error_msg); + g_free (error_msg); + } + g_free (full_name); + if (module) + break; } - g_free (full_name); } - if (!gmodule) { + if (!module) { mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "DllImport loading: '%s'.", file_name); - gmodule=g_module_open (file_name, G_MODULE_BIND_LAZY); - if (!gmodule) { + module = cached_module_load (file_name, MONO_DL_LAZY, &error_msg); + if (!module) { mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "DllImport error loading library '%s'.", - g_module_error ()); + error_msg); } } g_free (file_name); - if (gmodule) + if (module) break; } - if (!gmodule) { + if (!module) { mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_DLLIMPORT, "DllImport unable to load library '%s'.", - g_module_error ()); + error_msg); + g_free (error_msg); if (exc_class) { *exc_class = "DllNotFoundException"; @@ -1167,7 +1211,7 @@ mono_lookup_pinvoke_call (MonoMethod *method, const char **exc_class, const char "Searching for '%s'.", import); if (piinfo->piflags & PINVOKE_ATTRIBUTE_NO_MANGLE) { - g_module_symbol (gmodule, import, &piinfo->addr); + error_msg = mono_dl_symbol (module, import, &piinfo->addr); } else { char *mangled_name = NULL, *mangled_name2 = NULL; int mangle_charset; @@ -1240,7 +1284,7 @@ mono_lookup_pinvoke_call (MonoMethod *method, const char **exc_class, const char mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "Probing '%s'.", mangled_name2); - g_module_symbol (gmodule, mangled_name2, &piinfo->addr); + error_msg = mono_dl_symbol (module, mangled_name2, &piinfo->addr); if (piinfo->addr) mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, @@ -1256,6 +1300,7 @@ mono_lookup_pinvoke_call (MonoMethod *method, const char **exc_class, const char } if (!piinfo->addr) { + g_free (error_msg); if (exc_class) { *exc_class = "EntryPointNotFoundException"; *exc_arg = import; @@ -1265,20 +1310,12 @@ mono_lookup_pinvoke_call (MonoMethod *method, const char **exc_class, const char return piinfo->addr; } -MonoGenericMethod * -mono_get_shared_generic_method (MonoGenericContainer *container) -{ - MonoGenericMethod *gmethod = g_new0 (MonoGenericMethod, 1); - gmethod->container = container; - gmethod->generic_class = container->context.gclass; - gmethod->inst = mono_get_shared_generic_inst (container); - - return gmethod; -} - +/* + * LOCKING: assumes the loader lock to be taken. + */ static MonoMethod * mono_get_method_from_token (MonoImage *image, guint32 token, MonoClass *klass, - MonoGenericContext *context) + MonoGenericContext *context, gboolean *used_context) { MonoMethod *result; int table = mono_metadata_token_table (token); @@ -1293,17 +1330,19 @@ mono_get_method_from_token (MonoImage *image, guint32 token, MonoClass *klass, return mono_lookup_dynamic_token (image, token); if (table != MONO_TABLE_METHOD) { - if (table == MONO_TABLE_METHODSPEC) + if (table == MONO_TABLE_METHODSPEC) { + if (used_context) *used_context = TRUE; return method_from_methodspec (image, context, idx); + } if (table != MONO_TABLE_MEMBERREF) g_print("got wrong token: 0x%08x\n", token); g_assert (table == MONO_TABLE_MEMBERREF); - result = method_from_memberref (image, idx, context); - - return result; + return method_from_memberref (image, idx, context, used_context); } - mono_metadata_decode_row (&tables [table], idx - 1, cols, 6); + if (used_context) *used_context = FALSE; + + mono_metadata_decode_row (&image->tables [MONO_TABLE_METHOD], idx - 1, cols, 6); if ((cols [2] & METHOD_ATTRIBUTE_PINVOKE_IMPL) || (cols [1] & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)) @@ -1330,22 +1369,17 @@ mono_get_method_from_token (MonoImage *image, guint32 token, MonoClass *klass, container = klass->generic_container; generic_container = mono_metadata_load_generic_params (image, token, container); if (generic_container) { - MonoGenericContext *context = &generic_container->context; - if (container) - context->gclass = container->context.gclass; - context->gmethod = mono_get_shared_generic_method (generic_container); - mono_metadata_load_generic_param_constraints (image, token, generic_container); + generic_container->owner.method = result; - for (i = 0; i < generic_container->type_argc; i++) { - generic_container->type_params [i].method = result; + mono_metadata_load_generic_param_constraints (image, token, generic_container); - mono_class_from_generic_parameter ( - &generic_container->type_params [i], image, TRUE); - } + for (i = 0; i < generic_container->type_argc; i++) + mono_class_from_generic_parameter (&generic_container->type_params [i], image, TRUE); container = generic_container; } + if (!sig) /* already taken from the methodref */ sig = mono_metadata_blob_heap (image, cols [4]); size = mono_metadata_decode_blob_size (sig, &sig); @@ -1386,6 +1420,7 @@ mono_get_method_full (MonoImage *image, guint32 token, MonoClass *klass, MonoGenericContext *context) { MonoMethod *result; + gboolean used_context = FALSE; /* We do everything inside the lock to prevent creation races */ @@ -1396,11 +1431,21 @@ mono_get_method_full (MonoImage *image, guint32 token, MonoClass *klass, return result; } - result = mono_get_method_from_token (image, token, klass, context); + result = mono_get_method_from_token (image, token, klass, context, &used_context); //printf ("GET: %s\n", mono_method_full_name (result, TRUE)); - if (!(result && result->is_inflated)) +#if 0 + g_message (G_STRLOC ": %s - %d - %d", mono_method_full_name (result, TRUE), + result->is_inflated, used_context); +#endif + + /* + * `used_context' specifies whether or not mono_get_method_from_token() actually + * used the `context' to get the method. See bug #80969. + */ + + if (!used_context && !(result && result->is_inflated)) g_hash_table_insert (image->method_cache, GINT_TO_POINTER (token), result); mono_loader_unlock (); @@ -1428,27 +1473,27 @@ mono_get_method_constrained (MonoImage *image, guint32 token, MonoClass *constra mono_loader_lock (); - *cil_method = mono_get_method_from_token (image, token, NULL, context); + *cil_method = mono_get_method_from_token (image, token, NULL, context, NULL); if (!*cil_method) { mono_loader_unlock (); return NULL; } mono_class_init (constrained_class); - method = mono_get_inflated_method (*cil_method); + method = *cil_method; sig = mono_method_signature (method); if (method->is_inflated && sig->generic_param_count) { MonoMethodInflated *imethod = (MonoMethodInflated *) method; sig = mono_method_signature (imethod->declaring); - method_context = imethod->context; + method_context = mono_method_get_context (method); } if ((constrained_class != method->klass) && (method->klass->interface_id != 0)) ic = method->klass; if (constrained_class->generic_class) - class_context = constrained_class->generic_class->context; + class_context = mono_class_get_context (constrained_class); result = find_method (constrained_class, ic, method->name, sig, constrained_class); if (!result) { @@ -1484,21 +1529,20 @@ mono_free_method (MonoMethod *method) if (method->dynamic) { MonoMethodWrapper *mw = (MonoMethodWrapper*)method; - + int i; + g_free ((char*)method->name); - if (mw->method.header) + if (mw->method.header) { g_free ((char*)mw->method.header->code); + for (i = 0; i < mw->method.header->num_locals; ++i) + g_free (mw->method.header->locals [i]); + g_free (mw->method.header->clauses); + g_free (mw->method.header); + } g_free (mw->method_data); - } - - if (method->dynamic && !(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && ((MonoMethodNormal *)method)->header) { - /* FIXME: Ditto */ - /* mono_metadata_free_mh (((MonoMethodNormal *)method)->header); */ - g_free (((MonoMethodNormal*)method)->header); - } - - if (method->dynamic) + g_free (method->signature); g_free (method); + } } void @@ -1515,7 +1559,7 @@ mono_method_get_param_names (MonoMethod *method, const char **names) for (i = 0; i < mono_method_signature (method)->param_count; ++i) names [i] = ""; - if (klass->generic_class) /* copy the names later */ + if (klass->generic_class || klass->rank) /* copy the names later */ return; mono_class_init (klass); @@ -1537,7 +1581,9 @@ mono_method_get_param_names (MonoMethod *method, const char **names) idx = mono_method_get_index (method); if (idx > 0) { guint32 cols [MONO_PARAM_SIZE]; - guint param_index = mono_metadata_decode_row_col (methodt, idx - 1, MONO_METHOD_PARAMLIST); + guint param_index; + + param_index = mono_metadata_decode_row_col (methodt, idx - 1, MONO_METHOD_PARAMLIST); if (idx < methodt->rows) lastp = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST); @@ -1559,9 +1605,6 @@ mono_method_get_param_token (MonoMethod *method, int index) MonoTableInfo *methodt; guint32 idx; - if (klass->generic_class) - g_assert_not_reached (); - mono_class_init (klass); if (klass->image->dynamic) { @@ -1573,7 +1616,11 @@ mono_method_get_param_token (MonoMethod *method, int index) if (idx > 0) { guint param_index = mono_metadata_decode_row_col (methodt, idx - 1, MONO_METHOD_PARAMLIST); - return mono_metadata_make_token (MONO_TABLE_PARAM, param_index + index); + if (index == -1) + /* Return value */ + return mono_metadata_make_token (MONO_TABLE_PARAM, 0); + else + return mono_metadata_make_token (MONO_TABLE_PARAM, param_index + index); } return 0; @@ -1781,7 +1828,7 @@ mono_method_signature (MonoMethod *m) MonoMethodSignature *signature; /* the lock is recursive */ signature = mono_method_signature (imethod->declaring); - m->signature = inflate_generic_signature (imethod->declaring->klass->image, signature, imethod->context); + m->signature = inflate_generic_signature (imethod->declaring->klass->image, signature, mono_method_get_context (m)); mono_loader_unlock (); return m->signature; } @@ -1922,7 +1969,7 @@ mono_method_get_header (MonoMethod *method) MonoMethodHeader *header; /* the lock is recursive */ header = mono_method_get_header (imethod->declaring); - mn->header = inflate_generic_header (header, imethod->context); + mn->header = inflate_generic_header (header, mono_method_get_context (method)); mono_loader_unlock (); return mn->header; } @@ -1962,8 +2009,12 @@ mono_method_get_index (MonoMethod *method) { mono_class_setup_methods (klass); for (i = 0; i < klass->method.count; ++i) { - if (method == klass->methods [i]) - return klass->method.first + 1 + i; + if (method == klass->methods [i]) { + if (klass->image->uncompressed_metadata) + return mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, klass->method.first + i + 1); + else + return klass->method.first + i + 1; + } } return 0; }