#include <mono/metadata/appdomain.h>
#include <mono/arch/x86/x86-codegen.h>
#include <mono/io-layer/io-layer.h>
+#include <mono/io-layer/threads.h>
#include "jit.h"
#include "regset.h"
#include "codegen.h"
#include "debug.h"
-/*
- * Pull the list of opcodes
- */
-#define OPDEF(a,b,c,d,e,f,g,h,i,j) \
- a = i,
+/*
+ * if OPT_BOOL is defined we use 32bit to store boolean local variables. This
+ * gives great speedup for boolean expressions, but unfortunately it changes
+ * semantics, so i disable it until we have a real solution */
+/* #define OPT_BOOL */
-enum {
-#include "mono/cil/opcode.def"
- LAST = 0xff
-};
-#undef OPDEF
+/* this is x86 specific */
+#define MB_TERM_LDIND_REF MB_TERM_LDIND_I4
+#define MB_TERM_LDIND_U4 MB_TERM_LDIND_I4
+#define MB_TERM_STIND_REF MB_TERM_STIND_I4
+#define MB_TERM_REMOTE_STIND_REF MB_TERM_REMOTE_STIND_I4
#define SET_VARINFO(vi,t,k,o,s) do { vi.type=t; vi.kind=k; vi.offset=o; vi.size=s; } while (0)
int near_jump = *ip == CEE_##name##_S; \
++ip; \
sp -= 2; \
- t1 = mono_ctree_new (mp, MB_TERM_##name, sp [0], sp [1]); \
+ t1 = mono_ctree_new (mp, MB_TERM_COMPARE, sp [0], sp [1]); \
+ t1 = mono_ctree_new (mp, MB_TERM_CBRANCH, t1, NULL); \
if (near_jump) \
target = cli_addr + 2 + (signed char) *ip; \
else \
tbb = &cfg->bblocks [bcinfo [target].block_id]; \
create_outstack (cfg, bb, stack, sp - stack); \
mark_reached (cfg, tbb, bb->outstack, bb->outdepth); \
- t1->data.p = tbb; \
+ t1->data.bi.target = tbb; \
+ t1->data.bi.cond = CEE_##name; \
ADD_TREE (t1, cli_addr); \
ip += near_jump ? 1: 4; \
break; \
case CEE_##cname: { \
++ip; \
sp -= 2; \
- t1 = mono_ctree_new (mp, MB_TERM_##cname, sp [0], sp [1]); \
+ t1 = mono_ctree_new (mp, MB_TERM_COMPARE, sp [0], sp [1]); \
+ t1 = mono_ctree_new (mp, MB_TERM_CSET, t1, NULL); \
+ t1->data.i = CEE_##cname; \
PUSH_TREE (t1, VAL_I32); \
break; \
}
/* Force jit to share code between application domains */
gboolean mono_jit_share_code = FALSE;
+/* use linear scan register allocation */
+gboolean mono_use_linear_scan = TRUE;
+
/* inline code */
gboolean mono_jit_inline_code = TRUE;
+/* Use alternative (faster) sequence to convert FP values to integers */
+gboolean mono_use_fast_iconv = FALSE;
+
/* maximum number of worker threads */
int mono_worker_threads = 1;
+/* TLS id to store jit data */
+guint32 mono_jit_tls_id;
+
MonoDebugHandle *mono_debug_handle = NULL;
GList *mono_debug_methods = NULL;
/* This is the address of the last breakpoint which was inserted. */
gchar *mono_debug_last_breakpoint_address = NULL;
-gpointer mono_end_of_stack = NULL;
-
-/* last managed frame (used by pinvoke) */
-guint32 lmf_thread_id = 0;
-
-/* used to store a function pointer called after uncatched exceptions */
-guint32 exc_cleanup_id = 0;
-
-/* stores a pointer to async result used by exceptions */
-guint32 async_result_id = 0;
-
MonoJitStats mono_jit_stats;
CRITICAL_SECTION *metadata_section = NULL;
typedef void (*MonoCCtor) (void);
+
static int
map_store_svt_type (int svt)
{
* prints the tree to stdout
*/
void
-mono_print_ctree (MBTree *tree)
+mono_print_ctree (MonoFlowGraph *cfg, MBTree *tree)
{
int arity;
switch (tree->op) {
case MB_TERM_CONST_I4:
- case MB_TERM_ADDR_L:
printf ("[%d]", tree->data.i);
break;
+ case MB_TERM_ADDR_L:
+ if (VARINFO (cfg, tree->data.i).reg >= 0)
+ printf ("[R%d]", tree->data.i);
+ else
+ printf ("[%d]", tree->data.i);
+ break;
}
g_assert (!(tree->right && !tree->left));
- mono_print_ctree (tree->left);
- mono_print_ctree (tree->right);
+ mono_print_ctree (cfg, tree->left);
+ mono_print_ctree (cfg, tree->right);
if (arity)
printf (")");
* prints the whole forest to stdout
*/
void
-mono_print_forest (GPtrArray *forest)
+mono_print_forest (MonoFlowGraph *cfg, GPtrArray *forest)
{
const int top = forest->len;
int i;
for (i = 0; i < top; i++) {
MBTree *t = (MBTree *) g_ptr_array_index (forest, i);
printf (" ");
- mono_print_ctree (t);
+ mono_print_ctree (cfg, t);
printf ("\n");
}
system ("as /tmp/test.s -o /tmp/test.o;objdump -d /tmp/test.o");
}
-static int
+int
arch_allocate_var (MonoFlowGraph *cfg, int size, int align, MonoValueKind kind, MonoValueType type)
{
MonoVarInfo vi;
mono_jit_stats.allocate_var++;
+ vi.range.last_use.abs_pos = 0;
+ vi.range.first_use.pos.bid = 0xffff;
+ vi.range.first_use.pos.tid = 0;
+ vi.isvolatile = 0;
+ vi.reg = -1;
+ vi.varnum = cfg->varinfo->len;
+
+ if (size != sizeof (gpointer))
+ vi.isvolatile = 1;
+
switch (kind) {
case MONO_TEMPVAR:
case MONO_LOCALVAR: {
t = mono_ctree_new (mp, MB_TERM_LDIND_I2, t, NULL);
t->svt = VAL_I32;
break;
- case MB_TERM_STIND_REF:
- case MB_TERM_LDIND_REF:
- t = ctree_dup_address (mp, s->left);
- t = mono_ctree_new (mp, MB_TERM_LDIND_REF, t, NULL);
- t->svt = VAL_POINTER;
- break;
case MB_TERM_STIND_I4:
case MB_TERM_LDIND_I4:
t = ctree_dup_address (mp, s->left);
t = mono_ctree_new (mp, MB_TERM_LDIND_I4, t, NULL);
t->svt = VAL_I32;
break;
- case MB_TERM_LDIND_U4:
- t = ctree_dup_address (mp, s->left);
- t = mono_ctree_new (mp, MB_TERM_LDIND_U4, t, NULL);
- t->svt = VAL_I32;
- break;
case MB_TERM_STIND_I8:
case MB_TERM_LDIND_I8:
t = ctree_dup_address (mp, s->left);
case MB_TERM_LDIND_I2:
case MB_TERM_STIND_I4:
case MB_TERM_LDIND_I4:
- case MB_TERM_STIND_REF:
- case MB_TERM_LDIND_REF:
case MB_TERM_STIND_I8:
case MB_TERM_LDIND_I8:
case MB_TERM_STIND_R4:
cfg->method = method;
cfg->mp = mp;
+ /* reserve space for caller saved registers */
+ /* fixme: this is arch dependent */
+ cfg->locals_size = 12;
+
/* fixme: we should also consider loader optimisation attributes */
cfg->share_code = mono_jit_share_code;
if (!cfg->bblocks [i].reached)
continue;
g_ptr_array_free (cfg->bblocks [i].forest, TRUE);
+ g_list_free (cfg->bblocks [i].succ);
}
if (cfg->bcinfo)
}
static MonoBBlock *
-mono_find_final_block (MonoFlowGraph *cfg, guint32 ip, int type)
+mono_find_final_block (MonoFlowGraph *cfg, guint32 ip, guint32 target, int type)
{
MonoMethod *method = cfg->method;
MonoBytecodeInfo *bcinfo = cfg->bcinfo;
for (i = 0; i < header->num_clauses; ++i) {
clause = &header->clauses [i];
- if (MONO_OFFSET_IN_HANDLER (clause, ip))
- continue;
- if (MONO_OFFSET_IN_CLAUSE (clause, ip)) {
+ if (MONO_OFFSET_IN_CLAUSE (clause, ip) &&
+ (!MONO_OFFSET_IN_CLAUSE (clause, target))) {
if (clause->flags & type) {
g_assert (bcinfo [clause->handler_offset].is_block_start);
return &cfg->bblocks [bcinfo [clause->handler_offset].block_id];
- } else
- return NULL;
+ }
}
}
return NULL;
}
+static void
+mono_cfg_add_successor (MonoFlowGraph *cfg, MonoBBlock *bb, gint32 target)
+{
+ MonoBBlock *tbb;
+ GList *l;
+
+ g_assert (cfg->bcinfo [target].is_block_start);
+
+ tbb = &cfg->bblocks [cfg->bcinfo [target].block_id];
+ g_assert (tbb);
+
+ for (l = bb->succ; l; l = l->next) {
+ MonoBBlock *t = (MonoBBlock *)l->data;
+ if (t == tbb)
+ return;
+ }
+
+ bb->succ = g_list_prepend (bb->succ, tbb);
+}
+
+
#define CREATE_BLOCK(t) {if (!bcinfo [t].is_block_start) {block_count++;bcinfo [t].is_block_start = 1; }}
void
for (i = 0; i < header->code_size; i++) {
if (bcinfo [i].is_block_start) {
bb->cli_addr = i;
+ bb->num = block_count;
+ bb->forest = g_ptr_array_new ();
if (block_count)
bb [-1].length = i - bb [-1].cli_addr;
bcinfo [i].block_id = block_count;
cfg->bcinfo = bcinfo;
cfg->bblocks = bblocks;
cfg->block_count = block_count;
+
+ for (i = 0; i < header->num_clauses; ++i) {
+ MonoBBlock *sbb, *tbb;
+ clause = &header->clauses [i];
+ sbb = &cfg->bblocks [bcinfo [clause->try_offset].block_id];
+ tbb = &cfg->bblocks [bcinfo [clause->handler_offset].block_id];
+ g_assert (sbb && tbb);
+ sbb->succ = g_list_prepend (sbb->succ, tbb);
+ }
+
+ ip = header->code;
+ end = ip + header->code_size;
+ bb = NULL;
+
+ while (ip < end) {
+ guint32 cli_addr = ip - header->code;
+
+ if (bcinfo [cli_addr].is_block_start) {
+ MonoBBlock *tbb = &cfg->bblocks [bcinfo [cli_addr].block_id];
+ if (bb && !bb->succ)
+ bb->succ = g_list_prepend (bb->succ, tbb);
+ bb = tbb;
+ }
+ g_assert (bb);
+
+ if (*ip == 0xfe) {
+ ++ip;
+ i = *ip + 256;
+ } else {
+ i = *ip;
+ }
+
+ opcode = &mono_opcodes [i];
+
+ switch (opcode->argument) {
+ case MonoInlineNone:
+ ++ip;
+ break;
+ case MonoInlineString:
+ case MonoInlineType:
+ case MonoInlineField:
+ case MonoInlineMethod:
+ case MonoInlineTok:
+ case MonoInlineSig:
+ case MonoShortInlineR:
+ case MonoInlineI:
+ ip += 5;
+ break;
+ case MonoInlineVar:
+ ip += 3;
+ break;
+ case MonoShortInlineVar:
+ case MonoShortInlineI:
+ ip += 2;
+ break;
+ case MonoShortInlineBrTarget:
+ ip++;
+ i = (signed char)*ip;
+ ip++;
+ mono_cfg_add_successor (cfg, bb, cli_addr + 2 + i);
+ if (opcode->flow_type == MONO_FLOW_COND_BRANCH)
+ mono_cfg_add_successor (cfg, bb, cli_addr + 2);
+ break;
+ case MonoInlineBrTarget:
+ ip++;
+ i = read32 (ip);
+ ip += 4;
+ mono_cfg_add_successor (cfg, bb, cli_addr + 5 + i);
+ if (opcode->flow_type == MONO_FLOW_COND_BRANCH)
+ mono_cfg_add_successor (cfg, bb, cli_addr + 5);
+ break;
+ case MonoInlineSwitch: {
+ gint32 st, target, n;
+ ++ip;
+ n = read32 (ip);
+ ip += 4;
+ st = cli_addr + 5 + 4 * n;
+ mono_cfg_add_successor (cfg, bb, st);
+
+ for (i = 0; i < n; i++) {
+ target = read32 (ip) + st;
+ ip += 4;
+ mono_cfg_add_successor (cfg, bb, target);
+ }
+ break;
+ }
+ case MonoInlineR:
+ case MonoInlineI8:
+ ip += 9;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ }
}
/**
#define PUSH_TREE(t,k) do { int tt = k; *sp = t; t->svt = tt; sp++; } while (0)
#define LOCAL_POS(n) (1 + n)
+
+#ifdef OPT_BOOL
+#define LOCAL_TYPE(n) ((header)->locals [(n)]->type == MONO_TYPE_BOOLEAN && !(header)->locals [(n)]->byref ? &mono_defaults.int32_class->byval_arg : (header)->locals [(n)])
+#else
#define LOCAL_TYPE(n) ((header)->locals [(n)])
+#endif
#define ARG_POS(n) (firstarg + n)
#define ARG_TYPE(n) ((n) ? (signature)->params [(n) - (signature)->hasthis] : \
(signature)->hasthis ? &method->klass->this_arg: (signature)->params [(0)])
+
+/*
+ * replaces all occurences of variable @varnum in @tree with @copy.
+ */
+static void
+mono_copy_used_var (MonoFlowGraph *cfg, MBTree *tree, int varnum, MBTree **copy)
+{
+ MBTree *t1, *t2;
+ int v, size, align;
+
+ if (tree->left)
+ mono_copy_used_var (cfg, tree->left, varnum, copy);
+ if (tree->right)
+ mono_copy_used_var (cfg, tree->right, varnum, copy);
+
+ switch (tree->op) {
+ case MB_TERM_LDIND_I1:
+ case MB_TERM_LDIND_I2:
+ case MB_TERM_LDIND_I4:
+ case MB_TERM_LDIND_I8:
+ case MB_TERM_LDIND_R4:
+ case MB_TERM_LDIND_R8:
+ if (tree->left->op == MB_TERM_ADDR_L &&
+ tree->left->data.i == varnum) {
+ if (*copy) {
+ tree->left->data.i = (*copy)->left->data.i;
+ return;
+ }
+
+ mono_get_val_sizes (tree->svt, &size, &align);
+ v = arch_allocate_var (cfg, size, align, MONO_TEMPVAR, tree->svt);
+
+ t1 = mono_ctree_new_leaf (cfg->mp, MB_TERM_ADDR_L);
+ t1->data.i = v;
+
+ t2 = mono_ctree_new_leaf (cfg->mp, MB_TERM_ADDR_L);
+ t2->data.i = varnum;
+ t2 = mono_ctree_new (cfg->mp, tree->op, t2, NULL);
+
+ t2 = mono_ctree_new (cfg->mp, map_store_svt_type (tree->svt), t1, t2);
+ t2->svt = tree->svt;
+
+ tree->left->data.i = v;
+
+ *copy = t2;
+ }
+ }
+}
+
+/*
+ * if a variable is modified and there are still referencence
+ * to it on the runtime stack we need to store the value into
+ * a temporary variable and use that value instead of the
+ * modified one.
+ */
+static MBTree *
+mono_stack_duplicate_used_var (MonoFlowGraph *cfg, MBTree **stack, MBTree **sp, int varnum)
+{
+ MBTree *res = NULL;
+
+ while (stack < sp) {
+ mono_copy_used_var (cfg, *stack, varnum, &res);
+ stack++;
+ }
+
+ return res;
+}
+
static int
check_inlining (MonoMethod *method)
{
int size, align;
for (i = 0; i < header->num_locals; ++i) {
- size = mono_type_size (header->locals [i], &align);
- varnum = arch_allocate_var (cfg, size, align, MONO_LOCALVAR, VAL_UNKNOWN);
+ MonoValueType svt;
+ size = mono_type_size (LOCAL_TYPE (i), &align);
+ map_ldind_type (header->locals [i], &svt);
+ varnum = arch_allocate_var (cfg, size, align, MONO_LOCALVAR, svt);
if (i == 0)
cfg->locals_start_index = varnum;
}
cfg->args_start_index = firstarg = varnum + 1;
if (signature->hasthis) {
- arch_allocate_var (cfg, sizeof (gpointer), sizeof (gpointer), MONO_ARGVAR, VAL_POINTER);
+ int thisvar;
+ thisvar = arch_allocate_var (cfg, sizeof (gpointer), sizeof (gpointer), MONO_ARGVAR, VAL_POINTER);
+ VARINFO (cfg, thisvar).isvolatile = 1;
}
if (signature->param_count) {
int align, size;
for (i = 0; i < signature->param_count; ++i) {
+ int argvar;
size = mono_type_stack_size (signature->params [i], &align);
- arch_allocate_var (cfg, size, align, MONO_ARGVAR, VAL_UNKNOWN);
+ argvar = arch_allocate_var (cfg, size, align, MONO_ARGVAR, VAL_UNKNOWN);
+ VARINFO (cfg, argvar).isvolatile = 1;
}
}
ip = header->code + bb->cli_addr;
end = ip + bb->length;
- bb->forest = forest = g_ptr_array_new ();
+ forest = bb->forest;
superblock_end = FALSE;
arg_sp = sp -= cm->signature->param_count;
- if ((cm->flags & METHOD_ATTRIBUTE_FINAL) ||
+ if ((cm->flags & METHOD_ATTRIBUTE_FINAL && cm->klass != mono_defaults.object_class) ||
!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
virtual = 0;
ii->arg_map [0], NULL);
ADD_TREE (ii->arg_map [0], cli_addr);
}
-
- inline_list = g_list_prepend (inline_list, ii);
- ip = ((MonoMethodNormal *)ii->method)->header->code;
- ii->end = ip + ii->method->inline_count;
- arg_map = ii->arg_map;
- image = cm->klass->image;
+
+ if (cm->inline_count) {
+ inline_list = g_list_prepend (inline_list, ii);
+ ip = ((MonoMethodNormal *)cm)->header->code;
+ ii->end = ip + cm->inline_count;
+ arg_map = ii->arg_map;
+ image = cm->klass->image;
+ }
continue;
}
}
if (csig->hasthis) {
- this = *(--sp);
+ this = *(--sp);
args_size += sizeof (gpointer);
} else
this = mono_ctree_new_leaf (mp, MB_TERM_NOP);
} else {
- if (virtual || (csig->hasthis && (cm->klass->marshalbyref ||
- shared_to_unshared_call ||
- cm->klass == mono_defaults.object_class))) {
+ if (virtual || (csig->hasthis &&
+ !(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) &&
+ (cm->klass->marshalbyref || shared_to_unshared_call))) {
+
mono_class_init (cm->klass);
if (cm->klass->flags & TYPE_ATTRIBUTE_INTERFACE)
t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
t1->data.i = LOCAL_POS (*ip);
+ VARINFO (cfg, t1->data.i).isvolatile = 1;
++ip;
PUSH_TREE (t1, VAL_POINTER);
break;
t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
t1->data.i = LOCAL_POS (n);
- t1 = ctree_create_store (cfg, LOCAL_TYPE (n), t1, *sp, FALSE);
+ if ((t2 = mono_stack_duplicate_used_var (cfg, stack, sp, t1->data.i)))
+ ADD_TREE (t2, cli_addr);
+
+ t1 = ctree_create_store (cfg, LOCAL_TYPE (n), t1, *sp, FALSE);
ADD_TREE (t1, cli_addr);
break;
}
t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
t1->data.i = LOCAL_POS (*ip);
- t1 = ctree_create_store (cfg, LOCAL_TYPE (*ip), t1, *sp, FALSE);
+ if ((t2 = mono_stack_duplicate_used_var (cfg, stack, sp, t1->data.i)))
+ ADD_TREE (t2, cli_addr);
+ t1 = ctree_create_store (cfg, LOCAL_TYPE (*ip), t1, *sp, FALSE);
++ip;
ADD_TREE (t1, cli_addr);
break;
}
- case CEE_SHR: {
- ++ip;
- sp -= 2;
- t1 = mono_ctree_new (mp, MB_TERM_SHR, sp [0], sp [1]);
- PUSH_TREE (t1, sp [0]->svt);
- break;
- }
- case CEE_SHR_UN: {
- ++ip;
- sp -= 2;
- t1 = mono_ctree_new (mp, MB_TERM_SHR_UN, sp [0], sp [1]);
- PUSH_TREE (t1, sp [0]->svt);
- break;
- }
- case CEE_SHL: {
- ++ip;
- sp -= 2;
- t1 = mono_ctree_new (mp, MB_TERM_SHL, sp [0], sp [1]);
- PUSH_TREE (t1, sp [0]->svt);
- break;
- }
-
MAKE_BI_ALU (ADD)
MAKE_BI_ALU (ADD_OVF)
MAKE_BI_ALU (ADD_OVF_UN)
MAKE_BI_ALU (AND)
MAKE_BI_ALU (OR)
MAKE_BI_ALU (XOR)
+ MAKE_SPILLED_BI_ALU (SHL)
+ MAKE_SPILLED_BI_ALU (SHR)
+ MAKE_SPILLED_BI_ALU (SHR_UN)
MAKE_SPILLED_BI_ALU (MUL)
MAKE_SPILLED_BI_ALU (MUL_OVF)
MAKE_SPILLED_BI_ALU (MUL_OVF_UN)
/* fixme: fault handler */
- if ((hb = mono_find_final_block (cfg, cli_addr, MONO_EXCEPTION_CLAUSE_FINALLY))) {
+ if ((hb = mono_find_final_block (cfg, cli_addr, target, MONO_EXCEPTION_CLAUSE_FINALLY))) {
mark_reached (cfg, hb, NULL, 0);
t1 = mono_ctree_new_leaf (mp, MB_TERM_HANDLER);
t1->data.p = hb;
if (sp > stack) {
g_warning ("more values on stack at IL_%04x: %d", ip - header->code, sp - stack);
- mono_print_ctree (sp [-1]);
+ mono_print_ctree (cfg, sp [-1]);
printf ("\n");
}
superblock_end = TRUE;
int vnum;
++ip;
- sp--;
- vnum = mono_allocate_intvar (cfg, sp - stack, sp [0]->svt);
- t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
- t1->data.i = vnum;
-
- t2 = mono_ctree_new (mp, map_store_svt_type (sp [0]->svt), t1, sp [0]);
- t2->svt = sp [0]->svt;
- ADD_TREE (t2, cli_addr);
+ /* fixme: maybe we should add more of these optimisations */
+ if (sp [-1]->op == MB_TERM_CONST_I4) {
- t1 = ctree_create_dup (mp, t2);
- PUSH_TREE (t1, t1->svt);
- t1 = ctree_create_dup (mp, t1);
- PUSH_TREE (t1, t1->svt);
+ t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
+ t1->data.i = sp [-1]->data.i;
+ PUSH_TREE (t1, VAL_I32);
+
+ } else {
+ sp--;
+ vnum = mono_allocate_intvar (cfg, sp - stack, sp [0]->svt);
+ t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
+ t1->data.i = vnum;
+
+ t2 = mono_ctree_new (mp, map_store_svt_type (sp [0]->svt), t1, sp [0]);
+ t2->svt = sp [0]->svt;
+ ADD_TREE (t2, cli_addr);
+
+ t1 = ctree_create_dup (mp, t2);
+ PUSH_TREE (t1, t1->svt);
+ t1 = ctree_create_dup (mp, t1);
+ PUSH_TREE (t1, t1->svt);
+ }
break;
}
case CEE_POP: {
break;
}
case CEE_CONV_U1:
- case CEE_CONV_I1: {
+ ++ip;
+ sp--;
+ t1 = mono_ctree_new (mp, MB_TERM_CONV_U1, *sp, NULL);
+ PUSH_TREE (t1, VAL_I32);
+ break;
+ case CEE_CONV_I1:
++ip;
sp--;
t1 = mono_ctree_new (mp, MB_TERM_CONV_I1, *sp, NULL);
PUSH_TREE (t1, VAL_I32);
break;
- }
case CEE_CONV_U2:
- case CEE_CONV_I2: {
+ ++ip;
+ sp--;
+ t1 = mono_ctree_new (mp, MB_TERM_CONV_U2, *sp, NULL);
+ PUSH_TREE (t1, VAL_I32);
+ break;
+ case CEE_CONV_I2:
++ip;
sp--;
t1 = mono_ctree_new (mp, MB_TERM_CONV_I2, *sp, NULL);
PUSH_TREE (t1, VAL_I32);
break;
- }
case CEE_CONV_I:
+ case CEE_CONV_I4:
+ ++ip;
+ sp--;
+ t1 = mono_ctree_new (mp, MB_TERM_CONV_I4, *sp, NULL);
+ PUSH_TREE (t1, VAL_I32);
+ break;
case CEE_CONV_U:
case CEE_CONV_U4:
- case CEE_CONV_I4: {
++ip;
sp--;
- t1 = mono_ctree_new (mp, MB_TERM_CONV_I4, *sp, NULL);
+ t1 = mono_ctree_new (mp, MB_TERM_CONV_U4, *sp, NULL);
PUSH_TREE (t1, VAL_I32);
break;
- }
- case CEE_CONV_I8: {
+ case CEE_CONV_I8:
++ip;
sp--;
t1 = mono_ctree_new (mp, MB_TERM_CONV_I8, *sp, NULL);
PUSH_TREE (t1, VAL_I64);
break;
- }
- case CEE_CONV_U8: {
+ case CEE_CONV_U8:
++ip;
sp--;
- t1 = mono_ctree_new (mp, MB_TERM_CONV_I8, *sp, NULL);
+ t1 = mono_ctree_new (mp, MB_TERM_CONV_U8, *sp, NULL);
PUSH_TREE (t1, VAL_I64);
break;
- }
- case CEE_CONV_R8: {
+ case CEE_CONV_R8:
++ip;
sp--;
t1 = mono_ctree_new (mp, MB_TERM_CONV_R8, *sp, NULL);
PUSH_TREE (t1, VAL_DOUBLE);
break;
- }
- case CEE_CONV_R4: {
+ case CEE_CONV_R4:
++ip;
sp--;
t1 = mono_ctree_new (mp, MB_TERM_CONV_R4, *sp, NULL);
PUSH_TREE (t1, VAL_DOUBLE);
break;
- }
- case CEE_CONV_R_UN: {
+ case CEE_CONV_R_UN:
++ip;
sp--;
t1 = mono_ctree_new (mp, MB_TERM_CONV_R_UN, *sp, NULL);
PUSH_TREE (t1, VAL_DOUBLE);
break;
- }
case CEE_CONV_OVF_I:
- case CEE_CONV_OVF_I4: {
+ case CEE_CONV_OVF_I4:
++ip;
sp--;
t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_I4, *sp, NULL);
PUSH_TREE (t1, VAL_I32);
break;
- }
case CEE_CONV_OVF_I_UN:
- case CEE_CONV_OVF_I4_UN: {
+ case CEE_CONV_OVF_I4_UN:
++ip;
sp--;
t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_I4_UN, *sp, NULL);
PUSH_TREE (t1, VAL_I32);
break;
- }
case CEE_CONV_OVF_U:
- case CEE_CONV_OVF_U4: {
+ case CEE_CONV_OVF_U4:
++ip;
sp--;
t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_U4, *sp, NULL);
PUSH_TREE (t1, VAL_I32);
break;
- }
- case CEE_CONV_OVF_I1: {
+ case CEE_CONV_OVF_I1:
++ip;
sp--;
t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_I1, *sp, NULL);
PUSH_TREE (t1, VAL_I32);
break;
- }
- case CEE_CONV_OVF_I1_UN: {
+ case CEE_CONV_OVF_I1_UN:
++ip;
sp--;
t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_I1_UN, *sp, NULL);
PUSH_TREE (t1, VAL_I32);
break;
- }
- case CEE_CONV_OVF_U1_UN: {
+ case CEE_CONV_OVF_U1_UN:
++ip;
sp--;
t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_U1_UN, *sp, NULL);
PUSH_TREE (t1, VAL_I32);
break;
- }
-
- case CEE_CONV_OVF_U1: {
+ case CEE_CONV_OVF_U1:
++ip;
sp--;
t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_U1, *sp, NULL);
PUSH_TREE (t1, VAL_I32);
break;
- }
- case CEE_CONV_OVF_I2: {
+ case CEE_CONV_OVF_I2:
++ip;
sp--;
t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_I2, *sp, NULL);
PUSH_TREE (t1, VAL_I32);
break;
- }
- case CEE_CONV_OVF_U2_UN: {
+ case CEE_CONV_OVF_U2_UN:
++ip;
sp--;
t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_U2_UN, *sp, NULL);
PUSH_TREE (t1, VAL_I32);
break;
- }
- case CEE_CONV_OVF_U2: {
+ case CEE_CONV_OVF_U2:
++ip;
sp--;
t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_U2, *sp, NULL);
PUSH_TREE (t1, VAL_I32);
break;
- }
- case CEE_CONV_OVF_I2_UN: {
+ case CEE_CONV_OVF_I2_UN:
++ip;
sp--;
t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_I2_UN, *sp, NULL);
PUSH_TREE (t1, VAL_I32);
break;
- }
- case CEE_CONV_OVF_U8: {
+ case CEE_CONV_OVF_U8:
++ip;
sp--;
t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_U8, *sp, NULL);
PUSH_TREE (t1, VAL_I32);
break;
- }
case CEE_CONV_OVF_U_UN:
- case CEE_CONV_OVF_U4_UN: {
+ case CEE_CONV_OVF_U4_UN:
// fixme: raise exceptions ?
++ip;
sp--;
t1 = mono_ctree_new (mp, MB_TERM_CONV_I4, *sp, NULL);
PUSH_TREE (t1, VAL_I32);
break;
- }
- case CEE_CONV_OVF_I8_UN: {
+ case CEE_CONV_OVF_I8_UN:
++ip;
sp--;
t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_I8_UN, *sp, NULL);
PUSH_TREE (t1, VAL_I64);
break;
- }
case CEE_PREFIX1: {
++ip;
switch (*ip) {
t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
t1->data.i = LOCAL_POS (read16 (ip));
+ VARINFO (cfg, t1->data.i).isvolatile = 1;
ip += 2;
PUSH_TREE (t1, VAL_POINTER);
break;
t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
t1->data.i = LOCAL_POS (read16 (ip));
- t1 = ctree_create_store (cfg, LOCAL_TYPE (read16 (ip)), t1, *sp, FALSE);
+ if ((t2 = mono_stack_duplicate_used_var (cfg, stack, sp, t1->data.i)))
+ ADD_TREE (t2, cli_addr);
+ t1 = ctree_create_store (cfg, LOCAL_TYPE (read16 (ip)), t1, *sp, FALSE);
ip += 2;
ADD_TREE (t1, cli_addr);
break;
cfg->invalid = 1;
return;
}
- mono_print_forest (forest);
+ mono_print_forest (cfg, forest);
g_assert_not_reached ();
}
}
if ((depth = sp - stack)) {
//printf ("DEPTH %d %d\n", depth, sp [0]->op);
- //mono_print_forest (forest);
+ //mono_print_forest (cfg, forest);
create_outstack (cfg, bb, stack, sp - stack);
}
//printf ("unreached block %d\n", i);
repeat = TRUE;
if (repeat_count >= 10) {
- /*mono_print_forest (forest);
+ /*mono_print_forest (cfg, forest);
g_warning ("repeat count exceeded at ip: 0x%04x in %s\n", bb->cli_addr, cfg->method->name);*/
repeat = FALSE;
}
int
mono_jit_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[])
{
- MonoArray *args = NULL;
MonoImage *image = assembly->image;
MonoCLIImageInfo *iinfo;
MonoMethod *method;
+ MonoObject *exc;
+ int rval;
iinfo = image->image_info;
method = mono_get_method (image, iinfo->cli_cli_header.ch_entry_point, NULL);
- if (method->signature->param_count) {
- int i;
- args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
- for (i = 0; i < argc; ++i) {
- MonoString *arg = mono_string_new (domain, argv [i]);
- mono_array_set (args, gpointer, i, arg);
- }
- }
-
- return mono_runtime_exec_main (method, args);
+ rval = mono_runtime_run_main (method, argc, argv, &exc);
+
+ return rval;
}
#ifdef PLATFORM_WIN32
}
/**
- * mono_jit_abort:
+ * mono_thread_abort:
* @obj: exception object
*
- * abort the program, print exception information and stack trace
+ * abort the thread, print exception information and stack trace
*/
static void
-mono_jit_abort (MonoObject *obj)
+mono_thread_abort (MonoObject *obj)
{
- const char *message = "";
- char *trace = NULL;
- MonoString *str; ;
-
+ MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
+
g_assert (obj);
- if (mono_object_isinst (obj, mono_defaults.exception_class)) {
- if ((str = ((MonoException *)obj)->message))
- message = mono_string_to_utf8 (str);
- if ((str = ((MonoException *)obj)->stack_trace))
- trace = mono_string_to_utf8 (str);
- }
-
- g_warning ("unhandled exception %s.%s: \"%s\"", obj->vtable->klass->name_space,
- obj->vtable->klass->name, message);
-
- if (trace) {
- g_printerr (trace);
- g_printerr ("\n");
+ if (jit_tls->env) {
+ longjmp (*jit_tls->env, obj);
}
+
+ if (obj)
+ mono_unhandled_exception (obj);
+
+ ExitThread (-1);
+}
+
+static void
+mono_thread_start_cb (gpointer stack_start)
+{
+ MonoJitTlsData *jit_tls;
+
+ jit_tls = g_new0 (MonoJitTlsData, 1);
+
+ TlsSetValue (mono_jit_tls_id, jit_tls);
- exit (1);
+ jit_tls->abort_func = mono_thread_abort;
+ jit_tls->end_of_stack = stack_start;
}
static CRITICAL_SECTION ms;
#endif
MonoDomain *domain;
+ mono_cpu_detect ();
#ifdef PLATFORM_WIN32
win32_seh_init();
metadata_section = &ms;
InitializeCriticalSection (metadata_section);
- lmf_thread_id = TlsAlloc ();
- TlsSetValue (lmf_thread_id, NULL);
- exc_cleanup_id = TlsAlloc ();
- TlsSetValue (exc_cleanup_id, mono_jit_abort);
- async_result_id = TlsAlloc ();
+ mono_jit_tls_id = TlsAlloc ();
+ mono_thread_start_cb (&file);
mono_install_trampoline (arch_create_jit_trampoline);
mono_install_remoting_trampoline (arch_create_remoting_trampoline);
domain = mono_init (file);
mono_runtime_init (domain);
- mono_thread_init (domain);
+ mono_thread_init (domain, mono_thread_start_cb);
mono_network_init ();
mono_delegate_init ();