pike.git / src / mapping.c

version» Context lines:

pike.git/src/mapping.c:299:   PMOD_EXPORT void do_free_mapping(struct mapping *m)   {    if (m)    inl_free_mapping(m);   }      /* This function is used to rehash a mapping without losing the internal    * order in each hash chain. This is to prevent mappings from becoming    * inefficient just after being rehashed.    */ + /* Evil: Steal the svalues from the old md. */   static void mapping_rehash_backwards_evil(struct mapping_data *md,    struct keypair *from)   {    unsigned INT32 h;    struct keypair *k, *prev = NULL, *next;       if(!(k = from)) return;       /* Reverse the hash chain. */    while ((next = k->next)) {    k->next = prev;    prev = k;    k = next;    }    k->next = prev;    -  from = k; +  prev = k;       /* Rehash and reverse the hash chain. */ -  while (from) { +  while ((from = prev)) { +  /* Reverse */ +  prev = from->next; +  from->next = next; +  next = from; +  +  if (md->flags & MAPPING_WEAK) { +  +  switch(md->flags & MAPPING_WEAK) { +  default: +  Pike_fatal("Instable mapping data flags.\n"); +  case MAPPING_WEAK_INDICES: +  if ((TYPEOF(from->ind) <= MAX_REF_TYPE) && +  (*from->ind.u.refs > 1)) { +  goto keep_keypair; +  } +  break; +  case MAPPING_WEAK_VALUES: +  if ((TYPEOF(from->val) <= MAX_REF_TYPE) && +  (*from->val.u.refs > 1)) { +  goto keep_keypair; +  } +  break; +  case MAPPING_WEAK: +  /* NB: Compat: Unreference counted values are counted +  * as multi-referenced here. +  */ +  if (((TYPEOF(from->ind) > MAX_REF_TYPE) || +  (*from->ind.u.refs > 1)) && +  ((TYPEOF(from->val) > MAX_REF_TYPE) || +  (*from->val.u.refs > 1))) { +  goto keep_keypair; +  } +  break; +  } +  +  /* Free. +  * Note that we don't need to free or unlink the keypair, +  * since that will be done by the caller anyway. */ +  free_svalue(&from->ind); +  free_svalue(&from->val); +  +  continue; +  } +  keep_keypair: +     /* unlink */    k=md->free_list;   #ifndef PIKE_MAPPING_KEYPAIR_LOOP   #ifdef PIKE_DEBUG    if(!k) Pike_fatal("Error in rehash: not enough keypairs.\n");   #endif    md->free_list=k->next;   #else /* PIKE_MAPPING_KEYPAIR_LOOP */    md->free_list++;   #endif /* !PIKE_MAPPING_KEYPAIR_LOOP */
pike.git/src/mapping.c:343:    /* link */    h=k->hval;    h&=md->hashsize - 1;    k->next=md->hash[h];    md->hash[h]=k;       /* update */    md->ind_types |= 1<< (TYPEOF(k->ind));    md->val_types |= 1<< (TYPEOF(k->val));    md->size++; -  -  /* Reverse */ -  prev = from->next; -  from->next = next; -  next = from; -  from = prev; +     }   }    -  + /* Good: Copy the svalues from the old md. */   static void mapping_rehash_backwards_good(struct mapping_data *md,    struct keypair *from)   {    unsigned INT32 h;    struct keypair *k, *prev = NULL, *next;       if(!(k = from)) return;       /* Reverse the hash chain. */    while ((next = k->next)) {    k->next = prev;    prev = k;    k = next;    }    k->next = prev;    -  from = k; +  prev = k;       /* Rehash and reverse the hash chain. */ -  while (from) { +  while ((from = prev)) { +  /* Reverse */ +  prev = from->next; +  from->next = next; +  next = from; +  +  if (md->flags & MAPPING_WEAK) { +  +  switch(md->flags & MAPPING_WEAK) { +  default: +  Pike_fatal("Instable mapping data flags.\n"); +  case MAPPING_WEAK_INDICES: +  if ((TYPEOF(from->ind) <= MAX_REF_TYPE) && +  (*from->ind.u.refs > 1)) { +  goto keep_keypair; +  } +  break; +  case MAPPING_WEAK_VALUES: +  if ((TYPEOF(from->val) <= MAX_REF_TYPE) && +  (*from->val.u.refs > 1)) { +  goto keep_keypair; +  } +  break; +  case MAPPING_WEAK: +  /* NB: Compat: Unreference counted values are counted +  * as multi-referenced here. +  */ +  if (((TYPEOF(from->ind) > MAX_REF_TYPE) || +  (*from->ind.u.refs > 1)) && +  ((TYPEOF(from->val) > MAX_REF_TYPE) || +  (*from->val.u.refs > 1))) { +  goto keep_keypair; +  } +  break; +  } +  +  /* Skip copying of this keypair. +  * +  * NB: We can't mess with the original md here, +  * since it might be in use by an iterator +  * or similar. +  */ +  +  continue; +  } +  keep_keypair: +     /* unlink */    k=md->free_list;   #ifndef PIKE_MAPPING_KEYPAIR_LOOP   #ifdef PIKE_DEBUG    if(!k) Pike_fatal("Error in rehash: not enough keypairs.\n");   #endif    md->free_list=k->next;   #else /* PIKE_MAPPING_KEYPAIR_LOOP */    md->free_list++;   #endif /* !PIKE_MAPPING_KEYPAIR_LOOP */
pike.git/src/mapping.c:398:    /* link */    h=k->hval;    h&=md->hashsize - 1;    k->next=md->hash[h];    md->hash[h]=k;       /* update */    md->ind_types |= 1<< (TYPEOF(k->ind));    md->val_types |= 1<< (TYPEOF(k->val));    md->size++; -  -  /* Reverse */ -  prev = from->next; -  from->next = next; -  next = from; -  from = prev; +     }   }      /** 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.    *    * @param m the mapping to be rehashed    * @param new_size new mappingsize    * @return the rehashed mapping
pike.git/src/mapping.c:445:    if ((md->hashsize == new_size) && (md->refs == 1)) return m;       init_mapping(m, new_size, md->flags);    debug_malloc_touch(m);    new_md=m->data;       /* This operation is now 100% atomic - no locking required */    if(md->refs>1)    {    /* good */ +  /* More than one reference to the md ==> We need to +  * keep it afterwards. +  */    for(e=0;e<md->hashsize;e++)    mapping_rehash_backwards_good(new_md, md->hash[e]);       unlink_mapping_data(md);    }else{    /* evil */ -  +  /* We have the only reference to the md, +  * so we can just copy the svalues without +  * bothering about type checking. +  */    for(e=0;e<md->hashsize;e++)    mapping_rehash_backwards_evil(new_md, md->hash[e]);       free((char *)md);    GC_FREE_BLOCK(md);    }      #ifdef PIKE_DEBUG    if(m->data->size != tmp)    Pike_fatal("Rehash failed, size not same any more.\n");