#define MONO_LLVM_IN_MINI 1
#include <config.h>
-#include <signal.h>
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
#include <mono/utils/memcheck.h>
#include <mono/utils/mono-threads.h>
#include "mini.h"
+#include "seq-points.h"
#include "mini-llvm.h"
#include "tasklets.h"
#include <string.h>
#include "mini-gc.h"
#include "debugger-agent.h"
+#include "seq-points.h"
static gpointer mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoException **ex);
/* Whenever to check for pending exceptions in managed-to-native wrappers */
gboolean check_for_pending_exc = TRUE;
-/* Whenever to disable passing/returning small valuetypes in registers for managed methods */
-gboolean disable_vtypes_in_regs = FALSE;
-
static GSList *tramp_infos;
static void register_icalls (void);
mono_debug_count (void)
{
static int count = 0;
- count ++;
static gboolean inited;
static const char *value;
+ count ++;
+
if (!inited) {
value = g_getenv ("COUNT");
inited = TRUE;
dest->klass = dest->inst_i0->klass;
}
+MonoInst*
+mini_get_int_to_float_spill_area (MonoCompile *cfg)
+{
+#ifdef TARGET_X86
+ if (!cfg->iconv_raw_var) {
+ cfg->iconv_raw_var = mono_compile_create_var (cfg, &mono_defaults.int32_class->byval_arg, OP_LOCAL);
+ cfg->iconv_raw_var->flags |= MONO_INST_VOLATILE; /*FIXME, use the don't regalloc flag*/
+ }
+ return cfg->iconv_raw_var;
+#else
+ return NULL;
+#endif
+}
+
#endif
void
/* Only two instructions */
opcode = bb->code->opcode;
- if ((opcode == OP_COMPARE) || (opcode == OP_COMPARE_IMM) || (opcode == OP_ICOMPARE) || (opcode == OP_ICOMPARE_IMM) || (opcode == OP_FCOMPARE) || (opcode == OP_LCOMPARE) || (opcode == OP_LCOMPARE_IMM)) {
+ if ((opcode == OP_COMPARE) || (opcode == OP_COMPARE_IMM) || (opcode == OP_ICOMPARE) || (opcode == OP_ICOMPARE_IMM) || (opcode == OP_FCOMPARE) || (opcode == OP_LCOMPARE) || (opcode == OP_LCOMPARE_IMM) || (opcode == OP_RCOMPARE)) {
/* NEW IR */
mono_bblock_insert_before_ins (bb, bb->code, inst);
} else {
} else {
opcode = bb->last_ins->prev->opcode;
- if ((opcode == OP_COMPARE) || (opcode == OP_COMPARE_IMM) || (opcode == OP_ICOMPARE) || (opcode == OP_ICOMPARE_IMM) || (opcode == OP_FCOMPARE) || (opcode == OP_LCOMPARE) || (opcode == OP_LCOMPARE_IMM)) {
+ if ((opcode == OP_COMPARE) || (opcode == OP_COMPARE_IMM) || (opcode == OP_ICOMPARE) || (opcode == OP_ICOMPARE_IMM) || (opcode == OP_FCOMPARE) || (opcode == OP_LCOMPARE) || (opcode == OP_LCOMPARE_IMM) || (opcode == OP_RCOMPARE)) {
/* NEW IR */
mono_bblock_insert_before_ins (bb, bb->last_ins->prev, inst);
} else {
MonoMethod *wrapper;
gconstpointer trampoline;
MonoDomain *domain = mono_get_root_domain ();
+ gboolean check_exc = check_for_pending_exc;
if (callinfo->wrapper) {
return callinfo->wrapper;
return callinfo->trampoline;
}
+ if (!strcmp (callinfo->name, "mono_thread_interruption_checkpoint"))
+ /* This icall is used to check for exceptions, so don't check in the wrapper */
+ check_exc = FALSE;
+
name = g_strdup_printf ("__icall_wrapper_%s", callinfo->name);
- wrapper = mono_marshal_get_icall_wrapper (callinfo->sig, name, callinfo->func, check_for_pending_exc);
+ wrapper = mono_marshal_get_icall_wrapper (callinfo->sig, name, callinfo->func, check_exc);
g_free (name);
if (do_compile)
g_assert (!sig->hasthis);
g_assert (sig->param_count < 3);
- info = mono_register_jit_icall_full (func, name, sig, no_throw, symbol);
+ /* Opcode emulation functions are assumed to don't call mono_raise_exception () */
+ info = mono_register_jit_icall_full (func, name, sig, no_throw, TRUE, symbol);
if (emul_opcode_num >= emul_opcode_alloced) {
int incr = emul_opcode_alloced? emul_opcode_alloced/2: 16;
else
sig = NULL;
- mono_register_jit_icall_full (func, name, sig, save, save ? name : NULL);
+ mono_register_jit_icall_full (func, name, sig, save, FALSE, save ? name : NULL);
+}
+
+/* Register a jit icall which doesn't throw exceptions through mono_raise_exception () */
+static void
+register_icall_noraise (gpointer func, const char *name, const char *sigstr)
+{
+ MonoMethodSignature *sig;
+
+ if (sigstr)
+ sig = mono_create_icall_signature (sigstr);
+ else
+ sig = NULL;
+
+ mono_register_jit_icall_full (func, name, sig, TRUE, TRUE, name);
}
static void
case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
case MONO_PATCH_INFO_JIT_TLS_ID:
case MONO_PATCH_INFO_MONITOR_ENTER:
+ case MONO_PATCH_INFO_MONITOR_ENTER_V4:
case MONO_PATCH_INFO_MONITOR_EXIT:
case MONO_PATCH_INFO_GOT_OFFSET:
return (ji->type << 8);
return g_str_hash (ji->data.target);
case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
return (ji->type << 8) | (gsize)ji->data.del_tramp->klass | (gsize)ji->data.del_tramp->method | (gsize)ji->data.del_tramp->virtual;
+ case MONO_PATCH_INFO_LDSTR_LIT:
+ return g_str_hash (ji->data.target);
default:
printf ("info type: %d\n", ji->type);
mono_print_ji (ji); printf ("\n");
case MONO_PATCH_INFO_TYPE_FROM_HANDLE: {
gpointer handle;
MonoClass *handle_class;
+ MonoError error;
- handle = mono_ldtoken (patch_info->data.token->image,
- patch_info->data.token->token, &handle_class, patch_info->data.token->has_context ? &patch_info->data.token->context : NULL);
+ handle = mono_ldtoken_checked (patch_info->data.token->image,
+ patch_info->data.token->token, &handle_class, patch_info->data.token->has_context ? &patch_info->data.token->context : NULL, &error);
+ if (!mono_error_ok (&error))
+ g_error ("Could not patch ldtoken due to %s", mono_error_get_message (&error));
mono_class_init (handle_class);
mono_class_init (mono_class_from_mono_type (handle));
case MONO_PATCH_INFO_LDTOKEN: {
gpointer handle;
MonoClass *handle_class;
+ MonoError error;
- handle = mono_ldtoken (patch_info->data.token->image,
- patch_info->data.token->token, &handle_class, patch_info->data.token->has_context ? &patch_info->data.token->context : NULL);
+ handle = mono_ldtoken_checked (patch_info->data.token->image,
+ patch_info->data.token->token, &handle_class, patch_info->data.token->has_context ? &patch_info->data.token->context : NULL, &error);
+ if (!mono_error_ok (&error))
+ g_error ("Could not patch ldtoken due to %s", mono_error_get_message (&error));
mono_class_init (handle_class);
target = handle;
case MONO_PATCH_INFO_MONITOR_ENTER:
target = mono_create_monitor_enter_trampoline ();
break;
+ case MONO_PATCH_INFO_MONITOR_ENTER_V4:
+ target = mono_create_monitor_enter_v4_trampoline ();
+ break;
case MONO_PATCH_INFO_MONITOR_EXIT:
target = mono_create_monitor_exit_trampoline ();
break;
target = NULL;
break;
}
+ case MONO_PATCH_INFO_LDSTR_LIT: {
+ target = mono_string_new (domain, patch_info->data.target);
+ break;
+ }
default:
g_assert_not_reached ();
}
}
}
-static void
-collect_pred_seq_points (MonoBasicBlock *bb, MonoInst *ins, GSList **next, int depth)
-{
- 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) {
- 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)
- collect_pred_seq_points (in_bb, ins, next, depth + 1);
- }
- }
-}
-
-static void
-mono_save_seq_point_info (MonoCompile *cfg)
-{
- MonoBasicBlock *bb;
- GSList *bb_seq_points, *l;
- MonoInst *last;
- MonoDomain *domain = cfg->domain;
- int i;
- MonoSeqPointInfo *info;
- GSList **next;
-
- if (!cfg->seq_points)
- return;
-
- info = g_malloc0 (sizeof (MonoSeqPointInfo) + (cfg->seq_points->len * sizeof (SeqPoint)));
- info->len = cfg->seq_points->len;
- for (i = 0; i < cfg->seq_points->len; ++i) {
- SeqPoint *sp = &info->seq_points [i];
- MonoInst *ins = g_ptr_array_index (cfg->seq_points, i);
-
- sp->il_offset = ins->inst_imm;
- sp->native_offset = ins->inst_offset;
- if (ins->flags & MONO_INST_NONEMPTY_STACK)
- sp->flags |= MONO_SEQ_POINT_FLAG_NONEMPTY_STACK;
-
- /* Used below */
- ins->backend.size = i;
- }
-
- /*
- * For each sequence point, compute the list of sequence points immediately
- * following it, this is needed to implement 'step over' in the debugger agent.
- */
- next = g_new0 (GSList*, cfg->seq_points->len);
- for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
- bb_seq_points = g_slist_reverse (bb->seq_points);
- last = NULL;
- for (l = bb_seq_points; l; l = l->next) {
- MonoInst *ins = l->data;
-
- if (ins->inst_imm == METHOD_ENTRY_IL_OFFSET || ins->inst_imm == METHOD_EXIT_IL_OFFSET)
- /* Used to implement method entry/exit events */
- continue;
- if (ins->inst_offset == SEQ_POINT_NATIVE_OFFSET_DEAD_CODE)
- continue;
-
- if (last != NULL) {
- /* Link with the previous seq point in the same bb */
- next [last->backend.size] = g_slist_append (next [last->backend.size], GUINT_TO_POINTER (ins->backend.size));
- } else {
- /* Link with the last bb in the previous bblocks */
- collect_pred_seq_points (bb, ins, next, 0);
- }
-
- last = ins;
- }
-
- if (bb->last_ins && bb->last_ins->opcode == OP_ENDFINALLY && bb->seq_points) {
- MonoBasicBlock *bb2;
- MonoInst *endfinally_seq_point = NULL;
-
- /*
- * The ENDFINALLY branches are not represented in the cfg, so link it with all seq points starting bbs.
- */
- l = g_slist_last (bb->seq_points);
- if (l) {
- endfinally_seq_point = l->data;
-
- for (bb2 = cfg->bb_entry; bb2; bb2 = bb2->next_bb) {
- GSList *l = g_slist_last (bb2->seq_points);
-
- if (l) {
- MonoInst *ins = l->data;
-
- if (!(ins->inst_imm == METHOD_ENTRY_IL_OFFSET || ins->inst_imm == METHOD_EXIT_IL_OFFSET) && ins != endfinally_seq_point)
- next [endfinally_seq_point->backend.size] = g_slist_append (next [endfinally_seq_point->backend.size], GUINT_TO_POINTER (ins->backend.size));
- }
- }
- }
- }
- }
-
- if (cfg->verbose_level > 2) {
- printf ("\nSEQ POINT MAP: \n");
- }
-
- for (i = 0; i < cfg->seq_points->len; ++i) {
- SeqPoint *sp = &info->seq_points [i];
- GSList *l;
- int j, next_index;
-
- sp->next_len = g_slist_length (next [i]);
- sp->next = g_new (int, sp->next_len);
- j = 0;
- if (cfg->verbose_level > 2 && next [i]) {
- printf ("\tIL0x%x ->", sp->il_offset);
- for (l = next [i]; l; l = l->next) {
- next_index = GPOINTER_TO_UINT (l->data);
- printf (" IL0x%x", info->seq_points [next_index].il_offset);
- }
- printf ("\n");
- }
- for (l = next [i]; l; l = l->next) {
- next_index = GPOINTER_TO_UINT (l->data);
- sp->next [j ++] = next_index;
- }
- g_slist_free (next [i]);
- }
- g_free (next);
-
- cfg->seq_point_info = info;
-
- // FIXME: dynamic methods
- if (!cfg->compile_aot) {
- mono_domain_lock (domain);
- // FIXME: How can the lookup succeed ?
- if (!g_hash_table_lookup (domain_jit_info (domain)->seq_points, cfg->method_to_register))
- g_hash_table_insert (domain_jit_info (domain)->seq_points, cfg->method_to_register, info);
- mono_domain_unlock (domain);
- }
-
- g_ptr_array_free (cfg->seq_points, TRUE);
- cfg->seq_points = NULL;
-}
-
void
mono_codegen (MonoCompile *cfg)
{
if (cfg->opt & MONO_OPT_PEEPHOLE)
mono_arch_peephole_pass_2 (cfg, bb);
+
+ if (cfg->gen_seq_points && !cfg->gen_seq_points_debug_data)
+ bb_deduplicate_op_il_seq_points (cfg, bb);
}
if (cfg->prof_options & MONO_PROFILE_COVERAGE)
cfg->code_len = code - cfg->native_code;
cfg->prolog_end = cfg->code_len;
+ cfg->cfa_reg = cfg->cur_cfa_reg;
+ cfg->cfa_offset = cfg->cur_cfa_offset;
mono_debug_open_method (cfg);
info = mono_jit_info_get_arch_eh_info (jinfo);
g_assert (info);
- info->epilog_size = cfg->epilog_end - cfg->epilog_begin;
+ info->epilog_size = cfg->code_len - cfg->epilog_begin;
}
jinfo->unwind_info = unwind_desc;
g_free (unwind_info);
copy = mono_image_alloc0 (image, sizeof (MonoGenericParamFull));
memcpy (copy, par, sizeof (MonoGenericParamFull));
} else {
- copy = g_memdup (par, sizeof (MonoGenericParamFull));
+ copy = g_memdup (par, sizeof (MonoGenericParam));
}
copy->owner = NULL;
// FIXME:
MonoMethod*
mini_get_shared_method_full (MonoMethod *method, gboolean all_vt, gboolean is_gsharedvt)
{
+ MonoError error;
MonoGenericContext shared_context;
MonoMethod *declaring_method, *res;
gboolean partial = FALSE;
partial = TRUE;
}
- res = mono_class_inflate_generic_method (declaring_method, &shared_context);
+ res = mono_class_inflate_generic_method_checked (declaring_method, &shared_context, &error);
+ g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+
if (!partial) {
/* The result should be an inflated method whose parent is not inflated */
g_assert (!res->klass->is_inflated);
cfg->full_aot = full_aot;
cfg->skip_visibility = method->skip_visibility;
cfg->orig_method = method;
- cfg->gen_seq_points = debug_options.gen_seq_points;
+ cfg->gen_seq_points = debug_options.gen_seq_points_compact_data || debug_options.gen_seq_points_debug_data;
+ cfg->gen_seq_points_debug_data = debug_options.gen_seq_points_debug_data;
+
cfg->explicit_null_checks = debug_options.explicit_null_checks;
cfg->soft_breakpoints = debug_options.soft_breakpoints;
cfg->check_pinvoke_callconv = debug_options.check_pinvoke_callconv;
cfg->compile_llvm = try_llvm;
cfg->token_info_hash = g_hash_table_new (NULL, NULL);
+ if (!mono_debug_count ())
+ cfg->opt &= ~MONO_OPT_FLOAT32;
+ cfg->r4fp = (cfg->opt & MONO_OPT_FLOAT32) ? 1 : 0;
+ cfg->r4_stack_type = cfg->r4fp ? STACK_R4 : STACK_R8;
+
if (cfg->gen_seq_points)
cfg->seq_points = g_ptr_array_new ();
mono_error_init (&cfg->error);
if (method->is_inflated)
ctx = mono_method_get_context (method);
method = info->d.synchronized_inner.method;
- if (ctx)
- method = mono_class_inflate_generic_method (method, ctx);
+ if (ctx) {
+ MonoError error;
+ method = mono_class_inflate_generic_method_checked (method, ctx, &error);
+ g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+ }
}
}
gpointer *args;
static RuntimeInvokeDynamicFunction dyn_runtime_invoke;
int i, pindex;
- guint8 buf [128];
- guint8 retval [128];
+ guint8 buf [256];
+ guint8 retval [256];
if (!dyn_runtime_invoke) {
invoke = mono_marshal_get_runtime_invoke_dynamic ();
{
MonoException *exc = NULL;
MonoJitInfo *ji;
- void *info = MONO_SIG_HANDLER_GET_INFO ();
+ MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
MONO_SIG_HANDLER_GET_CONTEXT;
ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context (ctx));
if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
return;
- mono_handle_native_sigsegv (SIGSEGV, ctx);
+ mono_handle_native_sigsegv (SIGSEGV, ctx, info);
if (mono_do_crash_chaining) {
mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
return;
gpointer fault_addr = NULL;
#ifdef HAVE_SIG_INFO
MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
+#else
+ void *info = NULL;
#endif
MONO_SIG_HANDLER_GET_CONTEXT;
}
#endif
-#if !defined(HOST_WIN32) && defined(HAVE_SIG_INFO)
+#if defined(HAVE_SIG_INFO)
+#if !defined(HOST_WIN32)
fault_addr = info->si_addr;
if (mono_aot_is_pagefault (info->si_addr)) {
mono_aot_handle_pagefault (info->si_addr);
if (!mono_domain_get () || !jit_tls) {
if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
return;
- mono_handle_native_sigsegv (SIGSEGV, ctx);
+ mono_handle_native_sigsegv (SIGSEGV, ctx, info);
if (mono_do_crash_chaining) {
mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
return;
}
}
+#endif
ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context (ctx));
#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
- if (mono_handle_soft_stack_ovf (jit_tls, ji, ctx, (guint8*)info->si_addr))
+ if (mono_handle_soft_stack_ovf (jit_tls, ji, ctx, info, (guint8*)info->si_addr))
return;
#ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
if (!ji && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
return;
- mono_arch_handle_altstack_exception (ctx, info->si_addr, FALSE);
+ mono_arch_handle_altstack_exception (ctx, info, info->si_addr, FALSE);
}
#else
if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
return;
- mono_handle_native_sigsegv (SIGSEGV, ctx);
+ mono_handle_native_sigsegv (SIGSEGV, ctx, info);
if (mono_do_crash_chaining) {
mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
else if (!strcmp (arg, "explicit-null-checks"))
debug_options.explicit_null_checks = TRUE;
else if (!strcmp (arg, "gen-seq-points"))
- debug_options.gen_seq_points = TRUE;
+ debug_options.gen_seq_points_debug_data = TRUE;
+ else if (!strcmp (arg, "gen-compact-seq-points"))
+ debug_options.gen_seq_points_compact_data = TRUE;
else if (!strcmp (arg, "init-stacks"))
debug_options.init_stacks = TRUE;
else if (!strcmp (arg, "casts"))
static gpointer
mini_create_ftnptr (MonoDomain *domain, gpointer addr)
{
-#if !defined(__ia64__) && !defined(__ppc64__) && !defined(__powerpc64__)
+#if !defined(__ia64__) && (!defined(__ppc64__) && !defined(__powerpc64__) || _CALL_ELF == 2)
return addr;
#else
-
gpointer* desc = NULL;
if ((desc = g_hash_table_lookup (domain->ftnptrs_hash, addr)))
static gpointer
mini_get_addr_from_ftnptr (gpointer descr)
{
-#if defined(__ia64__) || defined(__ppc64__) || defined(__powerpc64__)
+#if defined(__ia64__) || ((defined(__ppc64__) || defined(__powerpc64__)) && _CALL_ELF != 2)
return *(gpointer*)descr;
#else
return descr;
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 ("Allocated seq points size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.allocated_seq_points_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);
}
static void runtime_invoke_info_free (gpointer value);
-static void seq_point_info_free (gpointer value);
static gint
class_method_pair_equal (gconstpointer ka, gconstpointer kb)
g_free (info);
}
-static void seq_point_info_free (gpointer value)
-{
- int i = 0;
- MonoSeqPointInfo* info = (MonoSeqPointInfo*)value;
-
- for (i = 0; i < info->len; ++i) {
- SeqPoint *sp = &info->seq_points [i];
- g_free (sp->next);
- }
-
- g_free (info);
-}
-
static void
mini_free_jit_domain_info (MonoDomain *domain)
{
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_counters_init ();
+
mono_threads_runtime_init (&ticallbacks);
if (g_getenv ("MONO_DEBUG") != NULL)
register_dyn_icall (mono_get_rethrow_exception (), "mono_arch_rethrow_exception", "void object", TRUE);
register_dyn_icall (mono_get_throw_corlib_exception (), "mono_arch_throw_corlib_exception", "void ptr", TRUE);
register_icall (mono_thread_get_undeniable_exception, "mono_thread_get_undeniable_exception", "object", FALSE);
- register_icall (mono_thread_interruption_checkpoint, "mono_thread_interruption_checkpoint", "void", FALSE);
+ register_icall (mono_thread_interruption_checkpoint, "mono_thread_interruption_checkpoint", "object", FALSE);
+ register_icall (mono_thread_force_interruption_checkpoint_noraise, "mono_thread_force_interruption_checkpoint_noraise", "object", FALSE);
register_icall (mono_thread_force_interruption_checkpoint, "mono_thread_force_interruption_checkpoint", "void", FALSE);
#ifndef DISABLE_REMOTING
register_icall (mono_load_remote_field_new, "mono_load_remote_field_new", "object object ptr ptr", FALSE);
register_opcode_emulation (OP_FCONV_TO_U4, "__emul_fconv_to_u4", "uint32 double", mono_fconv_u4, "mono_fconv_u4", FALSE);
register_opcode_emulation (OP_FCONV_TO_OVF_I8, "__emul_fconv_to_ovf_i8", "long double", mono_fconv_ovf_i8, "mono_fconv_ovf_i8", FALSE);
register_opcode_emulation (OP_FCONV_TO_OVF_U8, "__emul_fconv_to_ovf_u8", "ulong double", mono_fconv_ovf_u8, "mono_fconv_ovf_u8", FALSE);
+ register_opcode_emulation (OP_RCONV_TO_OVF_I8, "__emul_rconv_to_ovf_i8", "long float", mono_rconv_ovf_i8, "mono_rconv_ovf_i8", FALSE);
+ register_opcode_emulation (OP_RCONV_TO_OVF_U8, "__emul_rconv_to_ovf_u8", "ulong float", mono_rconv_ovf_u8, "mono_rconv_ovf_u8", FALSE);
#ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
register_opcode_emulation (OP_FCONV_TO_I8, "__emul_fconv_to_i8", "long double", mono_fconv_i8, "mono_fconv_i8", FALSE);
+ register_opcode_emulation (OP_RCONV_TO_I8, "__emul_rconv_to_i8", "long float", mono_rconv_i8, "mono_rconv_i8", FALSE);
#endif
#ifdef MONO_ARCH_EMULATE_CONV_R8_UN
register_opcode_emulation (OP_ICONV_TO_R_UN, "__emul_iconv_to_r_un", "double int32", mono_conv_to_r8_un, "mono_conv_to_r8_un", FALSE);