Example #1
0
static void reset_finalizer_tree(GCTYPE *gc)
/* After a GC, move gen0 finalizers to the old finalizer list. Note
   that the old gen0 splay tree is otherwise broken, since object
   addresses have moved. */
{
  Fnl *fnl, *next;

  fnl = gc->gen0_finalizers;
  gc->gen0_finalizers = NULL;
  gc->splayed_gen0_finalizers = NULL;

  for (; fnl; fnl = next) {
    next = fnl->next;
    /* Checking both `fnl` and `fnl->p` is redundant, since
       `fnl` is always allocated after `fnl->p`, but check
       both just in case the order of allocation somehow
       changes in the future. */
    if (is_in_generation_half(gc, fnl)
        || is_in_generation_half(gc, fnl->f)
        || is_in_generation_half(gc, fnl->p)
        || is_in_generation_half(gc, fnl->data))
      add_finalizer(fnl, 1, gc);
    else
      add_finalizer(fnl, 0, gc);
  }

}
Example #2
0
static int mark_ready_ephemerons(GCTYPE *gc, int inc_gen1)
{
  GC_Ephemeron *waiting, *next, *eph;
  int did_one = 0, j;

  GC_mark_no_recur(gc, 1);

  for (j = 0; j < (inc_gen1 ? 1 : 2); j++) {
    if (inc_gen1)
      eph = gc->inc_ephemerons;
    else if (j == 0)
      eph = gc->ephemerons;
    else
      eph = gc->bp_ephemerons;

    waiting = NULL;
    
    for (; eph; eph = next) {
      if (inc_gen1)
        next = eph->inc_next;
      else
        next = eph->next;
      if (is_marked(gc, eph->key)) {
        if (!inc_gen1)
          eph->key = GC_resolve2(eph->key, gc);
        gcMARK2(eph->val, gc);
        gc->num_last_seen_ephemerons++;
        did_one = 1;
        if (!inc_gen1 && (j == 0) && !gc->gc_full && gc->started_incremental) {
          /* Need to preserve the ephemeron in the incremental list,
             unless it's kept in generation 1/2 nistead of promoted to
             generation 1. */
          if (!is_in_generation_half(gc, eph)) {
            eph->inc_next = gc->inc_ephemerons;
            gc->inc_ephemerons = eph;
          }
        }
      } else {
        if (inc_gen1) {
          /* Ensure that we can write to the page containing the emphemeron: */
          check_incremental_unprotect(gc, pagemap_find_page(gc->page_maps, eph));
          eph->inc_next = waiting;
        } else
          eph->next = waiting;
        waiting = eph;
      }
    }

    if (inc_gen1)
      gc->inc_ephemerons = waiting;
    else if (j == 0)
      gc->ephemerons = waiting;
    else
      gc->bp_ephemerons = waiting;
  }

  GC_mark_no_recur(gc, 0);

  return did_one;
}
Example #3
0
static int zero_weak_arrays(GCTYPE *gc, int force_zero, int from_inc, int fuel)
{
  GC_Weak_Array *wa;
  int i, num_gen0;

  if (from_inc) {
    wa = gc->inc_weak_arrays;
    num_gen0 = 0;
  } else
    wa = append_weak_arrays(gc->weak_arrays, gc->bp_weak_arrays, &num_gen0);

  if (gc->gc_full || !gc->started_incremental)
    num_gen0 = 0;

  while (wa) {
    void **data;

    data = wa->data;
    for (i = wa->count; i--; ) {
      void *p = data[i];
      if (p && (force_zero || !is_marked(gc, p)))
        data[i] = wa->replace_val;
      else
        data[i] = GC_resolve2(p, gc);
    }
    if (fuel > 0)
      fuel = ((fuel > wa->count) ? (fuel - wa->count) : 0);

    if (num_gen0 > 0) {
      if (!is_in_generation_half(gc, wa)) {
        /* For incremental mode, preserve this weak box
           in the incremental list for re-checking later. */
        wa->data[wa->count] = gc->inc_weak_arrays;
        gc->inc_weak_arrays = wa;
      }
    }

    if (from_inc) {
      GC_Weak_Array *next;
      next = (GC_Weak_Array *)wa->data[wa->count];
      wa->data[wa->count] = gc->weak_incremental_done;
      wa = next;
    } else
      wa = wa->next;
    num_gen0--;
  }
  if (from_inc)
    gc->inc_weak_arrays = NULL;
  else {
    gc->weak_arrays = NULL;
    gc->bp_weak_arrays = NULL;
  }

  return fuel;
}
Example #4
0
static int zero_weak_boxes(GCTYPE *gc, int is_late, int force_zero, int from_inc, int fuel)
{
  GC_Weak_Box *wb;
  int num_gen0;

  if (from_inc) {
    wb = gc->inc_weak_boxes[is_late];
    num_gen0 = 0;
  } else {
    wb = append_weak_boxes(gc->weak_boxes[is_late],
                           gc->bp_weak_boxes[is_late],
                           &num_gen0);
    if (gc->gc_full || !gc->started_incremental)
      num_gen0 = 0;
  }

  while (wb) {
    GC_ASSERT(is_marked(gc, wb));
    if (!wb->val) {
      /* nothing to do */
    } else if (force_zero || !is_marked(gc, wb->val)) {
      wb->val = NULL;
      if (wb->secondary_erase) {
        void **p;
        mpage *page;

        /* it's possible for the secondary to be in an old generation
           and therefore on an mprotected page: */
        page = pagemap_find_page(gc->page_maps, wb->secondary_erase);
        if (page->mprotected) {
          page->mprotected = 0;
          mmu_write_unprotect_page(gc->mmu, page->addr, APAGE_SIZE, page_mmu_type(page), &page->mmu_src_block);
          page->reprotect_next = gc->reprotect_next;
          gc->reprotect_next = page;
          page->reprotect = 1;
        }
        p = (void **)GC_resolve2(wb->secondary_erase, gc);
        *(p + wb->soffset) = NULL;
        wb->secondary_erase = NULL;
      }
    } else {
      wb->val = GC_resolve2(wb->val, gc);
    }
    if (num_gen0 > 0) {
      if (!is_in_generation_half(gc, wb)) {
        /* For incremental mode, preserve this weak box
           in the incremental list for re-checking later. */
        check_weak_box_not_already_in_inc_chain(wb, gc->inc_weak_boxes[wb->is_late]);
        wb->inc_next = gc->inc_weak_boxes[is_late];
        gc->inc_weak_boxes[is_late] = wb;
      }
    }
    if (from_inc) {
      GC_Weak_Box *next;
      next = wb->inc_next;
      wb->inc_next = gc->weak_incremental_done;
      wb = next;
    } else
      wb = wb->next;

    num_gen0--;

    if (fuel >= 0) {
      if (fuel > 0)
        fuel--;
      else {
        GC_ASSERT(from_inc);
        gc->inc_weak_boxes[is_late] = wb;
        return 0;
      }
    }
  }

  /* reset, in case we have a second round */
  if (from_inc) {
    gc->inc_weak_boxes[is_late] = NULL;
  } else {
    gc->weak_boxes[is_late] = NULL;
    gc->bp_weak_boxes[is_late] = NULL;
  }

  return fuel;
}