diff --git a/src/las.c b/src/las.c index 4e14ad1eba305a2bd1b7d5c181187f82ef4d024e..3056b71adafc0bb1def998b6bb0f539856451caf 100644 --- a/src/las.c +++ b/src/las.c @@ -5,7 +5,7 @@ \*/ /**/ #include "global.h" -RCSID("$Id: las.c,v 1.222 2000/11/20 01:20:25 mast Exp $"); +RCSID("$Id: las.c,v 1.223 2000/11/25 16:45:02 grubba Exp $"); #include "language.h" #include "interpret.h" @@ -400,9 +400,11 @@ static void sub_node(node *n) { node *prior; +#ifdef PIKE_DEBUG if (!node_hash.size) { return; } +#endif /* PIKE_DEBUG */ prior = node_hash.table[n->hash % node_hash.size]; @@ -427,11 +429,12 @@ static node *freeze_node(node *orig) { size_t hash = hash_node(orig); node *n; + int found = 0; /* free_node() wants a correct hash */ orig->hash = hash; - if (orig->node_info & OPT_NOT_SHARED) { + if (orig->tree_info & OPT_NOT_SHARED) { /* No need to have this node in the hash-table. */ /* add_node(orig); */ return check_node_hash(dmalloc_touch(node *, orig)); @@ -440,11 +443,17 @@ static node *freeze_node(node *orig) /* Mark this node as a possible duplicate */ orig->node_info |= OPT_DEFROSTED; /* Make sure we don't find ourselves */ - sub_node(orig); + /* sub_node(orig); */ n = node_hash.table[hash % node_hash.size]; while (n) { + if (n == orig) { + found = 1; + if (!(n = n->next)) { + break; + } + } if ((n->hash == hash) && !MEMCMP(&(n->token), &(orig->token), sizeof(node) - OFFSETOF(node_s, token))) { @@ -460,6 +469,21 @@ static node *freeze_node(node *orig) copy_shared_string(n->type, orig->type); } } + if (!found) { + node *scan = n; + while(scan->next) { + if (scan->next == orig) { + scan->next = orig->next; + break; + } + scan = scan->next; + } + } else { + /* FIXME: sub_node() recalculates the hash index. + * We might get better performance by using the one we already have. + */ + sub_node(orig); + } free_node(dmalloc_touch(node *, orig)); n->refs++; return check_node_hash(dmalloc_touch(node *, n)); @@ -467,7 +491,9 @@ static node *freeze_node(node *orig) n = n->next; } orig->node_info &= ~OPT_DEFROSTED; - add_node(dmalloc_touch(node *, orig)); + if (!found) { + add_node(dmalloc_touch(node *, orig)); + } check_tree(orig,0); return check_node_hash(orig); } @@ -531,6 +557,11 @@ void free_all_nodes(void) #endif { /* Free the node and be happy */ +#ifdef SHARED_NODES + /* Force the hashtable to be cleared. */ + tmp->next = NULL; + sub_node(tmp); +#endif /* SHARED_NODES */ /* Make sure we don't free any nodes twice */ if(car_is_node(tmp)) _CAR(tmp)=0; if(cdr_is_node(tmp)) _CDR(tmp)=0; @@ -563,7 +594,7 @@ void free_all_nodes(void) cumulative_parse_error=0; #ifdef SHARED_NODES - MEMSET(node_hash.table, 0, sizeof(node *) * node_hash.size); + /* MEMSET(node_hash.table, 0, sizeof(node *) * node_hash.size); */ #endif /* SHARED_NODES */ } } @@ -816,16 +847,6 @@ node *debug_mknode(short token, node *a, node *b) res->token = token; res->type = 0; -#ifdef SHARED_NODES - { - node *res2 = freeze_node(res); - - if (res2 != res) { - return dmalloc_touch(node *, res2); - } - } -#endif /* SHARED_NODES */ - switch(token) { case F_CATCH: @@ -978,6 +999,18 @@ node *debug_mknode(short token, node *a, node *b) res->tree_info |= res->node_info; +#ifdef SHARED_NODES + /* No need to freeze the node if it can't be shared. */ + if (!(res->tree_info & OPT_NOT_SHARED)) + { + node *res2 = freeze_node(res); + + if (res2 != res) { + return dmalloc_touch(node *, res2); + } + } +#endif /* SHARED_NODES */ + #ifdef PIKE_DEBUG if(d_flag > 3) verify_shared_strings_tables(); @@ -1032,6 +1065,7 @@ node *debug_mknewintnode(int nr) node *res = mkemptynode(); res->token = F_CONSTANT; res->node_info = OPT_NOT_SHARED; + res->tree_info = OPT_NOT_SHARED; res->u.sval.type = T_INT; res->u.sval.subtype = NUMBER_NUMBER; res->u.sval.u.integer = nr;