#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)
-gboolean mono_arch_handle_exception (struct sigcontext *ctx, gpointer obj, gboolean test_only);
+gboolean mono_arch_print_tree(MonoInst *tree, int arity);
static gpointer mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt);
static gpointer mono_jit_compile_method (MonoMethod *method);
static gpointer mono_jit_find_compiled_method (MonoDomain *domain, MonoMethod *method);
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:
*
(tblock) = NEW_BBLOCK (cfg); \
(tblock)->cil_code = (ip); \
ADD_BBLOCK (cfg, (bbhash), (tblock)); \
- } \
- (tblock)->real_offset = real_offset; \
+ } \
} while (0)
#define CHECK_BBLOCK(target,ip,tblock) do { \
(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:
* at basic block boundaries. What happens is that we save the values to local variables
* and we reload them later when first entering the target basic block (with the
* handle_loaded_temps () function).
+ * It is also used to handle items on the stack in store opcodes, since it is
+ * possible that the variable to be stored into is already on the stack, in
+ * which case its old value should be used.
* A single joint point will use the same variables (stored in the array bb->out_stack or
* bb->in_stack, if the basic block is before or after the joint point).
*/
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;
MonoMethodSignature *res;
int i;
- if (!sighash)
+ EnterCriticalSection (&trampoline_hash_mutex);
+ if (!sighash) {
sighash = g_hash_table_new (NULL, NULL);
-
-
- if ((res = g_hash_table_lookup (sighash, (gpointer)arity)))
+ }
+ 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.array_class->byval_arg;
for (i = 1; i <= arity; i++)
res->ret = &mono_defaults.int_class->byval_arg;
g_hash_table_insert (sighash, (gpointer)arity, res);
+ LeaveCriticalSection (&trampoline_hash_mutex);
+
+ 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 MonoInst *
+handle_box (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *val, const guchar *ip, MonoClass *klass)
+{
+ MonoInst *iargs [2];
+ MonoInst *dest, *vtoffset, *add, *vstore;
+ int temp;
+
+ /* much like NEWOBJ */
+ if (cfg->opt & MONO_OPT_SHARED) {
+ NEW_DOMAINCONST (cfg, iargs [0]);
+ NEW_CLASSCONST (cfg, iargs [1], klass);
+
+ temp = mono_emit_jit_icall (cfg, bblock, mono_object_new, iargs, ip);
+ } else {
+ MonoVTable *vtable = mono_class_vtable (cfg->domain, klass);
+ NEW_VTABLECONST (cfg, iargs [0], vtable);
+ if (klass->has_finalize || (cfg->prof_options & MONO_PROFILE_ALLOCATIONS))
+ temp = mono_emit_jit_icall (cfg, bblock, mono_object_new_specific, iargs, ip);
+ else
+ temp = mono_emit_jit_icall (cfg, bblock, mono_object_new_fast, iargs, ip);
+ }
+ NEW_TEMPLOAD (cfg, dest, temp);
+ NEW_ICONST (cfg, vtoffset, sizeof (MonoObject));
+ MONO_INST_NEW (cfg, add, OP_PADD);
+ add->inst_left = dest;
+ add->inst_right = vtoffset;
+ add->cil_code = ip;
+ add->klass = klass;
+ MONO_INST_NEW (cfg, vstore, CEE_STIND_I);
+ vstore->opcode = mono_type_to_stind (&klass->byval_arg);
+ vstore->cil_code = ip;
+ vstore->inst_left = add;
+ vstore->inst_right = val;
+
+ if (vstore->opcode == CEE_STOBJ) {
+ handle_stobj (cfg, bblock, add, val, ip, klass, FALSE, FALSE);
+ } else
+ MONO_ADD_INS (bblock, vstore);
+
+ NEW_TEMPLOAD (cfg, dest, temp);
+ return dest;
+}
+
#define CODE_IS_STLOC(ip) (((ip) [0] >= CEE_STLOC_0 && (ip) [0] <= CEE_STLOC_3) || ((ip) [0] == CEE_STLOC_S))
static gboolean
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));
#define CHECK_LOCAL(num) if ((unsigned)(num) >= (unsigned)header->num_locals) goto unverified
#define CHECK_OPSIZE(size) if (ip + size > end) goto unverified
-#define TYPE_PARAM_TO_TYPE(num) (method->klass->generic_inst->type_argv [(num)])
-#define TYPE_PARAM_TO_CLASS(num) (mono_class_from_mono_type (TYPE_PARAM_TO_TYPE ((num))))
-
-#define MTYPE_PARAM_TO_TYPE(num) (method->signature->gen_method->mtype_argv [(num)])
-#define MTYPE_PARAM_TO_CLASS(num) (mono_class_from_mono_type (MTYPE_PARAM_TO_TYPE ((num))))
-
/* offset from br.s -> br like opcodes */
#define BIG_BRANCH_OFFSET 13
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 MonoClassField *
-get_generic_field_inst (MonoClassField *field, MonoClass *klass, MonoClass **retclass)
-{
- int i;
- for (i = 0; i < field->parent->field.count; ++i) {
- if (field == &field->parent->fields [i]) {
- *retclass = klass;
- return &klass->fields [i];
- }
- }
- return NULL;
-}
-
-static MonoClassField *
-inflate_generic_field (MonoClassField *field, MonoClass *klass, MonoClass **retclass)
+static MonoInst*
+emit_tree (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *ins)
{
- MonoGenericInst *ginst;
- MonoClassField *res;
-
- res = g_new0 (MonoClassField, 1);
- *res = *field;
- ginst = klass->generic_inst;
- res->type = mono_class_inflate_generic_type (field->type, ginst, NULL);
- return res;
-}
-
-static MonoMethod *
-mini_get_method (MonoImage *image, guint32 token, MonoMethod *calling_method)
-{
- MonoMethod *method = mono_get_method (image, token, NULL);
- MonoGenericMethod *gmethod;
-
- if (!calling_method->signature->gen_method || !method->signature->gen_method)
- return method;
-
- gmethod = g_new0 (MonoGenericMethod, 1);
- *gmethod = *calling_method->signature->gen_method;
- gmethod->generic_method = method;
- gmethod->generic_inst = calling_method->klass->generic_inst;
-
- return mono_class_inflate_generic_method (method, gmethod, NULL);
+ 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;
}
/*
MonoImage *image;
guint32 token, ins_flag;
MonoClass *klass;
+ MonoClass *constrained_call = NULL;
unsigned char *ip, *end, *target, *err_pos;
static double r8_0 = 0.0;
MonoMethodSignature *sig;
+ MonoGenericContext *generic_context = NULL;
MonoType **param_types;
GList *bb_recheck = NULL, *tmp;
int i, n, start_new_bblock, align;
end = ip + header->code_size;
mono_jit_stats.cil_code_size += header->code_size;
+ if (method->signature->is_inflated)
+ generic_context = ((MonoMethodInflated *) method)->context;
+
if (cfg->method == method) {
real_offset = 0;
bbhash = cfg->bb_hash;
if (cfg->verbose_level > 2)
g_print ("method to IR %s\n", mono_method_full_name (method, TRUE));
- if (cfg->prof_options & MONO_PROFILE_INS_COVERAGE)
- cfg->coverage_info = mono_profiler_coverage_alloc (cfg->method, header->code_size);
-
dont_inline = g_list_prepend (dont_inline, method);
if (cfg->method == method) {
+ if (cfg->prof_options & MONO_PROFILE_INS_COVERAGE)
+ cfg->coverage_info = mono_profiler_coverage_alloc (cfg->method, header->code_size);
+
/* ENTRY BLOCK */
cfg->bb_entry = start_bblock = NEW_BBLOCK (cfg);
start_bblock->cil_code = NULL;
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;
}
}
}
- if (cfg->coverage_info) {
+ bblock->real_offset = real_offset;
+
+ if ((cfg->method == method) && cfg->coverage_info) {
MonoInst *store, *one;
guint32 cil_offset = ip - header->code;
cfg->coverage_info->data [cil_offset].cil_code = ip;
if (cfg->verbose_level > 3)
g_print ("converting (in B%d: stack: %d) %s", bblock->block_num, sp-stack_start, mono_disasm_code_one (NULL, method, ip, NULL));
- /* Workaround for bug #51126 */
- bblock->real_offset = real_offset;
-
switch (*ip) {
case CEE_NOP:
++ip;
*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_INST_NEW (cfg, ins, CEE_JMP);
token = read32 (ip + 1);
/* FIXME: check the signature matches */
- cmethod = mini_get_method (image, token, method);
+ cmethod = mono_get_method_full (image, token, NULL, generic_context);
ins->inst_p0 = cmethod;
MONO_ADD_INS (bblock, ins);
ip += 5;
} else {
if (method->wrapper_type != MONO_WRAPPER_NONE) {
cmethod = (MonoMethod *)mono_method_get_wrapper_data (method, token);
+ } else if (constrained_call) {
+ cmethod = mono_get_method_constrained (image, token, constrained_call, generic_context);
} else {
- cmethod = mini_get_method (image, token, method);
+ cmethod = mono_get_method_full (image, token, NULL, generic_context);
}
+ g_assert (cmethod);
+
if (!cmethod->klass->inited)
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);
}
sp -= n;
+ if (constrained_call) {
+ /*
+ * 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.
+ */
+ 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;
+
+ /*
+ * The type parameter is instantiated as a reference
+ * type. We have a managed pointer on the stack, so
+ * we need to dereference it here.
+ */
+
+ MONO_INST_NEW (cfg, ins, CEE_LDIND_REF);
+ ins->cil_code = ip;
+ ins->inst_i0 = sp [0];
+ ins->type = STACK_OBJ;
+ sp [0] = ins;
+ } else if (cmethod->klass->valuetype)
+ virtual = 0;
+ constrained_call = NULL;
+ }
+
if (*ip != CEE_CALLI && check_call_signature (cfg, fsig, sp))
goto unverified;
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;
if (strcmp (cmethod->name, "Set") == 0) { /* array Set */
if (sp [fsig->param_count]->type == STACK_OBJ) {
MonoInst *iargs [2];
+ MonoInst *array, *to_store, *store;
handle_loaded_temps (cfg, bblock, stack_start, sp);
- iargs [0] = sp [0];
- iargs [1] = sp [fsig->param_count];
-
- mono_emit_jit_icall (cfg, bblock, helper_stelem_ref_check, iargs, ip);
+ array = mono_compile_create_var (cfg, type_from_stack_type (sp [0]), OP_LOCAL);
+ NEW_TEMPSTORE (cfg, store, array->inst_c0, sp [0]);
+ store->cil_code = ip;
+ MONO_ADD_INS (bblock, store);
+ NEW_TEMPLOAD (cfg, iargs [0], array->inst_c0);
+
+ to_store = mono_compile_create_var (cfg, type_from_stack_type (sp [fsig->param_count]), OP_LOCAL);
+ NEW_TEMPSTORE (cfg, store, to_store->inst_c0, sp [fsig->param_count]);
+ store->cil_code = ip;
+ MONO_ADD_INS (bblock, store);
+ NEW_TEMPLOAD (cfg, iargs [1], to_store->inst_c0);
+
+ /*
+ * We first save the args for the call so that the args are copied to the stack
+ * and a new instruction tree for them is created. If we don't do this,
+ * the same MonoInst is added to two different trees and this is not
+ * allowed by burg.
+ */
+ mono_emit_jit_icall (cfg, bblock, helper_stelem_ref_check, iargs, ip);
+
+ NEW_TEMPLOAD (cfg, sp [0], array->inst_c0);
+ NEW_TEMPLOAD (cfg, sp [fsig->param_count], to_store->inst_c0);
}
addr = mini_get_ldelema_ins (cfg, bblock, cmethod, sp, ip, TRUE);
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 (method->wrapper_type != MONO_WRAPPER_NONE)
klass = mono_method_get_wrapper_data (method, token);
else
- klass = mono_class_get (image, token);
+ klass = mono_class_get_full (image, token, generic_context);
mono_class_init (klass);
- if (klass->byval_arg.type == MONO_TYPE_VAR)
- klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.generic_param->num);
- else if (klass->byval_arg.type == MONO_TYPE_MVAR)
- klass = MTYPE_PARAM_TO_CLASS (klass->byval_arg.data.generic_param->num);
sp -= 2;
if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
MonoInst *store, *load;
if (method->wrapper_type != MONO_WRAPPER_NONE)
klass = mono_method_get_wrapper_data (method, token);
else
- klass = mono_class_get (image, token);
+ klass = mono_class_get_full (image, token, generic_context);
mono_class_init (klass);
- if (klass->byval_arg.type == MONO_TYPE_VAR)
- klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.generic_param->num);
- else if (klass->byval_arg.type == MONO_TYPE_MVAR)
- klass = MTYPE_PARAM_TO_CLASS (klass->byval_arg.data.generic_param->num);
if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
MONO_INST_NEW (cfg, ins, CEE_LDIND_REF);
ins->cil_code = ip;
if (method->wrapper_type != MONO_WRAPPER_NONE) {
cmethod = mono_method_get_wrapper_data (method, token);
} else
- cmethod = mini_get_method (image, token, method);
+ cmethod = mono_get_method_full (image, token, NULL, generic_context);
fsig = mono_method_get_signature (cmethod, image, token);
mono_class_init (cmethod->klass);
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;
CHECK_STACK (1);
--sp;
CHECK_OPSIZE (5);
- klass = mono_class_get (image, read32 (ip + 1));
+ klass = mono_class_get_full (image, read32 (ip + 1), generic_context);
mono_class_init (klass);
if (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
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;
if (method->wrapper_type != MONO_WRAPPER_NONE)
klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
else
- klass = mono_class_get (image, token);
+ klass = mono_class_get_full (image, token, generic_context);
mono_class_init (klass);
- if (klass->byval_arg.type == MONO_TYPE_VAR)
- klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.generic_param->num);
- else if (klass->byval_arg.type == MONO_TYPE_MVAR)
- klass = MTYPE_PARAM_TO_CLASS (klass->byval_arg.data.generic_param->num);
-
if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
/* CASTCLASS */
if (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
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;
if (method->wrapper_type != MONO_WRAPPER_NONE)
klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
else
- klass = mono_class_get (image, token);
+ klass = mono_class_get_full (image, token, generic_context);
mono_class_init (klass);
- if (klass->byval_arg.type == MONO_TYPE_VAR)
- klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.generic_param->num);
- else if (klass->byval_arg.type == MONO_TYPE_MVAR)
- klass = MTYPE_PARAM_TO_CLASS (klass->byval_arg.data.generic_param->num);
-
MONO_INST_NEW (cfg, ins, OP_UNBOXCAST);
ins->type = STACK_OBJ;
ins->inst_left = *sp;
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;
CHECK_STACK (1);
--sp;
CHECK_OPSIZE (5);
- klass = mono_class_get (image, read32 (ip + 1));
+ klass = mono_class_get_full (image, read32 (ip + 1), generic_context);
mono_class_init (klass);
- if (klass->byval_arg.type == MONO_TYPE_VAR)
- klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.generic_param->num);
- else if (klass->byval_arg.type == MONO_TYPE_MVAR)
- klass = MTYPE_PARAM_TO_CLASS (klass->byval_arg.data.generic_param->num);
if (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
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;
// goto unverified;
CHECK_OPSIZE (5);
token = read32 (ip + 1);
- field = mono_field_from_token (image, token, &klass);
- if (field->parent->gen_params)
- field = get_generic_field_inst (field, method->klass, &klass);
- else if (field->parent->generic_inst && method->klass->generic_inst)
- field = inflate_generic_field (field, method->klass, &klass);
+ field = mono_field_from_token (image, token, &klass, generic_context);
mono_class_init (klass);
foffset = klass->valuetype? field->offset - sizeof (MonoObject): field->offset;
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;
CHECK_OPSIZE (5);
token = read32 (ip + 1);
- field = mono_field_from_token (image, token, &klass);
- if (field->parent->gen_params)
- field = get_generic_field_inst (field, method->klass, &klass);
- else if (field->parent->generic_inst && method->klass->generic_inst)
- field = inflate_generic_field (field, method->klass, &klass);
+ field = mono_field_from_token (image, token, &klass, generic_context);
mono_class_init (klass);
- handle_loaded_temps (cfg, bblock, stack_start, sp);
+ if ((*ip) == CEE_STSFLD)
+ handle_loaded_temps (cfg, bblock, stack_start, sp);
if (cfg->domain->special_static_fields)
addr = g_hash_table_lookup (cfg->domain->special_static_fields, field);
if (method->wrapper_type != MONO_WRAPPER_NONE)
klass = mono_method_get_wrapper_data (method, token);
else
- klass = mono_class_get (image, token);
+ klass = mono_class_get_full (image, token, generic_context);
mono_class_init (klass);
- if (klass->byval_arg.type == MONO_TYPE_VAR)
- klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.generic_param->num);
- else if (klass->byval_arg.type == MONO_TYPE_MVAR)
- klass = MTYPE_PARAM_TO_CLASS (klass->byval_arg.data.generic_param->num);
n = mono_type_to_stind (&klass->byval_arg);
if (n == CEE_STOBJ) {
handle_stobj (cfg, bblock, sp [0], sp [1], ip, klass, FALSE, FALSE);
inline_costs += 1;
break;
case CEE_BOX: {
- MonoInst *iargs [2];
- MonoInst *load, *vtoffset, *add, *val, *vstore;
- int temp;
+ MonoInst *val;
CHECK_STACK (1);
--sp;
val = *sp;
if (method->wrapper_type != MONO_WRAPPER_NONE)
klass = mono_method_get_wrapper_data (method, token);
else
- klass = mono_class_get (image, token);
+ klass = mono_class_get_full (image, token, generic_context);
mono_class_init (klass);
- if (klass->byval_arg.type == MONO_TYPE_VAR)
- klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.generic_param->num);
- else if (klass->byval_arg.type == MONO_TYPE_MVAR)
- klass = MTYPE_PARAM_TO_CLASS (klass->byval_arg.data.generic_param->num);
if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
*sp++ = val;
ip += 5;
break;
}
- /* much like NEWOBJ */
- if (cfg->opt & MONO_OPT_SHARED) {
- NEW_DOMAINCONST (cfg, iargs [0]);
- NEW_CLASSCONST (cfg, iargs [1], klass);
-
- temp = mono_emit_jit_icall (cfg, bblock, mono_object_new, iargs, ip);
- } else {
- MonoVTable *vtable = mono_class_vtable (cfg->domain, klass);
- NEW_VTABLECONST (cfg, iargs [0], vtable);
- if (klass->has_finalize || (cfg->prof_options & MONO_PROFILE_ALLOCATIONS))
- temp = mono_emit_jit_icall (cfg, bblock, mono_object_new_specific, iargs, ip);
- else
- temp = mono_emit_jit_icall (cfg, bblock, mono_object_new_fast, iargs, ip);
- }
- NEW_TEMPLOAD (cfg, load, temp);
- NEW_ICONST (cfg, vtoffset, sizeof (MonoObject));
- MONO_INST_NEW (cfg, add, CEE_ADD);
- add->inst_left = load;
- add->inst_right = vtoffset;
- add->cil_code = ip;
- add->klass = klass;
- MONO_INST_NEW (cfg, vstore, CEE_STIND_I);
- vstore->opcode = mono_type_to_stind (&klass->byval_arg);
- vstore->cil_code = ip;
- vstore->inst_left = add;
- vstore->inst_right = val;
-
- if (vstore->opcode == CEE_STOBJ) {
- handle_stobj (cfg, bblock, add, val, ip, klass, FALSE, FALSE);
- } else
- MONO_ADD_INS (bblock, vstore);
-
- NEW_TEMPLOAD (cfg, load, temp);
- *sp++ = load;
+ *sp++ = handle_box (cfg, bblock, val, ip, klass);
ip += 5;
inline_costs += 1;
break;
if (method->wrapper_type != MONO_WRAPPER_NONE)
klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
else
- klass = mono_class_get (image, token);
+ klass = mono_class_get_full (image, token, generic_context);
mono_class_init (klass);
- if (klass->byval_arg.type == MONO_TYPE_VAR)
- klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.generic_param->num);
- else if (klass->byval_arg.type == MONO_TYPE_MVAR)
- klass = MTYPE_PARAM_TO_CLASS (klass->byval_arg.data.generic_param->num);
ins->inst_newa_class = klass;
ins->inst_newa_len = *sp;
ins->type = STACK_OBJ;
if (method->wrapper_type != MONO_WRAPPER_NONE)
klass = (MonoClass*)mono_method_get_wrapper_data (method, read32 (ip + 1));
else
- klass = mono_class_get (image, read32 (ip + 1));
+ klass = mono_class_get_full (image, read32 (ip + 1), generic_context);
mono_class_init (klass);
- if (klass->byval_arg.type == MONO_TYPE_VAR)
- klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.generic_param->num);
- else if (klass->byval_arg.type == MONO_TYPE_MVAR)
- klass = MTYPE_PARAM_TO_CLASS (klass->byval_arg.data.generic_param->num);
NEW_LDELEMA (cfg, ins, sp, klass);
ins->cil_code = ip;
*sp++ = ins;
ip += 5;
break;
- case CEE_LDELEM: {
+ case CEE_LDELEM_ANY: {
MonoInst *load;
CHECK_STACK (2);
sp -= 2;
CHECK_OPSIZE (5);
token = read32 (ip + 1);
- klass = mono_class_get (image, token);
+ klass = mono_class_get_full (image, token, generic_context);
mono_class_init (klass);
- if (klass->byval_arg.type == MONO_TYPE_VAR)
- klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.generic_param->num);
- else if (klass->byval_arg.type == MONO_TYPE_MVAR)
- klass = MTYPE_PARAM_TO_CLASS (klass->byval_arg.data.generic_param->num);
NEW_LDELEMA (cfg, load, sp, klass);
load->cil_code = ip;
MONO_INST_NEW (cfg, ins, mono_type_to_ldind (&klass->byval_arg));
inline_costs += 1;
break;
}
- case CEE_STELEM: {
+ case CEE_STELEM_ANY: {
MonoInst *load;
/*
* translate to:
sp -= 3;
CHECK_OPSIZE (5);
token = read32 (ip + 1);
- klass = mono_class_get (image, token);
+ klass = mono_class_get_full (image, token, generic_context);
mono_class_init (klass);
- if (klass->byval_arg.type == MONO_TYPE_VAR)
- klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.generic_param->num);
- else if (klass->byval_arg.type == MONO_TYPE_MVAR)
- klass = MTYPE_PARAM_TO_CLASS (klass->byval_arg.data.generic_param->num);
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;
- MONO_INST_NEW (cfg, ins, mono_type_to_stind (&klass->byval_arg));
- ins->cil_code = ip;
- ins->inst_left = load;
- ins->inst_right = sp [2];
- handle_loaded_temps (cfg, bblock, stack_start, sp);
- MONO_ADD_INS (bblock, ins);
+
+ n = mono_type_to_stind (&klass->byval_arg);
+ if (n == CEE_STOBJ)
+ handle_stobj (cfg, bblock, load, sp [2], ip, klass, FALSE, FALSE);
+ else {
+ MONO_INST_NEW (cfg, ins, n);
+ ins->cil_code = ip;
+ ins->inst_left = load;
+ ins->inst_right = sp [2];
+ handle_loaded_temps (cfg, bblock, stack_start, sp);
+ MONO_ADD_INS (bblock, ins);
+ }
}
ip += 5;
inline_costs += 1;
}
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;
MONO_INST_NEW (cfg, ins, *ip);
--sp;
CHECK_OPSIZE (5);
- klass = mono_class_get (image, read32 (ip + 1));
+ klass = mono_class_get_full (image, read32 (ip + 1), generic_context);
mono_class_init (klass);
- if (klass->byval_arg.type == MONO_TYPE_VAR)
- klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.generic_param->num);
- else if (klass->byval_arg.type == MONO_TYPE_MVAR)
- klass = MTYPE_PARAM_TO_CLASS (klass->byval_arg.data.generic_param->num);
ins->type = STACK_MP;
ins->inst_left = *sp;
ins->klass = klass;
MONO_INST_NEW (cfg, ins, *ip);
--sp;
CHECK_OPSIZE (5);
- klass = mono_class_get (image, read32 (ip + 1));
+ klass = mono_class_get_full (image, read32 (ip + 1), generic_context);
mono_class_init (klass);
- if (klass->byval_arg.type == MONO_TYPE_VAR)
- klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.generic_param->num);
- else if (klass->byval_arg.type == MONO_TYPE_MVAR)
- klass = MTYPE_PARAM_TO_CLASS (klass->byval_arg.data.generic_param->num);
ins->cil_code = ip;
loc = mono_compile_create_var (cfg, &mono_defaults.typed_reference_class->byval_arg, OP_LOCAL);
CHECK_OPSIZE (5);
n = read32 (ip + 1);
- handle = mono_ldtoken (image, n, &handle_class);
+ handle = mono_ldtoken (image, n, &handle_class, generic_context);
mono_class_init (handle_class);
if (cfg->opt & MONO_OPT_SHARED) {
MONO_ADD_INS (bblock, store);
NEW_TEMPLOAD (cfg, ins, vtvar->inst_c0);
} else {
- if ((ip [5] == CEE_CALL) && (cmethod = mini_get_method (image, read32 (ip + 6), method)) &&
+ 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:
- /* FIXME: check stack state */
MONO_INST_NEW (cfg, ins, *ip);
MONO_ADD_INS (bblock, ins);
ins->cil_code = ip++;
start_new_bblock = 1;
+
+ /*
+ * Control will leave the method so empty the stack, otherwise
+ * the next basic block will start with a nonempty stack.
+ */
+ while (sp != stack_start) {
+ MONO_INST_NEW (cfg, ins, CEE_POP);
+ ins->cil_code = ip;
+ sp--;
+ ins->inst_i0 = *sp;
+ MONO_ADD_INS (bblock, ins);
+ }
break;
case CEE_LEAVE:
case CEE_LEAVE_S: {
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;
- default:
- g_warning ("unknown conversion %d\n", ip [2]);
- g_assert_not_reached ();
- }
+ token = read32 (ip + 2);
+ func = mono_method_get_wrapper_data (method, token);
+ info = mono_find_jit_icall_by_addr (func);
+ g_assert (info);
- temp = mono_emit_jit_icall (cfg, bblock, func, sp, ip);
- NEW_TEMPLOAD (cfg, *sp, temp);
- sp++;
+ CHECK_STACK (info->sig->param_count);
+ sp -= info->sig->param_count;
- ip += 3;
- inline_costs += 10 * num_calls++;
- break;
- }
- case CEE_MONO_PROC2: {
- gpointer func = NULL;
- CHECK_STACK (2);
- sp -= 2;
-
- 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;
}
if (method->wrapper_type != MONO_WRAPPER_NONE)
cmethod = mono_method_get_wrapper_data (method, n);
else {
- cmethod = mini_get_method (image, n, method);
+ cmethod = mono_get_method_full (image, n, NULL, generic_context);
}
mono_class_init (cmethod->klass);
if (method->wrapper_type != MONO_WRAPPER_NONE)
cmethod = mono_method_get_wrapper_data (method, n);
else
- cmethod = mini_get_method (image, n, method);
+ cmethod = mono_get_method_full (image, n, NULL, generic_context);
mono_class_init (cmethod->klass);
handle_loaded_temps (cfg, bblock, stack_start, sp);
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;
if (method->wrapper_type != MONO_WRAPPER_NONE)
klass = mono_method_get_wrapper_data (method, token);
else
- klass = mono_class_get (image, token);
- if (klass->byval_arg.type == MONO_TYPE_VAR)
- klass = TYPE_PARAM_TO_CLASS (klass->byval_arg.data.generic_param->num);
- else if (klass->byval_arg.type == MONO_TYPE_MVAR)
- klass = MTYPE_PARAM_TO_CLASS (klass->byval_arg.data.generic_param->num);
-
+ klass = mono_class_get_full (image, token, generic_context);
if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
MonoInst *store, *load;
NEW_PCONST (cfg, load, NULL);
/* FIXME: implement */
CHECK_OPSIZE (6);
token = read32 (ip + 2);
+ constrained_call = mono_class_get_full (image, token, generic_context);
ip += 6;
break;
case CEE_CPBLK:
MonoType *type = mono_type_create_from_typespec (image, token);
token = mono_type_size (type, &align);
} else {
- MonoClass *szclass = mono_class_get (image, token);
+ MonoClass *szclass = mono_class_get_full (image, token, generic_context);
mono_class_init (szclass);
token = mono_class_value_size (szclass, &align);
}
break;
case CEE_REFANYTYPE:
CHECK_STACK (1);
- MONO_INST_NEW (cfg, ins, ip [1]);
+ MONO_INST_NEW (cfg, ins, OP_REFANYTYPE);
--sp;
ins->type = STACK_MP;
ins->inst_left = *sp;
mono_print_tree (tree->inst_left);
break;
default:
- if (arity) {
- mono_print_tree (tree->inst_left);
- if (arity > 1)
- mono_print_tree (tree->inst_right);
+ if (!mono_arch_print_tree(tree, arity)) {
+ if (arity) {
+ mono_print_tree (tree->inst_left);
+ if (arity > 1)
+ mono_print_tree (tree->inst_right);
+ }
}
break;
}
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)
-{
- g_assert (jit_icall_hash_name);
+ helper_sig_memset = make_icall_sig ("void ptr int32 int32");
- //printf ("lookup addr %s %p\n", name, g_hash_table_lookup (jit_icall_hash_name, name));
- return g_hash_table_lookup (jit_icall_hash_name, name);
-}
-
-MonoJitICallInfo *
-mono_find_jit_icall_by_addr (gconstpointer addr)
-{
- g_assert (jit_icall_hash_addr);
-
- return g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
+ helper_sig_class_init_trampoline = make_icall_sig ("void");
}
gconstpointer
{
char *name;
MonoMethod *wrapper;
+ gconstpointer code;
if (callinfo->wrapper)
return callinfo->wrapper;
+
name = g_strdup_printf ("__icall_wrapper_%s", callinfo->name);
wrapper = mono_marshal_get_icall_wrapper (callinfo->sig, name, callinfo->func);
/* Must be domain neutral since there is only one copy */
- callinfo->wrapper = mono_jit_compile_method_with_opt (wrapper, default_opt | MONO_OPT_SHARED);
+ code = mono_jit_compile_method_with_opt (wrapper, default_opt | MONO_OPT_SHARED);
- g_hash_table_insert (jit_icall_hash_addr, (gpointer)callinfo->wrapper, callinfo);
+ if (!callinfo->wrapper) {
+ callinfo->wrapper = code;
+ mono_register_jit_icall_wrapper (callinfo, code);
+ mono_debug_add_icall_wrapper (wrapper, callinfo);
+ }
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);
-
- 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);
-
- 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
}
/**
MonoJitTlsData *jit_tls;
MonoLMF *lmf;
+ jit_tls = TlsGetValue (mono_jit_tls_id);
+ if (jit_tls)
+ return jit_tls;
+
jit_tls = g_new0 (MonoJitTlsData, 1);
TlsSetValue (mono_jit_tls_id, jit_tls);
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;
mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, MonoJumpInfo *patch_info, gboolean run_cctors)
{
unsigned char *ip = patch_info->ip.i + code;
- gpointer target = NULL;
+ gconstpointer target = NULL;
switch (patch_info->type) {
case MONO_PATCH_INFO_BB:
target = mono_arch_create_jit_trampoline (patch_info->data.method);
break;
case MONO_PATCH_INFO_SWITCH: {
- gpointer *jump_table = mono_code_manager_reserve (domain->code_mp, sizeof (gpointer) * patch_info->table_size);
+ gpointer *jump_table;
int i;
+
+ mono_domain_lock (domain);
+ jump_table = mono_code_manager_reserve (domain->code_mp, sizeof (gpointer) * patch_info->table_size);
+ mono_domain_unlock (domain);
for (i = 0; i < patch_info->table_size; i++) {
jump_table [i] = code + (int)patch_info->data.table [i];
break;
case MONO_PATCH_INFO_IID:
mono_class_init (patch_info->data.klass);
- target = patch_info->data.klass->interface_id;
+ target = (gpointer)patch_info->data.klass->interface_id;
break;
case MONO_PATCH_INFO_VTABLE:
target = mono_class_vtable (domain, patch_info->data.klass);
MonoClass *handle_class;
handle = mono_ldtoken (patch_info->data.token->image,
- patch_info->data.token->token, &handle_class);
+ patch_info->data.token->token, &handle_class, NULL);
mono_class_init (handle_class);
mono_class_init (mono_class_from_mono_type (handle));
MonoClass *handle_class;
handle = mono_ldtoken (patch_info->data.token->image,
- patch_info->data.token->token, &handle_class);
+ patch_info->data.token->token, &handle_class, NULL);
mono_class_init (handle_class);
target = handle;
break;
}
+ case MONO_PATCH_INFO_BB_OVF:
+ case MONO_PATCH_INFO_EXC_OVF:
+ break;
default:
g_assert_not_reached ();
}
- return target;
+ return (gpointer)target;
}
static void
&& 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) {
static void
mini_select_instructions (MonoCompile *cfg)
{
- static int reverse_map [] = {
+ static const int reverse_map [] = {
CEE_BNE_UN, CEE_BLT, CEE_BLE, CEE_BGT, CEE_BGE,
CEE_BEQ, CEE_BLT_UN, CEE_BLE_UN, CEE_BGT_UN, CEE_BGE_UN
};
- static int reverse_fmap [] = {
+ static const int reverse_fmap [] = {
OP_FBNE_UN, OP_FBLT, OP_FBLE, OP_FBGT, OP_FBGE,
OP_FBEQ, OP_FBLT_UN, OP_FBLE_UN, OP_FBGT_UN, OP_FBGE_UN
};
- static int reverse_lmap [] = {
+ static const int reverse_lmap [] = {
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));
/* we always allocate code in cfg->domain->code_mp to increase locality */
cfg->code_size = cfg->code_len + max_epilog_size;
/* fixme: align to MONO_ARCH_CODE_ALIGNMENT */
+
+ mono_domain_lock (cfg->domain);
code = mono_code_manager_reserve (cfg->domain->code_mp, cfg->code_size);
+ mono_domain_unlock (cfg->domain);
+
memcpy (code, cfg->native_code, cfg->code_len);
g_free (cfg->native_code);
cfg->native_code = code;
break;
}
case MONO_PATCH_INFO_SWITCH: {
- gpointer *table = mono_code_manager_reserve (cfg->domain->code_mp, sizeof (gpointer) * patch_info->table_size);
+ gpointer *table;
+ mono_domain_lock (cfg->domain);
+ table = mono_code_manager_reserve (cfg->domain->code_mp, sizeof (gpointer) * patch_info->table_size);
+ mono_domain_unlock (cfg->domain);
+
patch_info->ip.i = patch_info->ip.label->inst_c0;
for (i = 0; i < patch_info->table_size; i++) {
table [i] = (gpointer)patch_info->data.table [i]->native_offset;
mono_arch_patch_code (cfg->method, cfg->domain, cfg->native_code, cfg->patch_info, cfg->run_cctors);
+ mono_domain_lock (cfg->domain);
mono_code_manager_commit (cfg->domain->code_mp, cfg->native_code, cfg->code_size, cfg->code_len);
+ mono_domain_unlock (cfg->domain);
+
mono_arch_flush_icache (cfg->native_code, cfg->code_len);
mono_debug_close_method (cfg);
#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)
}
static gpointer
-mono_jit_compile_method_inner (MonoMethod *method)
+mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain)
{
- /* FIXME: later copy the code from mono */
- MonoDomain *target_domain, *domain = mono_domain_get ();
MonoCompile *cfg;
GHashTable *jit_code_hash;
- gpointer code;
+ gpointer code = NULL;
guint32 opt;
+ MonoJitInfo *info;
opt = default_opt;
- if (opt & MONO_OPT_SHARED)
- target_domain = mono_root_domain;
- else
- target_domain = domain;
-
jit_code_hash = target_domain->jit_code_hash;
#ifdef MONO_USE_AOT_COMPILER
if (!mono_compile_aot && (opt & MONO_OPT_AOT)) {
MonoJitInfo *info;
+ MonoDomain *domain = mono_domain_get ();
mono_domain_lock (domain);
mono_class_init (method->klass);
if ((info = mono_aot_get_method (domain, method))) {
-
g_hash_table_insert (domain->jit_code_hash, method, info);
-
mono_domain_unlock (domain);
-
- /* make sure runtime_init is called */
mono_runtime_class_init (mono_class_vtable (domain, method->klass));
-
return info->code_start;
}
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;
}
cfg = mini_method_compile (method, opt, target_domain, TRUE, 0);
- code = cfg->native_code;
- g_hash_table_insert (jit_code_hash, method, cfg->jit_info);
+ mono_domain_lock (target_domain);
+
+ /* Check if some other thread already did the job. In this case, we can
+ discard the code this thread generated. */
+
+ if ((info = g_hash_table_lookup (target_domain->jit_code_hash, method))) {
+ /* We can't use a domain specific method in another domain */
+ if ((target_domain == mono_domain_get ()) || info->domain_neutral) {
+ code = info->code_start;
+// printf("Discarding code for method %s\n", method->name);
+ }
+ }
+
+ if (code == NULL) {
+ g_hash_table_insert (jit_code_hash, method, cfg->jit_info);
+ code = cfg->native_code;
+ }
mono_destroy_compile (cfg);
mono_arch_patch_code (NULL, target_domain, tmp->data, &patch_info, TRUE);
g_slist_free (list);
}
- /* make sure runtime_init is called */
- mono_runtime_class_init (mono_class_vtable (target_domain, method->klass));
+ mono_domain_unlock (target_domain);
+
+ mono_runtime_class_init (mono_class_vtable (target_domain, method->klass));
return code;
}
/* FIXME: later copy the code from mono */
MonoDomain *target_domain, *domain = mono_domain_get ();
MonoJitInfo *info;
- gpointer code;
+ 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 (domain, method->klass));
return info->code_start;
}
}
- code = mono_jit_compile_method_inner (method);
-
mono_domain_unlock (target_domain);
-
- return code;
+ p = mono_jit_compile_method_inner (method, target_domain);
+ return p;
}
static gpointer
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
struct sigcontext *ctx = (struct sigcontext*)_dummy;
#else
#ifdef __sparc
+#define GET_CONTEXT \
+ void *ctx = context;
+#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
static void
mono_runtime_install_handlers (void)
{
-#ifndef PLATFORM_WIN32
+#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
struct sigaction sa;
#endif
* 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);
}
add_signal_handler (SIGFPE, sigfpe_signal_handler);
add_signal_handler (SIGQUIT, sigquit_signal_handler);
add_signal_handler (SIGILL, sigill_signal_handler);
+ add_signal_handler (SIGBUS, sigsegv_signal_handler);
add_signal_handler (mono_thread_get_abort_signal (), sigusr1_signal_handler);
/* catch SIGSEGV */
#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);
mono_install_handler (mono_arch_get_throw_exception ());
#endif
mono_install_stack_walk (mono_jit_walk_stack);
- mono_install_get_config_dir ();
- 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);
#if SIZEOF_VOID_P == 4
mono_register_opcode_emulation (OP_FCONV_TO_U, "__emul_fconv_to_u", helper_sig_uint_double, mono_fconv_u4, TRUE);
#else
+#ifdef __GNUC__
#warning "fixme: add opcode emulation"
+#endif
#endif
/* other jit icalls */
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_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);
g_print ("Used classes: %ld\n", mono_stats.used_class_count);
g_print ("Static data size: %ld\n", mono_stats.class_static_data_size);
g_print ("VTable data size: %ld\n", mono_stats.class_vtable_size);
+
+ g_print ("\nGeneric instances: %ld\n", mono_stats.generic_instance_count);
+ g_print ("Inflated methods: %ld\n", mono_stats.inflated_method_count);
+ g_print ("Inflated types: %ld\n", mono_stats.inflated_type_count);
+ g_print ("Generics metadata size: %ld\n", mono_stats.generics_metadata_size);
}
}
* fully working (mono_domain_finalize may invoke managed finalizers
* and mono_runtime_cleanup will wait for other threads to finish).
*/
- mono_domain_finalize (domain, -1);
+ mono_domain_finalize (domain, 2000);
mono_runtime_cleanup (domain);
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);
+ }
}
}