e576bb2002-10-11Martin Nilsson /* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information.
a1b3872003-01-11Martin Stjernholm || $Id: mapping.c,v 1.161 2003/01/11 03:06:54 mast Exp $
e576bb2002-10-11Martin Nilsson */
aedfb12002-10-09Martin Nilsson 
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "global.h"
a1b3872003-01-11Martin Stjernholm RCSID("$Id: mapping.c,v 1.161 2003/01/11 03:06:54 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"
b2d3e42000-12-01Fredrik Hübinette (Hubbe) #include "pike_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"
447e9b2001-09-06Fredrik Hübinette (Hubbe) #include "stuff.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 MAPPING_DATA_SIZE(HSIZE, KEYPAIRS) \
2b46992003-01-10Henrik Grubbström (Grubba)  (((char *)(MD_KEYPAIRS(0, HSIZE) + KEYPAIRS))-(char *)0)
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  #undef EXIT_BLOCK
aad99b2001-03-28Fredrik Hübinette (Hubbe) #define EXIT_BLOCK(m) do{ \
62aab62000-02-04Fredrik Hübinette (Hubbe) DO_IF_DEBUG( \
d631b82002-12-01Martin Stjernholm  if(m->refs) { \ DO_IF_DMALLOC(describe_something(m, T_MAPPING, 0,2,0, NULL)); \ Pike_fatal("really free mapping on mapping with %d refs.\n", m->refs); \ } \
57a4ab2000-01-27Fredrik Hübinette (Hubbe) ) \ \ FREE_PROT(m); \ \
1f342f2000-02-04Fredrik Hübinette (Hubbe)  unlink_mapping_data(m->data); \
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  \
e2d9e62000-06-10Martin Stjernholm  DOUBLEUNLINK(first_mapping, m); \
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  \
aad99b2001-03-28Fredrik Hübinette (Hubbe)  GC_FREE(m); \ }while(0)
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  #undef COUNT_OTHER #define COUNT_OTHER() do{ \ struct mapping *m; \
69e2282001-11-25Martin Stjernholm  double datasize = 0.0; \
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  for(m=first_mapping;m;m=m->next) \ { \
69e2282001-11-25Martin Stjernholm  datasize+=MAPPING_DATA_SIZE(m->data->hashsize, m->data->num_keypairs) / \ (double) m->data->refs; \
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  } \
69e2282001-11-25Martin Stjernholm  size += (INT32) datasize; \
57a4ab2000-01-27Fredrik Hübinette (Hubbe) }while(0)
3aab372002-11-24Martin Stjernholm BLOCK_ALLOC_FILL_PAGES(mapping, 2)
57a4ab2000-01-27Fredrik Hübinette (Hubbe) 
df9b622001-05-27Henrik Grubbström (Grubba) #ifndef PIKE_MAPPING_KEYPAIR_LOOP #define FREE_KEYPAIR(md, k) do { \ k->next = md->free_list; \ md->free_list = k; \ } while(0) #else /* PIKE_MAPPING_KEYPAIR_LOOP */ #define FREE_KEYPAIR(md, k) do { \ md->free_list--; \ if (k != md->free_list) { \ struct keypair **prev_; \ unsigned INT32 h_; \ /* Move the last keypair to the new hole. */ \ *k = *(md->free_list); \ h_ = k->hval % md->hashsize; \ prev_ = md->hash + h_; \ DO_IF_DEBUG( \ if (!*prev_) { \
5aad932002-08-15Marcus Comstedt  Pike_fatal("Node to move not found!\n"); \
df9b622001-05-27Henrik Grubbström (Grubba)  } \ ); \ while (*prev_ != md->free_list) { \ prev_ = &((*prev_)->next); \ DO_IF_DEBUG( \ if (!*prev_) { \
5aad932002-08-15Marcus Comstedt  Pike_fatal("Node to move not found!\n"); \
df9b622001-05-27Henrik Grubbström (Grubba)  } \ ); \ } \ *prev_ = k; \ } \ } while(0) #endif /* !PIKE_MAPPING_KEYPAIR_LOOP */
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))
5aad932002-08-15Marcus Comstedt  Pike_fatal("Mapping value types out of order!\n");
06983f1996-09-22Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(ind_types & ~(m->data->ind_types))
5aad932002-08-15Marcus Comstedt  Pike_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) 
f4d7572001-04-15Martin Stjernholm static struct mapping_data empty_data =
2fbeae2001-07-01Martin Stjernholm  { PIKE_CONSTANT_MEMOBJ_INIT(1), 1, 0,0,0,0,0,0, 0, 0,{0}};
0b5d2b2001-06-05Martin Stjernholm static struct mapping_data weak_ind_empty_data =
2fbeae2001-07-01Martin Stjernholm  { PIKE_CONSTANT_MEMOBJ_INIT(1), 1, 0,0,0,0,0,0, MAPPING_WEAK_INDICES, 0,{0}};
0b5d2b2001-06-05Martin Stjernholm static struct mapping_data weak_val_empty_data =
2fbeae2001-07-01Martin Stjernholm  { PIKE_CONSTANT_MEMOBJ_INIT(1), 1, 0,0,0,0,0,0, MAPPING_WEAK_VALUES, 0,{0}};
0b5d2b2001-06-05Martin Stjernholm static struct mapping_data weak_both_empty_data =
2fbeae2001-07-01Martin Stjernholm  { PIKE_CONSTANT_MEMOBJ_INIT(1), 1, 0,0,0,0,0,0, MAPPING_WEAK, 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)  */
c0e91b2001-01-25Fredrik Hübinette (Hubbe) static void init_mapping(struct mapping *m, INT32 size, INT16 flags)
515b6c1996-06-09Fredrik Hübinette (Hubbe) {
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct mapping_data *md;
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)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Can't allocate a new mapping_data inside gc.\n"); if(size < 0) Pike_fatal("init_mapping with negative value.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
9076fa1997-02-17Fredrik Hübinette (Hubbe)  if(size) {
851b962001-08-31Fredrik Hübinette (Hubbe)  hashsize=find_good_hash_size(size / AVG_LINK_LENGTH + 1);
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);
df9b622001-05-27Henrik Grubbström (Grubba) #ifndef PIKE_MAPPING_KEYPAIR_LOOP
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;
df9b622001-05-27Henrik Grubbström (Grubba) #endif /* !PIKE_MAPPING_KEYPAIR_LOOP */
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md->ind_types = 0; md->val_types = 0;
c0e91b2001-01-25Fredrik Hübinette (Hubbe)  md->flags = flags;
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{
0b5d2b2001-06-05Martin Stjernholm  switch (flags & MAPPING_WEAK) { case 0: md = &empty_data; break; case MAPPING_WEAK_INDICES: md = &weak_ind_empty_data; break; case MAPPING_WEAK_VALUES: md = &weak_val_empty_data; break; default: md = &weak_both_empty_data; break;
c0e91b2001-01-25Fredrik Hübinette (Hubbe)  }
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) }
7964ef2002-10-27Martin Nilsson /* This function allocates an empty mapping with initial 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);
c0e91b2001-01-25Fredrik Hübinette (Hubbe)  init_mapping(m,size,0);
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
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) {
5aad932002-08-15Marcus Comstedt  Pike_fatal("really_free_mapping_data(): md has non-zero refs: %d\n",
765de02000-01-28Henrik Grubbström (Grubba)  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;
54beb22000-02-01Fredrik Hübinette (Hubbe)  struct keypair *k; if(!from) return; mapping_rehash_backwards_evil(md,from->next); /* unlink */ k=md->free_list;
df9b622001-05-27Henrik Grubbström (Grubba) #ifndef PIKE_MAPPING_KEYPAIR_LOOP
54beb22000-02-01Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
5aad932002-08-15Marcus Comstedt  if(!k) Pike_fatal("Error in rehash: not enough keypairs.\n");
54beb22000-02-01Fredrik Hübinette (Hubbe) #endif md->free_list=k->next;
df9b622001-05-27Henrik Grubbström (Grubba) #else /* PIKE_MAPPING_KEYPAIR_LOOP */ md->free_list++; #endif /* !PIKE_MAPPING_KEYPAIR_LOOP */
54beb22000-02-01Fredrik Hübinette (Hubbe)  /* 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 *k; if(!from) return; mapping_rehash_backwards_good(md,from->next); /* unlink */ k=md->free_list;
df9b622001-05-27Henrik Grubbström (Grubba) #ifndef PIKE_MAPPING_KEYPAIR_LOOP
54beb22000-02-01Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
5aad932002-08-15Marcus Comstedt  if(!k) Pike_fatal("Error in rehash: not enough keypairs.\n");
54beb22000-02-01Fredrik Hübinette (Hubbe) #endif md->free_list=k->next;
df9b622001-05-27Henrik Grubbström (Grubba) #else /* PIKE_MAPPING_KEYPAIR_LOOP */ md->free_list++; #endif /* !PIKE_MAPPING_KEYPAIR_LOOP */
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)
5aad932002-08-15Marcus Comstedt  Pike_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) 
c0e91b2001-01-25Fredrik Hübinette (Hubbe)  init_mapping(m, new_size, md->flags);
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) 
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)
5aad932002-08-15Marcus Comstedt  Pike_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)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Can't allocate a new mapping_data inside gc.\n");
5eca4d2000-09-04Martin Stjernholm #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);
df9b622001-05-27Henrik Grubbström (Grubba) #ifndef PIKE_MAPPING_KEYPAIR_LOOP
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  for(e=0;e<nmd->num_keypairs;e++) { RELOC(keypairs[e].next); add_ref_svalue(& keypairs[e].ind); add_ref_svalue(& keypairs[e].val); }
df9b622001-05-27Henrik Grubbström (Grubba) #else /* PIKE_MAPPING_KEYPAIR_LOOP */ for(e=0;e<nmd->size;e++) { RELOC(keypairs[e].next); add_ref_svalue(& keypairs[e].ind); add_ref_svalue(& keypairs[e].val); } #endif /* PIKE_MAPPING_KEYPAIR_LOOP */
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  nmd->refs=1; nmd->valrefs=0; nmd->hardlinks=0; if(md->hardlinks) { #ifdef PIKE_DEBUG if(md->refs <= 0 || md->valrefs<=0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Hardlink without refs/valrefs!\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #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)) \ { \
9e6d452001-09-04Fredrik Hübinette (Hubbe)  k2=omd->hash[h2 % omd->hashsize]; \
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  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))
5aad932002-08-15Marcus Comstedt  Pike_fatal("Mapping value types out of order!\n");
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(ind_types & ~(m->data->ind_types))
5aad932002-08-15Marcus Comstedt  Pike_fatal("Mapping indices types out of order!\n");
515b6c1996-06-09Fredrik Hübinette (Hubbe) #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(); }
c0e91b2001-01-25Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
0b5d2b2001-06-05Martin Stjernholm  if(flags & MAPPING_WEAK)
c0e91b2001-01-25Fredrik Hübinette (Hubbe)  { debug_malloc_touch(m); debug_malloc_touch(md); } else { debug_malloc_touch(m); debug_malloc_touch(md); } #endif
5eca4d2000-09-04Martin Stjernholm  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)
5aad932002-08-15Marcus Comstedt  Pike_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)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Wrong dataset in mapping_insert!\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  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)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Wrong dataset in mapping_insert!\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(d_flag>1) check_mapping(m); #endif free_mapping_data(md); /* We do a re-hash here instead of copying the mapping. */
df9b622001-05-27Henrik Grubbström (Grubba)  if( #ifndef PIKE_MAPPING_KEYPAIR_LOOP (!md->free_list) || #else /* PIKE_MAPPING_KEYPAIR_LOOP */ (md->size >= md->num_keypairs) || #endif /* !PIKE_MAPPING_KEYPAIR_LOOP */ 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;
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;
df9b622001-05-27Henrik Grubbström (Grubba) #ifndef PIKE_MAPPING_KEYPAIR_LOOP
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md->free_list=k->next;
df9b622001-05-27Henrik Grubbström (Grubba) #else /* PIKE_MAPPING_KEYPAIR_LOOP */ md->free_list++; #endif /* !PIKE_MAPPING_KEYPAIR_LOOP */
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  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)
5aad932002-08-15Marcus Comstedt  Pike_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)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Wrong dataset in mapping_get_item_ptr!\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  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)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Wrong dataset in mapping_get_item_ptr!\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  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 */
df9b622001-05-27Henrik Grubbström (Grubba)  if( #ifndef PIKE_MAPPING_KEYPAIR_LOOP !(md->free_list) || #else /* PIKE_MAPPING_KEYPAIR_LOOP */ (md->size >= md->num_keypairs) || #endif /* !PIKE_MAPPING_KEYPAIR_LOOP */ 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;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  }
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  h=h2 % md->hashsize;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
df9b622001-05-27Henrik Grubbström (Grubba)  k=md->free_list; #ifndef PIKE_MAPPING_KEYPAIR_LOOP
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  md->free_list=k->next;
df9b622001-05-27Henrik Grubbström (Grubba) #else /* PIKE_MAPPING_KEYPAIR_LOOP */ md->free_list++; #endif /* !PIKE_MAPPING_KEYPAIR_LOOP */
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  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)
5aad932002-08-15Marcus Comstedt  Pike_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)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Too few refs i mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(m->data != md)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Wrong dataset in mapping_delete!\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  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);
df9b622001-05-27Henrik Grubbström (Grubba)  FREE_KEYPAIR(md, k); md->free_list->ind.type=T_INT; md->free_list->val.type=T_INT;
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
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) }
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)
5aad932002-08-15Marcus Comstedt  Pike_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);
853b832000-12-14Martin Stjernholm  if (Pike_in_gc > GC_PASS_PREPARE && Pike_in_gc < GC_PASS_FREE)
5aad932002-08-15Marcus Comstedt  Pike_fatal("check_mapping_for_destruct called in invalid pass inside gc.\n");
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)  {
853b832000-12-14Martin Stjernholm  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)  {
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();
853b832000-12-14Martin Stjernholm  *prev=k->next; free_svalue(& k->ind); free_svalue(& k->val);
df9b622001-05-27Henrik Grubbström (Grubba)  FREE_KEYPAIR(md, k); md->free_list->ind.type = T_INT; md->free_list->val.type = T_INT;
853b832000-12-14Martin Stjernholm  md->size--;
5eca4d2000-09-04Martin Stjernholm #ifdef MAPPING_SIZE_DEBUG
853b832000-12-14Martin Stjernholm  if(m->data ==md) { m->debug_size++; debug_malloc_touch(m); }
9e398c2000-02-08Fredrik Hübinette (Hubbe) #endif
853b832000-12-14Martin Stjernholm  debug_malloc_touch(md);
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)  } } }
5eca4d2000-09-04Martin Stjernholm 
cfa62c2001-11-12Martin Stjernholm  md->val_types = val_types; md->ind_types = ind_types;
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)  } }
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)
5aad932002-08-15Marcus Comstedt  Pike_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)
5aad932002-08-15Marcus Comstedt  Pike_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)
5aad932002-08-15Marcus Comstedt  Pike_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)
5aad932002-08-15Marcus Comstedt  Pike_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)
5aad932002-08-15Marcus Comstedt  Pike_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)
5aad932002-08-15Marcus Comstedt  Pike_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)
5aad932002-08-15Marcus Comstedt  Pike_fatal("mkmapping on different sized arrays.\n");
515b6c1996-06-09Fredrik Hübinette (Hubbe) #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)
5aad932002-08-15Marcus Comstedt  Pike_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) {
a5cd6a2001-09-24Henrik Grubbström (Grubba)  ONERROR r1,r2,r3,r4;
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)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(b->data->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe)  ai=mapping_indices(a);
49398c2000-11-08Fredrik Hübinette (Hubbe)  SET_ONERROR(r1,do_free_array,ai);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  av=mapping_values(a);
49398c2000-11-08Fredrik Hübinette (Hubbe)  SET_ONERROR(r2,do_free_array,av);
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);
49398c2000-11-08Fredrik Hübinette (Hubbe)  SET_ONERROR(r3,do_free_array,bi);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  bv=mapping_values(b);
49398c2000-11-08Fredrik Hübinette (Hubbe)  SET_ONERROR(r4,do_free_array,bv);
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);
49398c2000-11-08Fredrik Hübinette (Hubbe)  UNSET_ONERROR(r4); free_array(bi); UNSET_ONERROR(r3); free_array(ai);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
515b6c1996-06-09Fredrik Hübinette (Hubbe)  cv=array_zip(av,bv,zipper);
49398c2000-11-08Fredrik Hübinette (Hubbe)  UNSET_ONERROR(r2); free_array(bv); UNSET_ONERROR(r1); free_array(av);
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) {
49398c2000-11-08Fredrik Hübinette (Hubbe)  ONERROR r1,r2;
2ad6b72000-01-29Mirar (Pontus Hagland)  struct array *ai, *av;
37b8782000-11-02Henrik Grubbström (Grubba)  struct array *ci = NULL, *cv = NULL; INT32 *zipper = NULL;
2ad6b72000-01-29Mirar (Pontus Hagland)  struct mapping *m; ai=mapping_indices(a);
49398c2000-11-08Fredrik Hübinette (Hubbe)  SET_ONERROR(r1,do_free_array,ai);
2ad6b72000-01-29Mirar (Pontus Hagland)  av=mapping_values(a);
49398c2000-11-08Fredrik Hübinette (Hubbe)  SET_ONERROR(r2,do_free_array,av);
2ad6b72000-01-29Mirar (Pontus Hagland)  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:
5aad932002-08-15Marcus Comstedt  Pike_fatal("merge_mapping_array on other than AND or SUB\n");
2ad6b72000-01-29Mirar (Pontus Hagland)  }
49398c2000-11-08Fredrik Hübinette (Hubbe)  UNSET_ONERROR(r2); free_array(av); UNSET_ONERROR(r1); free_array(ai);
2ad6b72000-01-29Mirar (Pontus Hagland)  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) {
49398c2000-11-08Fredrik Hübinette (Hubbe)  ONERROR r1;
2ad6b72000-01-29Mirar (Pontus Hagland)  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);
49398c2000-11-08Fredrik Hübinette (Hubbe)  SET_ONERROR(r1,do_free_array,b_temp);
2ad6b72000-01-29Mirar (Pontus Hagland)  m=merge_mapping_array_ordered(a,b_temp,op);
49398c2000-11-08Fredrik Hübinette (Hubbe)  UNSET_ONERROR(r1); free_array(b_temp);
2ad6b72000-01-29Mirar (Pontus Hagland)  } 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;
0b5d2b2001-06-05Martin Stjernholm  if(!(md->flags & MAPPING_WEAK))
59791f2000-09-08Fredrik Hübinette (Hubbe)  {
c193a62000-09-07Fredrik Hübinette (Hubbe) #if 1 /* major optimization */
ab59f42001-11-25Martin Stjernholm  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)
5aad932002-08-15Marcus Comstedt  Pike_fatal("add_mappings is confused!\n");
59791f2000-09-08Fredrik Hübinette (Hubbe) #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)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(b->data->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_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{
4112122001-09-04Fredrik Hübinette (Hubbe)  INT32 d; struct mapping_data *bmd = b->data; struct keypair *kp; /* This is neither pretty nor fast, but it should * perform a bit more like expected... -Hubbe */ bmd->valrefs++; add_ref(bmd);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  eq=0;
4112122001-09-04Fredrik Hübinette (Hubbe)  for(d=0;d<(bmd)->hashsize;d++) { for(kp=bmd->hash[d];kp;kp=kp->next) { if(low_is_equal(&k->ind, &kp->ind, &curr) && low_is_equal(&k->val, &kp->val, &curr)) { eq=1; break; } } } bmd->valrefs--; free_mapping_data(bmd); if(!eq) 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;
5267b71995-08-09Fredrik Hübinette (Hubbe)  char buf[40];
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(m->data->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_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) 
5f45a72001-12-16Martin Stjernholm  if (Pike_in_gc) { /* Have to do without any temporary allocations. */ struct keypair *k; int notfirst = 0; if (m->data->size == 1) { my_strcat("([ /* 1 element */\n"); } else { sprintf(buf, "([ /* %ld elements */\n", (long)m->data->size); my_strcat(buf); } NEW_MAPPING_LOOP(m->data) { if (notfirst) my_strcat(",\n"); else notfirst = 1; for(d = 0; d < indent; d++) my_putchar(' ');
7056b22002-11-28Martin Stjernholm #if 0 /* describe_svalue might do anything. */
5f45a72001-12-16Martin Stjernholm  describe_svalue(&k->ind, indent+2, &doing); my_putchar(':'); describe_svalue(&k->val, indent+2, &doing);
7056b22002-11-28Martin Stjernholm #else sprintf (buf, "<%d>", k->ind.type); my_strcat (buf); my_putchar(':'); sprintf (buf, "<%d>", k->val.type); my_strcat (buf); #endif
5f45a72001-12-16Martin Stjernholm  } my_putchar('\n'); for(e=2; e<indent; e++) my_putchar(' '); my_strcat("])"); return; }
674fae2000-01-14Fredrik Noring  a = mapping_indices(m); SET_ONERROR(err, do_free_array, a);
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
853b832000-12-14Martin Stjernholm  if(! m->data->size) { /* mapping_indices may remove elements */ my_strcat("([ ])"); } else {
97ebb32003-01-09Henrik Grubbström (Grubba)  int save_t_flag = Pike_interpreter.trace_level;
f7b1eb2001-02-08Martin Stjernholm 
853b832000-12-14Martin Stjernholm  if (m->data->size == 1) { my_strcat("([ /* 1 element */\n"); } else { sprintf(buf, "([ /* %ld elements */\n", (long)m->data->size); my_strcat(buf); }
57a4ab2000-01-27Fredrik Hübinette (Hubbe) 
97ebb32003-01-09Henrik Grubbström (Grubba)  Pike_interpreter.trace_level = 0;
c1b8f02001-07-02Martin Stjernholm  if(SETJMP(catch)) { free_svalue(&throw_value); throw_value.type = T_INT; } else
853b832000-12-14Martin Stjernholm  sort_array_destructively(a); UNSETJMP(catch);
97ebb32003-01-09Henrik Grubbström (Grubba)  Pike_interpreter.trace_level = save_t_flag;
853b832000-12-14Martin Stjernholm  for(e = 0; e < a->size; e++) { struct svalue *tmp; if(e) my_strcat(",\n");
674fae2000-01-14Fredrik Noring 
853b832000-12-14Martin Stjernholm  for(d = 0; d < indent; d++) my_putchar(' ');
674fae2000-01-14Fredrik Noring 
853b832000-12-14Martin Stjernholm  describe_svalue(ITEM(a)+e, indent+2, &doing); my_putchar(':');
ab1b1e2001-01-17Fredrik Hübinette (Hubbe)  {
97ebb32003-01-09Henrik Grubbström (Grubba)  int save_t_flag=Pike_interpreter.trace_level; Pike_interpreter.trace_level=0;
ab1b1e2001-01-17Fredrik Hübinette (Hubbe)  tmp=low_mapping_lookup(m, ITEM(a)+e);
97ebb32003-01-09Henrik Grubbström (Grubba)  Pike_interpreter.trace_level=save_t_flag;
ab1b1e2001-01-17Fredrik Hübinette (Hubbe)  } if(tmp)
853b832000-12-14Martin Stjernholm  describe_svalue(tmp, indent+2, &doing); else my_strcat("** gone **"); } my_putchar('\n'); for(e=2; e<indent; e++) my_putchar(' '); my_strcat("])");
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) }
765de02000-01-28Henrik Grubbström (Grubba) node *make_node_from_mapping(struct mapping *m)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(m->data->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_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);
84387d2001-09-24Fredrik Hübinette (Hubbe)  if(!mapping_is_constant(m,0))
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); } }
ce4d672001-01-31Henrik Grubbström (Grubba) /*! @decl mapping aggregate_mapping(mixed ... elems) *! *! Construct a mapping. *! *! Groups the arguments together two and two in key-index pairs and
c9e8202001-04-14Johan Sundström  *! creates a mapping of those pairs. Generally, the mapping literal *! syntax is handier: @code{([ key1:val1, key2:val2, ... ])@}
ce4d672001-01-31Henrik Grubbström (Grubba)  *! *! @seealso *! @[sizeof()], @[mappingp()], @[mkmapping()] */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void f_aggregate_mapping(INT32 args)
5267b71995-08-09Fredrik Hübinette (Hubbe) { INT32 e; struct mapping *m; if(args & 1)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_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) 
9b150a2002-05-11Martin Nilsson  for(e=-args;e<0;e+=2) mapping_insert(m, Pike_sp+e, Pike_sp+e+1);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  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)
5aad932002-08-15Marcus Comstedt  Pike_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)  {
9b150a2002-05-11Martin Nilsson  copy_svalues_recursively_no_free(Pike_sp,&k->ind, 1, &doing); Pike_sp++; copy_svalues_recursively_no_free(Pike_sp,&k->val, 1, &doing); Pike_sp++;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
9b150a2002-05-11Martin Nilsson  mapping_insert(ret, Pike_sp-2, Pike_sp-1);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  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)
5aad932002-08-15Marcus Comstedt  Pike_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)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Mapping has zero refs.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(!m->data)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Mapping has no data block.\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) 
765de02000-01-28Henrik Grubbström (Grubba)  if (!m->data->refs)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Mapping data block has zero refs.\n");
765de02000-01-28Henrik Grubbström (Grubba) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(m->next && m->next->prev != m)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Mapping ->next->prev != mapping.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe) 
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);
5aad932002-08-15Marcus Comstedt  Pike_fatal("Mapping zapping detected (%d != %d)!\n",m->debug_size,md->size);
a4033e2000-04-14Fredrik Hübinette (Hubbe)  }
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)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Mapping ->prev->next != mapping.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe)  }else{ if(first_mapping != m)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Mapping ->prev == 0 but first_mapping != mapping.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->valrefs <0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("md->valrefs < 0\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->hardlinks <0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("md->valrefs < 0\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->refs < md->valrefs+1)
5aad932002-08-15Marcus Comstedt  Pike_fatal("md->refs < md->valrefs+1\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->valrefs < md->hardlinks)
5aad932002-08-15Marcus Comstedt  Pike_fatal("md->refs < md->valrefs+1\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->hashsize < 0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Assert: I don't think he's going to make it Jim.\n");
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->size < 0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Core breach, evacuate ship!\n");
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->num_keypairs < 0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Starboard necell on fire!\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->size > md->num_keypairs)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Pretty mean hashtable there buster!\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->hashsize > md->num_keypairs)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Pretty mean hashtable there buster %d > %d (2)!\n",md->hashsize,md->num_keypairs);
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(md->num_keypairs > (md->hashsize + 3) * AVG_LINK_LENGTH)
5aad932002-08-15Marcus Comstedt  Pike_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))
5aad932002-08-15Marcus Comstedt  Pike_fatal("Mapping type fields are... wrong.\n");
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
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) ))
5aad932002-08-15Marcus Comstedt  Pike_fatal("Mapping indices type field lies.\n");
e2d5221998-05-16Fredrik Hübinette (Hubbe) 
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  if(! ( (1 << k->val.type) & (md->val_types) ))
5aad932002-08-15Marcus Comstedt  Pike_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)
5aad932002-08-15Marcus Comstedt  Pike_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) 
853b832000-12-14Martin Stjernholm #ifdef MAPPING_SIZE_DEBUG #define DO_IF_MAPPING_SIZE_DEBUG(x) x #else #define DO_IF_MAPPING_SIZE_DEBUG(x) #endif
c1089d2001-12-02Martin Stjernholm #define GC_RECURSE_MD_IN_USE(MD, RECURSE_FN, IND_TYPES, VAL_TYPES) do { \
853b832000-12-14Martin Stjernholm  INT32 e; \ struct keypair *k; \
c1089d2001-12-02Martin Stjernholm  IND_TYPES = MD->ind_types; \ NEW_MAPPING_LOOP(MD) { \ if (!IS_DESTRUCTED(&k->ind) && RECURSE_FN(&k->ind, 1)) { \
5aad932002-08-15Marcus Comstedt  DO_IF_DEBUG(Pike_fatal("Didn't expect an svalue zapping now.\n")); \
853b832000-12-14Martin Stjernholm  } \
c1089d2001-12-02Martin Stjernholm  RECURSE_FN(&k->val, 1); \ VAL_TYPES |= 1 << k->val.type; \
853b832000-12-14Martin Stjernholm  } \ } while (0)
0b5d2b2001-06-05Martin Stjernholm #define GC_RECURSE(MD, REC_KEYPAIR, TYPE, IND_TYPES, VAL_TYPES) do { \
853b832000-12-14Martin Stjernholm  INT32 e; \
0b5d2b2001-06-05Martin Stjernholm  int remove; \
853b832000-12-14Martin Stjernholm  struct keypair *k,**prev; \ /* no locking required (no is_eq) */ \
0b5d2b2001-06-05Martin Stjernholm  for(e=0;e<MD->hashsize;e++) \
853b832000-12-14Martin Stjernholm  { \
0b5d2b2001-06-05Martin Stjernholm  for(prev= MD->hash + e;(k=*prev);) \
853b832000-12-14Martin Stjernholm  { \
0b5d2b2001-06-05Martin Stjernholm  REC_KEYPAIR(remove, \ PIKE_CONCAT(TYPE, _svalues), \ PIKE_CONCAT(TYPE, _weak_svalues), \ PIKE_CONCAT(TYPE, _without_recurse), \ PIKE_CONCAT(TYPE, _weak_without_recurse)); \ if (remove) \
853b832000-12-14Martin Stjernholm  { \ *prev=k->next; \
0b5d2b2001-06-05Martin Stjernholm  FREE_KEYPAIR(MD, k); \ MD->free_list->ind.type = T_INT; \ MD->free_list->val.type = T_INT; \ MD->size--; \
853b832000-12-14Martin Stjernholm  DO_IF_MAPPING_SIZE_DEBUG( \
0b5d2b2001-06-05Martin Stjernholm  if(m->data ==MD) \
853b832000-12-14Martin Stjernholm  m->debug_size--; \
0b5d2b2001-06-05Martin Stjernholm  ); \
853b832000-12-14Martin Stjernholm  }else{ \
0b5d2b2001-06-05Martin Stjernholm  VAL_TYPES |= 1 << k->val.type; \ IND_TYPES |= 1 << k->ind.type; \
853b832000-12-14Martin Stjernholm  prev=&k->next; \ } \ } \ } \ } while (0)
0b5d2b2001-06-05Martin Stjernholm #define GC_REC_KP(REMOVE, N_REC, W_REC, N_TST, W_TST) do { \ if ((REMOVE = N_REC(&k->ind, 1))) \ gc_free_svalue(&k->val); \ else \ N_REC(&k->val, 1); \ } while (0) #define GC_REC_KP_IND(REMOVE, N_REC, W_REC, N_TST, W_TST) do { \ if ((REMOVE = W_REC(&k->ind, 1))) \ gc_free_svalue(&k->val); \ else \ N_REC(&k->val, 1); \ } while (0) #define GC_REC_KP_VAL(REMOVE, N_REC, W_REC, N_TST, W_TST) do { \ if ((REMOVE = N_TST(&k->ind))) /* Don't recurse now. */ \ gc_free_svalue(&k->val); \ else if ((REMOVE = W_REC(&k->val, 1))) \ gc_free_svalue(&k->ind); \ else \ N_REC(&k->ind, 1); /* Now we can recurse the index. */ \ } while (0) #define GC_REC_KP_BOTH(REMOVE, N_REC, W_REC, N_TST, W_TST) do { \ if ((REMOVE = W_TST(&k->ind))) /* Don't recurse now. */ \ gc_free_svalue(&k->val); \ else if ((REMOVE = W_REC(&k->val, 1))) \ gc_free_svalue(&k->ind); \ else \ W_REC(&k->ind, 1); /* Now we can recurse the index. */ \
853b832000-12-14Martin Stjernholm } while (0)
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)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zero refs in mapping->data\n");
57a4ab2000-01-27Fredrik Hübinette (Hubbe) #endif
9a6d002001-06-26Fredrik Hübinette (Hubbe)  debug_malloc_touch(m); debug_malloc_touch(m->data);
57a4ab2000-01-27Fredrik Hübinette (Hubbe) 
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 
853b832000-12-14Martin Stjernholm  if(gc_mark(md) && ((md->ind_types | md->val_types) & BIT_COMPLEX)) { TYPE_FIELD ind_types = 0, val_types = 0; if (MAPPING_DATA_IN_USE(md)) {
0b5d2b2001-06-05Martin Stjernholm  /* Must leave the mapping data untouched if it's busy. */
853b832000-12-14Martin Stjernholm  GC_RECURSE_MD_IN_USE(md, gc_mark_svalues, ind_types, val_types); gc_assert_checked_as_nonweak(md); }
0b5d2b2001-06-05Martin Stjernholm  else switch (md->flags & MAPPING_WEAK) { case 0: GC_RECURSE(md, GC_REC_KP, gc_mark, ind_types, val_types); gc_assert_checked_as_nonweak(md); break; case MAPPING_WEAK_INDICES: GC_RECURSE(md, GC_REC_KP_IND, gc_mark, ind_types, val_types); gc_assert_checked_as_weak(md); break; case MAPPING_WEAK_VALUES: GC_RECURSE(md, GC_REC_KP_VAL, gc_mark, ind_types, val_types); gc_assert_checked_as_weak(md); break; default: GC_RECURSE(md, GC_REC_KP_BOTH, gc_mark, ind_types, val_types); gc_assert_checked_as_weak(md); break; }
853b832000-12-14Martin Stjernholm  md->val_types = val_types; md->ind_types = ind_types;
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;
9a6d002001-06-26Fredrik Hübinette (Hubbe)  debug_malloc_touch(m); debug_malloc_touch(md);
5eca4d2000-09-04Martin Stjernholm 
e2d9e62000-06-10Martin Stjernholm #ifdef PIKE_DEBUG
5eca4d2000-09-04Martin Stjernholm  if(md->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zero refs in mapping->data\n");
e2d9e62000-06-10Martin Stjernholm #endif
853b832000-12-14Martin Stjernholm  if ((md->ind_types | md->val_types) & BIT_COMPLEX) { TYPE_FIELD ind_types = 0, val_types = 0;
5eca4d2000-09-04Martin Stjernholm  if (MAPPING_DATA_IN_USE(md)) {
0b5d2b2001-06-05Martin Stjernholm  /* Must leave the mapping data untouched if it's busy. */
9a6d002001-06-26Fredrik Hübinette (Hubbe)  debug_malloc_touch(m); debug_malloc_touch(md);
853b832000-12-14Martin Stjernholm  GC_RECURSE_MD_IN_USE(md, gc_cycle_check_svalues, ind_types, val_types);
595dac2000-09-30Martin Stjernholm  gc_assert_checked_as_nonweak(md);
5eca4d2000-09-04Martin Stjernholm  }
0b5d2b2001-06-05Martin Stjernholm  else switch (md->flags & MAPPING_WEAK) { case 0:
9a6d002001-06-26Fredrik Hübinette (Hubbe)  debug_malloc_touch(m); debug_malloc_touch(md);
0b5d2b2001-06-05Martin Stjernholm  GC_RECURSE(md, GC_REC_KP, gc_cycle_check, ind_types, val_types); gc_assert_checked_as_nonweak(md); break; case MAPPING_WEAK_INDICES:
9a6d002001-06-26Fredrik Hübinette (Hubbe)  debug_malloc_touch(m); debug_malloc_touch(md);
0b5d2b2001-06-05Martin Stjernholm  GC_RECURSE(md, GC_REC_KP_IND, gc_cycle_check, ind_types, val_types); gc_assert_checked_as_weak(md); break; case MAPPING_WEAK_VALUES:
9a6d002001-06-26Fredrik Hübinette (Hubbe)  debug_malloc_touch(m); debug_malloc_touch(md);
0b5d2b2001-06-05Martin Stjernholm  GC_RECURSE(md, GC_REC_KP_VAL, gc_cycle_check, ind_types, val_types); gc_assert_checked_as_weak(md); break; default:
9a6d002001-06-26Fredrik Hübinette (Hubbe)  debug_malloc_touch(m); debug_malloc_touch(md);
0b5d2b2001-06-05Martin Stjernholm  GC_RECURSE(md, GC_REC_KP_BOTH, gc_cycle_check, ind_types, val_types); gc_assert_checked_as_weak(md); break; }
853b832000-12-14Martin Stjernholm  md->val_types = val_types; md->ind_types = ind_types;
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 
d9d6f02001-06-30Martin Stjernholm  if(debug_gc_check2(md, T_MAPPING, m, " as mapping data block of a mapping")) return;
0816292000-07-03Martin Stjernholm 
0b5d2b2001-06-05Martin Stjernholm  if (!(md->flags & MAPPING_WEAK) || MAPPING_DATA_IN_USE(md))
5eca4d2000-09-04Martin Stjernholm  /* Disregard the weak flag if the mapping data is busy; we must * leave it untouched in that case anyway. */ NEW_MAPPING_LOOP(md) {
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)  }
0b5d2b2001-06-05Martin Stjernholm  else { switch (md->flags & MAPPING_WEAK) { case MAPPING_WEAK_INDICES: NEW_MAPPING_LOOP(md) { debug_gc_check_weak_svalues(&k->ind, 1, T_MAPPING, m); debug_gc_check_svalues(&k->val, 1, T_MAPPING, m); } break; case MAPPING_WEAK_VALUES: NEW_MAPPING_LOOP(md) { debug_gc_check_svalues(&k->ind, 1, T_MAPPING, m); debug_gc_check_weak_svalues(&k->val, 1, T_MAPPING, m); } break; default: NEW_MAPPING_LOOP(md) { debug_gc_check_weak_svalues(&k->ind, 1, T_MAPPING, m); debug_gc_check_weak_svalues(&k->val, 1, T_MAPPING, m); } break; } gc_checked_as_weak(md);
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)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Error in mapping link list.\n");
7bf6232000-04-23Martin Stjernholm  for (m = first_mapping; m; m = m->next) { debug_gc_touch(m); n++;
e2d9e62000-06-10Martin Stjernholm  if (m->next && m->next->prev != m)
5aad932002-08-15Marcus Comstedt  Pike_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");
6e7eea2001-08-22Henrik Grubbström (Grubba)  describe_something(m, T_MAPPING, 0,2,0, NULL);
5aad932002-08-15Marcus Comstedt  Pike_fatal("Zapped mapping in list of active mappings!\n");
20513c2000-04-12Fredrik Hübinette (Hubbe)  } #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;
9a6d002001-06-26Fredrik Hübinette (Hubbe)  debug_malloc_touch(m); debug_malloc_touch(m->data);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  if(gc_is_referenced(m)) gc_mark_mapping_as_referenced(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); }
88cf4f2003-01-11Martin Stjernholm size_t gc_free_all_unreferenced_mappings(void)
515b6c1996-06-09Fredrik Hübinette (Hubbe) { struct mapping *m,*next;
57a4ab2000-01-27Fredrik Hübinette (Hubbe)  struct mapping_data *md;
a1b3872003-01-11Martin Stjernholm  size_t unreferenced = 0;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
e2d9e62000-06-10Martin Stjernholm  for(m=gc_internal_mapping;m;m=next)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
9a6d002001-06-26Fredrik Hübinette (Hubbe)  debug_malloc_touch(m); debug_malloc_touch(m->data);
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;
9a6d002001-06-26Fredrik Hübinette (Hubbe)  debug_malloc_touch(m); debug_malloc_touch(md);
27bec92000-02-15Henrik Grubbström (Grubba)  /* Protect against unlink_mapping_data() recursing too far. */
1f342f2000-02-04Fredrik Hübinette (Hubbe)  m->data=&empty_data;
9a6d002001-06-26Fredrik Hübinette (Hubbe)  add_ref(m->data);
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; }
a1b3872003-01-11Martin Stjernholm  unreferenced++;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  }
88cf4f2003-01-11Martin Stjernholm 
a1b3872003-01-11Martin Stjernholm  return unreferenced;
515b6c1996-06-09Fredrik Hübinette (Hubbe) }
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;
06983f1996-09-22Fredrik Hübinette (Hubbe)  free_svalue(&k->ind); free_svalue(&k->val);
df9b622001-05-27Henrik Grubbström (Grubba)  FREE_KEYPAIR(md, k); md->free_list->ind.type = T_INT; md->free_list->val.type = T_INT;
06983f1996-09-22Fredrik Hübinette (Hubbe)  }
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) 
7d91bf2001-05-13Fredrik Hübinette (Hubbe)  SET_NEXT_AND_FREE(m, free_mapping);
c94c371996-03-28Fredrik Hübinette (Hubbe)  }
c3c7031996-12-04Fredrik Hübinette (Hubbe) }
32b3842001-02-22Fredrik Hübinette (Hubbe) 
84387d2001-09-24Fredrik Hübinette (Hubbe) int mapping_is_constant(struct mapping *m, struct processing *p) {
c7ad762001-10-03Fredrik Hübinette (Hubbe)  int ret=1;
84387d2001-09-24Fredrik Hübinette (Hubbe)  INT32 e; struct keypair *k; struct mapping_data *md=m->data; if( (md->ind_types | md->val_types) & ~(BIT_INT|BIT_FLOAT|BIT_STRING)) { md->valrefs++; add_ref(md); NEW_MAPPING_LOOP(md) {
c7ad762001-10-03Fredrik Hübinette (Hubbe)  if(!svalues_are_constant(&k->ind, 1, md->ind_types, p) || !svalues_are_constant(&k->val, 1, md->val_types, p)) { ret=0; e=md->hashsize; break; }
84387d2001-09-24Fredrik Hübinette (Hubbe)  } md->valrefs--; free_mapping_data(md); }
c7ad762001-10-03Fredrik Hübinette (Hubbe)  return ret;
84387d2001-09-24Fredrik Hübinette (Hubbe) }