#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"
char *outfile;
char *llvm_outfile;
char *data_outfile;
- char *profile_file;
+ GList *profile_files;
gboolean save_temps;
gboolean write_symbols;
gboolean metadata_only;
int nrgctx_fetch_trampolines;
gboolean print_skipped_methods;
gboolean stats;
+ gboolean verbose;
char *tool_prefix;
char *ld_flags;
char *mtriple;
char *instances_logfile_path;
char *logfile;
gboolean dump_json;
+ gboolean profile_only;
} MonoAotOptions;
typedef enum {
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;
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, ...)
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);
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;
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;
} 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");
printf (" stats\n");
printf (" dump\n");
printf (" info\n");
+ printf (" verbose\n");
printf (" help/?\n");
exit (0);
} else {
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
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)
{
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);
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) {
}
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);
}
}
- acfg->profile_data = data;
+ fclose (infile);
+ acfg->profile_data = g_list_append (acfg->profile_data, data);
}
static void
* 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;
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);
/*
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;
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));
+ }
}
}
}
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;
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.
*/
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);
}
}
- 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;
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);