X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;ds=sidebyside;f=mono%2Fmini%2Faot-compiler.c;h=b5516fb8034973468e22a76047c504a9cda3e76a;hb=5600f484aa032bddfe71c1d85a80a33a32ae4a92;hp=f9f546ecf1c2784d2a2bc009fe40efa78a80c6a0;hpb=2fdd06c04bf8fd77a2f40112e218faa18c40e7b3;p=mono.git diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index f9f546ecf1c..b5516fb8034 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -144,7 +144,7 @@ typedef struct MonoAotCompile { GPtrArray *extra_methods; GPtrArray *image_table; GPtrArray *globals; - GList *method_order; + GPtrArray *method_order; guint32 *plt_got_info_offsets; guint32 got_offset, plt_offset, plt_got_offset_base; guint32 final_got_size; @@ -185,7 +185,7 @@ typedef struct MonoAotCompile { MonoClass **typespec_classes; GString *llc_args; GString *as_args; - gboolean thumb_mixed, need_no_dead_strip; + gboolean thumb_mixed, need_no_dead_strip, need_pt_gnu_stack; } MonoAotCompile; typedef struct { @@ -505,6 +505,13 @@ encode_sleb128 (gint32 value, guint8 *buf, guint8 **endbuf) #endif #endif +#ifdef TARGET_POWERPC64 +#ifdef __mono_ilp32__ +#define AOT_TARGET_STR "POWERPC64 (mono ilp32)" +#else +#define AOT_TARGET_STR "POWERPC64 (!mono ilp32)" +#endif +#else #ifdef TARGET_POWERPC #ifdef __mono_ilp32__ #define AOT_TARGET_STR "POWERPC (mono ilp32)" @@ -512,13 +519,6 @@ encode_sleb128 (gint32 value, guint8 *buf, guint8 **endbuf) #define AOT_TARGET_STR "POWERPC (!mono ilp32)" #endif #endif - -#ifdef TARGET_POWERPC64 -#ifdef __mono_ilp32__ -#define AOT_TARGET_STR "POWERPC64 (mono ilp32)" -#else -#define AOT_TARGET_STR "POWERPC64 (!mono ilp32)" -#endif #endif #ifdef TARGET_WIN32 @@ -573,6 +573,10 @@ arch_init (MonoAotCompile *acfg) acfg->llvm_label_prefix = "_"; acfg->need_no_dead_strip = TRUE; #endif + +#if defined(__linux__) && !defined(TARGET_ARM) + acfg->need_pt_gnu_stack = TRUE; +#endif } /* @@ -2080,6 +2084,15 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 g_assert_not_reached (); } break; + case MONO_WRAPPER_CASTCLASS: + if (!strcmp (method->name, "__castclass_with_cache")) { + encode_value (MONO_AOT_WRAPPER_CASTCLASS_WITH_CACHE, p, &p); + } else if (!strcmp (method->name, "__isinst_with_cache")) { + encode_value (MONO_AOT_WRAPPER_ISINST_WITH_CACHE, p, &p); + } else { + g_assert_not_reached (); + } + break; default: g_assert_not_reached (); } @@ -2361,8 +2374,7 @@ add_method_full (MonoAotCompile *acfg, MonoMethod *method, gboolean extra, int d index = acfg->method_index; add_method_with_index (acfg, method, index, extra); - /* FIXME: Fix quadratic behavior */ - acfg->method_order = g_list_append (acfg->method_order, GUINT_TO_POINTER (index)); + g_ptr_array_add (acfg->method_order, GUINT_TO_POINTER (index)); g_hash_table_insert (acfg->method_depth, method, GUINT_TO_POINTER (depth)); @@ -2653,7 +2665,14 @@ add_wrappers (MonoAotCompile *acfg) klass = mono_class_get (acfg->image, token); if (klass) add_method (acfg, mono_marshal_get_virtual_stelemref (mono_array_class_get (klass, 1))); + else + mono_loader_clear_error (); } + + /* castclass_with_check wrapper */ + add_method (acfg, mono_marshal_get_castclass_with_cache ()); + /* isinst_with_check wrapper */ + add_method (acfg, mono_marshal_get_isinst_with_cache ()); } /* @@ -2686,6 +2705,11 @@ add_wrappers (MonoAotCompile *acfg) token = MONO_TOKEN_TYPE_DEF | (i + 1); klass = mono_class_get (acfg->image, token); + if (!klass) { + mono_loader_clear_error (); + continue; + } + if (klass->delegate && klass != mono_defaults.delegate_class && klass != mono_defaults.multicastdelegate_class && !klass->generic_container) { method = mono_get_delegate_invoke (klass); @@ -2793,6 +2817,11 @@ add_wrappers (MonoAotCompile *acfg) token = MONO_TOKEN_TYPE_DEF | (i + 1); klass = mono_class_get (acfg->image, token); + if (!klass) { + mono_loader_clear_error (); + continue; + } + if (klass->valuetype && !klass->generic_container && can_marshal_struct (klass)) { add_method (acfg, mono_marshal_get_struct_to_ptr (klass)); add_method (acfg, mono_marshal_get_ptr_to_struct (klass)); @@ -2851,6 +2880,34 @@ add_generic_class (MonoAotCompile *acfg, MonoClass *klass, gboolean force) add_generic_class_with_depth (acfg, klass, 0); } +static gboolean +check_type_depth (MonoType *t, int depth) +{ + int i; + + if (depth > 8) + return TRUE; + + switch (t->type) { + case MONO_TYPE_GENERICINST: { + MonoGenericClass *gklass = t->data.generic_class; + MonoGenericInst *ginst = gklass->context.class_inst; + + if (ginst) { + for (i = 0; i < ginst->type_argc; ++i) { + if (check_type_depth (ginst->type_argv [i], depth + 1)) + return TRUE; + } + } + break; + } + default: + break; + } + + return FALSE; +} + /* * add_generic_class: * @@ -2873,6 +2930,9 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth) if (!klass->generic_class && !klass->rank) return; + if (check_type_depth (&klass->byval_arg, 0)) + return; + iter = NULL; while ((method = mono_class_get_methods (klass, &iter))) { if (mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE)) @@ -2887,7 +2947,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth) * FIXME: Instances which are referenced by these methods are not added, * for example Array.Resize for List.Add (). */ - add_extra_method_with_depth (acfg, method, depth); + add_extra_method_with_depth (acfg, method, depth + 1); } if (klass->delegate) { @@ -3121,24 +3181,28 @@ add_generic_instances (MonoAotCompile *acfg) token = MONO_TOKEN_TYPE_SPEC | (i + 1); klass = mono_class_get (acfg->image, token); - if (!klass || klass->rank) + if (!klass || klass->rank) { + mono_loader_clear_error (); continue; + } add_generic_class (acfg, klass, FALSE); } /* Add types of args/locals */ for (i = 0; i < acfg->methods->len; ++i) { - int j; + int j, depth; method = g_ptr_array_index (acfg->methods, i); + depth = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->method_depth, method)); + sig = mono_method_signature (method); if (sig) { for (j = 0; j < sig->param_count; ++j) if (sig->params [j]->type == MONO_TYPE_GENERICINST) - add_generic_class (acfg, mono_class_from_mono_type (sig->params [j]), FALSE); + add_generic_class_with_depth (acfg, mono_class_from_mono_type (sig->params [j]), depth + 1); } header = mono_method_get_header (method); @@ -3146,7 +3210,7 @@ add_generic_instances (MonoAotCompile *acfg) if (header) { for (j = 0; j < header->num_locals; ++j) if (header->locals [j]->type == MONO_TYPE_GENERICINST) - add_generic_class (acfg, mono_class_from_mono_type (header->locals [j]), FALSE); + add_generic_class_with_depth (acfg, mono_class_from_mono_type (header->locals [j]), depth + 1); } } @@ -3518,6 +3582,7 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint break; case MONO_PATCH_INFO_MSCORLIB_GOT_ADDR: case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR: + case MONO_PATCH_INFO_CASTCLASS_CACHE: break; case MONO_PATCH_INFO_METHOD_REL: encode_value ((gint)patch_info->data.offset, p, &p); @@ -3656,7 +3721,6 @@ emit_method_info (MonoAotCompile *acfg, MonoCompile *cfg) MonoMethod *method; GList *l; int pindex, buf_size, n_patches; - guint8 *code; GPtrArray *patches; MonoJumpInfo *patch_info; MonoMethodHeader *header; @@ -3665,7 +3729,6 @@ emit_method_info (MonoAotCompile *acfg, MonoCompile *cfg) guint32 first_got_offset; method = cfg->orig_method; - code = cfg->native_code; header = mono_method_get_header (method); method_index = get_method_index (acfg, method); @@ -3809,7 +3872,7 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg) seq_points = cfg->seq_point_info; - buf_size = header->num_clauses * 256 + debug_info_size + 1024 + (seq_points ? (seq_points->len * 64) : 0) + cfg->gc_map_size; + buf_size = header->num_clauses * 256 + debug_info_size + 2048 + (seq_points ? (seq_points->len * 64) : 0) + cfg->gc_map_size; p = buf = g_malloc (buf_size); #ifdef MONO_ARCH_HAVE_XP_UNWIND @@ -3989,6 +4052,8 @@ emit_klass_info (MonoAotCompile *acfg, guint32 token) gpointer iter = NULL; if (!klass) { + mono_loader_clear_error (); + buf_size = 16; p = buf = g_malloc (buf_size); @@ -4339,11 +4404,11 @@ static void emit_trampolines (MonoAotCompile *acfg) { char symbol [256]; + char end_symbol [256]; int i, tramp_got_offset; MonoAotTrampoline ntype; #ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES int tramp_type; - guint8 *code; #endif if (!acfg->aot_opts.full_aot) @@ -4381,15 +4446,15 @@ emit_trampolines (MonoAotCompile *acfg) emit_trampoline (acfg, acfg->got_offset, info); /* Emit the exception related code pieces */ - code = mono_arch_get_restore_context (&info, TRUE); + mono_arch_get_restore_context (&info, TRUE); emit_trampoline (acfg, acfg->got_offset, info); - code = mono_arch_get_call_filter (&info, TRUE); + mono_arch_get_call_filter (&info, TRUE); emit_trampoline (acfg, acfg->got_offset, info); - code = mono_arch_get_throw_exception (&info, TRUE); + mono_arch_get_throw_exception (&info, TRUE); emit_trampoline (acfg, acfg->got_offset, info); - code = mono_arch_get_rethrow_exception (&info, TRUE); + mono_arch_get_rethrow_exception (&info, TRUE); emit_trampoline (acfg, acfg->got_offset, info); - code = mono_arch_get_throw_corlib_exception (&info, TRUE); + mono_arch_get_throw_corlib_exception (&info, TRUE); emit_trampoline (acfg, acfg->got_offset, info); #if defined(MONO_ARCH_HAVE_GET_TRAMPOLINES) @@ -4409,11 +4474,11 @@ emit_trampolines (MonoAotCompile *acfg) int offset; offset = MONO_RGCTX_SLOT_MAKE_RGCTX (i); - code = mono_arch_create_rgctx_lazy_fetch_trampoline (offset, &info, TRUE); + mono_arch_create_rgctx_lazy_fetch_trampoline (offset, &info, TRUE); emit_trampoline (acfg, acfg->got_offset, info); offset = MONO_RGCTX_SLOT_MAKE_MRGCTX (i); - code = mono_arch_create_rgctx_lazy_fetch_trampoline (offset, &info, TRUE); + mono_arch_create_rgctx_lazy_fetch_trampoline (offset, &info, TRUE); emit_trampoline (acfg, acfg->got_offset, info); } @@ -4481,6 +4546,11 @@ emit_trampolines (MonoAotCompile *acfg) g_assert_not_reached (); } + sprintf (end_symbol, "%s_e", symbol); + + if (acfg->aot_opts.write_symbols) + emit_local_symbol (acfg, symbol, end_symbol, TRUE); + emit_alignment (acfg, AOT_FUNC_ALIGNMENT); emit_label (acfg, symbol); @@ -4515,6 +4585,8 @@ emit_trampolines (MonoAotCompile *acfg) acfg->trampoline_size [ntype] = tramp_size; } } + + emit_label (acfg, end_symbol); } /* Reserve some entries at the end of the GOT for our use */ @@ -4680,6 +4752,13 @@ can_encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info) return TRUE; else return FALSE; + case MONO_WRAPPER_CASTCLASS: + if (!strcmp (method->name, "__castclass_with_cache")) + return TRUE; + else if (!strcmp (method->name, "__isinst_with_cache")) + return TRUE; + else + return FALSE; default: //printf ("Skip (wrapper call): %d -> %s\n", patch_info->type, mono_method_full_name (patch_info->data.method, TRUE)); return FALSE; @@ -4783,6 +4862,7 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method) return; } if (cfg->exception_type != MONO_EXCEPTION_NONE) { + //printf ("E: %s\n", mono_method_full_name (method, TRUE)); /* Let the exception happen at runtime */ return; } @@ -5035,7 +5115,8 @@ load_profile_files (MonoAotCompile *acfg) int file_index, res, method_index, i; char ver [256]; guint32 token; - GList *unordered; + GList *unordered, *l; + gboolean found; file_index = 0; while (TRUE) { @@ -5081,9 +5162,15 @@ load_profile_files (MonoAotCompile *acfg) 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)); + found = FALSE; + for (i = 0; i < acfg->method_order->len; ++i) { + if (g_ptr_array_index (acfg->method_order, i) == GUINT_TO_POINTER (method_index)) { + found = TRUE; + break; + } } + if (!found) + g_ptr_array_add (acfg->method_order, GUINT_TO_POINTER (method_index)); } else { //printf ("No method found matching '%s'.\n", name); } @@ -5093,15 +5180,20 @@ load_profile_files (MonoAotCompile *acfg) /* Add missing methods */ unordered = NULL; - for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) { - if (!g_list_find (acfg->method_order, GUINT_TO_POINTER (i))) - unordered = g_list_prepend (unordered, GUINT_TO_POINTER (i)); + for (method_index = 0; method_index < acfg->image->tables [MONO_TABLE_METHOD].rows; ++method_index) { + found = FALSE; + for (i = 0; i < acfg->method_order->len; ++i) { + if (g_ptr_array_index (acfg->method_order, i) == GUINT_TO_POINTER (method_index)) { + found = TRUE; + break; + } + } + if (!found) + unordered = g_list_prepend (unordered, GUINT_TO_POINTER (method_index)); } unordered = g_list_reverse (unordered); - if (acfg->method_order) - g_list_last (acfg->method_order)->next = unordered; - else - acfg->method_order = unordered; + for (l = unordered; l; l = l->next) + g_ptr_array_add (acfg->method_order, l->data); } /* Used by the LLVM backend */ @@ -5221,7 +5313,7 @@ emit_llvm_file (MonoAotCompile *acfg) * then removing tailcallelim + the global opts, and adding a second gvn. */ opts = g_strdup ("-instcombine -simplifycfg"); - opts = g_strdup ("-simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -basiccg -prune-eh -inline -functionattrs -domtree -domfrontier -scalarrepl -simplify-libcalls -instcombine -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loopsimplify -domfrontier -loopsimplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loopsimplify -lcssa -iv-users -indvars -loop-deletion -loopsimplify -lcssa -loop-unroll -instcombine -memdep -gvn -memdep -memcpyopt -sccp -instcombine -domtree -memdep -dse -adce -gvn -simplifycfg -preverify -domtree -verify"); + opts = g_strdup ("-simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -basiccg -prune-eh -inline -functionattrs -domtree -domfrontier -scalarrepl -simplify-libcalls -instcombine -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loop-simplify -domfrontier -loop-simplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loop-simplify -lcssa -iv-users -indvars -loop-deletion -loop-simplify -lcssa -loop-unroll -instcombine -memdep -gvn -memdep -memcpyopt -sccp -instcombine -domtree -memdep -dse -adce -simplifycfg -preverify -domtree -verify"); #if 1 command = g_strdup_printf ("%sopt -f %s -o temp.opt.bc temp.bc", acfg->aot_opts.llvm_path, opts); printf ("Executing opt: %s\n", command); @@ -5259,10 +5351,9 @@ emit_llvm_file (MonoAotCompile *acfg) static void emit_code (MonoAotCompile *acfg) { - int i; + int oindex, i; char symbol [256]; char end_symbol [256]; - GList *l; #if defined(TARGET_POWERPC64) sprintf (symbol, ".Lgot_addr"); @@ -5308,13 +5399,12 @@ emit_code (MonoAotCompile *acfg) emit_bytes (acfg, pad_buffer, kPaddingSize); } #endif - - for (l = acfg->method_order; l != NULL; l = l->next) { + for (oindex = 0; oindex < acfg->method_order->len; ++oindex) { MonoCompile *cfg; MonoMethod *method; - i = GPOINTER_TO_UINT (l->data); + i = GPOINTER_TO_UINT (g_ptr_array_index (acfg->method_order, oindex)); cfg = acfg->cfgs [i]; @@ -5325,8 +5415,6 @@ emit_code (MonoAotCompile *acfg) /* 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); @@ -5345,9 +5433,7 @@ emit_code (MonoAotCompile *acfg) emit_label (acfg, symbol); - sprintf (call_target, "%s", cfg->asm_symbol); - - arch_emit_unbox_trampoline (acfg, cfg, cfg->orig_method, call_target); + arch_emit_unbox_trampoline (acfg, cfg, cfg->orig_method, cfg->asm_symbol); } if (cfg->compile_llvm) @@ -5397,15 +5483,14 @@ emit_code (MonoAotCompile *acfg) static void emit_info (MonoAotCompile *acfg) { - int i; + int oindex, i; char symbol [256]; - GList *l; gint32 *offsets; offsets = g_new0 (gint32, acfg->nmethods); - for (l = acfg->method_order; l != NULL; l = l->next) { - i = GPOINTER_TO_UINT (l->data); + for (oindex = 0; oindex < acfg->method_order->len; ++oindex) { + i = GPOINTER_TO_UINT (g_ptr_array_index (acfg->method_order, oindex)); if (acfg->cfgs [i]) { emit_method_info (acfg, acfg->cfgs [i]); @@ -5464,8 +5549,9 @@ mono_aot_type_hash (MonoType *t1) return ((hash << 5) - hash) ^ mono_metadata_type_hash (&t1->data.array->eklass->byval_arg); case MONO_TYPE_GENERICINST: return ((hash << 5) - hash) ^ 0; + default: + return hash; } - return hash; } /* @@ -5927,8 +6013,10 @@ emit_class_name_table (MonoAotCompile *acfg) for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i) { token = MONO_TOKEN_TYPE_DEF | (i + 1); klass = mono_class_get (acfg->image, token); - if (!klass) + if (!klass) { + mono_loader_clear_error (); continue; + } full_name = mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_FULL_NAME); hash = mono_metadata_str_hash (full_name) % table_size; g_free (full_name); @@ -6717,6 +6805,7 @@ acfg_create (MonoAssembly *ass, guint32 opts) acfg->unwind_info_offsets = g_hash_table_new (NULL, NULL); acfg->unwind_ops = g_ptr_array_new (); acfg->method_label_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + acfg->method_order = g_ptr_array_new (); InitializeCriticalSection (&acfg->mutex); return acfg; @@ -7030,6 +7119,13 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) emit_mem_end (acfg); + if (acfg->need_pt_gnu_stack) { + /* This is required so the .so doesn't have an executable stack */ + /* The bin writer already emits this */ + if (!acfg->use_bin_writer) + fprintf (acfg->fp, "\n.section .note.GNU-stack,\"\",@progbits\n"); + } + TV_GETTIME (btv); acfg->stats.gen_time = TV_ELAPSED (atv, btv);