pike.git / src / gc.c

version» Context lines:

pike.git/src/gc.c:165:   #define GC_VERBOSE_DO(X) X   #else   #define GC_VERBOSE_DO(X)   #endif      int num_objects = 2; /* Account for *_empty_array. */   int got_unlinked_things;   ALLOC_COUNT_TYPE num_allocs =0;   ALLOC_COUNT_TYPE alloc_threshold = GC_MIN_ALLOC_THRESHOLD;   PMOD_EXPORT int Pike_in_gc = 0; - int gc_generation = 0; + unsigned INT32 gc_generation = 1;   time_t last_gc;   int gc_trace = 0, gc_debug = 0;   #ifdef DO_PIKE_CLEANUP   int gc_destruct_everything = 0;   #endif   size_t gc_ext_weak_refs;      ALLOC_COUNT_TYPE saved_alloc_threshold;   /* Used to backup alloc_threshold if the gc is disabled, so that it    * can be restored when it's enabled again. This is to not affect the
pike.git/src/gc.c:558:   /* These callbacks are run early in the check pass of the gc and when    * locate_references is called. They are typically used to mark    * external references (using gc_mark_external) for debug purposes. */   struct callback *debug_add_gc_callback(callback_func call,    void *arg,    callback_func free_func)   {    return add_to_callback(&gc_callbacks, call, arg, free_func);   }    - static void init_gc(void); +    static void gc_cycle_pop();    - #undef BLOCK_ALLOC_NEXT - #define BLOCK_ALLOC_NEXT next -  - #undef INIT_BLOCK - #ifdef PIKE_DEBUG - #define INIT_BLOCK(X) \ -  (X)->flags=(X)->refs=(X)->weak_refs=(X)->xrefs=0; \ -  (X)->saved_refs=-1; \ -  (X)->frame = 0; - #else - #define INIT_BLOCK(X) \ -  (X)->flags=(X)->refs=(X)->weak_refs=0; \ -  (X)->frame = 0; - #endif - #undef EXIT_BLOCK - #define EXIT_BLOCK(f) -  - #undef get_marker - #define get_marker debug_get_marker - #undef find_marker - #define find_marker debug_find_marker -  - PTR_HASH_ALLOC_FIXED_FILL_PAGES(marker,2) -  - #undef get_marker - #define get_marker(X) ((struct marker *) debug_malloc_pass(debug_get_marker(X))) - #undef find_marker - #define find_marker(X) ((struct marker *) debug_malloc_pass(debug_find_marker(X))) -  - PMOD_EXPORT struct marker *pmod_get_marker (void *p) - { -  return debug_get_marker (p); - } -  - PMOD_EXPORT struct marker *pmod_find_marker (void *p) - { -  return debug_find_marker (p); - } -  +    #if defined (PIKE_DEBUG) || defined (GC_MARK_DEBUG)   PMOD_EXPORT void *gc_found_in = NULL;   PMOD_EXPORT int gc_found_in_type = PIKE_T_UNKNOWN;   PMOD_EXPORT const char *gc_found_place = NULL;   #endif      #ifdef DO_PIKE_CLEANUP   /* To keep the markers after the gc. Only used for the leak report at exit. */   int gc_keep_markers = 0;   PMOD_EXPORT int gc_external_refs_zapped = 0;
pike.git/src/gc.c:1168: Inside #if defined(PIKE_DEBUG)
   int indent,    int depth,    int flags,    void *inblock)   {    struct program *p=(struct program *)a;    struct marker *m;       if(depth<0) return;    -  if (marker_hash_table && (m = find_marker(a))) { +  if (m = find_marker(a)) {    fprintf(stderr,"%*s**Got gc ",indent,"");    describe_marker(m);    }      again:    switch(t)    {    case T_STORAGE:    if (!inblock) attempt_to_identify (a, &a);    t = T_OBJECT;
pike.git/src/gc.c:1751:    ID_FROM_INT(s->u.object->prog, SUBTYPEOF(*s))->name->str);    }    }    }    describe_something(s->u.refs, TYPEOF(*s), 0, 1, 0, 0);   }      PMOD_EXPORT void gc_watch(void *a)   {    struct marker *m; -  init_gc(); +     m = get_marker(a);    if (!(m->flags & GC_WATCHED)) {    m->flags |= GC_WATCHED;    fprintf(stderr, "## Watching thing %p.\n", a);    gc_is_watching++;    }    else    fprintf(stderr, "## Already watching thing %p.\n", a);   }      static void gc_watched_found (struct marker *m, const char *found_in)   { -  fprintf(stderr, "## Watched thing %p with %d refs found in " -  "%s in pass %d.\n", m->data, *(INT32 *) m->data, found_in, Pike_in_gc); +  fprintf(stderr, "## Watched thing found in " +  "%s in pass %d.\n", found_in, Pike_in_gc);    describe_marker (m);   }      #endif /* PIKE_DEBUG */      #ifndef GC_MARK_DEBUG   struct pike_queue gc_mark_queue;   #define CHECK_MARK_QUEUE_EMPTY() assert (!gc_mark_queue.first)   #else /* GC_MARK_DEBUG */   
pike.git/src/gc.c:1878:    b->used++;   }      #endif /* GC_MARK_DEBUG */      void debug_gc_touch(void *a)   {    struct marker *m;      #ifdef PIKE_DEBUG +  if (!a) Pike_fatal("Got null pointer.\n");    if (gc_is_watching && (m = find_marker(a)) && m->flags & GC_WATCHED) {    /* This is useful to set breakpoints on. */    gc_watched_found (m, "gc_touch()");    } -  if (!a) Pike_fatal("Got null pointer.\n"); +    #endif       switch (Pike_in_gc) {    case GC_PASS_PRETOUCH:    m = find_marker(a);   #ifdef PIKE_DEBUG    if (   #ifdef DO_PIKE_CLEANUP    !gc_keep_markers &&   #endif
pike.git/src/gc.c:2042:       ret=m->refs;    add_ref(m);    if (m->refs == *(INT32 *) a)    m->flags |= GC_NOT_REFERENCED;    return ret;   }      static void cleanup_markers (void)   { - #ifdef DO_PIKE_CLEANUP -  size_t e=0; -  -  if (gc_keep_markers) { -  /* Carry over any GC_CLEANUP_LEAKED flags but reinitialize them -  * otherwise. */ -  for(e=0;e<marker_hash_table_size;e++) { -  struct marker *m; -  for (m = marker_hash_table[e]; m; m = m->next) { - #ifdef PIKE_DEBUG -  m->flags &= GC_CLEANUP_LEAKED; -  m->xrefs = 0; -  m->saved_refs = -1; - #else -  m->flags = 0; - #endif -  m->refs = m->weak_refs = 0; -  m->frame = 0; +    } -  } -  return; -  } +     -  for(e=0;e<marker_hash_table_size;e++) -  while(marker_hash_table[e]) -  remove_marker(marker_hash_table[e]->data); - #endif -  exit_marker_hash(); - } -  - static void init_gc(void) - { - #ifdef PIKE_DEBUG -  if (!gc_is_watching) { - #endif - #if defined (PIKE_DEBUG) || defined (DO_PIKE_CLEANUP) -  /* The marker hash table is left around after a previous gc if -  * gc_keep_markers is set. */ -  if (marker_hash_table) cleanup_markers(); -  if (!marker_hash_table) - #endif -  low_init_marker_hash(num_objects); - #ifdef PIKE_DEBUG -  } - #endif - } -  +    void exit_gc(void)   {    if (gc_evaluator_callback) {    remove_callback(gc_evaluator_callback);    gc_evaluator_callback = NULL;    }    if (!gc_keep_markers)    cleanup_markers();       ba_free_all(&gc_rec_frame_allocator);
pike.git/src/gc.c:2135: Inside #if defined(PIKE_DEBUG)
   if (master_object)    gc_mark_external (master_object, " as master_object");    if ((constants = get_builtin_constants()))    gc_mark_external (constants, " as global constants mapping");   }      PMOD_EXPORT void locate_references(void *a)   {    int tmp, orig_in_gc = Pike_in_gc;    const char *orig_gc_found_place = gc_found_place; -  int i=0; -  if(!marker_hash_table) -  { -  i=1; -  init_gc(); -  } +     Pike_in_gc = GC_PASS_LOCATE;    gc_found_place = NULL;       /* Disable debug, this may help reduce recursion bugs */    tmp=d_flag;    d_flag=0;       fprintf(stderr,"**Looking for references to %p:\n", a);       check_for=a;
pike.git/src/gc.c:2180: Inside #if defined(PIKE_DEBUG) and #if defined(DEBUG_MALLOC)
   dmalloc_find_references_to(a);   #endif    }   #endif       fprintf(stderr,"**Done looking for references to %p, "    "found %"PRINTSIZET"u refs.\n", a, found_ref_count);       Pike_in_gc = orig_in_gc;    gc_found_place = orig_gc_found_place; -  if(i) exit_gc(); +     d_flag=tmp;   }      void debug_gc_add_extra_ref(void *a)   {    struct marker *m;       if (gc_is_watching && (m = find_marker(a)) && m->flags & GC_WATCHED) {    /* This is useful to set breakpoints on. */    gc_watched_found (m, "gc_add_extra_ref()");
pike.git/src/gc.c:2863: Inside #if defined(PIKE_DEBUG)
     #ifdef PIKE_DEBUG    if (gc_is_watching && m && m->flags & GC_WATCHED) {    /* This is useful to set breakpoints on. */    gc_watched_found (m, "gc_cycle_push()");    }       debug_malloc_touch (data);       if (!data) Pike_fatal ("Got null pointer.\n"); -  if (m->data != data) Pike_fatal ("Got wrong marker.\n"); +     if (Pike_in_gc != GC_PASS_CYCLE)    Pike_fatal("GC cycle push attempted in invalid pass.\n");    if (gc_debug && !(m->flags & GC_PRETOUCHED))    gc_fatal (data, 0, "gc_cycle_push() called for untouched thing.\n");    if (!gc_destruct_everything) {    if ((!(m->flags & GC_NOT_REFERENCED) || m->flags & GC_MARKED) &&    *(INT32 *) data)    gc_fatal (data, 1, "Got a referenced marker to gc_cycle_push.\n");    if (m->flags & GC_XREFERENCED)    gc_fatal (data, 1, "Doing cycle check in externally referenced thing "
pike.git/src/gc.c:3530:    remove_callback (gc_evaluator_callback);    gc_evaluator_callback = NULL;    }    return 0;    }      #ifdef DEBUG_MALLOC    if(debug_options & GC_RESET_DMALLOC)    reset_debug_malloc();   #endif -  init_gc(); +     gc_generation++;    Pike_in_gc=GC_PASS_PREPARE;       if (!SAFE_IS_ZERO(&gc_pre_cb)) {    safe_apply_svalue(&gc_pre_cb, 0, 1);    pop_stack();    }       gc_start_time = get_cpu_time();    gc_start_real_time = get_real_time();
pike.git/src/gc.c:3957:    GC_VERBOSE_DO(obj_count = num_objects);    destruct_objects_to_destruct();    GC_VERBOSE_DO(fprintf(stderr, "| destruct: %d things really freed\n",    obj_count - num_objects));      #ifdef PIKE_DEBUG    if (gc_extra_refs) {    size_t e;    fprintf (stderr, "Lost track of %d extra refs to things in gc.\n"    "Searching for marker(s) with extra refs:\n", gc_extra_refs); -  for (e = 0; e < marker_hash_table_size; e++) { -  struct marker *s = marker_hash_table[e], *m; -  for (m = s; m;) { -  if (m->flags & GC_GOT_EXTRA_REF) { +     fprintf (stderr, "========================================\n" -  "Found marker with extra ref: "); -  describe_marker (m); -  fprintf (stderr, "Describing the thing pointed to:\n"); -  describe (m->data); -  } -  m = m->next; -  /* The marker might be moved to the head of the chain via -  * describe() above, so do this to avoid infinite recursion. -  * Some entries in the chain might be missed, but I don't want -  * to bother. */ -  if (m == s) break; -  } -  } -  fprintf (stderr, "========================================\n" +     "Done searching for marker(s) with extra refs.\n");    Pike_fatal("Lost track of %d extra refs to things in gc.\n", gc_extra_refs);    }    if(fatal_after_gc) Pike_fatal("%s", fatal_after_gc);   #endif       /* Calculate the next alloc_threshold. */    {    double multiplier, new_threshold;    cpu_time_t last_non_gc_time, last_gc_time;
pike.git/src/gc.c:6119:    }       mc_pass = 0;    visit_enter = NULL;    visit_ref = NULL;    visit_leave = NULL;       DL_MAKE_EMPTY (mc_incomplete);    DL_MAKE_EMPTY (mc_indirect);   #ifdef DO_PIKE_CLEANUP -  { -  size_t e; -  for (e = 0; e < mc_marker_hash_table_size; e++) -  while (mc_marker_hash_table[e]) -  remove_mc_marker (mc_marker_hash_table[e]->thing); -  } +    #endif       assert (mc_wq_used == 1);    mc_work_queue++; /* Compensate for 1-based indexing. */    free(mc_work_queue);    mc_work_queue = NULL;    stop_mc();       pop_n_elems (args);    push_ulongest (return_count ? count_internal : mc_counted_bytes);