Ejemplo n.º 1
0
static void reset_back_edge(ptr_t p, size_t n_bytes GC_ATTR_UNUSED,
                            word gc_descr GC_ATTR_UNUSED)
{
  /* Skip any free list links, or dropped blocks */
  if (GC_HAS_DEBUG_INFO(p)) {
    ptr_t old_back_ptr = GET_OH_BG_PTR(p);
    if ((word)old_back_ptr & FLAG_MANY) {
      back_edges *be = (back_edges *)((word)old_back_ptr & ~FLAG_MANY);
      if (!(be -> flags & RETAIN)) {
        deallocate_back_edges(be);
        SET_OH_BG_PTR(p, 0);
      } else {

        GC_ASSERT(GC_is_marked(p));

        /* Back edges may point to objects that will not be retained.   */
        /* Delete them for now, but remember the height.                */
        /* Some will be added back at next GC.                          */
          be -> n_edges = 0;
          if (0 != be -> cont) {
            deallocate_back_edges(be -> cont);
            be -> cont = 0;
          }

        GC_ASSERT(GC_is_marked(p));

        /* We only retain things for one GC cycle at a time.            */
          be -> flags &= ~RETAIN;
      }
    } else /* Simple back pointer */ {
      /* Clear to avoid dangling pointer. */
      SET_OH_BG_PTR(p, 0);
    }
  }
}
Ejemplo n.º 2
0
/* q are pointers to the object base, i.e. pointers to an oh.		*/
static void add_edge(ptr_t p,  ptr_t q)
{
    ptr_t old_back_ptr = GET_OH_BG_PTR(q);
    back_edges * be, *be_cont;
    word i;
    static unsigned random_number = 13;
#   define GOT_LUCKY_NUMBER (((++random_number) & 0x7f) == 0)
      /* A not very random number we use to occasionally allocate a	*/
      /* back_edges structure even for a single backward edge.  This	*/
      /* prevents us from repeatedly tracing back through very long	*/
      /* chains, since we will have some place to store height and	*/
      /* in_progress flags along the way.				*/

    GC_ASSERT(p == GC_base(p) && q == GC_base(q));
    if (!GC_HAS_DEBUG_INFO(q) || !GC_HAS_DEBUG_INFO(p)) {
      /* This is really a misinterpreted free list link, since we saw */
      /* a pointer to a free list.  Dont overwrite it!		      */
      return;
    }
    if (0 == old_back_ptr) {
	SET_OH_BG_PTR(q, p);
	if (GOT_LUCKY_NUMBER) ensure_struct(q);
	return;
    }
    /* Check whether it was already in the list of predecessors. */
      FOR_EACH_PRED(pred, q, { if (p == pred) return; });
Ejemplo n.º 3
0
/* Ensure that p has a back_edges structure associated with it.	*/
static void ensure_struct(ptr_t p)
{
  ptr_t old_back_ptr = GET_OH_BG_PTR(p);

  if (!((word)old_back_ptr & FLAG_MANY)) {
    back_edges *be = new_back_edges();
    be -> flags = 0;
    if (0 == old_back_ptr) {
      be -> n_edges = 0;
    } else {
      be -> n_edges = 1;
      be -> edges[0] = old_back_ptr;
    }
    be -> height = HEIGHT_UNKNOWN;
    be -> height_gc_no = (unsigned short)(GC_gc_no - 1);
    GC_ASSERT(be >= back_edge_space);
    SET_OH_BG_PTR(p, (word)be | FLAG_MANY);
  }
}
Ejemplo n.º 4
0
    GC_ASSERT(p == GC_base(p) && q == GC_base(q));
    if (!GC_HAS_DEBUG_INFO(q) || !GC_HAS_DEBUG_INFO(p)) {
      /* This is really a misinterpreted free list link, since we saw */
      /* a pointer to a free list.  Dont overwrite it!		      */
      return;
    }
    if (0 == old_back_ptr) {
	SET_OH_BG_PTR(q, p);
	if (GOT_LUCKY_NUMBER) ensure_struct(q);
	return;
    }
    /* Check whether it was already in the list of predecessors. */
      FOR_EACH_PRED(pred, q, { if (p == pred) return; });
    ensure_struct(q);
    old_back_ptr = GET_OH_BG_PTR(q);
    be = (back_edges *)((word)old_back_ptr & ~FLAG_MANY);
    for (i = be -> n_edges, be_cont = be; i > MAX_IN;
	be_cont = be_cont -> cont, i -= MAX_IN) {}
    if (i == MAX_IN) {
	be_cont -> cont = new_back_edges();
	be_cont = be_cont -> cont;
	i = 0;
    }
    be_cont -> edges[i] = p;
    be -> n_edges++;
    if (be -> n_edges == 100) {
#       if 0
	  if (GC_print_stats) {
	    GC_err_printf("The following object has in-degree >= 100:\n");
	    GC_print_heap_obj(q);
Ejemplo n.º 5
0
/* GC_deepest_obj to be the corresponding object.                       */
static void update_max_height(ptr_t p, size_t n_bytes GC_ATTR_UNUSED,
                              word gc_descr GC_ATTR_UNUSED)
{
  if (GC_is_marked(p) && GC_HAS_DEBUG_INFO(p)) {
    word p_height = 0;
    ptr_t p_deepest_obj = 0;
    ptr_t back_ptr;
    back_edges *be = 0;

    /* If we remembered a height last time, use it as a minimum.        */
    /* It may have increased due to newly unreachable chains pointing   */
    /* to p, but it can't have decreased.                               */
    back_ptr = GET_OH_BG_PTR(p);
    if (0 != back_ptr && ((word)back_ptr & FLAG_MANY)) {
      be = (back_edges *)((word)back_ptr & ~FLAG_MANY);
      if (be -> height != HEIGHT_UNKNOWN) p_height = be -> height;
    }

    {
      ptr_t pred = GET_OH_BG_PTR(p);
      back_edges *e = (back_edges *)((word)pred & ~FLAG_MANY);
      word n_edges;
      word total;
      int local = 0;

      if (((word)pred & FLAG_MANY) != 0) {
        n_edges = e -> n_edges;
      } else if (pred != NULL && ((word)pred & 1) == 0) {
        /* A misinterpreted freelist link.      */
        n_edges = 1;
        local = -1;
      } else {
        n_edges = 0;
      }
      for (total = 0; total < n_edges; ++total) {
        if (local == MAX_IN) {
          e = e -> cont;
          local = 0;
        }
        if (local >= 0)
          pred = e -> edges[local++];

        /* Execute the following once for each predecessor pred of p    */
        /* in the points-to graph.                                      */
        if (!GC_is_marked(pred) && GC_HAS_DEBUG_INFO(pred)) {
          word this_height = backwards_height(pred);
          if (this_height > p_height) {
            p_height = this_height;
            p_deepest_obj = pred;
          }
        }
      }
    }

    if (p_height > 0) {
      /* Remember the height for next time. */
        if (be == 0) {
          ensure_struct(p);
          back_ptr = GET_OH_BG_PTR(p);
          be = (back_edges *)((word)back_ptr & ~FLAG_MANY);
        }
        be -> flags |= RETAIN;
        be -> height = p_height;
        be -> height_gc_no = (unsigned short)GC_gc_no;
    }
    if (p_height > GC_max_height) {
        GC_max_height = p_height;
        GC_deepest_obj = p_deepest_obj;
    }
  }
}
Ejemplo n.º 6
0
/* of p.                                                                */
static word backwards_height(ptr_t p)
{
  word result;
  ptr_t pred = GET_OH_BG_PTR(p);
  back_edges *be;

  if (NULL == pred)
    return 1;
  if (((word)pred & FLAG_MANY) == 0) {
    if (is_in_progress(p)) return 0; /* DFS back edge, i.e. we followed */
                                     /* an edge to an object already    */
                                     /* on our stack: ignore            */
    push_in_progress(p);
    result = backwards_height(pred) + 1;
    pop_in_progress(p);
    return result;
  }
  be = (back_edges *)((word)pred & ~FLAG_MANY);
  if (be -> height >= 0 && be -> height_gc_no == (unsigned short)GC_gc_no)
      return be -> height;
  /* Ignore back edges in DFS */
    if (be -> height == HEIGHT_IN_PROGRESS) return 0;
  result = (be -> height > 0? be -> height : 1);
  be -> height = HEIGHT_IN_PROGRESS;

  {
      back_edges *e = be;
      word n_edges;
      word total;
      int local = 0;

      if (((word)pred & FLAG_MANY) != 0) {
        n_edges = e -> n_edges;
      } else if (pred != NULL && ((word)pred & 1) == 0) {
        /* A misinterpreted freelist link.      */
        n_edges = 1;
        local = -1;
      } else {
        n_edges = 0;
      }
      for (total = 0; total < n_edges; ++total) {
        word this_height;
        if (local == MAX_IN) {
          e = e -> cont;
          local = 0;
        }
        if (local >= 0)
          pred = e -> edges[local++];

        /* Execute the following once for each predecessor pred of p    */
        /* in the points-to graph.                                      */
        if (GC_is_marked(pred) && ((word)GET_OH_BG_PTR(p) & FLAG_MANY) == 0) {
          GC_COND_LOG_PRINTF("Found bogus pointer from %p to %p\n",
                             (void *)pred, (void *)p);
            /* Reachable object "points to" unreachable one.            */
            /* Could be caused by our lax treatment of GC descriptors.  */
          this_height = 1;
        } else {
          this_height = backwards_height(pred);
        }
        if (this_height >= result)
          result = this_height + 1;
      }
  }

  be -> height = result;
  be -> height_gc_no = (unsigned short)GC_gc_no;
  return result;
}
Ejemplo n.º 7
0
/* q are pointers to the object base, i.e. pointers to an oh.           */
static void add_edge(ptr_t p, ptr_t q)
{
    ptr_t pred = GET_OH_BG_PTR(q);
    back_edges * be, *be_cont;
    word i;

    GC_ASSERT(p == GC_base(p) && q == GC_base(q));
    if (!GC_HAS_DEBUG_INFO(q) || !GC_HAS_DEBUG_INFO(p)) {
      /* This is really a misinterpreted free list link, since we saw   */
      /* a pointer to a free list.  Don't overwrite it!                 */
      return;
    }
    if (NULL == pred) {
      static unsigned random_number = 13;
#     define GOT_LUCKY_NUMBER (((++random_number) & 0x7f) == 0)
        /* A not very random number we use to occasionally allocate a   */
        /* back_edges structure even for a single backward edge.  This  */
        /* prevents us from repeatedly tracing back through very long   */
        /* chains, since we will have some place to store height and    */
        /* in_progress flags along the way.                             */

        SET_OH_BG_PTR(q, p);
        if (GOT_LUCKY_NUMBER) ensure_struct(q);
        return;
    }

    /* Check whether it was already in the list of predecessors. */
    {
      back_edges *e = (back_edges *)((word)pred & ~FLAG_MANY);
      word n_edges;
      word total;
      int local = 0;

      if (((word)pred & FLAG_MANY) != 0) {
        n_edges = e -> n_edges;
      } else if (pred != NULL && ((word)pred & 1) == 0) {
        /* A misinterpreted freelist link.      */
        n_edges = 1;
        local = -1;
      } else {
        n_edges = 0;
      }
      for (total = 0; total < n_edges; ++total) {
        if (local == MAX_IN) {
          e = e -> cont;
          local = 0;
        }
        if (local >= 0)
          pred = e -> edges[local++];
        if (pred == p)
          return;
      }
    }

    ensure_struct(q);
    be = (back_edges *)((word)GET_OH_BG_PTR(q) & ~FLAG_MANY);
    for (i = be -> n_edges, be_cont = be; i > MAX_IN; i -= MAX_IN)
        be_cont = be_cont -> cont;
    if (i == MAX_IN) {
        be_cont -> cont = new_back_edges();
        be_cont = be_cont -> cont;
        i = 0;
    }
    be_cont -> edges[i] = p;
    be -> n_edges++;
#   ifdef DEBUG_PRINT_BIG_N_EDGES
      if (GC_print_stats == VERBOSE && be -> n_edges == 100) {
        GC_err_printf("The following object has big in-degree:\n");
        GC_print_heap_obj(q);
      }
#   endif
}