Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZoltan Varga <vargaz@gmail.com>2012-12-05 16:49:15 +0400
committerZoltan Varga <vargaz@gmail.com>2012-12-05 16:49:15 +0400
commit9e7f20630990870ec2fb9a9d357d462c4dafe228 (patch)
tree5f9d324b13214801f9a6111011f21a244c89c35b
parent1b5becdecc831a4befa9c246c49c9c888532bc08 (diff)
Treat param area stack slots as being part of the callee frame, not the caller, so precise stack marking works for methods with tail calls as well.mono-3.0.2
-rw-r--r--mono/mini/mini-gc.c92
1 files changed, 15 insertions, 77 deletions
diff --git a/mono/mini/mini-gc.c b/mono/mini/mini-gc.c
index bc74b10510d..5bbd3751710 100644
--- a/mono/mini/mini-gc.c
+++ b/mono/mini/mini-gc.c
@@ -781,6 +781,8 @@ conservative_pass (TlsData *tls, guint8 *stack_start, guint8 *stack_end)
ji = frame.ji;
+ // FIXME: For skipped frames, scan the param area of the parent frame conservatively ?
+
if (frame.type == FRAME_TYPE_MANAGED_TO_NATIVE) {
/*
* These frames are problematic for several reasons:
@@ -1668,10 +1670,6 @@ process_variables (MonoCompile *cfg)
if (ins->inst_offset % SIZEOF_SLOT != 0)
continue;
- if (is_arg && ins->inst_offset >= gcfg->max_offset)
- /* In parent frame */
- continue;
-
pos = fp_offset_to_slot (cfg, ins->inst_offset);
if (is_arg && ins->flags & MONO_INST_IS_DEAD) {
@@ -1792,7 +1790,7 @@ process_variables (MonoCompile *cfg)
if (!mini_type_is_reference (cfg, t)) {
set_slot_everywhere (gcfg, pos, SLOT_NOREF);
if (cfg->verbose_level > 1)
- printf ("\tnoref at %s0x%x(fp) (R%d, slot = %d): %s\n", ins->inst_offset < 0 ? "-" : "", (ins->inst_offset < 0) ? -(int)ins->inst_offset : (int)ins->inst_offset, vmv->vreg, pos, mono_type_full_name (ins->inst_vtype));
+ printf ("\tnoref%s at %s0x%x(fp) (R%d, slot = %d): %s\n", (is_arg ? " arg" : ""), ins->inst_offset < 0 ? "-" : "", (ins->inst_offset < 0) ? -(int)ins->inst_offset : (int)ins->inst_offset, vmv->vreg, pos, mono_type_full_name (ins->inst_vtype));
if (!t->byref && sizeof (mgreg_t) == 4 && (t->type == MONO_TYPE_I8 || t->type == MONO_TYPE_U8 || t->type == MONO_TYPE_R8)) {
set_slot_everywhere (gcfg, pos + 1, SLOT_NOREF);
if (cfg->verbose_level > 1)
@@ -1830,7 +1828,7 @@ process_variables (MonoCompile *cfg)
}
if (cfg->verbose_level > 1) {
- printf ("\tref at %s0x%x(fp) (R%d, slot = %d): %s\n", ins->inst_offset < 0 ? "-" : "", (ins->inst_offset < 0) ? -(int)ins->inst_offset : (int)ins->inst_offset, vmv->vreg, pos, mono_type_full_name (ins->inst_vtype));
+ printf ("\tref%s at %s0x%x(fp) (R%d, slot = %d): %s\n", (is_arg ? " arg" : ""), ins->inst_offset < 0 ? "-" : "", (ins->inst_offset < 0) ? -(int)ins->inst_offset : (int)ins->inst_offset, vmv->vreg, pos, mono_type_full_name (ins->inst_vtype));
}
}
@@ -1858,28 +1856,6 @@ sp_offset_to_fp_offset (MonoCompile *cfg, int sp_offset)
#endif
}
-static GCSlotType
-type_to_gc_slot_type (MonoCompile *cfg, MonoType *t)
-{
- if (t->byref)
- return SLOT_PIN;
- t = mini_type_get_underlying_type (NULL, t);
- if (mini_type_is_reference (cfg, t))
- return SLOT_REF;
- else {
- if (MONO_TYPE_ISSTRUCT (t)) {
- MonoClass *klass = mono_class_from_mono_type (t);
- if (!klass->has_references) {
- return SLOT_NOREF;
- } else {
- // FIXME:
- return SLOT_PIN;
- }
- }
- return SLOT_NOREF;
- }
-}
-
static void
process_param_area_slots (MonoCompile *cfg)
{
@@ -1929,54 +1905,10 @@ process_param_area_slots (MonoCompile *cfg)
set_slot_everywhere (gcfg, i, SLOT_NOREF);
}
- for (cindex = 0; cindex < gcfg->ncallsites; ++cindex) {
- GCCallSite *callsite = gcfg->callsites [cindex];
- GSList *l;
-
- for (l = callsite->param_slots; l; l = l->next) {
- MonoInst *def = l->data;
- MonoType *t = def->inst_vtype;
- int sp_offset = def->inst_offset;
- int fp_offset = sp_offset_to_fp_offset (cfg, sp_offset);
- int slot = fp_offset_to_slot (cfg, fp_offset);
- GCSlotType type = type_to_gc_slot_type (cfg, t);
-
- if (MONO_TYPE_ISSTRUCT (t)) {
- guint32 align;
- guint32 size;
- int size_in_slots;
- gsize *bitmap;
- int j, numbits;
-
- size = mini_type_stack_size_full (cfg->generic_sharing_context, t, &align, FALSE);
- size_in_slots = ALIGN_TO (size, SIZEOF_SLOT) / SIZEOF_SLOT;
-
- bitmap = get_vtype_bitmap (t, &numbits);
- if (type == SLOT_NOREF || !bitmap) {
- for (i = 0; i < size_in_slots; ++i) {
- set_slot_in_range (gcfg, slot + i, def->backend.pc_offset, callsite->pc_offset + 1, type);
- }
- if (cfg->verbose_level > 1)
- printf ("\t%s param area slots at %s0x%x(fp)=0x%x(sp) (slot = %d-%d) [0x%x-0x%x]\n", slot_type_to_string (type), get_offset_sign (fp_offset), get_offset_val (fp_offset), sp_offset, slot, slot + (size / (int)sizeof (mgreg_t)), def->backend.pc_offset, callsite->pc_offset + 1);
- } else {
- for (j = 0; j < numbits; ++j) {
- if (bitmap [j / GC_BITS_PER_WORD] & ((gsize)1 << (j % GC_BITS_PER_WORD))) {
- /* The descriptor is for the boxed object */
- set_slot (gcfg, (slot + j - (sizeof (MonoObject) / SIZEOF_SLOT)), cindex, SLOT_REF);
- }
- }
- if (cfg->verbose_level > 1)
- printf ("\tvtype param area slots at %s0x%x(fp)=0x%x(sp) (slot = %d-%d) [0x%x-0x%x]\n", get_offset_sign (fp_offset), get_offset_val (fp_offset), sp_offset, slot, slot + (size / (int)sizeof (mgreg_t)), def->backend.pc_offset, callsite->pc_offset + 1);
- }
- g_free (bitmap);
- } else {
- /* The slot is live between the def instruction and the call */
- set_slot_in_range (gcfg, slot, def->backend.pc_offset, callsite->pc_offset + 1, type);
- if (cfg->verbose_level > 1)
- printf ("\t%s param area slot at %s0x%x(fp)=0x%x(sp) (slot = %d) [0x%x-0x%x]\n", slot_type_to_string (type), get_offset_sign (fp_offset), get_offset_val (fp_offset), sp_offset, slot, def->backend.pc_offset, callsite->pc_offset + 1);
- }
- }
- }
+ /*
+ * We treat param area slots as being part of the callee's frame, to be able to handle tail calls which overwrite
+ * the argument area of the caller.
+ */
}
static void
@@ -2067,8 +1999,14 @@ compute_frame_size (MonoCompile *cfg)
for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
MonoInst *ins = cfg->args [i];
- if (ins->opcode == OP_REGOFFSET)
+ if (ins->opcode == OP_REGOFFSET) {
+ int size, size_in_slots;
+ size = mini_type_stack_size_full (cfg->generic_sharing_context, ins->inst_vtype, NULL, ins->backend.is_pinvoke);
+ size_in_slots = ALIGN_TO (size, SIZEOF_SLOT) / SIZEOF_SLOT;
+
min_offset = MIN (min_offset, ins->inst_offset);
+ max_offset = MAX ((int)max_offset, (int)(ins->inst_offset + (size_in_slots * SIZEOF_SLOT)));
+ }
}
/* Cfa slots */