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.55 2000/01/31 21:26:59 hubbe Exp $"); + RCSID("$Id: mapping.c,v 1.56 2000/02/01 06:25:06 hubbe Exp $");   #include "main.h"   #include "object.h"   #include "mapping.h"   #include "svalue.h"   #include "array.h"   #include "pike_macros.h"   #include "language.h"   #include "error.h"   #include "pike_memory.h"   #include "dynamic_buffer.h"
pike.git/src/mapping.c:197:    }       free((char *) md);   }      /* This function is used to rehash a mapping without loosing the internal    * order in each hash chain. This is to prevent mappings from becoming    * inefficient just after being rehashed.    * (wonder if this can't be done faster somehow?)    */ - static void mapping_rehash_backwards(struct mapping_data *md, struct keypair *p) + static void mapping_rehash_backwards(struct mapping *m, +  struct keypair *p)   {    unsigned INT32 h;    struct keypair *tmp;       if(!p) return; -  mapping_rehash_backwards(md,p->next); -  h=hash_svalue(& p->ind) % md->hashsize; -  tmp=md->free_list; -  md->free_list=tmp->next; -  tmp->next=md->hash[h]; -  md->hash[h]=tmp; -  tmp->ind=p->ind; -  tmp->val=p->val; -  md->size++; -  md->ind_types |= 1 << p->ind.type; -  md->val_types |= 1 << p->val.type; +  mapping_rehash_backwards(m,p->next); +  +  /* We insert without overwriting +  * however, this could still cause +  * problems. (for instance if someone does an +  * m_delete on an element that is not there yet.. +  */ +  low_mapping_insert(m, &p->ind, &p->val,0);   }      /* This function re-allocates a mapping. It adjusts the max no. of    * values can be fitted into the mapping. It takes a bit of time to    * run, but is used seldom enough not to degrade preformance significantly.    */   static struct mapping *rehash(struct mapping *m, int new_size)   {    struct mapping_data *md;   #ifdef PIKE_DEBUG    INT32 tmp=m->data->size;   #endif    INT32 e;    -  +  md=m->data;   #ifdef PIKE_DEBUG -  if(m->data->refs <=0) +  if(md->refs <=0)    fatal("Zero refs in mapping->data\n");       if(d_flag>1) check_mapping(m);   #endif    -  /* This can be optimized to do rehash and copy -  * in one operation.. -Hubbe -  */ -  md=m->data; -  if(md->refs>1) -  { -  debug_malloc_touch(md); -  md=m->data=copy_mapping_data(m->data); -  debug_malloc_touch(md); -  } -  - #ifdef PIKE_DEBUG -  if(d_flag>1) check_mapping(m); - #endif -  +     init_mapping(m, new_size);    debug_malloc_touch(m);    -  +  /* No need to do add_ref(md) because the ref +  * from 'm' is not freed yet +  */ +  md->valrefs++; +     for(e=0;e<md->hashsize;e++) -  mapping_rehash_backwards(m->data, md->hash[e]); -  m->data->size = md->size; +  mapping_rehash_backwards(m, md->hash[e]);    -  +  md->valrefs--; +    #ifdef PIKE_DEBUG    if(m->data->size != tmp)    fatal("Rehash failed, size not same any more.\n"); -  if(md->refs>1) -  fatal("MD has extra refs in rehash!\n"); +    #endif    -  free((char *)md); +  free_mapping_data(md);      #ifdef PIKE_DEBUG    if(d_flag>1) check_mapping(m);   #endif       return m;   }      /*    * No need for super efficiency, should not be called very often
pike.git/src/mapping.c:472: Inside #if defined(PIKE_DEBUG)
   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;   }      /* This function inserts key:val into the mapping m.    * Same as doing m[key]=val; in pike.    */ - void mapping_insert(struct mapping *m, + void low_mapping_insert(struct mapping *m,    struct svalue *key, -  struct svalue *val) +  struct svalue *val, +  int overwrite)   {    unsigned INT32 h,h2;    struct keypair *k, **prev;    struct mapping_data *md, *omd;      #ifdef PIKE_DEBUG    if(m->data->refs <=0)    fatal("Zero refs in mapping->data\n");   #endif   
pike.git/src/mapping.c:520:    free_mapping_data(md);    return;       mi_set_value:   #ifdef PIKE_DEBUG    if(m->data != md)    fatal("Wrong dataset in mapping_insert!\n");    if(d_flag>1) check_mapping(m);   #endif    free_mapping_data(md); +  if(!overwrite) return;    PREPARE_FOR_DATA_CHANGE2();    PROPAGATE(); /* propagate after preparing */    md->val_types |= 1 << val->type;    assign_svalue(& k->val, val);   #ifdef PIKE_DEBUG    if(d_flag>1) check_mapping(m);   #endif    return;       mi_insert:   #ifdef PIKE_DEBUG    if(m->data != md)    fatal("Wrong dataset in mapping_insert!\n");    if(d_flag>1) check_mapping(m);   #endif    free_mapping_data(md);    /* We do a re-hash here instead of copying the mapping. */    if((!(k=md->free_list)) || md->refs>1)    { -  +  debug_malloc_touch(m);    rehash(m, md->size * 2 + 2);    md=m->data;    k=md->free_list;    }    h=h2 % md->hashsize;       /* no need to lock here since we are not calling is_eq - Hubbe */       k=md->free_list;    md->free_list=k->next;
pike.git/src/mapping.c:562:    md->val_types |= 1 << val->type;    assign_svalue_no_free(& k->ind, key);    assign_svalue_no_free(& k->val, val);    md->size++;      #ifdef PIKE_DEBUG    if(d_flag>1) check_mapping(m);   #endif   }    + void mapping_insert(struct mapping *m, +  struct svalue *key, +  struct svalue *val) + { +  low_mapping_insert(m,key,val,1); + } +    union anything *mapping_get_item_ptr(struct mapping *m,    struct svalue *key,    TYPE_T t)   {    unsigned INT32 h, h2;    struct keypair *k, **prev;    struct mapping_data *md,*omd;      #ifdef PIKE_DEBUG    if(m->data->refs <=0)
pike.git/src/mapping.c:638: Inside #if defined(PIKE_DEBUG)
   if(d_flag)    check_mapping(m);   #endif    free_mapping_data(md);       if(t != T_INT) return 0;       /* no need to call PREPARE_* because we re-hash instead */    if(!(k=md->free_list) || md->refs>1)    { +  debug_malloc_touch(m);    rehash(m, md->size * 2 + 2);    md=m->data;    k=md->free_list;    }    h=h2 % md->hashsize;       md->free_list=k->next;    k->next=md->hash[h];    md->hash[h]=k;    assign_svalue_no_free(& k->ind, key);
pike.git/src/mapping.c:674:    struct svalue *to)   {    unsigned INT32 h,h2;    struct keypair *k, **prev;    struct mapping_data *md,*omd;      #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);   #endif       h2=hash_svalue(key);       LOW_FIND(is_eq, key,    struct svalue *tmp=&k->ind;    SAME_DATA(goto md_remove_value,    omd=md;    LOW_FIND(is_identical, tmp,    free_mapping_data(omd);    goto md_remove_value,    free_mapping_data(omd);    goto md_do_nothing)),    goto md_do_nothing);       md_do_nothing: -  +  debug_malloc_touch(m);    free_mapping_data(md);    if(to)    {    to->type=T_INT;    to->subtype=NUMBER_UNDEFINED;    to->u.integer=0;    }    return;       md_remove_value:   #ifdef PIKE_DEBUG    if(md->refs <= 1)    fatal("Too few refs i mapping->data\n");    if(m->data != md)    fatal("Wrong dataset in mapping_delete!\n");    if(d_flag>1) check_mapping(m); -  +  debug_malloc_touch(m);   #endif    free_mapping_data(md);    PREPARE_FOR_INDEX_CHANGE2();    /* No need to propagate */    *prev=k->next;    free_svalue(& k->ind);    if(to)    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--;       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;   }      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);   #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;
pike.git/src/mapping.c:778:    md->free_list=k;    md->size--;    }else{    val_types |= 1 << k->val.type;    ind_types |= 1 << k->ind.type;    prev=&k->next;    }    }    }    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    }   }      struct svalue *low_mapping_lookup(struct mapping *m,
pike.git/src/mapping.c:1097:   struct mapping *copy_mapping(struct mapping *m)   {    struct mapping *n;      #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;    n->data->refs++;    n->data->valrefs++;    n->data->hardlinks++;    debug_malloc_touch(n->data);    return n;   }   
pike.git/src/mapping.c:1828:    free_svalue(& k->val);    k->next=md->free_list;    md->free_list=k;    md->size--;    }else{    prev=&k->next;    }    }    }    if(MAP_SLOTS(md->size) < md->hashsize * MIN_LINK_LENGTH) +  { +  debug_malloc_touch(m);    rehash(m, MAP_SLOTS(md->size)); -  +  }    next=m->next;    free_mapping(m);    }    else    {    next=m->next;    }    }   }