more c*****y windows issues.
[mono.git] / mono / mini / liveness.c
index 45d526b82724875ebc325ae696838b0ff95fb503..dca20e64992782c725c56e2777a153a0e8947902 100644 (file)
@@ -72,7 +72,7 @@ update_gen_kill_set (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *inst, int i
                int idx = inst->inst_i0->inst_c0;
                MonoMethodVar *vi = MONO_VARINFO (cfg, idx);
                g_assert (idx < max_vars);
-               if (bb->region != -1) {
+               if ((bb->region != -1) && !MONO_BBLOCK_IS_IN_REGION (bb, MONO_REGION_TRY)) {
                        /*
                         * Variables used in exception regions can't be allocated to 
                         * registers.
@@ -83,12 +83,13 @@ update_gen_kill_set (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *inst, int i
                if (!mono_bitset_test (bb->kill_set, idx))
                        mono_bitset_set (bb->gen_set, idx);
                vi->spill_costs += 1 + (bb->nesting * 2);
-       } else if (inst->ssa_op == MONO_SSA_STORE) {
+       } else if ((inst->ssa_op == MONO_SSA_STORE) || (inst->opcode == OP_DUMMY_STORE)) {
                int idx = inst->inst_i0->inst_c0;
                MonoMethodVar *vi = MONO_VARINFO (cfg, idx);
                g_assert (idx < max_vars);
-               g_assert (inst->inst_i1->opcode != OP_PHI);
-               if (bb->region != -1) {
+               if (arity > 0)
+                       g_assert (inst->inst_i1->opcode != OP_PHI);
+               if ((bb->region != -1) && !MONO_BBLOCK_IS_IN_REGION (bb, MONO_REGION_TRY)) {
                        /*
                         * Variables used in exception regions can't be allocated to 
                         * registers.
@@ -117,32 +118,56 @@ update_volatile (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *inst, int inst_
                int idx = inst->inst_i0->inst_c0;
                MonoMethodVar *vi = MONO_VARINFO (cfg, idx);
                g_assert (idx < max_vars);
-               if (bb->region != -1) {
-                       cfg->varinfo [vi->idx]->flags |= MONO_INST_VOLATILE;
-               }
+               cfg->varinfo [vi->idx]->flags |= MONO_INST_VOLATILE;
        }
 } 
 
+static void
+visit_bb (MonoCompile *cfg, MonoBasicBlock *bb, GSList **visited)
+{
+       int i, tree_num;
+       MonoInst *inst;
+
+       if (g_slist_find (*visited, bb))
+               return;
+
+       for (tree_num = 0, inst = bb->code; inst; inst = inst->next, tree_num++) {
+               update_volatile (cfg, bb, inst, tree_num);
+       }
+
+       *visited = g_slist_append (*visited, bb);
+
+       /* 
+        * Need to visit all bblocks reachable from this one since they can be
+        * reached during exception handling.
+        */
+       for (i = 0; i < bb->out_count; ++i) {
+               visit_bb (cfg, bb->out_bb [i], visited);
+       }
+}
+
 static void
 handle_exception_clauses (MonoCompile *cfg)
 {
        MonoBasicBlock *bb;
+       GSList *visited = NULL;
 
        /*
         * Variables in exception handler register cannot be allocated to registers
-        * so make them volatile. See bug #42136.
+        * so make them volatile. See bug #42136. This will not be neccessary when
+        * the back ends could guarantee that the variables will be in the
+        * correct registers when a handler is called.
+        * This includes try blocks too, since a variable in a try block might be
+        * accessed after an exception handler has been run.
         */
        for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
-               MonoInst *inst;
-               int tree_num;
 
-               if (bb->region == -1)
+               if (bb->region == -1 || MONO_BBLOCK_IS_IN_REGION (bb, MONO_REGION_TRY))
                        continue;
 
-               for (tree_num = 0, inst = bb->code; inst; inst = inst->next, tree_num++) {
-                       update_volatile (cfg, bb, inst, tree_num);
-               }
+               visit_bb (cfg, bb, &visited);
        }
+       g_slist_free (visited);
 }
 
 /* generic liveness analysis code. CFG specific parts are 
@@ -179,6 +204,11 @@ mono_analyze_liveness (MonoCompile *cfg)
                bb->live_in_set = mono_bitset_mp_new (cfg->mempool, max_vars);
                bb->live_out_set = mono_bitset_mp_new (cfg->mempool, max_vars);
        }
+       for (i = 0; i < max_vars; i ++) {
+               MONO_VARINFO (cfg, i)->range.first_use.abs_pos = ~ 0;
+               MONO_VARINFO (cfg, i)->range.last_use .abs_pos =   0;
+               MONO_VARINFO (cfg, i)->spill_costs = 0;
+       }
 
        for (i = 0; i < cfg->num_bblocks; ++i) {
                MonoBasicBlock *bb = cfg->bblocks [i];
@@ -186,7 +216,9 @@ mono_analyze_liveness (MonoCompile *cfg)
                int tree_num;
 
                for (tree_num = 0, inst = bb->code; inst; inst = inst->next, tree_num++) {
-                       //mono_print_tree (inst); printf ("\n");
+#ifdef DEBUG_LIVENESS
+                       mono_print_tree (inst); printf ("\n");
+#endif
                        update_gen_kill_set (cfg, bb, inst, tree_num);
                }