#include <mono/metadata/profiler-private.h>
#include <mono/metadata/mono-config.h>
#include <mono/metadata/environment.h>
+#include <mono/metadata/mono-debug.h>
+#include <mono/metadata/mono-debug-debugger.h>
#include "mini.h"
#include <string.h>
#include <ctype.h>
#include "inssel.h"
-#include "debug.h"
#include "jit-icalls.c"
#define MONO_CHECK_THIS(ins) (cfg->method->signature->hasthis && (ins)->ssa_op == MONO_SSA_LOAD && (ins)->inst_left->inst_c0 == 0)
+gboolean mono_arch_handle_exception (struct sigcontext *ctx, gpointer obj, gboolean test_only);
static gpointer mono_jit_compile_method (MonoMethod *method);
static void handle_stobj (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *dest, MonoInst *src,
const unsigned char *ip, MonoClass *klass, gboolean to_end, gboolean native);
+static int mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_bblock, MonoBasicBlock *end_bblock,
+ int locals_offset, MonoInst *return_var, GList *dont_inline, MonoInst **inline_args,
+ guint inline_offset, gboolean is_virtual_call);
+
extern guint8 mono_burg_arity [];
/* helper methods signature */
static MonoMethodSignature *helper_sig_long_long_long = NULL;
static MonoMethodSignature *helper_sig_long_double = NULL;
static MonoMethodSignature *helper_sig_uint_double = NULL;
static MonoMethodSignature *helper_sig_int_double = NULL;
+static MonoMethodSignature *helper_sig_stelem_ref = NULL;
static guint32 default_opt = MONO_OPT_PEEPHOLE;
}
#endif
-#if 0
/* debug function */
static void
print_method_from_ip (void *ip)
g_free (method);
}
-#endif
#define MONO_INIT_VARINFO(vi,id) do { \
(vi)->range.first_use.pos.bid = 0xffff; \
} while (0)
#define NEW_DOMAINCONST(cfg,dest) do { \
- if ((cfg->opt & MONO_OPT_SAHRED) || mono_compile_aot) { \
+ if ((cfg->opt & MONO_OPT_SHARED) || mono_compile_aot) { \
NEW_TEMPLOAD (cfg, dest, mono_get_domainvar (cfg)->inst_c0); \
} else { \
NEW_PCONST (cfg, dest, (cfg)->domain); \
(dest)->klass = (k); \
} while (0)
+#define NEW_GROUP(cfg,dest,el1,el2) do { \
+ (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
+ (dest)->opcode = OP_GROUP; \
+ (dest)->inst_left = (el1); \
+ (dest)->inst_right = (el2); \
+ } while (0)
+
static GHashTable *coverage_hash = NULL;
MonoCoverageInfo *
return -1;
}
-static MonoBasicBlock *
+static GList*
mono_find_final_block (MonoCompile *cfg, unsigned char *ip, unsigned char *target, int type)
{
MonoMethod *method = cfg->method;
MonoExceptionClause *clause;
MonoBasicBlock *handler;
int i;
+ GList *res = NULL;
for (i = 0; i < header->num_clauses; ++i) {
clause = &header->clauses [i];
if (MONO_OFFSET_IN_CLAUSE (clause, (ip - header->code)) &&
(!MONO_OFFSET_IN_CLAUSE (clause, (target - header->code)))) {
- if (clause->flags & type) {
+ if (clause->flags == type) {
handler = g_hash_table_lookup (cfg->bb_hash, header->code + clause->handler_offset);
g_assert (handler);
- return handler;
+ res = g_list_append (res, handler);
}
}
}
- return NULL;
+ return res;
}
{0},
{0, 1, 0, 1, 0, 0, 4, 0},
{0, 0, 1, 0, 0, 0, 0, 0},
- {0, 1, 0, 1, 0, 2, 0, 0},
+ {0, 1, 0, 1, 0, 2, 4, 0},
{0, 0, 0, 0, 1, 0, 0, 0},
{0, 0, 0, 2, 0, 1, 0, 0},
- {0, 4, 0, 0, 0, 0, 3, 0},
+ {0, 4, 0, 4, 0, 0, 3, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
};
return cfg->domainvar;
}
-static void
-realloc_var_info (MonoCompile *cfg, int count)
-{
- gpointer data;
- int num = cfg->varinfo_count;
-
- g_assert (count > num);
-
- cfg->varinfo_count = count;
-
- data = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst*) * cfg->varinfo_count);
- if (num)
- memcpy (data, cfg->varinfo, sizeof (MonoInst*) * num);
- cfg->varinfo = (MonoInst **)data;
-
- data = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoMethodVar*) * cfg->varinfo_count);
- if (num)
- memcpy (data, cfg->vars, sizeof (MonoMethodVar*) * num);
- cfg->vars = (MonoMethodVar **)data;
-}
-
MonoInst*
mono_compile_create_var (MonoCompile *cfg, MonoType *type, int opcode)
{
MonoInst *inst;
int num = cfg->num_varinfo;
- if ((num + 1) >= cfg->varinfo_count)
- realloc_var_info (cfg, cfg->varinfo_count + 16);
+ if ((num + 1) >= cfg->varinfo_count) {
+ cfg->varinfo_count = (cfg->varinfo_count + 2) * 2;
+ cfg->varinfo = (MonoInst **)g_realloc (cfg->varinfo, sizeof (MonoInst*) * cfg->varinfo_count);
+ cfg->vars = (MonoMethodVar **)g_realloc (cfg->vars, sizeof (MonoMethodVar*) * cfg->varinfo_count);
+ }
mono_jit_stats.allocate_var++;
if ((method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
(method->iflags & METHOD_IMPL_ATTRIBUTE_NOINLINING) ||
+ (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) ||
(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
(method->klass->marshalbyref) ||
!header || header->num_clauses ||
return FALSE;
}
+static MonoInst*
+mini_get_opcode_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
+{
+ int pc, op;
+ MonoInst *ins;
+
+ if (cmethod->klass == mono_defaults.string_class) {
+ if (cmethod->name [0] != 'g' || strcmp (cmethod->name, "get_Chars"))
+ return NULL;
+ op = OP_GETCHR;
+ } else if (cmethod->klass == mono_defaults.math_class) {
+ if (strcmp (cmethod->name, "Sin") == 0)
+ op = OP_SIN;
+ else if (strcmp (cmethod->name, "Cos") == 0)
+ op = OP_COS;
+ else if (strcmp (cmethod->name, "Tan") == 0)
+ op = OP_TAN;
+ else if (strcmp (cmethod->name, "Atan") == 0)
+ op = OP_ATAN;
+ else if (strcmp (cmethod->name, "Sqrt") == 0)
+ op = OP_SQRT;
+ else if (strcmp (cmethod->name, "Abs") == 0 && fsig->params [0]->type == MONO_TYPE_R8)
+ op = OP_ABS;
+ else
+ return NULL;
+ } else {
+ return NULL;
+ }
+ pc = fsig->param_count + fsig->hasthis;
+ MONO_INST_NEW (cfg, ins, op);
+
+ if (pc > 0) {
+ ins->inst_i0 = args [0];
+ if (pc > 1)
+ ins->inst_i1 = args [1];
+ }
+
+ return ins;
+}
+
static void
mono_save_args (MonoCompile *cfg, MonoBasicBlock *bblock, MonoMethodSignature *sig, MonoInst **sp, MonoInst **args)
{
if (sp [0]->opcode == OP_ICONST) {
*args++ = sp [0];
} else {
- temp = mono_compile_create_var (cfg, type_from_stack_type (*sp), OP_LOCAL);
+ temp = mono_compile_create_var (cfg, sig->params [i], OP_LOCAL);
*args++ = temp;
NEW_TEMPSTORE (cfg, store, temp->inst_c0, *sp);
store->cil_code = sp [0]->cil_code;
}
}
+static int
+inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoBasicBlock *bblock, MonoInst **sp,
+ guchar *ip, guint real_offset, GList *dont_inline, MonoBasicBlock **last_b)
+{
+ MonoInst *ins, *rvar = NULL;
+ MonoMethodHeader *cheader;
+ MonoBasicBlock *ebblock, *sbblock;
+ int i, costs, new_locals_offset;
+
+ if (cfg->verbose_level > 2)
+ g_print ("INLINE START %p %s\n", cmethod, mono_method_full_name (cmethod, TRUE));
+
+ cheader = ((MonoMethodNormal *)cmethod)->header;
+
+ if (!cmethod->inline_info) {
+ mono_jit_stats.inlineable_methods++;
+ cmethod->inline_info = 1;
+ }
+ /* allocate space to store the return value */
+ if (!MONO_TYPE_IS_VOID (fsig->ret))
+ rvar = mono_compile_create_var (cfg, fsig->ret, OP_LOCAL);
+
+ /* allocate local variables */
+ new_locals_offset = cfg->num_varinfo;
+ for (i = 0; i < cheader->num_locals; ++i)
+ mono_compile_create_var (cfg, cheader->locals [i], OP_LOCAL);
+
+ /* allocate starte and end blocks */
+ sbblock = NEW_BBLOCK (cfg);
+ sbblock->block_num = cfg->num_bblocks++;
+ sbblock->real_offset = real_offset;
+
+ ebblock = NEW_BBLOCK (cfg);
+ ebblock->block_num = cfg->num_bblocks++;
+ ebblock->real_offset = real_offset;
+
+ costs = mono_method_to_ir (cfg, cmethod, sbblock, ebblock, new_locals_offset, rvar, dont_inline, sp, real_offset, *ip == CEE_CALLVIRT);
+
+ if (costs >= 0 && costs < 60) {
+ if (cfg->verbose_level > 2)
+ g_print ("INLINE END %s\n", mono_method_full_name (cmethod, TRUE));
+
+ mono_jit_stats.inlined_methods++;
+
+ /* always add some code to avoid block split failures */
+ MONO_INST_NEW (cfg, ins, CEE_NOP);
+ MONO_ADD_INS (bblock, ins);
+ ins->cil_code = ip;
+
+ bblock->next_bb = sbblock;
+ link_bblock (cfg, bblock, sbblock);
+
+ if (rvar) {
+ NEW_TEMPLOAD (cfg, ins, rvar->inst_c0);
+ *sp++ = ins;
+ }
+ *last_b = ebblock;
+ return costs + 1;
+ } else {
+ if (cfg->verbose_level > 2)
+ g_print ("INLINE ABORTED %s\n", mono_method_full_name (cmethod, TRUE));
+ }
+ return 0;
+}
+
/*
* Some of these comments may well be out-of-date.
* Design decisions: we do a single pass over the IL code (and we do bblock
static int
mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_bblock, MonoBasicBlock *end_bblock,
int locals_offset, MonoInst *return_var, GList *dont_inline, MonoInst **inline_args,
- guint inline_offset)
+ guint inline_offset, gboolean is_virtual_call)
{
MonoInst *zero_int32, *zero_int64, *zero_ptr, *zero_obj, *zero_r8;
MonoInst *ins, **sp, **stack_start;
int i, n, start_new_bblock, align;
int num_calls = 0, inline_costs = 0;
int *filter_lengths = NULL;
+ int breakpoint_id = 0;
guint real_offset;
image = method->klass->image;
bbhash = g_hash_table_new (g_direct_hash, NULL);
}
+ dont_inline = g_list_prepend (dont_inline, method);
if (cfg->method == method) {
/* ENTRY BLOCK */
arg_array [i] = cfg->varinfo [i];
if (mono_compile_aot)
- cfg->opt |= MONO_OPT_SAHRED;
+ cfg->opt |= MONO_OPT_SHARED;
if (header->num_clauses) {
int size = sizeof (int) * header->num_clauses;
ADD_BBLOCK (cfg, bbhash, bblock);
if (cfg->method == method) {
- if (mono_method_has_breakpoint (method, FALSE)) {
+ breakpoint_id = mono_debugger_method_has_breakpoint (method);
+ if (breakpoint_id && (mono_debug_format != MONO_DEBUG_FORMAT_DEBUGGER)) {
MONO_INST_NEW (cfg, ins, CEE_BREAK);
MONO_ADD_INS (bblock, ins);
}
}
- if ((header->init_locals || (cfg->method == method && (cfg->opt & MONO_OPT_SAHRED)))) {
+ if ((header->init_locals || (cfg->method == method && (cfg->opt & MONO_OPT_SHARED)))) {
/* we use a separate basic block for the initialization code */
cfg->bb_init = init_localsbb = NEW_BBLOCK (cfg);
init_localsbb->real_offset = real_offset;
link_bblock (cfg, start_bblock, bblock);
}
- mono_debug_init_method (cfg, bblock);
+ mono_debug_init_method (cfg, bblock, breakpoint_id);
param_types = mono_mempool_alloc (cfg->mempool, sizeof (MonoType*) * (sig->hasthis + sig->param_count));
if (sig->hasthis)
zero_r8->inst_p0 = &r8_0;
/* add a check for this != NULL to inlined methods */
- if (cfg->method != method && sig->hasthis) {
+ if (is_virtual_call) {
MONO_INST_NEW (cfg, ins, OP_CHECK_THIS);
NEW_ARGLOAD (cfg, ins->inst_left, 0);
ins->cil_code = ip;
case CEE_CALLVIRT: {
MonoInst *addr = NULL;
MonoMethodSignature *fsig = NULL;
- MonoMethodHeader *cheader;
- int mop, temp, array_rank = 0;
+ int temp, array_rank = 0;
int virtual = *ip == CEE_CALLVIRT;
token = read32 (ip + 1);
if (*ip == CEE_CALLI) {
cmethod = NULL;
- cheader = NULL;
CHECK_STACK (1);
--sp;
addr = *sp;
} else {
cmethod = mono_get_method (image, token, NULL);
- cheader = ((MonoMethodNormal *)cmethod)->header;
if (!cmethod->klass->inited)
mono_class_init (cmethod->klass);
sp -= n;
- if (cmethod && (mop = mono_find_method_opcode (cmethod))) {
-
- MONO_INST_NEW (cfg, ins, mop);
+ if (cmethod && (cfg->opt & MONO_OPT_INTRINS) && (ins = mini_get_opcode_for_method (cfg, cmethod, fsig, sp))) {
ins->cil_code = ip;
- g_assert (n <= 2);
-
- if (fsig->param_count > 0) {
- ins->inst_i0 = sp [0];
- if (fsig->param_count > 1)
- ins->inst_i1 = sp [1];
- }
if (MONO_TYPE_IS_VOID (fsig->ret)) {
MONO_ADD_INS (bblock, ins);
break;
}
- if ((cfg->opt & MONO_OPT_INLINE) &&
+ if ((cfg->opt & MONO_OPT_INLINE) && cmethod &&
(!virtual || !(cmethod->flags & METHOD_ATTRIBUTE_VIRTUAL) || (cmethod->flags & METHOD_ATTRIBUTE_FINAL)) &&
- cmethod && cheader && mono_method_check_inlining (cmethod) &&
- method != cmethod && !g_list_find (dont_inline, cmethod)) {
- MonoInst *rvar = NULL;
- MonoBasicBlock *ebblock, *sbblock;
- int costs, new_locals_offset;
-
- if (cfg->verbose_level > 2)
- g_print ("INLINE START %p %s\n", cmethod, mono_method_full_name (cmethod, TRUE));
-
- if (!cmethod->inline_info) {
- mono_jit_stats.inlineable_methods++;
- cmethod->inline_info = 1;
- }
- /* allocate space to store the return value */
- if (!MONO_TYPE_IS_VOID (fsig->ret))
- rvar = mono_compile_create_var (cfg, fsig->ret, OP_LOCAL);
-
- /* allocate local variables */
- new_locals_offset = cfg->num_varinfo;
- for (i = 0; i < cheader->num_locals; ++i)
- mono_compile_create_var (cfg, cheader->locals [i], OP_LOCAL);
+ mono_method_check_inlining (cmethod) &&
+ !g_list_find (dont_inline, cmethod)) {
+ int costs;
+ MonoBasicBlock *ebblock;
- /* allocate starte and end blocks */
- sbblock = NEW_BBLOCK (cfg);
- sbblock->block_num = cfg->num_bblocks++;
- sbblock->real_offset = real_offset;
-
- ebblock = NEW_BBLOCK (cfg);
- ebblock->block_num = cfg->num_bblocks++;
- ebblock->real_offset = real_offset;
-
- dont_inline = g_list_prepend (dont_inline, method);
- costs = mono_method_to_ir (cfg, cmethod, sbblock, ebblock, new_locals_offset, rvar, dont_inline, sp, real_offset);
- dont_inline = g_list_remove (dont_inline, method);
-
- if (costs >= 0 && costs < 60) {
-
- mono_jit_stats.inlined_methods++;
-
- /* always add some code to avoid block split failures */
- MONO_INST_NEW (cfg, ins, CEE_NOP);
- MONO_ADD_INS (bblock, ins);
- ins->cil_code = ip;
-
+ if ((costs = inline_method (cfg, cmethod, fsig, bblock, sp, ip, real_offset, dont_inline, &ebblock))) {
ip += 5;
real_offset += 5;
- bblock->next_bb = sbblock;
- link_bblock (cfg, bblock, sbblock);
-
GET_BBLOCK (cfg, bbhash, bblock, ip);
ebblock->next_bb = bblock;
link_bblock (cfg, ebblock, bblock);
+ if (!MONO_TYPE_IS_VOID (fsig->ret))
+ sp++;
- if (rvar) {
- NEW_TEMPLOAD (cfg, ins, rvar->inst_c0);
- *sp++ = ins;
+ if (sp != stack_start) {
+ handle_stack_args (cfg, ebblock, stack_start, sp - stack_start);
+ sp = stack_start;
}
- if (cfg->verbose_level > 2)
- g_print ("INLINE END %s\n", mono_method_full_name (cmethod, TRUE));
-
- // { static int c = 0; printf ("ICOUNT %d %d %s\n", c++, costs, mono_method_full_name (cmethod, TRUE)); }
+ start_new_bblock = 1;
inline_costs += costs;
break;
- } else {
-
- if (cfg->verbose_level > 2)
- g_print ("INLINE ABORTED %s\n", mono_method_full_name (cmethod, TRUE));
-
}
}
klass = mono_method_get_wrapper_data (method, token);
else
klass = mono_class_get (image, token);
+
mono_class_init (klass);
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);
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;
cfg->ldstr_list = g_list_prepend (cfg->ldstr_list, (gpointer)n);
}
- if ((cfg->opt & MONO_OPT_SAHRED) || mono_compile_aot) {
+ if ((cfg->opt & MONO_OPT_SHARED) || mono_compile_aot) {
int temp;
MonoInst *iargs [3];
NEW_TEMPLOAD (cfg, iargs [0], mono_get_domainvar (cfg)->inst_c0);
NEW_TEMPLOAD (cfg, *sp, temp);
}
- /* now call the actual ctor */
- mono_emit_method_call_spilled (cfg, bblock, cmethod, sp, ip, NULL);
+ /* FIXME: currently disabled because of bug #42175 */
+ if (0 && (cfg->opt & MONO_OPT_INLINE) && cmethod &&
+ mono_method_check_inlining (cmethod) &&
+ !mono_class_is_subclass_of (cmethod->klass, mono_defaults.exception_class, FALSE) &&
+ !g_list_find (dont_inline, cmethod)) {
+ int costs;
+ MonoBasicBlock *ebblock;
+ if ((costs = inline_method (cfg, cmethod, cmethod->signature, bblock, sp, ip, real_offset, dont_inline, &ebblock))) {
+
+ GET_BBLOCK (cfg, bbhash, bblock, ip + 5);
+ ebblock->next_bb = bblock;
+ link_bblock (cfg, ebblock, bblock);
+
+ /*if (sp != stack_start) {
+ handle_stack_args (cfg, ebblock, stack_start, sp - stack_start);
+ sp = stack_start;
+ }
+ start_new_bblock = 1;*/
+
+ inline_costs += costs;
+ /*g_print ("inlined newobj for %s\n", cmethod->klass->name);*/
+ }
+ } else {
+ /* now call the actual ctor */
+ mono_emit_method_call_spilled (cfg, bblock, cmethod, sp, ip, NULL);
+ }
}
NEW_TEMPLOAD (cfg, *sp, temp);
break;
case CEE_UNBOX: {
MonoInst *add, *vtoffset;
- /* FIXME: need to check class: move to inssel.brg? */
+
CHECK_STACK (1);
--sp;
token = read32 (ip + 1);
else
klass = mono_class_get (image, token);
mono_class_init (klass);
+
+
+ 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 = *sp;
+ add->inst_left = ins;
add->inst_right = vtoffset;
add->type = STACK_MP;
*sp++ = add;
ip += 5;
- inline_costs += 1;
+ inline_costs += 2;
break;
}
case CEE_CASTCLASS:
handle_loaded_temps (cfg, bblock, stack_start, sp);
- if (((cfg->opt & MONO_OPT_SAHRED) || mono_compile_aot)) {
+ if (((cfg->opt & MONO_OPT_SHARED) || mono_compile_aot)) {
int temp;
MonoInst *iargs [2];
g_assert (field->parent);
token = read32 (ip + 1);
/* allocate the domainvar - becaus this is used in decompose_foreach */
- if ((cfg->opt & MONO_OPT_SAHRED) || mono_compile_aot)
+ if ((cfg->opt & MONO_OPT_SHARED) || mono_compile_aot)
mono_get_domainvar (cfg);
if (method->wrapper_type != MONO_WRAPPER_NONE)
case CEE_STELEM_I4:
case CEE_STELEM_I8:
case CEE_STELEM_R4:
- case CEE_STELEM_R8:
- case CEE_STELEM_REF: {
+ case CEE_STELEM_R8: {
MonoInst *load;
/*
* translate to:
cfg->disable_ssa = TRUE;
break;
}
+ case CEE_STELEM_REF: {
+ MonoInst *iargs [3];
+
+ CHECK_STACK (3);
+ sp -= 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);
+
+ /*
+ MonoInst *group;
+ NEW_GROUP (cfg, group, sp [0], sp [1]);
+ MONO_INST_NEW (cfg, ins, CEE_STELEM_REF);
+ ins->cil_code = ip;
+ ins->inst_left = group;
+ ins->inst_right = sp [2];
+ MONO_ADD_INS (bblock, ins);
+ */
+
+ ++ip;
+ inline_costs += 1;
+ cfg->disable_ssa = TRUE;
+ break;
+ }
case CEE_CKFINITE: {
MonoInst *store, *temp;
CHECK_STACK (1);
handle = mono_ldtoken (image, n, &handle_class);
mono_class_init (handle_class);
- if (((cfg->opt & MONO_OPT_SAHRED) || mono_compile_aot)) {
+ if (((cfg->opt & MONO_OPT_SHARED) || mono_compile_aot)) {
int temp;
MonoInst *res, *store, *addr, *vtvar, *iargs [2];
start_new_bblock = 1;
break;
case CEE_LEAVE:
- case CEE_LEAVE_S:
+ case CEE_LEAVE_S: {
+ GList *handlers;
if (*ip == CEE_LEAVE) {
target = ip + 5 + (gint32)read32(ip + 1);
} else {
/* fixme: call fault handler ? */
- if ((tblock = mono_find_final_block (cfg, ip, target, MONO_EXCEPTION_CLAUSE_FINALLY))) {
- link_bblock (cfg, bblock, tblock);
- MONO_INST_NEW (cfg, ins, OP_HANDLER);
- ins->cil_code = ip;
- ins->inst_target_bb = tblock;
- MONO_ADD_INS (bblock, ins);
+ if ((handlers = mono_find_final_block (cfg, ip, target, MONO_EXCEPTION_CLAUSE_FINALLY))) {
+ GList *tmp;
+ for (tmp = handlers; tmp; tmp = tmp->next) {
+ tblock = tmp->data;
+ link_bblock (cfg, bblock, tblock);
+ MONO_INST_NEW (cfg, ins, OP_HANDLER);
+ ins->cil_code = ip;
+ ins->inst_target_bb = tblock;
+ MONO_ADD_INS (bblock, ins);
+ }
+ g_list_free (handlers);
}
-
MONO_INST_NEW (cfg, ins, CEE_BR);
ins->cil_code = ip;
MONO_ADD_INS (bblock, ins);
else
ip += 2;
-
break;
+ }
case CEE_STIND_I:
CHECK_STACK (2);
MONO_INST_NEW (cfg, ins, *ip);
n = read32 (ip + 2);
if (method->wrapper_type != MONO_WRAPPER_NONE)
cmethod = mono_method_get_wrapper_data (method, n);
- else
+ else {
cmethod = mono_get_method (image, n, NULL);
-
+
+ /*
+ * We can't do this in mono_ldftn, since it is used in
+ * the synchronized wrapper, leading to an infinite loop.
+ */
+ if (cmethod->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
+ cmethod = mono_marshal_get_synchronized_wrapper (cmethod);
+ }
+
mono_class_init (cmethod->klass);
handle_loaded_temps (cfg, bblock, stack_start, sp);
g_hash_table_destroy (bbhash);
}
+ dont_inline = g_list_remove (dont_inline, method);
return inline_costs;
inline_failure:
if (cfg->method != method)
g_hash_table_destroy (bbhash);
+ dont_inline = g_list_remove (dont_inline, method);
return -1;
unverified:
g_hash_table_destroy (bbhash);
g_error ("Invalid IL code at IL%04x in %s: %s\n", ip - header->code,
mono_method_full_name (method, TRUE), mono_disasm_code_one (NULL, method, ip, NULL));
+ dont_inline = g_list_remove (dont_inline, method);
return -1;
}
helper_sig_domain_get->ret = &mono_defaults.int_class->byval_arg;
helper_sig_domain_get->pinvoke = 1;
+ /* void* stelem_ref (MonoArray *, int index, MonoObject *) */
+ helper_sig_stelem_ref = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
+ helper_sig_stelem_ref->params [0] = &mono_defaults.array_class->byval_arg;
+ helper_sig_stelem_ref->params [1] = &mono_defaults.int32_class->byval_arg;
+ helper_sig_stelem_ref->params [2] = &mono_defaults.object_class->byval_arg;
+ helper_sig_stelem_ref->ret = &mono_defaults.void_class->byval_arg;
+ helper_sig_stelem_ref->pinvoke = 1;
+
/* long amethod (long, long) */
helper_sig_long_long_long = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
helper_sig_long_long_long->params [0] = helper_sig_long_long_long->params [1] =
helper_sig_memset->pinvoke = 1;
}
-static GHashTable *method_opcode_hash = NULL;
-
-static void
-mono_register_method_opcode (MonoMethod *method, int opcode)
-{
-
- if (!method_opcode_hash)
- method_opcode_hash = g_hash_table_new (NULL, NULL);
-
- g_hash_table_insert (method_opcode_hash, method, (gpointer)opcode);
-
-}
-
-int
-mono_find_method_opcode (MonoMethod *method)
-{
- g_assert (method_opcode_hash);
-
- return (int)g_hash_table_lookup (method_opcode_hash, method);
-}
-
static GHashTable *jit_icall_hash_name = NULL;
static GHashTable *jit_icall_hash_addr = NULL;
mono_mempool_destroy (cfg->mempool);
g_list_free (cfg->ldstr_list);
+ g_free (cfg->varinfo);
+ g_free (cfg->vars);
g_free (cfg);
}
/* we skip the entry block (exit is handled specially instead ) */
for (bb = cfg->bb_entry->next_bb; bb; bb = bb->next_bb) {
+ /* dont touch code inside exception clauses */
+ if (bb->region != -1)
+ continue;
+
if (bb->out_count == 1) {
bbn = bb->out_bb [0];
int dfn = 0, i, code_size_ratio;
mono_jit_stats.methods_compiled++;
+ if (mono_jit_profile)
+ mono_profiler_method_jit (method);
cfg = g_new0 (MonoCompile, 1);
cfg->method = method;
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)) < 0) {
+ if ((i = mono_method_to_ir (cfg, method, NULL, NULL, cfg->locals_start, NULL, NULL, NULL, 0, FALSE)) < 0) {
mono_destroy_compile (cfg);
+ if (mono_jit_profile)
+ mono_profiler_method_end_jit (method, MONO_PROFILE_FAILED);
return NULL;
}
decompose_pass (cfg);
- if (cfg->opt & MONO_OPT_LINEARS) {
+ /* FIXME: disabled with exception clauses: bug #42136 */
+ if ((!header->num_clauses) && (cfg->opt & MONO_OPT_LINEARS)) {
GList *vars, *regs;
/* fixme: maybe we can avoid to compute livenesss here if already computed ? */
tblock = g_hash_table_lookup (cfg->bb_hash, ip + ec->try_offset);
g_assert (tblock);
ei->try_start = cfg->native_code + tblock->native_offset;
+ g_assert (tblock->native_offset);
tblock = g_hash_table_lookup (cfg->bb_hash, ip + ec->try_offset + ec->try_len);
g_assert (tblock);
ei->try_end = cfg->native_code + tblock->native_offset;
+ g_assert (tblock->native_offset);
tblock = g_hash_table_lookup (cfg->bb_hash, ip + ec->handler_offset);
g_assert (tblock);
ei->handler_start = cfg->native_code + tblock->native_offset;
-
}
}
}
mono_jit_stats.native_code_size += cfg->code_len;
+ if (mono_jit_profile)
+ mono_profiler_method_end_jit (method, MONO_PROFILE_OK);
+
return cfg;
}
GHashTable *jit_code_hash;
gpointer code;
- if (default_opt & MONO_OPT_SAHRED)
+ if (default_opt & MONO_OPT_SHARED)
target_domain = mono_root_domain;
else
target_domain = domain;
return addr;
}
-static MonoMethod *
-mono_find_unique_method (MonoClass *klass, const char *name, int param_count)
-{
- MonoMethod *rval = NULL;
- int i;
-
- mono_class_init (klass);
-
- for (i = 0; i < klass->method.count; ++i) {
- if (!strcmp (name, klass->methods [i]->name) &&
- klass->methods [i]->signature->param_count == param_count) {
- g_assert (rval == NULL);
- rval = klass->methods [i];
- g_assert (!(rval->flags & METHOD_ATTRIBUTE_VIRTUAL));
- }
- }
-
- return rval;
-}
-
-
static CRITICAL_SECTION ms;
MonoDomain *
mini_init (const char *filename)
{
MonoDomain *domain;
- MonoMethod *m;
- MonoMethodDesc *desc;
metadata_section = &ms;
InitializeCriticalSection (metadata_section);
mono_register_jit_icall (mono_arch_get_throw_exception_by_name (), "mono_arch_throw_exception_by_name",
helper_sig_void_ptr, TRUE);
-
- g_assert ((m = mono_find_unique_method (mono_defaults.math_class, "Sin", 1)));
- mono_register_method_opcode (m, OP_SIN);
- g_assert ((m = mono_find_unique_method (mono_defaults.math_class, "Cos", 1)));
- mono_register_method_opcode (m, OP_COS);
- g_assert ((m = mono_find_unique_method (mono_defaults.math_class, "Tan", 1)));
- mono_register_method_opcode (m, OP_TAN);
- g_assert ((m = mono_find_unique_method (mono_defaults.math_class, "Atan", 1)));
- mono_register_method_opcode (m, OP_ATAN);
- g_assert ((m = mono_find_unique_method (mono_defaults.math_class, "Sqrt", 1)));
- mono_register_method_opcode (m, OP_SQRT);
-
- g_assert ((desc = mono_method_desc_new ("System.Math:Abs(double)", 0)));
- g_assert ((m = mono_method_desc_search_in_image (desc, mono_defaults.corlib)));
- mono_register_method_opcode (m, OP_ABS);
-
/*
* NOTE, NOTE, NOTE, NOTE:
* when adding emulation for some opcodes, remember to also add a dummy
mono_register_jit_icall (helper_memcpy, "helper_memcpy", helper_sig_memcpy, FALSE);
mono_register_jit_icall (helper_memset, "helper_memset", helper_sig_memset, FALSE);
mono_register_jit_icall (helper_initobj, "helper_initobj", helper_sig_initobj, FALSE);
+ 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_array_new, "mono_array_new", helper_sig_newarr, FALSE);
mono_register_jit_icall (mono_string_to_utf16, "mono_string_to_utf16", helper_sig_ptr_obj, FALSE);
mini_cleanup (MonoDomain *domain)
{
/*
- * mono_runtime_cleanup() needs to be called early since
- * it needs the execution engine still fully working (it will
- * wait for other threads to finish).
+ * mono_runtime_cleanup() and mono_domain_finalize () need to
+ * be called early since they need the execution engine still
+ * fully working (mono_domain_finalize may invoke managed finalizers
+ * and mono_runtime_cleanup will wait for other threads to finish).
*/
- mono_runtime_cleanup (domain);
-
mono_domain_finalize (domain);
+ mono_runtime_cleanup (domain);
+
mono_profiler_shutdown ();
mono_debug_cleanup ();
}
void
-mini_set_defaults (int verbose_level, guint32 opts)
+mono_set_defaults (int verbose_level, guint32 opts)
{
mini_verbose = verbose_level;
default_opt = opts;