cb22561995-10-11Fredrik Hübinette (Hubbe) /*\
06983f1996-09-22Fredrik Hübinette (Hubbe) ||| This file a part of Pike, and is copyright by Fredrik Hubinette ||| Pike is distributed as GPL (General Public License)
cb22561995-10-11Fredrik Hübinette (Hubbe) ||| See the files COPYING and DISCLAIMER for more information. \*/
5cdf941999-09-06Henrik Grubbström (Grubba) /**/
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "global.h"
595dac2000-09-30Martin Stjernholm RCSID("$Id: mapping.c,v 1.108 2000/09/30 15:58:30 mast Exp $");
515b6c1996-06-09Fredrik Hübinette (Hubbe) #include "main.h" #include "object.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "mapping.h" #include "svalue.h" #include "array.h"
bb55f81997-03-16Fredrik Hübinette (Hubbe) #include "pike_macros.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "error.h"
9aa6fa1997-05-19Fredrik Hübinette (Hubbe) #include "pike_memory.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "dynamic_buffer.h" #include "interpret.h"
515b6c1996-06-09Fredrik Hübinette (Hubbe) #include "las.h"
c94c371996-03-28Fredrik Hübinette (Hubbe) #include "gc.h"
5588271998-01-13Henrik Grubbström (Grubba) #include "stralloc.h"
7e97c31999-01-21Fredrik Hübinette (Hubbe) #include "security.h"
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #include "block_alloc.h"
f76b4c2000-05-11Henrik Grubbström (Grubba) #include "opcodes.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) 
06983f1996-09-22Fredrik Hübinette (Hubbe) #define AVG_LINK_LENGTH 4 #define MIN_LINK_LENGTH 1
9076fa1997-02-17Fredrik Hübinette (Hubbe) #define MAP_SLOTS(X) ((X)?((X)+((X)>>4)+8):0)
5267b71995-08-09Fredrik Hübinette (Hubbe)  struct mapping *first_mapping;
e2d9e62000-06-10Martin Stjernholm struct mapping *gc_internal_mapping = 0; static struct mapping *gc_mark_mapping_pos = 0;
1f342f2000-02-04Fredrik Hübinette (Hubbe) #define unlink_mapping_data(M) do{ \ struct mapping_data *md_=(M); \ if(md_->hardlinks) { md_->hardlinks--; md_->valrefs--; } \ free_mapping_data(M); \ }while(0)
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #define MD_KEYPAIRS(MD, HSIZE) \
c048112000-08-07Henrik Grubbström (Grubba)  ( (struct keypair *)DO_ALIGN( (ptrdiff_t) (((struct mapping_data *)(MD))->hash + HSIZE), ALIGNOF(struct keypair)) )
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  #define MAPPING_DATA_SIZE(HSIZE, KEYPAIRS) \
f5757f2000-08-11Henrik Grubbström (Grubba)  (ptrdiff_t)( MD_KEYPAIRS(0, HSIZE) + KEYPAIRS )
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  #undef EXIT_BLOCK #define EXIT_BLOCK(m) \ INT32 e; \
62aab62000-02-04Fredrik Hübinette (Hubbe) DO_IF_DEBUG( \
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(m->refs) \ fatal("really free mapping on mapping with nonzero refs.\n"); \ ) \ \ FREE_PROT(m); \ \
1f342f2000-02-04Fredrik Hübinette (Hubbe)  unlink_mapping_data(m->data); \
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  \
e2d9e62000-06-10Martin Stjernholm  if (gc_internal_mapping) { \ if (m == gc_internal_mapping) \ gc_internal_mapping = m->next; \ if (m == gc_mark_mapping_pos) \ gc_mark_mapping_pos = m->next; \ } \ DOUBLEUNLINK(first_mapping, m); \
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  \
553d232000-09-14Martin Stjernholm  GC_FREE(m);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  #undef COUNT_OTHER #define COUNT_OTHER() do{ \ struct mapping *m; \ for(m=first_mapping;m;m=m->next) \ { \ num++; \ size+=MAPPING_DATA_SIZE(m->data->hashsize, m->data->num_keypairs); \ } \ }while(0) BLOCK_ALLOC(mapping, 511)
06983f1996-09-22Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
06983f1996-09-22Fredrik Hübinette (Hubbe) /* This function checks that the type field isn't lacking any bits. * It is used for debugging purposes only.
5267b71995-08-09Fredrik Hübinette (Hubbe)  */
06983f1996-09-22Fredrik Hübinette (Hubbe) static void check_mapping_type_fields(struct mapping *m)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
06983f1996-09-22Fredrik Hübinette (Hubbe)  INT32 e;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct keypair *k=0,**prev;
06983f1996-09-22Fredrik Hübinette (Hubbe)  TYPE_FIELD ind_types, val_types; ind_types=val_types=0;
0cde281998-05-14Fredrik Hübinette (Hubbe)  MAPPING_LOOP(m)
06983f1996-09-22Fredrik Hübinette (Hubbe)  { val_types |= 1 << k->val.type; ind_types |= 1 << k->ind.type; }
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(val_types & ~(m->data->val_types))
06983f1996-09-22Fredrik Hübinette (Hubbe)  fatal("Mapping value types out of order!\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(ind_types & ~(m->data->ind_types))
06983f1996-09-22Fredrik Hübinette (Hubbe)  fatal("Mapping indices types out of order!\n");
5267b71995-08-09Fredrik Hübinette (Hubbe) }
06983f1996-09-22Fredrik Hübinette (Hubbe) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) 
5eca4d2000-09-04Martin Stjernholm static struct mapping_data empty_data = { 1, 1, 0,0,0,0,0,0 };
06983f1996-09-22Fredrik Hübinette (Hubbe)  /* 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.
5267b71995-08-09Fredrik Hübinette (Hubbe)  */
515b6c1996-06-09Fredrik Hübinette (Hubbe) static void init_mapping(struct mapping *m, INT32 size) {
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct mapping_data *md;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  char *tmp;
f5757f2000-08-11Henrik Grubbström (Grubba)  ptrdiff_t e;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  INT32 hashsize;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  debug_malloc_touch(m);
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
5eca4d2000-09-04Martin Stjernholm  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");
515b6c1996-06-09Fredrik Hübinette (Hubbe)  if(size < 0) fatal("init_mapping with negative value.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
9076fa1997-02-17Fredrik Hübinette (Hubbe)  if(size) { hashsize=size / AVG_LINK_LENGTH + 1; if(!(hashsize & 1)) hashsize++;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  e=MAPPING_DATA_SIZE(hashsize, size); md=(struct mapping_data *)xalloc(e);
7bf6232000-04-23Martin Stjernholm 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  m->data=md; md->hashsize=hashsize;
9076fa1997-02-17Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  MEMSET((char *)md->hash, 0, sizeof(struct keypair *) * md->hashsize);
9076fa1997-02-17Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md->free_list=MD_KEYPAIRS(md, hashsize);
9076fa1997-02-17Fredrik Hübinette (Hubbe)  for(e=1;e<size;e++)
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  { 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;
5eca4d2000-09-04Martin Stjernholm  md->flags = 0;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md->size = 0; md->refs=0; md->valrefs=0; md->hardlinks=0; md->num_keypairs=size;
9076fa1997-02-17Fredrik Hübinette (Hubbe)  }else{
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md=&empty_data;
9076fa1997-02-17Fredrik Hübinette (Hubbe)  }
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  add_ref(md); m->data=md;
5eca4d2000-09-04Martin Stjernholm #ifdef MAPPING_SIZE_DEBUG
20b19f2000-02-09Fredrik Hübinette (Hubbe)  m->debug_size = md->size;
9e398c2000-02-08Fredrik Hübinette (Hubbe) #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe) }
06983f1996-09-22Fredrik Hübinette (Hubbe) /* This function allocates an empty mapping with room for 'size' values
5267b71995-08-09Fredrik Hübinette (Hubbe)  */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct mapping *debug_allocate_mapping(int size)
5267b71995-08-09Fredrik Hübinette (Hubbe) { struct mapping *m;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  m=alloc_mapping();
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
7bf6232000-04-23Martin Stjernholm  GC_ALLOC(m);
7e97c31999-01-21Fredrik Hübinette (Hubbe)  INITIALIZE_PROT(m);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  init_mapping(m,size);
5267b71995-08-09Fredrik Hübinette (Hubbe)  m->refs = 1;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
e2d9e62000-06-10Martin Stjernholm  DOUBLELINK(first_mapping, m);
5267b71995-08-09Fredrik Hübinette (Hubbe)  return m; }
57a4ab2000-01-27Fredrik Hübinette (Hubbe) 
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void really_free_mapping_data(struct mapping_data *md)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  INT32 e; struct keypair *k;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  debug_malloc_touch(md);
7dd0d72000-09-14Martin Stjernholm 
765de02000-01-28Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG if (md->refs) { fatal("really_free_mapping_data(): md has non-zero refs: %d\n", md->refs); } #endif /* PIKE_DEBUG */
7dd0d72000-09-14Martin Stjernholm 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  NEW_MAPPING_LOOP(md)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  { free_svalue(& k->val); free_svalue(& k->ind); }
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  free((char *) md);
553d232000-09-14Martin Stjernholm  GC_FREE_BLOCK(md);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void do_free_mapping(struct mapping *m)
65b6732000-07-07Martin Stjernholm { if (m) free_mapping(m); }
06983f1996-09-22Fredrik Hübinette (Hubbe) /* This function is used to rehash a mapping without loosing the internal * order in each hash chain. This is to prevent mappings from becoming
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  * inefficient just after being rehashed.
06983f1996-09-22Fredrik Hübinette (Hubbe)  */
54beb22000-02-01Fredrik Hübinette (Hubbe) static void mapping_rehash_backwards_evil(struct mapping_data *md, struct keypair *from)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  unsigned INT32 h; struct keypair *tmp;
54beb22000-02-01Fredrik Hübinette (Hubbe)  struct keypair *k; if(!from) return; mapping_rehash_backwards_evil(md,from->next); /* unlink */ k=md->free_list; #ifdef PIKE_DEBUG
27bec92000-02-15Henrik Grubbström (Grubba)  if(!k) fatal("Error in rehash: not enough keypairs.\n");
54beb22000-02-01Fredrik Hübinette (Hubbe) #endif md->free_list=k->next; /* initialize */ *k=*from; /* link */ h=k->hval; h%=md->hashsize; k->next=md->hash[h]; md->hash[h]=k; /* update */ md->ind_types |= 1<< (k->ind.type); md->val_types |= 1<< (k->val.type); md->size++; } static void mapping_rehash_backwards_good(struct mapping_data *md, struct keypair *from) { unsigned INT32 h; struct keypair *tmp; struct keypair *k; if(!from) return; mapping_rehash_backwards_good(md,from->next); /* unlink */ k=md->free_list; #ifdef PIKE_DEBUG
27bec92000-02-15Henrik Grubbström (Grubba)  if(!k) fatal("Error in rehash: not enough keypairs.\n");
54beb22000-02-01Fredrik Hübinette (Hubbe) #endif md->free_list=k->next;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
54beb22000-02-01Fredrik Hübinette (Hubbe)  /* initialize */ k->hval=from->hval; assign_svalue_no_free(&k->ind, &from->ind); assign_svalue_no_free(&k->val, &from->val);
59e53e2000-01-31Fredrik Hübinette (Hubbe) 
54beb22000-02-01Fredrik Hübinette (Hubbe)  /* link */ h=k->hval; h%=md->hashsize; k->next=md->hash[h]; md->hash[h]=k; /* update */ md->ind_types |= 1<< (k->ind.type); md->val_types |= 1<< (k->val.type); md->size++;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
06983f1996-09-22Fredrik Hübinette (Hubbe) /* 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. */
515b6c1996-06-09Fredrik Hübinette (Hubbe) static struct mapping *rehash(struct mapping *m, int new_size)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
54beb22000-02-01Fredrik Hübinette (Hubbe)  struct mapping_data *md, *new_md;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  INT32 tmp=m->data->size;
515b6c1996-06-09Fredrik Hübinette (Hubbe) #endif
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  INT32 e;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
59e53e2000-01-31Fredrik Hübinette (Hubbe)  md=m->data;
27bec92000-02-15Henrik Grubbström (Grubba)  debug_malloc_touch(md);
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
59e53e2000-01-31Fredrik Hübinette (Hubbe)  if(md->refs <=0)
765de02000-01-28Henrik Grubbström (Grubba)  fatal("Zero refs in mapping->data\n");
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(d_flag>1) check_mapping(m); #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  init_mapping(m, new_size);
616b622000-01-31Fredrik Hübinette (Hubbe)  debug_malloc_touch(m);
54beb22000-02-01Fredrik Hübinette (Hubbe)  new_md=m->data;
c193a62000-09-07Fredrik Hübinette (Hubbe)  new_md->flags = md->flags;
57a4ab2000-01-27Fredrik Hübinette (Hubbe) 
54beb22000-02-01Fredrik Hübinette (Hubbe)  /* This operation is now 100% atomic - no locking required */ if(md->refs>1) { /* good */ for(e=0;e<md->hashsize;e++) mapping_rehash_backwards_good(new_md, md->hash[e]);
59e53e2000-01-31Fredrik Hübinette (Hubbe) 
1f342f2000-02-04Fredrik Hübinette (Hubbe)  unlink_mapping_data(md);
54beb22000-02-01Fredrik Hübinette (Hubbe)  }else{ /* evil */ for(e=0;e<md->hashsize;e++) mapping_rehash_backwards_evil(new_md, md->hash[e]);
59e53e2000-01-31Fredrik Hübinette (Hubbe) 
54beb22000-02-01Fredrik Hübinette (Hubbe)  free((char *)md);
553d232000-09-14Martin Stjernholm  GC_FREE_BLOCK(md);
54beb22000-02-01Fredrik Hübinette (Hubbe)  }
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  #ifdef PIKE_DEBUG if(m->data->size != tmp) fatal("Rehash failed, size not same any more.\n");
5eca4d2000-09-04Martin Stjernholm #endif #ifdef MAPPING_SIZE_DEBUG
20b19f2000-02-09Fredrik Hübinette (Hubbe)  m->debug_size = m->data->size;
515b6c1996-06-09Fredrik Hübinette (Hubbe) #endif
57a4ab2000-01-27Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(d_flag>1) check_mapping(m);
06983f1996-09-22Fredrik Hübinette (Hubbe) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe)  return m; }
57a4ab2000-01-27Fredrik Hübinette (Hubbe) /* * No need for super efficiency, should not be called very often * -Hubbe */ #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) {
f5757f2000-08-11Henrik Grubbström (Grubba)  long e; ptrdiff_t size, off;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct mapping_data *nmd; struct keypair *keypairs;
5eca4d2000-09-04Martin Stjernholm #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
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  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]); keypairs=MD_KEYPAIRS(nmd, nmd->hashsize); for(e=0;e<nmd->num_keypairs;e++) { RELOC(keypairs[e].next); add_ref_svalue(& keypairs[e].ind); add_ref_svalue(& keypairs[e].val); } nmd->refs=1; nmd->valrefs=0; nmd->hardlinks=0; if(md->hardlinks) { #ifdef PIKE_DEBUG if(md->refs <= 0 || md->valrefs<=0) fatal("Hardlink without refs/valrefs!\n"); #endif md->hardlinks--; md->valrefs--; } md->refs--; return nmd; }
5eca4d2000-09-04Martin Stjernholm #define MAPPING_DATA_IN_USE(MD) ((MD)->refs != (MD)->hardlinks + 1)
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #define LOW_FIND(FUN, KEY, FOUND, NOT_FOUND) do { \ md=m->data; \ add_ref(md); \ if(md->hashsize) \ { \ h=h2 % md->hashsize; \
9e398c2000-02-08Fredrik Hübinette (Hubbe)  DO_IF_DEBUG( if(d_flag > 1) check_mapping_type_fields(m); ) \
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->ind_types & (1 << key->type)) \ { \ for(prev= md->hash + h;(k=*prev);prev=&k->next) \ { \
54beb22000-02-01Fredrik Hübinette (Hubbe)  if(h2 == k->hval && FUN(& k->ind, KEY)) \
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  { \ FOUND; \ } \ } \ } \ } \ NOT_FOUND; \ }while(0) #define LOW_FIND2(FUN, KEY, FOUND, NOT_FOUND) do { \ struct keypair *k2; \ md=m->data; \ add_ref(md); \ if(md->hashsize) \ { \ h=h2 % md->hashsize; \
9e398c2000-02-08Fredrik Hübinette (Hubbe)  DO_IF_DEBUG( if(d_flag > 1) check_mapping_type_fields(m); ) \
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->ind_types & (1 << key->type)) \ { \ k2=omd->hash[h2 % md->hashsize]; \ prev= md->hash + h; \ for(;(k=*prev) && k2;(prev=&k->next),(k2=k2->next)) \
54beb22000-02-01Fredrik Hübinette (Hubbe)  if(!(h2 == k->hval && is_identical(&k2->ind, &k->ind))) \
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  break; \ for(;(k=*prev);prev=&k->next) \ { \ if(FUN(& k->ind, KEY)) \ { \ FOUND; \ } \ } \ } \ } \ NOT_FOUND; \ }while(0) #define SAME_DATA(SAME,NOT_SAME) \ if(m->data == md) \ { \ SAME; \ }else{ \ NOT_SAME; \ } /* FIXME: the 'no action' might need to be fixed.... */ #define FIND() do{ \ LOW_FIND(is_eq, key, \ omd=md; \ SAME_DATA( break, \ struct svalue *tmp=&k->ind; \ LOW_FIND(is_identical, tmp, break, ;); \ free_mapping_data(omd)), \ break); \ free_mapping_data(md); \ }while(0) /* Assumes md is *NOT* locked */ #define COPYMAP2() do { \
aa45cf2000-08-07Henrik Grubbström (Grubba)  ptrdiff_t off; \
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  m->data=copy_mapping_data(m->data); \ debug_malloc_touch(m->data); \
d3018a2000-01-30Fredrik Hübinette (Hubbe)  DO_IF_DEBUG( if(d_flag>1) check_mapping(m); ) \
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  off=((char *)m->data)-((char *)md); \ LOW_RELOC(k); \ LOW_RELOC(prev); \ md=m->data; \ }while(0) #define PREPARE_FOR_DATA_CHANGE2() \ if(md->valrefs) COPYMAP2() #define PREPARE_FOR_INDEX_CHANGE2() \ if(md->refs>1) COPYMAP2() #define PROPAGATE() do { \ if(md->refs==1) \ { \ h=h2 % md->hashsize; \ *prev=k->next; \ k->next=md->hash[h]; \ md->hash[h]=k; \ } \ }while(0) /* Assumes md is locked */ #define COPYMAP() do { \
d1f2712000-08-07Henrik Grubbström (Grubba)  ptrdiff_t off; \
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  m->data=copy_mapping_data(m->data); \ debug_malloc_touch(m->data); \ off=((char *)m->data)-((char *)md); \ LOW_RELOC(k); \ free_mapping_data(md); \ md=m->data; \ md->refs++; \ }while(0) #define PREPARE_FOR_DATA_CHANGE() \ if(md->valrefs) COPYMAP() #define PREPARE_FOR_INDEX_CHANGE() \ if(md->refs>1) COPYMAP()
06983f1996-09-22Fredrik Hübinette (Hubbe) /* This function brings the type fields in the mapping up to speed. * I only use it when the type fields MUST be correct, which is not * very often. */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void mapping_fix_type_field(struct mapping *m)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  INT32 e; struct keypair *k; TYPE_FIELD ind_types, val_types; val_types = ind_types = 0;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  NEW_MAPPING_LOOP(m->data)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  { val_types |= 1 << k->val.type; ind_types |= 1 << k->ind.type; }
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(val_types & ~(m->data->val_types))
515b6c1996-06-09Fredrik Hübinette (Hubbe)  fatal("Mapping value types out of order!\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(ind_types & ~(m->data->ind_types))
515b6c1996-06-09Fredrik Hübinette (Hubbe)  fatal("Mapping indices types out of order!\n"); #endif
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  m->data->val_types = val_types; m->data->ind_types = ind_types;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
5eca4d2000-09-04Martin Stjernholm PMOD_EXPORT void mapping_set_flags(struct mapping *m, int flags) { struct mapping_data *md = m->data; if (md->refs > 1) {
f258372000-09-08Henrik Grubbström (Grubba)  struct keypair *k = NULL, *prev = NULL;
5eca4d2000-09-04Martin Stjernholm  COPYMAP2(); } md->flags = flags; }
06983f1996-09-22Fredrik Hübinette (Hubbe) /* This function inserts key:val into the mapping m. * Same as doing m[key]=val; in pike. */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void low_mapping_insert(struct mapping *m,
59e53e2000-01-31Fredrik Hübinette (Hubbe)  struct svalue *key, struct svalue *val, int overwrite)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
9076fa1997-02-17Fredrik Hübinette (Hubbe)  unsigned INT32 h,h2;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct keypair *k, **prev;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct mapping_data *md, *omd; #ifdef PIKE_DEBUG if(m->data->refs <=0)
765de02000-01-28Henrik Grubbström (Grubba)  fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
9076fa1997-02-17Fredrik Hübinette (Hubbe)  h2=hash_svalue(key);
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(d_flag>1) check_mapping(m);
515b6c1996-06-09Fredrik Hübinette (Hubbe) #endif
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  LOW_FIND(is_eq, key, struct svalue *tmp=&k->ind; SAME_DATA(goto mi_set_value, omd=md; LOW_FIND(is_identical, tmp, free_mapping_data(omd); goto mi_set_value, free_mapping_data(omd); goto mi_do_nothing)), Z: SAME_DATA(goto mi_insert, omd=md; LOW_FIND2(is_eq, key, free_mapping_data(omd); goto mi_do_nothing, free_mapping_data(omd); goto Z))); mi_do_nothing: free_mapping_data(md); return; mi_set_value:
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(m->data != md) fatal("Wrong dataset in mapping_insert!\n"); if(d_flag>1) check_mapping(m);
06983f1996-09-22Fredrik Hübinette (Hubbe) #endif
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  free_mapping_data(md);
59e53e2000-01-31Fredrik Hübinette (Hubbe)  if(!overwrite) return;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  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)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
59e53e2000-01-31Fredrik Hübinette (Hubbe)  debug_malloc_touch(m);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  rehash(m, md->size * 2 + 2); md=m->data; k=md->free_list;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  }
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  h=h2 % md->hashsize;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  /* no need to lock here since we are not calling is_eq - Hubbe */ 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;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  assign_svalue_no_free(& k->ind, key); assign_svalue_no_free(& k->val, val);
54beb22000-02-01Fredrik Hübinette (Hubbe)  k->hval = h2;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md->size++;
5eca4d2000-09-04Martin Stjernholm #ifdef MAPPING_SIZE_DEBUG
10da6b2000-04-15Fredrik Hübinette (Hubbe)  if(m->data ==md) m->debug_size++;
9e398c2000-02-08Fredrik Hübinette (Hubbe) #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(d_flag>1) check_mapping(m);
515b6c1996-06-09Fredrik Hübinette (Hubbe) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void mapping_insert(struct mapping *m,
59e53e2000-01-31Fredrik Hübinette (Hubbe)  struct svalue *key, struct svalue *val) { low_mapping_insert(m,key,val,1); }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT union anything *mapping_get_item_ptr(struct mapping *m,
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct svalue *key, TYPE_T t)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
9076fa1997-02-17Fredrik Hübinette (Hubbe)  unsigned INT32 h, h2;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct keypair *k, **prev;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct mapping_data *md,*omd;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(m->data->refs <=0)
765de02000-01-28Henrik Grubbström (Grubba)  fatal("Zero refs in mapping->data\n");
9076fa1997-02-17Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(d_flag>1) check_mapping(m);
06983f1996-09-22Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  debug_malloc_touch(m); debug_malloc_touch(m->data);
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
06983f1996-09-22Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  h2=hash_svalue(key); LOW_FIND(is_eq, key, struct svalue *tmp=&k->ind; SAME_DATA(goto mg_set_value, omd=md; LOW_FIND(is_identical, tmp, free_mapping_data(omd); goto mg_set_value, free_mapping_data(omd); goto mg_do_nothing)), Z: SAME_DATA(goto mg_insert, omd=md; LOW_FIND2(is_eq, key, free_mapping_data(omd); goto mg_do_nothing, free_mapping_data(omd); goto Z))); mg_do_nothing: free_mapping_data(md); return 0; mg_set_value:
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(m->data != md) fatal("Wrong dataset in mapping_get_item_ptr!\n"); if(d_flag) check_mapping(m);
06983f1996-09-22Fredrik Hübinette (Hubbe) #endif
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  free_mapping_data(md); if(k->val.type == t) { PREPARE_FOR_DATA_CHANGE2(); PROPAGATE(); /* prepare then propagate */ return & ( k->val.u );
515b6c1996-06-09Fredrik Hübinette (Hubbe)  }
9076fa1997-02-17Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  return 0; mg_insert: #ifdef PIKE_DEBUG if(m->data != md) fatal("Wrong dataset in mapping_get_item_ptr!\n"); 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)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
59e53e2000-01-31Fredrik Hübinette (Hubbe)  debug_malloc_touch(m);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  rehash(m, md->size * 2 + 2); md=m->data; k=md->free_list;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  }
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  h=h2 % md->hashsize;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md->free_list=k->next; k->next=md->hash[h]; md->hash[h]=k;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  assign_svalue_no_free(& k->ind, key); k->val.type=T_INT; k->val.subtype=NUMBER_NUMBER; k->val.u.integer=0;
54beb22000-02-01Fredrik Hübinette (Hubbe)  k->hval = h2;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md->ind_types |= 1 << key->type; md->val_types |= BIT_INT; md->size++;
5eca4d2000-09-04Martin Stjernholm #ifdef MAPPING_SIZE_DEBUG
10da6b2000-04-15Fredrik Hübinette (Hubbe)  if(m->data ==md) m->debug_size++;
9e398c2000-02-08Fredrik Hübinette (Hubbe) #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
06983f1996-09-22Fredrik Hübinette (Hubbe)  if(d_flag > 1) check_mapping_type_fields(m);
515b6c1996-06-09Fredrik Hübinette (Hubbe) #endif
06983f1996-09-22Fredrik Hübinette (Hubbe)  return & ( k->val.u );
515b6c1996-06-09Fredrik Hübinette (Hubbe) }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void map_delete_no_free(struct mapping *m,
ea0be61999-11-11Fredrik Hübinette (Hubbe)  struct svalue *key, struct svalue *to)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  unsigned INT32 h,h2;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct keypair *k, **prev;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct mapping_data *md,*omd;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(m->data->refs <=0)
765de02000-01-28Henrik Grubbström (Grubba)  fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(d_flag>1) check_mapping(m);
59e53e2000-01-31Fredrik Hübinette (Hubbe)  debug_malloc_touch(m);
06983f1996-09-22Fredrik Hübinette (Hubbe) #endif
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  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:
59e53e2000-01-31Fredrik Hübinette (Hubbe)  debug_malloc_touch(m);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  free_mapping_data(md);
ea0be61999-11-11Fredrik Hübinette (Hubbe)  if(to) { to->type=T_INT; to->subtype=NUMBER_UNDEFINED; to->u.integer=0; }
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  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);
59e53e2000-01-31Fredrik Hübinette (Hubbe)  debug_malloc_touch(m);
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #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--;
5eca4d2000-09-04Martin Stjernholm #ifdef MAPPING_SIZE_DEBUG
10da6b2000-04-15Fredrik Hübinette (Hubbe)  if(m->data ==md) m->debug_size--;
9e398c2000-02-08Fredrik Hübinette (Hubbe) #endif
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->size < (md->hashsize + 1) * MIN_LINK_LENGTH)
59e53e2000-01-31Fredrik Hübinette (Hubbe)  { debug_malloc_touch(m);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  rehash(m, MAP_SLOTS(m->data->size));
59e53e2000-01-31Fredrik Hübinette (Hubbe)  }
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  #ifdef PIKE_DEBUG if(d_flag>1) check_mapping(m); #endif return;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
5eca4d2000-09-04Martin Stjernholm 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; }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void check_mapping_for_destruct(struct mapping *m)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  INT32 e; struct keypair *k, **prev; TYPE_FIELD ind_types, val_types;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct mapping_data *md=m->data;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(m->data->refs <=0)
765de02000-01-28Henrik Grubbström (Grubba)  fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(d_flag>1) check_mapping(m);
59e53e2000-01-31Fredrik Hübinette (Hubbe)  debug_malloc_touch(m);
515b6c1996-06-09Fredrik Hübinette (Hubbe) #endif
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  /* no is_eq -> no locking */
9076fa1997-02-17Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(!md->size) return; if((md->ind_types | md->val_types) & (BIT_OBJECT | BIT_FUNCTION))
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  val_types = ind_types = 0;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md->val_types |= BIT_INT; for(e=0;e<md->hashsize;e++)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  for(prev= md->hash + e;(k=*prev);)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
4ab0aa1996-09-23Fredrik Hübinette (Hubbe)  if((k->ind.type == T_OBJECT || k->ind.type == T_FUNCTION) && !k->ind.u.object->prog)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
5eca4d2000-09-04Martin Stjernholm #ifdef MAPPING_SIZE_DEBUG size_t old_size = md->size; #endif
c5ae922000-04-16Fredrik Hübinette (Hubbe)  debug_malloc_touch(m);
5eca4d2000-09-04Martin Stjernholm  debug_malloc_touch(md);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  PREPARE_FOR_INDEX_CHANGE2();
5eca4d2000-09-04Martin Stjernholm  low_check_mapping_for_destruct (md, e, prev, ind_types, val_types); #ifdef MAPPING_SIZE_DEBUG m->debug_size -= old_size - md->size;
9e398c2000-02-08Fredrik Hübinette (Hubbe) #endif
5eca4d2000-09-04Martin Stjernholm  goto done;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  }else{
5eca4d2000-09-04Martin Stjernholm  check_destructed(& k->val);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  val_types |= 1 << k->val.type; ind_types |= 1 << k->ind.type;
cb859e1996-09-23Fredrik Hübinette (Hubbe)  prev=&k->next;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  } } }
5eca4d2000-09-04Martin Stjernholm  done:
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(MAP_SLOTS(md->size) < md->hashsize * MIN_LINK_LENGTH)
59e53e2000-01-31Fredrik Hübinette (Hubbe)  { debug_malloc_touch(m);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  rehash(m, MAP_SLOTS(md->size));
59e53e2000-01-31Fredrik Hübinette (Hubbe)  }
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
5eca4d2000-09-04Martin Stjernholm  if(d_flag>1) check_mapping(m);
515b6c1996-06-09Fredrik Hübinette (Hubbe) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
5eca4d2000-09-04Martin Stjernholm /* 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); }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct svalue *low_mapping_lookup(struct mapping *m,
06983f1996-09-22Fredrik Hübinette (Hubbe)  struct svalue *key)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  unsigned INT32 h,h2; struct keypair *k=0, **prev=0; struct mapping_data *md, *omd;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(m->data->refs <=0)
765de02000-01-28Henrik Grubbström (Grubba)  fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(d_flag>1) check_mapping(m);
515b6c1996-06-09Fredrik Hübinette (Hubbe) #endif
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  h2=hash_svalue(key); #ifdef PIKE_DEBUG if(d_flag > 1) check_mapping_type_fields(m); #endif FIND(); if(k)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  PROPAGATE(); return &k->val;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
515b6c1996-06-09Fredrik Hübinette (Hubbe)  return 0;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct svalue *low_mapping_string_lookup(struct mapping *m,
14dae91997-01-26Fredrik Hübinette (Hubbe)  struct pike_string *p) { struct svalue tmp; tmp.type=T_STRING; tmp.u.string=p; return low_mapping_lookup(m, &tmp); }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void mapping_string_insert(struct mapping *m,
a28dd21998-04-23Fredrik Hübinette (Hubbe)  struct pike_string *p, struct svalue *val) { struct svalue tmp; tmp.type=T_STRING; tmp.u.string=p; mapping_insert(m, &tmp, val); }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void mapping_string_insert_string(struct mapping *m,
ea0be61999-11-11Fredrik Hübinette (Hubbe)  struct pike_string *p, struct pike_string *val) { struct svalue tmp; tmp.type=T_STRING; tmp.u.string=val; mapping_string_insert(m, p, &tmp); }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct svalue *simple_mapping_string_lookup(struct mapping *m,
85f59e1998-01-08Fredrik Hübinette (Hubbe)  char *p) { struct pike_string *tmp; if((tmp=findstring(p))) return low_mapping_string_lookup(m,tmp); return 0; }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct svalue *mapping_mapping_lookup(struct mapping *m,
8a5d441999-10-19Fredrik Hübinette (Hubbe)  struct svalue *key1, struct svalue *key2, int create) { struct svalue tmp; struct mapping *m2; struct svalue *s=low_mapping_lookup(m, key1);
1e38531999-10-28Fredrik Hübinette (Hubbe)  debug_malloc_touch(m);
8a5d441999-10-19Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(m->data->refs <=0)
765de02000-01-28Henrik Grubbström (Grubba)  fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif
8a5d441999-10-19Fredrik Hübinette (Hubbe)  if(!s || !s->type==T_MAPPING) { if(!create) return 0; tmp.u.mapping=allocate_mapping(5); tmp.type=T_MAPPING; mapping_insert(m, key1, &tmp);
1e38531999-10-28Fredrik Hübinette (Hubbe)  debug_malloc_touch(m); debug_malloc_touch(tmp.u.mapping); free_mapping(tmp.u.mapping); /* There is one ref in 'm' */
8a5d441999-10-19Fredrik Hübinette (Hubbe)  s=&tmp; } m2=s->u.mapping;
1e38531999-10-28Fredrik Hübinette (Hubbe)  debug_malloc_touch(m2);
8a5d441999-10-19Fredrik Hübinette (Hubbe)  s=low_mapping_lookup(m2, key2); if(s) return s; if(!create) return 0; tmp.type=T_INT; tmp.subtype=NUMBER_UNDEFINED; tmp.u.integer=0; mapping_insert(m2, key2, &tmp);
1e38531999-10-28Fredrik Hübinette (Hubbe)  debug_malloc_touch(m2);
8a5d441999-10-19Fredrik Hübinette (Hubbe)  return low_mapping_lookup(m2, key2); }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct svalue *mapping_mapping_string_lookup(struct mapping *m,
8a5d441999-10-19Fredrik Hübinette (Hubbe)  struct pike_string *key1, struct pike_string *key2, int create) { struct svalue k1,k2; k1.type=T_STRING; k1.u.string=key1; k2.type=T_STRING; k2.u.string=key2; return mapping_mapping_lookup(m,&k1,&k2,create); }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void mapping_index_no_free(struct svalue *dest,
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct mapping *m, struct svalue *key)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct svalue *p;
9c6f7d1997-04-15Fredrik Hübinette (Hubbe)  if((p=low_mapping_lookup(m,key)))
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
06983f1996-09-22Fredrik Hübinette (Hubbe)  if(p->type==T_INT) p->subtype=NUMBER_NUMBER;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  assign_svalue_no_free(dest, p); }else{ dest->type=T_INT; dest->u.integer=0; dest->subtype=NUMBER_UNDEFINED; }
5267b71995-08-09Fredrik Hübinette (Hubbe) }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct array *mapping_indices(struct mapping *m)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  INT32 e; struct array *a; struct svalue *s; struct keypair *k;
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(m->data->refs <=0)
765de02000-01-28Henrik Grubbström (Grubba)  fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif
0279c82000-09-24Henrik Grubbström (Grubba)  check_mapping_for_destruct(m);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  a=allocate_array(m->data->size);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  s=ITEM(a);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  /* no locking required */ NEW_MAPPING_LOOP(m->data) assign_svalue(s++, & k->ind);
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  a->type_field = m->data->ind_types;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
06983f1996-09-22Fredrik Hübinette (Hubbe)  if(d_flag > 1) check_mapping_type_fields(m); #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe)  return a; }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct array *mapping_values(struct mapping *m)
515b6c1996-06-09Fredrik Hübinette (Hubbe) { INT32 e; struct keypair *k; struct array *a; struct svalue *s;
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(m->data->refs <=0)
765de02000-01-28Henrik Grubbström (Grubba)  fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif
0279c82000-09-24Henrik Grubbström (Grubba)  check_mapping_for_destruct(m);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  a=allocate_array(m->data->size);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  s=ITEM(a);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  /* no locking required */ NEW_MAPPING_LOOP(m->data) assign_svalue(s++, & k->val);
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  a->type_field = m->data->val_types;
06983f1996-09-22Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
06983f1996-09-22Fredrik Hübinette (Hubbe)  if(d_flag > 1) check_mapping_type_fields(m); #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe)  return a; }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct array *mapping_to_array(struct mapping *m)
2043ba1998-02-10Fredrik Hübinette (Hubbe) { INT32 e; struct keypair *k; struct array *a; struct svalue *s;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  #ifdef PIKE_DEBUG if(m->data->refs <=0)
765de02000-01-28Henrik Grubbström (Grubba)  fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif a=allocate_array(m->data->size);
2043ba1998-02-10Fredrik Hübinette (Hubbe)  s=ITEM(a);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  /* no locking required */ NEW_MAPPING_LOOP(m->data)
2043ba1998-02-10Fredrik Hübinette (Hubbe)  { struct array *b=allocate_array(2); assign_svalue(b->item+0, & k->ind); assign_svalue(b->item+1, & k->val); s->u.array=b; s->type=T_ARRAY;
1757d81998-05-12Fredrik Hübinette (Hubbe)  s++;
2043ba1998-02-10Fredrik Hübinette (Hubbe)  } a->type_field = BIT_ARRAY; return a; }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void mapping_replace(struct mapping *m,struct svalue *from, struct svalue *to)
515b6c1996-06-09Fredrik Hübinette (Hubbe) { INT32 e; struct keypair *k;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct mapping_data *md;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(m->data->refs <=0)
765de02000-01-28Henrik Grubbström (Grubba)  fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md=m->data; if(md->size) { add_ref(md); NEW_MAPPING_LOOP(md) { if(is_eq(& k->val, from)) { PREPARE_FOR_DATA_CHANGE(); assign_svalue(& k->val, to); md->val_types|=1<<to->type; } } free_mapping_data(md); }
06983f1996-09-22Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
06983f1996-09-22Fredrik Hübinette (Hubbe)  if(d_flag > 1) check_mapping_type_fields(m); #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe) }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct mapping *mkmapping(struct array *ind, struct array *val)
515b6c1996-06-09Fredrik Hübinette (Hubbe) { struct mapping *m; struct svalue *i,*v; INT32 e;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
515b6c1996-06-09Fredrik Hübinette (Hubbe)  if(ind->size != val->size) fatal("mkmapping on different sized arrays.\n"); #endif m=allocate_mapping(MAP_SLOTS(ind->size)); i=ITEM(ind); v=ITEM(val); for(e=0;e<ind->size;e++) mapping_insert(m, i++, v++); return m; }
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #if 0
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct mapping *copy_mapping(struct mapping *m)
515b6c1996-06-09Fredrik Hübinette (Hubbe) { INT32 e; struct mapping *n; struct keypair *k;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct mapping_data *md;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md=m->data; n=allocate_mapping(MAP_SLOTS(md->size));
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md->valrefs++; add_ref(md); NEW_MAPPING_LOOP(md) mapping_insert(n, &k->ind, &k->val); md->valrefs--; free_mapping_data(md);
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
36ce9c1996-10-08Fredrik Hübinette (Hubbe)  return n;
515b6c1996-06-09Fredrik Hübinette (Hubbe) }
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #else /* deferred mapping copy! */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct mapping *copy_mapping(struct mapping *m)
57a4ab2000-01-27Fredrik Hübinette (Hubbe) { struct mapping *n; #ifdef PIKE_DEBUG if(m->data->refs <=0)
765de02000-01-28Henrik Grubbström (Grubba)  fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif n=allocate_mapping(0);
59e53e2000-01-31Fredrik Hübinette (Hubbe)  if(!m_sizeof(m)) return n; /* done */
765de02000-01-28Henrik Grubbström (Grubba)  debug_malloc_touch(n->data);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  free_mapping_data(n->data); n->data=m->data;
5eca4d2000-09-04Martin Stjernholm #ifdef MAPPING_SIZE_DEBUG
e945ee2000-02-09Fredrik Hübinette (Hubbe)  n->debug_size=n->data->size; #endif
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  n->data->refs++; n->data->valrefs++; n->data->hardlinks++;
765de02000-01-28Henrik Grubbström (Grubba)  debug_malloc_touch(n->data);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  return n; } #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct mapping *merge_mappings(struct mapping *a, struct mapping *b, INT32 op)
515b6c1996-06-09Fredrik Hübinette (Hubbe) { struct array *ai, *av; struct array *bi, *bv; struct array *ci, *cv;
5267b71995-08-09Fredrik Hübinette (Hubbe)  INT32 *zipper;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct mapping *m;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(a->data->refs <=0)
765de02000-01-28Henrik Grubbström (Grubba)  fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(b->data->refs <=0)
765de02000-01-28Henrik Grubbström (Grubba)  fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe)  ai=mapping_indices(a); av=mapping_values(a);
61e9a01998-01-25Fredrik Hübinette (Hubbe)  if(ai->size > 1) { zipper=get_set_order(ai); order_array(ai, zipper); order_array(av, zipper); free((char *)zipper); }
515b6c1996-06-09Fredrik Hübinette (Hubbe)  bi=mapping_indices(b); bv=mapping_values(b);
61e9a01998-01-25Fredrik Hübinette (Hubbe)  if(bi->size > 1) { zipper=get_set_order(bi); order_array(bi, zipper); order_array(bv, zipper); free((char *)zipper); }
515b6c1996-06-09Fredrik Hübinette (Hubbe)  zipper=merge(ai,bi,op);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
515b6c1996-06-09Fredrik Hübinette (Hubbe)  ci=array_zip(ai,bi,zipper); free_array(ai); free_array(bi);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
515b6c1996-06-09Fredrik Hübinette (Hubbe)  cv=array_zip(av,bv,zipper); free_array(av); free_array(bv);
5267b71995-08-09Fredrik Hübinette (Hubbe)  free((char *)zipper);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  m=mkmapping(ci, cv); free_array(ci); free_array(cv); return m;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct mapping *merge_mapping_array_ordered(struct mapping *a,
2ad6b72000-01-29Mirar (Pontus Hagland)  struct array *b, INT32 op) { struct array *ai, *av; struct array *ci, *cv; INT32 *zipper; struct mapping *m; ai=mapping_indices(a); av=mapping_values(a); if(ai->size > 1) { zipper=get_set_order(ai); order_array(ai, zipper); order_array(av, zipper); free((char *)zipper); } switch (op) /* no elements from »b» may be selected */ { case PIKE_ARRAY_OP_AND: zipper=merge(b,ai,op); ci=array_zip(b,ai,zipper); /* b must not be used */ cv=array_zip(b,av,zipper); /* b must not be used */ break; case PIKE_ARRAY_OP_SUB: zipper=merge(ai,b,op); ci=array_zip(ai,b,zipper); /* b must not be used */ cv=array_zip(av,b,zipper); /* b must not be used */ break; default:
27bec92000-02-15Henrik Grubbström (Grubba)  fatal("merge_mapping_array on other than AND or SUB\n");
2ad6b72000-01-29Mirar (Pontus Hagland)  } free_array(ai); free_array(av); free((char *)zipper); m=mkmapping(ci, cv); free_array(ci); free_array(cv); return m; }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct mapping *merge_mapping_array_unordered(struct mapping *a,
2ad6b72000-01-29Mirar (Pontus Hagland)  struct array *b, INT32 op) { struct array *b_temp; INT32 *zipper; struct mapping *m; if (b->size>1) { zipper=get_set_order(b); b_temp=reorder_and_copy_array(b,zipper); m=merge_mapping_array_ordered(a,b_temp,op); free_array(b_temp); } else m=merge_mapping_array_ordered(a,b,op); return m; }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct mapping *add_mappings(struct svalue *argp, INT32 args)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
5cd1511998-04-27Fredrik Hübinette (Hubbe)  INT32 e,d;
59791f2000-09-08Fredrik Hübinette (Hubbe)  struct mapping *ret=0;
5cd1511998-04-27Fredrik Hübinette (Hubbe)  struct keypair *k;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  for(e=d=0;d<args;d++) { #ifdef PIKE_DEBUG if(d_flag>1) check_mapping(argp[d].u.mapping); #endif e+=argp[d].u.mapping->data->size; }
c193a62000-09-07Fredrik Hübinette (Hubbe)  if(!e) return allocate_mapping(0); d=0;
57a4ab2000-01-27Fredrik Hübinette (Hubbe) 
c193a62000-09-07Fredrik Hübinette (Hubbe)  for(;d<args;d++)
50d1d62000-04-30Fredrik Hübinette (Hubbe)  {
c193a62000-09-07Fredrik Hübinette (Hubbe)  struct mapping *m=argp[d].u.mapping; struct mapping_data *md=m->data; if(md->size == 0) continue;
59791f2000-09-08Fredrik Hübinette (Hubbe)  if(!(md->flags && MAPPING_FLAG_WEAK)) {
c193a62000-09-07Fredrik Hübinette (Hubbe) #if 1 /* major optimization */
59791f2000-09-08Fredrik Hübinette (Hubbe)  if(e==md->size) return copy_mapping(m);
c193a62000-09-07Fredrik Hübinette (Hubbe) #endif
59791f2000-09-08Fredrik Hübinette (Hubbe)  if(m->refs == 1 && !md->hardlinks) { add_ref( ret=m ); d++; break; }
c193a62000-09-07Fredrik Hübinette (Hubbe)  }
59791f2000-09-08Fredrik Hübinette (Hubbe)  ret=allocate_mapping(MAP_SLOTS(e)); break;
c193a62000-09-07Fredrik Hübinette (Hubbe) 
59791f2000-09-08Fredrik Hübinette (Hubbe)  }
c193a62000-09-07Fredrik Hübinette (Hubbe) 
59791f2000-09-08Fredrik Hübinette (Hubbe)  for(;d<args;d++) { struct mapping *m=argp[d].u.mapping; struct mapping_data *md=m->data; add_ref(md); NEW_MAPPING_LOOP(md) mapping_insert(ret, &k->ind, &k->val); free_mapping_data(md);
50d1d62000-04-30Fredrik Hübinette (Hubbe)  }
59791f2000-09-08Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(!ret) fatal("add_mappings is confused!\n"); #endif return ret;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT int mapping_equal_p(struct mapping *a, struct mapping *b, struct processing *p)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct processing curr; struct keypair *k;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct mapping_data *md; INT32 e,eq=1; #ifdef PIKE_DEBUG if(a->data->refs <=0)
765de02000-01-28Henrik Grubbström (Grubba)  fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(b->data->refs <=0)
765de02000-01-28Henrik Grubbström (Grubba)  fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe)  if(a==b) return 1;
5eca4d2000-09-04Martin Stjernholm  check_mapping_for_destruct(a); check_mapping_for_destruct(b);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(m_sizeof(a) != m_sizeof(b)) return 0;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  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;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md=a->data; md->valrefs++; add_ref(md); NEW_MAPPING_LOOP(md)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  { struct svalue *s;
9c6f7d1997-04-15Fredrik Hübinette (Hubbe)  if((s=low_mapping_lookup(b, & k->ind)))
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(!low_is_equal(s, &k->val, &curr)) { eq=0; break; }
515b6c1996-06-09Fredrik Hübinette (Hubbe)  }else{
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  eq=0; break;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  } }
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md->valrefs--; free_mapping_data(md); return eq;
5267b71995-08-09Fredrik Hübinette (Hubbe) } void describe_mapping(struct mapping *m,struct processing *p,int indent) { struct processing doing;
674fae2000-01-14Fredrik Noring  struct array *a; JMP_BUF catch; ONERROR err; INT32 e,d;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct keypair *k;
5267b71995-08-09Fredrik Hübinette (Hubbe)  char buf[40];
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(m->data->refs <=0)
765de02000-01-28Henrik Grubbström (Grubba)  fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif if(! m->data->size)
5267b71995-08-09Fredrik Hübinette (Hubbe)  { my_strcat("([ ])"); return; } doing.next=p; doing.pointer_a=(void *)m; for(e=0;p;e++,p=p->next) { if(p->pointer_a == (void *)m) {
f90e541995-08-17Fredrik Hübinette (Hubbe)  sprintf(buf,"@%ld",(long)e);
5267b71995-08-09Fredrik Hübinette (Hubbe)  my_strcat(buf); return; } }
d1cac52000-09-07Henrik Grubbström (Grubba)  if (m->data->size == 1) { my_strcat("([ /* 1 element */\n"); } else { sprintf(buf, "([ /* %ld elements */\n", (long)m->data->size); my_strcat(buf); }
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
674fae2000-01-14Fredrik Noring  a = mapping_indices(m); SET_ONERROR(err, do_free_array, a);
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
674fae2000-01-14Fredrik Noring  if(!SETJMP(catch)) sort_array_destructively(a); UNSETJMP(catch);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  /* no mapping locking required (I hope) */
674fae2000-01-14Fredrik Noring  for(e = 0; e < a->size; e++)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct svalue *tmp;
674fae2000-01-14Fredrik Noring  if(e) my_strcat(",\n"); for(d = 0; d < indent; d++) my_putchar(' '); describe_svalue(ITEM(a)+e, indent+2, &doing);
5267b71995-08-09Fredrik Hübinette (Hubbe)  my_putchar(':');
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if((tmp=low_mapping_lookup(m, ITEM(a)+e))) describe_svalue(tmp, indent+2, &doing); else my_strcat("** gone **");
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
674fae2000-01-14Fredrik Noring  UNSET_ONERROR(err); free_array(a);
5267b71995-08-09Fredrik Hübinette (Hubbe)  my_putchar('\n'); for(e=2; e<indent; e++) my_putchar(' '); my_strcat("])"); }
765de02000-01-28Henrik Grubbström (Grubba) node *make_node_from_mapping(struct mapping *m)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct keypair *k; INT32 e;
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(m->data->refs <=0)
765de02000-01-28Henrik Grubbström (Grubba)  fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe)  mapping_fix_type_field(m);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if((m->data->ind_types | m->data->val_types) & (BIT_FUNCTION | BIT_OBJECT))
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct array *ind, *val; node *n; ind=mapping_indices(m);
69d94d1997-04-23Fredrik Hübinette (Hubbe)  val=mapping_values(m);
3c04e81997-03-13Fredrik Hübinette (Hubbe)  n=mkefuncallnode("mkmapping", mknode(F_ARG_LIST, make_node_from_array(ind), make_node_from_array(val)));
515b6c1996-06-09Fredrik Hübinette (Hubbe)  free_array(ind); free_array(val); return n; }else{
5267b71995-08-09Fredrik Hübinette (Hubbe)  struct svalue s;
3c04e81997-03-13Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(!m->data->size)
3c04e81997-03-13Fredrik Hübinette (Hubbe)  return mkefuncallnode("aggregate_mapping",0);
5267b71995-08-09Fredrik Hübinette (Hubbe)  s.type=T_MAPPING; s.subtype=0; s.u.mapping=m; return mkconstantsvaluenode(&s); } }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void f_aggregate_mapping(INT32 args)
5267b71995-08-09Fredrik Hübinette (Hubbe) { INT32 e;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct keypair *k;
5267b71995-08-09Fredrik Hübinette (Hubbe)  struct mapping *m; if(args & 1)
24697f1997-03-12Henrik Grubbström (Grubba)  error("Uneven number of arguments to aggregate_mapping.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe) 
515b6c1996-06-09Fredrik Hübinette (Hubbe)  m=allocate_mapping(MAP_SLOTS(args / 2));
5267b71995-08-09Fredrik Hübinette (Hubbe) 
515b6c1996-06-09Fredrik Hübinette (Hubbe)  for(e=-args;e<0;e+=2) mapping_insert(m, sp+e, sp+e+1); pop_n_elems(args);
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(d_flag) check_mapping(m); #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe)  push_mapping(m);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct mapping *copy_mapping_recursively(struct mapping *m,
a12df92000-09-17Henrik Grubbström (Grubba)  struct processing *p)
5267b71995-08-09Fredrik Hübinette (Hubbe) { struct processing doing; struct mapping *ret;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  INT32 e; struct keypair *k;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct mapping_data *md; #ifdef PIKE_DEBUG if(m->data->refs <=0)
765de02000-01-28Henrik Grubbström (Grubba)  fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe)  doing.next=p; doing.pointer_a=(void *)m; for(;p;p=p->next) { if(p->pointer_a == (void *)m) {
d6ac731998-04-20Henrik Grubbström (Grubba)  add_ref(ret=(struct mapping *)p->pointer_b);
5267b71995-08-09Fredrik Hübinette (Hubbe)  return ret; } }
20b19f2000-02-09Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
9e398c2000-02-08Fredrik Hübinette (Hubbe)  if(d_flag > 1) check_mapping_type_fields(m);
20b19f2000-02-09Fredrik Hübinette (Hubbe) #endif
0b6c802000-02-03Fredrik Hübinette (Hubbe)  if(!((m->data->val_types | m->data->ind_types) & BIT_COMPLEX))
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  return copy_mapping(m); ret=allocate_mapping(MAP_SLOTS(m->data->size));
515b6c1996-06-09Fredrik Hübinette (Hubbe)  doing.pointer_b=ret;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
a12df92000-09-17Henrik Grubbström (Grubba)  ret->data->flags = m->data->flags;
f152401996-06-21Fredrik Hübinette (Hubbe)  check_stack(2);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md=m->data; md->valrefs++; add_ref(md);
c193a62000-09-07Fredrik Hübinette (Hubbe)  NEW_MAPPING_LOOP(md)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  { copy_svalues_recursively_no_free(sp,&k->ind, 1, p); sp++; copy_svalues_recursively_no_free(sp,&k->val, 1, p); sp++; mapping_insert(ret, sp-2, sp-1); pop_n_elems(2); }
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md->valrefs--; free_mapping_data(md);
5267b71995-08-09Fredrik Hübinette (Hubbe)  return ret; }
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void mapping_search_no_free(struct svalue *to,
5267b71995-08-09Fredrik Hübinette (Hubbe)  struct mapping *m, struct svalue *look_for,
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct svalue *key /* start */)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct mapping_data *md, *omd; #ifdef PIKE_DEBUG if(m->data->refs <=0)
765de02000-01-28Henrik Grubbström (Grubba)  fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif md=m->data;
9001b42000-01-27Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->size) {
9001b42000-01-27Fredrik Hübinette (Hubbe)  unsigned INT32 h2,h=0; struct keypair *k=md->hash[0], **prev;
57a4ab2000-01-27Fredrik Hübinette (Hubbe) 
9001b42000-01-27Fredrik Hübinette (Hubbe)  if(key)
9076fa1997-02-17Fredrik Hübinette (Hubbe)  {
9001b42000-01-27Fredrik Hübinette (Hubbe)  h2=hash_svalue(key); FIND(); if(!k)
9076fa1997-02-17Fredrik Hübinette (Hubbe)  {
9001b42000-01-27Fredrik Hübinette (Hubbe)  to->type=T_INT; to->subtype=NUMBER_UNDEFINED; to->u.integer=0; return; }
a11c9f2000-02-05Fredrik Hübinette (Hubbe)  k=k->next;
9001b42000-01-27Fredrik Hübinette (Hubbe)  } md=m->data; if(md->size) { md->valrefs++; add_ref(md); if(h < (unsigned INT32)md->hashsize) { while(1)
9076fa1997-02-17Fredrik Hübinette (Hubbe)  {
9001b42000-01-27Fredrik Hübinette (Hubbe)  while(k) { if(is_eq(look_for, &k->val)) { assign_svalue_no_free(to,&k->ind); md->valrefs--; free_mapping_data(md); return; } k=k->next; } h++; if(h>= (unsigned INT32)md->hashsize) break; k=md->hash[h];
9076fa1997-02-17Fredrik Hübinette (Hubbe)  } }
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  }
9001b42000-01-27Fredrik Hübinette (Hubbe)  md->valrefs--; free_mapping_data(md);
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
515b6c1996-06-09Fredrik Hübinette (Hubbe)  to->type=T_INT; to->subtype=NUMBER_UNDEFINED; to->u.integer=0;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
5267b71995-08-09Fredrik Hübinette (Hubbe) 
515b6c1996-06-09Fredrik Hübinette (Hubbe) void check_mapping(struct mapping *m)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
e2d5221998-05-16Fredrik Hübinette (Hubbe)  int e,num; struct keypair *k;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct mapping_data *md;
c5ae922000-04-16Fredrik Hübinette (Hubbe)  static int in_check_mapping; if(in_check_mapping) return; in_check_mapping=1;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md=m->data;
e2d5221998-05-16Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(m->refs <=0) fatal("Mapping has zero refs.\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(!m->data) fatal("Mapping has no data block.\n");
765de02000-01-28Henrik Grubbström (Grubba)  if (!m->data->refs) fatal("Mapping data block has zero refs.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(m->next && m->next->prev != m) fatal("Mapping ->next->prev != mapping.\n");
5eca4d2000-09-04Martin Stjernholm #ifdef MAPPING_SIZE_DEBUG
20b19f2000-02-09Fredrik Hübinette (Hubbe)  if(m->debug_size != md->size)
a4033e2000-04-14Fredrik Hübinette (Hubbe)  {
d9ad012000-04-16Fredrik Hübinette (Hubbe)  if(Pike_in_gc) { fprintf(stderr,"Pike was in GC stage %d when this fatal occured:\n",Pike_in_gc); Pike_in_gc=0; }
c5ae922000-04-16Fredrik Hübinette (Hubbe)  fprintf(stderr,"--MAPPING ZAPPING (%d!=%d), mapping:\n",m->debug_size,md->size);
a4033e2000-04-14Fredrik Hübinette (Hubbe)  describe(m);
c5ae922000-04-16Fredrik Hübinette (Hubbe)  fprintf(stderr,"--MAPPING ZAPPING (%d!=%d), mapping data:\n",m->debug_size,md->size);
a4033e2000-04-14Fredrik Hübinette (Hubbe)  describe(md); fatal("Mapping zapping detected (%d != %d)!\n",m->debug_size,md->size); }
5eca4d2000-09-04Martin Stjernholm #endif
9e398c2000-02-08Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  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"); }
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->valrefs <0) fatal("md->valrefs < 0\n"); if(md->hardlinks <0) fatal("md->valrefs < 0\n"); if(md->refs < md->valrefs+1) fatal("md->refs < md->valrefs+1\n"); if(md->valrefs < md->hardlinks) fatal("md->refs < md->valrefs+1\n"); if(md->hashsize < 0)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  fatal("Assert: I don't think he's going to make it Jim.\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->size < 0)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  fatal("Core breach, evacuate ship!\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->num_keypairs < 0) fatal("Starboard necell on fire!\n"); if(md->size > md->num_keypairs) fatal("Pretty mean hashtable there buster!\n"); if(md->hashsize > md->num_keypairs) fatal("Pretty mean hashtable there buster (2)!\n"); if(md->num_keypairs > (md->hashsize + 3) * AVG_LINK_LENGTH) fatal("Mapping from hell detected, attempting to send it back...\n");
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->size > 0 && (!md->ind_types || !md->val_types))
515b6c1996-06-09Fredrik Hübinette (Hubbe)  fatal("Mapping type fields are... wrong.\n");
e2d5221998-05-16Fredrik Hübinette (Hubbe)  num=0;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  NEW_MAPPING_LOOP(md)
e2d5221998-05-16Fredrik Hübinette (Hubbe)  { num++;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(! ( (1 << k->ind.type) & (md->ind_types) ))
e2d5221998-05-16Fredrik Hübinette (Hubbe)  fatal("Mapping indices type field lies.\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(! ( (1 << k->val.type) & (md->val_types) ))
e2d5221998-05-16Fredrik Hübinette (Hubbe)  fatal("Mapping values type field lies.\n");
59edba1998-08-05Fredrik Hübinette (Hubbe) 
0e46fc1998-08-05Fredrik Hübinette (Hubbe)  check_svalue(& k->ind); check_svalue(& k->val);
54beb22000-02-01Fredrik Hübinette (Hubbe)  /* FIXME add check for k->hval * beware that hash_svalue may be threaded and locking * is required!! */
e2d5221998-05-16Fredrik Hübinette (Hubbe)  }
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->size != num)
e2d5221998-05-16Fredrik Hübinette (Hubbe)  fatal("Shields are failing, hull integrity down to 20%%\n");
c5ae922000-04-16Fredrik Hübinette (Hubbe)  in_check_mapping=0;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
be478c1997-08-30Henrik Grubbström (Grubba) void check_all_mappings(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) { struct mapping *m; for(m=first_mapping;m;m=m->next)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  check_mapping(m); } #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) 
515b6c1996-06-09Fredrik Hübinette (Hubbe)  void gc_mark_mapping_as_referenced(struct mapping *m) {
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(m->data->refs <=0)
765de02000-01-28Henrik Grubbström (Grubba)  fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif
e2d9e62000-06-10Martin Stjernholm  if(gc_mark(m)) {
5eca4d2000-09-04Martin Stjernholm  struct mapping_data *md = m->data;
e2d9e62000-06-10Martin Stjernholm  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. */ }
1b0ac81999-10-29Martin Stjernholm 
595dac2000-09-30Martin Stjernholm  if(gc_mark(md)) { if ((md->ind_types | md->val_types) & BIT_COMPLEX) { INT32 e; struct keypair *k; if (MAPPING_DATA_IN_USE(md)) { /* Must leave destructed indices intact if the mapping data is busy. */ stealth_check_mapping_for_destruct(m); NEW_MAPPING_LOOP(md) { if (!IS_DESTRUCTED(&k->ind) && gc_mark_svalues(&k->ind, 1)) {
5eca4d2000-09-04Martin Stjernholm #ifdef PIKE_DEBUG
595dac2000-09-30Martin Stjernholm  fatal("Didn't expect an svalue zapping now.\n");
5eca4d2000-09-04Martin Stjernholm #endif
595dac2000-09-30Martin Stjernholm  } if (gc_mark_svalues(&k->val, 1)) {
c4ccb82000-07-04Martin Stjernholm #ifdef PIKE_DEBUG
595dac2000-09-30Martin Stjernholm  fatal("stealth_check_mapping_for_destruct didn't do its job properly.\n");
c4ccb82000-07-04Martin Stjernholm #endif
595dac2000-09-30Martin Stjernholm  } } gc_assert_checked_as_nonweak(md); } else if (md->flags & MAPPING_FLAG_WEAK) { INT32 e; struct keypair *k,**prev; TYPE_FIELD ind_types = 0, val_types = 0; /* no locking required (no is_eq) */ for(e=0;e<md->hashsize;e++) { for(prev= md->hash + e;(k=*prev);) { int i = gc_mark_weak_svalues(&k->ind, 1); int v = gc_mark_weak_svalues(&k->val, 1); if(i || v) { *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 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; } }
c4ccb82000-07-04Martin Stjernholm  }
595dac2000-09-30Martin Stjernholm  md->val_types = val_types; md->ind_types = ind_types; gc_assert_checked_as_weak(md); } else { stealth_check_mapping_for_destruct(m); 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 } gc_assert_checked_as_nonweak(md); } } else stealth_check_mapping_for_destruct(m);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  } }
5267b71995-08-09Fredrik Hübinette (Hubbe) }
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
45d87e2000-07-18Martin Stjernholm void real_gc_cycle_check_mapping(struct mapping *m, int weak)
e2d9e62000-06-10Martin Stjernholm {
45d87e2000-07-18Martin Stjernholm  GC_CYCLE_ENTER(m, weak) {
5eca4d2000-09-04Martin Stjernholm  struct mapping_data *md = m->data;
e2d9e62000-06-10Martin Stjernholm #ifdef PIKE_DEBUG
5eca4d2000-09-04Martin Stjernholm  if(md->refs <=0)
45d87e2000-07-18Martin Stjernholm  fatal("Zero refs in mapping->data\n");
e2d9e62000-06-10Martin Stjernholm #endif
5eca4d2000-09-04Martin Stjernholm  if((md->ind_types | md->val_types) & BIT_COMPLEX)
45d87e2000-07-18Martin Stjernholm  { INT32 e; struct keypair *k;
e2d9e62000-06-10Martin Stjernholm 
5eca4d2000-09-04Martin Stjernholm  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("Didn't expect an svalue zapping now.\n"); #endif }
595dac2000-09-30Martin Stjernholm  gc_assert_checked_as_nonweak(md);
5eca4d2000-09-04Martin Stjernholm  }
595dac2000-09-30Martin Stjernholm  else if (md->flags & MAPPING_FLAG_WEAK) { /* We don't remove any entries in this case, since weak * internal references are kept intact. */
5eca4d2000-09-04Martin Stjernholm  NEW_MAPPING_LOOP(md)
595dac2000-09-30Martin Stjernholm  if (gc_cycle_check_weak_svalues(&k->ind, 1) | gc_cycle_check_weak_svalues(&k->val, 1)) {
c4ccb82000-07-04Martin Stjernholm #ifdef PIKE_DEBUG
5eca4d2000-09-04Martin Stjernholm  fatal("stealth_check_mapping_for_destruct didn't do its job properly.\n");
c4ccb82000-07-04Martin Stjernholm #endif
45d87e2000-07-18Martin Stjernholm  }
595dac2000-09-30Martin Stjernholm  gc_assert_checked_as_weak(md); } 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_assert_checked_as_nonweak(md); }
45d87e2000-07-18Martin Stjernholm  }
e2d9e62000-06-10Martin Stjernholm  } GC_CYCLE_LEAVE; }
20513c2000-04-12Fredrik Hübinette (Hubbe) static void gc_check_mapping(struct mapping *m)
515b6c1996-06-09Fredrik Hübinette (Hubbe) {
5eca4d2000-09-04Martin Stjernholm  struct mapping_data *md = m->data;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
5eca4d2000-09-04Martin Stjernholm  if((md->ind_types | md->val_types) & BIT_COMPLEX)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
5eca4d2000-09-04Martin Stjernholm  INT32 e; struct keypair *k;
e2d9e62000-06-10Martin Stjernholm 
5eca4d2000-09-04Martin Stjernholm  if(debug_gc_check(md, T_MAPPING, m)) return;
0816292000-07-03Martin Stjernholm 
5eca4d2000-09-04Martin Stjernholm  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) {
e2d9e62000-06-10Martin Stjernholm  debug_gc_check_weak_svalues(&k->ind, 1, T_MAPPING, m);
c4ccb82000-07-04Martin Stjernholm  debug_gc_check_weak_svalues(&k->val, 1, T_MAPPING, m);
e2d9e62000-06-10Martin Stjernholm  }
595dac2000-09-30Martin Stjernholm  gc_checked_as_weak(md);
e2d9e62000-06-10Martin Stjernholm  } else {
5eca4d2000-09-04Martin Stjernholm  NEW_MAPPING_LOOP(md)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
f6d0171997-10-15Fredrik Hübinette (Hubbe)  debug_gc_check_svalues(&k->ind, 1, T_MAPPING, m);
c4ccb82000-07-04Martin Stjernholm  debug_gc_check_svalues(&k->val, 1, T_MAPPING, m);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  }
e2d9e62000-06-10Martin Stjernholm  }
20513c2000-04-12Fredrik Hübinette (Hubbe)  } }
06983f1996-09-22Fredrik Hübinette (Hubbe) 
7bf6232000-04-23Martin Stjernholm #ifdef PIKE_DEBUG
e2d9e62000-06-10Martin Stjernholm unsigned gc_touch_all_mappings(void)
7bf6232000-04-23Martin Stjernholm {
e2d9e62000-06-10Martin Stjernholm  unsigned n = 0;
7bf6232000-04-23Martin Stjernholm  struct mapping *m;
e2d9e62000-06-10Martin Stjernholm  if (first_mapping && first_mapping->prev) fatal("Error in mapping link list.\n");
7bf6232000-04-23Martin Stjernholm  for (m = first_mapping; m; m = m->next) { debug_gc_touch(m);
5eca4d2000-09-04Martin Stjernholm  debug_gc_touch(m->data);
7bf6232000-04-23Martin Stjernholm  n++;
e2d9e62000-06-10Martin Stjernholm  if (m->next && m->next->prev != m) fatal("Error in mapping link list.\n");
7bf6232000-04-23Martin Stjernholm  } return n; } #endif
20513c2000-04-12Fredrik Hübinette (Hubbe) void gc_check_all_mappings(void) { struct mapping *m; for(m=first_mapping;m;m=m->next) { #ifdef DEBUG_MALLOC if (((int)m->data) == 0x55555555) { fprintf(stderr, "** Zapped mapping in list of active mappings!\n");
a4033e2000-04-14Fredrik Hübinette (Hubbe)  describe_something(m, T_MAPPING, 0,2,0);
20513c2000-04-12Fredrik Hübinette (Hubbe)  fatal("Zapped mapping in list of active mappings!\n"); } #endif /* DEBUG_MALLOC */ gc_check_mapping(m);
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
0816292000-07-03Martin Stjernholm  if(d_flag > 1) check_mapping_type_fields(m);
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe)  } }
be478c1997-08-30Henrik Grubbström (Grubba) void gc_mark_all_mappings(void)
515b6c1996-06-09Fredrik Hübinette (Hubbe) {
e2d9e62000-06-10Martin Stjernholm  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;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  if(gc_is_referenced(m)) gc_mark_mapping_as_referenced(m);
0816292000-07-03Martin Stjernholm  else /* Done in gc_mark_mapping_as_referenced() otherwise (and it has * to be done there). */
5eca4d2000-09-04Martin Stjernholm  stealth_check_mapping_for_destruct(m);
e2d9e62000-06-10Martin Stjernholm  } } void gc_cycle_check_all_mappings(void) { struct mapping *m; for (m = gc_internal_mapping; m; m = m->next) {
45d87e2000-07-18Martin Stjernholm  real_gc_cycle_check_mapping(m, 0); gc_cycle_run_queue();
e2d9e62000-06-10Martin Stjernholm  }
515b6c1996-06-09Fredrik Hübinette (Hubbe) }
45d87e2000-07-18Martin Stjernholm void gc_zap_ext_weak_refs_in_mappings(void) { gc_mark_mapping_pos = first_mapping; while (gc_mark_mapping_pos != gc_internal_mapping && gc_ext_weak_refs) { struct mapping *m = gc_mark_mapping_pos; gc_mark_mapping_pos = m->next; gc_mark_mapping_as_referenced(m); } discard_queue(&gc_mark_queue); }
be478c1997-08-30Henrik Grubbström (Grubba) void gc_free_all_unreferenced_mappings(void)
515b6c1996-06-09Fredrik Hübinette (Hubbe) { INT32 e;
3b589f1999-02-04Fredrik Hübinette (Hubbe)  struct keypair *k,**prev;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct mapping *m,*next;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct mapping_data *md;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
e2d9e62000-06-10Martin Stjernholm  for(m=gc_internal_mapping;m;m=next)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  { if(gc_do_free(m)) {
e2d9e62000-06-10Martin Stjernholm  /* Got an extra ref from gc_cycle_pop(). */
27bec92000-02-15Henrik Grubbström (Grubba)  md = m->data; /* Protect against unlink_mapping_data() recursing too far. */
1f342f2000-02-04Fredrik Hübinette (Hubbe)  m->data=&empty_data; m->data->refs++;
27bec92000-02-15Henrik Grubbström (Grubba)  unlink_mapping_data(md);
5eca4d2000-09-04Martin Stjernholm #ifdef MAPPING_SIZE_DEBUG
e945ee2000-02-09Fredrik Hübinette (Hubbe)  m->debug_size=0; #endif
e2d9e62000-06-10Martin Stjernholm  gc_free_extra_ref(m);
69ee4b2000-04-06Fredrik Hübinette (Hubbe)  SET_NEXT_AND_FREE(m, free_mapping);
3b589f1999-02-04Fredrik Hübinette (Hubbe)  } else {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  next=m->next; } } }
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
61e9a01998-01-25Fredrik Hübinette (Hubbe)  void simple_describe_mapping(struct mapping *m) { char *s; 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) {
5eca4d2000-09-04Martin Stjernholm  fprintf(stderr, "Refs=%d, next=%p, prev=%p", m->refs, m->next, m->prev);
f5757f2000-08-11Henrik Grubbström (Grubba)  if (((ptrdiff_t)m->data) & 3) {
18bc0c2000-03-08Henrik Grubbström (Grubba)  fprintf(stderr, ", data=%p (unaligned)\n", m->data); } else {
5eca4d2000-09-04Martin Stjernholm  fprintf(stderr, ", flags=0x%x, size=%d, hashsize=%d\n", m->data->flags, m->data->size, m->data->hashsize);
18bc0c2000-03-08Henrik Grubbström (Grubba)  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");
375bed2000-03-08Henrik Grubbström (Grubba)  simple_describe_mapping(m);
18bc0c2000-03-08Henrik Grubbström (Grubba)  }
61e9a01998-01-25Fredrik Hübinette (Hubbe) } #endif
be478c1997-08-30Henrik Grubbström (Grubba) void zap_all_mappings(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) { INT32 e;
06983f1996-09-22Fredrik Hübinette (Hubbe)  struct keypair *k;
c94c371996-03-28Fredrik Hübinette (Hubbe)  struct mapping *m,*next;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct mapping_data *md;
c94c371996-03-28Fredrik Hübinette (Hubbe)  for(m=first_mapping;m;m=next) {
d6ac731998-04-20Henrik Grubbström (Grubba)  add_ref(m);
c94c371996-03-28Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #if defined(PIKE_DEBUG) && defined(DEBUG_MALLOC)
61e9a01998-01-25Fredrik Hübinette (Hubbe)  if(verbose_debug_exit) debug_dump_mapping(m); #endif
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md=m->data; for(e=0;e<md->hashsize;e++)
06983f1996-09-22Fredrik Hübinette (Hubbe)  {
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  while((k=md->hash[e]))
06983f1996-09-22Fredrik Hübinette (Hubbe)  {
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md->hash[e]=k->next; k->next=md->free_list; md->free_list=k;
06983f1996-09-22Fredrik Hübinette (Hubbe)  free_svalue(&k->ind); free_svalue(&k->val); }
c94c371996-03-28Fredrik Hübinette (Hubbe)  }
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md->size=0;
5eca4d2000-09-04Martin Stjernholm #ifdef MAPPING_SIZE_DEBUG
10da6b2000-04-15Fredrik Hübinette (Hubbe)  if(m->data ==md) m->debug_size=0;
9e398c2000-02-08Fredrik Hübinette (Hubbe) #endif
06983f1996-09-22Fredrik Hübinette (Hubbe)  next=m->next;
cbd60b1996-12-04Fredrik Hübinette (Hubbe)  /* free_mapping(m); */
c94c371996-03-28Fredrik Hübinette (Hubbe)  }
c3c7031996-12-04Fredrik Hübinette (Hubbe) }