diff --git a/src/gc.c b/src/gc.c index 3f8567e938498805765e11cdac67c4b9af0b08d8..660e595ae2bd2ddeee3d46334858a72528c97c64 100644 --- a/src/gc.c +++ b/src/gc.c @@ -378,6 +378,70 @@ INT32 gc_check(void *a) return getmark(a)->refs++; } +static void init_gc(void) +{ + INT32 tmp3; + /* init hash , hashsize will be a prime between num_objects/8 and + * num_objects/4, this will assure that no re-hashing is needed. + */ + tmp3=my_log2(num_objects); + + if(!d_flag) tmp3-=2; + if(tmp3<0) tmp3=0; + if(tmp3>=(long)NELEM(hashprimes)) tmp3=NELEM(hashprimes)-1; + hashsize=hashprimes[tmp3]; + + hash=(struct marker **)xalloc(sizeof(struct marker **)*hashsize); + MEMSET((char *)hash,0,sizeof(struct marker **)*hashsize); + markers_left_in_chunk=0; +} + +static void exit_gc(void) +{ + struct marker_chunk *m; + /* Free hash table */ + free((char *)hash); + while((m=chunk)) + { + chunk=m->next; + free((char *)m); + } +} + +void locate_references(void *a) +{ + if(!in_gc) + init_gc(); + + fprintf(stderr,"**Looking for references:\n"); + + check_for=a; + + found_where=" in an array"; + gc_check_all_arrays(); + + found_where=" in a multiset"; + gc_check_all_multisets(); + + found_where=" in a mapping"; + gc_check_all_mappings(); + + found_where=" in a program"; + gc_check_all_programs(); + + found_where=" in an object"; + gc_check_all_objects(); + + found_where=" in a module"; + call_callback(& gc_callbacks, (void *)0); + + found_where=""; + check_for=0; + + if(!in_gc) + exit_gc(); +} + int gc_is_referenced(void *a) { struct marker *m; @@ -392,29 +456,7 @@ int gc_is_referenced(void *a) fprintf(stderr,"**Something has %ld references, while gc() found %ld + %ld external.\n",(long)*(INT32 *)a,(long)refs,(long)xrefs); describe_something(a, t); - fprintf(stderr,"**Looking for references:\n"); - check_for=a; - - found_where=" in an array"; - gc_check_all_arrays(); - - found_where=" in a multiset"; - gc_check_all_multisets(); - - found_where=" in a mapping"; - gc_check_all_mappings(); - - found_where=" in a program"; - gc_check_all_programs(); - - found_where=" in an object"; - gc_check_all_objects(); - - found_where=" in a module"; - call_callback(& gc_callbacks, (void *)0); - - found_where=""; - check_for=0; + locate_references(a); fatal("Ref counts are wrong (has %d, found %d + %d external)\n", *(INT32 *)a, @@ -474,8 +516,7 @@ int gc_do_free(void *a) void do_gc(void) { double tmp; - INT32 tmp2,tmp3; - struct marker_chunk *m; + INT32 tmp2; double multiplier; if(in_gc) return; @@ -507,19 +548,7 @@ void do_gc(void) objects_freed += (double) num_objects; - /* init hash , hashsize will be a prime between num_objects/8 and - * num_objects/4, this will assure that no re-hashing is needed. - */ - tmp3=my_log2(num_objects); - - if(!d_flag) tmp3-=2; - if(tmp3<0) tmp3=0; - if(tmp3>=(long)NELEM(hashprimes)) tmp3=NELEM(hashprimes)-1; - hashsize=hashprimes[tmp3]; - - hash=(struct marker **)xalloc(sizeof(struct marker **)*hashsize); - MEMSET((char *)hash,0,sizeof(struct marker **)*hashsize); - markers_left_in_chunk=0; + init_gc(); /* First we count internal references */ gc_check_all_arrays(); @@ -546,14 +575,7 @@ void do_gc(void) gc_free_all_unreferenced_programs(); gc_free_all_unreferenced_objects(); - - /* Free hash table */ - free((char *)hash); - while((m=chunk)) - { - chunk=m->next; - free((char *)m); - } + exit_gc(); destruct_objects_to_destruct();