gboolean mono_break_on_exc = FALSE;
gboolean mono_compile_aot = FALSE;
-CRITICAL_SECTION *metadata_section = NULL;
-
static int mini_verbose = 0;
#ifdef MONO_USE_EXC_TABLES
return CEE_LDOBJ;
case MONO_TYPE_TYPEDBYREF:
return CEE_LDOBJ;
+ case MONO_TYPE_GENERICINST:
+ if (type->data.generic_inst->generic_type->type == MONO_TYPE_VALUETYPE)
+ return CEE_LDOBJ;
+ return CEE_LDIND_REF;
default:
g_error ("unknown type 0x%02x in type_to_ldind", type->type);
}
return CEE_STOBJ;
case MONO_TYPE_TYPEDBYREF:
return CEE_STOBJ;
+ case MONO_TYPE_GENERICINST:
+ if (type->data.generic_inst->generic_type->type == MONO_TYPE_VALUETYPE)
+ return CEE_STOBJ;
+ return CEE_STIND_REF;
default:
g_error ("unknown type 0x%02x in type_to_stind", type->type);
}
inst->klass = mono_defaults.typed_reference_class;
inst->type = STACK_VTYPE;
return;
+ case MONO_TYPE_GENERICINST:
+ if (type->data.generic_inst->generic_type->type == MONO_TYPE_VALUETYPE) {
+ inst->klass = mono_class_from_mono_type (type);
+ inst->type = STACK_VTYPE;
+ } else {
+ inst->type = STACK_OBJ;
+ }
+ return;
default:
g_error ("unknown type 0x%02x in eval stack type", type->type);
}
cfg->vars = (MonoMethodVar **)g_realloc (cfg->vars, sizeof (MonoMethodVar*) * cfg->varinfo_count);
}
+ /*g_print ("created temp %d of type 0x%x\n", num, type->type);*/
mono_jit_stats.allocate_var++;
MONO_INST_NEW (cfg, inst, opcode);
MonoInst **args, int calli, int virtual, const guint8 *ip, gboolean to_end)
{
MonoCallInst *call;
+ MonoInst *arg;
int i;
MONO_INST_NEW_CALL (cfg, call, ret_type_to_call_opcode (sig->ret, calli, virtual));
call->signature = sig;
call = mono_arch_call_opcode (cfg, bblock, call, virtual);
- for (i = 0; i < (sig->param_count + sig->hasthis); ++i) {
- if (call->args [i]) {
- if (!call->args [i]->cil_code)
- call->args [i]->cil_code = ip;
- if (to_end)
- mono_add_ins_to_end (bblock, call->args [i]);
- else
- MONO_ADD_INS (bblock, call->args [i]);
- }
+ for (arg = call->out_args; arg;) {
+ MonoInst *narg = arg->next;
+ arg->next = NULL;
+ if (!arg->cil_code)
+ arg->cil_code = ip;
+ if (to_end)
+ mono_add_ins_to_end (bblock, arg);
+ else
+ MONO_ADD_INS (bblock, arg);
+ arg = narg;
}
return call;
}
mono_emulate_opcode (MonoCompile *cfg, MonoInst *tree, MonoInst **iargs, MonoJitICallInfo *info)
{
MonoInst *ins, *temp = NULL, *store, *load;
+ MonoInst *last_arg = NULL;
int i, nargs;
MonoCallInst *call;
nargs = info->sig->param_count + info->sig->hasthis;
- for (i = 1; i < nargs; i++) {
- call->args [i - 1]->next = call->args [i];
- }
+ for (last_arg = call->out_args; last_arg && last_arg->next; last_arg = last_arg->next) ;
if (nargs)
- call->args [nargs - 1]->next = store;
+ last_arg->next = store;
if (cfg->prev_ins) {
store->next = cfg->prev_ins->next;
if (nargs)
- cfg->prev_ins->next = call->args [0];
+ cfg->prev_ins->next = call->out_args;
else
cfg->prev_ins->next = store;
} else {
store->next = cfg->cbb->code;
if (nargs)
- cfg->cbb->code = call->args [0];
+ cfg->cbb->code = call->out_args;
else
cfg->cbb->code = store;
}
MONO_ADD_INS (bblock, ins);
break;
default:
+ if (n <= sizeof (gpointer) * 5) {
+ ins->opcode = OP_MEMSET;
+ ins->inst_imm = 0;
+ ins->unused = n;
+ MONO_ADD_INS (bblock, ins);
+ break;
+ }
handle_loaded_temps (cfg, bblock, stack_start, sp);
NEW_ICONST (cfg, ins, n);
iargs [0] = dest;
#endif
else
return NULL;
+ } else if (cmethod->klass == mono_defaults.array_class) {
+ if (strcmp (cmethod->name, "get_Rank") == 0)
+ op = OP_ARRAY_RANK;
+ else if (strcmp (cmethod->name, "get_Length") == 0)
+ op = CEE_LDLEN;
+ else
+ return NULL;
} else {
return NULL;
}
#define CHECK_STACK(num) if ((sp - stack_start) < (num)) goto unverified
#define CHECK_STACK_OVF(num) if (((sp - stack_start) + (num)) > header->max_stack) goto unverified
+#define TYPE_PARAM_TO_TYPE(num) (method->klass->generic_inst->data.generic_inst->type_argv [(num)])
+#define TYPE_PARAM_TO_CLASS(num) (mono_class_from_mono_type (TYPE_PARAM_TO_TYPE ((num))))
+
/* offset from br.s -> br like opcodes */
#define BIG_BRANCH_OFFSET 13
return 1;
}
+static MonoClassField *
+get_generic_field_inst (MonoClassField *field, MonoClass *klass, MonoClass **retclass)
+{
+ int i;
+ for (i = 0; i < field->parent->field.count; ++i) {
+ if (field == &field->parent->fields [i]) {
+ *retclass = klass;
+ return &klass->fields [i];
+ }
+ }
+ return NULL;
+}
+
/*
* mono_method_to_ir: translates IL into basic blocks containing trees
*/
bbhash = g_hash_table_new (g_direct_hash, NULL);
}
- if (cfg->prof_options & MONO_PROFILE_COVERAGE)
- if (mono_profiler_get_coverage_level () == MONO_COVERAGE_INSTRUCTION)
- cfg->coverage_info = mono_profiler_coverage_alloc (cfg->method, header->code_size);
+ if (cfg->verbose_level > 2)
+ g_print ("method to IR %s\n", mono_method_full_name (method, TRUE));
+
+ if (cfg->prof_options & MONO_PROFILE_INS_COVERAGE)
+ cfg->coverage_info = mono_profiler_coverage_alloc (cfg->method, header->code_size);
dont_inline = g_list_prepend (dont_inline, method);
if (cfg->method == method) {
ip++;
break;
case CEE_CPOBJ:
- g_error ("opcode 0x%02x not handled", *ip);
+ 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 (image, token);
+
+ mono_class_init (klass);
+ if (klass->byval_arg.type == MONO_TYPE_VAR)
+ klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
+ sp -= 2;
+ if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
+ MonoInst *store, *load;
+ MONO_INST_NEW (cfg, load, CEE_LDIND_REF);
+ load->cil_code = ip;
+ load->inst_i0 = sp [1];
+ load->type = ldind_type [CEE_LDIND_REF];
+ load->flags |= ins_flag;
+ MONO_INST_NEW (cfg, store, CEE_STIND_REF);
+ store->cil_code = ip;
+ handle_loaded_temps (cfg, bblock, stack_start, sp);
+ MONO_ADD_INS (bblock, store);
+ store->inst_i0 = sp [0];
+ store->inst_i1 = load;
+ store->flags |= ins_flag;
+ } else {
+ n = mono_class_value_size (klass, NULL);
+ if ((cfg->opt & MONO_OPT_INTRINS) && n <= sizeof (gpointer) * 5) {
+ MonoInst *copy;
+ MONO_INST_NEW (cfg, copy, OP_MEMCPY);
+ copy->inst_left = sp [0];
+ copy->inst_right = sp [1];
+ copy->cil_code = ip;
+ copy->unused = n;
+ MONO_ADD_INS (bblock, copy);
+ } else {
+ MonoInst *iargs [3];
+ iargs [0] = sp [0];
+ iargs [1] = sp [1];
+ NEW_ICONST (cfg, iargs [2], n);
+ iargs [2]->cil_code = ip;
+
+ mono_emit_jit_icall (cfg, bblock, helper_memcpy, iargs, ip);
+ }
+ }
+ ins_flag = 0;
+ ip += 5;
break;
case CEE_LDOBJ: {
MonoInst *iargs [3];
klass = mono_class_get (image, token);
mono_class_init (klass);
+ if (klass->byval_arg.type == MONO_TYPE_VAR)
+ klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
+ if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
+ MONO_INST_NEW (cfg, ins, CEE_LDIND_REF);
+ ins->cil_code = ip;
+ ins->inst_i0 = sp [0];
+ ins->type = ldind_type [CEE_LDIND_REF];
+ ins->flags |= ins_flag;
+ ins_flag = 0;
+ *sp++ = ins;
+ ip += 5;
+ break;
+ }
n = mono_class_value_size (klass, NULL);
ins = mono_compile_create_var (cfg, &klass->byval_arg, OP_LOCAL);
NEW_TEMPLOADA (cfg, iargs [0], ins->inst_c0);
NEW_TEMPLOAD (cfg, *sp, ins->inst_c0);
++sp;
ip += 5;
+ ins_flag = 0;
inline_costs += 1;
break;
}
} else {
MonoVTable *vtable = mono_class_vtable (cfg->domain, cmethod->klass);
NEW_PCONST (cfg, iargs [0], vtable);
- temp = mono_emit_jit_icall (cfg, bblock, mono_object_new_specific, iargs, ip);
+ if (cmethod->klass->has_finalize || cmethod->klass->marshalbyref || (cfg->prof_options & MONO_PROFILE_ALLOCATIONS))
+ temp = mono_emit_jit_icall (cfg, bblock, mono_object_new_specific, iargs, ip);
+ else
+ temp = mono_emit_jit_icall (cfg, bblock, mono_object_new_fast, iargs, ip);
}
NEW_TEMPLOAD (cfg, *sp, temp);
}
ip += 5;
*sp++ = ins;
break;
+ case CEE_UNBOX_ANY: {
+ MonoInst *add, *vtoffset;
+ MonoInst *iargs [3];
+
+ CHECK_STACK (1);
+ --sp;
+ 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 (image, token);
+ mono_class_init (klass);
+
+ if (klass->byval_arg.type == MONO_TYPE_VAR)
+ klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
+
+ if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
+ /* CASTCLASS */
+ MONO_INST_NEW (cfg, ins, CEE_CASTCLASS);
+ ins->type = STACK_OBJ;
+ ins->inst_left = *sp;
+ ins->klass = klass;
+ ins->inst_newa_class = klass;
+ ins->cil_code = ip;
+ *sp++ = ins;
+ ip += 5;
+ break;
+ }
+
+ MONO_INST_NEW (cfg, ins, OP_UNBOXCAST);
+ ins->type = STACK_OBJ;
+ ins->inst_left = *sp;
+ ins->klass = klass;
+ ins->inst_newa_class = klass;
+ ins->cil_code = ip;
+
+ MONO_INST_NEW (cfg, add, CEE_ADD);
+ NEW_ICONST (cfg, vtoffset, sizeof (MonoObject));
+ add->inst_left = ins;
+ add->inst_right = vtoffset;
+ add->type = STACK_MP;
+ *sp = add;
+ ip += 5;
+ /* LDOBJ impl */
+ n = mono_class_value_size (klass, NULL);
+ ins = mono_compile_create_var (cfg, &klass->byval_arg, OP_LOCAL);
+ NEW_TEMPLOADA (cfg, iargs [0], ins->inst_c0);
+ if ((cfg->opt & MONO_OPT_INTRINS) && n <= sizeof (gpointer) * 5) {
+ MonoInst *copy;
+ MONO_INST_NEW (cfg, copy, OP_MEMCPY);
+ copy->inst_left = iargs [0];
+ copy->inst_right = *sp;
+ copy->cil_code = ip;
+ copy->unused = n;
+ MONO_ADD_INS (bblock, copy);
+ } else {
+ iargs [1] = *sp;
+ NEW_ICONST (cfg, iargs [2], n);
+ iargs [2]->cil_code = ip;
+
+ mono_emit_jit_icall (cfg, bblock, helper_memcpy, iargs, ip);
+ }
+ NEW_TEMPLOAD (cfg, *sp, ins->inst_c0);
+ ++sp;
+ inline_costs += 2;
+ break;
+ }
case CEE_UNBOX: {
MonoInst *add, *vtoffset;
klass = mono_class_get (image, token);
mono_class_init (klass);
+ if (klass->byval_arg.type == MONO_TYPE_VAR)
+ klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
MONO_INST_NEW (cfg, ins, OP_UNBOXCAST);
ins->type = STACK_OBJ;
--sp;
klass = mono_class_get (image, read32 (ip + 1));
mono_class_init (klass);
+ if (klass->byval_arg.type == MONO_TYPE_VAR)
+ klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
ins->type = STACK_OBJ;
ins->inst_left = *sp;
ins->klass = klass;
// goto unverified;
token = read32 (ip + 1);
field = mono_field_from_token (image, token, &klass);
+ if (field->parent->gen_params)
+ field = get_generic_field_inst (field, method->klass, &klass);
mono_class_init (klass);
foffset = klass->valuetype? field->offset - sizeof (MonoObject): field->offset;
else
klass = mono_class_get (image, token);
mono_class_init (klass);
+ if (klass->byval_arg.type == MONO_TYPE_VAR)
+ klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
n = mono_type_to_stind (&klass->byval_arg);
if (n == CEE_STOBJ) {
handle_stobj (cfg, bblock, sp [0], sp [1], ip, klass, FALSE, FALSE);
else
klass = mono_class_get (image, token);
mono_class_init (klass);
+ if (klass->byval_arg.type == MONO_TYPE_VAR)
+ klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
+ if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
+ *sp = val;
+ ip += 5;
+ break;
+ }
/* much like NEWOBJ */
- NEW_DOMAINCONST (cfg, iargs [0]);
- NEW_CLASSCONST (cfg, iargs [1], klass);
-
- temp = mono_emit_jit_icall (cfg, bblock, mono_object_new, iargs, ip);
+ if ((cfg->opt & MONO_OPT_SHARED) || mono_compile_aot) {
+ NEW_DOMAINCONST (cfg, iargs [0]);
+ NEW_CLASSCONST (cfg, iargs [1], klass);
+
+ temp = mono_emit_jit_icall (cfg, bblock, mono_object_new, iargs, ip);
+ } else {
+ MonoVTable *vtable = mono_class_vtable (cfg->domain, klass);
+ NEW_PCONST (cfg, iargs [0], vtable);
+ if (1 || klass->has_finalize || (cfg->prof_options & MONO_PROFILE_ALLOCATIONS))
+ temp = mono_emit_jit_icall (cfg, bblock, mono_object_new_specific, iargs, ip);
+ else
+ temp = mono_emit_jit_icall (cfg, bblock, mono_object_new_fast, iargs, ip);
+ }
NEW_TEMPLOAD (cfg, load, temp);
NEW_ICONST (cfg, vtoffset, sizeof (MonoObject));
MONO_INST_NEW (cfg, add, CEE_ADD);
klass = mono_class_get (image, token);
mono_class_init (klass);
+ if (klass->byval_arg.type == MONO_TYPE_VAR)
+ klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
ins->inst_newa_class = klass;
ins->inst_newa_len = *sp;
ins->type = STACK_OBJ;
sp -= 2;
klass = mono_class_get (image, read32 (ip + 1));
mono_class_init (klass);
+ if (klass->byval_arg.type == MONO_TYPE_VAR)
+ klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
NEW_LDELEMA (cfg, ins, sp, klass);
ins->cil_code = ip;
*sp++ = ins;
ip += 5;
break;
+ case CEE_LDELEM: {
+ MonoInst *load;
+ CHECK_STACK (2);
+ sp -= 2;
+ token = read32 (ip + 1);
+ klass = mono_class_get (image, token);
+ mono_class_init (klass);
+ if (klass->byval_arg.type == MONO_TYPE_VAR)
+ klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
+ NEW_LDELEMA (cfg, load, sp, klass);
+ load->cil_code = ip;
+ MONO_INST_NEW (cfg, ins, mono_type_to_ldind (&klass->byval_arg));
+ ins->cil_code = ip;
+ ins->inst_left = load;
+ *sp++ = ins;
+ type_to_eval_stack_type (&klass->byval_arg, ins);
+ ip += 5;
+ break;
+ }
case CEE_LDELEM_I1:
case CEE_LDELEM_U1:
case CEE_LDELEM_I2:
++ip;
handle_loaded_temps (cfg, bblock, stack_start, sp);
MONO_ADD_INS (bblock, ins);
- /* FIXME: add the implicit STELEM_REF castclass */
+ inline_costs += 1;
+ cfg->disable_ssa = TRUE;
+ break;
+ }
+ case CEE_STELEM: {
+ MonoInst *load;
+ /*
+ * translate to:
+ * stind.x (ldelema (array, index), val)
+ * ldelema does the bounds check
+ */
+ CHECK_STACK (3);
+ sp -= 3;
+ token = read32 (ip + 1);
+ klass = mono_class_get (image, token);
+ mono_class_init (klass);
+ if (klass->byval_arg.type == MONO_TYPE_VAR)
+ klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
+ if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
+ MonoInst *iargs [3];
+ handle_loaded_temps (cfg, bblock, stack_start, sp);
+
+ iargs [2] = sp [2];
+ iargs [1] = sp [1];
+ iargs [0] = sp [0];
+
+ mono_emit_jit_icall (cfg, bblock, helper_stelem_ref, iargs, ip);
+ } else {
+ NEW_LDELEMA (cfg, load, sp, klass);
+ load->cil_code = ip;
+ MONO_INST_NEW (cfg, ins, mono_type_to_stind (&klass->byval_arg));
+ ins->cil_code = ip;
+ ins->inst_left = load;
+ ins->inst_right = sp [2];
+ handle_loaded_temps (cfg, bblock, stack_start, sp);
+ MONO_ADD_INS (bblock, ins);
+ }
+ ip += 5;
inline_costs += 1;
cfg->disable_ssa = TRUE;
break;
case CEE_ARGLIST: {
/* somewhat similar to LDTOKEN */
MonoInst *addr, *vtvar;
- CHECK_STACK (1);
+ CHECK_STACK_OVF (1);
vtvar = mono_compile_create_var (cfg, &mono_defaults.argumenthandle_class->byval_arg, OP_LOCAL);
NEW_TEMPLOADA (cfg, addr, vtvar->inst_c0);
klass = mono_method_get_wrapper_data (method, token);
else
klass = mono_class_get (image, token);
- handle_initobj (cfg, bblock, *sp, NULL, klass, stack_start, sp);
+ if (klass->byval_arg.type == MONO_TYPE_VAR)
+ klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.type_param);
+ if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
+ MonoInst *store, *load;
+ NEW_PCONST (cfg, load, NULL);
+ load->cil_code = ip;
+ load->type = STACK_OBJ;
+ MONO_INST_NEW (cfg, store, CEE_STIND_REF);
+ store->cil_code = ip;
+ handle_loaded_temps (cfg, bblock, stack_start, sp);
+ MONO_ADD_INS (bblock, store);
+ store->inst_i0 = sp [0];
+ store->inst_i1 = load;
+ break;
+ } else {
+ handle_initobj (cfg, bblock, *sp, NULL, klass, stack_start, sp);
+ }
ip += 6;
inline_costs += 1;
break;
+ case CEE_CONSTRAINED_:
+ /* FIXME: implement */
+ token = read32 (ip + 2);
+ ip += 6;
+ break;
case CEE_CPBLK:
case CEE_INITBLK: {
MonoInst *iargs [3];
inline_costs += 1;
break;
}
+ case CEE_NO_:
+ if (ip [2] & 0x1)
+ ins_flag |= MONO_INST_NOTYPECHECK;
+ if (ip [2] & 0x2)
+ ins_flag |= MONO_INST_NORANGECHECK;
+ /* we ignore the no-nullcheck for now since we
+ * really do it explicitly only when doing callvirt->call
+ */
+ ip += 3;
+ break;
case CEE_RETHROW: {
MonoInst *load;
/* FIXME: check we are in a catch handler */
case CEE_SIZEOF:
CHECK_STACK_OVF (1);
token = read32 (ip + 2);
+ /* FIXXME: handle generics. */
if (mono_metadata_token_table (token) == MONO_TABLE_TYPESPEC) {
MonoType *type = mono_type_create_from_typespec (image, token);
token = mono_type_size (type, &align);
case CEE_REFANYTYPE:
g_error ("opcode 0xfe 0x%02x not handled", ip [1]);
break;
+ case CEE_READONLY_:
+ ip += 2;
+ break;
default:
g_error ("opcode 0xfe 0x%02x not handled", ip [1]);
}
info = newarr_info;
}
else {
- MonoVTable *vtable = mono_class_vtable (cfg->domain,
- mono_array_class_get (&tree->inst_newa_class->byval_arg, 1));
+ MonoVTable *vtable = mono_class_vtable (cfg->domain, mono_array_class_get (tree->inst_newa_class, 1));
NEW_PCONST (cfg, iargs [0], vtable);
iargs [1] = tree->inst_newa_len;
{
MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
- g_free (jit_tls);
+ /* handle_remove should be eventually called for this thread, too
+ g_free (jit_tls);*/
ExitThread (-1);
}
static void
-mono_thread_start_cb (guint32 tid, gpointer stack_start, gpointer func)
+setup_jit_tls_data (gpointer stack_start, gpointer abort_func)
{
MonoJitTlsData *jit_tls;
MonoLMF *lmf;
+ MonoThread *thread;
jit_tls = g_new0 (MonoJitTlsData, 1);
TlsSetValue (mono_jit_tls_id, jit_tls);
- jit_tls->abort_func = mono_thread_abort;
+ jit_tls->abort_func = abort_func;
jit_tls->end_of_stack = stack_start;
lmf = g_new0 (MonoLMF, 1);
lmf->ebp = -1;
- jit_tls->lmf = lmf;
+ jit_tls->lmf = jit_tls->first_lmf = lmf;
+
+ thread = mono_thread_current ();
+ if (thread)
+ thread->jit_data = jit_tls;
+}
+
+static void
+mono_thread_start_cb (guint32 tid, gpointer stack_start, gpointer func)
+{
+ setup_jit_tls_data (stack_start, mono_thread_abort);
}
void (*mono_thread_attach_aborted_cb ) (MonoObject *obj) = NULL;
static void
mono_thread_attach_cb (guint32 tid, gpointer stack_start)
{
- MonoJitTlsData *jit_tls;
- MonoLMF *lmf;
-
- jit_tls = g_new0 (MonoJitTlsData, 1);
-
- TlsSetValue (mono_jit_tls_id, jit_tls);
-
- jit_tls->abort_func = mono_thread_abort_dummy;
- jit_tls->end_of_stack = stack_start;
+ setup_jit_tls_data (stack_start, mono_thread_abort_dummy);
+}
- lmf = g_new0 (MonoLMF, 1);
- lmf->ebp = -1;
+static void
+mini_thread_cleanup (MonoThread *thread)
+{
+ MonoJitTlsData *jit_tls = thread->jit_data;
- jit_tls->lmf = lmf;
+ if (jit_tls) {
+ g_free (jit_tls->first_lmf);
+ g_free (jit_tls);
+ thread->jit_data = NULL;
+ }
}
void
cfg->ret->inst_vtype = sig->ret;
cfg->ret->klass = mono_class_from_mono_type (sig->ret);
}
+ if (cfg->verbose_level > 2)
+ g_print ("creating vars\n");
if (sig->hasthis)
mono_compile_create_var (cfg, &cfg->method->klass->this_arg, OP_ARG);
cfg->locals_start = cfg->num_varinfo;
+ if (cfg->verbose_level > 2)
+ g_print ("creating locals\n");
for (i = 0; i < header->num_locals; ++i)
mono_compile_create_var (cfg, header->locals [i], OP_LOCAL);
+ if (cfg->verbose_level > 2)
+ g_print ("locals done\n");
}
#if 0
}
if (cfg->prof_options & MONO_PROFILE_COVERAGE)
- if (mono_profiler_get_coverage_level () == MONO_COVERAGE_BASIC_BLOCK)
- cfg->coverage_info = mono_profiler_coverage_alloc (cfg->method, cfg->num_bblocks);
+ cfg->coverage_info = mono_profiler_coverage_alloc (cfg->method, cfg->num_bblocks);
code = mono_arch_emit_prolog (cfg);
cfg->intvars = mono_mempool_alloc0 (cfg->mempool, sizeof (guint16) * STACK_MAX *
((MonoMethodNormal *)method)->header->max_stack);
+ if (cfg->verbose_level > 2)
+ g_print ("converting method %s\n", mono_method_full_name (method, TRUE));
+
/*
* create MonoInst* which represents arguments and local variables
*/
mono_compile_create_vars (cfg);
- if (cfg->verbose_level > 2)
- g_print ("converting method %s\n", mono_method_full_name (method, TRUE));
-
if ((i = mono_method_to_ir (cfg, method, NULL, NULL, cfg->locals_start, NULL, NULL, NULL, 0, FALSE)) < 0) {
if (cfg->prof_options & MONO_PROFILE_JIT_COMPILATION)
mono_profiler_method_end_jit (method, MONO_PROFILE_FAILED);
mono_jit_stats.basic_blocks += cfg->num_bblocks;
mono_jit_stats.max_basic_blocks = MAX (cfg->num_bblocks, mono_jit_stats.max_basic_blocks);
+ if (cfg->num_varinfo > 2000) {
+ /*
+ * we disable some optimizations if there are too many variables
+ * because JIT time may become too expensive. The actual number needs
+ * to be tweaked and eventually the non-linear algorithms should be fixed.
+ */
+ cfg->opt &= ~ (MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP);
+ cfg->disable_ssa = TRUE;
+ }
/*g_print ("numblocks = %d\n", cfg->num_bblocks);*/
/* Depth-first ordering on basic blocks */
mono_arch_handle_exception (ctx, thread->abort_exc, FALSE);
}
+static void
+sigquit_signal_handler (int _dummy)
+{
+ MonoException *exc;
+ GET_CONTEXT
+
+ exc = mono_get_exception_execution_engine ("Interrupted (SIGQUIT).");
+
+ mono_arch_handle_exception (ctx, exc, FALSE);
+}
+
+
static void
mono_runtime_install_handlers (void)
{
//g_assert (syscall (SYS_sigaction, SIGFPE, &sa, NULL) != -1);
g_assert (sigaction (SIGFPE, &sa, NULL) != -1);
+ /* catch SIGQUIT */
+ sa.sa_handler = sigquit_signal_handler;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+ g_assert (sigaction (SIGQUIT, &sa, NULL) != -1);
+
/* catch SIGILL */
sa.sa_handler = sigill_signal_handler;
sigemptyset (&sa.sa_mask);
mini_init (const char *filename)
{
MonoDomain *domain;
-
+
+ mono_arch_cpu_init ();
+
metadata_section = &ms;
InitializeCriticalSection (metadata_section);
mono_burg_init ();
mono_runtime_install_handlers ();
+ mono_threads_install_cleanup (mini_thread_cleanup);
mono_install_compile_method (mono_jit_compile_method);
mono_install_trampoline (mono_arch_create_jit_trampoline);
mono_register_jit_icall (helper_stelem_ref, "helper_stelem_ref", helper_sig_stelem_ref, 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_object_new_fast, "mono_object_new_fast", 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_string_to_utf16, "mono_string_to_utf16", helper_sig_ptr_obj, FALSE);
mono_register_jit_icall (mono_ldftn, "mono_ldftn", helper_sig_compile, FALSE);
mono_register_jit_icall (mono_ldvirtfn, "mono_ldvirtfn", helper_sig_compile_virt, FALSE);
- mono_runtime_init (domain, mono_thread_start_cb,
- mono_thread_attach_cb);
+ mono_runtime_install_cleanup ((MonoDomainFunc)mini_cleanup);
+ mono_runtime_init (domain, mono_thread_start_cb, mono_thread_attach_cb);
//mono_thread_attach (domain);
return domain;