diff options
author | Zoltan Varga <vargaz@gmail.com> | 2004-07-08 23:15:11 +0400 |
---|---|---|
committer | Zoltan Varga <vargaz@gmail.com> | 2004-07-08 23:15:11 +0400 |
commit | 3f3302374872f3afa8984d1ec2a5cb09527175ef (patch) | |
tree | 67db20383afefc5cdcfd72c8f50ae822d95873d3 | |
parent | 8a2c6383e9d7412d5ef04f141e1d602e377de36a (diff) |
Merge from HEAD.
svn path=/branches/mono-1-0/mono/; revision=30898
-rw-r--r-- | mono/mini/ChangeLog | 5 | ||||
-rw-r--r-- | mono/mini/mini.c | 84 | ||||
-rw-r--r-- | mono/mini/mini.h | 1 |
3 files changed, 70 insertions, 20 deletions
diff --git a/mono/mini/ChangeLog b/mono/mini/ChangeLog index cdcd480a069..dad985c6904 100644 --- a/mono/mini/ChangeLog +++ b/mono/mini/ChangeLog @@ -1,3 +1,8 @@ +2004-07-08 Zoltan Varga <vargaz@freemail.hu> + + * mini.c (handle_stack_args): Handle some corner cases. Fixes + 58863. + 2004-07-05 Zoltan Varga <vargaz@freemail.hu> * mini.c (optimize_branches): Fix linking of bblocks in branch->branch diff --git a/mono/mini/mini.c b/mono/mini/mini.c index d1e340a5966..14a32f6dd6c 100644 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -1581,23 +1581,24 @@ mono_compile_get_interface_var (MonoCompile *cfg, int slot, MonoInst *ins) */ 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; } @@ -1606,19 +1607,34 @@ handle_stack_args (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst **sp, int coun if (!found) { bb->out_stack = mono_mempool_alloc (cfg->mempool, sizeof (MonoInst*) * count); for (i = 0; i < count; ++i) { -/* see bug#58863, but removing this code causes regressions in gtk-sharp build - * (SEGV running Method::Initialize() in gapi_codegen.exe) - */ -#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 */ @@ -1633,14 +1649,36 @@ handle_stack_args (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst **sp, int coun 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; } @@ -2427,6 +2465,7 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, 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)); @@ -2455,8 +2494,13 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, 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); + 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)); diff --git a/mono/mini/mini.h b/mono/mini/mini.h index adc1e9086b5..e62be1b95cb 100644 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -492,6 +492,7 @@ typedef struct { MonoSpillInfo *spill_info_float; /* fp register spills */ gint spill_count; /* unsigned char *cil_code; */ + MonoMethod *inlined_method; /* the method which is currently inlined */ /* the exception object passed to catch/filter blocks */ MonoInst *exvar; |