X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Faot-compiler.c;h=28944ce9843305c2fd6364bf1d4efc01ed15c378;hb=8219a5b7639b02781dd1d49bd872d8382bfd7851;hp=6431b0140e1cc01b3630cce929b03b53c340de02;hpb=a957d74bcb0a80e84c88074801ed3a99905b51e6;p=mono.git diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index 6431b0140e1..28944ce9843 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -57,7 +57,7 @@ #include #include #include -#include +#include #include #include #include @@ -100,6 +100,7 @@ typedef struct MonoAotOptions { int nthreads; int ntrampolines; int nrgctx_trampolines; + int nimt_trampolines; gboolean print_skipped_methods; gboolean stats; char *tool_prefix; @@ -1196,32 +1197,6 @@ arch_emit_autoreg (MonoAotCompile *acfg, char *symbol) #endif } -/* - * mono_arch_get_cie_program: - * - * Get the unwind bytecode for the DWARF CIE. - */ -GSList* -mono_arch_get_cie_program (void) -{ -#ifdef TARGET_AMD64 - GSList *l = NULL; - - mono_add_unwind_op_def_cfa (l, (guint8*)NULL, (guint8*)NULL, AMD64_RSP, 8); - mono_add_unwind_op_offset (l, (guint8*)NULL, (guint8*)NULL, AMD64_RIP, -8); - - return l; -#elif defined(TARGET_POWERPC) - GSList *l = NULL; - - mono_add_unwind_op_def_cfa (l, (guint8*)NULL, (guint8*)NULL, ppc_r1, 0); - - return l; -#else - return NULL; -#endif -} - /* END OF ARCH SPECIFIC CODE */ static guint32 @@ -1618,7 +1593,7 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 case MONO_WRAPPER_LDFLDA: case MONO_WRAPPER_STFLD: case MONO_WRAPPER_ISINST: { - MonoClass *proxy_class = mono_marshal_wrapper_info_from_wrapper (method); + MonoClass *proxy_class = mono_marshal_get_wrapper_info (method); encode_klass_ref (acfg, proxy_class, p, &p); break; } @@ -1626,11 +1601,14 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 case MONO_WRAPPER_STFLD_REMOTE: break; case MONO_WRAPPER_ALLOC: { - int alloc_type = mono_gc_get_managed_allocator_type (method); - g_assert (alloc_type != -1); - encode_value (alloc_type, p, &p); + AllocatorWrapperInfo *info = mono_marshal_get_wrapper_info (method); + + g_assert (info->alloc_type != -1); + encode_value (info->alloc_type, p, &p); break; } + case MONO_WRAPPER_WRITE_BARRIER: + break; case MONO_WRAPPER_STELEMREF: break; case MONO_WRAPPER_UNKNOWN: @@ -1654,7 +1632,7 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 } case MONO_WRAPPER_MANAGED_TO_MANAGED: if (!strcmp (method->name, "ElementAddr")) { - ElementAddrWrapperInfo *info = mono_marshal_wrapper_info_from_wrapper (method); + ElementAddrWrapperInfo *info = mono_marshal_get_wrapper_info (method); g_assert (info); encode_value (MONO_AOT_WRAPPER_ELEMENT_ADDR, p, &p); @@ -1840,11 +1818,12 @@ get_got_offset (MonoAotCompile *acfg, MonoJumpInfo *ji) if (got_offset) return got_offset - 1; - g_assert (!acfg->final_got_size); - got_offset = acfg->got_offset; acfg->got_offset ++; + if (acfg->final_got_size) + g_assert (got_offset < acfg->final_got_size); + acfg->stats.got_slots ++; acfg->stats.got_slot_types [ji->type] ++; @@ -2381,7 +2360,7 @@ add_generic_class (MonoAotCompile *acfg, MonoClass *klass) iter = NULL; while ((method = mono_class_get_methods (klass, &iter))) { - if (mono_method_is_generic_sharable_impl (method, FALSE)) + if (mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE)) /* Already added */ continue; @@ -2502,18 +2481,98 @@ add_generic_instances (MonoAotCompile *acfg) token = MONO_TOKEN_METHOD_SPEC | (i + 1); method = mono_get_method (acfg->image, token, NULL); - context = mono_method_get_context (method); - if (context && ((context->class_inst && context->class_inst->is_open) || - (context->method_inst && context->method_inst->is_open))) + if (method->klass->image != acfg->image) continue; - if (method->klass->image != acfg->image) + context = mono_method_get_context (method); + + if (context && ((context->class_inst && context->class_inst->is_open))) continue; - if (mono_method_is_generic_sharable_impl (method, FALSE)) - /* Already added */ + /* + * For open methods, create an instantiation which can be passed to the JIT. + * FIXME: Handle class_inst as well. + */ + if (context && context->method_inst && context->method_inst->is_open) { + MonoGenericContext shared_context; + MonoGenericInst *inst; + MonoType **type_argv; + int i; + MonoMethod *declaring_method; + gboolean supported = TRUE; + + /* Check that the context doesn't contain open constructed types */ + if (context->class_inst) { + inst = context->class_inst; + for (i = 0; i < inst->type_argc; ++i) { + if (MONO_TYPE_IS_REFERENCE (inst->type_argv [i]) || inst->type_argv [i]->type == MONO_TYPE_VAR || inst->type_argv [i]->type == MONO_TYPE_MVAR) + continue; + if (mono_class_is_open_constructed_type (inst->type_argv [i])) + supported = FALSE; + } + } + if (context->method_inst) { + inst = context->method_inst; + for (i = 0; i < inst->type_argc; ++i) { + if (MONO_TYPE_IS_REFERENCE (inst->type_argv [i]) || inst->type_argv [i]->type == MONO_TYPE_VAR || inst->type_argv [i]->type == MONO_TYPE_MVAR) + continue; + if (mono_class_is_open_constructed_type (inst->type_argv [i])) + supported = FALSE; + } + } + + if (!supported) + continue; + + memset (&shared_context, 0, sizeof (MonoGenericContext)); + + inst = context->class_inst; + if (inst) { + type_argv = g_new0 (MonoType*, inst->type_argc); + for (i = 0; i < inst->type_argc; ++i) { + if (MONO_TYPE_IS_REFERENCE (inst->type_argv [i]) || inst->type_argv [i]->type == MONO_TYPE_VAR || inst->type_argv [i]->type == MONO_TYPE_MVAR) + type_argv [i] = &mono_defaults.object_class->byval_arg; + else + type_argv [i] = inst->type_argv [i]; + } + + shared_context.class_inst = mono_metadata_get_generic_inst (inst->type_argc, type_argv); + g_free (type_argv); + } + + inst = context->method_inst; + if (inst) { + type_argv = g_new0 (MonoType*, inst->type_argc); + for (i = 0; i < inst->type_argc; ++i) { + if (MONO_TYPE_IS_REFERENCE (inst->type_argv [i]) || inst->type_argv [i]->type == MONO_TYPE_VAR || inst->type_argv [i]->type == MONO_TYPE_MVAR) + type_argv [i] = &mono_defaults.object_class->byval_arg; + else + type_argv [i] = inst->type_argv [i]; + } + + shared_context.method_inst = mono_metadata_get_generic_inst (inst->type_argc, type_argv); + g_free (type_argv); + } + + if (method->is_generic || method->klass->generic_container) + declaring_method = method; + else + declaring_method = mono_method_get_declaring_generic_method (method); + + method = mono_class_inflate_generic_method (declaring_method, &shared_context); + } + + /* + * If the method is fully sharable, it was already added in place of its + * generic definition. + */ + if (mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE)) continue; + /* + * FIXME: Partially shared methods are not shared here, so we end up with + * many identical methods. + */ add_extra_method (acfg, method); } @@ -2839,26 +2898,6 @@ emit_method_code (MonoAotCompile *acfg, MonoCompile *cfg) method_index = get_method_index (acfg, method); - /* Emit unbox trampoline */ - if (acfg->aot_opts.full_aot && cfg->orig_method->klass->valuetype && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) { - char call_target [256]; - - if (!method->wrapper_type && !method->is_inflated) { - g_assert (method->token); - sprintf (symbol, "ut_%d", mono_metadata_token_index (method->token) - 1); - } else { - sprintf (symbol, "ut_e_%d", get_method_index (acfg, method)); - } - - emit_section_change (acfg, ".text", 0); - emit_global (acfg, symbol, TRUE); - emit_label (acfg, symbol); - - sprintf (call_target, "%s", cfg->asm_symbol); - - arch_emit_unbox_trampoline (acfg, cfg->orig_method, cfg->generic_sharing_context, call_target); - } - /* Make the labels local */ sprintf (symbol, "%s", cfg->asm_symbol); @@ -3229,29 +3268,49 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg) } /* Exception table */ - if (jinfo->num_clauses) - encode_value (jinfo->num_clauses, p, &p); + if (cfg->compile_llvm) { + /* The assembly might be CIL stripped so emit the data ourselves */ + if (header->num_clauses) + encode_value (header->num_clauses, p, &p); - for (k = 0; k < jinfo->num_clauses; ++k) { - MonoJitExceptionInfo *ei = &jinfo->clauses [k]; + for (k = 0; k < header->num_clauses; ++k) { + MonoExceptionClause *clause; - encode_value (ei->flags, p, &p); - encode_value (ei->exvar_offset, p, &p); + clause = &header->clauses [k]; - if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) - encode_value ((gint)((guint8*)ei->data.filter - code), p, &p); - else { - if (ei->data.catch_class) { + encode_value (clause->flags, p, &p); + if (clause->data.catch_class) { encode_value (1, p, &p); - encode_klass_ref (acfg, ei->data.catch_class, p, &p); + encode_klass_ref (acfg, clause->data.catch_class, p, &p); } else { encode_value (0, p, &p); } } + } else { + if (jinfo->num_clauses) + encode_value (jinfo->num_clauses, p, &p); + + for (k = 0; k < jinfo->num_clauses; ++k) { + MonoJitExceptionInfo *ei = &jinfo->clauses [k]; + + encode_value (ei->flags, p, &p); + encode_value (ei->exvar_offset, p, &p); - encode_value ((gint)((guint8*)ei->try_start - code), p, &p); - encode_value ((gint)((guint8*)ei->try_end - code), p, &p); - encode_value ((gint)((guint8*)ei->handler_start - code), p, &p); + if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER || ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY) + encode_value ((gint)((guint8*)ei->data.filter - code), p, &p); + else { + if (ei->data.catch_class) { + encode_value (1, p, &p); + encode_klass_ref (acfg, ei->data.catch_class, p, &p); + } else { + encode_value (0, p, &p); + } + } + + encode_value ((gint)((guint8*)ei->try_start - code), p, &p); + encode_value ((gint)((guint8*)ei->try_end - code), p, &p); + encode_value ((gint)((guint8*)ei->handler_start - code), p, &p); + } } if (jinfo->has_generic_jit_info) { @@ -3586,7 +3645,7 @@ emit_trampolines (MonoAotCompile *acfg) g_assert (acfg->image->assembly); - /* Currently, we only emit most trampolines into the mscorlib AOT image. */ + /* Currently, we emit most trampolines into the mscorlib AOT image. */ if (strcmp (acfg->image->assembly->aname.name, "mscorlib") == 0) { #ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES /* @@ -3802,6 +3861,8 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts) opts->ntrampolines = atoi (arg + strlen ("ntrampolines=")); } else if (str_begins_with (arg, "nrgctx-trampolines=")) { opts->nrgctx_trampolines = atoi (arg + strlen ("nrgctx-trampolines=")); + } else if (str_begins_with (arg, "nimt-trampolines=")) { + opts->nimt_trampolines = atoi (arg + strlen ("nimt-trampolines=")); } else if (str_begins_with (arg, "autoreg")) { opts->autoreg = TRUE; } else if (str_begins_with (arg, "tool-prefix=")) { @@ -3870,6 +3931,7 @@ can_encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info) case MONO_WRAPPER_ALLOC: case MONO_WRAPPER_REMOTING_INVOKE: case MONO_WRAPPER_UNKNOWN: + case MONO_WRAPPER_WRITE_BARRIER: break; case MONO_WRAPPER_MANAGED_TO_MANAGED: if (!strcmp (method->name, "ElementAddr")) @@ -4237,7 +4299,7 @@ load_profile_files (MonoAotCompile *acfg) file_index = 0; while (TRUE) { - tmp = g_strdup_printf ("%s/.mono/aot-profile-data/%s-%s-%d", g_get_home_dir (), acfg->image->assembly_name, acfg->image->guid, file_index); + tmp = g_strdup_printf ("%s/.mono/aot-profile-data/%s-%d", g_get_home_dir (), acfg->image->assembly_name, file_index); if (!g_file_test (tmp, G_FILE_TEST_IS_REGULAR)) { g_free (tmp); @@ -4253,21 +4315,38 @@ load_profile_files (MonoAotCompile *acfg) file_index ++; res = fscanf (infile, "%32s\n", ver); - if ((res != 1) || strcmp (ver, "#VER:1") != 0) { + if ((res != 1) || strcmp (ver, "#VER:2") != 0) { printf ("Profile file has wrong version or invalid.\n"); fclose (infile); continue; } while (TRUE) { - res = fscanf (infile, "%d\n", &token); - if (res < 1) + char name [1024]; + MonoMethodDesc *desc; + MonoMethod *method; + + if (fgets (name, 1023, infile) == NULL) break; - method_index = mono_metadata_token_index (token) - 1; + /* Kill the newline */ + if (strlen (name) > 0) + name [strlen (name) - 1] = '\0'; + + desc = mono_method_desc_new (name, TRUE); - if (!g_list_find (acfg->method_order, GUINT_TO_POINTER (method_index))) - acfg->method_order = g_list_append (acfg->method_order, GUINT_TO_POINTER (method_index)); + method = mono_method_desc_search_in_image (desc, acfg->image); + + if (method && mono_method_get_token (method)) { + token = mono_method_get_token (method); + method_index = mono_metadata_token_index (token) - 1; + + if (!g_list_find (acfg->method_order, GUINT_TO_POINTER (method_index))) { + acfg->method_order = g_list_append (acfg->method_order, GUINT_TO_POINTER (method_index)); + } + } else { + //printf ("No method found matching '%s'.\n", name); + } } fclose (infile); } @@ -4369,8 +4448,26 @@ emit_llvm_file (MonoAotCompile *acfg) } } } + acfg->final_got_size = acfg->got_offset + acfg->plt_offset; + if (acfg->aot_opts.full_aot) { + int ntype; + + /* + * Need to add the got entries used by the trampolines. + * This is only a conservative approximation. + */ + if (strcmp (acfg->image->assembly->aname.name, "mscorlib") == 0) { + /* For the generic + rgctx trampolines */ + acfg->final_got_size += 200; + /* For the specific trampolines */ + for (ntype = 0; ntype < MONO_AOT_TRAMP_NUM; ++ntype) + acfg->final_got_size += acfg->num_trampolines [ntype] * 2; + } + } + + mono_llvm_emit_aot_module ("temp.bc", acfg->final_got_size); /* @@ -4434,7 +4531,7 @@ emit_code (MonoAotCompile *acfg) if (acfg->llvm) { for (i = 0; i < acfg->nmethods; ++i) { if (acfg->cfgs [i] && acfg->cfgs [i]->compile_llvm) { - fprintf (acfg->fp, "\n.set methods, %s\n", acfg->cfgs [i]->asm_symbol); + fprintf (acfg->fp, "\n.set methods, %s\n", acfg->cfgs [i]->asm_symbol); break; } } @@ -4452,14 +4549,42 @@ emit_code (MonoAotCompile *acfg) emit_zero_bytes (acfg, 16); for (l = acfg->method_order; l != NULL; l = l->next) { + MonoCompile *cfg; + MonoMethod *method; + i = GPOINTER_TO_UINT (l->data); - if (acfg->cfgs [i]) { - if (acfg->cfgs [i]->compile_llvm) - acfg->stats.llvm_count ++; - else - emit_method_code (acfg, acfg->cfgs [i]); + cfg = acfg->cfgs [i]; + + if (!cfg) + continue; + + method = cfg->orig_method; + + /* Emit unbox trampoline */ + if (acfg->aot_opts.full_aot && cfg->orig_method->klass->valuetype && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) { + char call_target [256]; + + if (!method->wrapper_type && !method->is_inflated) { + g_assert (method->token); + sprintf (symbol, "ut_%d", mono_metadata_token_index (method->token) - 1); + } else { + sprintf (symbol, "ut_e_%d", get_method_index (acfg, method)); + } + + emit_section_change (acfg, ".text", 0); + emit_global (acfg, symbol, TRUE); + emit_label (acfg, symbol); + + sprintf (call_target, "%s", cfg->asm_symbol); + + arch_emit_unbox_trampoline (acfg, cfg->orig_method, cfg->generic_sharing_context, call_target); } + + if (cfg->compile_llvm) + acfg->stats.llvm_count ++; + else + emit_method_code (acfg, cfg); } sprintf (symbol, "methods_end"); @@ -4476,7 +4601,7 @@ emit_code (MonoAotCompile *acfg) acfg->stats.offsets_size += acfg->nmethods * 4; - sprintf (end_symbol, "%smethods", acfg->llvm_label_prefix); + sprintf (end_symbol, "methods"); for (i = 0; i < acfg->nmethods; ++i) { if (acfg->cfgs [i]) { emit_symbol_diff (acfg, acfg->cfgs [i]->asm_symbol, end_symbol, 0); @@ -4776,6 +4901,8 @@ emit_extra_methods (MonoAotCompile *acfg) nmethods ++; + method = cfg->method_to_register; + name = NULL; if (method->wrapper_type) { /* @@ -5781,6 +5908,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) acfg->aot_opts.write_symbols = TRUE; acfg->aot_opts.ntrampolines = 1024; acfg->aot_opts.nrgctx_trampolines = 1024; + acfg->aot_opts.nimt_trampolines = 128; mono_aot_parse_options (aot_options, &acfg->aot_opts); @@ -5826,7 +5954,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) #ifdef MONO_ARCH_HAVE_STATIC_RGCTX_TRAMPOLINE acfg->num_trampolines [MONO_AOT_TRAMP_STATIC_RGCTX] = acfg->aot_opts.full_aot ? acfg->aot_opts.nrgctx_trampolines : 0; #endif - acfg->num_trampolines [MONO_AOT_TRAMP_IMT_THUNK] = acfg->aot_opts.full_aot ? 128 : 0; + acfg->num_trampolines [MONO_AOT_TRAMP_IMT_THUNK] = acfg->aot_opts.full_aot ? acfg->aot_opts.nimt_trampolines : 0; acfg->got_symbol_base = g_strdup_printf ("mono_aot_%s_got", acfg->image->assembly->aname.name); acfg->plt_symbol = g_strdup_printf ("mono_aot_%s_plt", acfg->image->assembly->aname.name); @@ -5971,7 +6099,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) img_writer_emit_start (acfg->w); if (acfg->dwarf) - mono_dwarf_writer_emit_base_info (acfg->dwarf, mono_arch_get_cie_program ()); + mono_dwarf_writer_emit_base_info (acfg->dwarf, mono_unwind_get_cie_program ()); emit_code (acfg); @@ -6017,7 +6145,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) acfg->stats.gen_time = TV_ELAPSED (atv, btv); if (acfg->llvm) - g_assert (acfg->got_offset == acfg->final_got_size); + g_assert (acfg->got_offset <= acfg->final_got_size); printf ("Code: %d Info: %d Ex Info: %d Unwind Info: %d Class Info: %d PLT: %d GOT Info: %d GOT: %d Offsets: %d\n", acfg->stats.code_size, acfg->stats.info_size, acfg->stats.ex_info_size, acfg->stats.unwind_info_size, acfg->stats.class_info_size, acfg->plt_offset, acfg->stats.got_info_size, (int)(acfg->got_offset * sizeof (gpointer)), acfg->stats.offsets_size);