Merge pull request #4444 from lateralusX/jlorenss/windows-unwind-info
[mono.git] / mono / mini / aot-compiler.c
index b91dfaedb245b11461172e3fae477c04cbee5ee8..22dc64f95197ac60691c4a89eac17f793438fc2f 100644 (file)
@@ -56,7 +56,7 @@
 #include <mono/utils/json.h>
 #include <mono/utils/mono-threads-coop.h>
 #include <mono/profiler/mono-profiler-aot.h>
-#include <mono/io-layer/io-layer.h>
+#include <mono/utils/w32api.h>
 
 #include "aot-compiler.h"
 #include "seq-points.h"
@@ -149,7 +149,7 @@ typedef struct MonoAotOptions {
        char *outfile;
        char *llvm_outfile;
        char *data_outfile;
-       char *profile_file;
+       GList *profile_files;
        gboolean save_temps;
        gboolean write_symbols;
        gboolean metadata_only;
@@ -182,6 +182,7 @@ typedef struct MonoAotOptions {
        int nrgctx_fetch_trampolines;
        gboolean print_skipped_methods;
        gboolean stats;
+       gboolean verbose;
        char *tool_prefix;
        char *ld_flags;
        char *mtriple;
@@ -190,6 +191,7 @@ typedef struct MonoAotOptions {
        char *instances_logfile_path;
        char *logfile;
        gboolean dump_json;
+       gboolean profile_only;
 } MonoAotOptions;
 
 typedef enum {
@@ -310,7 +312,8 @@ typedef struct MonoAotCompile {
        int objc_selector_index, objc_selector_index_2;
        GPtrArray *objc_selectors;
        GHashTable *objc_selector_to_index;
-       ProfileData *profile_data;
+       GList *profile_data;
+       GHashTable *profile_methods;
        FILE *logfile;
        FILE *instances_logfile;
        FILE *data_outfile;
@@ -381,7 +384,7 @@ static void
 add_gsharedvt_wrappers (MonoAotCompile *acfg, MonoMethodSignature *sig, gboolean gsharedvt_in, gboolean gsharedvt_out);
 
 static void
-add_profile_instances (MonoAotCompile *acfg);
+add_profile_instances (MonoAotCompile *acfg, ProfileData *data);
 
 static void
 aot_printf (MonoAotCompile *acfg, const gchar *format, ...)
@@ -4327,7 +4330,9 @@ add_wrappers (MonoAotCompile *acfg)
                                        named += slen;
                                }
 
-                               wrapper = mono_marshal_get_managed_wrapper (method, klass, 0);
+                               wrapper = mono_marshal_get_managed_wrapper (method, klass, 0, &error);
+                               mono_error_assert_ok (&error);
+
                                add_method (acfg, wrapper);
                                if (export_name)
                                        g_hash_table_insert (acfg->export_names, wrapper, export_name);
@@ -5241,11 +5246,11 @@ compute_line_numbers (MonoMethod *method, int code_size, MonoDebugMethodJitInfo
                if (il_offset == -1 || il_offset == prev_il_offset)
                        continue;
                prev_il_offset = il_offset;
-               loc = mono_debug_symfile_lookup_location (minfo, il_offset);
+               loc = mono_debug_method_lookup_location (minfo, il_offset);
                if (!(loc && loc->source_file))
                        continue;
                if (loc->row == prev_line) {
-                       mono_debug_symfile_free_location (loc);
+                       mono_debug_free_source_location (loc);
                        continue;
                }
                prev_line = loc->row;
@@ -5344,7 +5349,7 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
                                options = "";
                        prologue_end = TRUE;
                        fprintf (acfg->fp, ".loc %d %d 0%s\n", findex, loc->row, options);
-                       mono_debug_symfile_free_location (loc);
+                       mono_debug_free_source_location (loc);
                }
 
                skip = FALSE;
@@ -7222,7 +7227,11 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                } else if (str_begins_with (arg, "data-outfile=")) {
                        opts->data_outfile = g_strdup (arg + strlen ("data-outfile="));
                } else if (str_begins_with (arg, "profile=")) {
-                       opts->profile_file = g_strdup (arg + strlen ("profile="));
+                       opts->profile_files = g_list_append (opts->profile_files, g_strdup (arg + strlen ("profile=")));
+               } else if (!strcmp (arg, "profile-only")) {
+                       opts->profile_only = TRUE;
+               } else if (!strcmp (arg, "verbose")) {
+                       opts->verbose = TRUE;
                } else if (str_begins_with (arg, "help") || str_begins_with (arg, "?")) {
                        printf ("Supported options for --aot:\n");
                        printf ("    outfile=\n");
@@ -7255,6 +7264,7 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                        printf ("    stats\n");
                        printf ("    dump\n");
                        printf ("    info\n");
+                       printf ("    verbose\n");
                        printf ("    help/?\n");
                        exit (0);
                } else {
@@ -7544,6 +7554,9 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
        if (method->wrapper_type == MONO_WRAPPER_COMINTEROP)
                return;
 
+       if (acfg->aot_opts.profile_only && !method->is_inflated && !g_hash_table_lookup (acfg->profile_methods, method))
+               return;
+
        InterlockedIncrement (&acfg->stats.mcount);
 
 #if 0
@@ -7879,14 +7892,13 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
 static mono_thread_start_return_t WINAPI
 compile_thread_main (gpointer user_data)
 {
-       MonoDomain *domain = ((MonoDomain **)user_data) [0];
-       MonoAotCompile *acfg = ((MonoAotCompile **)user_data) [1];
-       GPtrArray *methods = ((GPtrArray **)user_data) [2];
+       MonoAotCompile *acfg = ((MonoAotCompile **)user_data) [0];
+       GPtrArray *methods = ((GPtrArray **)user_data) [1];
        int i;
 
        MonoError error;
-       MonoThread *thread = mono_thread_attach (domain);
-       mono_thread_set_name_internal (thread->internal_thread, mono_string_new (mono_get_root_domain (), "AOT compiler"), TRUE, &error);
+       MonoInternalThread *internal = mono_thread_internal_current ();
+       mono_thread_set_name_internal (internal, mono_string_new (mono_domain_get (), "AOT compiler"), TRUE, FALSE, &error);
        mono_error_assert_ok (&error);
 
        for (i = 0; i < methods->len; ++i)
@@ -8188,7 +8200,7 @@ execute_system (const char * command)
 {
        int status = 0;
 
-#if HOST_WIN32
+#if defined(HOST_WIN32) && defined(HAVE_SYSTEM)
        // We need an extra set of quotes around the whole command to properly handle commands 
        // with spaces since internally the command is called through "cmd /c.
        char * quoted_command = g_strdup_printf ("\"%s\"", command);
@@ -9856,6 +9868,9 @@ compile_methods (MonoAotCompile *acfg)
                        methods [i] = (MonoMethod *)g_ptr_array_index (acfg->methods, i);
                i = 0;
                while (i < methods_len) {
+                       MonoError error;
+                       MonoInternalThread *thread;
+
                        frag = g_ptr_array_new ();
                        for (j = 0; j < len; ++j) {
                                if (i < methods_len) {
@@ -9865,11 +9880,13 @@ compile_methods (MonoAotCompile *acfg)
                        }
 
                        user_data = g_new0 (gpointer, 3);
-                       user_data [0] = mono_domain_get ();
-                       user_data [1] = acfg;
-                       user_data [2] = frag;
+                       user_data [0] = acfg;
+                       user_data [1] = frag;
                        
-                       thread_handle = mono_threads_create_thread (compile_thread_main, (gpointer) user_data, NULL, NULL);
+                       thread = mono_thread_create_internal (mono_domain_get (), compile_thread_main, (gpointer) user_data, MONO_THREAD_CREATE_FLAGS_NONE, &error);
+                       mono_error_assert_ok (&error);
+
+                       thread_handle = mono_threads_open_thread_handle (thread->handle);
                        g_ptr_array_add (threads, thread_handle);
                }
                g_free (methods);
@@ -10314,7 +10331,8 @@ load_profile_file (MonoAotCompile *acfg, char *filename)
                }
        }
 
-       acfg->profile_data = data;
+       fclose (infile);
+       acfg->profile_data = g_list_append (acfg->profile_data, data);
 }
 
 static void
@@ -10372,9 +10390,8 @@ resolve_class (ClassProfileData *cdata)
  * Resolve the profile data to the corresponding loaded classes/methods etc. if possible.
  */
 static void
-resolve_profile_data (MonoAotCompile *acfg)
+resolve_profile_data (MonoAotCompile *acfg, ProfileData *data)
 {
-       ProfileData *data = acfg->profile_data;
        GHashTableIter iter;
        gpointer key, value;
        int i;
@@ -10404,8 +10421,11 @@ resolve_profile_data (MonoAotCompile *acfg)
        while (g_hash_table_iter_next (&iter, &key, &value)) {
                ClassProfileData *cdata = (ClassProfileData*)value;
 
-               if (!cdata->image->image)
+               if (!cdata->image->image) {
+                       if (acfg->aot_opts.verbose)
+                               printf ("Unable to load class '%s.%s' because its image '%s' is not loaded.\n", cdata->ns, cdata->name, cdata->image->name);
                        continue;
+               }
 
                resolve_class (cdata);
                /*
@@ -10424,8 +10444,11 @@ resolve_profile_data (MonoAotCompile *acfg)
 
                resolve_class (mdata->klass);
                klass = mdata->klass->klass;
-               if (!klass)
+               if (!klass) {
+                       if (acfg->aot_opts.verbose)
+                               printf ("Unable to load method '%s' because its class '%s.%s' is not loaded.\n", mdata->name, mdata->klass->ns, mdata->klass->name);
                        continue;
+               }
                miter = NULL;
                while ((m = mono_class_get_methods (klass, &miter))) {
                        MonoError error;
@@ -10459,11 +10482,16 @@ resolve_profile_data (MonoAotCompile *acfg)
                        gboolean match = !strcmp (sig_str, mdata->signature);
                        g_free (sig_str);
                        if (!match)
+
                                continue;
                        //printf ("%s\n", mono_method_full_name (m, 1));
                        mdata->method = m;
                        break;
                }
+               if (!mdata->method) {
+                       if (acfg->aot_opts.verbose)
+                               printf ("Unable to load method '%s' from class '%s', not found.\n", mdata->name, mono_class_full_name (klass));
+               }
        }
 }
 
@@ -10499,9 +10527,8 @@ is_local_inst (MonoGenericInst *inst, MonoImage *image)
 }
 
 static void
-add_profile_instances (MonoAotCompile *acfg)
+add_profile_instances (MonoAotCompile *acfg, ProfileData *data)
 {
-       ProfileData *data = acfg->profile_data;
        GHashTableIter iter;
        gpointer key, value;
        int count = 0;
@@ -10509,6 +10536,23 @@ add_profile_instances (MonoAotCompile *acfg)
        if (!data)
                return;
 
+       if (acfg->aot_opts.profile_only) {
+               /* Add methods referenced by the profile */
+               g_hash_table_iter_init (&iter, data->methods);
+               while (g_hash_table_iter_next (&iter, &key, &value)) {
+                       MethodProfileData *mdata = (MethodProfileData*)value;
+                       MonoMethod *m = mdata->method;
+
+                       if (!m)
+                               continue;
+                       if (m->is_inflated)
+                               continue;
+                       add_extra_method (acfg, m);
+                       g_hash_table_insert (acfg->profile_methods, m, m);
+                       count ++;
+               }
+       }
+
        /*
         * Add method instances 'related' to this assembly to the AOT image.
         */
@@ -10596,6 +10640,7 @@ acfg_create (MonoAssembly *ass, guint32 opts)
        acfg->plt_entry_debug_sym_cache = g_hash_table_new (g_str_hash, g_str_equal);
        acfg->gsharedvt_in_signatures = g_hash_table_new ((GHashFunc)mono_signature_hash, (GEqualFunc)mono_metadata_signature_equal);
        acfg->gsharedvt_out_signatures = g_hash_table_new ((GHashFunc)mono_signature_hash, (GEqualFunc)mono_metadata_signature_equal);
+       acfg->profile_methods = g_hash_table_new (NULL, NULL);
        mono_os_mutex_init_recursive (&acfg->mutex);
 
        init_got_info (&acfg->got_info);
@@ -11031,8 +11076,13 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                }
        }
 
-       if (acfg->aot_opts.profile_file)
-               load_profile_file (acfg, acfg->aot_opts.profile_file);
+       if (acfg->aot_opts.profile_files) {
+               GList *l;
+
+               for (l = acfg->aot_opts.profile_files; l; l = l->next) {
+                       load_profile_file (acfg, (char*)l->data);
+               }
+       }
 
        {
                int method_index;
@@ -11101,9 +11151,14 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        if (!res)
                return 1;
 
-       resolve_profile_data (acfg);
+       {
+               GList *l;
 
-       add_profile_instances (acfg);
+               for (l = acfg->profile_data; l; l = l->next)
+                       resolve_profile_data (acfg, (ProfileData*)l->data);
+               for (l = acfg->profile_data; l; l = l->next)
+                       add_profile_instances (acfg, (ProfileData*)l->data);
+       }
 
        acfg->cfgs_size = acfg->methods->len + 32;
        acfg->cfgs = g_new0 (MonoCompile*, acfg->cfgs_size);