X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Faot-compiler.c;h=933ecfaf395cab7cbbaeced533c87631f4669cc7;hb=f03a1b538bfb0d9be810688e8713731e122320b5;hp=cf80a74070f7288e5974752117cdf0ab12ca7351;hpb=1cab4433d38987c2fdc24a323e04d27bf5bfd66f;p=mono.git diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index cf80a74070f..933ecfaf395 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -99,7 +99,7 @@ typedef struct MonoAotOptions { gboolean write_symbols; gboolean metadata_only; gboolean bind_to_runtime_version; - gboolean full_aot; + MonoAotMode mode; gboolean no_dlsym; gboolean static_link; gboolean asm_only; @@ -130,6 +130,7 @@ typedef struct MonoAotOptions { gboolean autoreg; char *mtriple; char *llvm_path; + char *temp_path; char *instances_logfile_path; char *logfile; gboolean dump_json; @@ -3066,7 +3067,6 @@ is_plt_patch (MonoJumpInfo *patch_info) case MONO_PATCH_INFO_ICALL_ADDR: case MONO_PATCH_INFO_CLASS_INIT: case MONO_PATCH_INFO_RGCTX_FETCH: - case MONO_PATCH_INFO_GENERIC_CLASS_INIT: case MONO_PATCH_INFO_MONITOR_ENTER: case MONO_PATCH_INFO_MONITOR_ENTER_V4: case MONO_PATCH_INFO_MONITOR_EXIT: @@ -3211,6 +3211,16 @@ add_method_with_index (MonoAotCompile *acfg, MonoMethod *method, int index, gboo g_ptr_array_add (acfg->extra_methods, method); } +static gboolean +prefer_gsharedvt_method (MonoAotCompile *acfg, MonoMethod *method) +{ + /* One instantiation with valuetypes is generated for each async method */ + if (method->klass->image == mono_defaults.corlib && (!strcmp (method->klass->name, "AsyncMethodBuilderCore") || !strcmp (method->klass->name, "AsyncVoidMethodBuilder"))) + return TRUE; + else + return FALSE; +} + static guint32 get_method_index (MonoAotCompile *acfg, MonoMethod *method) { @@ -3253,6 +3263,9 @@ add_extra_method_with_depth (MonoAotCompile *acfg, MonoMethod *method, int depth { if (mono_method_is_generic_sharable_full (method, FALSE, TRUE, FALSE)) method = mini_get_shared_method (method); + else if ((acfg->opts & MONO_OPT_GSHAREDVT) && prefer_gsharedvt_method (acfg, method) && mono_method_is_generic_sharable_full (method, FALSE, FALSE, TRUE)) + /* Use the gsharedvt version */ + return; if (acfg->aot_opts.log_generics) aot_printf (acfg, "%*sAdding method %s.\n", depth, "", mono_method_full_name (method, TRUE)); @@ -3559,7 +3572,12 @@ add_wrappers (MonoAotCompile *acfg) /* Managed Allocators */ nallocators = mono_gc_get_managed_allocator_types (); for (i = 0; i < nallocators; ++i) { - m = mono_gc_get_managed_allocator_by_type (i); + m = mono_gc_get_managed_allocator_by_type (i, TRUE); + if (m) + add_method (acfg, m); + } + for (i = 0; i < nallocators; ++i) { + m = mono_gc_get_managed_allocator_by_type (i, FALSE); if (m) add_method (acfg, m); } @@ -3655,8 +3673,18 @@ add_wrappers (MonoAotCompile *acfg) for (j = 0; j < cattr->num_attrs; ++j) if (cattr->attrs [j].ctor && (!strcmp (cattr->attrs [j].ctor->klass->name, "MonoNativeFunctionWrapperAttribute") || !strcmp (cattr->attrs [j].ctor->klass->name, "UnmanagedFunctionPointerAttribute"))) break; - if (j < cattr->num_attrs) - add_method (acfg, mono_marshal_get_native_func_wrapper_aot (klass)); + if (j < cattr->num_attrs) { + MonoMethod *invoke; + MonoMethod *wrapper; + MonoMethod *del_invoke; + + /* Add wrappers needed by mono_ftnptr_to_delegate () */ + invoke = mono_get_delegate_invoke (klass); + wrapper = mono_marshal_get_native_func_wrapper_aot (klass); + del_invoke = mono_marshal_get_delegate_invoke_internal (invoke, FALSE, TRUE, wrapper); + add_method (acfg, wrapper); + add_method (acfg, del_invoke); + } } } else if ((acfg->opts & MONO_OPT_GSHAREDVT) && klass->generic_container) { MonoError error; @@ -3972,13 +4000,19 @@ method_has_type_vars (MonoMethod *method) return FALSE; } +static +gboolean mono_aot_mode_is_full (MonoAotOptions *opts) +{ + return opts->mode == MONO_AOT_MODE_FULL; +} + static void add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth, const char *ref); static void add_generic_class (MonoAotCompile *acfg, MonoClass *klass, gboolean force, const char *ref) { /* This might lead to a huge code blowup so only do it if neccesary */ - if (!acfg->aot_opts.full_aot && !force) + if (!mono_aot_mode_is_full (&acfg->aot_opts) && !force) return; add_generic_class_with_depth (acfg, klass, 0, ref); @@ -4983,7 +5017,9 @@ get_debug_sym (MonoMethod *method, const char *prefix, GHashTable *cache) memcpy (name2, prefix, strlen (prefix)); j = strlen (prefix); for (i = 0; i < len; ++i) { - if (isalnum (name1 [i])) { + if (i == 0 && name1 [0] >= '0' && name1 [0] <= '9') { + name2 [j ++] = '_'; + } else if (isalnum (name1 [i])) { name2 [j ++] = name1 [i]; } else if (name1 [i] == ' ' && name1 [i + 1] == '(' && name1 [i + 2] == ')') { i += 2; @@ -5230,7 +5266,6 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint encode_patch (acfg, entry->data, p, &p); break; } - case MONO_PATCH_INFO_GENERIC_CLASS_INIT: case MONO_PATCH_INFO_MONITOR_ENTER: case MONO_PATCH_INFO_MONITOR_ENTER_V4: case MONO_PATCH_INFO_MONITOR_EXIT: @@ -5846,9 +5881,6 @@ get_plt_entry_debug_sym (MonoAotCompile *acfg, MonoJumpInfo *ji, GHashTable *cac case MONO_PATCH_INFO_JIT_ICALL_ADDR: debug_sym = g_strdup_printf ("%s_jit_icall_native_%s", prefix, ji->data.name); break; - case MONO_PATCH_INFO_GENERIC_CLASS_INIT: - debug_sym = g_strdup_printf ("%s_generic_class_init", prefix); - break; default: break; } @@ -6112,7 +6144,7 @@ emit_trampolines (MonoAotCompile *acfg) int tramp_type; #endif - if (!acfg->aot_opts.full_aot) + if (!mono_aot_mode_is_full (&acfg->aot_opts)) return; g_assert (acfg->image->assembly); @@ -6156,9 +6188,6 @@ emit_trampolines (MonoAotCompile *acfg) emit_trampoline (acfg, acfg->got_offset, info); #endif - mono_arch_create_generic_class_init_trampoline (&info, TRUE); - emit_trampoline (acfg, acfg->got_offset, info); - /* Emit the exception related code pieces */ mono_arch_get_restore_context (&info, TRUE); emit_trampoline (acfg, acfg->got_offset, info); @@ -6427,6 +6456,21 @@ add_readonly_value (MonoAotOptions *opts, const char *val) readonly_values = rdv; } +static gchar * +clean_path (gchar * path) +{ + if (!path) + return NULL; + + if (g_str_has_suffix (path, G_DIR_SEPARATOR_S)) + return path; + + gchar *clean = g_strconcat (path, G_DIR_SEPARATOR_S, NULL); + g_free (path); + + return clean; +} + static void mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts) { @@ -6440,6 +6484,8 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts) opts->outfile = g_strdup (arg + strlen ("outfile=")); } else if (str_begins_with (arg, "llvm-outfile=")) { opts->llvm_outfile = g_strdup (arg + strlen ("llvm-outfile=")); + } else if (str_begins_with (arg, "temp-path=")) { + opts->temp_path = clean_path (g_strdup (arg + strlen ("temp-path="))); } else if (str_begins_with (arg, "save-temps")) { opts->save_temps = TRUE; } else if (str_begins_with (arg, "keep-temps")) { @@ -6453,7 +6499,9 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts) } else if (str_begins_with (arg, "bind-to-runtime-version")) { opts->bind_to_runtime_version = TRUE; } else if (str_begins_with (arg, "full")) { - opts->full_aot = TRUE; + opts->mode = MONO_AOT_MODE_FULL; + } else if (str_begins_with (arg, "hybrid")) { + opts->mode = MONO_AOT_MODE_HYBRID; } else if (str_begins_with (arg, "threads=")) { opts->nthreads = atoi (arg + strlen ("threads=")); } else if (str_begins_with (arg, "static")) { @@ -6511,12 +6559,7 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts) } else if (str_begins_with (arg, "mtriple=")) { opts->mtriple = g_strdup (arg + strlen ("mtriple=")); } else if (str_begins_with (arg, "llvm-path=")) { - opts->llvm_path = g_strdup (arg + strlen ("llvm-path=")); - if (!g_str_has_suffix (opts->llvm_path, G_DIR_SEPARATOR_S)) { - gchar *old = opts->llvm_path; - opts->llvm_path = g_strconcat (opts->llvm_path, G_DIR_SEPARATOR_S, NULL); - g_free (old); - } + opts->llvm_path = clean_path (g_strdup (arg + strlen ("llvm-path="))); } else if (!strcmp (arg, "llvm")) { opts->llvm = TRUE; } else if (str_begins_with (arg, "readonly-value=")) { @@ -6532,6 +6575,8 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts) printf ("Supported options for --aot:\n"); printf (" outfile=\n"); printf (" llvm-outfile=\n"); + printf (" llvm-path=\n"); + printf (" temp-path=\n"); printf (" save-temps\n"); printf (" keep-temps\n"); printf (" write-symbols\n"); @@ -6758,7 +6803,7 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method) * does not need to support them by creating a fake GOT etc. */ flags = JIT_FLAG_AOT; - if (acfg->aot_opts.full_aot) + if (mono_aot_mode_is_full (&acfg->aot_opts)) flags |= JIT_FLAG_FULL_AOT; if (acfg->llvm) flags |= JIT_FLAG_LLVM; @@ -6875,7 +6920,7 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method) mono_method_is_generic_sharable_full (m, FALSE, FALSE, FALSE)) && !method_has_type_vars (m)) { if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) { - if (acfg->aot_opts.full_aot) + if (mono_aot_mode_is_full (&acfg->aot_opts)) add_extra_method_with_depth (acfg, mono_marshal_get_native_wrapper (m, TRUE, TRUE), depth + 1); } else { add_extra_method_with_depth (acfg, m, depth + 1); @@ -7405,7 +7450,7 @@ emit_code (MonoAotCompile *acfg) method = cfg->orig_method; /* Emit unbox trampoline */ - if (acfg->aot_opts.full_aot && cfg->orig_method->klass->valuetype) { + if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype) { sprintf (symbol, "ut_%d", get_method_index (acfg, method)); emit_section_change (acfg, ".text", 0); @@ -7500,7 +7545,7 @@ emit_code (MonoAotCompile *acfg) method = cfg->orig_method; - if (acfg->aot_opts.full_aot && cfg->orig_method->klass->valuetype) { + if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype) { index = get_method_index (acfg, method); emit_int32 (acfg, index); @@ -7530,7 +7575,7 @@ emit_code (MonoAotCompile *acfg) method = cfg->orig_method; - if (acfg->aot_opts.full_aot && cfg->orig_method->klass->valuetype) { + if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype) { #ifdef MONO_ARCH_AOT_SUPPORTED int call_size; @@ -8465,11 +8510,6 @@ emit_file_info (MonoAotCompile *acfg) emit_pointer (acfg, NULL); emit_pointer (acfg, NULL); } - if (acfg->thumb_mixed) { - emit_pointer (acfg, "thumb_end"); - } else { - emit_pointer (acfg, NULL); - } if (acfg->aot_opts.static_link) { emit_pointer (acfg, "globals"); } else { @@ -8651,7 +8691,7 @@ collect_methods (MonoAotCompile *acfg) /* Load all methods eagerly to skip the slower lazy loading code */ mono_class_setup_methods (method->klass); - if (acfg->aot_opts.full_aot && method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) { + if (mono_aot_mode_is_full (&acfg->aot_opts) && method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) { /* Compile the wrapper instead */ /* We do this here instead of add_wrappers () because it is easy to do it here */ MonoMethod *wrapper = mono_marshal_get_native_wrapper (method, check_for_pending_exc, TRUE); @@ -8708,7 +8748,7 @@ collect_methods (MonoAotCompile *acfg) add_generic_instances (acfg); - if (acfg->aot_opts.full_aot) + if (mono_aot_mode_is_full (&acfg->aot_opts)) add_wrappers (acfg); return TRUE; } @@ -8821,7 +8861,7 @@ compile_asm (MonoAotCompile *acfg) #define LD_NAME "gcc -shared --dll" #elif defined(TARGET_X86) && defined(TARGET_MACH) && !defined(__native_client_codegen__) #define LD_NAME "clang -m32 -dynamiclib" -#elif defined(TARGET_ARM) +#elif defined(TARGET_ARM) && !defined(TARGET_ANDROID) #define LD_NAME "gcc --shared" #endif @@ -8918,7 +8958,7 @@ compile_asm (MonoAotCompile *acfg) * gas generates 'mapping symbols' each time code and data is mixed, which * happens a lot in emit_and_reloc_code (), so we need to get rid of them. */ - command = g_strdup_printf ("%sstrip --strip-symbol=\\$a --strip-symbol=\\$d %s", tool_prefix, tmp_outfile_name); + command = g_strdup_printf ("\"%sstrip\" --strip-symbol=\\$a --strip-symbol=\\$d %s", tool_prefix, tmp_outfile_name); aot_printf (acfg, "Stripping the binary: %s\n", command); if (execute_system (command) != 0) { g_free (tmp_outfile_name); @@ -9258,7 +9298,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) aot_printf (acfg, "Mono Ahead of Time compiler - compiling assembly %s\n", image->name); #ifndef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES - if (acfg->aot_opts.full_aot) { + if (mono_aot_mode_is_full (&acfg->aot_opts)) { aot_printerrf (acfg, "--aot=full is not supported on this platform.\n"); return 1; } @@ -9306,11 +9346,17 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) * Emit all LLVM code into a separate assembly/object file and link with it * normally. */ - if (!acfg->aot_opts.asm_only) + if (!acfg->aot_opts.asm_only) { acfg->llvm_owriter = TRUE; + } else if (acfg->aot_opts.llvm_outfile) { + int len = strlen (acfg->aot_opts.llvm_outfile); + + if (len >= 2 && acfg->aot_opts.llvm_outfile [len - 2] == '.' && acfg->aot_opts.llvm_outfile [len - 1] == 'o') + acfg->llvm_owriter = TRUE; + } } - if (acfg->aot_opts.full_aot) + if (mono_aot_mode_is_full (&acfg->aot_opts)) acfg->flags |= MONO_AOT_FILE_FLAG_FULL_AOT; if (acfg->aot_opts.instances_logfile_path) { @@ -9323,20 +9369,23 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) load_profile_files (acfg); - acfg->num_trampolines [MONO_AOT_TRAMP_SPECIFIC] = acfg->aot_opts.full_aot ? acfg->aot_opts.ntrampolines : 0; + acfg->num_trampolines [MONO_AOT_TRAMP_SPECIFIC] = mono_aot_mode_is_full (&acfg->aot_opts) ? acfg->aot_opts.ntrampolines : 0; #ifdef MONO_ARCH_GSHARED_SUPPORTED - acfg->num_trampolines [MONO_AOT_TRAMP_STATIC_RGCTX] = acfg->aot_opts.full_aot ? acfg->aot_opts.nrgctx_trampolines : 0; + acfg->num_trampolines [MONO_AOT_TRAMP_STATIC_RGCTX] = mono_aot_mode_is_full (&acfg->aot_opts) ? acfg->aot_opts.nrgctx_trampolines : 0; #endif - acfg->num_trampolines [MONO_AOT_TRAMP_IMT_THUNK] = acfg->aot_opts.full_aot ? acfg->aot_opts.nimt_trampolines : 0; + acfg->num_trampolines [MONO_AOT_TRAMP_IMT_THUNK] = mono_aot_mode_is_full (&acfg->aot_opts) ? acfg->aot_opts.nimt_trampolines : 0; #ifdef MONO_ARCH_GSHAREDVT_SUPPORTED if (acfg->opts & MONO_OPT_GSHAREDVT) - acfg->num_trampolines [MONO_AOT_TRAMP_GSHAREDVT_ARG] = acfg->aot_opts.full_aot ? acfg->aot_opts.ngsharedvt_arg_trampolines : 0; + acfg->num_trampolines [MONO_AOT_TRAMP_GSHAREDVT_ARG] = mono_aot_mode_is_full (&acfg->aot_opts) ? acfg->aot_opts.ngsharedvt_arg_trampolines : 0; #endif acfg->temp_prefix = mono_img_writer_get_temp_label_prefix (NULL); arch_init (acfg); + if (acfg->llvm && acfg->thumb_mixed) + acfg->flags |= MONO_AOT_FILE_FLAG_LLVM_THUMB; + acfg->assembly_name_sym = g_strdup (acfg->image->assembly->aname.name); /* Get rid of characters which cannot occur in symbols */ for (p = acfg->assembly_name_sym; *p; ++p) { @@ -9356,7 +9405,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) acfg->method_index = 1; - if (acfg->aot_opts.full_aot) + if (mono_aot_mode_is_full (&acfg->aot_opts)) mono_set_partial_sharing_supported (TRUE); res = collect_methods (acfg); @@ -9434,6 +9483,10 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) } g_assert (acfg->aot_opts.llvm_outfile); acfg->llvm_sfile = g_strdup (acfg->aot_opts.llvm_outfile); + if (acfg->llvm_owriter) + acfg->llvm_ofile = g_strdup (acfg->aot_opts.llvm_outfile); + else + acfg->llvm_sfile = g_strdup (acfg->aot_opts.llvm_outfile); } else { acfg->tmpbasename = g_strdup_printf ("%s", "temp"); acfg->tmpfname = g_strdup_printf ("%s.s", acfg->tmpbasename); @@ -9526,21 +9579,6 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) if (acfg->dwarf) mono_dwarf_writer_emit_base_info (acfg->dwarf, g_path_get_basename (acfg->image->name), mono_unwind_get_cie_program ()); - if (acfg->thumb_mixed) { - char symbol [256]; - /* - * This global symbol marks the end of THUMB code, and the beginning of ARM - * code generated by our JIT. - */ - sprintf (symbol, "thumb_end"); - emit_section_change (acfg, ".text", 0); - emit_alignment_code (acfg, 8); - emit_label (acfg, symbol); - emit_zero_bytes (acfg, 16); - - fprintf (acfg->fp, ".arm\n"); - } - emit_code (acfg); emit_info (acfg);