Branch: Tag:

2003-09-08

2003-09-08 15:28:15 by Martin Stjernholm <mast@lysator.liu.se>

Added more tracking in the gc to help track down bugs when the gc follows
munged pointers in the mark pass. Activated with GC_MARK_DEBUG.

Rev: src/array.c:1.135
Rev: src/gc.c:1.196
Rev: src/gc.h:1.95
Rev: src/mapping.c:1.160
Rev: src/object.c:1.221
Rev: src/program.c:1.478
Rev: src/svalue.c:1.156

2:   || This file is part of Pike. For copyright information see COPYRIGHT.   || Pike is distributed under GPL, LGPL and MPL. See the file COPYING   || for more information. - || $Id: gc.c,v 1.195 2003/07/16 14:43:25 mast Exp $ + || $Id: gc.c,v 1.196 2003/09/08 15:28:14 mast Exp $   */      #include "global.h"
31:      #include "block_alloc.h"    - RCSID("$Id: gc.c,v 1.195 2003/07/16 14:43:25 mast Exp $"); + RCSID("$Id: gc.c,v 1.196 2003/09/08 15:28:14 mast Exp $");      /* Run garbage collect approximately every time    * 20 percent of all arrays, objects and programs is
100:   ptrdiff_t alloc_threshold = MIN_ALLOC_THRESHOLD;   PMOD_EXPORT int Pike_in_gc = 0;   int gc_generation = 0; - struct pike_queue gc_mark_queue; +    time_t last_gc;   int gc_trace = 0, gc_debug = 0;   
205:   static void init_gc(void);   static void gc_cycle_pop(void *a);    + #ifdef GC_MARK_DEBUG + #else + struct pike_queue gc_mark_queue; + #endif      #undef BLOCK_ALLOC_NEXT   #define BLOCK_ALLOC_NEXT next
230:      PTR_HASH_ALLOC_FIXED_FILL_PAGES(marker,2)    + #if defined (PIKE_DEBUG) || defined (GC_MARK_DEBUG) + static char *found_where=""; + static void *found_in=0; + static int found_in_type=0; +  + void debug_gc_set_where (int type, void *data) + { +  found_in = data; +  found_in_type = type; + } + #endif +    #ifdef PIKE_DEBUG      #undef get_marker
316:   }      void *check_for =0; - static char *found_where=""; - static void *found_in=0; - static int found_in_type=0; +    void *gc_svalue_location=0;   char *fatal_after_gc=0;   
1122:      #endif /* PIKE_DEBUG */    + #ifdef GC_MARK_DEBUG +  + TYPE_FIELD debug_gc_mark_svalues (struct svalue *s, ptrdiff_t num, +  int in_type, void *in) + { +  TYPE_FIELD res; +  found_in = in; +  found_in_type = in_type; +  res = gc_mark_svalues (s, num); +  found_in_type = PIKE_T_UNKNOWN; +  found_in = NULL; +  return res; + } +  + TYPE_FIELD debug_gc_mark_weak_svalues (struct svalue *s, ptrdiff_t num, +  int in_type, void *in) + { +  TYPE_FIELD res; +  found_in = in; +  found_in_type = in_type; +  res = gc_mark_weak_svalues (s, num); +  found_in_type = PIKE_T_UNKNOWN; +  found_in = NULL; +  return res; + } +  + int debug_gc_mark_short_svalue (union anything *u, int type, +  int in_type, void *in) + { +  int res; +  found_in = in; +  found_in_type = in_type; +  res = gc_mark_short_svalue (u, type); +  found_in_type = PIKE_T_UNKNOWN; +  found_in = NULL; +  return res; + } +  + int debug_gc_mark_weak_short_svalue (union anything *u, int type, +  int in_type, void *in) + { +  int res; +  found_in = in; +  found_in_type = in_type; +  res = gc_mark_weak_short_svalue (u, type); +  found_in_type = PIKE_T_UNKNOWN; +  found_in = NULL; +  return res; + } +  + /* Cut'n'paste from queue.c. */ +  + struct gc_queue_entry + { +  queue_call call; +  void *data; +  int in_type; +  void *in; + }; +  + #define GC_QUEUE_ENTRIES 8191 +  + struct gc_queue_block + { +  struct gc_queue_block *next; +  int used; +  struct gc_queue_entry entries[GC_QUEUE_ENTRIES]; + }; +  + struct gc_queue_block *gc_mark_first = NULL, *gc_mark_last = NULL; +  + void gc_mark_run_queue() + { +  struct gc_queue_block *b; +  +  while((b=gc_mark_first)) +  { +  int e; +  for(e=0;e<b->used;e++) +  { +  debug_malloc_touch(b->entries[e].data); +  b->entries[e].call(b->entries[e].data); +  } +  +  gc_mark_first=b->next; +  free((char *)b); +  } +  gc_mark_last=0; + } +  + void gc_mark_discard_queue() + { +  struct gc_queue_block *b = gc_mark_first; +  while (b) +  { +  struct gc_queue_block *next = b->next; +  free((char *) b); +  b = next; +  } +  gc_mark_first = gc_mark_last = 0; + } +  + void gc_mark_enqueue (queue_call call, void *data) + { +  struct gc_queue_block *b; +  +  b=gc_mark_last; +  if(!b || b->used >= GC_QUEUE_ENTRIES) +  { +  b = (struct gc_queue_block *) malloc (sizeof (struct gc_queue_block)); +  if (!b) fatal ("Out of memory in gc.\n"); +  b->used=0; +  b->next=0; +  if(gc_mark_first) +  gc_mark_last->next=b; +  else +  gc_mark_first=b; +  gc_mark_last=b; +  } +  +  b->entries[b->used].call=call; +  b->entries[b->used].data=debug_malloc_pass(data); +  b->entries[b->used].in_type = found_in_type; +  b->entries[b->used].in = debug_malloc_pass (found_in); +  b->used++; + } +  + #endif +    void debug_gc_touch(void *a)   {    struct marker *m;
2557:    * follow the same reference several times, e.g. with shared mapping    * data blocks. */    gc_mark_all_arrays(); -  run_queue(&gc_mark_queue); +  gc_mark_run_queue();    gc_mark_all_multisets(); -  run_queue(&gc_mark_queue); +  gc_mark_run_queue();    gc_mark_all_mappings(); -  run_queue(&gc_mark_queue); +  gc_mark_run_queue();    gc_mark_all_programs(); -  run_queue(&gc_mark_queue); +  gc_mark_run_queue();    gc_mark_all_objects(); -  run_queue(&gc_mark_queue); +  gc_mark_run_queue();   #ifdef PIKE_DEBUG    if(gc_debug) gc_mark_all_strings();   #endif /* PIKE_DEBUG */