pike.git / src / mapping.c

version» Context lines:

pike.git/src/mapping.c:1:   /*\   ||| This file a part of Pike, and is copyright by Fredrik Hubinette   ||| Pike is distributed as GPL (General Public License)   ||| See the files COPYING and DISCLAIMER for more information.   \*/   /**/   #include "global.h" - RCSID("$Id: mapping.c,v 1.98 2000/08/11 13:20:44 grubba Exp $"); + RCSID("$Id: mapping.c,v 1.99 2000/09/03 23:18:46 mast Exp $");   #include "main.h"   #include "object.h"   #include "mapping.h"   #include "svalue.h"   #include "array.h"   #include "pike_macros.h"   #include "error.h"   #include "pike_memory.h"   #include "dynamic_buffer.h"   #include "interpret.h"
pike.git/src/mapping.c:103: Inside #if defined(PIKE_DEBUG)
   }       if(val_types & ~(m->data->val_types))    fatal("Mapping value types out of order!\n");       if(ind_types & ~(m->data->ind_types))    fatal("Mapping indices types out of order!\n");   }   #endif    - static struct mapping_data empty_data = { 1, 1, 0,0,0,0,0 }; + static struct mapping_data empty_data = { 1, 1, 0,0,0,0,0,0 };      /* This function allocates the hash table and svalue space for a mapping    * struct. The size is the max number of indices that can fit in the    * allocated space.    */   static void init_mapping(struct mapping *m, INT32 size)   {    struct mapping_data *md;    char *tmp;    ptrdiff_t e;    INT32 hashsize;       debug_malloc_touch(m);   #ifdef PIKE_DEBUG -  +  if (Pike_in_gc > GC_PASS_PREPARE && Pike_in_gc < GC_PASS_ZAP_WEAK) +  fatal("Can't allocate a new mapping_data inside gc.\n");    if(size < 0) fatal("init_mapping with negative value.\n");   #endif    if(size)    {    hashsize=size / AVG_LINK_LENGTH + 1;    if(!(hashsize & 1)) hashsize++;       e=MAPPING_DATA_SIZE(hashsize, size);       md=(struct mapping_data *)xalloc(e);
pike.git/src/mapping.c:146:    {    md->free_list[e-1].next = md->free_list + e;    md->free_list[e-1].ind.type=T_INT;    md->free_list[e-1].val.type=T_INT;    }    md->free_list[e-1].next=0;    md->free_list[e-1].ind.type=T_INT;    md->free_list[e-1].val.type=T_INT;    md->ind_types = 0;    md->val_types = 0; +  md->flags = 0;    md->size = 0;    md->refs=0;    md->valrefs=0;    md->hardlinks=0;    md->num_keypairs=size;    }else{    md=&empty_data;    }    add_ref(md);    m->data=md; - #ifdef PIKE_DEBUG + #ifdef MAPPING_SIZE_DEBUG    m->debug_size = md->size;   #endif   }      /* This function allocates an empty mapping with room for 'size' values    */   PMOD_EXPORT struct mapping *debug_allocate_mapping(int size)   {    struct mapping *m;       m=alloc_mapping();       GC_ALLOC(m);       INITIALIZE_PROT(m);    init_mapping(m,size);       m->refs = 1; -  m->flags = 0; +        DOUBLELINK(first_mapping, m);       return m;   }         PMOD_EXPORT void really_free_mapping_data(struct mapping_data *md)   {    INT32 e;
pike.git/src/mapping.c:323:    /* evil */    for(e=0;e<md->hashsize;e++)    mapping_rehash_backwards_evil(new_md, md->hash[e]);       free((char *)md);    }      #ifdef PIKE_DEBUG    if(m->data->size != tmp)    fatal("Rehash failed, size not same any more.\n"); -  + #endif + #ifdef MAPPING_SIZE_DEBUG    m->debug_size = m->data->size;   #endif      #ifdef PIKE_DEBUG    if(d_flag>1) check_mapping(m);   #endif       return m;   }   
pike.git/src/mapping.c:348:   #define LOW_RELOC(X) X= (void *) ((char *)(X) + off);   #define RELOC(X) if(X) LOW_RELOC(X)      struct mapping_data *copy_mapping_data(struct mapping_data *md)   {    long e;    ptrdiff_t size, off;    struct mapping_data *nmd;    struct keypair *keypairs;    + #ifdef PIKE_DEBUG +  if (Pike_in_gc > GC_PASS_PREPARE && Pike_in_gc < GC_PASS_ZAP_WEAK) +  fatal("Can't allocate a new mapping_data inside gc.\n"); + #endif +     debug_malloc_touch(md);       size=MAPPING_DATA_SIZE(md->hashsize, md->num_keypairs);       nmd=(struct mapping_data *)xalloc(size);    MEMCPY(nmd, md, size);    off=((char *)nmd) - ((char *)md);       RELOC(nmd->free_list);    for(e=0;e<nmd->hashsize;e++) RELOC(nmd->hash[e]);
pike.git/src/mapping.c:385:    fatal("Hardlink without refs/valrefs!\n");   #endif    md->hardlinks--;    md->valrefs--;    }    md->refs--;       return nmd;   }    + #define MAPPING_DATA_IN_USE(MD) ((MD)->refs != (MD)->hardlinks + 1) +    #define LOW_FIND(FUN, KEY, FOUND, NOT_FOUND) do { \    md=m->data; \    add_ref(md); \    if(md->hashsize) \    { \    h=h2 % md->hashsize; \    DO_IF_DEBUG( if(d_flag > 1) check_mapping_type_fields(m); ) \    if(md->ind_types & (1 << key->type)) \    { \    for(prev= md->hash + h;(k=*prev);prev=&k->next) \
pike.git/src/mapping.c:533: Inside #if defined(PIKE_DEBUG)
   if(val_types & ~(m->data->val_types))    fatal("Mapping value types out of order!\n");       if(ind_types & ~(m->data->ind_types))    fatal("Mapping indices types out of order!\n");   #endif    m->data->val_types = val_types;    m->data->ind_types = ind_types;   }    + PMOD_EXPORT void mapping_set_flags(struct mapping *m, int flags) + { +  struct mapping_data *md = m->data; +  if (md->refs > 1) { +  struct keypair *k, *prev; +  COPYMAP2(); +  } +  md->flags = flags; + } +  +    /* This function inserts key:val into the mapping m.    * Same as doing m[key]=val; in pike.    */   PMOD_EXPORT void low_mapping_insert(struct mapping *m,    struct svalue *key,    struct svalue *val,    int overwrite)   {    unsigned INT32 h,h2;    struct keypair *k, **prev;
pike.git/src/mapping.c:624:    k=md->free_list;    md->free_list=k->next;    k->next=md->hash[h];    md->hash[h]=k;    md->ind_types |= 1 << key->type;    md->val_types |= 1 << val->type;    assign_svalue_no_free(& k->ind, key);    assign_svalue_no_free(& k->val, val);    k->hval = h2;    md->size++; - #ifdef PIKE_DEBUG + #ifdef MAPPING_SIZE_DEBUG    if(m->data ==md)    m->debug_size++;   #endif      #ifdef PIKE_DEBUG    if(d_flag>1) check_mapping(m);   #endif   }      PMOD_EXPORT void mapping_insert(struct mapping *m,
pike.git/src/mapping.c:735:    k->next=md->hash[h];    md->hash[h]=k;    assign_svalue_no_free(& k->ind, key);    k->val.type=T_INT;    k->val.subtype=NUMBER_NUMBER;    k->val.u.integer=0;    k->hval = h2;    md->ind_types |= 1 << key->type;    md->val_types |= BIT_INT;    md->size++; - #ifdef PIKE_DEBUG + #ifdef MAPPING_SIZE_DEBUG    if(m->data ==md)    m->debug_size++;   #endif      #ifdef PIKE_DEBUG    if(d_flag > 1) check_mapping_type_fields(m);   #endif       return & ( k->val.u );   }
pike.git/src/mapping.c:811:    to[0]=k->val;    else    free_svalue(& k->val);       k->ind.type=T_INT;    k->val.type=T_INT;       k->next=md->free_list;    md->free_list=k;    md->size--; - #ifdef PIKE_DEBUG + #ifdef MAPPING_SIZE_DEBUG    if(m->data ==md)    m->debug_size--;   #endif       if(md->size < (md->hashsize + 1) * MIN_LINK_LENGTH)    {    debug_malloc_touch(m);    rehash(m, MAP_SLOTS(m->data->size));    }      #ifdef PIKE_DEBUG    if(d_flag>1) check_mapping(m);   #endif    return;   }    -  + static void low_check_mapping_for_destruct( +  struct mapping_data *md, int e, struct keypair **prev, +  TYPE_FIELD ind_types, TYPE_FIELD val_types) + { +  struct keypair *k; +  + #ifdef PIKE_DEBUG +  if (MAPPING_DATA_IN_USE(md)) fatal("The mapping data is busy.\n"); + #endif +  debug_malloc_touch(md); +  +  if (prev) { +  k = *prev; +  goto jump_in; +  } +  +  for(e=0;e<md->hashsize;e++) +  { +  for(prev= md->hash + e;(k=*prev);) +  { +  jump_in: +  check_destructed(& k->val); +  +  if((k->ind.type == T_OBJECT || k->ind.type == T_FUNCTION) && +  !k->ind.u.object->prog) +  { +  *prev=k->next; +  free_svalue(& k->ind); +  free_svalue(& k->val); +  k->next=md->free_list; +  md->free_list=k; +  md->size--; +  }else{ +  val_types |= 1 << k->val.type; +  ind_types |= 1 << k->ind.type; +  prev=&k->next; +  } +  } +  } +  +  md->val_types = val_types; +  md->ind_types = ind_types; + } +    PMOD_EXPORT void check_mapping_for_destruct(struct mapping *m)   {    INT32 e;    struct keypair *k, **prev;    TYPE_FIELD ind_types, val_types;    struct mapping_data *md=m->data;      #ifdef PIKE_DEBUG    if(m->data->refs <=0)    fatal("Zero refs in mapping->data\n");    if(d_flag>1) check_mapping(m);    debug_malloc_touch(m); -  if (Pike_in_gc > GC_PASS_PREPARE && Pike_in_gc < GC_PASS_ZAP_WEAK && -  Pike_in_gc != GC_PASS_MARK) -  fatal("check_mapping_for_destruct called in wrong pass inside gc.\n"); +    #endif       /* no is_eq -> no locking */       if(!md->size) return;       if((md->ind_types | md->val_types) & (BIT_OBJECT | BIT_FUNCTION))    {    val_types = ind_types = 0;    md->val_types |= BIT_INT;    for(e=0;e<md->hashsize;e++)    {    for(prev= md->hash + e;(k=*prev);)    { -  check_destructed(& k->val); -  +     if((k->ind.type == T_OBJECT || k->ind.type == T_FUNCTION) &&    !k->ind.u.object->prog)    { -  debug_malloc_touch(md); + #ifdef MAPPING_SIZE_DEBUG +  size_t old_size = md->size; + #endif    debug_malloc_touch(m); -  +  debug_malloc_touch(md);    PREPARE_FOR_INDEX_CHANGE2(); -  *prev=k->next; -  free_svalue(& k->ind); -  free_svalue(& k->val); -  k->next=md->free_list; -  md->free_list=k; -  md->size--; - #ifdef PIKE_DEBUG -  if(m->data ==md) -  { -  m->debug_size++; -  debug_malloc_touch(m); -  } +  low_check_mapping_for_destruct (md, e, prev, ind_types, val_types); + #ifdef MAPPING_SIZE_DEBUG +  m->debug_size -= old_size - md->size;   #endif -  debug_malloc_touch(md); +  goto done;    }else{ -  +  check_destructed(& k->val);    val_types |= 1 << k->val.type;    ind_types |= 1 << k->ind.type;    prev=&k->next;    }    }    } -  +  +  done:    if(MAP_SLOTS(md->size) < md->hashsize * MIN_LINK_LENGTH)    {    debug_malloc_touch(m);    rehash(m, MAP_SLOTS(md->size));    }    -  md->val_types = val_types; -  md->ind_types = ind_types; +    #ifdef PIKE_DEBUG    if(d_flag>1) check_mapping(m);   #endif    }   }    -  + /* This one doesn't copy the mapping data before writing it. Instead +  * it does nothing at all if the mapping data is busy. */ + static void stealth_check_mapping_for_destruct(struct mapping *m) + { +  struct mapping_data *md=m->data; +  +  if (MAPPING_DATA_IN_USE(md)) { +  TYPE_FIELD val_types = 0; +  INT32 e; +  struct keypair *k; +  md->val_types |= BIT_INT; +  NEW_MAPPING_LOOP(md) { +  check_destructed(&k->val); +  val_types |= 1 << k->val.type; +  } +  md->val_types = val_types; +  } +  +  else +  if((md->ind_types | md->val_types) & (BIT_OBJECT | BIT_FUNCTION)) +  low_check_mapping_for_destruct (md, 0, 0, 0, 0); + } +    PMOD_EXPORT struct svalue *low_mapping_lookup(struct mapping *m,    struct svalue *key)   {    unsigned INT32 h,h2;    struct keypair *k=0, **prev=0;    struct mapping_data *md, *omd;      #ifdef PIKE_DEBUG    if(m->data->refs <=0)    fatal("Zero refs in mapping->data\n");
pike.git/src/mapping.c:1213: Inside #if defined(PIKE_DEBUG)
  #ifdef PIKE_DEBUG    if(m->data->refs <=0)    fatal("Zero refs in mapping->data\n");   #endif       n=allocate_mapping(0);    if(!m_sizeof(m)) return n; /* done */    debug_malloc_touch(n->data);    free_mapping_data(n->data);    n->data=m->data; - #ifdef PIKE_DEBUG + #ifdef MAPPING_SIZE_DEBUG    n->debug_size=n->data->size;   #endif    n->data->refs++;    n->data->valrefs++;    n->data->hardlinks++;    debug_malloc_touch(n->data);    return n;   }      #endif
pike.git/src/mapping.c:1397:    INT32 e,eq=1;      #ifdef PIKE_DEBUG    if(a->data->refs <=0)    fatal("Zero refs in mapping->data\n");    if(b->data->refs <=0)    fatal("Zero refs in mapping->data\n");   #endif       if(a==b) return 1; +  +  check_mapping_for_destruct(a); +  check_mapping_for_destruct(b); +     if(m_sizeof(a) != m_sizeof(b)) return 0;       curr.pointer_a = a;    curr.pointer_b = b;    curr.next = p;       for( ;p ;p=p->next)    if(p->pointer_a == (void *)a && p->pointer_b == (void *)b)    return 1;    -  check_mapping_for_destruct(a); -  check_mapping_for_destruct(b); -  +     md=a->data;    md->valrefs++;    add_ref(md);       NEW_MAPPING_LOOP(md)    {    struct svalue *s;    if((s=low_mapping_lookup(b, & k->ind)))    {    if(!low_is_equal(s, &k->val, &curr))
pike.git/src/mapping.c:1596:    }      #ifdef PIKE_DEBUG    if(d_flag > 1) check_mapping_type_fields(m);   #endif       if(!((m->data->val_types | m->data->ind_types) & BIT_COMPLEX))    return copy_mapping(m);       ret=allocate_mapping(MAP_SLOTS(m->data->size)); -  ret->flags=m->flags; +     doing.pointer_b=ret;       check_stack(2);       md=m->data;    md->valrefs++;    add_ref(md);    MAPPING_LOOP(m) /* FIXME: Shouldn't NEW_MAPPING_LOOP() be used? */    {    copy_svalues_recursively_no_free(sp,&k->ind, 1, p);
pike.git/src/mapping.c:1722: Inside #if defined(PIKE_DEBUG)
      if(!m->data)    fatal("Mapping has no data block.\n");       if (!m->data->refs)    fatal("Mapping data block has zero refs.\n");       if(m->next && m->next->prev != m)    fatal("Mapping ->next->prev != mapping.\n");    + #ifdef MAPPING_SIZE_DEBUG    if(m->debug_size != md->size)    {    if(Pike_in_gc)    {    fprintf(stderr,"Pike was in GC stage %d when this fatal occured:\n",Pike_in_gc);    Pike_in_gc=0;    }       fprintf(stderr,"--MAPPING ZAPPING (%d!=%d), mapping:\n",m->debug_size,md->size);    describe(m);    fprintf(stderr,"--MAPPING ZAPPING (%d!=%d), mapping data:\n",m->debug_size,md->size);    describe(md);    fatal("Mapping zapping detected (%d != %d)!\n",m->debug_size,md->size);    } -  + #endif       if(m->prev)    {    if(m->prev->next != m)    fatal("Mapping ->prev->next != mapping.\n");    }else{    if(first_mapping != m)    fatal("Mapping ->prev == 0 but first_mapping != mapping.\n");    }   
pike.git/src/mapping.c:1823:      static void gc_recurse_weak_mapping(struct mapping *m,    TYPE_FIELD (*recurse_fn)(struct svalue *, size_t))   {    INT32 e;    struct keypair *k,**prev;    TYPE_FIELD ind_types = 0, val_types = 0;    struct mapping_data *md=m->data;      #ifdef PIKE_DEBUG -  if(!(m->flags & MAPPING_FLAG_WEAK)) +  if(!(md->flags & MAPPING_FLAG_WEAK))    fatal("Mapping is not weak.\n"); -  +  if (MAPPING_DATA_IN_USE(md)) fatal("Mapping data is busy.\n");   #endif       /* no locking required (no is_eq) */    for(e=0;e<md->hashsize;e++)    {    for(prev= md->hash + e;(k=*prev);)    {    int i, v;    if((i = recurse_fn(&k->ind, 1)) | (v = recurse_fn(&k->val, 1)))    { -  PREPARE_FOR_INDEX_CHANGE(); +     *prev=k->next;    if (!i) free_svalue(&k->ind);    if (!v) free_svalue(&k->val);    k->next=md->free_list;    md->free_list=k;    md->size--; - #ifdef PIKE_DEBUG + #ifdef MAPPING_SIZE_DEBUG    if(m->data ==md)    m->debug_size--;   #endif    }else{    val_types |= 1 << k->val.type;    ind_types |= 1 << k->ind.type;    prev=&k->next;    }    }    }    md->val_types = val_types;    md->ind_types = ind_types; -  -  if(MAP_SLOTS(md->size) < md->hashsize * MIN_LINK_LENGTH) -  { -  debug_malloc_touch(m); -  rehash(m, MAP_SLOTS(md->size)); +    } - } +       void gc_mark_mapping_as_referenced(struct mapping *m)   { -  INT32 e; -  struct keypair *k; -  +    #ifdef PIKE_DEBUG    if(m->data->refs <=0)    fatal("Zero refs in mapping->data\n");   #endif       if(gc_mark(m)) { -  check_mapping_for_destruct(m); +  struct mapping_data *md = m->data; +  +  stealth_check_mapping_for_destruct(m);    if (m == gc_mark_mapping_pos)    gc_mark_mapping_pos = m->next;    if (m == gc_internal_mapping)    gc_internal_mapping = m->next;    else {    DOUBLEUNLINK(first_mapping, m);    DOUBLELINK(first_mapping, m); /* Linked in first. */    }    -  if(gc_mark(m->data) && -  ((m->data->ind_types | m->data->val_types) & BIT_COMPLEX)) +  if(gc_mark(md) && ((md->ind_types | md->val_types) & BIT_COMPLEX))    { -  if (m->flags & MAPPING_FLAG_WEAK) -  gc_recurse_weak_mapping(m, gc_mark_weak_svalues); -  else -  NEW_MAPPING_LOOP(m->data) -  { -  if (gc_mark_svalues(&k->ind, 1) || +  INT32 e; +  struct keypair *k; +  +  if (MAPPING_DATA_IN_USE(md)) { +  /* Must leave destructed indices intact if the mapping data is busy. */ +  NEW_MAPPING_LOOP(md) +  if ((!IS_DESTRUCTED(&k->ind) && gc_mark_svalues(&k->ind, 1)) |    gc_mark_svalues(&k->val, 1)) {   #ifdef PIKE_DEBUG -  fatal("Looks like check_mapping_for_destruct " -  "didn't do its job properly.\n"); +  fatal("Didn't expect an svalue zapping now.\n");   #endif    }    } -  +  else if (md->flags & MAPPING_FLAG_WEAK) +  gc_recurse_weak_mapping(m, gc_mark_weak_svalues); +  else +  NEW_MAPPING_LOOP(md) +  if (gc_mark_svalues(&k->ind, 1) | gc_mark_svalues(&k->val, 1)) { + #ifdef PIKE_DEBUG +  fatal("stealth_check_mapping_for_destruct didn't do its job properly.\n"); + #endif    }    }    } -  + }      void real_gc_cycle_check_mapping(struct mapping *m, int weak)   {    GC_CYCLE_ENTER(m, weak) { -  +  struct mapping_data *md = m->data; +    #ifdef PIKE_DEBUG -  if(m->data->refs <=0) +  if(md->refs <=0)    fatal("Zero refs in mapping->data\n");   #endif    -  if((m->data->ind_types | m->data->val_types) & BIT_COMPLEX) +  if((md->ind_types | md->val_types) & BIT_COMPLEX)    {    INT32 e;    struct keypair *k;    -  if (m->flags & MAPPING_FLAG_WEAK) -  gc_recurse_weak_mapping(m, gc_cycle_check_weak_svalues); -  else -  NEW_MAPPING_LOOP(m->data) -  { -  if (gc_cycle_check_svalues(&k->ind, 1) || +  if (MAPPING_DATA_IN_USE(md)) { +  /* Must leave destructed indices intact if the mapping data is busy. */ +  NEW_MAPPING_LOOP(md) +  if ((!IS_DESTRUCTED(&k->ind) && gc_cycle_check_svalues(&k->ind, 1)) |    gc_cycle_check_svalues(&k->val, 1)) {   #ifdef PIKE_DEBUG -  fatal("Looks like check_mapping_for_destruct " -  "didn't do its job properly.\n"); +  fatal("Didn't expect an svalue zapping now.\n");   #endif    }    } -  +  else if (md->flags & MAPPING_FLAG_WEAK) +  gc_recurse_weak_mapping(m, gc_cycle_check_weak_svalues); +  else +  NEW_MAPPING_LOOP(md) +  if (gc_cycle_check_svalues(&k->ind, 1) | gc_cycle_check_svalues(&k->val, 1)) { + #ifdef PIKE_DEBUG +  fatal("stealth_check_mapping_for_destruct didn't do its job properly.\n"); + #endif    } -  +  }    } GC_CYCLE_LEAVE;   }      static void gc_check_mapping(struct mapping *m)   { -  +  struct mapping_data *md = m->data; +  +  if((md->ind_types | md->val_types) & BIT_COMPLEX) +  {    INT32 e;    struct keypair *k;    -  if((m->data->ind_types | m->data->val_types) & BIT_COMPLEX) -  { -  if(debug_gc_check(m->data, T_MAPPING, m)) return; +  if(debug_gc_check(md, T_MAPPING, m)) return;    -  if (m->flags & MAPPING_FLAG_WEAK) { -  MAPPING_LOOP(m) +  if (md->flags & MAPPING_FLAG_WEAK && !MAPPING_DATA_IN_USE(md)) { +  /* Disregard the weak flag if the mapping data is busy; we must +  * leave it untouched in that case anyway. */ +  NEW_MAPPING_LOOP(md)    { -  /* We do not want to count this key:index pair if -  * the index is a destructed object or function -  */ -  if(((1 << k->ind.type) & (BIT_OBJECT | BIT_FUNCTION)) && -  !(k->ind.u.object->prog)) -  continue; -  +     debug_gc_check_weak_svalues(&k->ind, 1, T_MAPPING, m);    debug_gc_check_weak_svalues(&k->val, 1, T_MAPPING, m);    }    }    else { -  MAPPING_LOOP(m) +  NEW_MAPPING_LOOP(md)    { -  /* We do not want to count this key:index pair if -  * the index is a destructed object or function -  */ -  if(((1 << k->ind.type) & (BIT_OBJECT | BIT_FUNCTION)) && -  !(k->ind.u.object->prog)) -  continue; -  +     debug_gc_check_svalues(&k->ind, 1, T_MAPPING, m);    debug_gc_check_svalues(&k->val, 1, T_MAPPING, m);    }    }    }   }      #ifdef PIKE_DEBUG   unsigned gc_touch_all_mappings(void)   {    unsigned n = 0;    struct mapping *m;    if (first_mapping && first_mapping->prev)    fatal("Error in mapping link list.\n");    for (m = first_mapping; m; m = m->next) {    debug_gc_touch(m); -  +  debug_gc_touch(m->data);    n++;    if (m->next && m->next->prev != m)    fatal("Error in mapping link list.\n");    }    return n;   }   #endif      void gc_check_all_mappings(void)   {
pike.git/src/mapping.c:2023:   {    gc_mark_mapping_pos = gc_internal_mapping;    while (gc_mark_mapping_pos) {    struct mapping *m = gc_mark_mapping_pos;    gc_mark_mapping_pos = m->next;    if(gc_is_referenced(m))    gc_mark_mapping_as_referenced(m);    else    /* Done in gc_mark_mapping_as_referenced() otherwise (and it has    * to be done there). */ -  check_mapping_for_destruct(m); +  stealth_check_mapping_for_destruct(m);    }   }      void gc_cycle_check_all_mappings(void)   {    struct mapping *m;    for (m = gc_internal_mapping; m; m = m->next) {    real_gc_cycle_check_mapping(m, 0);    gc_cycle_run_queue();    }
pike.git/src/mapping.c:2065:    {    if(gc_do_free(m))    {    /* Got an extra ref from gc_cycle_pop(). */    md = m->data;    /* Protect against unlink_mapping_data() recursing too far. */    m->data=&empty_data;    m->data->refs++;       unlink_mapping_data(md); - #ifdef PIKE_DEBUG + #ifdef MAPPING_SIZE_DEBUG    m->debug_size=0;   #endif    gc_free_extra_ref(m);    SET_NEXT_AND_FREE(m, free_mapping);    }    else    {    next=m->next;    }    }
pike.git/src/mapping.c:2093: Inside #if defined(PIKE_DEBUG)
   init_buf();    describe_mapping(m,0,2);    s=simple_free_buf();    fprintf(stderr,"%s\n",s);    free(s);   }         void debug_dump_mapping(struct mapping *m)   { -  fprintf(stderr, "Refs=%d, flags=0x%x, next=%p, prev=%p", -  m->refs, m->flags, m->next, m->prev); +  fprintf(stderr, "Refs=%d, next=%p, prev=%p", +  m->refs, m->next, m->prev);    if (((ptrdiff_t)m->data) & 3) {    fprintf(stderr, ", data=%p (unaligned)\n", m->data);    } else { -  fprintf(stderr, ", size=%d, hashsize=%d\n", -  m->data->size, m->data->hashsize); +  fprintf(stderr, ", flags=0x%x, size=%d, hashsize=%d\n", +  m->data->flags, m->data->size, m->data->hashsize);    fprintf(stderr, "Indices type field = ");    debug_dump_type_field(m->data->ind_types);    fprintf(stderr, "\n");    fprintf(stderr, "Values type field = ");    debug_dump_type_field(m->data->val_types);    fprintf(stderr, "\n");    simple_describe_mapping(m);    }   }   #endif
pike.git/src/mapping.c:2140:    while((k=md->hash[e]))    {    md->hash[e]=k->next;    k->next=md->free_list;    md->free_list=k;    free_svalue(&k->ind);    free_svalue(&k->val);    }    }    md->size=0; - #ifdef PIKE_DEBUG + #ifdef MAPPING_SIZE_DEBUG    if(m->data ==md)    m->debug_size=0;   #endif       next=m->next;       /* free_mapping(m); */    }   }