#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>
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;
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;
}
}
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;
}
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;
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;
#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.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);
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);
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)
{
}
/* 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));
/* FIXME: check the signature matches */
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 = mini_get_method (method, token, NULL, generic_context);
}
- g_assert (cmethod);
+ if (!cmethod)
+ goto load_error;
if (!virtual && (cmethod->flags & METHOD_ATTRIBUTE_ABSTRACT))
/* MS.NET seems to silently convert this to a callvirt */
}
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 (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;
ADD_BINOP (*ip);
#ifdef MONO_ARCH_NO_EMULATE_MUL_IMM
- if (ins->inst_right->opcode == OP_ICONST) {
+ /* 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);
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;
CHECK_OPSIZE (5);
token = read32 (ip + 1);
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 */
--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;
/* 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;
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;
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) {
CHECK_OPSIZE (6);
n = read32 (ip + 2);
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_OPSIZE (6);
n = read32 (ip + 2);
cmethod = mini_get_method (method, n, NULL, generic_context);
-
+ if (!cmethod)
+ goto load_error;
mono_class_init (cmethod->klass);
if (mono_use_security_manager) {
--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;
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);
#endif
}
+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)
{
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, ptr, vtable);
- LeaveCriticalSection (&jit_mutex);
+ mono_jit_unlock ();
return ptr;
}
{
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 (t->type == MONO_TYPE_VALUETYPE)
align = sizeof (gpointer);
- offset += size;
- offset += align - 1;
- offset &= ~(align - 1);
- slot = offset;
+ 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, const char *sigstr, gpointer func, gboolean no_throw)
{
mono_arch_setup_jit_tls_data (jit_tls);
+#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
+ mono_setup_altstack (jit_tls);
+#endif
+
return jit_tls;
}
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;
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;
+ if (!header)
+ return NULL;
+
+ ip = (guint8 *)header->code;
+
mono_jit_stats.methods_compiled++;
if (mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION)
mono_profiler_method_jit (method);
}
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 ();
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
#endif
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 */
if (jit_tls->stack_size &&
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
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', 'abort-on-sigsegv', 'collect-pagefault-stats'\n");
exit (1);
}
}
mono_init_trampolines ();
+ mono_init_exceptions ();
+
if (!g_thread_supported ())
g_thread_init (NULL);
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 ();
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 ());
+ }
}
}