Don't use System.Environment.Exit to finish a sdb session on iOS.
[mono.git] / mono / mini / dominators.c
index a733189d1d10a841eec9e11af0d4e135e66c823a..d4071234f12e0475f79ae9979d0572dcfc19973d 100644 (file)
@@ -6,14 +6,25 @@
  *   Paolo Molaro (lupus@ximian.com)
  *
  * (C) 2003 Ximian, Inc.
+ * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
  */
 #include <string.h>
 #include <mono/metadata/debug-helpers.h>
+#include <mono/metadata/mempool.h>
+#include <mono/metadata/mempool-internals.h>
 
 #include "mini.h"
 
+#ifndef DISABLE_JIT
+
 //#define DEBUG_DOMINATORS
 
+/*
+ * bb->dfn == 0 means either the bblock is ignored by the dfn calculation, or
+ * it is the entry bblock.
+ */
+#define HAS_DFN(bb, entry) ((bb)->dfn || ((bb) == entry))
+
 /*
  * Compute dominators and immediate dominators using the algorithm in the
  * paper "A Simple, Fast Dominance Algorithm" by Keith D. Cooper, 
 static void
 compute_dominators (MonoCompile *cfg)
 {
-       int i, j, bitsize;
-       char* mem;
-       gboolean *in_worklist;
-       MonoBasicBlock **worklist;
-       guint32 l_begin, l_end;
+       int bindex, i, bitsize;
+       MonoBasicBlock *entry;
        MonoBasicBlock **doms;
+       gboolean changed;
 
        g_assert (!(cfg->comp_done & MONO_COMP_DOM));
 
        bitsize = mono_bitset_alloc_size (cfg->num_bblocks, 0);
-       in_worklist = g_new0 (gboolean, cfg->num_bblocks);
-       worklist = g_new (MonoBasicBlock*, cfg->num_bblocks + 1);
-       l_begin = 0;
-       l_end = 0;
 
-       mem = mono_mempool_alloc0 (cfg->mempool, bitsize * cfg->num_bblocks);
-
-       /* the first is always the entry */
-       worklist [l_end ++] = cfg->bblocks [0];
+       entry = cfg->bblocks [0];
 
        doms = g_new0 (MonoBasicBlock*, cfg->num_bblocks);
-       doms [cfg->bblocks [0]->dfn] = cfg->bblocks [0];
+       doms [entry->dfn] = entry;
 
 #ifdef DEBUG_DOMINATORS
        for (i = 0; i < cfg->num_bblocks; ++i) {
@@ -57,63 +59,54 @@ compute_dominators (MonoCompile *cfg)
        }
 #endif
 
-       while (l_begin != l_end) {
-               MonoBasicBlock *bb = worklist [l_begin ++];
-               MonoBasicBlock *idom;
+       changed = TRUE;
+       while (changed) {
+               changed = FALSE;
 
-               in_worklist [bb->dfn] = FALSE;
+               for (bindex = 0; bindex < cfg->num_bblocks; ++bindex) {
+                       MonoBasicBlock *bb = cfg->bblocks [bindex];
+                       MonoBasicBlock *idom;
 
-               if (l_begin == cfg->num_bblocks + 1)
-                       l_begin = 0;
-
-               idom = NULL;
-               for (i = 0; i < bb->in_count; ++i) {
-                       MonoBasicBlock *in_bb = bb->in_bb [i];
-                       if (doms [in_bb->dfn]) {
-                               idom = in_bb;
-                               break;
-                       }
-               }
-               if (bb != cfg->bblocks [0])
-                       g_assert (idom);
-                       
-               while (i < bb->in_count) {
-                       MonoBasicBlock *in_bb = bb->in_bb [i];
-
-                       if (in_bb->dfn && doms [in_bb->dfn]) {
-                               /* Intersect */
-                               MonoBasicBlock *f1 = idom;
-                               MonoBasicBlock *f2 = in_bb;
-
-                               while (f1 != f2) {
-                                       if (f1->dfn < f2->dfn)
-                                               f2 = doms [f2->dfn];
-                                       else
-                                               f1 = doms [f1->dfn];
+                       idom = NULL;
+                       for (i = 0; i < bb->in_count; ++i) {
+                               MonoBasicBlock *in_bb = bb->in_bb [i];
+                               if ((in_bb != bb) && doms [in_bb->dfn]) {
+                                       idom = in_bb;
+                                       break;
                                }
+                       }
+                       if (bb != cfg->bblocks [0])
+                               g_assert (idom);
+
+                       while (i < bb->in_count) {
+                               MonoBasicBlock *in_bb = bb->in_bb [i];
+
+                               if (HAS_DFN (in_bb, entry) && doms [in_bb->dfn]) {
+                                       /* Intersect */
+                                       MonoBasicBlock *f1 = idom;
+                                       MonoBasicBlock *f2 = in_bb;
+
+                                       while (f1 != f2) {
+                                               if (f1->dfn < f2->dfn)
+                                                       f2 = doms [f2->dfn];
+                                               else
+                                                       f1 = doms [f1->dfn];
+                                       }
 
-                               idom = f1;
+                                       idom = f1;
+                               }
+                               i ++;
                        }
-                       i ++;
-               }
 
-               if (idom != doms [bb->dfn]) {
-                       if (bb == cfg->bblocks [0])
-                               doms [bb->dfn] = bb;
-                       else
-                               doms [bb->dfn] = idom;
-                                       
-                       for (j = 0; j < bb->out_count; ++j) {
-                               MonoBasicBlock *out_bb = bb->out_bb [j];
-                               if (!in_worklist [out_bb->dfn]) {
-#ifdef DEBUG_DOMINATORS
-                                       printf ("\tADD %d to worklist.\n", out_bb->dfn);
-#endif
-                                       worklist [l_end ++] = out_bb;
-                                       if (l_end == cfg->num_bblocks + 1)
-                                               l_end = 0;
-                                       in_worklist [out_bb->dfn] = TRUE;
+                       if (idom != doms [bb->dfn]) {
+                               if (bb == cfg->bblocks [0])
+                                       doms [bb->dfn] = bb;
+                               else {
+                                       doms [bb->dfn] = idom;
+                                       changed = TRUE;
                                }
+
+                               //printf ("A: bb=%d dfn=%d dom:%d\n", bb->block_num, bb->dfn, doms [bb->dfn]->block_num);
                        }
                }
        }
@@ -123,6 +116,9 @@ compute_dominators (MonoCompile *cfg)
                MonoBasicBlock *bb = cfg->bblocks [i];
                MonoBasicBlock *cbb;
                MonoBitSet *dominators;
+               char *mem;
+
+               mem = mono_mempool_alloc0 (cfg->mempool, bitsize);
 
                bb->dominators = dominators = mono_bitset_mem_new (mem, cfg->num_bblocks, 0);
                mem += bitsize;
@@ -135,22 +131,20 @@ compute_dominators (MonoCompile *cfg)
 
                        bb->idom = doms [bb->dfn];
                        if (bb->idom)
-                               bb->idom->dominated = g_list_prepend (bb->idom->dominated, bb);
+                               bb->idom->dominated = g_slist_prepend_mempool (cfg->mempool, bb->idom->dominated, bb);
                }
 
                /* The entry bb */
                mono_bitset_set_fast (dominators, 0);
        }
 
-       g_free (worklist);
-       g_free (in_worklist);
        g_free (doms);
 
        cfg->comp_done |= MONO_COMP_DOM | MONO_COMP_IDOM;
 
 #ifdef DEBUG_DOMINATORS
        printf ("DTREE %s %d\n", mono_method_full_name (cfg->method, TRUE), 
-               mono_method_get_header (cfg->method)->num_clauses);
+               cfg->header->num_clauses);
        for (i = 0; i < cfg->num_bblocks; ++i) {
                MonoBasicBlock *bb = cfg->bblocks [i];
                printf ("BB%d(dfn=%d) (IDOM=BB%d): ", bb->block_num, bb->dfn, bb->idom ? bb->idom->block_num : -1);
@@ -159,6 +153,8 @@ compute_dominators (MonoCompile *cfg)
 #endif
 }
 
+#if 0
+
 static void
 check_dominance_frontier (MonoBasicBlock *x, MonoBasicBlock *t)
 {
@@ -187,6 +183,8 @@ check_dominance_frontier (MonoBasicBlock *x, MonoBasicBlock *t)
        }
 } 
 
+#endif
+
 /**
  * Compute dominance frontiers using the algorithm from the same paper.
  */
@@ -265,7 +263,7 @@ df_set (MonoCompile *m, MonoBitSet* dest, MonoBitSet *set)
        int i;
 
        mono_bitset_foreach_bit (set, i, m->num_bblocks) {
-               mono_bitset_union (dest, m->bblocks [i]->dfrontier);
+               mono_bitset_union_fast (dest, m->bblocks [i]->dfrontier);
        }
 }
 
@@ -346,7 +344,7 @@ mono_compute_natural_loops (MonoCompile *cfg)
                                        if ((cb->dfn && mono_bitset_test_fast (in_loop_blocks, cb->dfn)) || (!cb->dfn && g_list_find (h->loop_blocks, cb)))
                                                continue;
 
-                                       h->loop_blocks = g_list_prepend (h->loop_blocks, cb);
+                                       h->loop_blocks = g_list_prepend_mempool (cfg->mempool, h->loop_blocks, cb);
                                        cb->nesting++;
                                        if (cb->dfn)
                                                mono_bitset_set_fast (in_loop_blocks, cb->dfn);
@@ -362,7 +360,7 @@ mono_compute_natural_loops (MonoCompile *cfg)
 
                                /* add the header if not already there */
                                if (!((h->dfn && mono_bitset_test_fast (in_loop_blocks, h->dfn)) || (!h->dfn && g_list_find (h->loop_blocks, h)))) {
-                                       h->loop_blocks = g_list_prepend (h->loop_blocks, h);
+                                       h->loop_blocks = g_list_prepend_mempool (cfg->mempool, h->loop_blocks, h);
                                        h->nesting++;
                                }
                        }
@@ -387,6 +385,9 @@ mono_compute_natural_loops (MonoCompile *cfg)
                        /* The loop body start is the first bblock in the order they will be emitted */
                        MonoBasicBlock *h = cfg->bblocks [i];
                        MonoBasicBlock *body_start = h;
+#if defined(__native_client_codegen__)
+                       MonoInst *inst;
+#endif
                        GList *l;
 
                        for (l = h->loop_blocks; l; l = l->next) {
@@ -397,6 +398,12 @@ mono_compute_natural_loops (MonoCompile *cfg)
                                }
                        }
 
+#if defined(__native_client_codegen__)
+                       /* Instrument the loop (GC back branch safe point) */
+                       MONO_INST_NEW (cfg, inst, OP_NACL_GC_SAFE_POINT);
+                       inst->dreg = mono_alloc_dreg (cfg, STACK_I4);
+                       mono_bblock_insert_before_ins (body_start, NULL, inst);
+#endif
                        body_start->loop_body_start = 1;
                }
        }
@@ -425,7 +432,6 @@ clear_idominators (MonoCompile *cfg)
     
        for (i = 0; i < cfg->num_bblocks; ++i) {
                if (cfg->bblocks[i]->dominated) {
-                       g_list_free (cfg->bblocks[i]->dominated);        
                        cfg->bblocks[i]->dominated = NULL;
                }
        }
@@ -440,10 +446,7 @@ clear_loops (MonoCompile *cfg)
     
        for (i = 0; i < cfg->num_bblocks; ++i) {
                cfg->bblocks[i]->nesting = 0;
-               if (cfg->bblocks[i]->loop_blocks) {
-                       g_list_free (cfg->bblocks[i]->loop_blocks);        
-                       cfg->bblocks[i]->loop_blocks = NULL;
-               }
+               cfg->bblocks[i]->loop_blocks = NULL;
        }
 
        cfg->comp_done &= ~MONO_COMP_LOOPS;   
@@ -457,3 +460,12 @@ mono_free_loop_info (MonoCompile *cfg)
     if (cfg->comp_done & MONO_COMP_LOOPS)
         clear_loops (cfg);
 }
+
+#else /* DISABLE_JIT */
+
+void
+mono_free_loop_info (MonoCompile *cfg)
+{
+}
+
+#endif /* DISABLE_JIT */