X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;ds=inline;f=mono%2Fmini%2Fmini.c;h=f5e831d770e0aaa1087fc372353265ec0b8e1a2d;hb=47b55a2fa87715cc58433289a91541780615a304;hp=4e221b9d9e0e7808eb67a0d874c4f1c28af159b9;hpb=3664f9db8f85efc3cb70e725322a8dc9b096d3bb;p=mono.git diff --git a/mono/mini/mini.c b/mono/mini/mini.c index 4e221b9d9e0..f5e831d770e 100644 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -7,6 +7,7 @@ * * Copyright 2002-2003 Ximian, Inc. * Copyright 2003-2010 Novell, Inc. + * Copyright 2011 Xamarin, Inc (http://www.xamarin.com) */ #define MONO_LLVM_IN_MINI 1 @@ -53,6 +54,7 @@ #include #include #include +#include #include #include "mini.h" @@ -69,34 +71,16 @@ #include "mini-gc.h" #include "debugger-agent.h" -#if defined(HAVE_KW_THREAD) -#define MINI_FAST_TLS_SET(x,y) x = y -#define MINI_FAST_TLS_GET(x) x -#define MINI_FAST_TLS_INIT(x) -#define MINI_FAST_TLS_DECLARE(x) static __thread gpointer x MONO_TLS_FAST; -#define MINI_HAVE_FAST_TLS -#define MINI_THREAD_VAR_OFFSET(x,y) MONO_THREAD_VAR_OFFSET(x,y) -#elif (defined(__APPLE__) && defined(__i386__)) -#define MINI_FAST_TLS_SET(x,y) pthread_setspecific(x, y) -#define MINI_FAST_TLS_GET(x) pthread_getspecific(x) -#define MINI_FAST_TLS_INIT(x) pthread_key_create(&x, NULL) -#define MINI_FAST_TLS_DECLARE(x) static pthread_key_t x; -#define MINI_HAVE_FAST_TLS -#define MINI_THREAD_VAR_OFFSET(x,y) y = (gint32) x -#else -#define MINI_THREAD_VAR_OFFSET(x,y) MONO_THREAD_VAR_OFFSET(x,y) -#endif - static gpointer mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoException **ex); static guint32 default_opt = 0; static gboolean default_opt_set = FALSE; -guint32 mono_jit_tls_id = -1; +MonoNativeTlsKey mono_jit_tls_id; -#ifdef MINI_HAVE_FAST_TLS -MINI_FAST_TLS_DECLARE(mono_jit_tls); +#ifdef MONO_HAVE_FAST_TLS +MONO_FAST_TLS_DECLARE(mono_jit_tls); #endif #ifndef MONO_ARCH_MONITOR_ENTER_ADJUSTMENT @@ -104,7 +88,6 @@ MINI_FAST_TLS_DECLARE(mono_jit_tls); #endif MonoTraceSpec *mono_jit_trace_calls = NULL; -gboolean mono_break_on_exc = FALSE; gboolean mono_compile_aot = FALSE; /* If this is set, no code is generated dynamically, everything is taken from AOT files */ gboolean mono_aot_only = FALSE; @@ -396,6 +379,7 @@ mono_print_method_from_ip (void *ip) } else g_print ("No method at %p\n", ip); + fflush (stdout); return; } method = mono_method_full_name (ji->method, TRUE); @@ -405,6 +389,7 @@ mono_print_method_from_ip (void *ip) if (source) g_print ("%s:%d\n", source->source_file, source->row); + fflush (stdout); mono_debug_free_source_location (source); g_free (method); @@ -1125,7 +1110,7 @@ mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode, memset (&cfg->vars [orig_count], 0, (cfg->varinfo_count - orig_count) * sizeof (MonoMethodVar)); } - mono_jit_stats.allocate_var++; + cfg->stat_allocate_var++; MONO_INST_NEW (cfg, inst, opcode); inst->inst_c0 = num; @@ -1141,7 +1126,7 @@ mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode, mono_mark_vreg_as_mp (cfg, vreg); } else { MonoType *t = mini_type_get_underlying_type (NULL, type); - if ((MONO_TYPE_ISSTRUCT (t) && inst->klass->has_references) || MONO_TYPE_IS_REFERENCE (t)) { + if ((MONO_TYPE_ISSTRUCT (t) && inst->klass->has_references) || mini_type_is_reference (cfg, t)) { inst->flags |= MONO_INST_GC_TRACK; mono_mark_vreg_as_ref (cfg, vreg); } @@ -1507,12 +1492,13 @@ mini_method_verify (MonoCompile *cfg, MonoMethod *method, gboolean fail_compile) if (method->verification_success) return FALSE; - is_fulltrust = mono_verifier_is_method_full_trust (method); - if (!mono_verifier_is_enabled_for_method (method)) return FALSE; - res = mono_method_verify_with_current_settings (method, cfg->skip_visibility); + /*skip verification implies the assembly must be */ + is_fulltrust = mono_verifier_is_method_full_trust (method) || mini_assembly_can_skip_verification (cfg->domain, method); + + res = mono_method_verify_with_current_settings (method, cfg->skip_visibility, is_fulltrust); if ((error = mono_loader_get_last_error ())) { if (fail_compile) @@ -1559,8 +1545,7 @@ gboolean mono_compile_is_broken (MonoCompile *cfg, MonoMethod *method, gboolean fail_compile) { MonoMethod *method_definition = method; - gboolean dont_verify = mini_assembly_can_skip_verification (cfg->domain, method); - dont_verify |= method->klass->image->assembly->corlib_internal; + gboolean dont_verify = method->klass->image->assembly->corlib_internal; while (method_definition->is_inflated) { MonoMethodInflated *imethod = (MonoMethodInflated *) method_definition; @@ -1673,7 +1658,7 @@ compare_by_interval_start_pos_func (gconstpointer a, gconstpointer b) #endif static gint32* -mono_allocate_stack_slots_full2 (MonoCompile *cfg, gboolean backward, guint32 *stack_size, guint32 *stack_align) +mono_allocate_stack_slots2 (MonoCompile *cfg, gboolean backward, guint32 *stack_size, guint32 *stack_align) { int i, slot, offset, size; guint32 align; @@ -1916,6 +1901,12 @@ mono_allocate_stack_slots_full2 (MonoCompile *cfg, gboolean backward, guint32 *s LSCAN_DEBUG (printf ("R%d %s -> 0x%x\n", inst->dreg, mono_type_full_name (t), slot)); + if (inst->flags & MONO_INST_LMF) { + size = sizeof (MonoLMF); + align = sizeof (mgreg_t); + reuse_slot = FALSE; + } + if (!reuse_slot) slot = 0xffffff; @@ -1959,14 +1950,14 @@ mono_allocate_stack_slots_full2 (MonoCompile *cfg, gboolean backward, guint32 *s g_list_free (vtype_stack_slots [i].active); } - mono_jit_stats.locals_stack_size += offset; + cfg->stat_locals_stack_size += offset; *stack_size = offset; return offsets; } /* - * mono_allocate_stack_slots_full: + * mono_allocate_stack_slots: * * Allocate stack slots for all non register allocated variables using a * linear scan algorithm. @@ -1975,7 +1966,7 @@ mono_allocate_stack_slots_full2 (MonoCompile *cfg, gboolean backward, guint32 *s * STACK_ALIGN is set to the alignment needed by the locals area. */ gint32* -mono_allocate_stack_slots_full (MonoCompile *cfg, gboolean backward, guint32 *stack_size, guint32 *stack_align) +mono_allocate_stack_slots (MonoCompile *cfg, gboolean backward, guint32 *stack_size, guint32 *stack_align) { int i, slot, offset, size; guint32 align; @@ -1989,7 +1980,7 @@ mono_allocate_stack_slots_full (MonoCompile *cfg, gboolean backward, guint32 *st gboolean reuse_slot; if ((cfg->num_varinfo > 0) && MONO_VARINFO (cfg, 0)->interval) - return mono_allocate_stack_slots_full2 (cfg, backward, stack_size, stack_align); + return mono_allocate_stack_slots2 (cfg, backward, stack_size, stack_align); scalar_stack_slots = mono_mempool_alloc0 (cfg->mempool, sizeof (StackSlotInfo) * MONO_TYPE_PINNED); vtype_stack_slots = NULL; @@ -2144,6 +2135,16 @@ mono_allocate_stack_slots_full (MonoCompile *cfg, gboolean backward, guint32 *st */ } + if (inst->flags & MONO_INST_LMF) { + /* + * This variable represents a MonoLMF structure, which has no corresponding + * CLR type, so hard-code its size/alignment. + */ + size = sizeof (MonoLMF); + align = sizeof (mgreg_t); + reuse_slot = FALSE; + } + if (!reuse_slot) slot = 0xffffff; @@ -2191,7 +2192,7 @@ mono_allocate_stack_slots_full (MonoCompile *cfg, gboolean backward, guint32 *st g_list_free (vtype_stack_slots [i].active); } - mono_jit_stats.locals_stack_size += offset; + cfg->stat_locals_stack_size += offset; *stack_size = offset; return offsets; @@ -2200,7 +2201,7 @@ mono_allocate_stack_slots_full (MonoCompile *cfg, gboolean backward, guint32 *st #else gint32* -mono_allocate_stack_slots_full (MonoCompile *cfg, gboolean backward, guint32 *stack_size, guint32 *stack_align) +mono_allocate_stack_slots (MonoCompile *cfg, gboolean backward, guint32 *stack_size, guint32 *stack_align) { g_assert_not_reached (); return NULL; @@ -2208,12 +2209,6 @@ mono_allocate_stack_slots_full (MonoCompile *cfg, gboolean backward, guint32 *st #endif /* DISABLE_JIT */ -gint32* -mono_allocate_stack_slots (MonoCompile *m, guint32 *stack_size, guint32 *stack_align) -{ - return mono_allocate_stack_slots_full (m, TRUE, stack_size, stack_align); -} - #define EMUL_HIT_SHIFT 3 #define EMUL_HIT_MASK ((1 << EMUL_HIT_SHIFT) - 1) /* small hit bitmap cache */ @@ -2455,18 +2450,18 @@ mono_destroy_compile (MonoCompile *cfg) g_free (cfg); } -#ifdef MINI_HAVE_FAST_TLS -MINI_FAST_TLS_DECLARE(mono_lmf_addr); +#ifdef MONO_HAVE_FAST_TLS +MONO_FAST_TLS_DECLARE(mono_lmf_addr); #ifdef MONO_ARCH_ENABLE_MONO_LMF_VAR /* * When this is defined, the current lmf is stored in this tls variable instead of in * jit_tls->lmf. */ -MINI_FAST_TLS_DECLARE(mono_lmf); +MONO_FAST_TLS_DECLARE(mono_lmf); #endif #endif -guint32 +MonoNativeTlsKey mono_get_jit_tls_key (void) { return mono_jit_tls_id; @@ -2475,21 +2470,17 @@ mono_get_jit_tls_key (void) gint32 mono_get_jit_tls_offset (void) { -#ifdef MINI_HAVE_FAST_TLS int offset; - MINI_THREAD_VAR_OFFSET (mono_jit_tls, offset); + MONO_THREAD_VAR_OFFSET (mono_jit_tls, offset); return offset; -#else - return -1; -#endif } gint32 mono_get_lmf_tls_offset (void) { -#if defined(MINI_HAVE_FAST_TLS) && defined(MONO_ARCH_ENABLE_MONO_LMF_VAR) +#if defined(MONO_ARCH_ENABLE_MONO_LMF_VAR) int offset; - MINI_THREAD_VAR_OFFSET(mono_lmf,offset); + MONO_THREAD_VAR_OFFSET(mono_lmf,offset); return offset; #else return -1; @@ -2500,19 +2491,19 @@ gint32 mono_get_lmf_addr_tls_offset (void) { int offset; - MINI_THREAD_VAR_OFFSET(mono_lmf_addr,offset); + MONO_THREAD_VAR_OFFSET(mono_lmf_addr,offset); return offset; } MonoLMF * mono_get_lmf (void) { -#if defined(MINI_HAVE_FAST_TLS) && defined(MONO_ARCH_ENABLE_MONO_LMF_VAR) - return MINI_FAST_TLS_GET (mono_lmf); +#if defined(MONO_HAVE_FAST_TLS) && defined(MONO_ARCH_ENABLE_MONO_LMF_VAR) + return MONO_FAST_TLS_GET (mono_lmf); #else MonoJitTlsData *jit_tls; - if ((jit_tls = TlsGetValue (mono_jit_tls_id))) + if ((jit_tls = mono_native_tls_get_value (mono_jit_tls_id))) return jit_tls->lmf; /* * We do not assert here because this function can be called from @@ -2526,12 +2517,12 @@ mono_get_lmf (void) MonoLMF ** mono_get_lmf_addr (void) { -#ifdef MINI_HAVE_FAST_TLS - return MINI_FAST_TLS_GET (mono_lmf_addr); +#ifdef MONO_HAVE_FAST_TLS + return MONO_FAST_TLS_GET (mono_lmf_addr); #else MonoJitTlsData *jit_tls; - if ((jit_tls = TlsGetValue (mono_jit_tls_id))) + if ((jit_tls = mono_native_tls_get_value (mono_jit_tls_id))) return &jit_tls->lmf; /* @@ -2544,7 +2535,7 @@ mono_get_lmf_addr (void) mono_jit_thread_attach (NULL); - if ((jit_tls = TlsGetValue (mono_jit_tls_id))) + if ((jit_tls = mono_native_tls_get_value (mono_jit_tls_id))) return &jit_tls->lmf; g_assert_not_reached (); @@ -2555,8 +2546,8 @@ mono_get_lmf_addr (void) void mono_set_lmf (MonoLMF *lmf) { -#if defined(MINI_HAVE_FAST_TLS) && defined(MONO_ARCH_ENABLE_MONO_LMF_VAR) - MINI_FAST_TLS_SET (mono_lmf, lmf); +#if defined(MONO_HAVE_FAST_TLS) && defined(MONO_ARCH_ENABLE_MONO_LMF_VAR) + MONO_FAST_TLS_SET (mono_lmf, lmf); #endif (*mono_get_lmf_addr ()) = lmf; @@ -2565,18 +2556,18 @@ mono_set_lmf (MonoLMF *lmf) static void mono_set_jit_tls (MonoJitTlsData *jit_tls) { - TlsSetValue (mono_jit_tls_id, jit_tls); + mono_native_tls_set_value (mono_jit_tls_id, jit_tls); -#ifdef MINI_HAVE_FAST_TLS - MINI_FAST_TLS_SET (mono_jit_tls, jit_tls); +#ifdef MONO_HAVE_FAST_TLS + MONO_FAST_TLS_SET (mono_jit_tls, jit_tls); #endif } static void mono_set_lmf_addr (gpointer lmf_addr) { -#ifdef MINI_HAVE_FAST_TLS - MINI_FAST_TLS_SET (mono_lmf_addr, lmf_addr); +#ifdef MONO_HAVE_FAST_TLS + MONO_FAST_TLS_SET (mono_lmf_addr, lmf_addr); #endif } @@ -2591,13 +2582,17 @@ mono_jit_thread_attach (MonoDomain *domain) */ domain = mono_get_root_domain (); -#ifdef MINI_HAVE_FAST_TLS - if (!MINI_FAST_TLS_GET (mono_lmf_addr)) { +#ifdef MONO_HAVE_FAST_TLS + if (!MONO_FAST_TLS_GET (mono_lmf_addr)) { mono_thread_attach (domain); + // #678164 + mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background); } #else - if (!TlsGetValue (mono_jit_tls_id)) + if (!mono_native_tls_get_value (mono_jit_tls_id)) { mono_thread_attach (domain); + mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background); + } #endif if (mono_domain_get () != domain) mono_domain_set (domain, TRUE); @@ -2612,7 +2607,7 @@ mono_jit_thread_attach (MonoDomain *domain) static void mono_thread_abort (MonoObject *obj) { - /* MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id); */ + /* MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id); */ /* handle_remove should be eventually called for this thread, too g_free (jit_tls);*/ @@ -2621,6 +2616,15 @@ mono_thread_abort (MonoObject *obj) (obj->vtable->klass == mono_defaults.threadabortexception_class)) { mono_thread_exit (); } else { + MonoObject *other = NULL; + MonoString *str = mono_object_to_string (obj, &other); + if (str) { + char *msg = mono_string_to_utf8 (str); + fprintf (stderr, "[ERROR] FATAL UNHANDLED EXCEPTION: %s\n", msg); + fflush (stderr); + g_free (msg); + } + exit (mono_environment_exitcode_get ()); } } @@ -2631,7 +2635,7 @@ setup_jit_tls_data (gpointer stack_start, gpointer abort_func) MonoJitTlsData *jit_tls; MonoLMF *lmf; - jit_tls = TlsGetValue (mono_jit_tls_id); + jit_tls = mono_native_tls_get_value (mono_jit_tls_id); if (jit_tls) return jit_tls; @@ -2647,9 +2651,9 @@ setup_jit_tls_data (gpointer stack_start, gpointer abort_func) jit_tls->first_lmf = lmf; -#if defined(MINI_HAVE_FAST_TLS) && defined(MONO_ARCH_ENABLE_MONO_LMF_VAR) +#if defined(MONO_HAVE_FAST_TLS) && defined(MONO_ARCH_ENABLE_MONO_LMF_VAR) /* jit_tls->lmf is unused */ - MINI_FAST_TLS_SET (mono_lmf, lmf); + MONO_FAST_TLS_SET (mono_lmf, lmf); mono_set_lmf_addr (&mono_lmf); #else mono_set_lmf_addr (&jit_tls->lmf); @@ -2726,9 +2730,12 @@ mini_thread_cleanup (MonoInternalThread *thread) * * The current offender is mono_thread_manage which cleanup threads from the outside. */ - if (thread == mono_thread_internal_current ()) { - mono_set_lmf (NULL); + if (thread == mono_thread_internal_current ()) mono_set_jit_tls (NULL); + + /* If we attach a thread but never call into managed land, we might never get an lmf.*/ + if (mono_get_lmf ()) { + mono_set_lmf (NULL); mono_set_lmf_addr (NULL); } @@ -2990,7 +2997,7 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, target = code; } else { /* get the trampoline to the method from the domain */ - target = mono_create_jit_trampoline (patch_info->data.method); + target = mono_create_jit_trampoline_in_domain (domain, patch_info->data.method); } break; case MONO_PATCH_INFO_SWITCH: { @@ -3038,6 +3045,7 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, case MONO_PATCH_INFO_CLASS: case MONO_PATCH_INFO_IMAGE: case MONO_PATCH_INFO_FIELD: + case MONO_PATCH_INFO_SIGNATURE: target = patch_info->data.target; break; case MONO_PATCH_INFO_IID: @@ -3084,7 +3092,7 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, if (run_cctors) mono_runtime_class_init (vtable); } - target = (char*)vtable->data + patch_info->data.field->offset; + target = (char*)mono_vtable_get_static_field_data (vtable) + patch_info->data.field->offset; break; } case MONO_PATCH_INFO_RVA: { @@ -3407,7 +3415,7 @@ mono_postprocess_patches (MonoCompile *cfg) break; } case MONO_PATCH_INFO_METHOD_JUMP: { - GSList *list; + MonoJumpList *jlist; MonoDomain *domain = cfg->domain; unsigned char *ip = cfg->native_code + patch_info->ip.i; #if defined(__native_client__) && defined(__native_client_codegen__) @@ -3418,11 +3426,12 @@ mono_postprocess_patches (MonoCompile *cfg) #endif mono_domain_lock (domain); - if (!domain_jit_info (domain)->jump_target_hash) - domain_jit_info (domain)->jump_target_hash = g_hash_table_new (NULL, NULL); - list = g_hash_table_lookup (domain_jit_info (domain)->jump_target_hash, patch_info->data.method); - list = g_slist_prepend (list, ip); - g_hash_table_insert (domain_jit_info (domain)->jump_target_hash, patch_info->data.method, list); + jlist = g_hash_table_lookup (domain_jit_info (domain)->jump_target_hash, patch_info->data.method); + if (!jlist) { + jlist = mono_domain_alloc0 (domain, sizeof (MonoJumpList)); + g_hash_table_insert (domain_jit_info (domain)->jump_target_hash, patch_info->data.method, jlist); + } + jlist->list = g_slist_prepend (jlist->list, ip); mono_domain_unlock (domain); break; } @@ -3438,12 +3447,21 @@ collect_pred_seq_points (MonoBasicBlock *bb, MonoInst *ins, GSList **next, int d { int i; MonoBasicBlock *in_bb; + GSList *l; for (i = 0; i < bb->in_count; ++i) { in_bb = bb->in_bb [i]; if (in_bb->last_seq_point) { - next [in_bb->last_seq_point->backend.size] = g_slist_append (next [in_bb->last_seq_point->backend.size], GUINT_TO_POINTER (ins->backend.size)); + int src_index = in_bb->last_seq_point->backend.size; + int dst_index = ins->backend.size; + + /* bb->in_bb might contain duplicates */ + for (l = next [src_index]; l; l = l->next) + if (GPOINTER_TO_UINT (l->data) == dst_index) + break; + if (!l) + next [src_index] = g_slist_append (next [src_index], GUINT_TO_POINTER (dst_index)); } else { /* Have to look at its predecessors */ if (depth < 5) @@ -3490,7 +3508,8 @@ mono_save_seq_point_info (MonoCompile *cfg) for (l = bb_seq_points; l; l = l->next) { MonoInst *ins = l->data; - if (!(ins->flags & MONO_INST_SINGLE_STEP_LOC)) + if (ins->inst_imm == METHOD_ENTRY_IL_OFFSET || ins->inst_imm == METHOD_EXIT_IL_OFFSET) + /* Used to implement method entry/exit events */ continue; if (last != NULL) { @@ -3634,8 +3653,6 @@ mono_codegen (MonoCompile *cfg) max_epilog_size = 0; - code = cfg->native_code + cfg->code_len; - /* we always allocate code in cfg->domain->code_mp to increase locality */ cfg->code_size = cfg->code_len + max_epilog_size; /* fixme: align to MONO_ARCH_CODE_ALIGNMENT */ @@ -3668,6 +3685,7 @@ mono_codegen (MonoCompile *cfg) nacl_allow_target_modification (TRUE); #endif + g_assert (code); memcpy (code, cfg->native_code, cfg->code_len); #if defined(__default_codegen__) g_free (cfg->native_code); @@ -3732,7 +3750,7 @@ if (valgrind_register){ mono_nacl_fix_patches (cfg->native_code, cfg->patch_info); #endif - mono_arch_patch_code (cfg->method, cfg->domain, cfg->native_code, cfg->patch_info, cfg->run_cctors); + mono_arch_patch_code (cfg->method, cfg->domain, cfg->native_code, cfg->patch_info, cfg->dynamic_info ? cfg->dynamic_info->code_mp : NULL, cfg->run_cctors); if (cfg->method->dynamic) { if (mono_using_xdebug) @@ -3789,8 +3807,9 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile) MonoMethodHeader *header; MonoJitInfo *jinfo; int num_clauses; - int generic_info_size; + int generic_info_size, arch_eh_info_size = 0; int holes_size = 0, num_holes = 0; + guint32 stack_size = 0; g_assert (method_to_compile == cfg->method); header = cfg->header; @@ -3800,6 +3819,21 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile) else generic_info_size = 0; + if (cfg->arch_eh_jit_info) { + MonoJitArgumentInfo *arg_info; + MonoMethodSignature *sig = mono_method_signature (cfg->method_to_register); + + /* + * This cannot be computed during stack walking, as + * mono_arch_get_argument_info () is not signal safe. + */ + arg_info = g_newa (MonoJitArgumentInfo, sig->param_count + 1); + stack_size = mono_arch_get_argument_info (sig, sig->param_count, arg_info); + + if (stack_size) + arch_eh_info_size = sizeof (MonoArchEHJitInfo); + } + if (cfg->try_block_holes) { for (tmp = cfg->try_block_holes; tmp; tmp = tmp->next) { TryBlockHole *hole = tmp->data; @@ -3825,11 +3859,11 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile) if (cfg->method->dynamic) { jinfo = g_malloc0 (MONO_SIZEOF_JIT_INFO + (num_clauses * sizeof (MonoJitExceptionInfo)) + - generic_info_size + holes_size); + generic_info_size + holes_size + arch_eh_info_size); } else { jinfo = mono_domain_alloc0 (cfg->domain, MONO_SIZEOF_JIT_INFO + (num_clauses * sizeof (MonoJitExceptionInfo)) + - generic_info_size + holes_size); + generic_info_size + holes_size + arch_eh_info_size); } jinfo->method = cfg->method_to_register; @@ -3927,6 +3961,15 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile) g_assert (i == num_holes); } + if (arch_eh_info_size) { + MonoArchEHJitInfo *info; + + jinfo->has_arch_eh_info = 1; + info = mono_jit_info_get_arch_eh_info (jinfo); + + info->stack_size = stack_size; + } + if (COMPILE_LLVM (cfg)) { if (num_clauses) memcpy (&jinfo->clauses [0], &cfg->llvm_ex_info [0], num_clauses * sizeof (MonoJitExceptionInfo)); @@ -4137,7 +4180,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool gboolean try_generic_shared, try_llvm = FALSE; MonoMethod *method_to_compile, *method_to_register; - mono_jit_stats.methods_compiled++; + InterlockedIncrement (&mono_jit_stats.methods_compiled); if (mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION) mono_profiler_method_jit (method); if (MONO_PROBE_METHOD_COMPILE_BEGIN_ENABLED ()) @@ -4188,6 +4231,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool cfg->orig_method = method; cfg->gen_seq_points = debug_options.gen_seq_points; cfg->explicit_null_checks = debug_options.explicit_null_checks; + cfg->soft_breakpoints = debug_options.soft_breakpoints; if (try_generic_shared) cfg->generic_sharing_context = (MonoGenericSharingContext*)&cfg->generic_sharing_context; cfg->compile_llvm = try_llvm; @@ -4448,8 +4492,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool return cfg; } - mono_jit_stats.basic_blocks += cfg->num_bblocks; - mono_jit_stats.max_basic_blocks = MAX (cfg->num_bblocks, mono_jit_stats.max_basic_blocks); + cfg->stat_basic_blocks += cfg->num_bblocks; if (COMPILE_LLVM (cfg)) { MonoInst *ins; @@ -5254,23 +5297,39 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in prof_options = cfg->prof_options; + /* + * Update global stats while holding a lock, instead of doing many + * InterlockedIncrement operations during JITting. + */ + mono_jit_stats.allocate_var += cfg->stat_allocate_var; + mono_jit_stats.locals_stack_size += cfg->stat_locals_stack_size; + mono_jit_stats.basic_blocks += cfg->stat_basic_blocks; + mono_jit_stats.max_basic_blocks = MAX (cfg->stat_basic_blocks, mono_jit_stats.max_basic_blocks); + mono_jit_stats.cil_code_size += cfg->stat_cil_code_size; + mono_jit_stats.regvars += cfg->stat_n_regvars; + mono_jit_stats.inlineable_methods += cfg->stat_inlineable_methods; + mono_jit_stats.inlined_methods += cfg->stat_inlined_methods; + mono_jit_stats.cas_demand_generation += cfg->stat_cas_demand_generation; + mono_jit_stats.code_reallocs += cfg->stat_code_reallocs; + mono_destroy_compile (cfg); #ifndef DISABLE_JIT if (domain_jit_info (target_domain)->jump_target_hash) { MonoJumpInfo patch_info; - GSList *list, *tmp; - list = g_hash_table_lookup (domain_jit_info (target_domain)->jump_target_hash, method); - if (list) { + MonoJumpList *jlist; + GSList *tmp; + jlist = g_hash_table_lookup (domain_jit_info (target_domain)->jump_target_hash, method); + if (jlist) { patch_info.next = NULL; patch_info.ip.i = 0; patch_info.type = MONO_PATCH_INFO_METHOD_JUMP; patch_info.data.method = method; g_hash_table_remove (domain_jit_info (target_domain)->jump_target_hash, method); + + for (tmp = jlist->list; tmp; tmp = tmp->next) + mono_arch_patch_code (NULL, target_domain, tmp->data, &patch_info, NULL, TRUE); } - for (tmp = list; tmp; tmp = tmp->next) - mono_arch_patch_code (NULL, target_domain, tmp->data, &patch_info, TRUE); - g_slist_free (list); } mono_emit_jit_map (jinfo); @@ -5363,6 +5422,8 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoException p = mono_create_ftnptr (target_domain, code); if (callinfo) { + /*mono_register_jit_icall_wrapper takes the loader lock, so we take it on the outside. */ + mono_loader_lock (); mono_jit_lock (); if (!callinfo->wrapper) { callinfo->wrapper = p; @@ -5370,6 +5431,7 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoException mono_debug_add_icall_wrapper (method, callinfo); } mono_jit_unlock (); + mono_loader_unlock (); } return p; @@ -5410,6 +5472,8 @@ mono_jit_free_method (MonoDomain *domain, MonoMethod *method) { MonoJitDynamicMethodInfo *ji; gboolean destroy = TRUE; + GHashTableIter iter; + MonoJumpList *jlist; g_assert (method->dynamic); @@ -5419,11 +5483,33 @@ mono_jit_free_method (MonoDomain *domain, MonoMethod *method) if (!ji) return; + + mono_debug_remove_method (method, domain); + mono_domain_lock (domain); g_hash_table_remove (domain_jit_info (domain)->dynamic_code_hash, method); mono_internal_hash_table_remove (&domain->jit_code_hash, method); g_hash_table_remove (domain_jit_info (domain)->jump_trampoline_hash, method); g_hash_table_remove (domain_jit_info (domain)->runtime_invoke_hash, method); + + /* Remove jump targets in this method */ + g_hash_table_iter_init (&iter, domain_jit_info (domain)->jump_target_hash); + while (g_hash_table_iter_next (&iter, NULL, (void**)&jlist)) { + GSList *tmp, *remove; + + remove = NULL; + for (tmp = jlist->list; tmp; tmp = tmp->next) { + guint8 *ip = tmp->data; + + if (ip >= (guint8*)ji->ji->code_start && ip < (guint8*)ji->ji->code_start + ji->ji->code_size) + remove = g_slist_prepend (remove, tmp); + } + for (tmp = remove; tmp; tmp = tmp->next) { + jlist->list = g_slist_delete_link (jlist->list, tmp->data); + } + g_slist_free (remove); + } + mono_domain_unlock (domain); #ifdef MONO_ARCH_HAVE_INVALIDATE_METHOD @@ -5754,7 +5840,7 @@ SIG_HANDLER_SIGNATURE (mono_sigfpe_signal_handler) mono_handle_native_sigsegv (SIGSEGV, ctx); } - mono_arch_handle_exception (ctx, exc, FALSE); + mono_arch_handle_exception (ctx, exc); } void @@ -5765,7 +5851,7 @@ SIG_HANDLER_SIGNATURE (mono_sigill_signal_handler) exc = mono_get_exception_execution_engine ("SIGILL"); - mono_arch_handle_exception (ctx, exc, FALSE); + mono_arch_handle_exception (ctx, exc); } #if defined(MONO_ARCH_USE_SIGACTION) || defined(HOST_WIN32) @@ -5776,7 +5862,7 @@ void SIG_HANDLER_SIGNATURE (mono_sigsegv_signal_handler) { MonoJitInfo *ji; - MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id); + MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id); gpointer fault_addr = NULL; GET_CONTEXT; @@ -5848,7 +5934,7 @@ SIG_HANDLER_SIGNATURE (mono_sigsegv_signal_handler) mono_handle_native_sigsegv (SIGSEGV, ctx); } - mono_arch_handle_exception (ctx, NULL, FALSE); + mono_arch_handle_exception (ctx, NULL); #endif } @@ -5860,7 +5946,7 @@ SIG_HANDLER_SIGNATURE (mono_sigint_signal_handler) exc = mono_get_exception_execution_engine ("Interrupted (SIGINT)."); - mono_arch_handle_exception (ctx, exc, FALSE); + mono_arch_handle_exception (ctx, exc); } /* mono_jit_create_remoting_trampoline: @@ -5977,6 +6063,8 @@ mini_parse_debug_options (void) debug_options.init_stacks = TRUE; else if (!strcmp (arg, "casts")) debug_options.better_cast_details = TRUE; + else if (!strcmp (arg, "soft-breakpoints")) + debug_options.soft_breakpoints = TRUE; else { fprintf (stderr, "Invalid option for the MONO_DEBUG env variable: %s\n", arg); fprintf (stderr, "Available options: 'handle-sigint', 'keep-delegates', 'reverse-pinvoke-exceptions', 'collect-pagefault-stats', 'break-on-unverified', 'no-gdb-backtrace', 'dont-free-domains', 'suspend-on-sigsegv', 'suspend-on-unhandled', 'dyn-runtime-invoke', 'gdb', 'explicit-null-checks', 'init-stacks'\n"); @@ -5996,16 +6084,20 @@ mini_get_debug_options (void) static gpointer mini_create_ftnptr (MonoDomain *domain, gpointer addr) { -#ifdef __ia64__ - gpointer *desc; +#if !defined(__ia64__) && !defined(__ppc64__) && !defined(__powerpc64__) + return addr; +#else + + gpointer* desc = NULL; + if ((desc = g_hash_table_lookup (domain->ftnptrs_hash, addr))) + return desc; +# ifdef __ia64__ desc = mono_domain_code_reserve (domain, 2 * sizeof (gpointer)); desc [0] = addr; desc [1] = NULL; - - return desc; -#elif defined(__ppc64__) || defined(__powerpc64__) +# elif defined(__ppc64__) || defined(__powerpc64__) gpointer *desc; desc = mono_domain_alloc0 (domain, 3 * sizeof (gpointer)); @@ -6013,10 +6105,9 @@ mini_create_ftnptr (MonoDomain *domain, gpointer addr) desc [0] = addr; desc [1] = NULL; desc [2] = NULL; - +# endif + g_hash_table_insert (domain->ftnptrs_hash, addr, desc); return desc; -#else - return addr; #endif } @@ -6035,9 +6126,21 @@ register_jit_stats (void) { mono_counters_register ("Compiled methods", MONO_COUNTER_JIT | MONO_COUNTER_WORD, &mono_jit_stats.methods_compiled); mono_counters_register ("Methods from AOT", MONO_COUNTER_JIT | MONO_COUNTER_WORD, &mono_jit_stats.methods_aot); - mono_counters_register ("Methods JITted using LLVM", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_with_llvm); mono_counters_register ("Methods JITted using mono JIT", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_without_llvm); + mono_counters_register ("Methods JITted using LLVM", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_with_llvm); mono_counters_register ("Total time spent JITting (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_time); + mono_counters_register ("Basic blocks", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.basic_blocks); + mono_counters_register ("Max basic blocks", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.max_basic_blocks); + mono_counters_register ("Allocated vars", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.allocate_var); + mono_counters_register ("Code reallocs", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.code_reallocs); + mono_counters_register ("Allocated code size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.allocated_code_size); + mono_counters_register ("Inlineable methods", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.inlineable_methods); + mono_counters_register ("Inlined methods", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.inlined_methods); + mono_counters_register ("Regvars", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.regvars); + mono_counters_register ("Locals stack size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.locals_stack_size); + mono_counters_register ("Method cache lookups", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_lookups); + mono_counters_register ("Compiled CIL code size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.cil_code_size); + mono_counters_register ("Native code size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.native_code_size); } static void runtime_invoke_info_free (gpointer value); @@ -6055,6 +6158,7 @@ mini_create_jit_domain_info (MonoDomain *domain) info->runtime_invoke_hash = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, runtime_invoke_info_free); info->seq_points = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, g_free); info->arch_seq_points = g_hash_table_new (mono_aligned_addr_hash, NULL); + info->jump_target_hash = g_hash_table_new (NULL, NULL); domain->runtime_info = info; } @@ -6062,7 +6166,8 @@ mini_create_jit_domain_info (MonoDomain *domain) static void delete_jump_list (gpointer key, gpointer value, gpointer user_data) { - g_slist_free (value); + MonoJumpList *jlist = value; + g_slist_free (jlist->list); } static void @@ -6090,10 +6195,8 @@ mini_free_jit_domain_info (MonoDomain *domain) { MonoJitDomainInfo *info = domain_jit_info (domain); - if (info->jump_target_hash) { - g_hash_table_foreach (info->jump_target_hash, delete_jump_list, NULL); - g_hash_table_destroy (info->jump_target_hash); - } + g_hash_table_foreach (info->jump_target_hash, delete_jump_list, NULL); + g_hash_table_destroy (info->jump_target_hash); if (info->jump_target_got_slot_hash) { g_hash_table_foreach (info->jump_target_got_slot_hash, delete_jump_list, NULL); g_hash_table_destroy (info->jump_target_got_slot_hash); @@ -6127,6 +6230,7 @@ mini_init (const char *filename, const char *runtime_version) { MonoDomain *domain; MonoRuntimeCallbacks callbacks; + MonoThreadInfoRuntimeCallbacks ticallbacks; MONO_PROBE_VES_INIT_BEGIN (); @@ -6148,11 +6252,11 @@ mini_init (const char *filename, const char *runtime_version) mini_debugger_init (); #endif -#ifdef MINI_HAVE_FAST_TLS - MINI_FAST_TLS_INIT (mono_jit_tls); - MINI_FAST_TLS_INIT (mono_lmf_addr); +#ifdef MONO_HAVE_FAST_TLS + MONO_FAST_TLS_INIT (mono_jit_tls); + MONO_FAST_TLS_INIT (mono_lmf_addr); #ifdef MONO_ARCH_ENABLE_MONO_LMF_VAR - MINI_FAST_TLS_INIT (mono_lmf); + MONO_FAST_TLS_INIT (mono_lmf); #endif #endif @@ -6171,6 +6275,8 @@ mini_init (const char *filename, const char *runtime_version) callbacks.get_addr_from_ftnptr = mini_get_addr_from_ftnptr; callbacks.get_runtime_build_info = mono_get_runtime_build_info; callbacks.set_cast_details = mono_set_cast_details; + callbacks.debug_log = mono_debugger_agent_debug_log; + callbacks.debug_log_is_enabled = mono_debugger_agent_debug_log_is_enabled; #ifdef MONO_ARCH_HAVE_IMT if (mono_use_imt) { @@ -6181,6 +6287,14 @@ mini_init (const char *filename, const char *runtime_version) mono_install_callbacks (&callbacks); + memset (&ticallbacks, 0, sizeof (ticallbacks)); + ticallbacks.setup_async_callback = mono_setup_async_callback; + ticallbacks.thread_state_init_from_sigctx = mono_thread_state_init_from_sigctx; + ticallbacks.thread_state_init_from_handle = mono_thread_state_init_from_handle; + + mono_threads_runtime_init (&ticallbacks); + + if (getenv ("MONO_DEBUG") != NULL) mini_parse_debug_options (); @@ -6218,7 +6332,7 @@ mini_init (const char *filename, const char *runtime_version) if (!g_thread_supported ()) g_thread_init (NULL); - mono_jit_tls_id = TlsAlloc (); + mono_native_tls_alloc (&mono_jit_tls_id, NULL); setup_jit_tls_data ((gpointer)-1, mono_thread_abort); if (default_opt & MONO_OPT_AOT) @@ -6260,7 +6374,6 @@ mini_init (const char *filename, const char *runtime_version) #ifdef JIT_INVOKE_WORKS mono_install_runtime_invoke (mono_jit_runtime_invoke); #endif - mono_install_stack_walk (mono_jit_walk_stack); mono_install_get_cached_class_info (mono_aot_get_cached_class_info); mono_install_get_class_from_name (mono_aot_get_class_from_name); mono_install_jit_info_find_in_aot (mono_aot_find_jit_info); @@ -6290,7 +6403,6 @@ mini_init (const char *filename, const char *runtime_version) /* This must come after mono_init () in the aot-only case */ mono_exceptions_init (); - mono_install_handler (mono_get_throw_exception ()); mono_icall_init (); @@ -6363,10 +6475,6 @@ mini_init (const char *filename, const char *runtime_version) #endif #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_DIV) - mono_register_opcode_emulation (CEE_DIV, "__emul_idiv", "int32 int32 int32", mono_idiv, FALSE); - mono_register_opcode_emulation (CEE_DIV_UN, "__emul_idiv_un", "int32 int32 int32", mono_idiv_un, FALSE); - mono_register_opcode_emulation (CEE_REM, "__emul_irem", "int32 int32 int32", mono_irem, FALSE); - mono_register_opcode_emulation (CEE_REM_UN, "__emul_irem_un", "int32 int32 int32", mono_irem_un, FALSE); mono_register_opcode_emulation (OP_IDIV, "__emul_op_idiv", "int32 int32 int32", mono_idiv, FALSE); mono_register_opcode_emulation (OP_IDIV_UN, "__emul_op_idiv_un", "int32 int32 int32", mono_idiv_un, FALSE); mono_register_opcode_emulation (OP_IREM, "__emul_op_irem", "int32 int32 int32", mono_irem, FALSE); @@ -6374,13 +6482,10 @@ mini_init (const char *filename, const char *runtime_version) #endif #ifdef MONO_ARCH_EMULATE_MUL_DIV - mono_register_opcode_emulation (CEE_MUL, "__emul_imul", "int32 int32 int32", mono_imul, TRUE); mono_register_opcode_emulation (OP_IMUL, "__emul_op_imul", "int32 int32 int32", mono_imul, TRUE); #endif #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_MUL_OVF) - mono_register_opcode_emulation (CEE_MUL_OVF, "__emul_imul_ovf", "int32 int32 int32", mono_imul_ovf, FALSE); - mono_register_opcode_emulation (CEE_MUL_OVF_UN, "__emul_imul_ovf_un", "int32 int32 int32", mono_imul_ovf_un, FALSE); mono_register_opcode_emulation (OP_IMUL_OVF, "__emul_op_imul_ovf", "int32 int32 int32", mono_imul_ovf, FALSE); mono_register_opcode_emulation (OP_IMUL_OVF_UN, "__emul_op_imul_ovf_un", "int32 int32 int32", mono_imul_ovf_un, FALSE); #endif @@ -6398,7 +6503,6 @@ mini_init (const char *filename, const char *runtime_version) mono_register_opcode_emulation (OP_FCONV_TO_I8, "__emul_fconv_to_i8", "long double", mono_fconv_i8, FALSE); #endif #ifdef MONO_ARCH_EMULATE_CONV_R8_UN - mono_register_opcode_emulation (CEE_CONV_R_UN, "__emul_conv_r_un", "double int32", mono_conv_to_r8_un, FALSE); mono_register_opcode_emulation (OP_ICONV_TO_R_UN, "__emul_iconv_to_r_un", "double int32", mono_conv_to_r8_un, FALSE); #endif #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8 @@ -6423,9 +6527,7 @@ mini_init (const char *filename, const char *runtime_version) mono_register_opcode_emulation (OP_FADD, "__emul_fadd", "double double double", mono_fadd, FALSE); mono_register_opcode_emulation (OP_FMUL, "__emul_fmul", "double double double", mono_fmul, FALSE); mono_register_opcode_emulation (OP_FNEG, "__emul_fneg", "double double", mono_fneg, FALSE); - mono_register_opcode_emulation (CEE_CONV_R8, "__emul_conv_r8", "double int32", mono_conv_to_r8, FALSE); mono_register_opcode_emulation (OP_ICONV_TO_R8, "__emul_iconv_to_r8", "double int32", mono_conv_to_r8, FALSE); - mono_register_opcode_emulation (CEE_CONV_R4, "__emul_conv_r4", "double int32", mono_conv_to_r4, FALSE); mono_register_opcode_emulation (OP_ICONV_TO_R4, "__emul_iconv_to_r4", "double int32", mono_conv_to_r4, FALSE); mono_register_opcode_emulation (OP_FCONV_TO_R4, "__emul_fconv_to_r4", "double double", mono_fconv_r4, FALSE); mono_register_opcode_emulation (OP_FCONV_TO_I1, "__emul_fconv_to_i1", "int8 double", mono_fconv_i1, FALSE); @@ -6507,6 +6609,8 @@ mini_init (const char *filename, const char *runtime_version) register_icall (mono_object_castclass_with_cache, "mono_object_castclass_with_cache", "object object ptr ptr", FALSE); register_icall (mono_object_isinst_with_cache, "mono_object_isinst_with_cache", "object object ptr ptr", FALSE); + register_icall (mono_debugger_agent_user_break, "mono_debugger_agent_user_break", "void", FALSE); + #endif mono_generic_sharing_init (); @@ -6547,22 +6651,10 @@ print_jit_stats (void) { if (mono_jit_stats.enabled) { g_print ("Mono Jit statistics\n"); - g_print ("Methods cache lookup: %ld\n", mono_jit_stats.methods_lookups); - g_print ("Basic blocks: %ld\n", mono_jit_stats.basic_blocks); - g_print ("Max basic blocks: %ld\n", mono_jit_stats.max_basic_blocks); - g_print ("Allocated vars: %ld\n", mono_jit_stats.allocate_var); - g_print ("Compiled CIL code size: %ld\n", mono_jit_stats.cil_code_size); - g_print ("Native code size: %ld\n", mono_jit_stats.native_code_size); g_print ("Max code size ratio: %.2f (%s)\n", mono_jit_stats.max_code_size_ratio/100.0, mono_jit_stats.max_ratio_method); g_print ("Biggest method: %ld (%s)\n", mono_jit_stats.biggest_method_size, mono_jit_stats.biggest_method); - g_print ("Code reallocs: %ld\n", mono_jit_stats.code_reallocs); - g_print ("Allocated code size: %ld\n", mono_jit_stats.allocated_code_size); - g_print ("Inlineable methods: %ld\n", mono_jit_stats.inlineable_methods); - g_print ("Inlined methods: %ld\n", mono_jit_stats.inlined_methods); - g_print ("Regvars: %ld\n", mono_jit_stats.regvars); - g_print ("Locals stack size: %ld\n", mono_jit_stats.locals_stack_size); g_print ("\nCreated object count: %ld\n", mono_stats.new_object_count); g_print ("Delegates created: %ld\n", mono_stats.delegate_creations); @@ -6649,7 +6741,7 @@ mini_cleanup (MonoDomain *domain) mono_runtime_cleanup (domain); #endif - free_jit_tls_data (TlsGetValue (mono_jit_tls_id)); + free_jit_tls_data (mono_native_tls_get_value (mono_jit_tls_id)); mono_icall_cleanup (); @@ -6690,7 +6782,7 @@ mini_cleanup (MonoDomain *domain) if (mono_inject_async_exc_method) mono_method_desc_free (mono_inject_async_exc_method); - TlsFree(mono_jit_tls_id); + mono_native_tls_free (mono_jit_tls_id); DeleteCriticalSection (&jit_mutex); @@ -6711,6 +6803,19 @@ mono_disable_optimizations (guint32 opts) default_opt &= ~opts; } +void +mono_set_optimizations (guint32 opts) +{ + default_opt = opts; + default_opt_set = TRUE; +} + +void +mono_set_verbose_level (guint32 level) +{ + mini_verbose = level; +} + /* * mono_get_runtime_build_info: *