gboolean dwarf_debug;
gboolean soft_debug;
gboolean log_generics;
+ gboolean log_instances;
gboolean direct_pinvoke;
gboolean direct_icalls;
gboolean no_direct_calls;
gboolean autoreg;
char *mtriple;
char *llvm_path;
+ char *instances_logfile_path;
} MonoAotOptions;
typedef struct MonoAotStats {
int objc_selector_index, objc_selector_index_2;
GPtrArray *objc_selectors;
GHashTable *objc_selector_to_index;
+ FILE *instances_logfile;
} MonoAotCompile;
typedef struct {
* Use gsharedvt for generic collections with vtype arguments to avoid code blowup.
* Enable this only for some classes since gsharedvt might not support all methods.
*/
- if ((acfg->opts & MONO_OPT_GSHAREDVT) && klass->image == mono_defaults.corlib && klass->generic_class && klass->generic_class->context.class_inst && is_vt_inst (klass->generic_class->context.class_inst) && (!strcmp (klass->name, "Dictionary`2") || !strcmp (klass->name, "List`1")))
+ if ((acfg->opts & MONO_OPT_GSHAREDVT) && klass->image == mono_defaults.corlib && klass->generic_class && klass->generic_class->context.class_inst && is_vt_inst (klass->generic_class->context.class_inst) &&
+ (!strcmp (klass->name, "Dictionary`2") || !strcmp (klass->name, "List`1") || !strcmp (klass->name, "ReadOnlyCollection`1")))
use_gsharedvt = TRUE;
iter = NULL;
opts->no_instances = TRUE;
} else if (str_begins_with (arg, "log-generics")) {
opts->log_generics = TRUE;
+ } else if (str_begins_with (arg, "log-instances=")) {
+ opts->log_instances = TRUE;
+ opts->instances_logfile_path = g_strdup (arg + strlen ("log-instances="));
+ } else if (str_begins_with (arg, "log-instances")) {
+ opts->log_instances = TRUE;
} else if (str_begins_with (arg, "mtriple=")) {
opts->mtriple = g_strdup (arg + strlen ("mtriple="));
} else if (str_begins_with (arg, "llvm-path=")) {
return;
}
+ if (method->is_inflated && acfg->aot_opts.log_instances) {
+ if (acfg->instances_logfile)
+ fprintf (acfg->instances_logfile, "%s ### %d\n", mono_method_full_name (method, TRUE), cfg->code_size);
+ else
+ printf ("%s ### %d\n", mono_method_full_name (method, TRUE), cfg->code_size);
+ }
+
/* Adds generic instances referenced by this method */
/*
* The depth is used to avoid infinite loops when generic virtual recursion is
method = cfg->orig_method;
if (acfg->aot_opts.full_aot && cfg->orig_method->klass->valuetype) {
+ int call_size;
+
index = get_method_index (acfg, method);
sprintf (symbol, "ut_%d", index);
emit_int32 (acfg, index);
if (acfg->direct_method_addresses) {
- emit_unset_mode (acfg);
- if (acfg->thumb_mixed && cfg->compile_llvm)
- fprintf (acfg->fp, "\n\tblx %s\n", symbol);
- else
- fprintf (acfg->fp, "\n\tbl %s\n", symbol);
+#ifdef MONO_ARCH_AOT_SUPPORTED
+ arch_emit_direct_call (acfg, symbol, FALSE, acfg->thumb_mixed && cfg->compile_llvm, NULL, &call_size);
+#endif
} else {
emit_symbol_diff (acfg, symbol, acfg->methods_symbol, 0);
}
if (acfg->aot_opts.full_aot)
acfg->flags |= MONO_AOT_FILE_FLAG_FULL_AOT;
+ if (acfg->aot_opts.instances_logfile_path) {
+ acfg->instances_logfile = fopen (acfg->aot_opts.instances_logfile_path, "w");
+ if (!acfg->instances_logfile) {
+ fprintf (stderr, "Unable to create logfile: '%s'.\n", acfg->aot_opts.instances_logfile_path);
+ exit (1);
+ }
+ }
+
load_profile_files (acfg);
acfg->num_trampolines [MONO_AOT_TRAMP_SPECIFIC] = acfg->aot_opts.full_aot ? acfg->aot_opts.ntrampolines : 0;