diff --git a/src/mapping.c b/src/mapping.c index f9f658a3371ce65a321baaf00d1c6a98fbd79f4f..e94fd5eae4f88b96f9d48709612dd8d1b1af3612 100644 --- a/src/mapping.c +++ b/src/mapping.c @@ -5,7 +5,7 @@ \*/ /**/ #include "global.h" -RCSID("$Id: mapping.c,v 1.55 2000/01/31 21:26:59 hubbe Exp $"); +RCSID("$Id: mapping.c,v 1.56 2000/02/01 06:25:06 hubbe Exp $"); #include "main.h" #include "object.h" #include "mapping.h" @@ -204,23 +204,21 @@ void really_free_mapping_data(struct mapping_data *md) * inefficient just after being rehashed. * (wonder if this can't be done faster somehow?) */ -static void mapping_rehash_backwards(struct mapping_data *md, struct keypair *p) +static void mapping_rehash_backwards(struct mapping *m, + struct keypair *p) { unsigned INT32 h; struct keypair *tmp; if(!p) return; - mapping_rehash_backwards(md,p->next); - h=hash_svalue(& p->ind) % md->hashsize; - tmp=md->free_list; - md->free_list=tmp->next; - tmp->next=md->hash[h]; - md->hash[h]=tmp; - tmp->ind=p->ind; - tmp->val=p->val; - md->size++; - md->ind_types |= 1 << p->ind.type; - md->val_types |= 1 << p->val.type; + mapping_rehash_backwards(m,p->next); + + /* We insert without overwriting + * however, this could still cause + * problems. (for instance if someone does an + * m_delete on an element that is not there yet.. + */ + low_mapping_insert(m, &p->ind, &p->val,0); } /* This function re-allocates a mapping. It adjusts the max no. of @@ -235,43 +233,33 @@ static struct mapping *rehash(struct mapping *m, int new_size) #endif INT32 e; + md=m->data; #ifdef PIKE_DEBUG - if(m->data->refs <=0) + if(md->refs <=0) fatal("Zero refs in mapping->data\n"); if(d_flag>1) check_mapping(m); #endif - /* This can be optimized to do rehash and copy - * in one operation.. -Hubbe - */ - md=m->data; - if(md->refs>1) - { - debug_malloc_touch(md); - md=m->data=copy_mapping_data(m->data); - debug_malloc_touch(md); - } - -#ifdef PIKE_DEBUG - if(d_flag>1) check_mapping(m); -#endif - init_mapping(m, new_size); debug_malloc_touch(m); + /* No need to do add_ref(md) because the ref + * from 'm' is not freed yet + */ + md->valrefs++; + for(e=0;e<md->hashsize;e++) - mapping_rehash_backwards(m->data, md->hash[e]); - m->data->size = md->size; + mapping_rehash_backwards(m, md->hash[e]); + + md->valrefs--; #ifdef PIKE_DEBUG if(m->data->size != tmp) fatal("Rehash failed, size not same any more.\n"); - if(md->refs>1) - fatal("MD has extra refs in rehash!\n"); #endif - free((char *)md); + free_mapping_data(md); #ifdef PIKE_DEBUG if(d_flag>1) check_mapping(m); @@ -479,9 +467,10 @@ void mapping_fix_type_field(struct mapping *m) /* This function inserts key:val into the mapping m. * Same as doing m[key]=val; in pike. */ -void mapping_insert(struct mapping *m, - struct svalue *key, - struct svalue *val) +void low_mapping_insert(struct mapping *m, + struct svalue *key, + struct svalue *val, + int overwrite) { unsigned INT32 h,h2; struct keypair *k, **prev; @@ -527,6 +516,7 @@ void mapping_insert(struct mapping *m, if(d_flag>1) check_mapping(m); #endif free_mapping_data(md); + if(!overwrite) return; PREPARE_FOR_DATA_CHANGE2(); PROPAGATE(); /* propagate after preparing */ md->val_types |= 1 << val->type; @@ -546,6 +536,7 @@ void mapping_insert(struct mapping *m, /* We do a re-hash here instead of copying the mapping. */ if((!(k=md->free_list)) || md->refs>1) { + debug_malloc_touch(m); rehash(m, md->size * 2 + 2); md=m->data; k=md->free_list; @@ -569,6 +560,13 @@ void mapping_insert(struct mapping *m, #endif } +void mapping_insert(struct mapping *m, + struct svalue *key, + struct svalue *val) +{ + low_mapping_insert(m,key,val,1); +} + union anything *mapping_get_item_ptr(struct mapping *m, struct svalue *key, TYPE_T t) @@ -645,6 +643,7 @@ union anything *mapping_get_item_ptr(struct mapping *m, /* no need to call PREPARE_* because we re-hash instead */ if(!(k=md->free_list) || md->refs>1) { + debug_malloc_touch(m); rehash(m, md->size * 2 + 2); md=m->data; k=md->free_list; @@ -681,6 +680,7 @@ void map_delete_no_free(struct mapping *m, if(m->data->refs <=0) fatal("Zero refs in mapping->data\n"); if(d_flag>1) check_mapping(m); + debug_malloc_touch(m); #endif h2=hash_svalue(key); @@ -697,6 +697,7 @@ void map_delete_no_free(struct mapping *m, goto md_do_nothing); md_do_nothing: + debug_malloc_touch(m); free_mapping_data(md); if(to) { @@ -713,6 +714,7 @@ void map_delete_no_free(struct mapping *m, if(m->data != md) fatal("Wrong dataset in mapping_delete!\n"); if(d_flag>1) check_mapping(m); + debug_malloc_touch(m); #endif free_mapping_data(md); PREPARE_FOR_INDEX_CHANGE2(); @@ -732,7 +734,10 @@ void map_delete_no_free(struct mapping *m, md->size--; if(md->size < (md->hashsize + 1) * MIN_LINK_LENGTH) + { + debug_malloc_touch(m); rehash(m, MAP_SLOTS(m->data->size)); + } #ifdef PIKE_DEBUG if(d_flag>1) check_mapping(m); @@ -751,6 +756,7 @@ void check_mapping_for_destruct(struct mapping *m) if(m->data->refs <=0) fatal("Zero refs in mapping->data\n"); if(d_flag>1) check_mapping(m); + debug_malloc_touch(m); #endif /* no is_eq -> no locking */ @@ -785,7 +791,10 @@ void check_mapping_for_destruct(struct mapping *m) } } if(MAP_SLOTS(md->size) < md->hashsize * MIN_LINK_LENGTH) + { + debug_malloc_touch(m); rehash(m, MAP_SLOTS(md->size)); + } md->val_types = val_types; md->ind_types = ind_types; @@ -1104,6 +1113,7 @@ struct mapping *copy_mapping(struct mapping *m) #endif n=allocate_mapping(0); + if(!m_sizeof(m)) return n; /* done */ debug_malloc_touch(n->data); free_mapping_data(n->data); n->data=m->data; @@ -1835,7 +1845,10 @@ void gc_free_all_unreferenced_mappings(void) } } if(MAP_SLOTS(md->size) < md->hashsize * MIN_LINK_LENGTH) + { + debug_malloc_touch(m); rehash(m, MAP_SLOTS(md->size)); + } next=m->next; free_mapping(m); } diff --git a/src/mapping.h b/src/mapping.h index 0830ad542d2ea9eef180a978597e0a71d7c1559b..6d000ce0b872e7ff1b6b9d962311eba7340b4cbc 100644 --- a/src/mapping.h +++ b/src/mapping.h @@ -5,12 +5,13 @@ \*/ /* - * $Id: mapping.h,v 1.18 2000/01/31 21:27:00 hubbe Exp $ + * $Id: mapping.h,v 1.19 2000/02/01 06:25:07 hubbe Exp $ */ #ifndef MAPPING_H #define MAPPING_H #include "las.h" +#include "block_alloc_h.h" #define MAPPING_FLAG_WEAK 1 @@ -64,10 +65,17 @@ extern struct mapping *first_mapping; #define free_mapping_data(M) do{ struct mapping_data *md_=(M); debug_malloc_touch(md_); if(!--md_->refs) really_free_mapping_data(md_); }while(0) /* Prototypes begin here */ +BLOCK_ALLOC(mapping, 511) + +static void check_mapping_type_fields(struct mapping *m); struct mapping *debug_allocate_mapping(int size); -void really_free_mapping(struct mapping *m); void really_free_mapping_data(struct mapping_data *md); +struct mapping_data *copy_mapping_data(struct mapping_data *md); void mapping_fix_type_field(struct mapping *m); +void low_mapping_insert(struct mapping *m, + struct svalue *key, + struct svalue *val, + int overwrite); void mapping_insert(struct mapping *m, struct svalue *key, struct svalue *val); @@ -107,11 +115,16 @@ struct array *mapping_to_array(struct mapping *m); void mapping_replace(struct mapping *m,struct svalue *from, struct svalue *to); struct mapping *mkmapping(struct array *ind, struct array *val); struct mapping *copy_mapping(struct mapping *m); +struct mapping *copy_mapping(struct mapping *m); struct mapping *merge_mappings(struct mapping *a, struct mapping *b, INT32 op); +struct mapping *merge_mapping_array_ordered(struct mapping *a, + struct array *b, INT32 op); +struct mapping *merge_mapping_array_unordered(struct mapping *a, + struct array *b, INT32 op); struct mapping *add_mappings(struct svalue *argp, INT32 args); int mapping_equal_p(struct mapping *a, struct mapping *b, struct processing *p); void describe_mapping(struct mapping *m,struct processing *p,int indent); -node * make_node_from_mapping(struct mapping *m); +node *make_node_from_mapping(struct mapping *m); void f_m_delete(INT32 args); void f_aggregate_mapping(INT32 args); struct mapping *copy_mapping_recursively(struct mapping *m, @@ -119,7 +132,7 @@ struct mapping *copy_mapping_recursively(struct mapping *m, void mapping_search_no_free(struct svalue *to, struct mapping *m, struct svalue *look_for, - struct svalue *start); + struct svalue *key ); void check_mapping(struct mapping *m); void check_all_mappings(void); void gc_mark_mapping_as_referenced(struct mapping *m); @@ -129,8 +142,6 @@ void gc_free_all_unreferenced_mappings(void); void simple_describe_mapping(struct mapping *m); void debug_dump_mapping(struct mapping *m); void zap_all_mappings(void); -void count_memory_in_mappings(INT32 *num_, INT32 *size_); -struct mapping_data *copy_mapping_data(struct mapping_data *md); /* Prototypes end here */ #endif