static int mini_verbose = 0;
-/* Enable xdebug mode. See aot-compiler.c for documentation */
-static gboolean enable_xdebug = FALSE;
-
#define mono_jit_lock() EnterCriticalSection (&jit_mutex)
#define mono_jit_unlock() LeaveCriticalSection (&jit_mutex)
static CRITICAL_SECTION jit_mutex;
}
}
+/**
+ * mono_create_unwind_op:
+ *
+ * Create an unwind op with the given parameters.
+ */
+MonoUnwindOp*
+mono_create_unwind_op (int when, int tag, int reg, int val)
+{
+ MonoUnwindOp *op = g_new0 (MonoUnwindOp, 1);
+
+ op->op = tag;
+ op->reg = reg;
+ op->val = val;
+ op->when = when;
+
+ return op;
+}
+
/**
* mono_emit_unwind_op:
*
{
switch (opcode) {
case OP_ADD_IMM:
-#if SIZEOF_VOID_P == 4
+#if SIZEOF_REGISTER == 4
return OP_IADD;
#else
return OP_LADD;
case OP_IMUL_IMM:
return OP_IMUL;
case OP_AND_IMM:
-#if SIZEOF_VOID_P == 4
+#if SIZEOF_REGISTER == 4
return OP_IAND;
#else
return OP_LAND;
case OP_IREM_IMM:
return OP_IREM;
case OP_DIV_IMM:
-#if SIZEOF_VOID_P == 4
+#if SIZEOF_REGISTER == 4
return OP_IDIV;
#else
return OP_LDIV;
#endif
case OP_REM_IMM:
-#if SIZEOF_VOID_P == 4
+#if SIZEOF_REGISTER == 4
return OP_IREM;
#else
return OP_LREM;
if (vreg != -1)
set_vreg_to_inst (cfg, vreg, inst);
-#if SIZEOF_VOID_P == 4
+#if SIZEOF_REGISTER == 4
#ifdef MONO_ARCH_SOFT_FLOAT
regpair = mono_type_is_long (type) || mono_type_is_float (type);
#else
/* inst->backend.is_pinvoke indicates native sized value types, this is used by the
* pinvoke wrappers when they call functions returning structures */
- if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype) && inst->inst_vtype->type != MONO_TYPE_TYPEDBYREF)
- size = mono_class_native_size (inst->inst_vtype->data.klass, &align);
+ if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype) && inst->inst_vtype->type != MONO_TYPE_TYPEDBYREF) {
+ size = mono_class_native_size (mono_class_from_mono_type (inst->inst_vtype), &align);
+ }
else {
int ialign;
case MONO_TYPE_PTR:
case MONO_TYPE_I:
case MONO_TYPE_U:
-#if SIZEOF_VOID_P == 4
+#if SIZEOF_REGISTER == 4
case MONO_TYPE_I4:
#else
case MONO_TYPE_I8:
/* inst->backend.is_pinvoke indicates native sized value types, this is used by the
* pinvoke wrappers when they call functions returning structures */
- if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype) && inst->inst_vtype->type != MONO_TYPE_TYPEDBYREF)
- size = mono_class_native_size (inst->inst_vtype->data.klass, &align);
- else {
+ if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype) && inst->inst_vtype->type != MONO_TYPE_TYPEDBYREF) {
+ size = mono_class_native_size (mono_class_from_mono_type (inst->inst_vtype), &align);
+ } else {
int ialign;
size = mono_type_size (inst->inst_vtype, &ialign);
case MONO_TYPE_PTR:
case MONO_TYPE_I:
case MONO_TYPE_U:
-#if SIZEOF_VOID_P == 4
+#if SIZEOF_REGISTER == 4
case MONO_TYPE_I4:
#else
case MONO_TYPE_I8:
g_free (jit_tls->first_lmf);
g_free (jit_tls);
thread->jit_data = NULL;
- TlsSetValue (mono_jit_tls_id, NULL);
+
+ /* We can't clean up tls information if we are on another thread, it will clean up the wrong stuff
+ * It would be nice to issue a warning when this happens outside of the shutdown sequence. but it's
+ * not a trivial thing.
+ *
+ * The current offender is mono_thread_manage which cleanup threads from the outside.
+ */
+ if (thread == mono_thread_current ()) {
+ TlsSetValue (mono_jit_tls_id, NULL);
+
+#ifdef HAVE_KW_THREAD
+ mono_jit_tls = NULL;
+ mono_lmf_addr = NULL;
+#if defined(MONO_ARCH_ENABLE_MONO_LMF_VAR)
+ mono_lmf = NULL;
+#endif
+#endif
+ }
}
}
return mono_create_tls_get (cfg, mono_get_jit_tls_offset ());
}
+MonoInst*
+mono_get_domain_intrinsic (MonoCompile* cfg)
+{
+ return mono_create_tls_get (cfg, mono_domain_get_tls_offset ());
+}
+
+MonoInst*
+mono_get_thread_intrinsic (MonoCompile* cfg)
+{
+ return mono_create_tls_get (cfg, mono_thread_get_tls_offset ());
+}
+
void
mono_add_patch_info (MonoCompile *cfg, int ip, MonoJumpInfoType type, gconstpointer target)
{
}
}
+static MonoGenericContext
+construct_object_context_for_method (MonoMethod *method)
+{
+ MonoGenericContext object_context;
+
+ g_assert (method->wrapper_type == MONO_WRAPPER_NONE);
+ g_assert (!method->klass->generic_class);
+ if (method->klass->generic_container) {
+ int type_argc = method->klass->generic_container->type_argc;
+
+ object_context.class_inst = get_object_generic_inst (type_argc);
+ } else {
+ object_context.class_inst = NULL;
+ }
+
+ if (mini_method_get_context (method)->method_inst) {
+ int type_argc = mini_method_get_context (method)->method_inst->type_argc;
+
+ object_context.method_inst = get_object_generic_inst (type_argc);
+ } else {
+ object_context.method_inst = NULL;
+ }
+
+ g_assert (object_context.class_inst || object_context.method_inst);
+
+ return object_context;
+}
+
/*
* mini_method_compile:
* @method: the method to compile
/* The debugger needs all locals to be on the stack or in a global register */
cfg->disable_vreg_to_lvreg = TRUE;
+ /* Don't remove unused variables when running inside the debugger since the user
+ * may still want to view them. */
+ cfg->disable_deadce_vars = TRUE;
+
// cfg->opt |= MONO_OPT_SHARED;
cfg->opt &= ~MONO_OPT_DEADCE;
cfg->opt &= ~MONO_OPT_INLINE;
}
if (cfg->generic_sharing_context) {
- MonoGenericContext object_context;
-
- g_assert (!method_to_compile->klass->generic_class);
- if (method_to_compile->klass->generic_container) {
- int type_argc = method_to_compile->klass->generic_container->type_argc;
-
- object_context.class_inst = get_object_generic_inst (type_argc);
- } else {
- object_context.class_inst = NULL;
- }
-
- if (mini_method_get_context (method_to_compile)->method_inst) {
- int type_argc = mini_method_get_context (method_to_compile)->method_inst->type_argc;
-
- object_context.method_inst = get_object_generic_inst (type_argc);
- } else {
- object_context.method_inst = NULL;
- }
-
- g_assert (object_context.class_inst || object_context.method_inst);
+ MonoGenericContext object_context = construct_object_context_for_method (method_to_compile);
method_to_register = mono_class_inflate_generic_method (method_to_compile, &object_context);
} else {
}
}
+ if (cfg->unwind_ops) {
+ guint32 info_len;
+ guint8 *unwind_info = mono_unwind_ops_encode (cfg->unwind_ops, &info_len);
+
+ jinfo->used_regs = mono_cache_unwind_info (unwind_info, info_len);
+ g_free (unwind_info);
+ }
+
cfg->jit_info = jinfo;
#if defined(__arm__)
mono_arch_fixup_jinfo (cfg);
#endif
- if (enable_xdebug) {
-#ifndef DISABLE_AOT
- mono_save_xdebug_info (method_to_register, jinfo->code_start, jinfo->code_size, cfg->args, cfg->unwind_ops);
-#endif
- }
+ mono_save_xdebug_info (method_to_register, jinfo->code_start, jinfo->code_size, cfg->args, cfg->unwind_ops);
if (!cfg->compile_aot) {
mono_domain_lock (cfg->domain);
#endif /* DISABLE_JIT */
+MonoJitInfo*
+mono_domain_lookup_shared_generic (MonoDomain *domain, MonoMethod *open_method)
+{
+ static gboolean inited = FALSE;
+ static int lookups = 0;
+ static int failed_lookups = 0;
+
+ MonoGenericContext object_context;
+ MonoMethod *object_method;
+ MonoJitInfo *ji;
+
+ object_context = construct_object_context_for_method (open_method);
+ object_method = mono_class_inflate_generic_method (open_method, &object_context);
+
+ ji = mono_internal_hash_table_lookup (&domain->jit_code_hash, object_method);
+ if (ji && !ji->has_generic_jit_info)
+ ji = NULL;
+
+ if (!inited) {
+ mono_counters_register ("Shared generic lookups", MONO_COUNTER_INT|MONO_COUNTER_GENERICS, &lookups);
+ mono_counters_register ("Failed shared generic lookups", MONO_COUNTER_INT|MONO_COUNTER_GENERICS, &failed_lookups);
+ inited = TRUE;
+ }
+
+ ++lookups;
+ if (!ji)
+ ++failed_lookups;
+
+ return ji;
+}
+
static MonoJitInfo*
lookup_generic_method (MonoDomain *domain, MonoMethod *method)
{
if (!mono_method_is_generic_sharable_impl (method, FALSE))
return NULL;
- open_method = mono_method_get_declaring_generic_method (method);
+ open_method = mono_method_get_declaring_generic_method (method);
return mono_domain_lookup_shared_generic (domain, open_method);
}
mono_class_init (method->klass);
- mono_domain_lock (domain);
if ((code = mono_aot_get_method (domain, method))) {
- mono_domain_unlock (domain);
vtable = mono_class_vtable (domain, method->klass);
g_assert (vtable);
mono_runtime_class_init (vtable);
return code;
}
-
- mono_domain_unlock (domain);
}
#endif
mono_domain_jit_code_hash_unlock (target_domain);
code = cfg->native_code;
- if (cfg->generic_sharing_context && mono_method_is_generic_sharable_impl (method, FALSE)) {
- /* g_print ("inserting method %s.%s.%s\n", method->klass->name_space, method->klass->name, method->name); */
- mono_domain_register_shared_generic (target_domain,
- mono_method_get_declaring_generic_method (method), cfg->jit_info);
+ if (cfg->generic_sharing_context && mono_method_is_generic_sharable_impl (method, FALSE))
mono_stats.generics_shared_methods++;
- }
} else {
mono_domain_jit_code_hash_unlock (target_domain);
}
gboolean running_managed;
MonoException *exc;
MonoThread *thread = mono_thread_current ();
+ MonoDomain *domain = mono_domain_get ();
void *ji;
GET_CONTEXT;
+ if (!thread || !domain)
+ /* The thread might not have started up yet */
+ /* FIXME: Specify the synchronization with start_wrapper () in threads.c */
+ return;
+
if (thread->thread_dump_requested) {
thread->thread_dump_requested = FALSE;
mono_arch_init ();
+ mono_unwind_init ();
+
+ if (getenv ("MONO_XDEBUG")) {
+ mono_xdebug_init ();
+ /* So methods for multiple domains don't have the same address */
+ mono_dont_free_domains = TRUE;
+ }
+
mono_trampolines_init ();
if (!g_thread_supported ())
}
#endif
- if (getenv ("MONO_XDEBUG"))
- enable_xdebug = TRUE;
-
#define JIT_TRAMPOLINES_WORK
#ifdef JIT_TRAMPOLINES_WORK
mono_install_compile_method (mono_jit_compile_method);
register_icall (mono_fload_r4_arg, "mono_fload_r4_arg", "uint32 double", FALSE);
#endif
-#if SIZEOF_VOID_P == 4
+#if SIZEOF_REGISTER == 4
mono_register_opcode_emulation (OP_FCONV_TO_U, "__emul_fconv_to_u", "uint32 double", mono_fconv_u4, TRUE);
#endif
mono_trampolines_cleanup ();
+ mono_unwind_cleanup ();
+
if (!mono_dont_free_global_codeman)
mono_code_manager_destroy (global_codeman);
g_hash_table_destroy (jit_icall_name_hash);