*
* Copyright 2002-2003 Ximian, Inc.
* Copyright 2003-2010 Novell, Inc.
+ * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
*/
#define MONO_LLVM_IN_MINI 1
#include <mono/utils/mono-counters.h>
#include <mono/utils/mono-logger-internal.h>
#include <mono/utils/mono-mmap.h>
+#include <mono/utils/mono-tls.h>
#include <mono/utils/dtrace.h>
#include "mini.h"
#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
#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;
}
else
g_print ("No method at %p\n", ip);
+ fflush (stdout);
return;
}
method = mono_method_full_name (ji->method, TRUE);
if (source)
g_print ("%s:%d\n", source->source_file, source->row);
+ fflush (stdout);
mono_debug_free_source_location (source);
g_free (method);
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;
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);
}
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)
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;
#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;
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;
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.
* 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;
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;
*/
}
+ 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;
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;
#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;
#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 */
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;
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;
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
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;
/*
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 ();
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;
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
}
*/
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);
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);*/
(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 ());
}
}
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;
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);
*
* 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);
}
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: {
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:
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: {
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__)
#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;
}
{
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)
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) {
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 */
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);
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)
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;
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;
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;
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));
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 ())
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;
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;
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);
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;
mono_debug_add_icall_wrapper (method, callinfo);
}
mono_jit_unlock ();
+ mono_loader_unlock ();
}
return p;
{
MonoJitDynamicMethodInfo *ji;
gboolean destroy = TRUE;
+ GHashTableIter iter;
+ MonoJumpList *jlist;
g_assert (method->dynamic);
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
mono_handle_native_sigsegv (SIGSEGV, ctx);
}
- mono_arch_handle_exception (ctx, exc, FALSE);
+ mono_arch_handle_exception (ctx, exc);
}
void
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)
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;
mono_handle_native_sigsegv (SIGSEGV, ctx);
}
- mono_arch_handle_exception (ctx, NULL, FALSE);
+ mono_arch_handle_exception (ctx, NULL);
#endif
}
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:
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");
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));
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
}
{
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);
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;
}
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
{
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);
{
MonoDomain *domain;
MonoRuntimeCallbacks callbacks;
+ MonoThreadInfoRuntimeCallbacks ticallbacks;
MONO_PROBE_VES_INIT_BEGIN ();
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
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) {
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 ();
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)
#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);
/* This must come after mono_init () in the aot-only case */
mono_exceptions_init ();
- mono_install_handler (mono_get_throw_exception ());
mono_icall_init ();
#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);
#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
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
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);
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 ();
{
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);
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 ();
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);
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:
*