#include <mono/metadata/mono-debug-debugger.h>
#include <mono/metadata/monitor.h>
#include <mono/metadata/security-manager.h>
+#include <mono/metadata/threads-types.h>
+#include <mono/metadata/rawbuffer.h>
#include <mono/utils/mono-math.h>
#include <mono/utils/mono-compiler.h>
#include <mono/os/gc_wrapper.h>
#include "jit-icalls.c"
+#include "aliasing.h"
+
/*
* this is used to determine when some branch optimizations are possible: we exclude FP compares
* because they have weird semantics with NaNs.
extern guint8 mono_burg_arity [];
/* helper methods signature */
-static MonoMethodSignature *helper_sig_long_long_long = NULL;
-static MonoMethodSignature *helper_sig_long_long_int = NULL;
-static MonoMethodSignature *helper_sig_newarr = NULL;
-static MonoMethodSignature *helper_sig_newarr_specific = NULL;
-static MonoMethodSignature *helper_sig_ldstr = NULL;
-static MonoMethodSignature *helper_sig_domain_get = NULL;
-static MonoMethodSignature *helper_sig_object_new = NULL;
-static MonoMethodSignature *helper_sig_object_new_specific = NULL;
-static MonoMethodSignature *helper_sig_compile = NULL;
-static MonoMethodSignature *helper_sig_compile_virt = NULL;
-static MonoMethodSignature *helper_sig_obj_ptr = NULL;
-static MonoMethodSignature *helper_sig_obj_ptr_ptr = NULL;
-static MonoMethodSignature *helper_sig_obj_obj_ptr_ptr = NULL;
-static MonoMethodSignature *helper_sig_obj_obj_obj_ptr = NULL;
-static MonoMethodSignature *helper_sig_void_obj_obj_ptr = NULL;
-static MonoMethodSignature *helper_sig_obj_void = NULL;
-static MonoMethodSignature *helper_sig_ptr_void = NULL;
-static MonoMethodSignature *helper_sig_void_void = NULL;
-static MonoMethodSignature *helper_sig_void_ptr = NULL;
-static MonoMethodSignature *helper_sig_void_obj = NULL;
-static MonoMethodSignature *helper_sig_void_obj_ptr_int = NULL;
-static MonoMethodSignature *helper_sig_void_obj_ptr_ptr_obj = NULL;
-static MonoMethodSignature *helper_sig_void_ptr_ptr = NULL;
-static MonoMethodSignature *helper_sig_void_ptr_ptr_ptr = NULL;
-static MonoMethodSignature *helper_sig_ptr_ptr_ptr = NULL;
-static MonoMethodSignature *helper_sig_ptr_ptr_ptr_ptr = NULL;
-static MonoMethodSignature *helper_sig_ptr_obj = NULL;
-static MonoMethodSignature *helper_sig_ptr_obj_int = NULL;
-static MonoMethodSignature *helper_sig_ptr_int = NULL;
-static MonoMethodSignature *helper_sig_ulong_double = NULL;
-static MonoMethodSignature *helper_sig_long_double = NULL;
-static MonoMethodSignature *helper_sig_double_long = NULL;
-static MonoMethodSignature *helper_sig_double_int = NULL;
-static MonoMethodSignature *helper_sig_float_long = NULL;
-static MonoMethodSignature *helper_sig_double_double_double = NULL;
-static MonoMethodSignature *helper_sig_uint_double = NULL;
-static MonoMethodSignature *helper_sig_int_double = NULL;
-static MonoMethodSignature *helper_sig_stelem_ref = NULL;
-static MonoMethodSignature *helper_sig_stelem_ref_check = NULL;
static MonoMethodSignature *helper_sig_class_init_trampoline = NULL;
-static MonoMethodSignature *helper_sig_compile_generic_method = NULL;
+static MonoMethodSignature *helper_sig_domain_get = NULL;
-static guint32 default_opt = MONO_OPT_PEEPHOLE;
+static guint32 default_opt = 0;
guint32 mono_jit_tls_id = -1;
MonoTraceSpec *mono_jit_trace_calls = NULL;
static int mini_verbose = 0;
+#define mono_jit_lock() EnterCriticalSection (&jit_mutex)
+#define mono_jit_unlock() LeaveCriticalSection (&jit_mutex)
static CRITICAL_SECTION jit_mutex;
static GHashTable *class_init_hash_addr = NULL;
* Address of the trampoline code. This is used by the debugger to check
* whether a method is a trampoline.
*/
-guint8 *mono_generic_trampoline_code = NULL;
-
-static guint8* trampoline_code [MONO_TRAMPOLINE_NUM];
+guint8* mono_trampoline_code [MONO_TRAMPOLINE_NUM];
gboolean
mono_running_on_valgrind (void)
#endif
}
+/*
+ * mono_create_ftnptr:
+ *
+ * Given a function address, create a function descriptor for it.
+ * This is only needed on IA64.
+ */
+gpointer
+mono_create_ftnptr (MonoDomain *domain, gpointer addr)
+{
+#ifdef __ia64__
+ gpointer *desc;
+
+ mono_domain_lock (domain);
+ desc = mono_code_manager_reserve (domain->code_mp, 2 * sizeof (gpointer));
+ mono_domain_unlock (domain);
+
+ desc [0] = addr;
+ desc [1] = NULL;
+
+ return desc;
+#else
+ return addr;
+#endif
+}
+
/* debug function */
G_GNUC_UNUSED static char*
get_method_from_ip (void *ip)
return res;
}
+G_GNUC_UNUSED char *
+mono_pmip (void *ip)
+{
+ return get_method_from_ip (ip);
+}
+
/* debug function */
G_GNUC_UNUSED static void
print_method_from_ip (void *ip)
return mono_code_manager_reserve (global_codeman, size);
}
else {
- EnterCriticalSection (&jit_mutex);
+ mono_jit_lock ();
ptr = mono_code_manager_reserve (global_codeman, size);
- LeaveCriticalSection (&jit_mutex);
+ mono_jit_unlock ();
return ptr;
}
}
#define NEW_LOCLOADA(cfg,dest,num) do { \
(dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- (dest)->ssa_op = MONO_SSA_MAYBE_LOAD; \
+ (dest)->ssa_op = MONO_SSA_ADDRESS_TAKEN; \
(dest)->inst_i0 = (cfg)->varinfo [locals_offset + (num)]; \
(dest)->inst_i0->flags |= MONO_INST_INDIRECT; \
(dest)->opcode = OP_LDADDR; \
#define NEW_RETLOADA(cfg,dest) do { \
(dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- (dest)->ssa_op = MONO_SSA_MAYBE_LOAD; \
+ (dest)->ssa_op = MONO_SSA_ADDRESS_TAKEN; \
(dest)->inst_i0 = (cfg)->ret; \
(dest)->inst_i0->flags |= MONO_INST_INDIRECT; \
(dest)->opcode = cfg->ret_var_is_local ? OP_LDADDR : CEE_LDIND_I; \
#define NEW_ARGLOADA(cfg,dest,num) do { \
if (arg_array [(num)]->opcode == OP_ICONST) goto inline_failure; \
(dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- (dest)->ssa_op = MONO_SSA_MAYBE_LOAD; \
+ (dest)->ssa_op = MONO_SSA_ADDRESS_TAKEN; \
(dest)->inst_i0 = arg_array [(num)]; \
(dest)->inst_i0->flags |= MONO_INST_INDIRECT; \
(dest)->opcode = OP_LDADDR; \
#define NEW_TEMPLOADA(cfg,dest,num) do { \
(dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- (dest)->ssa_op = MONO_SSA_MAYBE_LOAD; \
+ (dest)->ssa_op = MONO_SSA_ADDRESS_TAKEN; \
(dest)->inst_i0 = (cfg)->varinfo [(num)]; \
(dest)->inst_i0->flags |= MONO_INST_INDIRECT; \
(dest)->opcode = OP_LDADDR; \
int i;
array [*dfn] = start;
- /*g_print ("visit %d at %p\n", *dfn, start->cil_code);*/
+ /*g_print ("visit %d at %p (BB%ld)\n", *dfn, start->cil_code, start->block_num);*/
for (i = 0; i < start->out_count; ++i) {
if (start->out_bb [i]->dfn)
continue;
found = FALSE;
for (i = 0; i < bb->out_count; ++i) {
outb = bb->out_bb [i];
+ /* exception handlers are linked, but they should not be considered for stack args */
+ if (outb->flags & BB_EXCEPTION_HANDLER)
+ continue;
//g_print (" %d", outb->block_num);
if (outb->in_stack) {
found = TRUE;
for (i = 0; i < bb->out_count; ++i) {
outb = bb->out_bb [i];
- if (outb->in_scount)
+ /* exception handlers are linked, but they should not be considered for stack args */
+ if (outb->flags & BB_EXCEPTION_HANDLER)
+ continue;
+ if (outb->in_scount) {
+ if (outb->in_scount != bb->out_scount)
+ G_BREAKPOINT ();
continue; /* check they are the same locals */
+ }
outb->in_scount = count;
outb->in_stack = bb->out_stack;
}
found = FALSE;
while (bindex < bb->out_count) {
outb = bb->out_bb [bindex];
+ /* exception handlers are linked, but they should not be considered for stack args */
+ if (outb->flags & BB_EXCEPTION_HANDLER) {
+ bindex++;
+ continue;
+ }
if (outb->in_stack != locals) {
/*
* Instead of storing sp [i] to locals [i], we need to store
MonoMethodSignature *res;
int i;
- EnterCriticalSection (&jit_mutex);
+ mono_jit_lock ();
if (!sighash) {
sighash = g_hash_table_new (NULL, NULL);
}
res->ret = &mono_defaults.int_class->byval_arg;
g_hash_table_insert (sighash, GINT_TO_POINTER (arity), res);
- LeaveCriticalSection (&jit_mutex);
+ mono_jit_unlock ();
return res;
}
MonoMethodSignature *res;
int i;
- EnterCriticalSection (&jit_mutex);
+ mono_jit_lock ();
if (!sighash) {
sighash = g_hash_table_new (NULL, NULL);
}
else if ((res = g_hash_table_lookup (sighash, GINT_TO_POINTER (arity)))) {
- LeaveCriticalSection (&jit_mutex);
+ mono_jit_unlock ();
return res;
}
res->ret = &mono_defaults.int_class->byval_arg;
g_hash_table_insert (sighash, GINT_TO_POINTER (arity), res);
- LeaveCriticalSection (&jit_mutex);
+ mono_jit_unlock ();
return res;
}
return mono_emit_jit_icall (cfg, bblock, alloc_ftn, iargs, ip);
}
+
+/**
+ * Handles unbox of a Nullable<T>, returning a temp variable
+ * where the result is stored
+ */
+static int
+handle_unbox_nullable (MonoCompile* cfg, MonoBasicBlock* bblock, MonoInst* val, const guchar *ip, MonoClass* klass)
+{
+ MonoMethod* method = mono_class_get_method_from_name (klass, "Unbox", 1);
+ return mono_emit_method_call_spilled (cfg, bblock, method, mono_method_signature (method), &val, ip, NULL);
+}
+
+
+
static MonoInst *
handle_box (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *val, const guchar *ip, MonoClass *klass)
{
MonoInst *dest, *vtoffset, *add, *vstore;
int temp;
+ if (mono_class_is_nullable (klass)) {
+ MonoMethod* method = mono_class_get_method_from_name (klass, "Box", 1);
+ temp = mono_emit_method_call_spilled (cfg, bblock, method, mono_method_signature (method), &val, ip, NULL);
+ NEW_TEMPLOAD (cfg, dest, temp);
+ return dest;
+ }
+
+
temp = handle_alloc (cfg, bblock, klass, TRUE, ip);
NEW_TEMPLOAD (cfg, dest, temp);
NEW_ICONST (cfg, vtoffset, sizeof (MonoObject));
name = g_strdup (icall_name);
info = mono_register_jit_icall (mono_array_new_va, name, esig, FALSE);
- EnterCriticalSection (&jit_mutex);
+ mono_jit_lock ();
g_hash_table_insert (jit_icall_name_hash, name, name);
- LeaveCriticalSection (&jit_mutex);
+ mono_jit_unlock ();
}
cfg->flags |= MONO_CFG_HAS_VARARGS;
rank = mono_method_signature (cmethod)->param_count - (is_set? 1: 0);
if (rank == 2 && (cfg->opt & MONO_OPT_INTRINS)) {
+#ifdef MONO_ARCH_EMULATE_MUL_DIV
+ /* OP_LDELEMA2D depends on OP_LMUL */
+#else
MonoInst *indexes;
NEW_GROUP (cfg, indexes, sp [1], sp [2]);
MONO_INST_NEW (cfg, addr, OP_LDELEMA2D);
addr->type = STACK_MP;
addr->klass = cmethod->klass;
return addr;
+#endif
}
/* Need to register the icall so it gets an icall wrapper */
name = g_strdup (icall_name);
info = mono_register_jit_icall (ves_array_element_address, name, esig, FALSE);
- EnterCriticalSection (&jit_mutex);
+ mono_jit_lock ();
g_hash_table_insert (jit_icall_name_hash, name, name);
- LeaveCriticalSection (&jit_mutex);
+ mono_jit_unlock ();
}
temp = mono_emit_native_call (cfg, bblock, mono_icall_get_wrapper (info), info->sig, sp, ip, FALSE, FALSE);
return NULL;
}
+static MonoException*
+mini_loader_error_to_exception (MonoLoaderError *error)
+{
+ MonoException *ex = NULL;
+
+ switch (error->kind) {
+ case MONO_LOADER_ERROR_TYPE: {
+ MonoString *class_name = mono_string_new (mono_domain_get (), error->class_name);
+
+ ex = mono_get_exception_type_load (class_name, error->assembly_name);
+ break;
+ }
+ case MONO_LOADER_ERROR_METHOD:
+ case MONO_LOADER_ERROR_FIELD: {
+ char *class_name;
+
+ class_name = g_strdup_printf ("%s%s%s", error->klass->name_space, *error->klass->name_space ? "." : "", error->klass->name);
+
+ if (error->kind == MONO_LOADER_ERROR_METHOD)
+ ex = mono_get_exception_missing_method (class_name, error->member_name);
+ else
+ ex = mono_get_exception_missing_field (class_name, error->member_name);
+ g_free (class_name);
+ break;
+ }
+ default:
+ g_assert_not_reached ();
+ }
+
+ return ex;
+}
+
static MonoInst*
mini_get_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
{
ins->inst_i0 = args [0];
return ins;
} else if (strcmp (cmethod->name, "InternalGetHashCode") == 0) {
+#ifdef MONO_ARCH_EMULATE_MUL_DIV
+ /* The OP_GETHASHCODE rule depends on OP_MUL */
+#else
MONO_INST_NEW (cfg, ins, OP_GETHASHCODE);
ins->inst_i0 = args [0];
return ins;
+#endif
+ } else if (strcmp (cmethod->name, ".ctor") == 0) {
+ MONO_INST_NEW (cfg, ins, CEE_NOP);
+ return ins;
} else
return NULL;
- } else if (mini_class_is_system_array (cmethod->klass)) {
+ } else if (cmethod->klass == mono_defaults.array_class) {
if (cmethod->name [0] != 'g')
return NULL;
} else if (cmethod->klass == mono_defaults.thread_class) {
if (strcmp (cmethod->name, "get_CurrentThread") == 0 && (ins = mono_arch_get_thread_intrinsic (cfg)))
return ins;
- return NULL;
}
return mono_arch_get_inst_for_method (cfg, cmethod, fsig, args);
target = start + cli_addr + 2 + (signed char)ip [1];
GET_BBLOCK (cfg, bbhash, bblock, target);
ip += 2;
+ if (ip < end)
+ GET_BBLOCK (cfg, bbhash, bblock, ip);
break;
case MonoInlineBrTarget:
target = start + cli_addr + 5 + (gint32)read32 (ip + 1);
GET_BBLOCK (cfg, bbhash, bblock, target);
ip += 5;
+ if (ip < end)
+ GET_BBLOCK (cfg, bbhash, bblock, ip);
break;
case MonoInlineSwitch: {
guint32 n = read32 (ip + 1);
default:
g_assert_not_reached ();
}
+
+ if (i == CEE_THROW) {
+ unsigned char *bb_start = ip - 1;
+
+ /* Find the start of the bblock containing the throw */
+ bblock = NULL;
+ while ((bb_start > start) && !bblock) {
+ bblock = g_hash_table_lookup (bbhash, (bb_start));
+ bb_start --;
+ }
+ if (bblock)
+ bblock->out_of_line = 1;
+ }
}
return 0;
unverified:
MonoInst *store, *temp, *load;
if (ip_in_bb (cfg, bblock, ip_next) &&
- (CODE_IS_STLOC (ip_next) || *ip_next == CEE_BRTRUE || *ip_next == CEE_BRFALSE ||
- *ip_next == CEE_BRTRUE_S || *ip_next == CEE_BRFALSE_S || *ip_next == CEE_RET))
+ (CODE_IS_STLOC (ip_next) || *ip_next == CEE_RET))
return ins;
temp = mono_compile_create_var (cfg, type_from_stack_type (ins), OP_LOCAL);
}
static inline MonoMethod *
-mini_get_method (MonoImage *image, guint32 token, MonoClass *klass, MonoGenericContext *context)
+mini_get_method (MonoMethod *m, guint32 token, MonoClass *klass, MonoGenericContext *context)
{
- MonoMethod *method = mono_get_method_full (image, token, klass, context);
+ MonoMethod *method;
+
+ if (m->wrapper_type != MONO_WRAPPER_NONE)
+ return mono_method_get_wrapper_data (m, token);
+
+ method = mono_get_method_full (m->klass->image, token, klass, context);
- if (method->is_inflated)
+ if (method && method->is_inflated)
method = mono_get_inflated_method (method);
return method;
}
+static inline MonoClass*
+mini_get_class (MonoMethod *method, guint32 token, MonoGenericContext *context)
+{
+ MonoClass *klass;
+
+ if (method->wrapper_type != MONO_WRAPPER_NONE)
+ klass = mono_method_get_wrapper_data (method, token);
+ else
+ klass = mono_class_get_full (method->klass->image, token, context);
+ if (klass)
+ mono_class_init (klass);
+ return klass;
+}
+
static
void check_linkdemand (MonoCompile *cfg, MonoMethod *caller, MonoMethod *callee, MonoBasicBlock *bblock, unsigned char *ip)
{
MonoBoolean security, pinvoke;
MonoSecurityManager* secman = NULL;
MonoDeclSecurityActions actions;
- GSList *class_inits;
+ GSList *class_inits = NULL;
image = method->klass->image;
header = mono_method_get_header (method);
- generic_container = ((MonoMethodNormal *)method)->generic_container;
+ generic_container = method->generic_container;
sig = mono_method_signature (method);
num_args = sig->hasthis + sig->param_count;
ip = (unsigned char*)header->code;
}
/* handle exception clauses */
for (i = 0; i < header->num_clauses; ++i) {
- //unsigned char *p = ip;
+ MonoBasicBlock *try_bb;
MonoExceptionClause *clause = &header->clauses [i];
- GET_BBLOCK (cfg, bbhash, tblock, ip + clause->try_offset);
- tblock->real_offset = clause->try_offset;
+ GET_BBLOCK (cfg, bbhash, try_bb, ip + clause->try_offset);
+ try_bb->real_offset = clause->try_offset;
GET_BBLOCK (cfg, bbhash, tblock, ip + clause->handler_offset);
tblock->real_offset = clause->handler_offset;
+ tblock->flags |= BB_EXCEPTION_HANDLER;
+
+ link_bblock (cfg, try_bb, tblock);
+
+ if (*(ip + clause->handler_offset) == CEE_POP)
+ tblock->flags |= BB_EXCEPTION_DEAD_OBJ;
if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY ||
clause->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
MONO_INST_NEW (cfg, ins, OP_START_HANDLER);
MONO_ADD_INS (tblock, ins);
+
+ /* todo: is a fault block unsafe to optimize? */
+ if (clause->flags == MONO_EXCEPTION_CLAUSE_FAULT)
+ tblock->flags |= BB_EXCEPTION_UNSAFE;
}
+
/*g_print ("clause try IL_%04x to IL_%04x handler %d at IL_%04x to IL_%04x\n", clause->try_offset, clause->try_offset + clause->try_len, clause->flags, clause->handler_offset, clause->handler_offset + clause->handler_len);
while (p < end) {
g_print ("%s", mono_disasm_code_one (NULL, method, p, &p));
tblock->real_offset = clause->data.filter_offset;
tblock->in_scount = 1;
tblock->in_stack = mono_mempool_alloc (cfg->mempool, sizeof (MonoInst*));
- tblock->in_stack [0] = mono_create_exvar_for_offset (cfg, clause->data.filter_offset);
+ /* The filter block shares the exvar with the handler block */
+ tblock->in_stack [0] = mono_create_exvar_for_offset (cfg, clause->handler_offset);
MONO_INST_NEW (cfg, ins, OP_START_HANDLER);
MONO_ADD_INS (tblock, ins);
}
switch (*ip) {
case CEE_NOP:
- ++ip;
- break;
case CEE_BREAK:
- MONO_INST_NEW (cfg, ins, CEE_BREAK);
+ MONO_INST_NEW (cfg, ins, *ip);
ins->cil_code = ip++;
MONO_ADD_INS (bblock, ins);
break;
MONO_INST_NEW (cfg, ins, CEE_JMP);
token = read32 (ip + 1);
/* FIXME: check the signature matches */
- cmethod = mini_get_method (image, token, NULL, generic_context);
+ cmethod = mini_get_method (method, token, NULL, generic_context);
+
+ if (!cmethod)
+ goto load_error;
if (mono_use_security_manager) {
check_linkdemand (cfg, method, cmethod, bblock, ip);
cmethod = mono_get_method_constrained (image, token, constrained_call, generic_context);
cmethod = mono_get_inflated_method (cmethod);
} else {
- cmethod = mini_get_method (image, token, NULL, generic_context);
+ cmethod = mini_get_method (method, token, NULL, generic_context);
}
- g_assert (cmethod);
+ if (!cmethod)
+ goto load_error;
if (!virtual && (cmethod->flags & METHOD_ATTRIBUTE_ABSTRACT))
- goto unverified;
+ /* MS.NET seems to silently convert this to a callvirt */
+ virtual = 1;
if (!cmethod->klass->inited)
mono_class_init (cmethod->klass);
}
if (cmethod && cmethod->klass->generic_container) {
- G_BREAKPOINT ();
+ // G_BREAKPOINT ();
goto unverified;
}
}
if (*ip != CEE_CALLI && check_call_signature (cfg, fsig, sp)) {
- G_BREAKPOINT ();
+ // G_BREAKPOINT ();
goto unverified;
}
- if (cmethod && virtual && mono_method_signature (cmethod)->generic_param_count) {
+ if (cmethod && virtual &&
+ (cmethod->flags & METHOD_ATTRIBUTE_VIRTUAL) &&
+ !((cmethod->flags & METHOD_ATTRIBUTE_FINAL) &&
+ cmethod->wrapper_type != MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK) &&
+ mono_method_signature (cmethod)->generic_param_count) {
MonoInst *this_temp, *store;
MonoInst *iargs [3];
ins->inst_target_bb = tblock;
start_new_bblock = 1;
- if (!MONO_TYPE_IS_VOID (fsig->ret)) {
- /* just create a dummy - the value is never used */
- ins = mono_compile_create_var (cfg, fsig->ret, OP_LOCAL);
- NEW_TEMPLOAD (cfg, *sp, ins->inst_c0);
- sp++;
- MONO_INST_NEW (cfg, ins, CEE_POP);
- MONO_ADD_INS (bblock, ins);
- --sp;
- ins->inst_i0 = *sp;
- }
/* skip the CEE_RET, too */
if (ip_in_bb (cfg, bblock, ip + 5))
ip += 6;
if (ip_in_bb (cfg, bblock, ip + 5)
&& (!MONO_TYPE_ISSTRUCT (fsig->ret))
&& (!MONO_TYPE_IS_VOID (fsig->ret) || cmethod->string_ctor)
- && (CODE_IS_STLOC (ip + 5) || ip [5] == CEE_POP || ip [5] == CEE_BRTRUE || ip [5] == CEE_BRFALSE ||
- ip [5] == CEE_BRTRUE_S || ip [5] == CEE_BRFALSE_S || ip [5] == CEE_RET)) {
+ && (CODE_IS_STLOC (ip + 5) || ip [5] == CEE_POP || ip [5] == CEE_RET)) {
/* no need to spill */
ins = (MonoInst*)mono_emit_method_call (cfg, bblock, cmethod, fsig, sp, ip, virtual ? sp [0] : NULL);
*sp++ = ins;
ins_flag = 0;
inline_costs += 1;
break;
+ case CEE_MUL:
+ CHECK_STACK (2);
+ ADD_BINOP (*ip);
+
+#ifdef MONO_ARCH_NO_EMULATE_MUL_IMM
+ /* FIXME: This breaks with ssapre (mono -O=ssapre loader.exe) */
+ if ((ins->inst_right->opcode == OP_ICONST) && !(cfg->opt & MONO_OPT_SSAPRE)) {
+ switch (ins->opcode) {
+ case CEE_MUL:
+ ins->opcode = OP_IMUL_IMM;
+ ins->inst_imm = ins->inst_right->inst_c0;
+ break;
+ case OP_LMUL:
+ ins->opcode = OP_LMUL_IMM;
+ ins->inst_imm = ins->inst_right->inst_c0;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ }
+#endif
+
+ if (mono_find_jit_opcode_emulation (ins->opcode)) {
+ --sp;
+ *sp++ = emit_tree (cfg, bblock, ins, ip + 1);
+ mono_get_got_var (cfg);
+ }
+ ip++;
+ break;
case CEE_ADD:
case CEE_SUB:
- case CEE_MUL:
case CEE_DIV:
case CEE_DIV_UN:
case CEE_REM:
CHECK_OPSIZE (5);
CHECK_STACK (2);
token = read32 (ip + 1);
- if (method->wrapper_type != MONO_WRAPPER_NONE)
- klass = mono_method_get_wrapper_data (method, token);
- else
- klass = mono_class_get_full (image, token, generic_context);
-
- mono_class_init (klass);
+ klass = mini_get_class (method, token, generic_context);
+ if (!klass)
+ goto load_error;
sp -= 2;
if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
MonoInst *store, *load;
CHECK_STACK (1);
--sp;
token = read32 (ip + 1);
- if (method->wrapper_type != MONO_WRAPPER_NONE)
- klass = mono_method_get_wrapper_data (method, token);
- else
- klass = mono_class_get_full (image, token, generic_context);
-
- mono_class_init (klass);
+ klass = mini_get_class (method, token, generic_context);
+ if (!klass)
+ goto load_error;
if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
MONO_INST_NEW (cfg, ins, CEE_LDIND_REF);
ins->cil_code = ip;
n = read32 (ip + 1);
if (method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD) {
- NEW_PCONST (cfg, ins, mono_method_get_wrapper_data (method, n));
+ NEW_PCONST (cfg, ins, mono_method_get_wrapper_data (method, n));
ins->cil_code = ip;
ins->type = STACK_OBJ;
*sp = ins;
NEW_TEMPLOAD (cfg, *sp, temp);
mono_ldstr (cfg->domain, image, mono_metadata_token_index (n));
} else {
- if (cfg->compile_aot)
+ if (bblock->out_of_line) {
+ MonoInst *iargs [2];
+ int temp;
+
+ /* Avoid creating the string object */
+ NEW_IMAGECONST (cfg, iargs [0], image);
+ NEW_ICONST (cfg, iargs [1], mono_metadata_token_index (n));
+ temp = mono_emit_jit_icall (cfg, bblock, helper_ldstr, iargs, ip);
+ NEW_TEMPLOAD (cfg, *sp, temp);
+ }
+ else
+ if (cfg->compile_aot) {
NEW_LDSTRCONST (cfg, ins, image, n);
+ *sp = ins;
+ }
else {
NEW_PCONST (cfg, ins, NULL);
ins->cil_code = ip;
ins->type = STACK_OBJ;
ins->inst_p0 = mono_ldstr (cfg->domain, image, mono_metadata_token_index (n));
+ *sp = ins;
}
- *sp = ins;
}
}
CHECK_OPSIZE (5);
token = read32 (ip + 1);
- if (method->wrapper_type != MONO_WRAPPER_NONE) {
- cmethod = mono_method_get_wrapper_data (method, token);
- } else
- cmethod = mini_get_method (image, token, NULL, generic_context);
+ cmethod = mini_get_method (method, token, NULL, generic_context);
+ if (!cmethod)
+ goto load_error;
fsig = mono_method_get_signature (cmethod, image, token);
mono_class_init (cmethod->klass);
--sp;
CHECK_OPSIZE (5);
token = read32 (ip + 1);
- if (method->wrapper_type != MONO_WRAPPER_NONE)
- klass = mono_method_get_wrapper_data (method, token);
- else
- klass = mono_class_get_full (image, token, generic_context);
- mono_class_init (klass);
+ klass = mini_get_class (method, token, generic_context);
+ if (!klass)
+ goto load_error;
/* Needed by the code generated in inssel.brg */
mono_get_got_var (cfg);
--sp;
CHECK_OPSIZE (5);
token = read32 (ip + 1);
- if (method->wrapper_type != MONO_WRAPPER_NONE)
- klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
- else
- klass = mono_class_get_full (image, token, generic_context);
- mono_class_init (klass);
+ klass = mini_get_class (method, token, generic_context);
+ if (!klass)
+ goto load_error;
if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
/* CASTCLASS */
break;
}
+ if (mono_class_is_nullable (klass)) {
+ int v = handle_unbox_nullable (cfg, bblock, *sp, ip, klass);
+ NEW_TEMPLOAD (cfg, *sp, v);
+ sp ++;
+ ip += 5;
+ break;
+ }
+
MONO_INST_NEW (cfg, ins, OP_UNBOXCAST);
ins->type = STACK_OBJ;
ins->inst_left = *sp;
--sp;
CHECK_OPSIZE (5);
token = read32 (ip + 1);
- if (method->wrapper_type != MONO_WRAPPER_NONE)
- klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
- else
- klass = mono_class_get_full (image, token, generic_context);
- mono_class_init (klass);
+ klass = mini_get_class (method, token, generic_context);
+ if (!klass)
+ goto load_error;
+
+ if (mono_class_is_nullable (klass)) {
+ int v = handle_unbox_nullable (cfg, bblock, *sp, ip, klass);
+ NEW_TEMPLOAD (cfg, *sp, v);
+ sp ++;
+ ip += 5;
+ break;
+ }
/* Needed by the code generated in inssel.brg */
mono_get_got_var (cfg);
--sp;
CHECK_OPSIZE (5);
token = read32 (ip + 1);
- if (method->wrapper_type != MONO_WRAPPER_NONE)
- klass = mono_method_get_wrapper_data (method, token);
- else
- klass = mono_class_get_full (image, token, generic_context);
- mono_class_init (klass);
+ klass = mini_get_class (method, token, generic_context);
+ if (!klass)
+ goto load_error;
/* Needed by the code generated in inssel.brg */
mono_get_got_var (cfg);
ins->cil_code = ip - 1;
MONO_ADD_INS (bblock, ins);
sp = stack_start;
+
link_bblock (cfg, bblock, end_bblock);
start_new_bblock = 1;
mono_get_got_var (cfg);
CHECK_OPSIZE (5);
token = read32 (ip + 1);
field = mono_field_from_token (image, token, &klass, generic_context);
+ if (!field)
+ goto load_error;
mono_class_init (klass);
foffset = klass->valuetype? field->offset - sizeof (MonoObject): field->offset;
}
} else {
if ((klass->marshalbyref && !MONO_CHECK_THIS (sp [0])) || klass->contextbound || klass == mono_defaults.marshalbyrefobject_class) {
- MonoMethod *ldfld_wrapper = mono_marshal_get_ldfld_wrapper (field->type);
+ MonoMethod *wrapper = (*ip == CEE_LDFLDA) ? mono_marshal_get_ldflda_wrapper (field->type) : mono_marshal_get_ldfld_wrapper (field->type);
MonoInst *iargs [4];
int temp;
NEW_CLASSCONST (cfg, iargs [1], klass);
NEW_FIELDCONST (cfg, iargs [2], field);
NEW_ICONST (cfg, iargs [3], klass->valuetype ? field->offset - sizeof (MonoObject) : field->offset);
- if ((cfg->opt & MONO_OPT_INLINE) && !MONO_TYPE_ISSTRUCT (mono_method_signature (ldfld_wrapper)->ret)) {
- costs = inline_method (cfg, ldfld_wrapper, mono_method_signature (ldfld_wrapper), bblock,
+ if ((cfg->opt & MONO_OPT_INLINE) && !MONO_TYPE_ISSTRUCT (mono_method_signature (wrapper)->ret)) {
+ costs = inline_method (cfg, wrapper, mono_method_signature (wrapper), bblock,
iargs, ip, real_offset, dont_inline, &ebblock, TRUE);
g_assert (costs > 0);
temp = iargs [0]->inst_i0->inst_c0;
- if (*ip == CEE_LDFLDA) {
- /* not sure howto handle this */
- NEW_TEMPLOADA (cfg, *sp, temp);
- } else {
- NEW_TEMPLOAD (cfg, *sp, temp);
- }
+ NEW_TEMPLOAD (cfg, *sp, temp);
sp++;
/* indicates start of a new block, and triggers a load of
inline_costs += costs;
break;
} else {
- temp = mono_emit_method_call_spilled (cfg, bblock, ldfld_wrapper, mono_method_signature (ldfld_wrapper), iargs, ip, NULL);
- if (*ip == CEE_LDFLDA) {
- /* not sure howto handle this */
- NEW_TEMPLOADA (cfg, *sp, temp);
- } else {
- NEW_TEMPLOAD (cfg, *sp, temp);
- }
+ temp = mono_emit_method_call_spilled (cfg, bblock, wrapper, mono_method_signature (wrapper), iargs, ip, NULL);
+ NEW_TEMPLOAD (cfg, *sp, temp);
sp++;
}
} else {
token = read32 (ip + 1);
field = mono_field_from_token (image, token, &klass, generic_context);
+ if (!field)
+ goto load_error;
mono_class_init (klass);
g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL));
sp -= 2;
CHECK_OPSIZE (5);
token = read32 (ip + 1);
- if (method->wrapper_type != MONO_WRAPPER_NONE)
- klass = mono_method_get_wrapper_data (method, token);
- else
- klass = mono_class_get_full (image, token, generic_context);
- mono_class_init (klass);
+ klass = mini_get_class (method, token, generic_context);
+ if (!klass)
+ goto load_error;
n = mono_type_to_stind (&klass->byval_arg);
if (n == CEE_STOBJ) {
handle_stobj (cfg, bblock, sp [0], sp [1], ip, klass, FALSE, FALSE);
val = *sp;
CHECK_OPSIZE (5);
token = read32 (ip + 1);
- if (method->wrapper_type != MONO_WRAPPER_NONE)
- klass = mono_method_get_wrapper_data (method, token);
- else
- klass = mono_class_get_full (image, token, generic_context);
- mono_class_init (klass);
+ klass = mini_get_class (method, token, generic_context);
+ if (!klass)
+ goto load_error;
if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
*sp++ = val;
/* Ditto */
mono_get_got_var (cfg);
- if (method->wrapper_type != MONO_WRAPPER_NONE)
- klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
- else
- klass = mono_class_get_full (image, token, generic_context);
-
- mono_class_init (klass);
+ klass = mini_get_class (method, token, generic_context);
+ if (!klass)
+ goto load_error;
ins->inst_newa_class = klass;
ins->inst_newa_len = *sp;
ins->type = STACK_OBJ;
sp -= 2;
CHECK_OPSIZE (5);
- if (method->wrapper_type != MONO_WRAPPER_NONE)
- klass = (MonoClass*)mono_method_get_wrapper_data (method, read32 (ip + 1));
- else
- klass = mono_class_get_full (image, read32 (ip + 1), generic_context);
-
+ klass = mini_get_class (method, read32 (ip + 1), generic_context);
+ if (!klass)
+ goto load_error;
/* we need to make sure that this array is exactly the type it needs
* to be for correctness. the wrappers are lax with their usage
* so we need to ignore them here
CHECK_OPSIZE (5);
token = read32 (ip + 1);
klass = mono_class_get_full (image, token, generic_context);
+ if (!klass)
+ goto load_error;
mono_class_init (klass);
NEW_LDELEMA (cfg, load, sp, klass);
load->cil_code = ip;
CHECK_OPSIZE (5);
token = read32 (ip + 1);
klass = mono_class_get_full (image, token, generic_context);
+ if (!klass)
+ goto load_error;
mono_class_init (klass);
if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
MonoMethod* helper = mono_marshal_get_stelemref ();
--sp;
CHECK_OPSIZE (5);
klass = mono_class_get_full (image, read32 (ip + 1), generic_context);
+ if (!klass)
+ goto load_error;
mono_class_init (klass);
ins->type = STACK_MP;
ins->inst_left = *sp;
--sp;
CHECK_OPSIZE (5);
klass = mono_class_get_full (image, read32 (ip + 1), generic_context);
+ if (!klass)
+ goto load_error;
mono_class_init (klass);
ins->cil_code = ip;
CHECK_OPSIZE (5);
n = read32 (ip + 1);
- handle = mono_ldtoken (image, n, &handle_class, generic_context);
+ if (method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD) {
+ handle = mono_method_get_wrapper_data (method, n);
+ handle_class = mono_method_get_wrapper_data (method, n + 1);
+ }
+ else {
+ handle = mono_ldtoken (image, n, &handle_class, generic_context);
+ }
+ if (!handle)
+ goto load_error;
mono_class_init (handle_class);
if (cfg->opt & MONO_OPT_SHARED) {
MONO_ADD_INS (bblock, store);
NEW_TEMPLOAD (cfg, ins, vtvar->inst_c0);
} else {
- if ((ip [5] == CEE_CALL) && (cmethod = mini_get_method (image, read32 (ip + 6), NULL, generic_context)) &&
+ if ((ip [5] == CEE_CALL) && (cmethod = mini_get_method (method, read32 (ip + 6), NULL, generic_context)) &&
(cmethod->klass == mono_defaults.monotype_class->parent) &&
(strcmp (cmethod->name, "GetTypeFromHandle") == 0) && ip_in_bb (cfg, bblock, ip + 5)) {
MonoClass *tclass = mono_class_from_mono_type (handle);
CHECK_STACK_OVF (1);
CHECK_OPSIZE (6);
n = read32 (ip + 2);
- if (method->wrapper_type != MONO_WRAPPER_NONE)
- cmethod = mono_method_get_wrapper_data (method, n);
- else {
- cmethod = mini_get_method (image, n, NULL, generic_context);
- }
-
+ cmethod = mini_get_method (method, n, NULL, generic_context);
+ if (!cmethod)
+ goto load_error;
mono_class_init (cmethod->klass);
if (mono_use_security_manager) {
CHECK_STACK (1);
CHECK_OPSIZE (6);
n = read32 (ip + 2);
- if (method->wrapper_type != MONO_WRAPPER_NONE)
- cmethod = mono_method_get_wrapper_data (method, n);
- else
- cmethod = mini_get_method (image, n, NULL, generic_context);
-
+ cmethod = mini_get_method (method, n, NULL, generic_context);
+ if (!cmethod)
+ goto load_error;
mono_class_init (cmethod->klass);
if (mono_use_security_manager) {
for (cc = 0; cc < header->num_clauses; ++cc) {
clause = &header->clauses [cc];
if ((clause->flags & MONO_EXCEPTION_CLAUSE_FILTER) &&
- (!nearest || (clause->data.filter_offset > nearest->data.filter_offset))) {
+ ((ip - header->code) > clause->data.filter_offset && (ip - header->code) <= clause->handler_offset) &&
+ (!nearest || (clause->data.filter_offset < nearest->data.filter_offset))) {
nearest = clause;
nearest_num = cc;
}
--sp;
CHECK_OPSIZE (6);
token = read32 (ip + 2);
- if (method->wrapper_type != MONO_WRAPPER_NONE)
- klass = mono_method_get_wrapper_data (method, token);
- else
- klass = mono_class_get_full (image, token, generic_context);
+ klass = mini_get_class (method, token, generic_context);
+ if (!klass)
+ goto load_error;
if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
MonoInst *store, *load;
NEW_PCONST (cfg, load, NULL);
CHECK_OPSIZE (6);
token = read32 (ip + 2);
constrained_call = mono_class_get_full (image, token, generic_context);
+ if (!constrained_call)
+ goto load_error;
ip += 6;
break;
case CEE_CPBLK:
handler_offset = clause->handler_offset;
}
+ bblock->flags |= BB_EXCEPTION_UNSAFE;
+
g_assert (handler_offset != -1);
NEW_TEMPLOAD (cfg, load, mono_find_exvar_for_offset (cfg, handler_offset)->inst_c0);
MonoType *type = mono_type_create_from_typespec (image, token);
token = mono_type_size (type, &align);
} else {
- MonoClass *szclass = mono_class_get_full (image, token, generic_context);
- mono_class_init (szclass);
- token = mono_class_value_size (szclass, &align);
+ MonoClass *klass = mono_class_get_full (image, token, generic_context);
+ if (!klass)
+ goto load_error;
+ mono_class_init (klass);
+ token = mono_class_value_size (klass, &align);
}
NEW_ICONST (cfg, ins, token);
ins->cil_code = ip;
((t == MONO_TYPE_GENERICINST) && mono_metadata_generic_class_is_valuetype (ptype->data.generic_class))) {
NEW_LOCLOADA (cfg, ins, i);
handle_initobj (cfg, init_localsbb, ins, NULL, mono_class_from_mono_type (ptype), NULL, NULL);
- break;
} else {
NEW_PCONST (cfg, ins, NULL);
NEW_LOCSTORE (cfg, store, i, ins);
dont_inline = g_list_remove (dont_inline, method);
return -1;
+ load_error:
+ if (cfg->method != method)
+ g_hash_table_destroy (bbhash);
+ g_slist_free (class_inits);
+ dont_inline = g_list_remove (dont_inline, method);
+ return -1;
+
unverified:
if (cfg->method != method)
g_hash_table_destroy (bbhash);
printf ("\n");
}
-#define make_icall_sig mono_create_icall_signature
-
static void
create_helper_signature (void)
{
- /* MonoArray * mono_array_new (MonoDomain *domain, MonoClass *klass, gint32 len) */
- helper_sig_newarr = make_icall_sig ("object ptr ptr int32");
-
- /* MonoArray * mono_array_new_specific (MonoVTable *vtable, guint32 len) */
- helper_sig_newarr_specific = make_icall_sig ("object ptr int32");
-
- /* MonoObject * mono_object_new (MonoDomain *domain, MonoClass *klass) */
- helper_sig_object_new = make_icall_sig ("object ptr ptr");
-
- /* MonoObject * mono_object_new_specific (MonoVTable *vtable) */
- helper_sig_object_new_specific = make_icall_sig ("object ptr");
-
- /* void* mono_method_compile (MonoMethod*) */
- helper_sig_compile = make_icall_sig ("ptr ptr");
-
- /* void* mono_ldvirtfn (MonoObject *, MonoMethod*) */
- helper_sig_compile_virt = make_icall_sig ("ptr object ptr");
-
- /* MonoString* mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 str_index) */
- helper_sig_ldstr = make_icall_sig ("object ptr ptr int32");
-
- /* MonoDomain *mono_domain_get (void) */
- helper_sig_domain_get = make_icall_sig ("ptr");
-
- /* void stelem_ref (MonoArray *, int index, MonoObject *) */
- helper_sig_stelem_ref = make_icall_sig ("void ptr int32 object");
-
- /* void stelem_ref_check (MonoArray *, MonoObject *) */
- helper_sig_stelem_ref_check = make_icall_sig ("void object object");
-
- /* void *helper_compile_generic_method (MonoObject *, MonoMethod *, MonoGenericContext *) */
- helper_sig_compile_generic_method = make_icall_sig ("ptr object ptr ptr");
-
- /* long amethod (long, long) */
- helper_sig_long_long_long = make_icall_sig ("long long long");
-
- /* object amethod (intptr) */
- helper_sig_obj_ptr = make_icall_sig ("object ptr");
-
- helper_sig_obj_ptr_ptr = make_icall_sig ("object ptr ptr");
-
- helper_sig_obj_obj_ptr_ptr = make_icall_sig ("object object ptr ptr");
-
- helper_sig_void_void = make_icall_sig ("void");
-
- /* void amethod (intptr) */
- helper_sig_void_ptr = make_icall_sig ("void ptr");
-
- /* void amethod (MonoObject *obj) */
- helper_sig_void_obj = make_icall_sig ("void object");
-
- /* void amethod (MonoObject *obj, void *ptr, int i) */
- helper_sig_void_obj_ptr_int = make_icall_sig ("void object ptr int");
-
- helper_sig_void_obj_ptr_ptr_obj = make_icall_sig ("void object ptr ptr object");
-
- /* intptr amethod (void) */
- helper_sig_ptr_void = make_icall_sig ("ptr");
-
- /* object amethod (void) */
- helper_sig_obj_void = make_icall_sig ("object");
-
- /* void amethod (intptr, intptr) */
- helper_sig_void_ptr_ptr = make_icall_sig ("void ptr ptr");
-
- /* void amethod (intptr, intptr, intptr) */
- helper_sig_void_ptr_ptr_ptr = make_icall_sig ("void ptr ptr ptr");
-
- /* intptr amethod (intptr, intptr) */
- helper_sig_ptr_ptr_ptr = make_icall_sig ("ptr ptr ptr");
-
- helper_sig_ptr_ptr_ptr_ptr = make_icall_sig ("ptr ptr ptr ptr");
-
- /* IntPtr amethod (object) */
- helper_sig_ptr_obj = make_icall_sig ("ptr object");
-
- /* IntPtr amethod (object, int) */
- helper_sig_ptr_obj_int = make_icall_sig ("ptr object int");
-
- /* IntPtr amethod (int) */
- helper_sig_ptr_int = make_icall_sig ("ptr int32");
-
- /* long amethod (long, guint32) */
- helper_sig_long_long_int = make_icall_sig ("long long int32");
-
- /* ulong amethod (double) */
- helper_sig_ulong_double = make_icall_sig ("ulong double");
-
- /* long amethod (double) */
- helper_sig_long_double = make_icall_sig ("long double");
-
- /* double amethod (long) */
- helper_sig_double_long = make_icall_sig ("double long");
-
- /* double amethod (int) */
- helper_sig_double_int = make_icall_sig ("double int32");
-
- /* float amethod (long) */
- helper_sig_float_long = make_icall_sig ("float long");
-
- /* double amethod (double, double) */
- helper_sig_double_double_double = make_icall_sig ("double double double");
-
- /* uint amethod (double) */
- helper_sig_uint_double = make_icall_sig ("uint32 double");
-
- /* int amethod (double) */
- helper_sig_int_double = make_icall_sig ("int32 double");
-
- helper_sig_class_init_trampoline = make_icall_sig ("void");
-
- helper_sig_obj_obj_obj_ptr = make_icall_sig ("object object object ptr");
-
- helper_sig_void_obj_obj_ptr = make_icall_sig ("void object object ptr");
+ helper_sig_domain_get = mono_create_icall_signature ("ptr");
+ helper_sig_class_init_trampoline = mono_create_icall_signature ("void");
}
gconstpointer
static void
mono_init_trampolines (void)
{
- trampoline_code [MONO_TRAMPOLINE_GENERIC] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_GENERIC);
- trampoline_code [MONO_TRAMPOLINE_JUMP] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_JUMP);
- trampoline_code [MONO_TRAMPOLINE_CLASS_INIT] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_CLASS_INIT);
+ mono_trampoline_code [MONO_TRAMPOLINE_GENERIC] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_GENERIC);
+ mono_trampoline_code [MONO_TRAMPOLINE_JUMP] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_JUMP);
+ mono_trampoline_code [MONO_TRAMPOLINE_CLASS_INIT] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_CLASS_INIT);
#ifdef MONO_ARCH_HAVE_PIC_AOT
- trampoline_code [MONO_TRAMPOLINE_AOT] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_AOT);
+ mono_trampoline_code [MONO_TRAMPOLINE_AOT] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_AOT);
+#endif
+#ifdef MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE
+ mono_trampoline_code [MONO_TRAMPOLINE_DELEGATE] = mono_arch_create_trampoline_code (MONO_TRAMPOLINE_DELEGATE);
#endif
+}
- mono_generic_trampoline_code = trampoline_code [MONO_TRAMPOLINE_GENERIC];
+static void
+mono_init_exceptions (void)
+{
+#ifndef CUSTOM_EXCEPTION_HANDLING
+ mono_arch_get_restore_context ();
+ mono_arch_get_call_filter ();
+ mono_arch_get_throw_exception ();
+ mono_arch_get_rethrow_exception ();
+#endif
}
guint8 *
mono_get_trampoline_code (MonoTrampolineType tramp_type)
{
- return trampoline_code [tramp_type];
+ return mono_trampoline_code [tramp_type];
}
gpointer
mono_create_class_init_trampoline (MonoVTable *vtable)
{
- gpointer code;
+ gpointer code, ptr;
/* previously created trampoline code */
mono_domain_lock (vtable->domain);
- code =
+ ptr =
g_hash_table_lookup (vtable->domain->class_init_trampoline_hash,
vtable);
mono_domain_unlock (vtable->domain);
- if (code)
- return code;
+ if (ptr)
+ return ptr;
+#ifdef MONO_ARCH_HAVE_CREATE_SPECIFIC_TRAMPOLINE
+ code = mono_arch_create_specific_trampoline (vtable, MONO_TRAMPOLINE_CLASS_INIT, vtable->domain, NULL);
+#else
code = mono_arch_create_class_init_trampoline (vtable);
+#endif
+
+ ptr = mono_create_ftnptr (vtable->domain, code);
/* store trampoline address */
mono_domain_lock (vtable->domain);
g_hash_table_insert (vtable->domain->class_init_trampoline_hash,
- vtable, code);
+ vtable, ptr);
mono_domain_unlock (vtable->domain);
- EnterCriticalSection (&jit_mutex);
+ mono_jit_lock ();
if (!class_init_hash_addr)
class_init_hash_addr = g_hash_table_new (NULL, NULL);
- g_hash_table_insert (class_init_hash_addr, code, vtable);
- LeaveCriticalSection (&jit_mutex);
+ g_hash_table_insert (class_init_hash_addr, ptr, vtable);
+ mono_jit_unlock ();
- return code;
+ return ptr;
}
gpointer
{
MonoJitInfo *ji;
gpointer code;
+#ifdef MONO_ARCH_HAVE_CREATE_SPECIFIC_TRAMPOLINE
+ guint32 code_size;
+#endif
if (add_sync_wrapper && method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
return mono_create_jump_trampoline (domain, mono_marshal_get_synchronized_wrapper (method), FALSE);
if (code)
return code;
+#ifdef MONO_ARCH_HAVE_CREATE_SPECIFIC_TRAMPOLINE
+ code = mono_arch_create_specific_trampoline (method, MONO_TRAMPOLINE_JUMP, mono_domain_get (), &code_size);
+
+ ji = g_new0 (MonoJitInfo, 1);
+ ji->code_start = code;
+ ji->code_size = code_size;
+ ji->method = method;
+#else
ji = mono_arch_create_jump_trampoline (method);
+#endif
/*
* mono_delegate_ctor needs to find the method metadata from the
* trampoline address, so we save it here.
*/
- mono_jit_info_table_add (mono_get_root_domain (), ji);
+ mono_jit_info_table_add (domain, ji);
mono_domain_lock (domain);
g_hash_table_insert (domain->jump_trampoline_hash, method, ji->code_start);
if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
return mono_create_jit_trampoline (mono_marshal_get_synchronized_wrapper (method));
+#ifdef MONO_ARCH_HAVE_CREATE_SPECIFIC_TRAMPOLINE
+ tramp = mono_arch_create_specific_trampoline (method, MONO_TRAMPOLINE_GENERIC, mono_domain_get (), NULL);
+#else
tramp = mono_arch_create_jit_trampoline (method);
+#endif
mono_domain_lock (domain);
g_hash_table_insert (domain->jit_trampoline_hash, method, tramp);
{
gpointer tramp;
- tramp = mono_arch_create_jit_trampoline_from_token (image, token);
+ MonoDomain *domain = mono_domain_get ();
+ guint8 *buf, *start;
+
+ mono_domain_lock (domain);
+ buf = start = mono_code_manager_reserve (domain->code_mp, 2 * sizeof (gpointer));
+ mono_domain_unlock (domain);
+
+ *(gpointer*)(gpointer)buf = image;
+ buf += sizeof (gpointer);
+ *(guint32*)(gpointer)buf = token;
+
+ tramp = mono_arch_create_specific_trampoline (start, MONO_TRAMPOLINE_AOT, domain, NULL);
mono_jit_stats.method_trampolines++;
}
#endif
+gpointer
+mono_create_delegate_trampoline (MonoMethod *method, gpointer addr)
+{
+#ifdef MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE
+ gpointer code, ptr;
+ guint32 code_size;
+ MonoDomain *domain = mono_domain_get ();
+
+#ifndef __ia64__
+ code = mono_jit_find_compiled_method (domain, method);
+ if (code)
+ return code;
+#else
+ /*
+ * FIXME: We should return a function descriptor here but it is not stored
+ * anywhere so it would be leaked.
+ */
+#endif
+
+ mono_domain_lock (domain);
+ ptr = g_hash_table_lookup (domain->delegate_trampoline_hash, method);
+ mono_domain_unlock (domain);
+ if (ptr)
+ return ptr;
+
+ code = mono_arch_create_specific_trampoline (method, MONO_TRAMPOLINE_DELEGATE, domain, &code_size);
+
+ ptr = mono_create_ftnptr (domain, code);
+
+ /* store trampoline address */
+ mono_domain_lock (domain);
+ g_hash_table_insert (domain->delegate_trampoline_hash,
+ method, ptr);
+ mono_domain_unlock (domain);
+
+ return ptr;
+#else
+ return addr;
+#endif
+}
+
MonoVTable*
mono_find_class_init_trampoline_by_addr (gconstpointer addr)
{
MonoVTable *res;
- EnterCriticalSection (&jit_mutex);
+ mono_jit_lock ();
if (class_init_hash_addr)
res = g_hash_table_lookup (class_init_hash_addr, addr);
else
res = NULL;
- LeaveCriticalSection (&jit_mutex);
+ mono_jit_unlock ();
return res;
}
} StackSlotInfo;
/*
- * mono_allocate_stack_slots:
+ * mono_allocate_stack_slots_full:
*
* 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 (MonoCompile *m, guint32 *stack_size, guint32 *stack_align)
+mono_allocate_stack_slots_full (MonoCompile *m, gboolean backward, guint32 *stack_size, guint32 *stack_align)
{
int i, slot, offset, size, align;
MonoMethodVar *vmv;
*/
}
if (slot == 0xffffff) {
- offset += size;
- offset += align - 1;
- offset &= ~(align - 1);
- slot = offset;
+ /*
+ * Allways allocate valuetypes to sizeof (gpointer) to allow more
+ * efficient copying (and to work around the fact that OP_MEMCPY
+ * and OP_MEMSET ignores alignment).
+ */
+ if (t->type == MONO_TYPE_VALUETYPE)
+ align = sizeof (gpointer);
+
+ if (backward) {
+ offset += size;
+ offset += align - 1;
+ offset &= ~(align - 1);
+ slot = offset;
+ }
+ else {
+ offset += align - 1;
+ offset &= ~(align - 1);
+ slot = offset;
+ offset += size;
+ }
if (*stack_align == 0)
*stack_align = align;
return offsets;
}
+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);
+}
+
void
-mono_register_opcode_emulation (int opcode, const char *name, MonoMethodSignature *sig, gpointer func, gboolean no_throw)
+mono_register_opcode_emulation (int opcode, const char *name, const char *sigstr, gpointer func, gboolean no_throw)
{
MonoJitICallInfo *info;
+ MonoMethodSignature *sig = mono_create_icall_signature (sigstr);
if (!emul_opcode_map)
emul_opcode_map = g_new0 (MonoJitICallInfo*, OP_LAST + 1);
emul_opcode_map [opcode] = info;
}
+static void
+register_icall (gpointer func, const char *name, const char *sigstr, gboolean save)
+{
+ MonoMethodSignature *sig;
+
+ if (sigstr)
+ sig = mono_create_icall_signature (sigstr);
+ else
+ sig = NULL;
+
+ mono_register_jit_icall (func, name, sig, save);
+}
+
static void
decompose_foreach (MonoInst *tree, gpointer data)
{
mono_arch_setup_jit_tls_data (jit_tls);
+#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
+ mono_setup_altstack (jit_tls);
+#endif
+
return jit_tls;
}
static void
-mono_thread_start_cb (guint32 tid, gpointer stack_start, gpointer func)
+mono_thread_start_cb (gsize tid, gpointer stack_start, gpointer func)
{
MonoThread *thread;
void *jit_tls = setup_jit_tls_data (stack_start, mono_thread_abort);
}
static void
-mono_thread_attach_cb (guint32 tid, gpointer stack_start)
+mono_thread_attach_cb (gsize tid, gpointer stack_start)
{
MonoThread *thread;
void *jit_tls = setup_jit_tls_data (stack_start, mono_thread_abort_dummy);
if (jit_tls) {
mono_arch_free_jit_tls_data (jit_tls);
+
+#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
+ mono_free_altstack (jit_tls);
+#endif
g_free (jit_tls->first_lmf);
g_free (jit_tls);
thread->jit_data = NULL;
* loop, see bug #53003 for an example. To prevent this, we put an upper
* bound on the number of iterations.
*/
- niterations = 1000;
+ if (cfg->num_bblocks > 1000)
+ niterations = cfg->num_bblocks * 2;
+ else
+ niterations = 1000;
do {
MonoBasicBlock *previous_bb;
changed = FALSE;
cfg->native_code, cfg->native_code + cfg->code_len, cfg->domain->friendly_name);
g_free (nm);
}
+
+#ifdef MONO_ARCH_HAVE_SAVE_UNWIND_INFO
+ mono_arch_save_unwind_info (cfg);
+#endif
mono_arch_patch_code (cfg->method, cfg->domain, cfg->native_code, cfg->patch_info, cfg->run_cctors);
case CEE_STIND_R4:
case CEE_STIND_R8:
case CEE_STOBJ:
- if (tree->ssa_op == MONO_SSA_NOP) {
+ if ((tree->ssa_op == MONO_SSA_NOP) || (tree->ssa_op & MONO_SSA_ADDRESS_TAKEN)) {
memset (acp, 0, sizeof (MonoInst *) * acp_size);
return;
}
mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gboolean run_cctors, gboolean compile_aot, int parts)
{
MonoMethodHeader *header = mono_method_get_header (method);
- guint8 *ip = (guint8 *)header->code;
+ guint8 *ip;
MonoCompile *cfg;
MonoJitInfo *jinfo;
int dfn = 0, i, code_size_ratio;
+ gboolean deadce_has_run = FALSE;
+
+ if (!header)
+ return NULL;
+
+ ip = (guint8 *)header->code;
mono_jit_stats.methods_compiled++;
if (mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION)
cfg->compile_aot = compile_aot;
cfg->intvars = mono_mempool_alloc0 (cfg->mempool, sizeof (guint16) * STACK_MAX *
mono_method_get_header (method)->max_stack);
-
+ cfg->aliasing_info = NULL;
+
if (cfg->verbose_level > 2)
g_print ("converting method %s\n", mono_method_full_name (method, TRUE));
#else
/* fixme: add all optimizations which requires SSA */
- if (cfg->opt & (MONO_OPT_DEADCE | MONO_OPT_ABCREM | MONO_OPT_SSAPRE)) {
+ if (cfg->opt & (MONO_OPT_SSA | MONO_OPT_ABCREM | MONO_OPT_SSAPRE)) {
if (!(cfg->comp_done & MONO_COMP_SSA) && !header->num_clauses && !cfg->disable_ssa) {
mono_local_cprop (cfg);
mono_ssa_compute (cfg);
}
if (cfg->comp_done & MONO_COMP_SSA) {
- mono_ssa_deadce (cfg);
+ //mono_ssa_deadce (cfg);
//mono_ssa_strength_reduction (cfg);
+ if (cfg->opt & MONO_OPT_SSAPRE) {
+ mono_perform_ssapre (cfg);
+ //mono_local_cprop (cfg);
+ }
+
+ if (cfg->opt & MONO_OPT_DEADCE) {
+ mono_ssa_deadce (cfg);
+ deadce_has_run = TRUE;
+ }
+
if ((cfg->flags & MONO_CFG_HAS_LDELEMA) && (cfg->opt & MONO_OPT_ABCREM))
mono_perform_abc_removal (cfg);
- if (cfg->opt & MONO_OPT_SSAPRE)
- mono_perform_ssapre (cfg);
-
mono_ssa_remove (cfg);
if (cfg->opt & MONO_OPT_BRANCH)
if (cfg->opt & MONO_OPT_LINEARS) {
GList *vars, *regs;
+
+ /* For now, compute aliasing info only if needed for deadce... */
+ if ((cfg->opt & MONO_OPT_DEADCE) && (! deadce_has_run) && (header->num_clauses == 0)) {
+ cfg->aliasing_info = mono_build_aliasing_information (cfg);
+ }
/* fixme: maybe we can avoid to compute livenesss here if already computed ? */
cfg->comp_done &= ~MONO_COMP_LIVENESS;
if (!(cfg->comp_done & MONO_COMP_LIVENESS))
mono_analyze_liveness (cfg);
+ if (cfg->aliasing_info != NULL) {
+ mono_aliasing_deadce (cfg->aliasing_info);
+ deadce_has_run = TRUE;
+ }
+
if ((vars = mono_arch_get_allocatable_int_vars (cfg))) {
regs = mono_arch_get_global_int_regs (cfg);
if (cfg->got_var)
regs = g_list_delete_link (regs, regs);
mono_linear_scan (cfg, vars, regs, &cfg->used_int_regs);
}
+
+ if (cfg->aliasing_info != NULL) {
+ mono_destroy_aliasing_information (cfg->aliasing_info);
+ cfg->aliasing_info = NULL;
+ }
}
//mono_print_code (cfg);
mono_codegen (cfg);
if (cfg->verbose_level >= 2) {
char *id = mono_method_full_name (cfg->method, FALSE);
- mono_disassemble_code (cfg->native_code, cfg->code_len, id + 3);
+ mono_disassemble_code (cfg, cfg->native_code, cfg->code_len, id + 3);
g_free (id);
}
}
cfg->jit_info = jinfo;
+#if defined(__arm__)
+ mono_arch_fixup_jinfo (cfg);
+#endif
mono_domain_lock (cfg->domain);
mono_jit_info_table_add (cfg->domain, jinfo);
method = mono_get_inflated_method (method);
#ifdef MONO_USE_AOT_COMPILER
- if (!mono_compile_aot && (opt & MONO_OPT_AOT)) {
+ if (!mono_compile_aot && (opt & MONO_OPT_AOT) && !(mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION)) {
MonoJitInfo *info;
MonoDomain *domain = mono_domain_get ();
mono_lookup_pinvoke_call (method, NULL, NULL);
}
nm = mono_marshal_get_native_wrapper (method);
- return mono_compile_method (nm);
+ return mono_get_addr_from_ftnptr (mono_compile_method (nm));
//if (mono_debug_format != MONO_DEBUG_FORMAT_NONE)
//mono_debug_add_wrapper (method, nm);
if (*name == '.' && (strcmp (name, ".ctor") == 0)) {
MonoJitICallInfo *mi = mono_find_jit_icall_by_name ("mono_delegate_ctor");
g_assert (mi);
- return (gpointer)mono_icall_get_wrapper (mi);
+ return mono_get_addr_from_ftnptr ((gpointer)mono_icall_get_wrapper (mi));
} else if (*name == 'I' && (strcmp (name, "Invoke") == 0)) {
nm = mono_marshal_get_delegate_invoke (method);
- return mono_jit_compile_method (nm);
+ return mono_get_addr_from_ftnptr (mono_compile_method (nm));
} else if (*name == 'B' && (strcmp (name, "BeginInvoke") == 0)) {
nm = mono_marshal_get_delegate_begin_invoke (method);
- return mono_jit_compile_method (nm);
+ return mono_get_addr_from_ftnptr (mono_compile_method (nm));
} else if (*name == 'E' && (strcmp (name, "EndInvoke") == 0)) {
nm = mono_marshal_get_delegate_end_invoke (method);
- return mono_jit_compile_method (nm);
+ return mono_get_addr_from_ftnptr (mono_compile_method (nm));
}
}
return NULL;
cfg = mini_method_compile (method, opt, target_domain, TRUE, FALSE, 0);
+ if (!cfg) {
+ /* Throw a type load exception if needed */
+ MonoLoaderError *error = mono_loader_get_last_error ();
+
+ if (error) {
+ MonoException *ex = mini_loader_error_to_exception (error);
+ mono_loader_clear_error ();
+ mono_raise_exception (ex);
+ }
+ else
+ g_assert_not_reached ();
+ }
+
mono_domain_lock (target_domain);
/* Check if some other thread already did the job. In this case, we can
mono_domain_unlock (target_domain);
mono_jit_stats.methods_lookups++;
mono_runtime_class_init (mono_class_vtable (domain, method->klass));
- return info->code_start;
+ return mono_create_ftnptr (target_domain, info->code_start);
}
}
mono_domain_unlock (target_domain);
p = mono_jit_compile_method_inner (method, target_domain);
- return p;
+ return mono_create_ftnptr (target_domain, p);
}
static gpointer
#define GET_CONTEXT \
ucontext_t *uctx = context; \
struct sigcontext *ctx = (struct sigcontext *)&(uctx->uc_mcontext);
-#elif defined(__ppc__) || defined (__powerpc__) || defined (__s390__) || defined (MONO_ARCH_USE_SIGACTION)
+#elif defined (MONO_ARCH_USE_SIGACTION)
#define GET_CONTEXT \
void *ctx = context;
#else
SIG_HANDLER_SIGNATURE (sigill_signal_handler)
{
MonoException *exc;
- GET_CONTEXT
+ GET_CONTEXT;
+
exc = mono_get_exception_execution_engine ("SIGILL");
mono_arch_handle_exception (ctx, exc, FALSE);
SIG_HANDLER_SIGNATURE (sigsegv_signal_handler)
{
MonoException *exc = NULL;
+ MonoJitInfo *ji;
+
#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
#endif
- GET_CONTEXT
+ GET_CONTEXT;
+
+#ifdef MONO_ARCH_USE_SIGACTION
+ if (debug_options.collect_pagefault_stats) {
+ if (mono_raw_buffer_is_pagefault (info->si_addr)) {
+ mono_raw_buffer_handle_pagefault (info->si_addr);
+ return;
+ }
+ if (mono_aot_is_pagefault (info->si_addr)) {
+ mono_aot_handle_pagefault (info->si_addr);
+ return;
+ }
+ }
+#endif
#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
/* Can't allocate memory using Boehm GC on altstack */
exc = mono_domain_get ()->null_reference_ex;
#endif
- if (debug_options.abort_on_sigsegv) {
- MonoJitInfo *ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context(ctx));
- if (!ji) {
- fprintf (stderr, "Got SIGSEGV while in unmanaged code, and the 'abort-on-sigsegv' MONO_DEBUG option is set. Aborting...\n");
- /* Segfault in unmanaged code */
- abort ();
- }
+ ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context(ctx));
+ if (!ji) {
+ mono_handle_native_sigsegv (ctx);
}
mono_arch_handle_exception (ctx, exc, FALSE);
static void
SIG_HANDLER_SIGNATURE (sigquit_signal_handler)
{
- MonoException *exc;
- GET_CONTEXT
+ MonoException *exc;
+ GET_CONTEXT;
- exc = mono_get_exception_execution_engine ("Interrupted (SIGQUIT).");
+ exc = mono_get_exception_execution_engine ("Interrupted (SIGQUIT).");
- mono_arch_handle_exception (ctx, exc, FALSE);
+ mono_arch_handle_exception (ctx, exc, FALSE);
}
static void
SIG_HANDLER_SIGNATURE (sigint_signal_handler)
{
MonoException *exc;
- GET_CONTEXT
+ GET_CONTEXT;
exc = mono_get_exception_execution_engine ("Interrupted (SIGINT).");
add_signal_handler (SIGUSR2, sigusr2_signal_handler);
add_signal_handler (mono_thread_get_abort_signal (), sigusr1_signal_handler);
+ signal (SIGPIPE, SIG_IGN);
/* catch SIGSEGV */
#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
} else {
addr = mono_compile_method (method);
}
- return addr;
+ return mono_get_addr_from_ftnptr (addr);
}
static void
debug_options.handle_sigint = TRUE;
else if (!strcmp (arg, "keep-delegates"))
debug_options.keep_delegates = TRUE;
- else if (!strcmp (arg, "abort-on-sigsegv"))
- debug_options.abort_on_sigsegv = TRUE;
+ else if (!strcmp (arg, "collect-pagefault-stats"))
+ debug_options.collect_pagefault_stats = TRUE;
else {
fprintf (stderr, "Invalid option for the MONO_DEBUG env variable: %s\n", arg);
- fprintf (stderr, "Available options: 'handle-sigint', 'keep-delegates', 'abort-on-sigsegv'\n");
+ fprintf (stderr, "Available options: 'handle-sigint', 'keep-delegates', 'collect-pagefault-stats'\n");
exit (1);
}
}
{
MonoDomain *domain;
+ /* Happens when using the embedding interface */
+ if (default_opt == 0)
+ default_opt = mono_parse_default_optimizations (NULL);
+
InitializeCriticalSection (&jit_mutex);
global_codeman = mono_code_manager_new ();
mono_init_trampolines ();
+ mono_init_exceptions ();
+
if (!g_thread_supported ())
g_thread_init (NULL);
if (getenv ("MONO_DEBUG") != NULL)
mini_parse_debug_options ();
-
+
+ if (mono_running_on_valgrind ()) {
+ gsize stack_bottom = (gsize)&domain;
+ stack_bottom += 4095;
+ stack_bottom &= ~4095;
+ GC_stackbottom = (char*)stack_bottom;
+ }
MONO_GC_PRE_INIT ();
mono_jit_tls_id = TlsAlloc ();
mono_install_free_method (mono_jit_free_method);
mono_install_trampoline (mono_create_jit_trampoline);
mono_install_remoting_trampoline (mono_jit_create_remoting_trampoline);
+ mono_install_delegate_trampoline (mono_create_delegate_trampoline);
#endif
#define JIT_INVOKE_WORKS
#ifdef JIT_INVOKE_WORKS
mono_install_get_cached_class_info (mono_aot_get_cached_class_info);
mono_install_jit_info_find_in_aot (mono_aot_find_jit_info);
+ if (debug_options.collect_pagefault_stats) {
+ mono_raw_buffer_set_make_unreadable (TRUE);
+ mono_aot_set_make_unreadable (TRUE);
+ }
+
domain = mono_init_from_assembly (filename, filename);
mono_icall_init ();
mono_marshal_init ();
mono_arch_register_lowlevel_calls ();
- mono_register_jit_icall (mono_profiler_method_enter, "mono_profiler_method_enter", NULL, TRUE);
- mono_register_jit_icall (mono_profiler_method_leave, "mono_profiler_method_leave", NULL, TRUE);
- mono_register_jit_icall (mono_trace_enter_method, "mono_trace_enter_method", NULL, TRUE);
- mono_register_jit_icall (mono_trace_leave_method, "mono_trace_leave_method", NULL, TRUE);
- mono_register_jit_icall (mono_get_lmf_addr, "mono_get_lmf_addr", helper_sig_ptr_void, TRUE);
- mono_register_jit_icall (mono_jit_thread_attach, "mono_jit_thread_attach", helper_sig_void_void, TRUE);
- mono_register_jit_icall (mono_domain_get, "mono_domain_get", helper_sig_domain_get, TRUE);
-
- mono_register_jit_icall (mono_arch_get_throw_exception (), "mono_arch_throw_exception", helper_sig_void_obj, TRUE);
- mono_register_jit_icall (mono_arch_get_rethrow_exception (), "mono_arch_rethrow_exception", helper_sig_void_obj, TRUE);
- mono_register_jit_icall (mono_arch_get_throw_exception_by_name (), "mono_arch_throw_exception_by_name",
- helper_sig_void_ptr, TRUE);
+ register_icall (mono_profiler_method_enter, "mono_profiler_method_enter", NULL, TRUE);
+ register_icall (mono_profiler_method_leave, "mono_profiler_method_leave", NULL, TRUE);
+ register_icall (mono_trace_enter_method, "mono_trace_enter_method", NULL, TRUE);
+ register_icall (mono_trace_leave_method, "mono_trace_leave_method", NULL, TRUE);
+ register_icall (mono_get_lmf_addr, "mono_get_lmf_addr", "ptr", TRUE);
+ register_icall (mono_jit_thread_attach, "mono_jit_thread_attach", "void", TRUE);
+ register_icall (mono_domain_get, "mono_domain_get", "ptr", TRUE);
+
+ register_icall (mono_arch_get_throw_exception (), "mono_arch_throw_exception", "void object", TRUE);
+ register_icall (mono_arch_get_rethrow_exception (), "mono_arch_rethrow_exception", "void object", TRUE);
+ register_icall (mono_arch_get_throw_exception_by_name (), "mono_arch_throw_exception_by_name", "void ptr", TRUE);
#if MONO_ARCH_HAVE_THROW_CORLIB_EXCEPTION
- mono_register_jit_icall (mono_arch_get_throw_corlib_exception (), "mono_arch_throw_corlib_exception",
- helper_sig_void_ptr, TRUE);
+ register_icall (mono_arch_get_throw_corlib_exception (), "mono_arch_throw_corlib_exception",
+ "void ptr", TRUE);
#endif
- mono_register_jit_icall (mono_thread_get_pending_exception, "mono_thread_get_pending_exception", helper_sig_obj_void, FALSE);
- mono_register_jit_icall (mono_thread_interruption_checkpoint, "mono_thread_interruption_checkpoint", helper_sig_void_void, FALSE);
- mono_register_jit_icall (mono_thread_force_interruption_checkpoint, "mono_thread_force_interruption_checkpoint", helper_sig_void_void, FALSE);
- mono_register_jit_icall (mono_load_remote_field_new, "mono_load_remote_field_new", helper_sig_obj_obj_ptr_ptr, FALSE);
- mono_register_jit_icall (mono_store_remote_field_new, "mono_store_remote_field_new", helper_sig_void_obj_ptr_ptr_obj, FALSE);
+ register_icall (mono_thread_get_pending_exception, "mono_thread_get_pending_exception", "object", FALSE);
+ register_icall (mono_thread_interruption_checkpoint, "mono_thread_interruption_checkpoint", "void", FALSE);
+ register_icall (mono_thread_force_interruption_checkpoint, "mono_thread_force_interruption_checkpoint", "void", FALSE);
+ register_icall (mono_load_remote_field_new, "mono_load_remote_field_new", "object object ptr ptr", FALSE);
+ register_icall (mono_store_remote_field_new, "mono_store_remote_field_new", "void object ptr ptr object", FALSE);
/*
* NOTE, NOTE, NOTE, NOTE:
* rule to the burg files, because we need the arity information to be correct.
*/
#ifndef MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
- mono_register_opcode_emulation (OP_LMUL, "__emul_lmul", helper_sig_long_long_long, mono_llmult, TRUE);
- mono_register_opcode_emulation (OP_LDIV, "__emul_ldiv", helper_sig_long_long_long, mono_lldiv, FALSE);
- mono_register_opcode_emulation (OP_LDIV_UN, "__emul_ldiv_un", helper_sig_long_long_long, mono_lldiv_un, FALSE);
- mono_register_opcode_emulation (OP_LREM, "__emul_lrem", helper_sig_long_long_long, mono_llrem, FALSE);
- mono_register_opcode_emulation (OP_LREM_UN, "__emul_lrem_un", helper_sig_long_long_long, mono_llrem_un, FALSE);
- mono_register_opcode_emulation (OP_LMUL_OVF_UN, "__emul_lmul_ovf_un", helper_sig_long_long_long, mono_llmult_ovf_un, FALSE);
- mono_register_opcode_emulation (OP_LMUL_OVF, "__emul_lmul_ovf", helper_sig_long_long_long, mono_llmult_ovf, FALSE);
+ mono_register_opcode_emulation (OP_LMUL, "__emul_lmul", "long long long", mono_llmult, TRUE);
+ mono_register_opcode_emulation (OP_LDIV, "__emul_ldiv", "long long long", mono_lldiv, FALSE);
+ mono_register_opcode_emulation (OP_LDIV_UN, "__emul_ldiv_un", "long long long", mono_lldiv_un, FALSE);
+ mono_register_opcode_emulation (OP_LREM, "__emul_lrem", "long long long", mono_llrem, FALSE);
+ mono_register_opcode_emulation (OP_LREM_UN, "__emul_lrem_un", "long long long", mono_llrem_un, FALSE);
+ mono_register_opcode_emulation (OP_LMUL_OVF_UN, "__emul_lmul_ovf_un", "long long long", mono_llmult_ovf_un, FALSE);
+ mono_register_opcode_emulation (OP_LMUL_OVF, "__emul_lmul_ovf", "long long long", mono_llmult_ovf, FALSE);
#endif
#ifndef MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
- mono_register_opcode_emulation (OP_LSHL, "__emul_lshl", helper_sig_long_long_int, mono_lshl, TRUE);
- mono_register_opcode_emulation (OP_LSHR, "__emul_lshr", helper_sig_long_long_int, mono_lshr, TRUE);
- mono_register_opcode_emulation (OP_LSHR_UN, "__emul_lshr_un", helper_sig_long_long_int, mono_lshr_un, TRUE);
+ mono_register_opcode_emulation (OP_LSHL, "__emul_lshl", "long long int32", mono_lshl, TRUE);
+ mono_register_opcode_emulation (OP_LSHR, "__emul_lshr", "long long int32", mono_lshr, TRUE);
+ mono_register_opcode_emulation (OP_LSHR_UN, "__emul_lshr_un", "long long int32", mono_lshr_un, TRUE);
#endif
- mono_register_opcode_emulation (OP_FCONV_TO_U8, "__emul_fconv_to_u8", helper_sig_ulong_double, mono_fconv_u8, FALSE);
- mono_register_opcode_emulation (OP_FCONV_TO_U4, "__emul_fconv_to_u4", helper_sig_uint_double, mono_fconv_u4, FALSE);
- mono_register_opcode_emulation (OP_FCONV_TO_OVF_I8, "__emul_fconv_to_ovf_i8", helper_sig_long_double, mono_fconv_ovf_i8, FALSE);
- mono_register_opcode_emulation (OP_FCONV_TO_OVF_U8, "__emul_fconv_to_ovf_u8", helper_sig_ulong_double, mono_fconv_ovf_u8, FALSE);
+#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, TRUE);
+ mono_register_opcode_emulation (CEE_DIV_UN, "__emul_idiv_un", "int32 int32 int32", mono_idiv_un, TRUE);
+ mono_register_opcode_emulation (CEE_REM, "__emul_irem", "int32 int32 int32", mono_irem, TRUE);
+ mono_register_opcode_emulation (CEE_REM_UN, "__emul_irem_un", "int32 int32 int32", mono_irem_un, TRUE);
+#endif
+
+#ifdef MONO_ARCH_EMULATE_MUL_DIV
+ mono_register_opcode_emulation (CEE_MUL_OVF, "__emul_imul_ovf", "int32 int32 int32", mono_imul_ovf, TRUE);
+ mono_register_opcode_emulation (CEE_MUL_OVF_UN, "__emul_imul_ovf_un", "int32 int32 int32", mono_imul_ovf_un, TRUE);
+ mono_register_opcode_emulation (CEE_MUL, "__emul_imul", "int32 int32 int32", mono_imul, TRUE);
+ mono_register_opcode_emulation (OP_FDIV, "__emul_fdiv", "double double double", mono_fdiv, TRUE);
+#endif
+
+ mono_register_opcode_emulation (OP_FCONV_TO_U8, "__emul_fconv_to_u8", "ulong double", mono_fconv_u8, FALSE);
+ mono_register_opcode_emulation (OP_FCONV_TO_U4, "__emul_fconv_to_u4", "uint32 double", mono_fconv_u4, FALSE);
+ mono_register_opcode_emulation (OP_FCONV_TO_OVF_I8, "__emul_fconv_to_ovf_i8", "long double", mono_fconv_ovf_i8, FALSE);
+ mono_register_opcode_emulation (OP_FCONV_TO_OVF_U8, "__emul_fconv_to_ovf_u8", "ulong double", mono_fconv_ovf_u8, FALSE);
#ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
- mono_register_opcode_emulation (OP_FCONV_TO_I8, "__emul_fconv_to_i8", helper_sig_long_double, mono_fconv_i8, FALSE);
+ 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", helper_sig_double_int, mono_conv_to_r8_un, FALSE);
+ mono_register_opcode_emulation (CEE_CONV_R_UN, "__emul_conv_r_un", "double int32", mono_conv_to_r8_un, FALSE);
#endif
#ifdef MONO_ARCH_EMULATE_LCONV_TO_R8
- mono_register_opcode_emulation (OP_LCONV_TO_R8, "__emul_lconv_to_r8", helper_sig_double_long, mono_lconv_to_r8, FALSE);
+ mono_register_opcode_emulation (OP_LCONV_TO_R8, "__emul_lconv_to_r8", "double long", mono_lconv_to_r8, FALSE);
#endif
#ifdef MONO_ARCH_EMULATE_LCONV_TO_R4
- mono_register_opcode_emulation (OP_LCONV_TO_R4, "__emul_lconv_to_r4", helper_sig_float_long, mono_lconv_to_r4, FALSE);
+ mono_register_opcode_emulation (OP_LCONV_TO_R4, "__emul_lconv_to_r4", "float long", mono_lconv_to_r4, FALSE);
#endif
#ifdef MONO_ARCH_EMULATE_LCONV_TO_R8_UN
- mono_register_opcode_emulation (OP_LCONV_TO_R_UN, "__emul_lconv_to_r8_un", helper_sig_double_long, mono_lconv_to_r8_un, FALSE);
+ mono_register_opcode_emulation (OP_LCONV_TO_R_UN, "__emul_lconv_to_r8_un", "double long", mono_lconv_to_r8_un, FALSE);
#endif
#ifdef MONO_ARCH_EMULATE_FREM
- mono_register_opcode_emulation (OP_FREM, "__emul_frem", helper_sig_double_double_double, fmod, FALSE);
+ mono_register_opcode_emulation (OP_FREM, "__emul_frem", "double double double", fmod, FALSE);
#endif
#if SIZEOF_VOID_P == 4
- mono_register_opcode_emulation (OP_FCONV_TO_U, "__emul_fconv_to_u", helper_sig_uint_double, mono_fconv_u4, TRUE);
+ mono_register_opcode_emulation (OP_FCONV_TO_U, "__emul_fconv_to_u", "uint32 double", mono_fconv_u4, TRUE);
#endif
/* other jit icalls */
- mono_register_jit_icall (mono_delegate_ctor, "mono_delegate_ctor", helper_sig_void_obj_obj_ptr, FALSE);
- mono_register_jit_icall (mono_class_static_field_address , "mono_class_static_field_address",
- helper_sig_ptr_ptr_ptr, FALSE);
- mono_register_jit_icall (mono_ldtoken_wrapper, "mono_ldtoken_wrapper", helper_sig_ptr_ptr_ptr_ptr, FALSE);
- mono_register_jit_icall (mono_get_special_static_data, "mono_get_special_static_data", helper_sig_ptr_int, FALSE);
- mono_register_jit_icall (mono_ldstr, "mono_ldstr", helper_sig_ldstr, FALSE);
- mono_register_jit_icall (helper_stelem_ref, "helper_stelem_ref", helper_sig_stelem_ref, FALSE);
- mono_register_jit_icall (helper_stelem_ref_check, "helper_stelem_ref_check", helper_sig_stelem_ref_check, FALSE);
- mono_register_jit_icall (mono_object_new, "mono_object_new", helper_sig_object_new, FALSE);
- mono_register_jit_icall (mono_object_new_specific, "mono_object_new_specific", helper_sig_object_new_specific, FALSE);
- mono_register_jit_icall (mono_array_new, "mono_array_new", helper_sig_newarr, FALSE);
- mono_register_jit_icall (mono_array_new_specific, "mono_array_new_specific", helper_sig_newarr_specific, FALSE);
- mono_register_jit_icall (mono_runtime_class_init, "mono_runtime_class_init", helper_sig_void_ptr, FALSE);
- mono_register_jit_icall (mono_ldftn, "mono_ldftn", helper_sig_compile, FALSE);
- mono_register_jit_icall (mono_ldftn_nosync, "mono_ldftn_nosync", helper_sig_compile, FALSE);
- mono_register_jit_icall (mono_ldvirtfn, "mono_ldvirtfn", helper_sig_compile_virt, FALSE);
- mono_register_jit_icall (helper_compile_generic_method, "compile_generic_method", helper_sig_compile_generic_method, FALSE);
+ register_icall (mono_delegate_ctor, "mono_delegate_ctor", "void object object ptr", FALSE);
+ register_icall (mono_class_static_field_address , "mono_class_static_field_address",
+ "ptr ptr ptr", FALSE);
+ register_icall (mono_ldtoken_wrapper, "mono_ldtoken_wrapper", "ptr ptr ptr ptr", FALSE);
+ register_icall (mono_get_special_static_data, "mono_get_special_static_data", "ptr int", FALSE);
+ register_icall (mono_ldstr, "mono_ldstr", "object ptr ptr int32", FALSE);
+ register_icall (helper_stelem_ref, "helper_stelem_ref", "void ptr int32 object", FALSE);
+ register_icall (helper_stelem_ref_check, "helper_stelem_ref_check", "void object object", FALSE);
+ register_icall (mono_object_new, "mono_object_new", "object ptr ptr", FALSE);
+ register_icall (mono_object_new_specific, "mono_object_new_specific", "object ptr", FALSE);
+ register_icall (mono_array_new, "mono_array_new", "object ptr ptr int32", FALSE);
+ register_icall (mono_array_new_specific, "mono_array_new_specific", "object ptr int32", FALSE);
+ register_icall (mono_runtime_class_init, "mono_runtime_class_init", "void ptr", FALSE);
+ register_icall (mono_ldftn, "mono_ldftn", "ptr ptr", FALSE);
+ register_icall (mono_ldftn_nosync, "mono_ldftn_nosync", "ptr ptr", FALSE);
+ register_icall (mono_ldvirtfn, "mono_ldvirtfn", "ptr object ptr", FALSE);
+ register_icall (helper_compile_generic_method, "compile_generic_method", "ptr object ptr ptr", FALSE);
+ register_icall (helper_ldstr, "helper_ldstr", "object ptr int", FALSE);
#endif
#define JIT_RUNTIME_WORKS
g_print ("LinkDemand (aptc) : %ld\n", mono_jit_stats.cas_linkdemand_aptc);
g_print ("Demand (code gen) : %ld\n", mono_jit_stats.cas_demand_generation);
}
+ if (debug_options.collect_pagefault_stats) {
+ g_print ("Metadata pagefaults : %d\n", mono_raw_buffer_get_n_pagefaults ());
+ g_print ("AOT pagefaults : %d\n", mono_aot_get_n_pagefaults ());
+ }
}
}