Ejemplo n.º 1
0
static void zero_weak_boxes(GCTYPE *gc, int is_late, int force_zero)
{
  GC_Weak_Box *wb;

  wb = gc->weak_boxes[is_late];
  while (wb) {
    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);
          GC_MP_CNT_INC(mp_mark_cnt);
        }

        p = (void **)GC_resolve2(wb->secondary_erase, gc);
        *(p + wb->soffset) = NULL;
        wb->secondary_erase = NULL;
      }
    }
    wb = wb->next;
  }

  /* reset, in case we have a second round */
  gc->weak_boxes[is_late] = NULL;
}
Ejemplo n.º 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;
}
Ejemplo n.º 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;
}
Ejemplo n.º 4
0
inline static void clean_up_account_hooks(NewGC *gc)
{
  AccountHook *work = gc->hooks;
  AccountHook *prev = NULL;

  while(work) {
    if((!work->c1 || marked(gc, work->c1)) && marked(gc, work->c2)) {
      work->c1 = GC_resolve2(work->c1, gc);
      work->c2 = GC_resolve2(work->c2, gc);
      prev = work;
      work = work->next;
    } else {
      /* remove work hook */
      AccountHook *next = work->next;

      if(prev) prev->next = next;
      if(!prev) gc->hooks = next;
      ofm_free(work, sizeof(AccountHook));
      work = next;
    }
  }
}
Ejemplo n.º 5
0
inline static void clean_up_thread_list(NewGC *gc)
{
  GC_Thread_Info *work = gc->thread_infos;
  GC_Thread_Info *prev = NULL;

  while(work) {
    if(!pagemap_find_page(gc->page_maps, work->thread) || marked(gc, work->thread)) {
      work->thread = GC_resolve2(work->thread, gc);
      prev = work;
      work = work->next;
    } else {
      GC_Thread_Info *next = work->next;

      if(prev) prev->next = next;
      if(!prev) gc->thread_infos = next;
      ofm_free(work, sizeof(GC_Thread_Info));
      work = next;
    }
  }
}
Ejemplo n.º 6
0
inline static void clean_up_owner_table(NewGC *gc)
{
  OTEntry **owner_table = gc->owner_table;
  const int table_size = gc->owner_table_size;
  int i;

  for(i = 1; i < table_size; i++)
    if(owner_table[i]) {
      /* repair or delete the originator */
      if(!marked(gc, owner_table[i]->originator)) {
        owner_table[i]->originator = NULL;
      } else 
        owner_table[i]->originator = GC_resolve2(owner_table[i]->originator, gc);

      /* potential delete */
      if(i != 1) 
        if((owner_table[i]->memory_use == 0) && !owner_table[i]->originator)
          free_owner_set(gc, i);
    }
}
Ejemplo n.º 7
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;
}