X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Faot-runtime.c;h=7330d1cd30a976205ad29f6ae985472c6a8b28ad;hb=HEAD;hp=ce87be85147787fadc4017bb32d96a9be54733ac;hpb=5c11fe647563fa051f73d3571da839dfccd26f8e;p=mono.git diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index ce87be85147..7330d1cd30a 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -1,5 +1,6 @@ -/* - * aot-runtime.c: mono Ahead of Time compiler +/** + * \file + * mono Ahead of Time compiler * * Author: * Dietmar Maurer (dietmar@ximian.com) @@ -504,6 +505,7 @@ decode_klass_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf, MonoError return NULL; t = mini_get_shared_gparam (&par_klass->byval_arg, gshared_constraint); + mono_metadata_free_type (gshared_constraint); klass = mono_class_from_mono_type (t); } else { int type = decode_value (p, &p); @@ -923,12 +925,12 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod case MONO_WRAPPER_ALLOC: { int atype = decode_value (p, &p); ManagedAllocatorVariant variant = - mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS ? - MANAGED_ALLOCATOR_SLOW_PATH : MANAGED_ALLOCATOR_REGULAR; + mono_profiler_allocations_enabled () ? + MANAGED_ALLOCATOR_PROFILER : MANAGED_ALLOCATOR_REGULAR; ref->method = mono_gc_get_managed_allocator_by_type (atype, variant); /* Try to fallback to the slow path version */ - if (!ref->method && variant == MANAGED_ALLOCATOR_REGULAR) + if (!ref->method) ref->method = mono_gc_get_managed_allocator_by_type (atype, MANAGED_ALLOCATOR_SLOW_PATH); if (!ref->method) { mono_error_set_bad_image_name (error, module->aot_name, "Error: No managed allocator, but we need one for AOT.\nAre you using non-standard GC options?\n"); @@ -1013,6 +1015,8 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod ref->method = mono_marshal_get_gsharedvt_in_wrapper (); } else if (subtype == WRAPPER_SUBTYPE_GSHAREDVT_OUT) { ref->method = mono_marshal_get_gsharedvt_out_wrapper (); + } else if (subtype == WRAPPER_SUBTYPE_INTERP_IN) { + ref->method = mini_get_interp_in_wrapper (target->signature); } else if (subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN_SIG) { MonoMethodSignature *sig = decode_signature (module, p, &p); if (!sig) @@ -1943,7 +1947,7 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data) */ return; - if (image_is_dynamic (assembly->image) || assembly->ref_only) + if (image_is_dynamic (assembly->image) || assembly->ref_only || mono_domain_get () != mono_get_root_domain ()) return; mono_aot_lock (); @@ -1965,6 +1969,7 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data) globals = (void **)info->globals; g_assert (globals); } + found_aot_name = g_strdup (aot_name); } else { char *err; @@ -1991,6 +1996,7 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data) mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT: image '%s' not found: %s", aot_name, err); g_free (err); } + g_free (aot_name); } if (!sofile) { GList *l; @@ -2014,7 +2020,7 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data) } } if (!sofile) { - if (mono_aot_only && assembly->image->tables [MONO_TABLE_METHOD].rows) { + if (mono_aot_only && !mono_use_interpreter && assembly->image->tables [MONO_TABLE_METHOD].rows) { aot_name = g_strdup_printf ("%s%s", assembly->image->name, MONO_SOLIB_EXT); g_error ("Failed to load AOT module '%s' in aot-only mode.\n", aot_name); g_free (aot_name); @@ -2058,7 +2064,7 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data) } if (!usable) { - if (mono_aot_only) { + if (mono_aot_only && !mono_use_interpreter) { g_error ("Failed to load AOT module '%s' while running in aot-only mode: %s.\n", found_aot_name, msg); } else { mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT: module %s is unusable: %s.", found_aot_name, msg); @@ -2262,7 +2268,7 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data) /* * Register the plt region as a single trampoline so we can unwind from this code */ - mono_tramp_info_register ( + mono_aot_tramp_info_register ( mono_tramp_info_create ( NULL, amodule->plt, @@ -2280,16 +2286,6 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data) * non-lazily, since we can't handle out-of-date errors later. * The cached class info also depends on the exact assemblies. */ -#if defined(__native_client__) - /* TODO: Don't 'load_image' on mscorlib due to a */ - /* recursive loading problem. This should be */ - /* removed if mscorlib is loaded from disk. */ - if (strncmp(assembly->aname.name, "mscorlib", 8)) { - do_load_image = TRUE; - } else { - do_load_image = FALSE; - } -#endif if (do_load_image) { for (i = 0; i < amodule->image_table_len; ++i) { MonoError error; @@ -2350,13 +2346,14 @@ mono_aot_init (void) mono_os_mutex_init_recursive (&aot_page_mutex); aot_modules = g_hash_table_new (NULL, NULL); -#ifndef __native_client__ mono_install_assembly_load_hook (load_aot_module, NULL); -#endif mono_counters_register ("Async JIT info size", MONO_COUNTER_INT|MONO_COUNTER_JIT, &async_jit_info_size); - if (g_getenv ("MONO_LASTAOT")) - mono_last_aot_method = atoi (g_getenv ("MONO_LASTAOT")); + char *lastaot = g_getenv ("MONO_LASTAOT"); + if (lastaot) { + mono_last_aot_method = atoi (lastaot); + g_free (lastaot); + } aot_cache_init (); } @@ -2660,15 +2657,15 @@ is_thumb_code (MonoAotModule *amodule, guint8 *code) * * Decode the EH information emitted by our modified LLVM compiler and construct a * MonoJitInfo structure from it. - * LOCKING: Acquires the domain lock. + * If JINFO is NULL, set OUT_LLVM_CLAUSES to the number of llvm level clauses. + * This function is async safe when called in async context. */ -static MonoJitInfo* -decode_llvm_mono_eh_frame (MonoAotModule *amodule, MonoDomain *domain, - MonoMethod *method, guint8 *code, guint32 code_len, +static void +decode_llvm_mono_eh_frame (MonoAotModule *amodule, MonoDomain *domain, MonoJitInfo *jinfo, + guint8 *code, guint32 code_len, MonoJitExceptionInfo *clauses, int num_clauses, - MonoJitInfoFlags flags, GSList **nesting, - int *this_reg, int *this_offset) + int *this_reg, int *this_offset, int *out_llvm_clauses) { guint8 *p, *code1, *code2; guint8 *fde, *cie, *code_start, *code_end; @@ -2678,14 +2675,19 @@ decode_llvm_mono_eh_frame (MonoAotModule *amodule, MonoDomain *domain, MonoJitExceptionInfo *ei; guint32 fde_len, ei_len, nested_len, nindex; gpointer *type_info; - MonoJitInfo *jinfo; MonoLLVMFDEInfo info; + guint8 *unw_info; + gboolean async; + + async = mono_thread_info_is_async_context (); if (!amodule->mono_eh_frame) { - jinfo = (MonoJitInfo *)mono_domain_alloc0_lock_free (domain, mono_jit_info_size (flags, num_clauses, 0)); - mono_jit_info_init (jinfo, method, code, code_len, flags, num_clauses, 0); + if (!jinfo) { + *out_llvm_clauses = num_clauses; + return; + } memcpy (jinfo->clauses, clauses, num_clauses * sizeof (MonoJitExceptionInfo)); - return jinfo; + return; } g_assert (amodule->mono_eh_frame && code); @@ -2754,13 +2756,29 @@ decode_llvm_mono_eh_frame (MonoAotModule *amodule, MonoDomain *domain, /* This won't overflow because there is +1 entry in the table */ fde_len = table [(pos * 2) + 2 + 1] - table [(pos * 2) + 1]; - mono_unwind_decode_llvm_mono_fde (fde, fde_len, cie, code_start, &info); - ei = info.ex_info; + /* Compute lengths */ + mono_unwind_decode_llvm_mono_fde (fde, fde_len, cie, code_start, &info, NULL, NULL, NULL); + + if (async) { + /* These are leaked, but the leak is bounded */ + ei = mono_domain_alloc0_lock_free (domain, info.ex_info_len * sizeof (MonoJitExceptionInfo)); + type_info = mono_domain_alloc0_lock_free (domain, info.ex_info_len * sizeof (gpointer)); + unw_info = mono_domain_alloc0_lock_free (domain, info.unw_info_len); + } else { + ei = (MonoJitExceptionInfo *)g_malloc0 (info.ex_info_len * sizeof (MonoJitExceptionInfo)); + type_info = (gpointer *)g_malloc0 (info.ex_info_len * sizeof (gpointer)); + unw_info = (guint8*)g_malloc0 (info.unw_info_len); + } + mono_unwind_decode_llvm_mono_fde (fde, fde_len, cie, code_start, &info, ei, type_info, unw_info); + ei_len = info.ex_info_len; - type_info = info.type_info; *this_reg = info.this_reg; *this_offset = info.this_offset; + /* + * LLVM might represent one IL region with multiple regions. + */ + /* Count number of nested clauses */ nested_len = 0; for (i = 0; i < ei_len; ++i) { @@ -2772,18 +2790,16 @@ decode_llvm_mono_eh_frame (MonoAotModule *amodule, MonoDomain *domain, nested_len ++; } - /* - * LLVM might represent one IL region with multiple regions, so have to - * allocate a new JI. - */ - jinfo = - (MonoJitInfo *)mono_domain_alloc0_lock_free (domain, mono_jit_info_size (flags, ei_len + nested_len, 0)); - mono_jit_info_init (jinfo, method, code, code_len, flags, ei_len + nested_len, 0); + if (!jinfo) { + *out_llvm_clauses = ei_len + nested_len; + return; + } - jinfo->unwind_info = mono_cache_unwind_info (info.unw_info, info.unw_info_len); - /* This signals that unwind_info points to a normal cached unwind info */ - jinfo->from_aot = 0; - jinfo->from_llvm = 1; + /* Store the unwind info addr/length in the MonoJitInfo structure itself so its async safe */ + MonoUnwindJitInfo *jinfo_unwind = mono_jit_info_get_unwind_info (jinfo); + g_assert (jinfo_unwind); + jinfo_unwind->unw_info = unw_info; + jinfo_unwind->unw_info_len = info.unw_info_len; for (i = 0; i < ei_len; ++i) { /* @@ -2833,8 +2849,6 @@ decode_llvm_mono_eh_frame (MonoAotModule *amodule, MonoDomain *domain, } } g_assert (nindex == ei_len + nested_len); - - return jinfo; } static gpointer @@ -2919,24 +2933,41 @@ decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain, MonoJitExceptionInfo *clauses; GSList **nesting; - // FIXME: async - g_assert (!async); - /* * Part of the info is encoded by the AOT compiler, the rest is in the .eh_frame * section. */ - clauses = g_new0 (MonoJitExceptionInfo, num_clauses); - nesting = g_new0 (GSList*, num_clauses); + if (async) { + if (num_clauses < 16) { + clauses = g_newa (MonoJitExceptionInfo, num_clauses); + nesting = g_newa (GSList*, num_clauses); + } else { + clauses = alloc0_jit_info_data (domain, sizeof (MonoJitExceptionInfo) * num_clauses, TRUE); + nesting = alloc0_jit_info_data (domain, sizeof (GSList*) * num_clauses, TRUE); + } + memset (clauses, 0, sizeof (MonoJitExceptionInfo) * num_clauses); + memset (nesting, 0, sizeof (GSList*) * num_clauses); + } else { + clauses = g_new0 (MonoJitExceptionInfo, num_clauses); + nesting = g_new0 (GSList*, num_clauses); + } for (i = 0; i < num_clauses; ++i) { MonoJitExceptionInfo *ei = &clauses [i]; ei->flags = decode_value (p, &p); - if (decode_value (p, &p)) { - ei->data.catch_class = decode_klass_ref (amodule, p, &p, &error); - mono_error_cleanup (&error); /* FIXME don't swallow the error */ + if (!(ei->flags == MONO_EXCEPTION_CLAUSE_FILTER || ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY)) { + int len = decode_value (p, &p); + + if (len > 0) { + if (async) { + p += len; + } else { + ei->data.catch_class = decode_klass_ref (amodule, p, &p, &error); + mono_error_cleanup (&error); /* FIXME don't swallow the error */ + } + } } ei->clause_index = i; @@ -2951,16 +2982,30 @@ decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain, int nesting_index = decode_value (p, &p); if (nesting_index == -1) break; + // FIXME: async + g_assert (!async); nesting [i] = g_slist_prepend (nesting [i], GINT_TO_POINTER (nesting_index)); } } - jinfo = decode_llvm_mono_eh_frame (amodule, domain, method, code, code_len, clauses, num_clauses, flags, nesting, &this_reg, &this_offset); + flags |= JIT_INFO_HAS_UNWIND_INFO; - g_free (clauses); - for (i = 0; i < num_clauses; ++i) - g_slist_free (nesting [i]); - g_free (nesting); + int num_llvm_clauses; + /* Get the length first */ + decode_llvm_mono_eh_frame (amodule, domain, NULL, code, code_len, clauses, num_clauses, nesting, &this_reg, &this_offset, &num_llvm_clauses); + len = mono_jit_info_size (flags, num_llvm_clauses, num_holes); + jinfo = (MonoJitInfo *)alloc0_jit_info_data (domain, len, async); + mono_jit_info_init (jinfo, method, code, code_len, flags, num_llvm_clauses, num_holes); + + decode_llvm_mono_eh_frame (amodule, domain, jinfo, code, code_len, clauses, num_clauses, nesting, &this_reg, &this_offset, NULL); + + if (!async) { + g_free (clauses); + for (i = 0; i < num_clauses; ++i) + g_slist_free (nesting [i]); + g_free (nesting); + } + jinfo->from_llvm = 1; } else { len = mono_jit_info_size (flags, num_clauses, num_holes); jinfo = (MonoJitInfo *)alloc0_jit_info_data (domain, len, async); @@ -3498,7 +3543,8 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin break; } case MONO_PATCH_INFO_INTERNAL_METHOD: - case MONO_PATCH_INFO_JIT_ICALL_ADDR: { + case MONO_PATCH_INFO_JIT_ICALL_ADDR: + case MONO_PATCH_INFO_JIT_ICALL_ADDR_NOCALL: { guint32 len = decode_value (p, &p); ji->data.name = (char*)p; @@ -3617,6 +3663,7 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR: case MONO_PATCH_INFO_GC_NURSERY_START: case MONO_PATCH_INFO_GC_NURSERY_BITS: + case MONO_PATCH_INFO_PROFILER_ALLOCATION_COUNT: break; case MONO_PATCH_INFO_CASTCLASS_CACHE: ji->data.index = decode_value (p, &p); @@ -3855,13 +3902,6 @@ load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoM init_amodule_got (amodule); - if (mono_profiler_get_events () & MONO_PROFILE_ENTER_LEAVE) { - if (mono_aot_only) - /* The caller cannot handle this */ - g_assert_not_reached (); - return NULL; - } - if (domain != mono_get_root_domain ()) /* Non shared AOT code can't be used in other appdomains */ return NULL; @@ -3888,9 +3928,11 @@ load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoM if (!method) return NULL; } - full_name = mono_method_full_name (method, TRUE); - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT: NOT FOUND: %s.", full_name); - g_free (full_name); + if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)) { + full_name = mono_method_full_name (method, TRUE); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT: NOT FOUND: %s.", full_name); + g_free (full_name); + } } return NULL; } @@ -3915,9 +3957,10 @@ load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoM return code; if (mono_last_aot_method != -1) { - if (mono_jit_stats.methods_aot >= mono_last_aot_method) - return NULL; - else if (mono_jit_stats.methods_aot == mono_last_aot_method - 1) { + gint32 methods_aot = InterlockedRead (&mono_jit_stats.methods_aot); + if (methods_aot >= mono_last_aot_method) + return NULL; + else if (methods_aot == mono_last_aot_method - 1) { if (!method) { method = mono_get_method_checked (image, token, NULL, NULL, error); if (!method) @@ -3974,7 +4017,7 @@ load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoM amodule_unlock (amodule); - if (mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION) { + if (MONO_PROFILER_ENABLED (jit_begin) || MONO_PROFILER_ENABLED (jit_done)) { MonoJitInfo *jinfo; if (!method) { @@ -3982,10 +4025,10 @@ load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoM if (!method) return NULL; } - mono_profiler_method_jit (method); + MONO_PROFILER_RAISE (jit_begin, (method)); jinfo = mono_jit_info_table_find (domain, (char*)code); g_assert (jinfo); - mono_profiler_method_end_jit (method, jinfo, MONO_PROFILE_OK); + MONO_PROFILER_RAISE (jit_done, (method, jinfo)); } return code; @@ -4592,24 +4635,6 @@ mono_aot_get_method_checked (MonoDomain *domain, MonoMethod *method, MonoError * return code; } -/* - * mono_aot_get_method: - * - * Return a pointer to the AOTed native code for METHOD if it can be found, - * NULL otherwise. - * On platforms with function pointers, this doesn't return a function pointer. - */ -gpointer -mono_aot_get_method (MonoDomain *domain, MonoMethod *method) -{ - MonoError error; - - gpointer res = mono_aot_get_method_checked (domain, method, &error); - /* This is external only, so its ok to raise here */ - mono_error_raise_exception (&error); /* OK to throw, external only without a good alternative */ - return res; -} - /** * Same as mono_aot_get_method, but we try to avoid loading any metadata from the * method. @@ -5119,6 +5144,8 @@ no_trampolines (void) g_assert_not_reached (); } + +#ifndef TARGET_WASM /* * Return the trampoline identified by NAME from the mscorlib AOT file. * On ppc64, this returns a function descriptor. @@ -5135,6 +5162,8 @@ mono_aot_get_trampoline_full (const char *name, MonoTrampInfo **out_tinfo) return mono_create_ftnptr_malloc ((guint8 *)load_function_full (amodule, name, out_tinfo)); } +#endif + gpointer mono_aot_get_trampoline (const char *name) @@ -5143,7 +5172,7 @@ mono_aot_get_trampoline (const char *name) gpointer code; code = mono_aot_get_trampoline_full (name, &out_tinfo); - mono_tramp_info_register (out_tinfo, NULL); + mono_aot_tramp_info_register (out_tinfo, NULL); return code; } @@ -5297,7 +5326,7 @@ get_new_trampoline_from_page (int tramp_type) /* Register the generic part at the beggining of the trampoline page */ gen_info = mono_tramp_info_create (NULL, (guint8*)taddr, amodule->info.tramp_page_code_offsets [tramp_type], NULL, NULL); read_page_trampoline_uwinfo (gen_info, tramp_type, TRUE); - mono_tramp_info_register (gen_info, NULL); + mono_aot_tramp_info_register (gen_info, NULL); /* * FIXME * Registering each specific trampoline produces a lot of @@ -5308,7 +5337,7 @@ get_new_trampoline_from_page (int tramp_type) /* Register the rest of the page as a single trampoline */ sp_info = mono_tramp_info_create (NULL, code, page->trampolines_end - code, NULL, NULL); read_page_trampoline_uwinfo (sp_info, tramp_type, FALSE); - mono_tramp_info_register (sp_info, NULL); + mono_aot_tramp_info_register (sp_info, NULL); } return code; } @@ -5577,7 +5606,7 @@ mono_aot_get_unbox_trampoline (MonoMethod *method) } tinfo->code_size = *(guint32*)symbol_addr; - mono_tramp_info_register (tinfo, NULL); + mono_aot_tramp_info_register (tinfo, NULL); /* The caller expects an ftnptr */ return mono_create_ftnptr (mono_domain_get (), code); @@ -5776,7 +5805,7 @@ mono_aot_is_pagefault (void *ptr) void mono_aot_handle_pagefault (void *ptr) { -#ifndef PLATFORM_WIN32 +#ifndef HOST_WIN32 guint8* start = (guint8*)ROUND_DOWN (((gssize)ptr), mono_pagesize ()); int res;