Merge pull request #2237 from xmcclure/container-owner
[mono.git] / mono / metadata / loader.c
index 89047003aa32a9e07298535151bd77a60cfe8895..d2136bbfc6419667341cf5066afe5afd7140a877 100644 (file)
 #include <mono/metadata/marshal.h>
 #include <mono/metadata/lock-tracer.h>
 #include <mono/metadata/verify-internals.h>
-#include <mono/utils/mono-logger-internal.h>
+#include <mono/utils/mono-logger-internals.h>
 #include <mono/utils/mono-dl.h>
 #include <mono/utils/mono-membar.h>
 #include <mono/utils/mono-counters.h>
 #include <mono/utils/mono-error-internals.h>
 #include <mono/utils/mono-tls.h>
+#include <mono/utils/mono-path.h>
 
 MonoDefaults mono_defaults;
 
@@ -55,7 +56,8 @@ MonoDefaults mono_defaults;
  * See domain-internals.h for locking policy in combination with the
  * domain lock.
  */
-static mono_mutex_t loader_mutex, global_loader_data_mutex;
+static MonoCoopMutex loader_mutex;
+static mono_mutex_t global_loader_data_mutex;
 static gboolean loader_lock_inited;
 
 /* Statistics */
@@ -81,13 +83,13 @@ static void dllmap_cleanup (void);
 static void
 global_loader_data_lock (void)
 {
-       mono_locks_acquire (&global_loader_data_mutex, LoaderGlobalDataLock);
+       mono_locks_os_acquire (&global_loader_data_mutex, LoaderGlobalDataLock);
 }
 
 static void
 global_loader_data_unlock (void)
 {
-       mono_locks_release (&global_loader_data_mutex, LoaderGlobalDataLock);
+       mono_locks_os_release (&global_loader_data_mutex, LoaderGlobalDataLock);
 }
 
 void
@@ -96,8 +98,8 @@ mono_loader_init ()
        static gboolean inited;
 
        if (!inited) {
-               mono_mutex_init_recursive (&loader_mutex);
-               mono_mutex_init_recursive (&global_loader_data_mutex);
+               mono_coop_mutex_init_recursive (&loader_mutex);
+               mono_os_mutex_init_recursive (&global_loader_data_mutex);
                loader_lock_inited = TRUE;
 
                mono_native_tls_alloc (&loader_error_thread_id, NULL);
@@ -125,8 +127,8 @@ mono_loader_cleanup (void)
        mono_native_tls_free (loader_error_thread_id);
        mono_native_tls_free (loader_lock_nest_id);
 
-       mono_mutex_destroy (&loader_mutex);
-       mono_mutex_destroy (&global_loader_data_mutex);
+       mono_coop_mutex_destroy (&loader_mutex);
+       mono_os_mutex_destroy (&global_loader_data_mutex);
        loader_lock_inited = FALSE;     
 }
 
@@ -600,8 +602,11 @@ mono_field_from_token_checked (MonoImage *image, guint32 token, MonoClass **retk
                }
        }
 
-       if (field && field->parent && !field->parent->generic_class && !field->parent->generic_container)
+       if (field && field->parent && !field->parent->generic_class && !field->parent->generic_container) {
+               mono_image_lock (image);
                mono_conc_hashtable_insert (image->field_cache, GUINT_TO_POINTER (token), field);
+               mono_image_unlock (image);
+       }
 
        mono_loader_assert_no_error ();
        return field;
@@ -1192,12 +1197,9 @@ method_from_methodspec (MonoImage *image, MonoGenericContext *context, guint32 i
        ptr++;
        param_count = mono_metadata_decode_value (ptr, &ptr);
 
-       inst = mono_metadata_parse_generic_inst (image, NULL, param_count, ptr, &ptr);
-       if (!inst) {
-               mono_loader_assert_no_error ();
-               mono_error_set_bad_image (error, image, "Cannot parse generic instance for methodspec 0x%08x", idx);
+       inst = mono_metadata_parse_generic_inst (image, NULL, param_count, ptr, &ptr, error);
+       if (!inst)
                return NULL;
-       }
 
        if (context && inst->is_open) {
                inst = mono_metadata_inflate_generic_inst (inst, context, error);
@@ -1428,7 +1430,7 @@ mono_lookup_pinvoke_call (MonoMethod *method, const char **exc_class, const char
        const char *new_scope;
        char *error_msg;
        char *full_name, *file_name, *found_name = NULL;
-       int i;
+       int i,j;
        MonoDl *module = NULL;
        gboolean cached = FALSE;
 
@@ -1535,7 +1537,7 @@ mono_lookup_pinvoke_call (MonoMethod *method, const char **exc_class, const char
                        continue;
                case 3:
                        if (!is_absolute && mono_dl_get_system_dir ()) {
-                               dir_name = mono_dl_get_system_dir ();
+                               dir_name = (char*)mono_dl_get_system_dir ();
                                file_name = g_path_get_basename (new_scope);
                                base_name = NULL;
                        } else
@@ -1576,23 +1578,85 @@ mono_lookup_pinvoke_call (MonoMethod *method, const char **exc_class, const char
                }
 
                if (!module && !is_absolute) {
-                       void *iter = NULL;
-                       char *mdirname = g_path_get_dirname (image->name);
-                       while ((full_name = mono_dl_build_path (mdirname, file_name, &iter))) {
-                               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': '%s'.",
-                                                               full_name, error_msg);
-                                       g_free (error_msg);
-                               } else {
-                                       found_name = g_strdup (full_name);
+                       void *iter;
+                       char *mdirname;
+
+                       for (j = 0; j < 3; ++j) {
+                               iter = NULL;
+                               mdirname = NULL;
+                               switch (j) {
+                                       case 0:
+                                               mdirname = g_path_get_dirname (image->name);
+                                               break;
+                                       case 1: /* @executable_path@/../lib */
+                                       {
+                                               char buf [4096];
+                                               int binl;
+                                               binl = mono_dl_get_executable_path (buf, sizeof (buf));
+                                               if (binl != -1) {
+                                                       char *base, *newbase;
+                                                       char *resolvedname;
+                                                       buf [binl] = 0;
+                                                       resolvedname = mono_path_resolve_symlinks (buf);
+
+                                                       base = g_path_get_dirname (resolvedname);
+                                                       newbase = g_path_get_dirname(base);
+                                                       mdirname = g_strdup_printf ("%s/lib", newbase);
+
+                                                       g_free (resolvedname);
+                                                       g_free (base);
+                                                       g_free (newbase);
+                                               }
+                                               break;
+                                       }
+#ifdef __MACH__
+                                       case 2: /* @executable_path@/../Libraries */
+                                       {
+                                               char buf [4096];
+                                               int binl;
+                                               binl = mono_dl_get_executable_path (buf, sizeof (buf));
+                                               if (binl != -1) {
+                                                       char *base, *newbase;
+                                                       char *resolvedname;
+                                                       buf [binl] = 0;
+                                                       resolvedname = mono_path_resolve_symlinks (buf);
+
+                                                       base = g_path_get_dirname (resolvedname);
+                                                       newbase = g_path_get_dirname(base);
+                                                       mdirname = g_strdup_printf ("%s/Libraries", newbase);
+
+                                                       g_free (resolvedname);
+                                                       g_free (base);
+                                                       g_free (newbase);
+                                               }
+                                               break;
+                                       }
+#endif
                                }
-                               g_free (full_name);
+
+                               if (!mdirname)
+                                       continue;
+
+                               while ((full_name = mono_dl_build_path (mdirname, file_name, &iter))) {
+                                       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': '%s'.",
+                                                                       full_name, error_msg);
+                                               g_free (error_msg);
+                                       } else {
+                                               found_name = g_strdup (full_name);
+                                       }
+                                       g_free (full_name);
+                                       if (module)
+                                               break;
+
+                               }
+                               g_free (mdirname);
                                if (module)
                                        break;
                        }
-                       g_free (mdirname);
+
                }
 
                if (!module) {
@@ -1879,6 +1943,7 @@ mono_get_method_from_token (MonoImage *image, guint32 token, MonoClass *klass,
        if (generic_container) {
                result->is_generic = TRUE;
                generic_container->owner.method = result;
+               generic_container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
                /*FIXME put this before the image alloc*/
                if (!mono_metadata_load_generic_param_constraints_checked (image, token, generic_container, error))
                        return NULL;
@@ -2376,10 +2441,11 @@ stack_walk_adapter (MonoStackFrameInfo *frame, MonoContext *ctx, gpointer data)
        switch (frame->type) {
        case FRAME_TYPE_DEBUGGER_INVOKE:
        case FRAME_TYPE_MANAGED_TO_NATIVE:
+       case FRAME_TYPE_TRAMPOLINE:
                return FALSE;
        case FRAME_TYPE_MANAGED:
                g_assert (frame->ji);
-               return d->func (mono_jit_info_get_method (frame->ji), frame->native_offset, frame->il_offset, frame->managed, d->user_data);
+               return d->func (frame->actual_method, frame->native_offset, frame->il_offset, frame->managed, d->user_data);
                break;
        default:
                g_assert_not_reached ();
@@ -2415,14 +2481,16 @@ async_stack_walk_adapter (MonoStackFrameInfo *frame, MonoContext *ctx, gpointer
        switch (frame->type) {
        case FRAME_TYPE_DEBUGGER_INVOKE:
        case FRAME_TYPE_MANAGED_TO_NATIVE:
+       case FRAME_TYPE_TRAMPOLINE:
                return FALSE;
        case FRAME_TYPE_MANAGED:
                if (!frame->ji)
                        return FALSE;
-               if (frame->ji->async)
+               if (frame->ji->async) {
                        return d->func (NULL, frame->domain, frame->ji->code_start, frame->native_offset, d->user_data);
-               else
-                       return d->func (mono_jit_info_get_method (frame->ji), frame->domain, frame->ji->code_start, frame->native_offset, d->user_data);
+               } else {
+                       return d->func (frame->actual_method, frame->domain, frame->ji->code_start, frame->native_offset, d->user_data);
+               }
                break;
        default:
                g_assert_not_reached ();
@@ -2474,10 +2542,7 @@ static gboolean loader_lock_track_ownership = FALSE;
 void
 mono_loader_lock (void)
 {
-       MONO_TRY_BLOCKING
-       mono_locks_acquire (&loader_mutex, LoaderLock);
-       MONO_FINISH_TRY_BLOCKING
-               
+       mono_locks_coop_acquire (&loader_mutex, LoaderLock);
        if (G_UNLIKELY (loader_lock_track_ownership)) {
                mono_native_tls_set_value (loader_lock_nest_id, GUINT_TO_POINTER (GPOINTER_TO_UINT (mono_native_tls_get_value (loader_lock_nest_id)) + 1));
        }
@@ -2486,7 +2551,7 @@ mono_loader_lock (void)
 void
 mono_loader_unlock (void)
 {
-       mono_locks_release (&loader_mutex, LoaderLock);
+       mono_locks_coop_release (&loader_mutex, LoaderLock);
        if (G_UNLIKELY (loader_lock_track_ownership)) {
                mono_native_tls_set_value (loader_lock_nest_id, GUINT_TO_POINTER (GPOINTER_TO_UINT (mono_native_tls_get_value (loader_lock_nest_id)) - 1));
        }