#include <mono/metadata/mempool-internals.h>
#include <mono/metadata/attach.h>
#include <mono/metadata/runtime.h>
+#include <mono/metadata/mono-debug-debugger.h>
#include <mono/utils/mono-math.h>
#include <mono/utils/mono-compiler.h>
#include <mono/utils/mono-counters.h>
#include <mono/utils/mono-tls.h>
#include <mono/utils/mono-hwcap.h>
#include <mono/utils/dtrace.h>
+#include <mono/utils/mono-signal-handler.h>
#include "mini.h"
#include "mini-llvm.h"
#include "jit-icalls.h"
-#include "debug-mini.h"
#include "mini-gc.h"
#include "debugger-agent.h"
-/* this macro is used for a runtime check done in mini_init () */
-#ifdef MONO_ARCH_EMULATE_MUL_DIV
-#define EMUL_MUL_DIV 1
-#else
-#define EMUL_MUL_DIV 0
-#endif
-
static gpointer mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoException **ex);
MONO_FAST_TLS_DECLARE(mono_jit_tls);
#endif
-#ifndef MONO_ARCH_MONITOR_ENTER_ADJUSTMENT
-#define MONO_ARCH_MONITOR_ENTER_ADJUSTMENT 1
-#endif
-
MonoTraceSpec *mono_jit_trace_calls = NULL;
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;
/* Whenever to use IMT */
-#ifdef MONO_ARCH_HAVE_IMT
-gboolean mono_use_imt = TRUE;
-#else
-gboolean mono_use_imt = FALSE;
-#endif
+gboolean mono_use_imt = ARCH_HAVE_IMT;
MonoMethodDesc *mono_inject_async_exc_method = NULL;
int mono_inject_async_exc_pos;
MonoMethodDesc *mono_break_at_bb_method = NULL;
gboolean mono_dont_free_global_codeman;
+static GSList *tramp_infos;
+
gpointer
mono_realloc_native_code (MonoCompile *cfg)
{
FindTrampUserData user_data;
MonoGenericSharingContext*gsctx;
const char *shared_type;
+ GSList *l;
ji = mini_jit_info_table_find (domain, ip, &target_domain);
if (!ji) {
char *mname = mono_method_full_name (user_data.method, TRUE);
printf ("IP %p is a JIT trampoline for %s\n", ip, mname);
g_free (mname);
+ return;
}
- else
- g_print ("No method at %p\n", ip);
+ for (l = tramp_infos; l; l = l->next) {
+ MonoTrampInfo *tinfo = l->data;
+
+ if ((guint8*)ip >= tinfo->code && (guint8*)ip <= tinfo->code + tinfo->code_size) {
+ printf ("IP %p is at offset 0x%x of trampoline '%s'.\n", ip, (int)((guint8*)ip - tinfo->code), tinfo->name);
+ return;
+ }
+ }
+
+ g_print ("No method at %p\n", ip);
fflush (stdout);
return;
}
op->when = when;
cfg->unwind_ops = g_slist_append_mempool (cfg->mempool, cfg->unwind_ops, op);
+ if (cfg->verbose_level > 1) {
+ switch (tag) {
+ case DW_CFA_def_cfa:
+ printf ("CFA: [%x] def_cfa: %s+0x%x\n", when, mono_arch_regname (reg), val);
+ break;
+ case DW_CFA_def_cfa_register:
+ printf ("CFA: [%x] def_cfa_reg: %s\n", when, mono_arch_regname (reg));
+ break;
+ case DW_CFA_def_cfa_offset:
+ printf ("CFA: [%x] def_cfa_offset: 0x%x\n", when, val);
+ break;
+ case DW_CFA_offset:
+ printf ("CFA: [%x] offset: %s at cfa-0x%x\n", when, mono_arch_regname (reg), -val);
+ break;
+ }
+ }
}
MonoJumpInfoToken *
g_free (info);
}
+/*
+ * mono_tramp_info_register:
+ *
+ * Remember INFO for use by xdebug, mono_print_method_from_ip (), jit maps, etc.
+ * INFO can be NULL.
+ * Frees INFO.
+ */
+void
+mono_tramp_info_register (MonoTrampInfo *info)
+{
+ MonoTrampInfo *copy;
+
+ if (!info)
+ return;
+
+ copy = g_new0 (MonoTrampInfo, 1);
+ copy->code = info->code;
+ copy->code_size = info->code_size;
+ copy->name = g_strdup (info->name);
+
+ mono_loader_lock_if_inited ();
+ tramp_infos = g_slist_prepend (tramp_infos, copy);
+ mono_loader_unlock_if_inited ();
+
+ mono_save_trampoline_xdebug_info (info);
+
+ if (mono_jit_map_is_enabled ())
+ mono_emit_jit_tramp (info->code, info->code_size, info->name);
+
+ mono_tramp_info_free (info);
+}
+
G_GNUC_UNUSED static void
break_count (void)
{
if (type->byref)
return OP_STORE_MEMBASE_REG;
+ type = mini_replace_type (type);
+
handle_enum:
switch (type->type) {
case MONO_TYPE_I1:
if (type->byref)
return OP_LOAD_MEMBASE;
- type = mono_type_get_underlying_type (type);
+ type = mini_replace_type (type);
switch (type->type) {
case MONO_TYPE_I1:
guint
mini_type_to_stind (MonoCompile* cfg, MonoType *type)
{
+ type = mini_replace_type (type);
+
if (cfg->generic_sharing_context && !type->byref) {
if (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) {
if (mini_type_var_is_vt (cfg, type))
int num = cfg->num_varinfo;
gboolean regpair;
+ type = mini_replace_type (type);
+
if ((num + 1) >= cfg->varinfo_count) {
int orig_count = cfg->varinfo_count;
cfg->varinfo_count = cfg->varinfo_count ? (cfg->varinfo_count * 2) : 64;
if (type->byref) {
mono_mark_vreg_as_mp (cfg, vreg);
} else {
- MonoType *t = mini_type_get_underlying_type (NULL, type);
+ MonoType *t = mini_replace_type (type);
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);
mono_compile_create_var (MonoCompile *cfg, MonoType *type, int opcode)
{
int dreg;
+ type = mini_replace_type (type);
if (mono_type_is_long (type))
dreg = mono_alloc_dreg (cfg, STACK_I8);
res = mono_metadata_signature_alloc (mono_defaults.corlib, arity + 1);
res->pinvoke = 1;
-#ifdef MONO_ARCH_VARARG_ICALLS
- /* Only set this only some archs since not all backends can handle varargs+pinvoke */
- res->call_convention = MONO_CALL_VARARG;
-#endif
+ if (ARCH_VARARG_ICALLS)
+ /* Only set this only some archs since not all backends can handle varargs+pinvoke */
+ res->call_convention = MONO_CALL_VARARG;
#ifdef TARGET_WIN32
res->call_convention = MONO_CALL_C;
MonoInternalThread *thread;
void *jit_tls = setup_jit_tls_data (stack_start, mono_thread_abort);
thread = mono_thread_internal_current ();
- mono_debugger_thread_created (tid, thread->root_domain_thread, jit_tls, func);
if (thread)
thread->jit_data = jit_tls;
MonoInternalThread *thread;
void *jit_tls = setup_jit_tls_data (stack_start, mono_thread_abort_dummy);
thread = mono_thread_internal_current ();
- mono_debugger_thread_created (tid, thread->root_domain_thread, (MonoJitTlsData *) jit_tls, NULL);
if (thread)
thread->jit_data = jit_tls;
if (mono_profiler_get_events () & MONO_PROFILE_STATISTICAL)
MonoJitTlsData *jit_tls = thread->jit_data;
if (jit_tls) {
- mono_debugger_thread_cleanup (jit_tls);
-
/* 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.
}
int
-mini_get_tls_offset (MonoJitTlsKey key)
+mini_get_tls_offset (MonoTlsKey key)
{
int offset;
case TLS_KEY_LMF:
offset = mono_get_lmf_tls_offset ();
break;
+ case TLS_KEY_LMF_ADDR:
+ offset = mono_get_lmf_addr_tls_offset ();
+ break;
default:
- g_assert_not_reached ();
- offset = -1;
+ offset = mono_tls_key_get_offset (key);
+ g_assert (offset != -1);
break;
}
+
return offset;
}
+#ifndef DISABLE_JIT
+
static MonoInst*
mono_create_tls_get_offset (MonoCompile *cfg, int offset)
{
return ins;
}
-static MonoInst*
-mono_create_tls_get (MonoCompile *cfg, MonoJitTlsKey key)
+gboolean
+mini_tls_get_supported (MonoCompile *cfg, MonoTlsKey key)
+{
+ if (!MONO_ARCH_HAVE_TLS_GET)
+ return FALSE;
+
+ if (cfg->compile_aot)
+ return ARCH_HAVE_TLS_GET_REG;
+ else
+ return mini_get_tls_offset (key) != -1;
+}
+
+MonoInst*
+mono_create_tls_get (MonoCompile *cfg, MonoTlsKey key)
{
/*
* TLS offsets might be different at AOT time, so load them from a GOT slot and
* use a different opcode.
*/
- if (cfg->compile_aot && MONO_ARCH_HAVE_TLS_GET && ARCH_HAVE_TLS_GET_REG) {
- MonoInst *ins, *c;
-
- EMIT_NEW_TLS_OFFSETCONST (cfg, c, key);
- MONO_INST_NEW (cfg, ins, OP_TLS_GET_REG);
- ins->dreg = mono_alloc_preg (cfg);
- ins->sreg1 = c->dreg;
- return ins;
+ if (cfg->compile_aot) {
+ if (MONO_ARCH_HAVE_TLS_GET && ARCH_HAVE_TLS_GET_REG) {
+ MonoInst *ins, *c;
+
+ EMIT_NEW_TLS_OFFSETCONST (cfg, c, key);
+ MONO_INST_NEW (cfg, ins, OP_TLS_GET_REG);
+ ins->dreg = mono_alloc_preg (cfg);
+ ins->sreg1 = c->dreg;
+ return ins;
+ } else {
+ return NULL;
+ }
}
return mono_create_tls_get_offset (cfg, mini_get_tls_offset (key));
return mono_create_tls_get (cfg, TLS_KEY_LMF);
}
+MonoInst*
+mono_get_lmf_addr_intrinsic (MonoCompile* cfg)
+{
+ return mono_create_tls_get (cfg, TLS_KEY_LMF_ADDR);
+}
+
+#endif /* !DISABLE_JIT */
+
void
mono_add_patch_info (MonoCompile *cfg, int ip, MonoJumpInfoType type, gconstpointer target)
{
cfg->patch_info = ji;
}
+void
+mono_add_patch_info_rel (MonoCompile *cfg, int ip, MonoJumpInfoType type, gconstpointer target, int relocation)
+{
+ MonoJumpInfo *ji = mono_mempool_alloc (cfg->mempool, sizeof (MonoJumpInfo));
+
+ ji->ip.i = ip;
+ ji->type = type;
+ ji->relocation = relocation;
+ ji->data.target = target;
+ ji->next = cfg->patch_info;
+
+ cfg->patch_info = ji;
+}
+
MonoJumpInfo *
mono_patch_info_list_prepend (MonoJumpInfo *list, int ip, MonoJumpInfoType type, gconstpointer target)
{
case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
case MONO_PATCH_INFO_SIGNATURE:
case MONO_PATCH_INFO_TLS_OFFSET:
+ case MONO_PATCH_INFO_METHOD_CODE_SLOT:
return (ji->type << 8) | (gssize)ji->data.target;
case MONO_PATCH_INFO_GSHAREDVT_CALL:
return (ji->type << 8) | (gssize)ji->data.gsharedvt->method;
}
#endif
break;
+ case MONO_PATCH_INFO_METHOD_CODE_SLOT: {
+ gpointer code_slot;
+
+ mono_domain_lock (domain);
+ if (!domain_jit_info (domain)->method_code_hash)
+ domain_jit_info (domain)->method_code_hash = g_hash_table_new (NULL, NULL);
+ code_slot = g_hash_table_lookup (domain_jit_info (domain)->method_code_hash, patch_info->data.method);
+ if (!code_slot) {
+ code_slot = mono_domain_alloc0 (domain, sizeof (gpointer));
+ g_hash_table_insert (domain_jit_info (domain)->method_code_hash, patch_info->data.method, code_slot);
+ }
+ mono_domain_unlock (domain);
+ target = code_slot;
+ break;
+ }
case MONO_PATCH_INFO_SWITCH: {
gpointer *jump_table;
int i;
target = (gpointer) (size_t) mono_jit_tls_id;
break;
}
- case MONO_PATCH_INFO_TLS_OFFSET:
- target = GINT_TO_POINTER (mini_get_tls_offset (GPOINTER_TO_INT (patch_info->data.target)));
+ case MONO_PATCH_INFO_TLS_OFFSET: {
+ int offset;
+
+ offset = mini_get_tls_offset (GPOINTER_TO_INT (patch_info->data.target));
+#ifdef MONO_ARCH_HAVE_TRANSLATE_TLS_OFFSET
+ offset = mono_arch_translate_tls_offset (offset);
+#endif
+ target = GINT_TO_POINTER (offset);
break;
+ }
case MONO_PATCH_INFO_OBJC_SELECTOR_REF: {
target = NULL;
break;
g_print ("locals done\n");
mono_arch_create_vars (cfg);
+
+ if (cfg->method->save_lmf && cfg->create_lmf_var) {
+ MonoInst *lmf_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
+ lmf_var->flags |= MONO_INST_VOLATILE;
+ lmf_var->flags |= MONO_INST_LMF;
+ cfg->lmf_var = lmf_var;
+ }
}
void
* Its possible to generate dwarf unwind info for xdebug etc, but not actually
* using it during runtime, hence the define.
*/
-#ifdef MONO_ARCH_HAVE_XP_UNWIND
if (cfg->encoded_unwind_ops) {
jinfo->used_regs = mono_cache_unwind_info (cfg->encoded_unwind_ops, cfg->encoded_unwind_ops_len);
g_free (cfg->encoded_unwind_ops);
jinfo->used_regs = mono_cache_unwind_info (unwind_info, info_len);
g_free (unwind_info);
}
-#endif
return jinfo;
}
get_gsharedvt_type (MonoType *t)
{
MonoGenericParam *par = t->data.generic_param;
+ MonoGenericParam *copy;
MonoType *res;
+ MonoImage *image = NULL;
/*
* Create an anonymous gparam with a different serial so normal gshared and gsharedvt methods have
* a different instantiation.
*/
g_assert (mono_generic_param_info (par));
- par = g_memdup (par, sizeof (MonoGenericParamFull));
- par->owner = NULL;
+ if (par->owner) {
+ image = par->owner->image;
+
+ mono_image_lock (image);
+ if (!image->gsharedvt_types)
+ image->gsharedvt_types = g_hash_table_new (NULL, NULL);
+ res = g_hash_table_lookup (image->gsharedvt_types, par);
+ mono_image_unlock (image);
+ if (res)
+ return res;
+ copy = mono_image_alloc0 (image, sizeof (MonoGenericParamFull));
+ memcpy (copy, par, sizeof (MonoGenericParamFull));
+ } else {
+ copy = g_memdup (par, sizeof (MonoGenericParamFull));
+ }
+ copy->owner = NULL;
// FIXME:
- par->image = mono_defaults.corlib;
- par->serial = 1;
+ copy->image = mono_defaults.corlib;
+ copy->serial = 1;
res = mono_metadata_type_dup (NULL, t);
- res->data.generic_param = par;
+ res->data.generic_param = copy;
+
+ if (par->owner) {
+ mono_image_lock (image);
+ /* Duplicates are ok */
+ g_hash_table_insert (image->gsharedvt_types, par, res);
+ mono_image_unlock (image);
+ }
return res;
}
#endif
/* The debugger has no liveness information, so avoid sharing registers/stack slots */
- if (mono_debug_using_mono_debugger () || debug_options.mdb_optimizations) {
+ if (debug_options.mdb_optimizations) {
cfg->disable_reuse_registers = TRUE;
cfg->disable_reuse_stack_slots = TRUE;
/*
mono_handle_global_vregs (cfg);
if (cfg->opt & MONO_OPT_DEADCE)
mono_local_deadce (cfg);
+ if (cfg->opt & MONO_OPT_ALIAS_ANALYSIS)
+ mono_local_alias_analysis (cfg);
/* Disable this for LLVM to make the IR easier to handle */
if (!COMPILE_LLVM (cfg))
mono_if_conversion (cfg);
#endif
if (cfg->comp_done & MONO_COMP_SSA && COMPILE_LLVM (cfg)) {
+ mono_ssa_loop_invariant_code_motion (cfg);
/* This removes MONO_INST_FAULT flags too so perform it unconditionally */
if (cfg->opt & MONO_OPT_ABCREM)
mono_perform_abc_removal (cfg);
if (COMPILE_SOFT_FLOAT (cfg))
mono_decompose_soft_float (cfg);
#endif
- if (!COMPILE_LLVM (cfg))
+ if (COMPILE_LLVM (cfg))
+ mono_decompose_vtype_opts_llvm (cfg);
+ else
mono_decompose_vtype_opts (cfg);
if (cfg->flags & MONO_CFG_HAS_ARRAY_ACCESS)
mono_decompose_array_access_opts (cfg);
if (jinfo)
mono_profiler_method_end_jit (method, jinfo, MONO_PROFILE_OK);
return code;
-
- //if (mono_debug_format != MONO_DEBUG_FORMAT_NONE)
- //mono_debug_add_wrapper (method, nm);
} else if ((method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
const char *name = method->name;
char *full_name, *msg;
if (!callinfo->wrapper) {
callinfo->wrapper = p;
mono_register_jit_icall_wrapper (callinfo, p);
- mono_debug_add_icall_wrapper (method, callinfo);
}
mono_jit_unlock ();
mono_loader_unlock ();
MonoException *ex = NULL;
gpointer code;
- code = mono_jit_compile_method_with_opt (method, default_opt, &ex);
+ code = mono_jit_compile_method_with_opt (method, mono_get_optimizations_for_method (method, default_opt), &ex);
if (!code) {
g_assert (ex);
mono_raise_exception (ex);
return NULL;
}
+gboolean mono_do_single_method_regression = FALSE;
+guint32 mono_single_method_regression_opt = 0;
+MonoMethod *mono_current_single_method = NULL;
+GSList *mono_single_method_list = NULL;
+GHashTable *mono_single_method_hash = NULL;
+
+guint32
+mono_get_optimizations_for_method (MonoMethod *method, guint32 default_opt)
+{
+ g_assert (method);
+
+ if (!mono_do_single_method_regression)
+ return default_opt;
+ if (!mono_current_single_method) {
+ if (!mono_single_method_hash)
+ mono_single_method_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
+ if (!g_hash_table_lookup (mono_single_method_hash, method)) {
+ g_hash_table_insert (mono_single_method_hash, method, method);
+ mono_single_method_list = g_slist_prepend (mono_single_method_list, method);
+ }
+ return default_opt;
+ }
+ if (method == mono_current_single_method)
+ return mono_single_method_regression_opt;
+ return default_opt;
+}
+
gpointer
mono_jit_find_compiled_method (MonoDomain *domain, MonoMethod *method)
{
if (callee) {
MonoException *jit_ex = NULL;
- info->compiled_method = mono_jit_compile_method_with_opt (callee, default_opt, &jit_ex);
+ info->compiled_method = mono_jit_compile_method_with_opt (callee, mono_get_optimizations_for_method (callee, default_opt), &jit_ex);
if (!info->compiled_method) {
g_free (info);
g_assert (jit_ex);
*/
#ifdef MONO_ARCH_DYN_CALL_SUPPORTED
if (mono_aot_only || debug_options.dyn_runtime_invoke) {
+ MonoType *ret_type;
MonoMethodSignature *sig = mono_method_signature (method);
gboolean supported = TRUE;
int i;
if (supported)
info->dyn_call_info = mono_arch_dyn_call_prepare (sig);
+ ret_type = sig->ret;
if (info->dyn_call_info) {
- switch (sig->ret->type) {
+ switch (ret_type->type) {
case MONO_TYPE_VOID:
break;
case MONO_TYPE_I1:
case MONO_TYPE_CHAR:
case MONO_TYPE_R4:
case MONO_TYPE_R8:
- info->ret_box_class = mono_class_from_mono_type (sig->ret);
+ info->ret_box_class = mono_class_from_mono_type (ret_type);
break;
case MONO_TYPE_PTR:
info->ret_box_class = mono_defaults.int_class;
case MONO_TYPE_OBJECT:
break;
case MONO_TYPE_GENERICINST:
- if (!MONO_TYPE_IS_REFERENCE (sig->ret))
- info->ret_box_class = mono_class_from_mono_type (sig->ret);
+ if (!MONO_TYPE_IS_REFERENCE (ret_type))
+ info->ret_box_class = mono_class_from_mono_type (ret_type);
break;
case MONO_TYPE_VALUETYPE:
- info->ret_box_class = mono_class_from_mono_type (sig->ret);
+ info->ret_box_class = mono_class_from_mono_type (ret_type);
break;
default:
g_assert_not_reached ();
return runtime_invoke (obj, params, exc, info->compiled_method);
}
-void
-SIG_HANDLER_SIGNATURE (mono_sigfpe_signal_handler)
+SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler)
{
MonoException *exc = NULL;
MonoJitInfo *ji;
mono_arch_handle_exception (ctx, exc);
}
-void
-SIG_HANDLER_SIGNATURE (mono_sigill_signal_handler)
+SIG_HANDLER_FUNC (, mono_sigill_signal_handler)
{
MonoException *exc;
GET_CONTEXT;
#define HAVE_SIG_INFO
#endif
-void
-SIG_HANDLER_SIGNATURE (mono_sigsegv_signal_handler)
+SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
{
MonoJitInfo *ji;
MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
#endif
}
-void
-SIG_HANDLER_SIGNATURE (mono_sigint_signal_handler)
+SIG_HANDLER_FUNC (, mono_sigint_signal_handler)
{
MonoException *exc;
GET_CONTEXT;
desc [0] = addr;
desc [1] = NULL;
# elif defined(__ppc64__) || defined(__powerpc64__)
- gpointer *desc;
desc = mono_domain_alloc0 (domain, 3 * sizeof (gpointer));
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);
+ mono_counters_register ("Aliases found", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.alias_found);
+ mono_counters_register ("Aliases eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.alias_removed);
+ mono_counters_register ("Aliased loads eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.loads_eliminated);
+ mono_counters_register ("Aliased stores eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.stores_eliminated);
}
static void runtime_invoke_info_free (gpointer value);
InitializeCriticalSection (&jit_mutex);
-#ifdef MONO_DEBUGGER_SUPPORTED
- if (mini_debug_running_inside_mdb ())
- mini_debugger_init ();
-#endif
-
#ifdef MONO_HAVE_FAST_TLS
MONO_FAST_TLS_INIT (mono_jit_tls);
MONO_FAST_TLS_INIT (mono_lmf_addr);
register_opcode_emulation (OP_LDIV_UN, "__emul_ldiv_un", "long long long", mono_lldiv_un, "mono_lldiv_un", FALSE);
register_opcode_emulation (OP_LREM, "__emul_lrem", "long long long", mono_llrem, "mono_llrem", FALSE);
register_opcode_emulation (OP_LREM_UN, "__emul_lrem_un", "long long long", mono_llrem_un, "mono_llrem_un", FALSE);
+#endif
+#if !defined(MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS) || defined(MONO_ARCH_EMULATE_LONG_MUL_OVF_OPTS)
register_opcode_emulation (OP_LMUL_OVF_UN, "__emul_lmul_ovf_un", "long long long", mono_llmult_ovf_un, "mono_llmult_ovf_un", FALSE);
register_opcode_emulation (OP_LMUL_OVF, "__emul_lmul_ovf", "long long long", mono_llmult_ovf, "mono_llmult_ovf", FALSE);
#endif
#endif
#if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_SOFT_FLOAT_FALLBACK)
- if (EMUL_MUL_DIV || mono_arch_is_soft_float ()) {
+ if (ARCH_EMULATE_MUL_DIV || mono_arch_is_soft_float ()) {
register_opcode_emulation (OP_FDIV, "__emul_fdiv", "double double double", mono_fdiv, "mono_fdiv", FALSE);
}
#endif
#if SIZEOF_REGISTER == 4
register_opcode_emulation (OP_FCONV_TO_U, "__emul_fconv_to_u", "uint32 double", mono_fconv_u4, "mono_fconv_u4", TRUE);
+#else
+ register_opcode_emulation (OP_FCONV_TO_U, "__emul_fconv_to_u", "ulong double", mono_fconv_u8, "mono_fconv_u8", TRUE);
#endif
/* other jit icalls */
register_icall (mono_array_new_4, "mono_array_new_4", "object ptr int int int int", FALSE);
register_icall (mono_get_native_calli_wrapper, "mono_get_native_calli_wrapper", "ptr ptr ptr ptr", FALSE);
register_icall (mono_resume_unwind, "mono_resume_unwind", "void", TRUE);
- register_icall (mono_gsharedvt_constrained_call, "mono_gsharedvt_constrained_call", "object ptr ptr ptr ptr ptr", TRUE);
+ register_icall (mono_gsharedvt_constrained_call, "mono_gsharedvt_constrained_call", "object ptr ptr ptr ptr ptr", FALSE);
register_icall (mono_gsharedvt_value_copy, "mono_gsharedvt_value_copy", "void ptr ptr ptr", TRUE);
register_icall (mono_gc_wbarrier_value_copy_bitmap, "mono_gc_wbarrier_value_copy_bitmap", "void ptr ptr int int", FALSE);
mono_domain_free (domain, TRUE);
#endif
- mono_debugger_cleanup ();
-
#ifdef ENABLE_LLVM
if (mono_use_llvm)
mono_llvm_cleanup ();
return mono_arch_jumptable_entry_from_code (code_ptr);
}
#endif
+
+/*
+ * mini_replace_type:
+ *
+ * Replace the type used in the metadata stream with what the JIT will actually use during compilation.
+*/
+MonoType*
+mini_replace_type (MonoType *type)
+{
+ return mono_type_get_underlying_type (type);
+}