#include <pthread.h>
#endif
+#ifdef PLATFORM_WIN32
+#define _WIN32_WINNT 0x0500
+#endif
+
#ifdef HAVE_VALGRIND_MEMCHECK_H
#include <valgrind/memcheck.h>
#endif
static gpointer mono_jit_compile_method (MonoMethod *method);
static gpointer mono_jit_find_compiled_method (MonoDomain *domain, MonoMethod *method);
static gpointer mono_create_jit_trampoline_in_domain (MonoDomain *domain, MonoMethod *method);
+inline static int mono_emit_jit_icall (MonoCompile *cfg, MonoBasicBlock *bblock, gconstpointer func, MonoInst **args, const guint8 *ip);
static void handle_stobj (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *dest, MonoInst *src,
const unsigned char *ip, MonoClass *klass, gboolean to_end, gboolean native, gboolean write_barrier);
return ((i + 1) << 8) | MONO_REGION_FILTER | clause->flags;
if (MONO_OFFSET_IN_HANDLER (clause, offset)) {
- if (clause->flags & MONO_EXCEPTION_CLAUSE_FINALLY)
+ if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY)
return ((i + 1) << 8) | MONO_REGION_FINALLY | clause->flags;
- else
+ else if (clause->flags == MONO_EXCEPTION_CLAUSE_FAULT)
+ return ((i + 1) << 8) | MONO_REGION_FAULT | clause->flags;
+ else if (clause->flags == MONO_EXCEPTION_CLAUSE_NONE)
return ((i + 1) << 8) | MONO_REGION_CATCH | clause->flags;
}
}
ins->type = STACK_PTR;
switch (ins->inst_i0->type) {
case STACK_I4:
+ break;
case STACK_PTR:
case STACK_MP:
+#if SIZEOF_VOID_P == 8
+ ins->opcode = OP_LCONV_TO_U;
+#endif
break;
case STACK_I8:
ins->opcode = OP_LCONV_TO_U;
MONO_INIT_VARINFO (cfg->vars [num], num);
cfg->num_varinfo++;
- //g_print ("created temp %d of type %s\n", num, mono_type_get_name (type));
+ if (cfg->verbose_level > 2)
+ g_print ("created temp %d of type %s\n", num, mono_type_get_name (type));
return inst;
}
case STACK_R8: return &mono_defaults.double_class->byval_arg;
case STACK_MP:
/*
- * FIXME: This doesn't work because mono_class_from_mono_type ()
- * returns the original klass for a byref type, not a 'byref' class,
- * causing the JIT to create variables with the wrong type, for
- * example.
+ * this if used to be commented without any specific reason, but
+ * it breaks #80235 when commented
*/
- /*
if (ins->klass)
return &ins->klass->this_arg;
else
- */
return &mono_defaults.object_class->this_arg;
- case STACK_OBJ: return &mono_defaults.object_class->byval_arg;
+ case STACK_OBJ:
+ /* ins->klass may not be set for ldnull.
+ * Also, if we have a boxed valuetype, we want an object lass,
+ * not the valuetype class
+ */
+ if (ins->klass && !ins->klass->valuetype)
+ return &ins->klass->byval_arg;
+ return &mono_defaults.object_class->byval_arg;
case STACK_VTYPE: return &ins->klass->byval_arg;
default:
g_error ("stack type %d to montype not handled\n", ins->type);
}
static MonoClass*
-array_access_to_klass (int opcode)
+array_access_to_klass (int opcode, MonoInst *array_obj)
{
switch (opcode) {
case CEE_LDELEM_U1:
case CEE_STELEM_R8:
return mono_defaults.double_class;
case CEE_LDELEM_REF:
- case CEE_STELEM_REF:
+ case CEE_STELEM_REF: {
+ MonoClass *klass = array_obj->klass;
+ /* FIXME: add assert */
+ if (klass && klass->rank)
+ return klass->element_class;
return mono_defaults.object_class;
+ }
default:
g_assert_not_reached ();
}
* in the inlined methods do not inherit their in_stack from
* the bblock they are inlined to. See bug #58863 for an
* example.
+ * This hack is disabled since it also prevents proper tracking of types.
*/
+#if 1
+ bb->out_stack [i] = mono_compile_create_var (cfg, type_from_stack_type (sp [i]), OP_LOCAL);
+#else
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]);
+#endif
}
}
}
if (arg->type != STACK_I4 && arg->type != STACK_PTR)
return 1;
return 0;
- case MONO_TYPE_CLASS:
- case MONO_TYPE_STRING:
case MONO_TYPE_OBJECT:
+ if (arg->type != STACK_OBJ)
+ return 1;
+ return 0;
+ case MONO_TYPE_STRING:
+ if (arg->type != STACK_OBJ)
+ return 1;
+ /* ldnull has arg->klass unset */
+ /*if (arg->klass && arg->klass != mono_defaults.string_class) {
+ G_BREAKPOINT ();
+ return 1;
+ }*/
+ return 0;
+ case MONO_TYPE_CLASS:
case MONO_TYPE_SZARRAY:
case MONO_TYPE_ARRAY:
if (arg->type != STACK_OBJ)
return 0;
case MONO_TYPE_GENERICINST:
if (mono_type_generic_inst_is_valuetype (simple_type)) {
+ klass = mono_class_from_mono_type (simple_type);
+ if (klass->enumtype)
+ return target_type_is_incompatible (cfg, klass->enum_basetype, arg);
if (arg->type != STACK_VTYPE)
return 1;
- klass = mono_class_from_mono_type (simple_type);
if (klass != arg->klass)
return 1;
return 0;
}
}
-static MonoMethodSignature *
-mono_get_element_address_signature (int arity)
-{
- static GHashTable *sighash = NULL;
- MonoMethodSignature *res;
- int i;
-
- mono_jit_lock ();
- if (!sighash) {
- sighash = g_hash_table_new (NULL, NULL);
- }
- else if ((res = g_hash_table_lookup (sighash, GINT_TO_POINTER (arity)))) {
- LeaveCriticalSection (&jit_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;
-
-#ifdef PLATFORM_WIN32
- /*
- * The default pinvoke calling convention is STDCALL but we need CDECL.
- */
- res->call_convention = MONO_CALL_C;
-#endif
-
- for (i = 1; i <= arity; i++)
- res->params [i] = &mono_defaults.int_class->byval_arg;
-
- res->ret = &mono_defaults.int_class->byval_arg;
-
- g_hash_table_insert (sighash, GINT_TO_POINTER (arity), res);
- mono_jit_unlock ();
-
- return res;
-}
-
static MonoMethodSignature *
mono_get_array_new_va_signature (int arity)
{
NEW_TEMPLOAD (cfg, (ins), temp); \
} \
} while (0)
+#define STARG_SOFT_FLOAT(cfg,ins,idx,ip) do {\
+ if (param_types [(idx)]->type == MONO_TYPE_R4 && !param_types [(idx)]->byref) { \
+ int temp; \
+ NEW_ARGLOADA (cfg, (ins), (idx)); \
+ handle_store_float (cfg, bblock, (ins), *sp, (ip)); \
+ MONO_INST_NEW (cfg, (ins), CEE_NOP); \
+ } \
+ } while (0)
#else
#define LDLOC_SOFT_FLOAT(cfg,ins,idx,ip)
#define STLOC_SOFT_FLOAT(cfg,ins,idx,ip)
#define LDARG_SOFT_FLOAT(cfg,ins,idx,ip)
+#define STARG_SOFT_FLOAT(cfg,ins,idx,ip)
#endif
static MonoMethod*
MONO_TYPE_ISSTRUCT (signature->ret))
return FALSE;
+#ifdef MONO_ARCH_SOFT_FLOAT
+ /* this complicates things, fix later */
+ if (signature->ret->type == MONO_TYPE_R4)
+ return FALSE;
+#endif
/* its not worth to inline methods with valuetype arguments?? */
for (i = 0; i < signature->param_count; i++) {
if (MONO_TYPE_ISSTRUCT (signature->params [i])) {
{
int temp, rank;
MonoInst *addr;
- MonoMethodSignature *esig;
- char icall_name [256];
- char *name;
- MonoJitICallInfo *info;
+ MonoMethod *addr_method;
+ int element_size;
rank = mono_method_signature (cmethod)->param_count - (is_set? 1: 0);
#endif
}
- /* Need to register the icall so it gets an icall wrapper */
- sprintf (icall_name, "ves_array_element_address_%d", rank);
-
- mono_jit_lock ();
- info = mono_find_jit_icall_by_name (icall_name);
- if (info == NULL) {
- esig = mono_get_element_address_signature (rank);
- name = g_strdup (icall_name);
- info = mono_register_jit_icall (ves_array_element_address, name, esig, FALSE);
-
- g_hash_table_insert (jit_icall_name_hash, name, name);
- }
- mono_jit_unlock ();
-
- /* FIXME: This uses info->sig, but it should use the signature of the wrapper */
- temp = mono_emit_native_call (cfg, bblock, mono_icall_get_wrapper (info), info->sig, sp, ip, FALSE, FALSE);
- cfg->flags |= MONO_CFG_HAS_VARARGS;
-
+ element_size = mono_class_array_element_size (cmethod->klass->element_class);
+ addr_method = mono_marshal_get_array_address (rank, element_size);
+ temp = mono_emit_method_call_spilled (cfg, bblock, addr_method, addr_method->signature, sp, ip, NULL);
NEW_TEMPLOAD (cfg, addr, temp);
return addr;
+
}
static MonoJitICallInfo **emul_opcode_map = NULL;
store->inst_left = args [2];
store->inst_right = load;
return store;
+ } else if (cmethod->klass->image == mono_defaults.corlib) {
+ if (cmethod->name [0] == 'B' && strcmp (cmethod->name, "Break") == 0
+ && strcmp (cmethod->klass->name, "Debugger") == 0) {
+ MONO_INST_NEW (cfg, ins, CEE_BREAK);
+ return ins;
+ }
+ if (cmethod->name [0] == 'g' && strcmp (cmethod->name, "get_IsRunningOnWindows") == 0
+ && strcmp (cmethod->klass->name, "Environment") == 0) {
+#ifdef PLATFORM_WIN32
+ NEW_ICONST (cfg, ins, 1);
+#else
+ NEW_ICONST (cfg, ins, 0);
+#endif
+ return ins;
+ }
}
return mono_arch_get_inst_for_method (cfg, cmethod, fsig, args);
static gboolean
can_access_member (MonoClass *access_klass, MonoClass *member_klass, int access_level)
{
+ if (access_klass->generic_class && member_klass->generic_class &&
+ access_klass->generic_class->container_class && member_klass->generic_class->container_class) {
+ if (can_access_member (access_klass->generic_class->container_class,
+ member_klass->generic_class->container_class, access_level))
+ return TRUE;
+ }
+
/* Partition I 8.5.3.2 */
/* the access level values are the same for fields and methods */
switch (access_level) {
return access_klass == member_klass;
case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
if (mono_class_has_parent (access_klass, member_klass) &&
- can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
+ can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
return TRUE;
return FALSE;
case FIELD_ATTRIBUTE_ASSEMBLY:
return can;
}
+/*
+ * Check that the IL instructions at ip are the array initialization
+ * sequence and return the pointer to the data and the size.
+ */
+static const char*
+initialize_array_data (MonoMethod *method, gboolean aot, unsigned char *ip, MonoInst *newarr, int *out_size)
+{
+ /*
+ * newarr[System.Int32]
+ * dup
+ * ldtoken field valuetype ...
+ * call void class [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype [mscorlib]System.RuntimeFieldHandle)
+ */
+ if (ip [0] == CEE_DUP && ip [1] == CEE_LDTOKEN && ip [5] == 0x4 && ip [6] == CEE_CALL) {
+ MonoClass *klass = newarr->inst_newa_class;
+ guint32 token = read32 (ip + 7);
+ guint32 rva, field_index;
+ const char *data_ptr;
+ int size = 0;
+ MonoMethod *cmethod;
+
+ if (newarr->inst_newa_len->opcode != OP_ICONST)
+ return NULL;
+ cmethod = mini_get_method (method, token, NULL, NULL);
+ if (strcmp (cmethod->name, "InitializeArray") || strcmp (cmethod->klass->name, "RuntimeHelpers") || cmethod->klass->image != mono_defaults.corlib)
+ return NULL;
+ switch (mono_type_get_underlying_type (&klass->byval_arg)->type) {
+ case MONO_TYPE_BOOLEAN:
+ case MONO_TYPE_I1:
+ case MONO_TYPE_U1:
+ size = 1; break;
+ /* we need to swap on big endian, so punt. Should we handle R4 and R8 as well? */
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ case MONO_TYPE_CHAR:
+ case MONO_TYPE_I2:
+ case MONO_TYPE_U2:
+ size = 2; break;
+ case MONO_TYPE_I4:
+ case MONO_TYPE_U4:
+ case MONO_TYPE_R4:
+ size = 4; break;
+ case MONO_TYPE_R8:
+#ifdef ARM_FPU_FPA
+ return NULL; /* stupid ARM FP swapped format */
+#endif
+ case MONO_TYPE_I8:
+ case MONO_TYPE_U8:
+ size = 8; break;
+#endif
+ default:
+ return NULL;
+ }
+ size *= newarr->inst_newa_len->inst_c0;
+ *out_size = size;
+ /*g_print ("optimized in %s: size: %d, numelems: %d\n", method->name, size, newarr->inst_newa_len->inst_c0);*/
+ field_index = read32 (ip + 2) & 0xffffff;
+ mono_metadata_field_info (method->klass->image, field_index - 1, NULL, &rva, NULL);
+ data_ptr = mono_image_rva_map (method->klass->image, rva);
+ /*g_print ("field: 0x%08x, rva: %d, rva_ptr: %p\n", read32 (ip + 2), rva, data_ptr);*/
+ /* for aot code we do the lookup on load */
+ if (aot && data_ptr)
+ return GUINT_TO_POINTER (rva);
+ return data_ptr;
+ }
+ return NULL;
+}
+
/*
* mono_method_to_ir: translates IL into basic blocks containing trees
*/
mono_jit_stats.cil_code_size += header->code_size;
if (sig->is_inflated)
- generic_context = ((MonoMethodInflated *) method)->context;
+ generic_context = mono_method_get_context (method);
else if (generic_container)
generic_context = &generic_container->context;
tblock->flags |= BB_EXCEPTION_DEAD_OBJ;
if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY ||
- clause->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
+ clause->flags == MONO_EXCEPTION_CLAUSE_FILTER ||
+ clause->flags == MONO_EXCEPTION_CLAUSE_FAULT) {
MONO_INST_NEW (cfg, ins, OP_START_HANDLER);
MONO_ADD_INS (tblock, ins);
ins->cil_code = ip;
if (!dont_verify_stloc && target_type_is_incompatible (cfg, param_types [ip [1]], *sp))
UNVERIFIED;
+ STARG_SOFT_FLOAT (cfg, ins, ip [1], ip);
if (ins->opcode == CEE_STOBJ) {
NEW_ARGLOADA (cfg, ins, ip [1]);
handle_stobj (cfg, bblock, ins, *sp, ip, ins->klass, FALSE, FALSE, FALSE);
} else if (constrained_call) {
cmethod = mono_get_method_constrained (image, token, constrained_call, generic_context, &cil_method);
cmethod = mono_get_inflated_method (cmethod);
+ cil_method = cmethod;
} else {
cmethod = mini_get_method (method, token, NULL, generic_context);
cil_method = cmethod;
NEW_TEMPLOAD (cfg, iargs [0], this_temp->inst_c0);
NEW_PCONST (cfg, iargs [1], cmethod);
- NEW_PCONST (cfg, iargs [2], ((MonoMethodInflated *) cmethod)->context);
+ NEW_PCONST (cfg, iargs [2], mono_method_get_context (cmethod));
NEW_TEMPLOADA (cfg, iargs [3], this_arg_temp->inst_c0);
temp = mono_emit_jit_icall (cfg, bblock, mono_helper_compile_generic_method, iargs, ip);
n = read32 (ip + 1);
if (method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD) {
+ /* FIXME: moving GC */
NEW_PCONST (cfg, ins, mono_method_get_wrapper_data (method, n));
ins->cil_code = ip;
ins->type = STACK_OBJ;
link_bblock (cfg, bblock, tblock);
CHECK_BBLOCK (target, ip, tblock);
ins->inst_target_bb = tblock;
+ GET_BBLOCK (cfg, bbhash, tblock, ip);
+ link_bblock (cfg, bblock, tblock);
if (sp != stack_start) {
handle_stack_args (cfg, bblock, stack_start, sp - stack_start);
sp = stack_start;
ins->inst_newa_class = klass;
ins->inst_newa_len = *sp;
ins->type = STACK_OBJ;
- ins->klass = klass;
+ ins->klass = mono_array_class_get (klass, 1);
ip += 5;
*sp++ = ins;
/*
*/
if (1) {
MonoInst *store, *temp, *load;
+ const char *data_ptr;
+ int data_size = 0;
--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);
+ /*
+ * we inline/optimize the initialization sequence if possible.
+ * we should also allocate the array as not cleared, since we spend as much time clearing to 0 as initializing
+ * for small sizes open code the memcpy
+ * ensure the rva field is big enough
+ */
+ if ((cfg->opt & MONO_OPT_INTRINS) && ip_in_bb (cfg, bblock, ip + 6) && (data_ptr = initialize_array_data (method, cfg->compile_aot, ip, ins, &data_size))) {
+ MonoMethod *memcpy_method = get_memcpy_method ();
+ MonoInst *data_offset, *add;
+ MonoInst *iargs [3];
+ NEW_ICONST (cfg, iargs [2], data_size);
+ NEW_TEMPLOAD (cfg, load, temp->inst_c0);
+ load->cil_code = ins->cil_code;
+ NEW_ICONST (cfg, data_offset, G_STRUCT_OFFSET (MonoArray, vector));
+ MONO_INST_NEW (cfg, add, OP_PADD);
+ add->inst_left = load;
+ add->inst_right = data_offset;
+ add->cil_code = ip;
+ iargs [0] = add;
+ if (cfg->compile_aot) {
+ NEW_AOTCONST_TOKEN (cfg, iargs [1], MONO_PATCH_INFO_RVA, method->klass->image, GPOINTER_TO_UINT(data_ptr), STACK_PTR, NULL);
+ } else {
+ NEW_PCONST (cfg, iargs [1], (char*)data_ptr);
+ }
+ mono_emit_method_call_spilled (cfg, bblock, memcpy_method, memcpy_method->signature, iargs, ip, NULL);
+ ip += 11;
+ }
NEW_TEMPLOAD (cfg, load, temp->inst_c0);
load->cil_code = ins->cil_code;
*sp++ = load;
*/
if (!klass->valuetype && method->wrapper_type == MONO_WRAPPER_NONE) {
MonoInst* check;
+
+ /* Needed by the code generated in inssel.brg */
+ mono_get_got_var (cfg);
+
MONO_INST_NEW (cfg, check, OP_CHECK_ARRAY_TYPE);
check->cil_code = ip;
check->klass = klass;
sp -= 2;
if (sp [0]->type != STACK_OBJ)
UNVERIFIED;
- klass = array_access_to_klass (*ip);
+ klass = array_access_to_klass (*ip, sp [0]);
NEW_LDELEMA (cfg, load, sp, klass);
load->cil_code = ip;
#ifdef MONO_ARCH_SOFT_FLOAT
sp -= 3;
if (sp [0]->type != STACK_OBJ)
UNVERIFIED;
- klass = array_access_to_klass (*ip);
+ klass = array_access_to_klass (*ip, sp [0]);
NEW_LDELEMA (cfg, load, sp, klass);
load->cil_code = ip;
#ifdef MONO_ARCH_SOFT_FLOAT
}
}
- /* fixme: call fault handler ? */
-
if ((handlers = mono_find_final_block (cfg, ip, target, MONO_EXCEPTION_CLAUSE_FINALLY))) {
GList *tmp;
for (tmp = handlers; tmp; tmp = tmp->next) {
token = read32 (ip + 2);
func = mono_method_get_wrapper_data (method, token);
info = mono_find_jit_icall_by_addr (func);
- g_assert (info);
+ if (info == NULL){
+ g_error ("An attempt has been made to perform an icall to address %p, "
+ "but the address has not been registered as an icall\n", info);
+ g_assert_not_reached ();
+ }
CHECK_STACK (info->sig->param_count);
sp -= info->sig->param_count;
ins->cil_code = ip;
if (!dont_verify_stloc && target_type_is_incompatible (cfg, param_types [n], *sp))
UNVERIFIED;
+ STARG_SOFT_FLOAT (cfg, ins, n, ip);
if (ins->opcode == CEE_STOBJ) {
NEW_ARGLOADA (cfg, ins, n);
handle_stobj (cfg, bblock, ins, *sp, ip, ins->klass, FALSE, FALSE, FALSE);
typedef struct {
MonoClass *vtype;
GList *active;
- GList *slots;
+ GSList *slots;
} StackSlotInfo;
+static inline GSList*
+g_slist_prepend_mempool (MonoMemPool *mp, GSList *list,
+ gpointer data)
+{
+ GSList *new_list;
+
+ new_list = mono_mempool_alloc (mp, sizeof (GSList));
+ new_list->data = data;
+ new_list->next = list;
+
+ return new_list;
+}
+
/*
* mono_allocate_stack_slots_full:
*
* Allocate stack slots for all non register allocated variables using a
* linear scan algorithm.
- * Returns: an array of stack offsets which the caller should free.
+ * Returns: an array of stack offsets.
* STACK_SIZE is set to the amount of stack space needed.
* STACK_ALIGN is set to the alignment needed by the locals area.
*/
MonoType *t;
int nvtypes;
- scalar_stack_slots = g_new0 (StackSlotInfo, MONO_TYPE_PINNED);
- vtype_stack_slots = g_new0 (StackSlotInfo, 256);
+ scalar_stack_slots = mono_mempool_alloc0 (m->mempool, sizeof (StackSlotInfo) * MONO_TYPE_PINNED);
+ vtype_stack_slots = NULL;
nvtypes = 0;
- offsets = g_new (gint32, m->num_varinfo);
+ offsets = mono_mempool_alloc (m->mempool, sizeof (gint32) * m->num_varinfo);
for (i = 0; i < m->num_varinfo; ++i)
offsets [i] = -1;
}
/* Fall through */
case MONO_TYPE_VALUETYPE:
+ if (!vtype_stack_slots)
+ vtype_stack_slots = mono_mempool_alloc0 (m->mempool, sizeof (StackSlotInfo) * 256);
for (i = 0; i < nvtypes; ++i)
if (t->data.klass == vtype_stack_slots [i].vtype)
break;
nvtypes ++;
}
break;
+ case MONO_TYPE_CLASS:
+ case MONO_TYPE_OBJECT:
+ case MONO_TYPE_ARRAY:
+ case MONO_TYPE_SZARRAY:
+ case MONO_TYPE_STRING:
+ case MONO_TYPE_PTR:
+ case MONO_TYPE_I:
+ case MONO_TYPE_U:
+#if SIZEOF_VOID_P == 4
+ case MONO_TYPE_I4:
+#else
+ case MONO_TYPE_I8:
+#endif
+ /* Share non-float stack slots of the same size */
+ slot_info = &scalar_stack_slots [MONO_TYPE_CLASS];
+ break;
default:
slot_info = &scalar_stack_slots [t->type];
}
//printf ("EXPIR %2d %08x %08x C%d R%d\n", amv->idx, amv->range.first_use.abs_pos, amv->range.last_use.abs_pos, amv->spill_costs, amv->reg);
slot_info->active = g_list_delete_link (slot_info->active, slot_info->active);
- slot_info->slots = g_list_prepend (slot_info->slots, GINT_TO_POINTER (offsets [amv->idx]));
+ slot_info->slots = g_slist_prepend_mempool (m->mempool, slot_info->slots, GINT_TO_POINTER (offsets [amv->idx]));
}
/*
if (slot_info->slots) {
slot = GPOINTER_TO_INT (slot_info->slots->data);
- slot_info->slots = g_list_delete_link (slot_info->slots, slot_info->slots);
+ slot_info->slots = slot_info->slots->next;
}
slot_info->active = mono_varlist_insert_sorted (m, slot_info->active, vmv, TRUE);
}
g_list_free (vars);
for (i = 0; i < MONO_TYPE_PINNED; ++i) {
- g_list_free (scalar_stack_slots [i].active);
- g_list_free (scalar_stack_slots [i].slots);
+ if (scalar_stack_slots [i].active)
+ g_list_free (scalar_stack_slots [i].active);
}
for (i = 0; i < nvtypes; ++i) {
- g_list_free (vtype_stack_slots [i].active);
- g_list_free (vtype_stack_slots [i].slots);
+ if (vtype_stack_slots [i].active)
+ g_list_free (vtype_stack_slots [i].active);
}
- g_free (scalar_stack_slots);
- g_free (vtype_stack_slots);
+
+ mono_jit_stats.locals_stack_size += offset;
*stack_size = offset;
return offsets;
memcpy (res, patch_info, sizeof (MonoJumpInfo));
switch (patch_info->type) {
+ case MONO_PATCH_INFO_RVA:
case MONO_PATCH_INFO_LDSTR:
case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
case MONO_PATCH_INFO_LDTOKEN:
const MonoJumpInfo *ji = (MonoJumpInfo*)data;
switch (ji->type) {
+ case MONO_PATCH_INFO_RVA:
case MONO_PATCH_INFO_LDSTR:
case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
case MONO_PATCH_INFO_LDTOKEN:
return 0;
switch (ji1->type) {
+ case MONO_PATCH_INFO_RVA:
case MONO_PATCH_INFO_LDSTR:
case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
case MONO_PATCH_INFO_LDTOKEN:
target = (char*)vtable->data + patch_info->data.field->offset;
break;
}
+ case MONO_PATCH_INFO_RVA:
+ target = mono_image_rva_map (patch_info->data.token->image, patch_info->data.token->token);
+ break;
case MONO_PATCH_INFO_R4:
case MONO_PATCH_INFO_R8:
target = patch_info->data.target;
}
emit_state (cfg, mbstate, MB_NTERM_stmt);
}
- bb->max_ireg = cfg->rs->next_vireg;
- bb->max_freg = cfg->rs->next_vfreg;
+ bb->max_vreg = cfg->rs->next_vreg;
if (bb->last_ins)
bb->last_ins->next = NULL;
g_list_free (regs);
}
+ /* todo: remove code when we have verified that the liveness for try/catch blocks
+ * works perfectly
+ */
+ /*
+ * Currently, this can't be commented out since exception blocks are not
+ * processed during liveness analysis.
+ */
+ mono_liveness_handle_exception_clauses (cfg);
+
if (cfg->opt & MONO_OPT_LINEARS) {
GList *vars, *regs;
mono_arch_handle_exception (ctx, exc, FALSE);
}
+#ifndef PLATFORM_WIN32
+
static void
SIG_HANDLER_SIGNATURE (sigabrt_signal_handler)
{
mono_print_thread_dump (ctx);
}
+static void
+SIG_HANDLER_SIGNATURE (sigusr2_signal_handler)
+{
+ gboolean enabled = mono_trace_is_enabled ();
+
+ mono_trace_enable (!enabled);
+}
+
+#endif
+
static void
SIG_HANDLER_SIGNATURE (sigint_signal_handler)
{
mono_arch_handle_exception (ctx, exc, FALSE);
}
-static void
-SIG_HANDLER_SIGNATURE (sigusr2_signal_handler)
-{
- gboolean enabled = mono_trace_is_enabled ();
-
- mono_trace_enable (!enabled);
-}
-
#ifdef PLATFORM_MACOSX
/*
}
#endif
+#ifdef PLATFORM_WIN32
+static HANDLE win32_main_thread;
+static MMRESULT win32_timer;
+
+static void CALLBACK
+win32_time_proc (UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
+{
+ CONTEXT context;
+
+ context.ContextFlags = CONTEXT_CONTROL;
+ if (GetThreadContext (win32_main_thread, &context)) {
+#ifdef _WIN64
+ mono_profiler_stat_hit ((guchar *) context.Rip, &context);
+#else
+ mono_profiler_stat_hit ((guchar *) context.Eip, &context);
+#endif
+ }
+}
+#endif
+
static void
setup_stat_profiler (void)
{
return;
inited = 1;
add_signal_handler (SIGPROF, sigprof_signal_handler);
+#elif defined (PLATFORM_WIN32)
+ static int inited = 0;
+ TIMECAPS timecaps;
+
+ if (inited)
+ return;
+
+ inited = 1;
+ if (timeGetDevCaps (&timecaps, sizeof (timecaps)) != TIMERR_NOERROR)
+ return;
+
+ if ((win32_main_thread = OpenThread (READ_CONTROL | THREAD_GET_CONTEXT, FALSE, GetCurrentThreadId ())) == NULL)
+ return;
+
+ if (timeBeginPeriod (1) != TIMERR_NOERROR)
+ return;
+
+ if ((win32_timer = timeSetEvent (1, 0, win32_time_proc, 0, TIME_PERIODIC)) == 0) {
+ timeEndPeriod (1);
+ return;
+ }
#endif
}
g_print ("Allocated code size: %ld\n", mono_jit_stats.allocated_code_size);
g_print ("Inlineable methods: %ld\n", mono_jit_stats.inlineable_methods);
g_print ("Inlined methods: %ld\n", mono_jit_stats.inlined_methods);
-
+ g_print ("Locals stack size: %ld\n", mono_jit_stats.locals_stack_size);
+
g_print ("\nCreated object count: %ld\n", mono_stats.new_object_count);
g_print ("Initialized classes: %ld\n", mono_stats.initialized_class_count);
g_print ("Used classes: %ld\n", mono_stats.used_class_count);