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"
54beb22000-02-01Fredrik Hübinette (Hubbe) RCSID("$Id: mapping.c,v 1.57 2000/02/01 23:51:47 hubbe 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 "language.h" #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"
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;
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #define MD_KEYPAIRS(MD, HSIZE) \ ( (struct keypair *)DO_ALIGN( (long) (((struct mapping_data *)(MD))->hash + HSIZE), ALIGNOF(struct keypair)) ) #define MAPPING_DATA_SIZE(HSIZE, KEYPAIRS) \ (long)( MD_KEYPAIRS(0, HSIZE) + KEYPAIRS ) #undef EXIT_BLOCK #define EXIT_BLOCK(m) \ INT32 e; \ DO_IF_DEBUG( \ if(m->refs) \ fatal("really free mapping on mapping with nonzero refs.\n"); \ ) \ \ FREE_PROT(m); \ \ free_mapping_data(m->data); \ \ if(m->prev) \ m->prev->next = m->next; \ else \ first_mapping = m->next; \ \ if(m->next) m->next->prev = m->prev; \ \ GC_FREE(); #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) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe) static struct mapping_data empty_data = { 1, 1, 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; INT32 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
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);
9076fa1997-02-17Fredrik Hübinette (Hubbe) 
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; 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;
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)  */
616b622000-01-31Fredrik Hübinette (Hubbe) struct mapping *debug_allocate_mapping(int size)
5267b71995-08-09Fredrik Hübinette (Hubbe) { struct mapping *m;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  GC_ALLOC();
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  m=alloc_mapping();
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
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->next = first_mapping; m->prev = 0; m->refs = 1;
a715b51999-10-30Martin Stjernholm  m->flags = 0;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(first_mapping) first_mapping->prev = m; first_mapping=m; return m; }
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  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);
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 */
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);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
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 if(!k) fatal("Error in rehash: not enough kehypairs.\n"); #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 if(!k) fatal("Error in rehash: not enough kehypairs.\n"); #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;
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;
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) 
54beb22000-02-01Fredrik Hübinette (Hubbe)  if(md->hardlinks) md->hardlinks--; free_mapping_data(md); }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); }
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  #ifdef PIKE_DEBUG if(m->data->size != tmp) fatal("Rehash failed, size not same any more.\n");
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) { long off,size,e; struct mapping_data *nmd; struct keypair *keypairs; 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; } #define LOW_FIND(FUN, KEY, FOUND, NOT_FOUND) do { \ md=m->data; \ add_ref(md); \ if(md->hashsize) \ { \ h=h2 % md->hashsize; \ 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; \ 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 { \ long off; \ 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 { \ long off; \ 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. */
515b6c1996-06-09Fredrik Hübinette (Hubbe) 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) }
06983f1996-09-22Fredrik Hübinette (Hubbe) /* This function inserts key:val into the mapping m. * Same as doing m[key]=val; in pike. */
59e53e2000-01-31Fredrik Hübinette (Hubbe) void low_mapping_insert(struct mapping *m, 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++;
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) }
59e53e2000-01-31Fredrik Hübinette (Hubbe) void mapping_insert(struct mapping *m, struct svalue *key, struct svalue *val) { low_mapping_insert(m,key,val,1); }
515b6c1996-06-09Fredrik Hübinette (Hubbe) union anything *mapping_get_item_ptr(struct mapping *m, 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++;
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) }
ea0be61999-11-11Fredrik Hübinette (Hubbe) void map_delete_no_free(struct mapping *m, 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--; 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) } void check_mapping_for_destruct(struct mapping *m) {
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)  { check_destructed(& k->val);
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)  {
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  PREPARE_FOR_INDEX_CHANGE2();
515b6c1996-06-09Fredrik Hübinette (Hubbe)  *prev=k->next; free_svalue(& k->ind); free_svalue(& k->val);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  k->next=md->free_list; md->free_list=k; md->size--;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  }else{ 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)  } } }
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) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md->val_types = val_types; md->ind_types = ind_types;
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)  } }
06983f1996-09-22Fredrik Hübinette (Hubbe) struct svalue *low_mapping_lookup(struct mapping *m, 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) }
14dae91997-01-26Fredrik Hübinette (Hubbe) struct svalue *low_mapping_string_lookup(struct mapping *m, struct pike_string *p) { struct svalue tmp; tmp.type=T_STRING; tmp.u.string=p; return low_mapping_lookup(m, &tmp); }
a28dd21998-04-23Fredrik Hübinette (Hubbe) void mapping_string_insert(struct mapping *m, struct pike_string *p, struct svalue *val) { struct svalue tmp; tmp.type=T_STRING; tmp.u.string=p; mapping_insert(m, &tmp, val); }
ea0be61999-11-11Fredrik Hübinette (Hubbe) void mapping_string_insert_string(struct mapping *m, 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); }
85f59e1998-01-08Fredrik Hübinette (Hubbe) struct svalue *simple_mapping_string_lookup(struct mapping *m, char *p) { struct pike_string *tmp; if((tmp=findstring(p))) return low_mapping_string_lookup(m,tmp); return 0; }
8a5d441999-10-19Fredrik Hübinette (Hubbe) struct svalue *mapping_mapping_lookup(struct mapping *m, 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); } struct svalue *mapping_mapping_string_lookup(struct mapping *m, 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); }
515b6c1996-06-09Fredrik Hübinette (Hubbe) void mapping_index_no_free(struct svalue *dest, 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) }
515b6c1996-06-09Fredrik Hübinette (Hubbe) 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 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; } struct array *mapping_values(struct mapping *m) { 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);
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; }
2043ba1998-02-10Fredrik Hübinette (Hubbe) struct array *mapping_to_array(struct mapping *m) { 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; }
515b6c1996-06-09Fredrik Hübinette (Hubbe) void mapping_replace(struct mapping *m,struct svalue *from, struct svalue *to) { 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) } struct mapping *mkmapping(struct array *ind, struct array *val) { 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
515b6c1996-06-09Fredrik Hübinette (Hubbe) struct mapping *copy_mapping(struct mapping *m) { 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! */ struct mapping *copy_mapping(struct mapping *m) { 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; 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)  struct mapping *merge_mappings(struct mapping *a, struct mapping *b, INT32 op) { 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) }
2ad6b72000-01-29Mirar (Pontus Hagland) struct mapping *merge_mapping_array_ordered(struct mapping *a, 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: fatal("merge_mapping_array on other then AND or SUB\n"); } free_array(ai); free_array(av); free((char *)zipper); m=mkmapping(ci, cv); free_array(ci); free_array(cv); return m; } struct mapping *merge_mapping_array_unordered(struct mapping *a, 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; }
515b6c1996-06-09Fredrik Hübinette (Hubbe) struct mapping *add_mappings(struct svalue *argp, INT32 args)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
5cd1511998-04-27Fredrik Hübinette (Hubbe)  INT32 e,d; struct mapping *ret; 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; } #if 1 /* Major optimization */ for(d=0;d<args;d++) if(e==argp[d].u.mapping->data->size) return copy_mapping(argp[d].u.mapping); #endif /* FIXME: need locking! */
5cd1511998-04-27Fredrik Hübinette (Hubbe)  ret=allocate_mapping(MAP_SLOTS(e)); for(d=0;d<args;d++)
0cde281998-05-14Fredrik Hübinette (Hubbe)  MAPPING_LOOP(argp[d].u.mapping)
5cd1511998-04-27Fredrik Hübinette (Hubbe)  mapping_insert(ret, &k->ind, &k->val); return ret;
5267b71995-08-09Fredrik Hübinette (Hubbe) } int mapping_equal_p(struct mapping *a, struct mapping *b, struct processing *p) {
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;
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;
5267b71995-08-09Fredrik Hübinette (Hubbe)  check_mapping_for_destruct(a); check_mapping_for_destruct(b);
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; } }
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  sprintf(buf, m->data->size == 1 ? "([ /* %ld element */\n" : "([ /* %ld elements */\n", (long)m->data->size);
5267b71995-08-09Fredrik Hübinette (Hubbe)  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); } } void f_m_delete(INT32 args) { if(args < 2) error("Too few arguments to m_delete.\n"); if(sp[-args].type != T_MAPPING)
fe3dd11997-09-08Henrik Grubbström (Grubba)  error("Bad argument 1 to m_delete.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe)  map_delete(sp[-args].u.mapping,sp+1-args); pop_n_elems(args-1); } void f_aggregate_mapping(INT32 args) { 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) } struct mapping *copy_mapping_recursively(struct mapping *m, struct processing *p) { 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; } }
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if((m->data->val_types | m->data->ind_types) & BIT_COMPLEX) return copy_mapping(m); ret=allocate_mapping(MAP_SLOTS(m->data->size));
3b589f1999-02-04Fredrik Hübinette (Hubbe)  ret->flags=m->flags;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  doing.pointer_b=ret;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
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);
765de02000-01-28Henrik Grubbström (Grubba)  MAPPING_LOOP(m) /* FIXME: Shouldn't NEW_MAPPING_LOOP() be used? */
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) 
5267b71995-08-09Fredrik Hübinette (Hubbe) void mapping_search_no_free(struct svalue *to, 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; } } 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; 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"); 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");
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) { INT32 e; 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
205a162000-01-28Fredrik Hübinette (Hubbe)  if(gc_mark(m) && gc_mark(m->data))
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if((m->data->ind_types | m->data->val_types) & BIT_COMPLEX)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
0cde281998-05-14Fredrik Hübinette (Hubbe)  MAPPING_LOOP(m)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
5d7d051996-09-25Fredrik Hübinette (Hubbe)  /* We do not want to count this key:index pair if * the index is a destructed object or function */ if(((1 << k->ind.type) & (BIT_OBJECT | BIT_FUNCTION)) && !(k->ind.u.object->prog)) continue;
1b0ac81999-10-29Martin Stjernholm  if (m->flags & MAPPING_FLAG_WEAK) { if (k->ind.type == T_OBJECT &&
ee9def1999-11-23Martin Stjernholm  k->ind.u.object->prog->flags & PROGRAM_NO_WEAK_FREE)
1b0ac81999-10-29Martin Stjernholm  gc_mark_svalues(&k->ind, 1); if (k->val.type == T_OBJECT && k->val.u.object->prog &&
ee9def1999-11-23Martin Stjernholm  k->val.u.object->prog->flags & PROGRAM_NO_WEAK_FREE)
1b0ac81999-10-29Martin Stjernholm  gc_mark_svalues(&k->val, 1); } else { gc_mark_svalues(&k->ind, 1); gc_mark_svalues(&k->val, 1); }
515b6c1996-06-09Fredrik Hübinette (Hubbe)  } } }
5267b71995-08-09Fredrik Hübinette (Hubbe) }
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
be478c1997-08-30Henrik Grubbström (Grubba) void gc_check_all_mappings(void)
515b6c1996-06-09Fredrik Hübinette (Hubbe) { INT32 e; struct keypair *k; struct mapping *m; for(m=first_mapping;m;m=m->next) {
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if((m->data->ind_types | m->data->val_types) & BIT_COMPLEX)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
205a162000-01-28Fredrik Hübinette (Hubbe)  if(gc_check(m->data)) continue;
0cde281998-05-14Fredrik Hübinette (Hubbe)  MAPPING_LOOP(m)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
5d7d051996-09-25Fredrik Hübinette (Hubbe)  /* We do not want to count this key:index pair if * the index is a destructed object or function */ if(((1 << k->ind.type) & (BIT_OBJECT | BIT_FUNCTION)) && !(k->ind.u.object->prog)) continue;
f6d0171997-10-15Fredrik Hübinette (Hubbe)  debug_gc_check_svalues(&k->ind, 1, T_MAPPING, m);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  m->data->val_types |= debug_gc_check_svalues(&k->val, 1, T_MAPPING, m);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  }
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);
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
06983f1996-09-22Fredrik Hübinette (Hubbe) 
515b6c1996-06-09Fredrik Hübinette (Hubbe)  } } }
be478c1997-08-30Henrik Grubbström (Grubba) void gc_mark_all_mappings(void)
515b6c1996-06-09Fredrik Hübinette (Hubbe) { struct mapping *m; for(m=first_mapping;m;m=m->next) if(gc_is_referenced(m)) gc_mark_mapping_as_referenced(m); }
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)  for(m=first_mapping;m;m=next) {
5d7d051996-09-25Fredrik Hübinette (Hubbe)  check_mapping_for_destruct(m);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  if(gc_do_free(m)) {
d6ac731998-04-20Henrik Grubbström (Grubba)  add_ref(m);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md=m->data; /* no locking required * * FIXME: is it possible that md->refs might not be zero here? * for now I will assume it is not possible... */ for(e=0;e<md->hashsize;e++)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  k=md->hash[e];
06983f1996-09-22Fredrik Hübinette (Hubbe)  while(k)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  { free_svalue(&k->ind); free_svalue(&k->val);
06983f1996-09-22Fredrik Hübinette (Hubbe)  if(k->next) { k = k->next; } else {
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  k->next=md->free_list; md->free_list=md->hash[e]; md->hash[e]=0;
06983f1996-09-22Fredrik Hübinette (Hubbe)  break; }
515b6c1996-06-09Fredrik Hübinette (Hubbe)  } }
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md->size=0;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  next=m->next; free_mapping(m);
3b589f1999-02-04Fredrik Hübinette (Hubbe)  } else if(m->flags & MAPPING_FLAG_WEAK) { add_ref(m);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md=m->data; /* no locking required (no is_eq) */ for(e=0;e<md->hashsize;e++)
3b589f1999-02-04Fredrik Hübinette (Hubbe)  {
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  for(prev= md->hash + e;(k=*prev);)
3b589f1999-02-04Fredrik Hübinette (Hubbe)  {
1b0ac81999-10-29Martin Stjernholm  if((k->val.type <= MAX_COMPLEX &&
a715b51999-10-30Martin Stjernholm  !(k->val.type == T_OBJECT &&
ee9def1999-11-23Martin Stjernholm  k->val.u.object->prog->flags & PROGRAM_NO_WEAK_FREE) &&
1b0ac81999-10-29Martin Stjernholm  gc_do_free(k->val.u.refs)) || (k->ind.type <= MAX_COMPLEX &&
a715b51999-10-30Martin Stjernholm  !(k->ind.type == T_OBJECT &&
ee9def1999-11-23Martin Stjernholm  k->ind.u.object->prog->flags & PROGRAM_NO_WEAK_FREE) &&
1b0ac81999-10-29Martin Stjernholm  gc_do_free(k->ind.u.refs)))
3b589f1999-02-04Fredrik Hübinette (Hubbe)  {
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  PREPARE_FOR_INDEX_CHANGE();
3b589f1999-02-04Fredrik Hübinette (Hubbe)  *prev=k->next; free_svalue(& k->ind); free_svalue(& k->val);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  k->next=md->free_list; md->free_list=k; md->size--;
3b589f1999-02-04Fredrik Hübinette (Hubbe)  }else{ prev=&k->next; } } }
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)  }
3b589f1999-02-04Fredrik Hübinette (Hubbe)  next=m->next; free_mapping(m); } 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) { fprintf(stderr,"Refs=%d, next=%p, prev=%p, size=%d, hashsize=%d\n", m->refs, m->next, m->prev,
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  m->data->size, m->data->hashsize);
61e9a01998-01-25Fredrik Hübinette (Hubbe)  fprintf(stderr,"Indices type field = ");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  debug_dump_type_field(m->data->ind_types);
61e9a01998-01-25Fredrik Hübinette (Hubbe)  fprintf(stderr,"\n"); fprintf(stderr,"Values type field = ");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  debug_dump_type_field(m->data->val_types);
61e9a01998-01-25Fredrik Hübinette (Hubbe)  fprintf(stderr,"\n"); simple_describe_mapping(m); } #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;
06983f1996-09-22Fredrik Hübinette (Hubbe)  next=m->next;
cbd60b1996-12-04Fredrik Hübinette (Hubbe)  /* free_mapping(m); */
c94c371996-03-28Fredrik Hübinette (Hubbe)  }
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  free_all_mapping_blocks();
c3c7031996-12-04Fredrik Hübinette (Hubbe) }