#include <unistd.h>
#include <math.h>
+#ifdef sun // Solaris x86
+#include <sys/types.h>
+#include <sys/ucontext.h>
+#endif
+
#ifdef HAVE_VALGRIND_MEMCHECK_H
#include <valgrind/memcheck.h>
#endif
#include <mono/metadata/environment.h>
#include <mono/metadata/mono-debug.h>
#include <mono/metadata/mono-debug-debugger.h>
+#include <mono/metadata/monitor.h>
#include "mini.h"
#include <string.h>
#include "jit-icalls.c"
-#define MONO_IS_COND_BRANCH(op) ((op >= CEE_BEQ && op <= CEE_BLT_UN) || (op >= OP_LBEQ && op <= OP_LBLT_UN) || (op >= OP_FBEQ && op <= OP_FBLT_UN))
+/*
+ * this is used to determine when some branch optimizations are possible: we exclude FP compares
+ * because they have weird semantics with NaNs.
+ */
+#define MONO_IS_COND_BRANCH_OP(ins) (((ins)->opcode >= CEE_BEQ && (ins)->opcode <= CEE_BLT_UN) || ((ins)->opcode >= OP_LBEQ && (ins)->opcode <= OP_LBLT_UN) || ((ins)->opcode >= OP_FBEQ && (ins)->opcode <= OP_FBLT_UN) || ((ins)->opcode >= OP_IBEQ && (ins)->opcode <= OP_IBLT_UN))
+#define MONO_IS_COND_BRANCH_NOFP(ins) (MONO_IS_COND_BRANCH_OP(ins) && (ins)->inst_left->inst_left->type != STACK_R8)
#define MONO_CHECK_THIS(ins) (cfg->method->signature->hasthis && (ins)->ssa_op == MONO_SSA_LOAD && (ins)->inst_left->inst_c0 == 0)
static MonoMethodSignature *helper_sig_compile = NULL;
static MonoMethodSignature *helper_sig_compile_virt = NULL;
static MonoMethodSignature *helper_sig_obj_ptr = NULL;
+static MonoMethodSignature *helper_sig_obj_ptr_ptr = NULL;
+static MonoMethodSignature *helper_sig_obj_obj_ptr_ptr = NULL;
static MonoMethodSignature *helper_sig_obj_void = NULL;
static MonoMethodSignature *helper_sig_ptr_void = NULL;
+static MonoMethodSignature *helper_sig_void_void = NULL;
static MonoMethodSignature *helper_sig_void_ptr = NULL;
static MonoMethodSignature *helper_sig_void_obj = NULL;
+static MonoMethodSignature *helper_sig_void_obj_ptr_int = NULL;
+static MonoMethodSignature *helper_sig_void_obj_ptr_ptr_obj = NULL;
static MonoMethodSignature *helper_sig_void_ptr_ptr = NULL;
static MonoMethodSignature *helper_sig_void_ptr_ptr_ptr = NULL;
static MonoMethodSignature *helper_sig_ptr_ptr_ptr = NULL;
static MonoMethodSignature *helper_sig_ptr_obj = NULL;
+static MonoMethodSignature *helper_sig_ptr_obj_int = NULL;
static MonoMethodSignature *helper_sig_ptr_int = NULL;
static MonoMethodSignature *helper_sig_initobj = NULL;
static MonoMethodSignature *helper_sig_memcpy = NULL;
#endif
}
-#ifdef MONO_USE_EXC_TABLES
-static gboolean
-mono_type_blittable (MonoType *type)
-{
- if (type->byref)
- return FALSE;
-
- switch (type->type){
- case MONO_TYPE_VOID:
- case MONO_TYPE_I1:
- case MONO_TYPE_U1:
- case MONO_TYPE_I2:
- case MONO_TYPE_U2:
- case MONO_TYPE_I4:
- case MONO_TYPE_U4:
- case MONO_TYPE_I8:
- case MONO_TYPE_U8:
- case MONO_TYPE_R4:
- case MONO_TYPE_R8:
- case MONO_TYPE_I:
- case MONO_TYPE_U:
- return TRUE;
- case MONO_TYPE_VALUETYPE:
- case MONO_TYPE_CLASS:
- return type->data.klass->blittable;
- break;
- default:
- break;
- }
-
- return FALSE;
-}
-
-gboolean
-mono_method_blittable (MonoMethod *method)
-{
- MonoMethodSignature *sig;
- int i;
-
- if (!method->addr)
- return FALSE;
-
- if (!mono_arch_has_unwind_info (method->addr)) {
- return FALSE;
- }
-
- if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)
- return TRUE;
-
- sig = method->signature;
-
- if (!mono_type_blittable (sig->ret))
- return FALSE;
-
- for (i = 0; i < sig->param_count; i++)
- if (!mono_type_blittable (sig->params [i]))
- return FALSE;
-
- if (mono_method_has_marshal_info (method))
- return FALSE;
-
- if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) && ((MonoMethodPInvoke*)method)->piflags & PINVOKE_ATTRIBUTE_SUPPORTS_LAST_ERROR)
- return FALSE;
-
- return TRUE;
-}
-#endif
-
/* debug function */
G_GNUC_UNUSED static void
print_method_from_ip (void *ip)
}
+G_GNUC_UNUSED void
+mono_print_method_from_ip (void *ip)
+{
+ print_method_from_ip (ip);
+}
+
/*
* mono_method_same_domain:
*
(dest)->type = STACK_I4; \
} while (0)
-/* FIXME: have a different definition of NEW_PCONST for 64 bit systems */
+#if SIZEOF_VOID_P == 8
+#define NEW_PCONST(cfg,dest,val) do { \
+ (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
+ (dest)->opcode = OP_I8CONST; \
+ (dest)->inst_p0 = (val); \
+ (dest)->type = STACK_PTR; \
+ } while (0)
+#else
#define NEW_PCONST(cfg,dest,val) do { \
(dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
(dest)->opcode = OP_ICONST; \
(dest)->inst_p0 = (val); \
(dest)->type = STACK_PTR; \
} while (0)
+#endif
+
+#if SIZEOF_VOID_P == 8
+#define OP_PCONST OP_I8CONST
+#else
+#define OP_PCONST OP_ICONST
+#endif
#define NEW_CLASSCONST(cfg,dest,val) do { \
(dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- (dest)->opcode = mono_compile_aot ? OP_AOTCONST : OP_ICONST; \
+ (dest)->opcode = mono_compile_aot ? OP_AOTCONST : OP_PCONST; \
(dest)->inst_p0 = (val); \
(dest)->inst_i1 = (gpointer)MONO_PATCH_INFO_CLASS; \
(dest)->type = STACK_PTR; \
#define NEW_IMAGECONST(cfg,dest,val) do { \
(dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- (dest)->opcode = mono_compile_aot ? OP_AOTCONST : OP_ICONST; \
+ (dest)->opcode = mono_compile_aot ? OP_AOTCONST : OP_PCONST; \
(dest)->inst_p0 = (val); \
(dest)->inst_i1 = (gpointer)MONO_PATCH_INFO_IMAGE; \
(dest)->type = STACK_PTR; \
#define NEW_FIELDCONST(cfg,dest,field) do { \
(dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- (dest)->opcode = mono_compile_aot ? OP_AOTCONST : OP_ICONST; \
+ (dest)->opcode = mono_compile_aot ? OP_AOTCONST : OP_PCONST; \
(dest)->inst_p0 = (field); \
(dest)->inst_i1 = (gpointer)MONO_PATCH_INFO_FIELD; \
(dest)->type = STACK_PTR; \
#define NEW_METHODCONST(cfg,dest,val) do { \
(dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- (dest)->opcode = mono_compile_aot ? OP_AOTCONST : OP_ICONST; \
+ (dest)->opcode = mono_compile_aot ? OP_AOTCONST : OP_PCONST; \
(dest)->inst_p0 = (val); \
(dest)->inst_i1 = (gpointer)MONO_PATCH_INFO_METHODCONST; \
(dest)->type = STACK_PTR; \
#define NEW_VTABLECONST(cfg,dest,vtable) do { \
(dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- (dest)->opcode = mono_compile_aot ? OP_AOTCONST : OP_ICONST; \
+ (dest)->opcode = mono_compile_aot ? OP_AOTCONST : OP_PCONST; \
(dest)->inst_p0 = mono_compile_aot ? (gpointer)((vtable)->klass) : (vtable); \
(dest)->inst_i1 = (gpointer)MONO_PATCH_INFO_VTABLE; \
(dest)->type = STACK_PTR; \
#define NEW_SFLDACONST(cfg,dest,field) do { \
(dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- (dest)->opcode = mono_compile_aot ? OP_AOTCONST : OP_ICONST; \
+ (dest)->opcode = mono_compile_aot ? OP_AOTCONST : OP_PCONST; \
(dest)->inst_p0 = (field); \
(dest)->inst_i1 = (gpointer)MONO_PATCH_INFO_SFLDA; \
(dest)->type = STACK_PTR; \
#define ADD_BINCOND(next_block) do { \
MonoInst *cmp; \
- MONO_INST_NEW(cfg, cmp, OP_COMPARE); \
sp -= 2; \
+ MONO_INST_NEW(cfg, cmp, OP_COMPARE); \
cmp->inst_i0 = sp [0]; \
cmp->inst_i1 = sp [1]; \
cmp->cil_code = ins->cil_code; \
/* FIXME: handle float, long ... */
#define ADD_UNCOND(istrue) do { \
MonoInst *cmp; \
- MONO_INST_NEW(cfg, cmp, OP_COMPARE); \
sp--; \
+ MONO_INST_NEW(cfg, cmp, OP_COMPARE); \
cmp->inst_i0 = sp [0]; \
switch (cmp->inst_i0->type) { \
case STACK_I8: \
(dest)->inst_right = (sp) [1]; \
(dest)->type = STACK_MP; \
(dest)->klass = (k); \
+ (cfg)->flags |= MONO_CFG_HAS_LDELEMA; \
} while (0)
#define NEW_GROUP(cfg,dest,el1,el2) do { \
/* handles from CEE_ADD to CEE_SHR_UN (CEE_REM_UN for floats) */
static const guint16
binops_op_map [STACK_MAX] = {
- 0, 0, OP_LADD-CEE_ADD, OP_PADD-CEE_ADD, OP_FADD-CEE_ADD, 0
+ 0, 0, OP_LADD-CEE_ADD, OP_PADD-CEE_ADD, OP_FADD-CEE_ADD, OP_PADD-CEE_ADD
};
/* handles from CEE_NEG to CEE_CONV_U8 */
static const guint16
unops_op_map [STACK_MAX] = {
- 0, 0, OP_LNEG-CEE_NEG, OP_PNEG-CEE_NEG, OP_FNEG-CEE_NEG, 0
+ 0, 0, OP_LNEG-CEE_NEG, OP_PNEG-CEE_NEG, OP_FNEG-CEE_NEG, OP_PNEG-CEE_NEG
};
/* handles from CEE_CONV_U2 to CEE_SUB_OVF_UN */
static const guint16
ovfops_op_map [STACK_MAX] = {
- 0, 0, OP_LCONV_TO_U2-CEE_CONV_U2, OP_PCONV_TO_U2-CEE_CONV_U2, OP_FCONV_TO_U2-CEE_CONV_U2, 0
+ 0, 0, OP_LCONV_TO_U2-CEE_CONV_U2, OP_PCONV_TO_U2-CEE_CONV_U2, OP_FCONV_TO_U2-CEE_CONV_U2, OP_PCONV_TO_U2-CEE_CONV_U2
};
/* handles from CEE_CONV_OVF_I1_UN to CEE_CONV_OVF_U_UN */
static const guint16
ovf2ops_op_map [STACK_MAX] = {
- 0, 0, OP_LCONV_TO_OVF_I1_UN-CEE_CONV_OVF_I1_UN, OP_PCONV_TO_OVF_I1_UN-CEE_CONV_OVF_I1_UN, OP_FCONV_TO_OVF_I1_UN-CEE_CONV_OVF_I1_UN, 0
+ 0, 0, OP_LCONV_TO_OVF_I1_UN-CEE_CONV_OVF_I1_UN, OP_PCONV_TO_OVF_I1_UN-CEE_CONV_OVF_I1_UN, OP_FCONV_TO_OVF_I1_UN-CEE_CONV_OVF_I1_UN, OP_PCONV_TO_OVF_I1_UN-CEE_CONV_OVF_I1_UN
};
/* handles from CEE_CONV_OVF_I1 to CEE_CONV_OVF_U8 */
static const guint16
ovf3ops_op_map [STACK_MAX] = {
- 0, 0, OP_LCONV_TO_OVF_I1-CEE_CONV_OVF_I1, OP_PCONV_TO_OVF_I1-CEE_CONV_OVF_I1, OP_FCONV_TO_OVF_I1-CEE_CONV_OVF_I1, 0
+ 0, 0, OP_LCONV_TO_OVF_I1-CEE_CONV_OVF_I1, OP_PCONV_TO_OVF_I1-CEE_CONV_OVF_I1, OP_FCONV_TO_OVF_I1-CEE_CONV_OVF_I1, OP_PCONV_TO_OVF_I1-CEE_CONV_OVF_I1
};
/* handles from CEE_CEQ to CEE_CLT_UN */
static const guint16
ceqops_op_map [STACK_MAX] = {
- 0, 0, OP_LCEQ-CEE_CEQ, OP_PCEQ-CEE_CEQ, OP_FCEQ-CEE_CEQ, 0
+ 0, 0, OP_LCEQ-CEE_CEQ, OP_PCEQ-CEE_CEQ, OP_FCEQ-CEE_CEQ, OP_LCEQ-CEE_CEQ
};
/*
ins->opcode += binops_op_map [ins->type];
return;
case OP_COMPARE:
+ case OP_LCOMPARE:
/* FIXME: handle some specifics with ins->next->type */
ins->type = bin_comp_table [ins->inst_i0->type] [ins->inst_i1->type] ? STACK_I4: STACK_INV;
+ if ((ins->inst_i0->type == STACK_I8) || ((sizeof (gpointer) == 8) && ((ins->inst_i0->type == STACK_PTR) || (ins->inst_i0->type == STACK_OBJ) || (ins->inst_i0->type == STACK_MP))))
+ ins->opcode = OP_LCOMPARE;
return;
case OP_CEQ:
case OP_CGT:
*/
static int
handle_stack_args (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst **sp, int count) {
- int i;
+ int i, bindex;
MonoBasicBlock *outb;
MonoInst *inst, **locals;
+ gboolean found;
if (!count)
return 0;
if (cfg->verbose_level > 3)
g_print ("%d item(s) on exit from B%d\n", count, bb->block_num);
if (!bb->out_scount) {
- int found = 0;
bb->out_scount = count;
//g_print ("bblock %d has out:", bb->block_num);
+ found = FALSE;
for (i = 0; i < bb->out_count; ++i) {
outb = bb->out_bb [i];
//g_print (" %d", outb->block_num);
if (outb->in_stack) {
- found = 1;
+ found = TRUE;
bb->out_stack = outb->in_stack;
break;
}
if (!found) {
bb->out_stack = mono_mempool_alloc (cfg->mempool, sizeof (MonoInst*) * count);
for (i = 0; i < count; ++i) {
-#if 1
- /* try to reuse temps already allocated for this purpouse, if they occupy the same
- * stack slot and if they are of the same type. */
- bb->out_stack [i] = mono_compile_get_interface_var (cfg, i, sp [i]);
-#else
- bb->out_stack [i] = mono_compile_create_var (cfg, type_from_stack_type (sp [i]), OP_LOCAL);
-#endif
+ /*
+ * try to reuse temps already allocated for this purpouse, if they occupy the same
+ * stack slot and if they are of the same type.
+ * This won't cause conflicts since if 'local' is used to
+ * store one of the values in the in_stack of a bblock, then
+ * the same variable will be used for the same outgoing stack
+ * slot as well.
+ * This doesn't work when inlining methods, since the bblocks
+ * in the inlined methods do not inherit their in_stack from
+ * the bblock they are inlined to. See bug #58863 for an
+ * example.
+ */
+ if (cfg->inlined_method)
+ bb->out_stack [i] = mono_compile_create_var (cfg, type_from_stack_type (sp [i]), OP_LOCAL);
+ else
+ bb->out_stack [i] = mono_compile_get_interface_var (cfg, i, sp [i]);
}
}
}
+
+ for (i = 0; i < bb->out_count; ++i) {
+ outb = bb->out_bb [i];
+ if (outb->in_scount)
+ continue; /* check they are the same locals */
+ outb->in_scount = count;
+ outb->in_stack = bb->out_stack;
+ }
+
locals = bb->out_stack;
for (i = 0; i < count; ++i) {
/* add store ops at the end of the bb, before the branch */
if (cfg->verbose_level > 3)
g_print ("storing %d to temp %d\n", i, locals [i]->inst_c0);
}
-
- for (i = 0; i < bb->out_count; ++i) {
- outb = bb->out_bb [i];
- if (outb->in_scount)
- continue; /* check they are the same locals */
- outb->in_scount = count;
- outb->in_stack = locals;
+
+ /*
+ * It is possible that the out bblocks already have in_stack assigned, and
+ * the in_stacks differ. In this case, we will store to all the different
+ * in_stacks.
+ */
+
+ found = TRUE;
+ bindex = 0;
+ while (found) {
+ /* Find a bblock which has a different in_stack */
+ found = FALSE;
+ while (bindex < bb->out_count) {
+ outb = bb->out_bb [bindex];
+ if (outb->in_stack != locals) {
+ /*
+ * Instead of storing sp [i] to locals [i], we need to store
+ * locals [i] to <new locals>[i], since the sp [i] tree can't
+ * be shared between trees.
+ */
+ for (i = 0; i < count; ++i)
+ mono_add_varcopy_to_end (cfg, bb, locals [i]->inst_c0, outb->in_stack [i]->inst_c0);
+ locals = outb->in_stack;
+ found = TRUE;
+ break;
+ }
+ bindex ++;
+ }
}
+
return 0;
}
static int
ret_type_to_call_opcode (MonoType *type, int calli, int virt)
{
- int t = type->type;
-
if (type->byref)
return calli? OP_CALL_REG: virt? CEE_CALLVIRT: CEE_CALL;
handle_enum:
- switch (t) {
+ switch (type->type) {
case MONO_TYPE_VOID:
return calli? OP_VOIDCALL_REG: virt? OP_VOIDCALLVIRT: OP_VOIDCALL;
case MONO_TYPE_I1:
return calli? OP_FCALL_REG: virt? OP_FCALLVIRT: OP_FCALL;
case MONO_TYPE_VALUETYPE:
if (type->data.klass->enumtype) {
- t = type->data.klass->enum_basetype->type;
+ type = type->data.klass->enum_basetype;
goto handle_enum;
} else
return calli? OP_VCALL_REG: virt? OP_VCALLVIRT: OP_VCALL;
case MONO_TYPE_TYPEDBYREF:
return calli? OP_VCALL_REG: virt? OP_VCALLVIRT: OP_VCALL;
case MONO_TYPE_GENERICINST:
- t = type->data.generic_inst->generic_type->type;
+ type = type->data.generic_inst->generic_type;
goto handle_enum;
default:
g_error ("unknown type 0x%02x in ret_type_to_call_opcode", type->type);
static int
check_call_signature (MonoCompile *cfg, MonoMethodSignature *sig, MonoInst **args)
{
- int i, simple_type;
+ MonoType *simple_type;
+ int i;
if (sig->hasthis) {
if (args [0]->type != STACK_OBJ && args [0]->type != STACK_MP && args [0]->type != STACK_PTR)
return 1;
continue;
}
- simple_type = sig->params [i]->type;
+ simple_type = sig->params [i];
handle_enum:
- switch (simple_type) {
+ switch (simple_type->type) {
case MONO_TYPE_VOID:
return 1;
continue;
return 1;
continue;
case MONO_TYPE_VALUETYPE:
- if (sig->params [i]->data.klass->enumtype) {
- simple_type = sig->params [i]->data.klass->enum_basetype->type;
+ if (simple_type->data.klass->enumtype) {
+ simple_type = simple_type->data.klass->enum_basetype;
goto handle_enum;
}
if (args [i]->type != STACK_VTYPE)
return 1;
continue;
case MONO_TYPE_GENERICINST:
- simple_type = sig->params [i]->data.generic_inst->generic_type->type;
+ simple_type = sig->params [i]->data.generic_inst->generic_type;
goto handle_enum;
default:
- g_error ("unknown type 0x%02x in check_call_signature", simple_type);
+ g_error ("unknown type 0x%02x in check_call_signature",
+ simple_type->type);
}
}
return 0;
res = mono_metadata_signature_alloc (mono_defaults.corlib, arity + 1);
res->pinvoke = 1;
+#ifdef MONO_ARCH_VARARG_ICALLS
+ /* Only set this only some archs since not all backends can handle varargs+pinvoke */
+ res->call_convention = MONO_CALL_VARARG;
+#endif
res->params [0] = &mono_defaults.array_class->byval_arg;
for (i = 1; i <= arity; i++)
return res;
}
+static MonoMethodSignature *
+mono_get_array_new_va_signature (int arity)
+{
+ static GHashTable *sighash = NULL;
+ MonoMethodSignature *res;
+ int i;
+
+ EnterCriticalSection (&trampoline_hash_mutex);
+ if (!sighash) {
+ sighash = g_hash_table_new (NULL, NULL);
+ }
+ else if ((res = g_hash_table_lookup (sighash, (gpointer)arity))) {
+ LeaveCriticalSection (&trampoline_hash_mutex);
+ return res;
+ }
+
+ res = mono_metadata_signature_alloc (mono_defaults.corlib, arity + 1);
+
+ res->pinvoke = 1;
+#ifdef MONO_ARCH_VARARG_ICALLS
+ /* Only set this only some archs since not all backends can handle varargs+pinvoke */
+ res->call_convention = MONO_CALL_VARARG;
+#endif
+
+ res->params [0] = &mono_defaults.int_class->byval_arg;
+ for (i = 0; i < arity; i++)
+ res->params [i + 1] = &mono_defaults.int_class->byval_arg;
+
+ res->ret = &mono_defaults.int_class->byval_arg;
+
+ g_hash_table_insert (sighash, (gpointer)arity, res);
+ LeaveCriticalSection (&trampoline_hash_mutex);
+
+ return res;
+}
+
static void
handle_stobj (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *dest, MonoInst *src, const unsigned char *ip, MonoClass *klass, gboolean to_end, gboolean native) {
MonoInst *iargs [3];
}
NEW_TEMPLOAD (cfg, dest, temp);
NEW_ICONST (cfg, vtoffset, sizeof (MonoObject));
- MONO_INST_NEW (cfg, add, CEE_ADD);
+ MONO_INST_NEW (cfg, add, OP_PADD);
add->inst_left = dest;
add->inst_right = vtoffset;
add->cil_code = ip;
MonoVTable *vtable;
int i;
+#ifdef MONO_ARCH_HAVE_LMF_OPS
+ if (((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
+ (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) &&
+ !MONO_TYPE_ISSTRUCT (signature->ret) && (method->klass->parent != mono_defaults.array_class))
+ return TRUE;
+#endif
+
if ((method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
(method->iflags & METHOD_IMPL_ATTRIBUTE_NOINLINING) ||
}
temp = mono_emit_native_call (cfg, bblock, mono_icall_get_wrapper (info), info->sig, sp, ip, FALSE);
+ cfg->flags |= MONO_CFG_HAS_VARARGS;
NEW_TEMPLOAD (cfg, addr, temp);
return addr;
{
int pc, op;
MonoInst *ins;
+
+ static MonoClass *runtime_helpers_class = NULL;
+ if (! runtime_helpers_class)
+ runtime_helpers_class = mono_class_from_name (mono_defaults.corlib,
+ "System.Runtime.CompilerServices", "RuntimeHelpers");
if (cmethod->klass == mono_defaults.string_class) {
if (cmethod->name [0] != 'g')
op = CEE_LDLEN;
else
return NULL;
+ } else if (cmethod->klass == runtime_helpers_class) {
+ if (strcmp (cmethod->name, "get_OffsetToStringData") == 0) {
+ NEW_ICONST (cfg, ins, G_STRUCT_OFFSET (MonoString, chars));
+ return ins;
+ } else
+ return NULL;
} else {
op = mono_arch_get_opcode_for_method (cfg, cmethod, fsig, args);
if (op < 0)
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)
+ guchar *ip, guint real_offset, GList *dont_inline, MonoBasicBlock **last_b, gboolean inline_allways)
{
MonoInst *ins, *rvar = NULL;
MonoMethodHeader *cheader;
MonoBasicBlock *ebblock, *sbblock;
int i, costs, new_locals_offset;
+ MonoMethod *prev_inlined_method;
if (cfg->verbose_level > 2)
g_print ("INLINE START %p %s -> %s\n", cmethod, mono_method_full_name (cfg->method, TRUE), mono_method_full_name (cmethod, TRUE));
- cheader = ((MonoMethodNormal *)cmethod)->header;
-
if (!cmethod->inline_info) {
mono_jit_stats.inlineable_methods++;
cmethod->inline_info = 1;
}
/* allocate local variables */
+ cheader = ((MonoMethodNormal *)cmethod)->header;
new_locals_offset = cfg->num_varinfo;
for (i = 0; i < cheader->num_locals; ++i)
mono_compile_create_var (cfg, cheader->locals [i], OP_LOCAL);
ebblock->block_num = cfg->num_bblocks++;
ebblock->real_offset = real_offset;
+ prev_inlined_method = cfg->inlined_method;
+ cfg->inlined_method = cmethod;
+
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) {
+ cfg->inlined_method = prev_inlined_method;
+
+ if ((costs >= 0 && costs < 60) || inline_allways) {
if (cfg->verbose_level > 2)
g_print ("INLINE END %s -> %s\n", mono_method_full_name (cfg->method, TRUE), mono_method_full_name (cmethod, TRUE));
while (ip < end) {
cli_addr = ip - start;
- i = mono_opcode_value ((const guint8 **)&ip);
+ i = mono_opcode_value ((const guint8 **)&ip, end);
+ if (i < 0)
+ goto unverified;
opcode = &mono_opcodes [i];
switch (opcode->argument) {
case MonoInlineNone:
return 1;
}
+static MonoInst*
+emit_tree (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *ins)
+{
+ MonoInst *store, *temp, *load;
+ temp = mono_compile_create_var (cfg, type_from_stack_type (ins), OP_LOCAL);
+ NEW_TEMPSTORE (cfg, store, temp->inst_c0, ins);
+ store->cil_code = ins->cil_code;
+ MONO_ADD_INS (bblock, store);
+ NEW_TEMPLOAD (cfg, load, temp->inst_c0);
+ load->cil_code = ins->cil_code;
+ return load;
+}
+
/*
* mono_method_to_ir: translates IL into basic blocks containing trees
*/
bblock = tblock;
start_new_bblock = 0;
for (i = 0; i < bblock->in_scount; ++i) {
+ if (cfg->verbose_level > 3)
+ g_print ("loading %d from temp %d\n", i, bblock->in_stack [i]->inst_c0);
NEW_TEMPLOAD (cfg, ins, bblock->in_stack [i]->inst_c0);
*sp++ = ins;
}
bblock->next_bb = tblock;
bblock = tblock;
for (i = 0; i < bblock->in_scount; ++i) {
+ if (cfg->verbose_level > 3)
+ g_print ("loading %d from temp %d\n", i, bblock->in_stack [i]->inst_c0);
NEW_TEMPLOAD (cfg, ins, bblock->in_stack [i]->inst_c0);
*sp++ = ins;
}
*sp++ = ins;
break;
case CEE_LDC_R4: {
- float *f = g_malloc (sizeof (float));
+ float *f = mono_mempool_alloc (cfg->domain->mp, sizeof (float));
CHECK_OPSIZE (5);
CHECK_STACK_OVF (1);
MONO_INST_NEW (cfg, ins, OP_R4CONST);
break;
}
case CEE_LDC_R8: {
- double *d = g_malloc (sizeof (double));
+ double *d = mono_mempool_alloc (cfg->domain->mp, sizeof (double));
CHECK_OPSIZE (9);
CHECK_STACK_OVF (1);
MONO_INST_NEW (cfg, ins, OP_R8CONST);
mono_class_init (cmethod->klass);
if (cmethod->signature->pinvoke) {
-#ifdef MONO_USE_EXC_TABLES
- if (mono_method_blittable (cmethod)) {
- fsig = cmethod->signature;
- } else {
-#endif
MonoMethod *wrapper = mono_marshal_get_native_wrapper (cmethod);
fsig = wrapper->signature;
-#ifdef MONO_USE_EXC_TABLES
- }
-#endif
} else {
fsig = mono_method_get_signature (cmethod, image, token);
}
* We have the `constrained.' prefix opcode.
*/
if (constrained_call->valuetype && !cmethod->klass->valuetype) {
+ MonoInst *load;
/*
* The type parameter is instantiated as a valuetype,
* but that type doesn't override the method we're
* calling, so we need to box `this'.
+ * sp [0] is a pointer to the data: we need the value
+ * in handle_box (), so load it here.
*/
- sp [0] = handle_box (cfg, bblock, sp [0], ip, constrained_call);
+ MONO_INST_NEW (cfg, load, mono_type_to_ldind (&constrained_call->byval_arg));
+ type_to_eval_stack_type (&constrained_call->byval_arg, load);
+ load->cil_code = ip;
+ load->inst_left = sp [0];
+ sp [0] = handle_box (cfg, bblock, load, ip, constrained_call);
} else if (!constrained_call->valuetype) {
MonoInst *ins;
if ((cfg->opt & MONO_OPT_INLINE) && cmethod &&
(!virtual || !(cmethod->flags & METHOD_ATTRIBUTE_VIRTUAL) || (cmethod->flags & METHOD_ATTRIBUTE_FINAL)) &&
mono_method_check_inlining (cfg, cmethod) &&
- !g_list_find (dont_inline, cmethod)) {
+ !g_list_find (dont_inline, cmethod)) {
int costs;
MonoBasicBlock *ebblock;
+ gboolean allways = FALSE;
- if ((costs = inline_method (cfg, cmethod, fsig, bblock, sp, ip, real_offset, dont_inline, &ebblock))) {
+ if ((cmethod->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
+ (cmethod->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
+ cmethod = mono_marshal_get_native_wrapper (cmethod);
+ allways = TRUE;
+ }
+
+ if ((costs = inline_method (cfg, cmethod, fsig, bblock, sp, ip, real_offset, dont_inline, &ebblock, allways))) {
ip += 5;
real_offset += 5;
case CEE_SHR_UN:
CHECK_STACK (2);
ADD_BINOP (*ip);
+ /* special case that gives a nice speedup and happens to workaorund a ppc jit but (for the release)
+ * later apply the speedup to the left shift as well
+ * See BUG# 57957.
+ */
+ if ((ins->opcode == OP_LSHR_UN) && (ins->type == STACK_I8)
+ && (ins->inst_right->opcode == OP_ICONST) && (ins->inst_right->inst_c0 == 32)) {
+ ins->opcode = OP_LONG_SHRUN_32;
+ /*g_print ("applied long shr speedup to %s\n", cfg->method->name);*/
+ ip++;
+ break;
+ }
if (mono_find_jit_opcode_emulation (ins->opcode)) {
- MonoInst *store, *temp, *load;
--sp;
- temp = mono_compile_create_var (cfg, type_from_stack_type (ins), OP_LOCAL);
- NEW_TEMPSTORE (cfg, store, temp->inst_c0, ins);
- store->cil_code = ins->cil_code;
- MONO_ADD_INS (bblock, store);
- NEW_TEMPLOAD (cfg, load, temp->inst_c0);
- load->cil_code = ins->cil_code;
- *sp++ = load;
- /*g_print ("found emulation for %d\n", ins->opcode);*/
+ *sp++ = emit_tree (cfg, bblock, ins);
}
ip++;
break;
CHECK_STACK (1);
ADD_UNOP (*ip);
if (mono_find_jit_opcode_emulation (ins->opcode)) {
- MonoInst *store, *temp, *load;
--sp;
- temp = mono_compile_create_var (cfg, type_from_stack_type (ins), OP_LOCAL);
- NEW_TEMPSTORE (cfg, store, temp->inst_c0, ins);
- store->cil_code = ins->cil_code;
- MONO_ADD_INS (bblock, store);
- NEW_TEMPLOAD (cfg, load, temp->inst_c0);
- load->cil_code = ins->cil_code;
- *sp++ = load;
- /*g_print ("found emulation for %d\n", ins->opcode);*/
+ *sp++ = emit_tree (cfg, bblock, ins);
}
ip++;
break;
if (cmethod->klass->parent == mono_defaults.array_class) {
NEW_METHODCONST (cfg, *sp, cmethod);
- temp = mono_emit_native_call (cfg, bblock, mono_array_new_va, fsig, sp, ip, FALSE);
+ temp = mono_emit_native_call (cfg, bblock, mono_array_new_va, mono_get_array_new_va_signature (fsig->param_count), sp, ip, FALSE);
+ cfg->flags |= MONO_CFG_HAS_VARARGS;
} else if (cmethod->string_ctor) {
/* we simply pass a null pointer */
!g_list_find (dont_inline, cmethod)) {
int costs;
MonoBasicBlock *ebblock;
- if ((costs = inline_method (cfg, cmethod, fsig, bblock, sp, ip, real_offset, dont_inline, &ebblock))) {
+ if ((costs = inline_method (cfg, cmethod, fsig, bblock, sp, ip, real_offset, dont_inline, &ebblock, FALSE))) {
ip += 5;
real_offset += 5;
iargs [0] = sp [0];
costs = inline_method (cfg, mono_isinst, mono_isinst->signature, bblock,
- iargs, ip, real_offset, dont_inline, &ebblock);
+ iargs, ip, real_offset, dont_inline, &ebblock, TRUE);
g_assert (costs > 0);
ins->inst_left = *sp;
ins->inst_newa_class = klass;
ins->cil_code = ip;
- *sp++ = ins;
+ *sp++ = emit_tree (cfg, bblock, ins);
ip += 5;
}
break;
iargs [0] = sp [0];
costs = inline_method (cfg, mono_castclass, mono_castclass->signature, bblock,
- iargs, ip, real_offset, dont_inline, &ebblock);
+ iargs, ip, real_offset, dont_inline, &ebblock, TRUE);
g_assert (costs > 0);
ins->inst_newa_class = klass;
ins->cil_code = ip;
- MONO_INST_NEW (cfg, add, CEE_ADD);
+ MONO_INST_NEW (cfg, add, OP_PADD);
NEW_ICONST (cfg, vtoffset, sizeof (MonoObject));
add->inst_left = ins;
add->inst_right = vtoffset;
ins->inst_newa_class = klass;
ins->cil_code = ip;
- MONO_INST_NEW (cfg, add, CEE_ADD);
+ MONO_INST_NEW (cfg, add, OP_PADD);
NEW_ICONST (cfg, vtoffset, sizeof (MonoObject));
add->inst_left = ins;
add->inst_right = vtoffset;
iargs [0] = sp [0];
costs = inline_method (cfg, mono_castclass, mono_castclass->signature, bblock,
- iargs, ip, real_offset, dont_inline, &ebblock);
+ iargs, ip, real_offset, dont_inline, &ebblock, TRUE);
g_assert (costs > 0);
ins->klass = klass;
ins->inst_newa_class = klass;
ins->cil_code = ip;
- *sp++ = ins;
+ *sp++ = emit_tree (cfg, bblock, ins);
ip += 5;
}
break;
if (cfg->opt & MONO_OPT_INLINE) {
costs = inline_method (cfg, stfld_wrapper, stfld_wrapper->signature, bblock,
- iargs, ip, real_offset, dont_inline, &ebblock);
+ iargs, ip, real_offset, dont_inline, &ebblock, TRUE);
g_assert (costs > 0);
ip += 5;
} else {
MonoInst *store;
NEW_ICONST (cfg, offset_ins, foffset);
- MONO_INST_NEW (cfg, ins, CEE_ADD);
+ MONO_INST_NEW (cfg, ins, OP_PADD);
ins->cil_code = ip;
ins->inst_left = *sp;
ins->inst_right = offset_ins;
NEW_ICONST (cfg, iargs [3], klass->valuetype ? field->offset - sizeof (MonoObject) : field->offset);
if (cfg->opt & MONO_OPT_INLINE) {
costs = inline_method (cfg, ldfld_wrapper, ldfld_wrapper->signature, bblock,
- iargs, ip, real_offset, dont_inline, &ebblock);
+ iargs, ip, real_offset, dont_inline, &ebblock, TRUE);
g_assert (costs > 0);
ip += 5;
}
} else {
NEW_ICONST (cfg, offset_ins, foffset);
- MONO_INST_NEW (cfg, ins, CEE_ADD);
+ MONO_INST_NEW (cfg, ins, OP_PADD);
ins->cil_code = ip;
ins->inst_left = *sp;
ins->inst_right = offset_ins;
*sp++ = ins;
ip += 5;
break;
- case CEE_LDELEM: {
+ case CEE_LDELEM_ANY: {
MonoInst *load;
CHECK_STACK (2);
sp -= 2;
inline_costs += 1;
break;
}
- case CEE_STELEM: {
+ case CEE_STELEM_ANY: {
MonoInst *load;
/*
* translate to:
klass = mono_class_get_full (image, token, generic_context);
mono_class_init (klass);
if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
+ MonoMethod* helper = mono_marshal_get_stelemref ();
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);
+
+ mono_emit_method_call_spilled (cfg, bblock, helper, helper->signature, iargs, ip, NULL);
} else {
NEW_LDELEMA (cfg, load, sp, klass);
load->cil_code = ip;
}
case CEE_STELEM_REF: {
MonoInst *iargs [3];
+ MonoMethod* helper = mono_marshal_get_stelemref ();
CHECK_STACK (3);
sp -= 3;
iargs [1] = sp [1];
iargs [0] = sp [0];
- mono_emit_jit_icall (cfg, bblock, helper_stelem_ref, iargs, ip);
+ mono_emit_method_call_spilled (cfg, bblock, helper, helper->signature, iargs, ip, NULL);
/*
MonoInst *group;
} else {
if ((ip [5] == CEE_CALL) && (cmethod = mono_get_method_full (image, read32 (ip + 6), NULL, generic_context)) &&
(cmethod->klass == mono_defaults.monotype_class->parent) &&
- (strcmp (cmethod->name, "GetTypeFromHandle") == 0)) {
+ (strcmp (cmethod->name, "GetTypeFromHandle") == 0) &&
+ ((g_hash_table_lookup (bbhash, ip + 5) == NULL) ||
+ (g_hash_table_lookup (bbhash, ip + 5) == bblock))) {
MonoClass *tclass = mono_class_from_mono_type (handle);
mono_class_init (tclass);
if (mono_compile_aot)
ins->klass = cmethod->klass;
ip += 5;
} else {
+ MonoInst *store, *addr, *vtvar;
+
if (mono_compile_aot)
NEW_LDTOKENCONST (cfg, ins, image, n);
else
NEW_PCONST (cfg, ins, handle);
- ins->type = STACK_VTYPE;
- ins->klass = handle_class;
+ vtvar = mono_compile_create_var (cfg, &handle_class->byval_arg, OP_LOCAL);
+ NEW_TEMPLOADA (cfg, addr, vtvar->inst_c0);
+ NEW_INDSTORE (cfg, store, addr, ins, &mono_defaults.int_class->byval_arg);
+ MONO_ADD_INS (bblock, store);
+ NEW_TEMPLOAD (cfg, ins, vtvar->inst_c0);
}
}
case CEE_SUB_OVF_UN:
CHECK_STACK (2);
ADD_BINOP (*ip);
+ if (mono_find_jit_opcode_emulation (ins->opcode)) {
+ --sp;
+ *sp++ = emit_tree (cfg, bblock, ins);
+ }
ip++;
break;
case CEE_ENDFINALLY:
CHECK_OPSIZE (2);
switch (ip [1]) {
- case CEE_MONO_FUNC1: {
+ case CEE_MONO_ICALL: {
int temp;
- gpointer func = NULL;
- CHECK_STACK (1);
- sp--;
+ gpointer func;
+ MonoJitICallInfo *info;
- CHECK_OPSIZE (3);
- switch (ip [2]) {
- case MONO_MARSHAL_CONV_STR_LPWSTR:
- func = mono_string_to_utf16;
- break;
- case MONO_MARSHAL_CONV_LPWSTR_STR:
- func = mono_string_from_utf16;
- break;
- case MONO_MARSHAL_CONV_LPSTR_STR:
- func = mono_string_new_wrapper;
- break;
- case MONO_MARSHAL_CONV_STR_LPTSTR:
- case MONO_MARSHAL_CONV_STR_LPSTR:
- func = mono_string_to_utf8;
- break;
- case MONO_MARSHAL_CONV_STR_BSTR:
- func = mono_string_to_bstr;
- break;
- case MONO_MARSHAL_CONV_STR_TBSTR:
- case MONO_MARSHAL_CONV_STR_ANSIBSTR:
- func = mono_string_to_ansibstr;
- break;
- case MONO_MARSHAL_CONV_SB_LPSTR:
- case MONO_MARSHAL_CONV_SB_LPTSTR:
- func = mono_string_builder_to_utf8;
- break;
- case MONO_MARSHAL_CONV_SB_LPWSTR:
- func = mono_string_builder_to_utf16;
- break;
- case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
- func = mono_array_to_savearray;
- break;
- case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
- func = mono_array_to_lparray;
- break;
- case MONO_MARSHAL_CONV_DEL_FTN:
- func = mono_delegate_to_ftnptr;
- break;
- case MONO_MARSHAL_CONV_STRARRAY_STRLPARRAY:
- func = mono_marshal_string_array;
- break;
- case MONO_MARSHAL_CONV_STRARRAY_STRWLPARRAY:
- func = mono_marshal_string_array_to_unicode;
- break;
- default:
- g_warning ("unknown conversion %d\n", ip [2]);
- g_assert_not_reached ();
- }
-
- temp = mono_emit_jit_icall (cfg, bblock, func, sp, ip);
- NEW_TEMPLOAD (cfg, *sp, temp);
- sp++;
+ token = read32 (ip + 2);
+ func = mono_method_get_wrapper_data (method, token);
+ info = mono_find_jit_icall_by_addr (func);
+ g_assert (info);
- ip += 3;
- inline_costs += 10 * num_calls++;
- break;
- }
- case CEE_MONO_PROC2: {
- gpointer func = NULL;
- CHECK_STACK (2);
- sp -= 2;
+ CHECK_STACK (info->sig->param_count);
+ sp -= info->sig->param_count;
- CHECK_OPSIZE (3);
- switch (ip [2]) {
- case MONO_MARSHAL_CONV_LPSTR_SB:
- case MONO_MARSHAL_CONV_LPTSTR_SB:
- func = mono_string_utf8_to_builder;
- break;
- case MONO_MARSHAL_CONV_LPWSTR_SB:
- func = mono_string_utf16_to_builder;
- break;
- case MONO_MARSHAL_FREE_ARRAY:
- func = mono_marshal_free_array;
- break;
- default:
- g_assert_not_reached ();
+ temp = mono_emit_jit_icall (cfg, bblock, info->func, sp, ip);
+ if (!MONO_TYPE_IS_VOID (info->sig->ret)) {
+ NEW_TEMPLOAD (cfg, *sp, temp);
+ sp++;
}
- mono_emit_jit_icall (cfg, bblock, func, sp, ip);
- ip += 3;
+ ip += 6;
inline_costs += 10 * num_calls++;
- break;
- }
- case CEE_MONO_PROC3: {
- gpointer func = NULL;
- CHECK_STACK (3);
- sp -= 3;
- CHECK_OPSIZE (3);
- switch (ip [2]) {
- case MONO_MARSHAL_CONV_STR_BYVALSTR:
- func = mono_string_to_byvalstr;
- break;
- case MONO_MARSHAL_CONV_STR_BYVALWSTR:
- func = mono_string_to_byvalwstr;
- break;
- default:
- g_assert_not_reached ();
- }
-
- mono_emit_jit_icall (cfg, bblock, func, sp, ip);
- ip += 3;
- inline_costs += 10 * num_calls++;
break;
}
- case CEE_MONO_FREE:
- CHECK_STACK (1);
- sp -= 1;
- mono_emit_jit_icall (cfg, bblock, g_free, sp, ip);
- ip += 2;
- inline_costs += 10 * num_calls++;
- break;
case CEE_MONO_LDPTR:
CHECK_STACK_OVF (1);
CHECK_OPSIZE (6);
ins->inst_left = *sp;
ins->inst_newa_class = klass;
ins->cil_code = ip;
- *sp++ = ins;
+ *sp++ = emit_tree (cfg, bblock, ins);
ip += 6;
break;
}
+ case CEE_MONO_SAVE_LMF:
+ case CEE_MONO_RESTORE_LMF:
+#ifdef MONO_ARCH_HAVE_LMF_OPS
+ MONO_INST_NEW (cfg, ins, (ip [1] == CEE_MONO_SAVE_LMF) ? OP_SAVE_LMF : OP_RESTORE_LMF);
+ MONO_ADD_INS (bblock, ins);
+ cfg->need_lmf_area = TRUE;
+#endif
+ ip += 2;
+ break;
default:
g_error ("opcode 0x%02x 0x%02x not handled", MONO_CUSTOM_PREFIX, ip [1]);
break;
cmp->cil_code = ip;
type_from_op (cmp);
CHECK_TYPE (cmp);
- cmp->opcode = OP_COMPARE;
+ if ((sp [0]->type == STACK_I8) || ((sizeof (gpointer) == 8) && ((sp [0]->type == STACK_PTR) || (sp [0]->type == STACK_OBJ) || (sp [0]->type == STACK_MP))))
+ cmp->opcode = OP_LCOMPARE;
+ else
+ cmp->opcode = OP_COMPARE;
ins->cil_code = ip;
ins->type = STACK_I4;
ins->inst_i0 = cmp;
*sp++ = ins;
+ /* spill it to reduce the expression complexity
+ * and workaround bug 54209
+ */
+ if (cmp->inst_left->type == STACK_I8) {
+ --sp;
+ *sp++ = emit_tree (cfg, bblock, ins);
+ }
ip += 2;
break;
}
MONO_INST_NEW (cfg, ins, OP_LOCALLOC);
ins->inst_left = *sp;
ins->cil_code = ip;
+ ins->type = STACK_MP;
cfg->flags |= MONO_CFG_HAS_ALLOCA;
if (header->init_locals)
ip += 2;
break;
case CEE_TAIL_:
- ins_flag |= MONO_INST_TAILCALL;
+ ins_flag |= MONO_INST_TAILCALL;
+ cfg->flags |= MONO_CFG_HAS_TAIL;
/* Can't inline tail calls at this time */
inline_costs += 100000;
ip += 2;
printf ("\n");
}
+#define make_icall_sig mono_create_icall_signature
+
static void
create_helper_signature (void)
{
- /* FIXME: set call conv */
/* MonoArray * mono_array_new (MonoDomain *domain, MonoClass *klass, gint32 len) */
- helper_sig_newarr = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
- helper_sig_newarr->params [0] = helper_sig_newarr->params [1] = &mono_defaults.int_class->byval_arg;
- helper_sig_newarr->ret = &mono_defaults.object_class->byval_arg;
- helper_sig_newarr->params [2] = &mono_defaults.int32_class->byval_arg;
- helper_sig_newarr->pinvoke = 1;
+ helper_sig_newarr = make_icall_sig ("object ptr ptr int32");
/* MonoArray * mono_array_new_specific (MonoVTable *vtable, guint32 len) */
- helper_sig_newarr_specific = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
- helper_sig_newarr_specific->params [0] = &mono_defaults.int_class->byval_arg;
- helper_sig_newarr_specific->params [1] = &mono_defaults.int32_class->byval_arg;
- helper_sig_newarr_specific->ret = &mono_defaults.object_class->byval_arg;
- helper_sig_newarr_specific->pinvoke = 1;
+ helper_sig_newarr_specific = make_icall_sig ("object ptr int32");
/* MonoObject * mono_object_new (MonoDomain *domain, MonoClass *klass) */
- helper_sig_object_new = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
- helper_sig_object_new->params [0] = helper_sig_object_new->params [1] = &mono_defaults.int_class->byval_arg;
- helper_sig_object_new->ret = &mono_defaults.object_class->byval_arg;
- helper_sig_object_new->pinvoke = 1;
+ helper_sig_object_new = make_icall_sig ("object ptr ptr");
/* MonoObject * mono_object_new_specific (MonoVTable *vtable) */
- helper_sig_object_new_specific = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
- helper_sig_object_new_specific->params [0] = &mono_defaults.int_class->byval_arg;
- helper_sig_object_new_specific->ret = &mono_defaults.object_class->byval_arg;
- helper_sig_object_new_specific->pinvoke = 1;
+ helper_sig_object_new_specific = make_icall_sig ("object ptr");
/* void* mono_method_compile (MonoMethod*) */
- helper_sig_compile = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
- helper_sig_compile->params [0] = helper_sig_compile->ret = &mono_defaults.int_class->byval_arg;
- helper_sig_compile->pinvoke = 1;
+ helper_sig_compile = make_icall_sig ("ptr ptr");
/* void* mono_ldvirtfn (MonoObject *, MonoMethod*) */
- helper_sig_compile_virt = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
- helper_sig_compile_virt->params [0] = &mono_defaults.object_class->byval_arg;
- helper_sig_compile_virt->params [1] = helper_sig_compile_virt->ret = &mono_defaults.int_class->byval_arg;
- helper_sig_compile_virt->pinvoke = 1;
+ helper_sig_compile_virt = make_icall_sig ("ptr object ptr");
/* MonoString* mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 str_index) */
- helper_sig_ldstr = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
- helper_sig_ldstr->params [0] = helper_sig_ldstr->params [1] = &mono_defaults.int_class->byval_arg;
- helper_sig_ldstr->params [2] = &mono_defaults.int32_class->byval_arg;
- helper_sig_ldstr->ret = &mono_defaults.object_class->byval_arg;
- helper_sig_ldstr->pinvoke = 1;
+ helper_sig_ldstr = make_icall_sig ("object ptr ptr int32");
/* MonoDomain *mono_domain_get (void) */
- helper_sig_domain_get = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
- 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;
-
- /* void* stelem_ref_check (MonoArray *, MonoObject *) */
- helper_sig_stelem_ref_check = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
- helper_sig_stelem_ref_check->params [0] = &mono_defaults.array_class->byval_arg;
- helper_sig_stelem_ref_check->params [1] = &mono_defaults.object_class->byval_arg;
- helper_sig_stelem_ref_check->ret = &mono_defaults.void_class->byval_arg;
- helper_sig_stelem_ref_check->pinvoke = 1;
+ helper_sig_domain_get = make_icall_sig ("ptr");
+
+ /* void stelem_ref (MonoArray *, int index, MonoObject *) */
+ helper_sig_stelem_ref = make_icall_sig ("void ptr int32 object");
+
+ /* void stelem_ref_check (MonoArray *, MonoObject *) */
+ helper_sig_stelem_ref_check = make_icall_sig ("void object object");
/* 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] =
- &mono_defaults.int64_class->byval_arg;
- helper_sig_long_long_long->ret = &mono_defaults.int64_class->byval_arg;
- helper_sig_long_long_long->pinvoke = 1;
+ helper_sig_long_long_long = make_icall_sig ("long long long");
/* object amethod (intptr) */
- helper_sig_obj_ptr = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
- helper_sig_obj_ptr->params [0] = &mono_defaults.int_class->byval_arg;
- helper_sig_obj_ptr->ret = &mono_defaults.object_class->byval_arg;
- helper_sig_obj_ptr->pinvoke = 1;
+ helper_sig_obj_ptr = make_icall_sig ("object ptr");
+
+ helper_sig_obj_ptr_ptr = make_icall_sig ("object ptr ptr");
+
+ helper_sig_obj_obj_ptr_ptr = make_icall_sig ("object object ptr ptr");
+
+ helper_sig_void_void = make_icall_sig ("void");
/* void amethod (intptr) */
- helper_sig_void_ptr = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
- helper_sig_void_ptr->params [0] = &mono_defaults.int_class->byval_arg;
- helper_sig_void_ptr->ret = &mono_defaults.void_class->byval_arg;
- helper_sig_void_ptr->pinvoke = 1;
+ helper_sig_void_ptr = make_icall_sig ("void ptr");
/* void amethod (MonoObject *obj) */
- helper_sig_void_obj = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
- helper_sig_void_obj->params [0] = &mono_defaults.object_class->byval_arg;
- helper_sig_void_obj->ret = &mono_defaults.void_class->byval_arg;
- helper_sig_void_obj->pinvoke = 1;
+ helper_sig_void_obj = make_icall_sig ("void object");
+
+ /* void amethod (MonoObject *obj, void *ptr, int i) */
+ helper_sig_void_obj_ptr_int = make_icall_sig ("void object ptr int");
+
+ helper_sig_void_obj_ptr_ptr_obj = make_icall_sig ("void object ptr ptr object");
/* intptr amethod (void) */
- helper_sig_ptr_void = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
- helper_sig_ptr_void->ret = &mono_defaults.int_class->byval_arg;
- helper_sig_ptr_void->pinvoke = 1;
+ helper_sig_ptr_void = make_icall_sig ("ptr");
/* object amethod (void) */
- helper_sig_obj_void = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
- helper_sig_obj_void->ret = &mono_defaults.object_class->byval_arg;
- helper_sig_obj_void->pinvoke = 1;
+ helper_sig_obj_void = make_icall_sig ("object");
/* void amethod (intptr, intptr) */
- helper_sig_void_ptr_ptr = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
- helper_sig_void_ptr_ptr->params [0] = &mono_defaults.int_class->byval_arg;
- helper_sig_void_ptr_ptr->params [1] = &mono_defaults.int_class->byval_arg;
- helper_sig_void_ptr_ptr->ret = &mono_defaults.void_class->byval_arg;
- helper_sig_void_ptr_ptr->pinvoke = 1;
+ helper_sig_void_ptr_ptr = make_icall_sig ("void ptr ptr");
/* void amethod (intptr, intptr, intptr) */
- helper_sig_void_ptr_ptr_ptr = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
- helper_sig_void_ptr_ptr_ptr->params [0] = &mono_defaults.int_class->byval_arg;
- helper_sig_void_ptr_ptr_ptr->params [1] = &mono_defaults.int_class->byval_arg;
- helper_sig_void_ptr_ptr_ptr->params [2] = &mono_defaults.int_class->byval_arg;
- helper_sig_void_ptr_ptr_ptr->ret = &mono_defaults.void_class->byval_arg;
- helper_sig_void_ptr_ptr_ptr->pinvoke = 1;
+ helper_sig_void_ptr_ptr_ptr = make_icall_sig ("void ptr ptr ptr");
/* intptr amethod (intptr, intptr) */
- helper_sig_ptr_ptr_ptr = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
- helper_sig_ptr_ptr_ptr->params [0] = &mono_defaults.int_class->byval_arg;
- helper_sig_ptr_ptr_ptr->params [1] = &mono_defaults.int_class->byval_arg;
- helper_sig_ptr_ptr_ptr->ret = &mono_defaults.int_class->byval_arg;
- helper_sig_ptr_ptr_ptr->pinvoke = 1;
+ helper_sig_ptr_ptr_ptr = make_icall_sig ("ptr ptr ptr");
/* IntPtr amethod (object) */
- helper_sig_ptr_obj = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
- helper_sig_ptr_obj->params [0] = &mono_defaults.object_class->byval_arg;
- helper_sig_ptr_obj->ret = &mono_defaults.int_class->byval_arg;
- helper_sig_ptr_obj->pinvoke = 1;
+ helper_sig_ptr_obj = make_icall_sig ("ptr object");
+
+ /* IntPtr amethod (object, int) */
+ helper_sig_ptr_obj_int = make_icall_sig ("ptr object int");
/* IntPtr amethod (int) */
- helper_sig_ptr_int = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
- helper_sig_ptr_int->params [0] = &mono_defaults.int32_class->byval_arg;
- helper_sig_ptr_int->ret = &mono_defaults.int_class->byval_arg;
- helper_sig_ptr_int->pinvoke = 1;
+ helper_sig_ptr_int = make_icall_sig ("ptr int32");
/* long amethod (long, guint32) */
- helper_sig_long_long_int = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
- helper_sig_long_long_int->params [0] = &mono_defaults.int64_class->byval_arg;
- helper_sig_long_long_int->params [1] = &mono_defaults.int32_class->byval_arg;
- helper_sig_long_long_int->ret = &mono_defaults.int64_class->byval_arg;
- helper_sig_long_long_int->pinvoke = 1;
+ helper_sig_long_long_int = make_icall_sig ("long long int32");
/* ulong amethod (double) */
- helper_sig_ulong_double = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
- helper_sig_ulong_double->params [0] = &mono_defaults.double_class->byval_arg;
- helper_sig_ulong_double->ret = &mono_defaults.uint64_class->byval_arg;
- helper_sig_ulong_double->pinvoke = 1;
+ helper_sig_ulong_double = make_icall_sig ("ulong double");
/* long amethod (double) */
- helper_sig_long_double = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
- helper_sig_long_double->params [0] = &mono_defaults.double_class->byval_arg;
- helper_sig_long_double->ret = &mono_defaults.int64_class->byval_arg;
- helper_sig_long_double->pinvoke = 1;
+ helper_sig_long_double = make_icall_sig ("long double");
/* double amethod (long) */
- helper_sig_double_long = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
- helper_sig_double_long->params [0] = &mono_defaults.int64_class->byval_arg;
- helper_sig_double_long->ret = &mono_defaults.double_class->byval_arg;
- helper_sig_double_long->pinvoke = 1;
+ helper_sig_double_long = make_icall_sig ("double long");
/* double amethod (int) */
- helper_sig_double_int = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
- helper_sig_double_int->params [0] = &mono_defaults.int32_class->byval_arg;
- helper_sig_double_int->ret = &mono_defaults.double_class->byval_arg;
- helper_sig_double_int->pinvoke = 1;
+ helper_sig_double_int = make_icall_sig ("double int32");
/* float amethod (long) */
- helper_sig_float_long = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
- helper_sig_float_long->params [0] = &mono_defaults.int64_class->byval_arg;
- helper_sig_float_long->ret = &mono_defaults.single_class->byval_arg;
- helper_sig_float_long->pinvoke = 1;
+ helper_sig_float_long = make_icall_sig ("float long");
/* double amethod (double, double) */
- helper_sig_double_double_double = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
- helper_sig_double_double_double->params [0] = &mono_defaults.double_class->byval_arg;
- helper_sig_double_double_double->params [1] = &mono_defaults.double_class->byval_arg;
- helper_sig_double_double_double->ret = &mono_defaults.double_class->byval_arg;
- helper_sig_double_double_double->pinvoke = 1;
+ helper_sig_double_double_double = make_icall_sig ("double double double");
/* uint amethod (double) */
- helper_sig_uint_double = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
- helper_sig_uint_double->params [0] = &mono_defaults.double_class->byval_arg;
- helper_sig_uint_double->ret = &mono_defaults.uint32_class->byval_arg;
- helper_sig_uint_double->pinvoke = 1;
+ helper_sig_uint_double = make_icall_sig ("uint32 double");
/* int amethod (double) */
- helper_sig_int_double = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
- helper_sig_int_double->params [0] = &mono_defaults.double_class->byval_arg;
- helper_sig_int_double->ret = &mono_defaults.int32_class->byval_arg;
- helper_sig_int_double->pinvoke = 1;
+ helper_sig_int_double = make_icall_sig ("int32 double");
/* void initobj (intptr, int size) */
- helper_sig_initobj = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
- helper_sig_initobj->params [0] = &mono_defaults.int_class->byval_arg;
- helper_sig_initobj->params [1] = &mono_defaults.int32_class->byval_arg;
- helper_sig_initobj->ret = &mono_defaults.void_class->byval_arg;
- helper_sig_initobj->pinvoke = 1;
+ helper_sig_initobj = make_icall_sig ("void ptr int32");
/* void memcpy (intptr, intptr, int size) */
- helper_sig_memcpy = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
- helper_sig_memcpy->params [0] = &mono_defaults.int_class->byval_arg;
- helper_sig_memcpy->params [1] = &mono_defaults.int_class->byval_arg;
- helper_sig_memcpy->params [2] = &mono_defaults.int32_class->byval_arg;
- helper_sig_memcpy->ret = &mono_defaults.void_class->byval_arg;
- helper_sig_memcpy->pinvoke = 1;
+ helper_sig_memcpy = make_icall_sig ("void ptr ptr int32");
/* void memset (intptr, int val, int size) */
- helper_sig_memset = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
- helper_sig_memset->params [0] = &mono_defaults.int_class->byval_arg;
- helper_sig_memset->params [1] = &mono_defaults.int32_class->byval_arg;
- helper_sig_memset->params [2] = &mono_defaults.int32_class->byval_arg;
- helper_sig_memset->ret = &mono_defaults.void_class->byval_arg;
- helper_sig_memset->pinvoke = 1;
-
- helper_sig_class_init_trampoline = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
- helper_sig_class_init_trampoline->ret = &mono_defaults.void_class->byval_arg;
- helper_sig_class_init_trampoline->pinvoke = 1;
-}
-
-static GHashTable *jit_icall_hash_name = NULL;
-static GHashTable *jit_icall_hash_addr = NULL;
-
-MonoJitICallInfo *
-mono_find_jit_icall_by_name (const char *name)
-{
- MonoJitICallInfo *info;
- g_assert (jit_icall_hash_name);
-
- //printf ("lookup addr %s %p\n", name, g_hash_table_lookup (jit_icall_hash_name, name));
- EnterCriticalSection (&trampoline_hash_mutex);
- info = g_hash_table_lookup (jit_icall_hash_name, name);
- LeaveCriticalSection (&trampoline_hash_mutex);
- return info;
-}
-
-MonoJitICallInfo *
-mono_find_jit_icall_by_addr (gconstpointer addr)
-{
- MonoJitICallInfo *info;
- g_assert (jit_icall_hash_addr);
+ helper_sig_memset = make_icall_sig ("void ptr int32 int32");
- EnterCriticalSection (&trampoline_hash_mutex);
- info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
- LeaveCriticalSection (&trampoline_hash_mutex);
-
- return info;
+ helper_sig_class_init_trampoline = make_icall_sig ("void");
}
gconstpointer
/* Must be domain neutral since there is only one copy */
code = mono_jit_compile_method_with_opt (wrapper, default_opt | MONO_OPT_SHARED);
- EnterCriticalSection (&trampoline_hash_mutex);
if (!callinfo->wrapper) {
callinfo->wrapper = code;
- g_hash_table_insert (jit_icall_hash_addr, (gpointer)callinfo->wrapper, callinfo);
+ mono_register_jit_icall_wrapper (callinfo, code);
+ mono_debug_add_icall_wrapper (wrapper, callinfo);
}
- LeaveCriticalSection (&trampoline_hash_mutex);
g_free (name);
return callinfo->wrapper;
}
-MonoJitICallInfo *
-mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
-{
- MonoJitICallInfo *info;
-
- g_assert (func);
- g_assert (name);
-
- EnterCriticalSection (&trampoline_hash_mutex);
-
- if (!jit_icall_hash_name) {
- jit_icall_hash_name = g_hash_table_new (g_str_hash, g_str_equal);
- jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
- }
-
- if (g_hash_table_lookup (jit_icall_hash_name, name)) {
- g_warning ("jit icall already defined \"%s\"\n", name);
- g_assert_not_reached ();
- }
-
- info = g_new (MonoJitICallInfo, 1);
-
- info->name = name;
- info->func = func;
- info->sig = sig;
-
- if (is_save
-#ifdef MONO_USE_EXC_TABLES
- || mono_arch_has_unwind_info (func)
-#endif
- ) {
- info->wrapper = func;
- } else {
- info->wrapper = NULL;
- }
-
- g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
- g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
-
- LeaveCriticalSection (&trampoline_hash_mutex);
- return info;
-}
-
gpointer
mono_create_class_init_trampoline (MonoVTable *vtable)
{
* trampoline address, so we save it here.
*/
- mono_jit_info_table_add (mono_root_domain, ji);
+ mono_jit_info_table_add (mono_get_root_domain (), ji);
if (!jump_trampoline_hash)
jump_trampoline_hash = g_hash_table_new (NULL, NULL);
for (i = 0; i < cfg->num_bblocks; ++i) {
bb = cfg->bblocks [i];
- if (bb->cil_code) {
+ /*if (bb->cil_code) {
char* code1, *code2;
code1 = mono_disasm_code_one (NULL, cfg->method, bb->cil_code, NULL);
if (bb->last_ins->cil_code)
code = g_strdup_printf ("%s -> %s", code1, code2);
g_free (code1);
g_free (code2);
- } else
+ } else*/
code = g_strdup ("\n");
g_print ("\nBB%d DFN%d (len: %d): %s", bb->block_num, i, bb->cil_length, code);
if (bb->code) {
{
//mono_mempool_stats (cfg->mempool);
g_hash_table_destroy (cfg->bb_hash);
+ mono_free_loop_info (cfg);
if (cfg->rs)
mono_regstate_free (cfg->rs);
if (cfg->spvars)
g_free (cfg);
}
+#ifdef HAVE_KW_THREAD
+static __thread gpointer mono_lmf_addr;
+#endif
+
MonoLMF **
mono_get_lmf_addr (void)
{
+#ifdef HAVE_KW_THREAD
+ return mono_lmf_addr;
+#else
MonoJitTlsData *jit_tls;
if ((jit_tls = TlsGetValue (mono_jit_tls_id)))
g_assert_not_reached ();
return NULL;
+#endif
}
/**
jit_tls->lmf = jit_tls->first_lmf = lmf;
+#ifdef HAVE_KW_THREAD
+ mono_lmf_addr = &jit_tls->lmf;
+#endif
+
mono_arch_setup_jit_tls_data (jit_tls);
return jit_tls;
target = handle;
break;
}
+ case MONO_PATCH_INFO_BB_OVF:
+ case MONO_PATCH_INFO_EXC_OVF:
+ break;
default:
g_assert_not_reached ();
}
&& tree->inst_left->inst_left->type == STACK_I4
&& (tree->inst_right->opcode == CEE_CONV_I8
|| tree->inst_right->opcode == CEE_CONV_U8)
- && tree->inst_right->inst_left->type == STACK_I4) {
+ && tree->inst_right->inst_left->type == STACK_I4
+ && tree->inst_left->opcode == tree->inst_right->opcode) {
tree->opcode = (tree->inst_left->opcode == CEE_CONV_I8 ? OP_BIGMUL: OP_BIGMUL_UN);
tree->inst_left = tree->inst_left->inst_left;
tree->inst_right = tree->inst_right->inst_left;
bbn = bb->out_bb [0];
/* conditional branches where true and false targets are the same can be also replaced with CEE_BR */
- if (bb->last_ins && MONO_IS_COND_BRANCH (bb->last_ins->opcode)) {
+ if (bb->last_ins && MONO_IS_COND_BRANCH_OP (bb->last_ins)) {
bb->last_ins->opcode = CEE_BR;
bb->last_ins->inst_target_bb = bb->last_ins->inst_true_bb;
changed = TRUE;
bbn->code->inst_target_bb->region == bb->region) {
if (cfg->verbose_level > 2)
- g_print ("in %s branch to branch triggered %d -> %d\n", cfg->method->name,
- bb->block_num, bbn->block_num);
-
- replace_basic_block (bb, bb->out_bb [0], bbn->code->inst_target_bb);
+ g_print ("in %s branch to branch triggered %d -> %d -> %d\n", cfg->method->name,
+ bb->block_num, bbn->block_num, bbn->code->inst_target_bb->block_num);
+
+ replace_in_block (bbn, bb, NULL);
+ replace_out_block (bb, bbn, bbn->code->inst_target_bb);
+ link_bblock (cfg, bb, bbn->code->inst_target_bb);
bb->last_ins->inst_target_bb = bbn->code->inst_target_bb;
changed = TRUE;
break;
}
}
} else if (bb->out_count == 2) {
- if (bb->last_ins && MONO_IS_COND_BRANCH (bb->last_ins->opcode)) {
+ if (bb->last_ins && MONO_IS_COND_BRANCH_NOFP (bb->last_ins)) {
bbn = bb->last_ins->inst_true_bb;
if (bb->region == bbn->region && bbn->code && bbn->code->opcode == CEE_BR &&
bbn->code->inst_target_bb->region == bb->region) {
OP_LBNE_UN, OP_LBLT, OP_LBLE, OP_LBGT, OP_LBGE,
OP_LBEQ, OP_LBLT_UN, OP_LBLE_UN, OP_LBGT_UN, OP_LBGE_UN
};
+ static const int reverse_imap [] = {
+ OP_IBNE_UN, OP_IBLT, OP_IBLE, OP_IBGT, OP_IBGE,
+ OP_IBEQ, OP_IBLT_UN, OP_IBLE_UN, OP_IBGT_UN, OP_IBGE_UN
+ };
MonoBasicBlock *bb;
cfg->rs = mono_regstate_new ();
for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
- if (bb->last_ins && MONO_IS_COND_BRANCH (bb->last_ins->opcode) &&
+ if (bb->last_ins && MONO_IS_COND_BRANCH_OP (bb->last_ins) &&
bb->next_bb != bb->last_ins->inst_false_bb) {
- if (bb->next_bb == bb->last_ins->inst_true_bb) {
+ /* we are careful when inverting, since bugs like #59580
+ * could show up when dealing with NaNs.
+ */
+ if (MONO_IS_COND_BRANCH_NOFP(bb->last_ins) && bb->next_bb == bb->last_ins->inst_true_bb) {
MonoBasicBlock *tmp = bb->last_ins->inst_true_bb;
bb->last_ins->inst_true_bb = bb->last_ins->inst_false_bb;
bb->last_ins->inst_false_bb = tmp;
bb->last_ins->opcode = reverse_fmap [bb->last_ins->opcode - OP_FBEQ];
} else if (bb->last_ins->opcode >= OP_LBEQ && bb->last_ins->opcode <= OP_LBLT_UN) {
bb->last_ins->opcode = reverse_lmap [bb->last_ins->opcode - OP_LBEQ];
+ } else if (bb->last_ins->opcode >= OP_IBEQ && bb->last_ins->opcode <= OP_IBLT_UN) {
+ bb->last_ins->opcode = reverse_imap [bb->last_ins->opcode - OP_IBEQ];
}
} else {
MonoInst *inst = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst));
#else
/* fixme: add all optimizations which requires SSA */
- if (cfg->opt & (MONO_OPT_DEADCE)) {
+ if (cfg->opt & (MONO_OPT_DEADCE | MONO_OPT_ABCREM)) {
if (!(cfg->comp_done & MONO_COMP_SSA) && !header->num_clauses && !cfg->disable_ssa) {
mono_local_cprop (cfg);
mono_ssa_compute (cfg);
//mono_ssa_strength_reduction (cfg);
+ if ((cfg->flags & MONO_CFG_HAS_LDELEMA) && (cfg->opt & MONO_OPT_ABCREM))
+ mono_perform_abc_removal (cfg);
+
mono_ssa_remove (cfg);
if (cfg->opt & MONO_OPT_BRANCH)
if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
mono_lookup_pinvoke_call (method, NULL, NULL);
}
-#ifdef MONO_USE_EXC_TABLES
- if (mono_method_blittable (method)) {
- return method->addr;
- } else {
-#endif
nm = mono_marshal_get_native_wrapper (method);
return mono_compile_method (nm);
//if (mono_debug_format != MONO_DEBUG_FORMAT_NONE)
//mono_debug_add_wrapper (method, nm);
-#ifdef MONO_USE_EXC_TABLES
- }
-#endif
} else if ((method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
const char *name = method->name;
MonoMethod *nm;
MonoJitInfo *info;
gpointer p;
- if (default_opt & MONO_OPT_SHARED)
- target_domain = mono_root_domain;
+ if (opt & MONO_OPT_SHARED)
+ target_domain = mono_get_root_domain ();
else
target_domain = domain;
if (! ((domain != target_domain) && !info->domain_neutral)) {
mono_domain_unlock (target_domain);
mono_jit_stats.methods_lookups++;
- mono_runtime_class_init (mono_class_vtable (target_domain, method->klass));
+ mono_runtime_class_init (mono_class_vtable (domain, method->klass));
return info->code_start;
}
}
MonoJitInfo *info;
if (default_opt & MONO_OPT_SHARED)
- target_domain = mono_root_domain;
+ target_domain = mono_get_root_domain ();
else
target_domain = domain;
mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
{
MonoMethod *invoke;
- MonoObject *(*runtime_invoke) (MonoObject *this, void **params, MonoObject **exc);
+ MonoObject *(*runtime_invoke) (MonoObject *this, void **params, MonoObject **exc, void* compiled_method);
+ void* compiled_method;
if (obj == NULL && !(method->flags & METHOD_ATTRIBUTE_STATIC) && !method->string_ctor && (method->wrapper_type == 0)) {
g_warning ("Ignoring invocation of an instance method on a NULL instance.\n");
invoke = mono_marshal_get_runtime_invoke (method);
runtime_invoke = mono_jit_compile_method (invoke);
- return runtime_invoke (obj, params, exc);
+
+ /* We need this here becuase mono_marshal_get_runtime_invoke can be place
+ * the helper method in System.Object and not the target class
+ */
+ mono_runtime_class_init (mono_class_vtable (mono_domain_get (), method->klass));
+
+ compiled_method = mono_jit_compile_method (method);
+ return runtime_invoke (obj, params, exc, compiled_method);
}
#ifdef PLATFORM_WIN32
#ifdef __sparc
#define GET_CONTEXT \
void *ctx = context;
-#elif defined(__ppc__) || defined (__powerpc__)
+#elif defined(sun) // Solaris x86
+#define GET_CONTEXT \
+ ucontext_t *uctx = context; \
+ struct sigcontext *ctx = (struct sigcontext *)&(uctx->uc_mcontext);
+#elif defined(__ppc__) || defined (__powerpc__) || defined (__s390__) || defined (MONO_ARCH_USE_SIGACTION)
#define GET_CONTEXT \
void *ctx = context;
#else
MonoException *exc;
MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
struct sigcontext *ctx = (struct sigcontext *)&(((ucontext_t*)context)->uc_mcontext);
-
+
/* Can't allocate memory using Boehm GC on altstack */
if (jit_tls->stack_size &&
((guint8*)info->si_addr >= (guint8*)jit_tls->end_of_stack - jit_tls->stack_size) &&
static void
SIG_HANDLER_SIGNATURE (sigusr1_signal_handler)
{
- MonoThread *thread;
- GET_CONTEXT
+ gboolean running_managed;
+ MonoException *exc;
- thread = mono_thread_current ();
-
- thread->abort_exc = mono_get_exception_thread_abort ();
+ GET_CONTEXT
- mono_arch_handle_exception (ctx, thread->abort_exc, FALSE);
+ running_managed = (mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context(ctx)) != NULL);
+
+ exc = mono_thread_request_interruption (running_managed);
+ if (!exc) return;
+
+ mono_arch_handle_exception (ctx, exc, FALSE);
}
static void
* but it seems to work well with our current exception
* handlers. If not we must call syscall directly instead
* of sigaction */
-
+
if (getenv ("MONO_DEBUG")) {
add_signal_handler (SIGINT, sigint_signal_handler);
}
#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
sa.sa_sigaction = sigsegv_signal_handler;
sigemptyset (&sa.sa_mask);
- sa.sa_flags = SA_SIGINFO | SA_STACK;
+ sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
g_assert (sigaction (SIGSEGV, &sa, NULL) != -1);
#else
add_signal_handler (SIGSEGV, sigsegv_signal_handler);
#endif
mono_install_stack_walk (mono_jit_walk_stack);
- domain = mono_init (filename);
+ domain = mono_init_from_assembly (filename, filename);
mono_init_icall ();
mono_add_internal_call ("System.Diagnostics.StackFrame::get_frame_info",
mono_register_jit_icall (mono_profiler_method_leave, "mono_profiler_method_leave", NULL, TRUE);
mono_register_jit_icall (mono_trace_enter_method, "mono_trace_enter_method", NULL, TRUE);
mono_register_jit_icall (mono_trace_leave_method, "mono_trace_leave_method", NULL, TRUE);
-
mono_register_jit_icall (mono_get_lmf_addr, "mono_get_lmf_addr", helper_sig_ptr_void, TRUE);
mono_register_jit_icall (mono_domain_get, "mono_domain_get", helper_sig_domain_get, TRUE);
- /* fixme: we cant hanlde vararg methods this way, because the signature is not constant */
+ /* fixme: we cant handle vararg methods this way, because the signature is not constant */
//mono_register_jit_icall (ves_array_element_address, "ves_array_element_address", NULL);
//mono_register_jit_icall (mono_array_new_va, "mono_array_new_va", NULL);
mono_register_jit_icall (mono_arch_get_throw_exception_by_name (), "mono_arch_throw_exception_by_name",
helper_sig_void_ptr, TRUE);
mono_register_jit_icall (mono_thread_get_pending_exception, "mono_thread_get_pending_exception", helper_sig_obj_void, FALSE);
+ mono_register_jit_icall (mono_thread_interruption_checkpoint, "mono_thread_interruption_checkpoint", helper_sig_void_void, FALSE);
+ mono_register_jit_icall (mono_load_remote_field_new, "mono_load_remote_field_new", helper_sig_obj_obj_ptr_ptr, FALSE);
+ mono_register_jit_icall (mono_store_remote_field_new, "mono_store_remote_field_new", helper_sig_void_obj_ptr_ptr_obj, FALSE);
/*
* NOTE, NOTE, NOTE, NOTE:
mono_register_opcode_emulation (OP_LREM, "__emul_lrem", helper_sig_long_long_long, mono_llrem, FALSE);
mono_register_opcode_emulation (OP_LREM_UN, "__emul_lrem_un", helper_sig_long_long_long, mono_llrem_un, FALSE);
+#ifndef MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
mono_register_opcode_emulation (OP_LSHL, "__emul_lshl", helper_sig_long_long_int, mono_lshl, TRUE);
mono_register_opcode_emulation (OP_LSHR, "__emul_lshr", helper_sig_long_long_int, mono_lshr, TRUE);
mono_register_opcode_emulation (OP_LSHR_UN, "__emul_lshr_un", helper_sig_long_long_int, mono_lshr_un, TRUE);
+#endif
mono_register_opcode_emulation (OP_FCONV_TO_U8, "__emul_fconv_to_u8", helper_sig_ulong_double, mono_fconv_u8, FALSE);
mono_register_opcode_emulation (OP_FCONV_TO_U4, "__emul_fconv_to_u4", helper_sig_uint_double, mono_fconv_u4, 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_string_from_utf16, "mono_string_from_utf16", helper_sig_obj_ptr, FALSE);
- mono_register_jit_icall (mono_string_new_wrapper, "mono_string_new_wrapper", helper_sig_obj_ptr, FALSE);
- mono_register_jit_icall (mono_string_to_utf8, "mono_string_to_utf8", helper_sig_ptr_obj, FALSE);
- mono_register_jit_icall (mono_string_to_bstr, "mono_string_to_bstr", helper_sig_ptr_obj, FALSE);
- mono_register_jit_icall (mono_string_to_ansibstr, "mono_string_to_ansibstr", helper_sig_ptr_obj, FALSE);
- mono_register_jit_icall (mono_string_builder_to_utf8, "mono_string_builder_to_utf8", helper_sig_ptr_obj, FALSE);
- mono_register_jit_icall (mono_string_builder_to_utf16, "mono_string_builder_to_utf16", helper_sig_ptr_obj, FALSE);
- mono_register_jit_icall (mono_array_to_savearray, "mono_array_to_savearray", helper_sig_ptr_obj, FALSE);
- mono_register_jit_icall (mono_array_to_lparray, "mono_array_to_lparray", helper_sig_ptr_obj, FALSE);
- mono_register_jit_icall (mono_delegate_to_ftnptr, "mono_delegate_to_ftnptr", helper_sig_ptr_obj, FALSE);
- mono_register_jit_icall (mono_marshal_string_array, "mono_marshal_string_array", helper_sig_ptr_obj, FALSE);
- mono_register_jit_icall (mono_marshal_string_array_to_unicode, "mono_marshal_string_array_to_unicode", helper_sig_ptr_obj, FALSE);
- mono_register_jit_icall (mono_string_utf8_to_builder, "mono_string_utf8_to_builder", helper_sig_void_ptr_ptr, FALSE);
- mono_register_jit_icall (mono_string_utf16_to_builder, "mono_string_utf16_to_builder", helper_sig_void_ptr_ptr, FALSE);
- mono_register_jit_icall (mono_marshal_free_array, "mono_marshal_free_array", helper_sig_void_ptr_ptr, FALSE);
- mono_register_jit_icall (mono_string_to_byvalstr, "mono_string_to_byvalstr", helper_sig_void_ptr_ptr_ptr, FALSE);
- mono_register_jit_icall (mono_string_to_byvalwstr, "mono_string_to_byvalwstr", helper_sig_void_ptr_ptr_ptr, FALSE);
- mono_register_jit_icall (g_free, "g_free", helper_sig_void_ptr, FALSE);
mono_register_jit_icall (mono_runtime_class_init, "mono_runtime_class_init", helper_sig_void_ptr, FALSE);
mono_register_jit_icall (mono_ldftn, "mono_ldftn", helper_sig_compile, FALSE);
mono_register_jit_icall (mono_ldftn_nosync, "mono_ldftn_nosync", helper_sig_compile, FALSE);
static void
mono_precompile_assembly (MonoAssembly *ass, void *user_data)
{
- MonoImage *image = ass->image;
- MonoMethod *method;
+ MonoImage *image = mono_assembly_get_image (ass);
+ MonoMethod *method, *invoke;
int i, count = 0;
if (mini_verbose > 0)
- printf ("PRECOMPILE: %s.\n", ass->image->name);
+ printf ("PRECOMPILE: %s.\n", mono_image_get_filename (image));
- for (i = 0; i < image->tables [MONO_TABLE_METHOD].rows; ++i) {
+ for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
method = mono_get_method (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL);
if (method->flags & METHOD_ATTRIBUTE_ABSTRACT)
continue;
- if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)
- continue;
count++;
if (mini_verbose > 1) {
g_free (desc);
}
mono_compile_method (method);
+ if (strcmp (method->name, "Finalize") == 0) {
+ invoke = mono_marshal_get_runtime_invoke (method);
+ mono_compile_method (invoke);
+ }
+ if (method->klass->marshalbyref && method->signature->hasthis) {
+ invoke = mono_marshal_get_remoting_invoke_with_check (method);
+ mono_compile_method (invoke);
+ }
}
}