return OP_LSUB;
case OP_IMUL_IMM:
return OP_IMUL;
+ case OP_LMUL_IMM:
+ return OP_LMUL;
case OP_AND_IMM:
#if SIZEOF_REGISTER == 4
return OP_IAND;
return OP_LSHR_UN;
case OP_IDIV_IMM:
return OP_IDIV;
+ case OP_LDIV_IMM:
+ return OP_LDIV;
case OP_IDIV_UN_IMM:
return OP_IDIV_UN;
+ case OP_LDIV_UN_IMM:
+ return OP_LDIV_UN;
case OP_IREM_UN_IMM:
return OP_IREM_UN;
+ case OP_LREM_UN_IMM:
+ return OP_LREM_UN;
case OP_IREM_IMM:
return OP_IREM;
case OP_LREM_IMM:
{
int opcode2 = mono_op_imm_to_op (ins->opcode);
MonoInst *temp;
+ guint32 dreg;
+ const char *spec = INS_INFO (ins->opcode);
+
+ if (spec [MONO_INST_SRC2] == 'l') {
+ dreg = mono_alloc_lreg (cfg);
+
+ /* Load the 64bit constant using decomposed ops */
+ MONO_INST_NEW (cfg, temp, OP_ICONST);
+ temp->inst_c0 = ins->inst_ls_word;
+ temp->dreg = MONO_LVREG_LS (dreg);
+ mono_bblock_insert_before_ins (bb, ins, temp);
+
+ MONO_INST_NEW (cfg, temp, OP_ICONST);
+ temp->inst_c0 = ins->inst_ms_word;
+ temp->dreg = MONO_LVREG_MS (dreg);
+ } else {
+ dreg = mono_alloc_ireg (cfg);
+
+ MONO_INST_NEW (cfg, temp, OP_ICONST);
+ temp->inst_c0 = ins->inst_imm;
+ temp->dreg = dreg;
+ }
- MONO_INST_NEW (cfg, temp, OP_ICONST);
- temp->inst_c0 = ins->inst_imm;
- temp->dreg = mono_alloc_ireg (cfg);
mono_bblock_insert_before_ins (bb, ins, temp);
if (opcode2 == -1)
ins->opcode = opcode2;
if (ins->opcode == OP_LOCALLOC)
- ins->sreg1 = temp->dreg;
+ ins->sreg1 = dreg;
else
- ins->sreg2 = temp->dreg;
+ ins->sreg2 = dreg;
bb->max_vreg = MAX (bb->max_vreg, cfg->next_vreg);
}
/*
* mini_method_verify:
*
- * Verify the method using the new verfier.
+ * Verify the method using the verfier.
*
* Returns true if the method is invalid.
*/
{
GSList *tmp, *res;
gboolean is_fulltrust;
- MonoLoaderError *error;
if (method->verification_success)
return FALSE;
res = mono_method_verify_with_current_settings (method, cfg->skip_visibility, is_fulltrust);
- if ((error = mono_loader_get_last_error ())) {
- if (fail_compile)
- cfg->exception_type = error->exception_type;
- else
+ if (mono_loader_get_last_error ()) {
+ if (fail_compile) {
+ mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);
+ mono_error_set_from_loader_error (&cfg->error);
+ } else {
mono_loader_clear_error ();
+ }
if (res)
mono_free_verify_list (res);
return TRUE;
if (info->info.status == MONO_VERIFY_NOT_VERIFIABLE && (!is_fulltrust || info->exception_type == MONO_EXCEPTION_METHOD_ACCESS || info->exception_type == MONO_EXCEPTION_FIELD_ACCESS)) {
if (fail_compile) {
char *method_name = mono_method_full_name (method, TRUE);
- cfg->exception_type = info->exception_type;
- cfg->exception_message = g_strdup_printf ("Error verifying %s: %s", method_name, info->info.message);
+ char *msg = g_strdup_printf ("Error verifying %s: %s", method_name, info->info.message);
+
+ if (info->exception_type == MONO_EXCEPTION_METHOD_ACCESS)
+ mono_error_set_generic_error (&cfg->error, "System", "MethodAccessException", "%s", msg);
+ else if (info->exception_type == info->exception_type == MONO_EXCEPTION_FIELD_ACCESS)
+ mono_error_set_generic_error (&cfg->error, "System", "FieldAccessException", "%s", msg);
+ else if (info->exception_type == MONO_EXCEPTION_UNVERIFIABLE_IL)
+ mono_error_set_generic_error (&cfg->error, "System.Security", "VerificationException", msg);
+ if (!mono_error_ok (&cfg->error)) {
+ mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);
+ g_free (msg);
+ } else {
+ cfg->exception_type = info->exception_type;
+ cfg->exception_message = msg;
+ }
g_free (method_name);
}
mono_free_verify_list (res);
#endif
if (cfg->verbose_level > 0) {
- char* nm = mono_method_full_name (cfg->method, TRUE);
+ char* nm = mono_method_get_full_name (cfg->method);
char *opt_descr = mono_opt_descr (cfg->opt);
g_print ("Method %s emitted at %p to %p (code length %d) [%s] with opts %s\n",
nm,
}
}
+static void mono_bb_ordering (MonoCompile *cfg)
+{
+ int dfn = 0;
+ /* Depth-first ordering on basic blocks */
+ cfg->bblocks = (MonoBasicBlock **)mono_mempool_alloc (cfg->mempool, sizeof (MonoBasicBlock*) * (cfg->num_bblocks + 1));
+
+ cfg->max_block_num = cfg->num_bblocks;
+
+ df_visit (cfg->bb_entry, &dfn, cfg->bblocks);
+ if (cfg->num_bblocks != dfn + 1) {
+ MonoBasicBlock *bb;
+
+ cfg->num_bblocks = dfn + 1;
+
+ /* remove unreachable code, because the code in them may be
+ * inconsistent (access to dead variables for example) */
+ for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
+ bb->flags &= ~BB_VISITED;
+ compute_reachable (cfg->bb_entry);
+ for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
+ if (bb->flags & BB_EXCEPTION_HANDLER)
+ compute_reachable (bb);
+ for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
+ if (!(bb->flags & BB_VISITED)) {
+ if (cfg->verbose_level > 1)
+ g_print ("found unreachable code in BB%d\n", bb->block_num);
+ bb->code = bb->last_ins = NULL;
+ while (bb->out_count)
+ mono_unlink_bblock (cfg, bb, bb->out_bb [0]);
+ }
+ }
+ for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
+ bb->flags &= ~BB_VISITED;
+ }
+}
+
static void
mono_handle_out_of_line_bblock (MonoCompile *cfg)
{
MonoMethodSignature *sig;
MonoError err;
MonoCompile *cfg;
- int dfn, i, code_size_ratio;
+ int i, code_size_ratio;
gboolean try_generic_shared, try_llvm = FALSE;
MonoMethod *method_to_compile, *method_to_register;
gboolean method_is_gshared = FALSE;
header = cfg->header;
if (!header) {
- MonoLoaderError *error;
-
- if ((error = mono_loader_get_last_error ())) {
- cfg->exception_type = error->exception_type;
+ if (mono_loader_get_last_error ()) {
+ mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);
+ mono_error_set_from_loader_error (&cfg->error);
} else {
- cfg->exception_type = MONO_EXCEPTION_INVALID_PROGRAM;
- cfg->exception_message = g_strdup_printf ("Missing or incorrect header for method %s", cfg->method->name);
+ mono_cfg_set_exception_invalid_program (cfg, g_strdup_printf ("Missing or incorrect header for method %s", cfg->method->name));
}
if (MONO_METHOD_COMPILE_END_ENABLED ())
MONO_PROBE_METHOD_COMPILE_END (method, FALSE);
if (cfg->verbose_level > 0) {
char *method_name;
- method_name = mono_method_full_name (method, TRUE);
+ method_name = mono_method_get_full_name (method);
g_print ("converting %s%s%smethod %s\n", COMPILE_LLVM (cfg) ? "llvm " : "", cfg->gsharedvt ? "gsharedvt " : "", (cfg->gshared && !cfg->gsharedvt) ? "gshared " : "", method_name);
/*
if (COMPILE_LLVM (cfg))
/* Should be done before branch opts */
if (cfg->opt & (MONO_OPT_CONSPROP | MONO_OPT_COPYPROP))
mono_local_cprop (cfg);
-
+ /*
+ * Should be done after cprop which can do strength reduction on
+ * some of these ops, after propagating immediates.
+ */
+ if (cfg->has_emulated_ops)
+ mono_local_emulate_ops (cfg);
if (cfg->opt & MONO_OPT_BRANCH)
mono_optimize_branches (cfg);
mono_threads_safepoint ();
- /* Depth-first ordering on basic blocks */
- cfg->bblocks = (MonoBasicBlock **)mono_mempool_alloc (cfg->mempool, sizeof (MonoBasicBlock*) * (cfg->num_bblocks + 1));
-
- cfg->max_block_num = cfg->num_bblocks;
-
- dfn = 0;
- df_visit (cfg->bb_entry, &dfn, cfg->bblocks);
- if (cfg->num_bblocks != dfn + 1) {
- MonoBasicBlock *bb;
-
- cfg->num_bblocks = dfn + 1;
-
- /* remove unreachable code, because the code in them may be
- * inconsistent (access to dead variables for example) */
- for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
- bb->flags &= ~BB_VISITED;
- compute_reachable (cfg->bb_entry);
- for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
- if (bb->flags & BB_EXCEPTION_HANDLER)
- compute_reachable (bb);
- for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
- if (!(bb->flags & BB_VISITED)) {
- if (cfg->verbose_level > 1)
- g_print ("found unreachable code in BB%d\n", bb->block_num);
- bb->code = bb->last_ins = NULL;
- while (bb->out_count)
- mono_unlink_bblock (cfg, bb, bb->out_bb [0]);
- }
- }
- for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
- bb->flags &= ~BB_VISITED;
- }
+ mono_bb_ordering (cfg);
if (((cfg->num_varinfo > 2000) || (cfg->num_bblocks > 1000)) && !cfg->compile_aot) {
/*
cfg->exception_type = type;
}
+/* Assumes ownership of the MSG argument */
+void
+mono_cfg_set_exception_invalid_program (MonoCompile *cfg, char *msg)
+{
+ mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);
+ mono_error_set_generic_error (&cfg->error, "System", "InvalidProgramException", msg);
+}
+
#endif /* DISABLE_JIT */
static MonoJitInfo*
return jinfo;
}
+GTimer *mono_time_track_start ()
+{
+ return g_timer_new ();
+}
+
+void mono_time_track_end (double *time, GTimer *timer)
+{
+ g_timer_stop (timer);
+ *time += g_timer_elapsed (timer, NULL);
+ g_timer_destroy (timer);
+}
+
+void mono_update_jit_stats (MonoCompile *cfg)
+{
+ mono_jit_stats.allocate_var += cfg->stat_allocate_var;
+ mono_jit_stats.locals_stack_size += cfg->stat_locals_stack_size;
+ mono_jit_stats.basic_blocks += cfg->stat_basic_blocks;
+ mono_jit_stats.max_basic_blocks = MAX (cfg->stat_basic_blocks, mono_jit_stats.max_basic_blocks);
+ mono_jit_stats.cil_code_size += cfg->stat_cil_code_size;
+ mono_jit_stats.regvars += cfg->stat_n_regvars;
+ mono_jit_stats.inlineable_methods += cfg->stat_inlineable_methods;
+ mono_jit_stats.inlined_methods += cfg->stat_inlined_methods;
+ mono_jit_stats.code_reallocs += cfg->stat_code_reallocs;
+}
+
/*
* mono_jit_compile_method_inner:
*
* Main entry point for the JIT.
*/
gpointer
-mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, int opt, MonoException **jit_ex)
+mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, int opt, MonoError *error)
{
MonoCompile *cfg;
gpointer code = NULL;
GTimer *jit_timer;
MonoMethod *prof_method, *shared;
+ mono_error_init (error);
+
if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
MonoMethod *nm;
full_name = mono_method_full_name (method, TRUE);
msg = g_strdup_printf ("Unrecognizable runtime implemented method '%s'", full_name);
- *jit_ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", msg);
+ ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", msg);
+ mono_error_set_exception_instance (error, ex);
g_free (full_name);
g_free (msg);
return NULL;
char *fullname = mono_method_full_name (method, TRUE);
char *msg = g_strdup_printf ("Attempting to JIT compile method '%s' while running with --aot-only. See http://docs.xamarin.com/ios/about/limitations for more information.\n", fullname);
- *jit_ex = mono_get_exception_execution_engine (msg);
+ ex = mono_get_exception_execution_engine (msg);
+ mono_error_set_exception_instance (error, ex);
g_free (fullname);
g_free (msg);
return NULL;
}
- jit_timer = g_timer_new ();
-
+ jit_timer = mono_time_track_start ();
cfg = mini_method_compile (method, opt, target_domain, JIT_FLAG_RUN_CCTORS, 0, -1);
- prof_method = cfg->method;
+ mono_time_track_end (&mono_jit_stats.jit_time, jit_timer);
- g_timer_stop (jit_timer);
- mono_jit_stats.jit_time += g_timer_elapsed (jit_timer, NULL);
- g_timer_destroy (jit_timer);
+ prof_method = cfg->method;
switch (cfg->exception_type) {
case MONO_EXCEPTION_NONE:
case MONO_EXCEPTION_FILE_NOT_FOUND:
case MONO_EXCEPTION_BAD_IMAGE: {
/* Throw a type load exception if needed */
- MonoLoaderError *error = mono_loader_get_last_error ();
-
- if (error) {
- ex = mono_loader_error_prepare_exception (error);
+ if (cfg->exception_ptr) {
+ ex = mono_class_get_exception_for_failure ((MonoClass *)cfg->exception_ptr);
} else {
- if (cfg->exception_ptr) {
- ex = mono_class_get_exception_for_failure ((MonoClass *)cfg->exception_ptr);
- } else {
- if (cfg->exception_type == MONO_EXCEPTION_MISSING_FIELD)
- ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingFieldException", cfg->exception_message);
- else if (cfg->exception_type == MONO_EXCEPTION_MISSING_METHOD)
- ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingMethodException", cfg->exception_message);
- else if (cfg->exception_type == MONO_EXCEPTION_TYPE_LOAD)
- ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "TypeLoadException", cfg->exception_message);
- else if (cfg->exception_type == MONO_EXCEPTION_FILE_NOT_FOUND)
- ex = mono_exception_from_name_msg (mono_defaults.corlib, "System.IO", "FileNotFoundException", cfg->exception_message);
- else if (cfg->exception_type == MONO_EXCEPTION_BAD_IMAGE)
- ex = mono_get_exception_bad_image_format (cfg->exception_message);
- else
- g_assert_not_reached ();
- }
+ if (cfg->exception_type == MONO_EXCEPTION_MISSING_FIELD)
+ ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingFieldException", cfg->exception_message);
+ else if (cfg->exception_type == MONO_EXCEPTION_MISSING_METHOD)
+ ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingMethodException", cfg->exception_message);
+ else if (cfg->exception_type == MONO_EXCEPTION_TYPE_LOAD)
+ ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "TypeLoadException", cfg->exception_message);
+ else if (cfg->exception_type == MONO_EXCEPTION_FILE_NOT_FOUND)
+ ex = mono_exception_from_name_msg (mono_defaults.corlib, "System.IO", "FileNotFoundException", cfg->exception_message);
+ else if (cfg->exception_type == MONO_EXCEPTION_BAD_IMAGE)
+ ex = mono_get_exception_bad_image_format (cfg->exception_message);
+ else
+ g_assert_not_reached ();
}
break;
}
- case MONO_EXCEPTION_INVALID_PROGRAM:
- ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", cfg->exception_message);
- break;
- case MONO_EXCEPTION_UNVERIFIABLE_IL:
- ex = mono_exception_from_name_msg (mono_defaults.corlib, "System.Security", "VerificationException", cfg->exception_message);
- break;
- case MONO_EXCEPTION_METHOD_ACCESS:
- ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MethodAccessException", cfg->exception_message);
- break;
- case MONO_EXCEPTION_FIELD_ACCESS:
- ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "FieldAccessException", cfg->exception_message);
- break;
- case MONO_EXCEPTION_OBJECT_SUPPLIED: {
- MonoException *exp = (MonoException *)cfg->exception_ptr;
- MONO_GC_UNREGISTER_ROOT (cfg->exception_ptr);
-
- ex = exp;
- break;
- }
- case MONO_EXCEPTION_OUT_OF_MEMORY:
- ex = mono_domain_get ()->out_of_memory_ex;
- break;
case MONO_EXCEPTION_MONO_ERROR:
+ // FIXME: MonoError has no copy ctor
g_assert (!mono_error_ok (&cfg->error));
ex = mono_error_convert_to_exception (&cfg->error);
break;
mono_profiler_method_end_jit (method, NULL, MONO_PROFILE_FAILED);
mono_destroy_compile (cfg);
- *jit_ex = ex;
+ mono_error_set_exception_instance (error, ex);
return NULL;
}
* Update global stats while holding a lock, instead of doing many
* InterlockedIncrement operations during JITting.
*/
- mono_jit_stats.allocate_var += cfg->stat_allocate_var;
- mono_jit_stats.locals_stack_size += cfg->stat_locals_stack_size;
- mono_jit_stats.basic_blocks += cfg->stat_basic_blocks;
- mono_jit_stats.max_basic_blocks = MAX (cfg->stat_basic_blocks, mono_jit_stats.max_basic_blocks);
- mono_jit_stats.cil_code_size += cfg->stat_cil_code_size;
- mono_jit_stats.regvars += cfg->stat_n_regvars;
- mono_jit_stats.inlineable_methods += cfg->stat_inlineable_methods;
- mono_jit_stats.inlined_methods += cfg->stat_inlined_methods;
- mono_jit_stats.code_reallocs += cfg->stat_code_reallocs;
+ mono_update_jit_stats (cfg);
mono_destroy_compile (cfg);
if (!vtable) {
ex = mono_class_get_exception_for_failure (method->klass);
g_assert (ex);
- *jit_ex = ex;
+ mono_error_set_exception_instance (error, ex);
return NULL;
}
ex = mono_runtime_class_init_full (vtable, FALSE);
if (ex) {
- *jit_ex = ex;
+ mono_error_set_exception_instance (error, ex);
return NULL;
}
return code;