6930181996-02-25Fredrik Hübinette (Hubbe) /*\
06983f1996-09-22Fredrik Hübinette (Hubbe) ||| This file a part of Pike, and is copyright by Fredrik Hubinette ||| Pike is distributed as GPL (General Public License)
6930181996-02-25Fredrik Hübinette (Hubbe) ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h"
a29e021996-10-15Fredrik Hübinette (Hubbe) struct callback *gc_evaluator_callback=0;
c94c371996-03-28Fredrik Hübinette (Hubbe) #include "array.h"
06983f1996-09-22Fredrik Hübinette (Hubbe) #include "multiset.h"
c94c371996-03-28Fredrik Hübinette (Hubbe) #include "mapping.h" #include "object.h" #include "program.h"
4a578f1997-01-27Fredrik Hübinette (Hubbe) #include "stralloc.h"
9c6f7d1997-04-15Fredrik Hübinette (Hubbe) #include "stuff.h" #include "error.h"
9aa6fa1997-05-19Fredrik Hübinette (Hubbe) #include "pike_memory.h"
1a11681997-10-06Fredrik Hübinette (Hubbe) #include "pike_macros.h"
1ca3ba1997-10-13Fredrik Hübinette (Hubbe) #include "pike_types.h"
dc296b1997-10-21Fredrik Hübinette (Hubbe) #include "time_stuff.h"
c94c371996-03-28Fredrik Hübinette (Hubbe) 
6930181996-02-25Fredrik Hübinette (Hubbe) #include "gc.h" #include "main.h"
dc296b1997-10-21Fredrik Hübinette (Hubbe) #include <math.h>
6930181996-02-25Fredrik Hübinette (Hubbe) 
991e5a1998-04-28Fredrik Hübinette (Hubbe) RCSID("$Id: gc.c,v 1.37 1998/04/29 02:45:21 hubbe Exp $");
24ddc71998-03-28Henrik Grubbström (Grubba) 
6930181996-02-25Fredrik Hübinette (Hubbe) /* Run garbage collect approximate every time we have * 20 percent of all arrays, objects and programs is * garbage. */ #define GC_CONST 20 #define MIN_ALLOC_THRESHOLD 1000
b95bef1996-03-29Fredrik Hübinette (Hubbe) #define MAX_ALLOC_THRESHOLD 10000000
6930181996-02-25Fredrik Hübinette (Hubbe) #define MULTIPLIER 0.9
c94c371996-03-28Fredrik Hübinette (Hubbe) #define MARKER_CHUNK_SIZE 1023
6930181996-02-25Fredrik Hübinette (Hubbe) 
dc296b1997-10-21Fredrik Hübinette (Hubbe) INT32 num_objects =0; INT32 num_allocs =0;
6930181996-02-25Fredrik Hübinette (Hubbe) INT32 alloc_threshold = MIN_ALLOC_THRESHOLD;
dc296b1997-10-21Fredrik Hübinette (Hubbe) static int in_gc = 0;
991e5a1998-04-28Fredrik Hübinette (Hubbe) struct queue gc_mark_queue;
6930181996-02-25Fredrik Hübinette (Hubbe) 
dc296b1997-10-21Fredrik Hübinette (Hubbe) static double objects_alloced = 0.0; static double objects_freed = 0.0;
6930181996-02-25Fredrik Hübinette (Hubbe) 
4a578f1997-01-27Fredrik Hübinette (Hubbe) struct callback_list gc_callbacks; struct callback *add_gc_callback(callback_func call, void *arg, callback_func free_func) { return add_to_callback(&gc_callbacks, call, arg, free_func); }
c94c371996-03-28Fredrik Hübinette (Hubbe) #define GC_REFERENCED 1
05c7cd1997-07-19Fredrik Hübinette (Hubbe) #define GC_XREFERENCED 2
c94c371996-03-28Fredrik Hübinette (Hubbe)  struct marker { INT32 refs;
05c7cd1997-07-19Fredrik Hübinette (Hubbe) #ifdef DEBUG INT32 xrefs; #endif
c94c371996-03-28Fredrik Hübinette (Hubbe)  INT32 flags;
05c7cd1997-07-19Fredrik Hübinette (Hubbe)  struct marker *next; void *marked;
c94c371996-03-28Fredrik Hübinette (Hubbe) }; struct marker_chunk { struct marker_chunk *next; struct marker markers[MARKER_CHUNK_SIZE]; }; static struct marker_chunk *chunk=0; static int markers_left_in_chunk=0;
be478c1997-08-30Henrik Grubbström (Grubba) static struct marker *new_marker(void)
c94c371996-03-28Fredrik Hübinette (Hubbe) { if(!markers_left_in_chunk) { struct marker_chunk *m; m=(struct marker_chunk *)xalloc(sizeof(struct marker_chunk)); m->next=chunk; chunk=m; markers_left_in_chunk=MARKER_CHUNK_SIZE; } markers_left_in_chunk--; return chunk->markers + markers_left_in_chunk; } static struct marker **hash=0;
cc15b71997-10-04Henrik Grubbström (Grubba) static unsigned long hashsize=0;
c94c371996-03-28Fredrik Hübinette (Hubbe)  static struct marker *getmark(void *a) {
9d09821998-04-09Fredrik Hübinette (Hubbe)  unsigned long hashval;
c94c371996-03-28Fredrik Hübinette (Hubbe)  struct marker *m;
adfda41998-04-09Fredrik Hübinette (Hubbe)  hashval=(unsigned long)a; hashval%=hashsize; #ifdef DEBUG if(hashval >= hashsize) fatal("Compiler has buggy modulo operator.\n"); #endif
c94c371996-03-28Fredrik Hübinette (Hubbe)  for(m=hash[hashval];m;m=m->next) if(m->marked == a) return m; m=new_marker(); m->marked=a; m->refs=0;
05c7cd1997-07-19Fredrik Hübinette (Hubbe) #ifdef DEBUG m->xrefs=0; #endif
c94c371996-03-28Fredrik Hübinette (Hubbe)  m->flags=0; m->next=hash[hashval]; hash[hashval]=m; return m; }
b8a6e71996-09-25Fredrik Hübinette (Hubbe) #ifdef DEBUG
1ca3ba1997-10-13Fredrik Hübinette (Hubbe) 
dc296b1997-10-21Fredrik Hübinette (Hubbe) time_t last_gc; void dump_gc_info(void) { fprintf(stderr,"Current number of objects: %ld\n",(long)num_objects); fprintf(stderr,"Objects allocated total : %ld\n",(long)num_allocs); fprintf(stderr," threshold for next gc() : %ld\n",(long)alloc_threshold); fprintf(stderr,"Average allocs per gc() : %f\n",objects_alloced); fprintf(stderr,"Average frees per gc() : %f\n",objects_freed); fprintf(stderr,"Second since last gc() : %ld\n", (long)TIME(0) - (long)last_gc); fprintf(stderr,"Projected garbage : %f\n", objects_freed * (double) num_allocs / (double) alloc_threshold); fprintf(stderr,"in_gc : %d\n", in_gc); }
1ca3ba1997-10-13Fredrik Hübinette (Hubbe) TYPE_T attempt_to_identify(void *something) { struct array *a; struct object *o; struct program *p;
62971d1998-01-19Fredrik Hübinette (Hubbe)  struct mapping *m; struct multiset *mu;
1ca3ba1997-10-13Fredrik Hübinette (Hubbe)  a=&empty_array; do { if(a==(struct array *)something) return T_ARRAY; a=a->next; }while(a!=&empty_array); for(o=first_object;o;o=o->next) if(o==(struct object *)something) return T_OBJECT; for(p=first_program;p;p=p->next) if(p==(struct program *)something) return T_PROGRAM;
62971d1998-01-19Fredrik Hübinette (Hubbe)  for(m=first_mapping;m;m=m->next) if(m==(struct mapping *)something) return T_MAPPING; for(mu=first_multiset;mu;mu=mu->next) if(mu==(struct multiset *)something) return T_MULTISET; if(safe_debug_findstring((struct pike_string *)something)) return T_STRING;
1ca3ba1997-10-13Fredrik Hübinette (Hubbe)  return T_UNKNOWN; }
b8a6e71996-09-25Fredrik Hübinette (Hubbe) static void *check_for =0;
1ca3ba1997-10-13Fredrik Hübinette (Hubbe) static char *found_where="";
f6d0171997-10-15Fredrik Hübinette (Hubbe) static void *found_in=0;
4694111997-11-07Fredrik Hübinette (Hubbe) static int found_in_type=0;
f6d0171997-10-15Fredrik Hübinette (Hubbe) void *gc_svalue_location=0;
b8a6e71996-09-25Fredrik Hübinette (Hubbe) 
3568101997-10-16Fredrik Hübinette (Hubbe) void describe_location(void *memblock, TYPE_T type, void *location) {
4694111997-11-07Fredrik Hübinette (Hubbe)  if(!location) return;
3568101997-10-16Fredrik Hübinette (Hubbe)  fprintf(stderr,"**Location of (short) svalue: %p\n",location);
62971d1998-01-19Fredrik Hübinette (Hubbe)  switch(type)
3568101997-10-16Fredrik Hübinette (Hubbe)  {
0b69441998-01-19Fredrik Hübinette (Hubbe)  case T_PROGRAM: { struct program *p=(struct program *)memblock; char *ptr=(char *)location; if(ptr >= (char *)p->inherits && ptr<(char*)(p->inherits+p->num_inherits)) fprintf(stderr,"**In inherit block.\n"); if(ptr >= (char *)p->strings && ptr<(char*)(p->strings+p->num_strings)) fprintf(stderr,"**In string block.\n"); if(ptr >= (char *)p->identifiers && ptr<(char*)(p->identifiers+p->num_identifiers)) fprintf(stderr,"**In identifier block.\n"); return; }
62971d1998-01-19Fredrik Hübinette (Hubbe)  case T_OBJECT:
3568101997-10-16Fredrik Hübinette (Hubbe)  {
62971d1998-01-19Fredrik Hübinette (Hubbe)  struct object *o=(struct object *)memblock; if(o->prog)
3568101997-10-16Fredrik Hübinette (Hubbe)  {
62971d1998-01-19Fredrik Hübinette (Hubbe)  INT32 e,d; for(e=0;e<(INT32)o->prog->num_inherits;e++)
3568101997-10-16Fredrik Hübinette (Hubbe)  {
62971d1998-01-19Fredrik Hübinette (Hubbe)  struct inherit tmp=o->prog->inherits[e]; char *base=o->storage + tmp.storage_offset; for(d=0;d<(INT32)tmp.prog->num_identifiers;d++)
3568101997-10-16Fredrik Hübinette (Hubbe)  {
62971d1998-01-19Fredrik Hübinette (Hubbe)  struct identifier *id=tmp.prog->identifiers+d; if(!IDENTIFIER_IS_VARIABLE(id->identifier_flags)) continue; if(location == (void *)(base + id->func.offset)) { fprintf(stderr,"**In variable %s\n",id->name->str); }
3568101997-10-16Fredrik Hübinette (Hubbe)  } } }
62971d1998-01-19Fredrik Hübinette (Hubbe)  return;
3568101997-10-16Fredrik Hübinette (Hubbe)  }
62971d1998-01-19Fredrik Hübinette (Hubbe)  case T_ARRAY: { struct array *a=(struct array *)memblock; struct svalue *s=(struct svalue *)location; fprintf(stderr,"**In index %ld\n",(long)(s-ITEM(a))); return; }
3568101997-10-16Fredrik Hübinette (Hubbe)  } }
b8a6e71996-09-25Fredrik Hübinette (Hubbe) static void gdb_gc_stop_here(void *a) {
4694111997-11-07Fredrik Hübinette (Hubbe)  fprintf(stderr,"***One ref found%s.\n",found_where);
8fb1e11998-04-05Fredrik Hübinette (Hubbe)  describe_something(found_in, found_in_type, 0);
3568101997-10-16Fredrik Hübinette (Hubbe)  describe_location(found_in, found_in_type, gc_svalue_location);
b8a6e71996-09-25Fredrik Hübinette (Hubbe) }
f6d0171997-10-15Fredrik Hübinette (Hubbe) 
4694111997-11-07Fredrik Hübinette (Hubbe) void debug_gc_xmark_svalues(struct svalue *s, int num, char *fromwhere) { found_in=(void *)fromwhere; found_in_type=-1; gc_xmark_svalues(s,num); found_in_type=T_UNKNOWN; found_in=0; }
f6d0171997-10-15Fredrik Hübinette (Hubbe) TYPE_FIELD debug_gc_check_svalues(struct svalue *s, int num, TYPE_T t, void *data) { TYPE_FIELD ret; found_in=data; found_in_type=t; ret=gc_check_svalues(s,num); found_in_type=T_UNKNOWN;
4694111997-11-07Fredrik Hübinette (Hubbe)  found_in=0;
f6d0171997-10-15Fredrik Hübinette (Hubbe)  return ret; } void debug_gc_check_short_svalue(union anything *u, TYPE_T type, TYPE_T t, void *data) { found_in=data; found_in_type=t; gc_check_short_svalue(u,type); found_in_type=T_UNKNOWN;
4694111997-11-07Fredrik Hübinette (Hubbe)  found_in=0;
f6d0171997-10-15Fredrik Hübinette (Hubbe) }
0b69441998-01-19Fredrik Hübinette (Hubbe)  int debug_gc_check(void *x, TYPE_T t, void *data) { int ret; found_in=data; found_in_type=t; ret=gc_check(x); found_in_type=T_UNKNOWN; found_in=0; return ret; }
8fb1e11998-04-05Fredrik Hübinette (Hubbe) void describe_something(void *a, int t, int dm)
f6d0171997-10-15Fredrik Hübinette (Hubbe) { struct program *p=(struct program *)a; if(!a) return;
d461731998-04-07Fredrik Hübinette (Hubbe)  #ifdef DEBUG_MALLOC
8fb1e11998-04-05Fredrik Hübinette (Hubbe)  if(dm) debug_malloc_dump_references(a);
d461731998-04-07Fredrik Hübinette (Hubbe) #endif
4694111997-11-07Fredrik Hübinette (Hubbe)  if(t==-1) { fprintf(stderr,"**Location description: %s\n",(char *)a); return; }
f6d0171997-10-15Fredrik Hübinette (Hubbe)  fprintf(stderr,"**Location: %p Type: %s Refs: %d\n",a, get_name_of_type(t), *(INT32 *)a); switch(t) { case T_OBJECT: p=((struct object *)a)->prog;
8fb1e11998-04-05Fredrik Hübinette (Hubbe)  fprintf(stderr,"**Parent identifier: %d\n",((struct object *)a)->parent_identifier); if( ((struct object *)a)->parent) { fprintf(stderr,"**Describing object's parent:\n"); describe_something( ((struct object *)a)->parent, t, 1); }else{ fprintf(stderr,"**There is no parent (any longer?)\n"); }
f6d0171997-10-15Fredrik Hübinette (Hubbe)  if(!p) { fprintf(stderr,"**The object is destructed.\n"); break; } fprintf(stderr,"**Attempting to describe program object was instantiated from:\n"); case T_PROGRAM:
3568101997-10-16Fredrik Hübinette (Hubbe)  { char *tmp; INT32 line,pos; fprintf(stderr,"**Program id: %ld\n",(long)(p->id));
05590d1998-04-23Fredrik Hübinette (Hubbe)  if(p->flags & PROGRAM_HAS_C_METHODS)
f6d0171997-10-15Fredrik Hübinette (Hubbe)  {
61e9a01998-01-25Fredrik Hübinette (Hubbe)  int e;
f6d0171997-10-15Fredrik Hübinette (Hubbe)  fprintf(stderr,"**The program was written in C.\n");
61e9a01998-01-25Fredrik Hübinette (Hubbe)  fprintf(stderr,"**identifiers:\n"); for(e=0;e<p->num_identifiers;e++)
8fb1e11998-04-05Fredrik Hübinette (Hubbe)  fprintf(stderr,"**** %s\n",p->identifiers[e].name->str);
f6d0171997-10-15Fredrik Hübinette (Hubbe)  }
3568101997-10-16Fredrik Hübinette (Hubbe) 
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  for(pos=0;pos<(long)p->num_program && pos<100;pos++)
f6d0171997-10-15Fredrik Hübinette (Hubbe)  {
3568101997-10-16Fredrik Hübinette (Hubbe)  tmp=get_line(p->program+pos, p, &line); if(tmp && line) { fprintf(stderr,"**Location: %s:%ld\n",tmp,(long)line); break; }
f6d0171997-10-15Fredrik Hübinette (Hubbe)  } break;
3568101997-10-16Fredrik Hübinette (Hubbe)  }
f6d0171997-10-15Fredrik Hübinette (Hubbe)  case T_ARRAY: fprintf(stderr,"**Describing array:\n"); debug_dump_array((struct array *)a); break;
62971d1998-01-19Fredrik Hübinette (Hubbe) 
61e9a01998-01-25Fredrik Hübinette (Hubbe)  case T_MAPPING: fprintf(stderr,"**Describing mapping:\n"); debug_dump_mapping((struct mapping *)a); break;
62971d1998-01-19Fredrik Hübinette (Hubbe)  case T_STRING: { struct pike_string *s=(struct pike_string *)a; fprintf(stderr,"**String length is %d:\n",s->len); if(s->len>77) { fprintf(stderr,"** \"%60s ...\"\n",s->str); }else{ fprintf(stderr,"** \"%s\"\n",s->str); } break; }
f6d0171997-10-15Fredrik Hübinette (Hubbe)  }
8fb1e11998-04-05Fredrik Hübinette (Hubbe)  fprintf(stderr,"*******************\n"); } void describe(void *x) { describe_something(x, attempt_to_identify(x),1);
f6d0171997-10-15Fredrik Hübinette (Hubbe) }
b8a6e71996-09-25Fredrik Hübinette (Hubbe) #endif
4a578f1997-01-27Fredrik Hübinette (Hubbe) INT32 gc_check(void *a)
c94c371996-03-28Fredrik Hübinette (Hubbe) {
b8a6e71996-09-25Fredrik Hübinette (Hubbe) #ifdef DEBUG if(check_for) { if(check_for == a) { gdb_gc_stop_here(a); }
4a578f1997-01-27Fredrik Hübinette (Hubbe)  return 0;
b8a6e71996-09-25Fredrik Hübinette (Hubbe)  } #endif
d6ac731998-04-20Henrik Grubbström (Grubba)  return add_ref(getmark(a));
c94c371996-03-28Fredrik Hübinette (Hubbe) }
b51e6d1998-02-18Fredrik Hübinette (Hubbe) 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); } }
25d21c1998-02-24Per Hedbor #ifdef DEBUG
b51e6d1998-02-18Fredrik Hübinette (Hubbe) void locate_references(void *a) { if(!in_gc) init_gc(); fprintf(stderr,"**Looking for references:\n"); check_for=a;
25d21c1998-02-24Per Hedbor 
b51e6d1998-02-18Fredrik Hübinette (Hubbe)  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(); }
25d21c1998-02-24Per Hedbor #endif
b51e6d1998-02-18Fredrik Hübinette (Hubbe) 
c94c371996-03-28Fredrik Hübinette (Hubbe) int gc_is_referenced(void *a) { struct marker *m; m=getmark(a); #ifdef DEBUG
8fb1e11998-04-05Fredrik Hübinette (Hubbe)  if(m->refs + m->xrefs > *(INT32 *)a || (!(m->refs < *(INT32 *)a) && m->xrefs) )
b8a6e71996-09-25Fredrik Hübinette (Hubbe)  {
1422411997-10-13Fredrik Hübinette (Hubbe)  INT32 refs=m->refs; INT32 xrefs=m->xrefs;
1ca3ba1997-10-13Fredrik Hübinette (Hubbe)  TYPE_T t=attempt_to_identify(a);
f6d0171997-10-15Fredrik Hübinette (Hubbe)  fprintf(stderr,"**Something has %ld references, while gc() found %ld + %ld external.\n",(long)*(INT32 *)a,(long)refs,(long)xrefs);
8fb1e11998-04-05Fredrik Hübinette (Hubbe)  describe_something(a, t, 1);
1ca3ba1997-10-13Fredrik Hübinette (Hubbe) 
b51e6d1998-02-18Fredrik Hübinette (Hubbe)  locate_references(a);
1422411997-10-13Fredrik Hübinette (Hubbe)  fatal("Ref counts are wrong (has %d, found %d + %d external)\n", *(INT32 *)a, refs, xrefs);
b8a6e71996-09-25Fredrik Hübinette (Hubbe)  }
c94c371996-03-28Fredrik Hübinette (Hubbe) #endif return m->refs < *(INT32 *)a; }
05c7cd1997-07-19Fredrik Hübinette (Hubbe) #ifdef DEBUG int gc_external_mark(void *a) { struct marker *m; if(check_for) { if(a==check_for) {
1ca3ba1997-10-13Fredrik Hübinette (Hubbe)  char *tmp=found_where;
199f9e1997-10-22Fredrik Hübinette (Hubbe)  found_where=" externally";
05c7cd1997-07-19Fredrik Hübinette (Hubbe)  gdb_gc_stop_here(a);
1ca3ba1997-10-13Fredrik Hübinette (Hubbe)  found_where=tmp;
05c7cd1997-07-19Fredrik Hübinette (Hubbe)  return 1; } return 0; } m=getmark(a); m->xrefs++; m->flags|=GC_XREFERENCED; gc_is_referenced(a); return 0; } #endif
c94c371996-03-28Fredrik Hübinette (Hubbe) int gc_mark(void *a) { struct marker *m; m=getmark(a); if(m->flags & GC_REFERENCED) { return 0; }else{ m->flags |= GC_REFERENCED; return 1; } } int gc_do_free(void *a) { struct marker *m; m=getmark(a);
8fb1e11998-04-05Fredrik Hübinette (Hubbe) #ifdef DEBUG if( !(m->flags & GC_REFERENCED) && m->flags & GC_XREFERENCED ) { INT32 refs=m->refs; INT32 xrefs=m->xrefs; TYPE_T t=attempt_to_identify(a); fprintf(stderr,"**gc_is_referenced failed, object has %ld references, while gc() found %ld + %ld external.\n",(long)*(INT32 *)a,(long)refs,(long)xrefs); describe_something(a, t, 1); locate_references(a); fatal("GC failed object (has %d, found %d + %d external)\n", *(INT32 *)a, refs, xrefs); } #endif
c94c371996-03-28Fredrik Hübinette (Hubbe)  return !(m->flags & GC_REFERENCED); }
be478c1997-08-30Henrik Grubbström (Grubba) void do_gc(void)
6930181996-02-25Fredrik Hübinette (Hubbe) { double tmp;
b51e6d1998-02-18Fredrik Hübinette (Hubbe)  INT32 tmp2;
dc296b1997-10-21Fredrik Hübinette (Hubbe)  double multiplier;
6930181996-02-25Fredrik Hübinette (Hubbe) 
890e5b1996-11-21Fredrik Hübinette (Hubbe)  if(in_gc) return; in_gc=1;
e78abd1996-11-21Fredrik Hübinette (Hubbe)  if(gc_evaluator_callback) { remove_callback(gc_evaluator_callback); gc_evaluator_callback=0; }
890e5b1996-11-21Fredrik Hübinette (Hubbe) 
6930181996-02-25Fredrik Hübinette (Hubbe)  tmp2=num_objects; #ifdef DEBUG if(t_flag) fprintf(stderr,"Garbage collecting ... ");
06983f1996-09-22Fredrik Hübinette (Hubbe)  if(num_objects < 0) fatal("Panic, less than zero objects!\n");
dc296b1997-10-21Fredrik Hübinette (Hubbe)  last_gc=TIME(0);
6930181996-02-25Fredrik Hübinette (Hubbe) #endif
dc296b1997-10-21Fredrik Hübinette (Hubbe)  multiplier=pow(MULTIPLIER, (double) num_allocs / (double) alloc_threshold); objects_alloced*=multiplier;
6930181996-02-25Fredrik Hübinette (Hubbe)  objects_alloced += (double) num_allocs;
dc296b1997-10-21Fredrik Hübinette (Hubbe)  objects_freed*=multiplier;
6930181996-02-25Fredrik Hübinette (Hubbe)  objects_freed += (double) num_objects;
c94c371996-03-28Fredrik Hübinette (Hubbe) 
b51e6d1998-02-18Fredrik Hübinette (Hubbe)  init_gc();
a991451997-07-08Fredrik Hübinette (Hubbe)  /* First we count internal references */
6930181996-02-25Fredrik Hübinette (Hubbe)  gc_check_all_arrays();
06983f1996-09-22Fredrik Hübinette (Hubbe)  gc_check_all_multisets();
c94c371996-03-28Fredrik Hübinette (Hubbe)  gc_check_all_mappings();
6930181996-02-25Fredrik Hübinette (Hubbe)  gc_check_all_programs(); gc_check_all_objects();
4a578f1997-01-27Fredrik Hübinette (Hubbe)  call_callback(& gc_callbacks, (void *)0);
c94c371996-03-28Fredrik Hübinette (Hubbe) 
a991451997-07-08Fredrik Hübinette (Hubbe)  /* Next we mark anything with external references */
c94c371996-03-28Fredrik Hübinette (Hubbe)  gc_mark_all_arrays();
991e5a1998-04-28Fredrik Hübinette (Hubbe)  run_queue(&gc_mark_queue);
06983f1996-09-22Fredrik Hübinette (Hubbe)  gc_mark_all_multisets();
991e5a1998-04-28Fredrik Hübinette (Hubbe)  run_queue(&gc_mark_queue);
c94c371996-03-28Fredrik Hübinette (Hubbe)  gc_mark_all_mappings();
991e5a1998-04-28Fredrik Hübinette (Hubbe)  run_queue(&gc_mark_queue);
c94c371996-03-28Fredrik Hübinette (Hubbe)  gc_mark_all_programs();
991e5a1998-04-28Fredrik Hübinette (Hubbe)  run_queue(&gc_mark_queue);
c94c371996-03-28Fredrik Hübinette (Hubbe)  gc_mark_all_objects();
991e5a1998-04-28Fredrik Hübinette (Hubbe)  run_queue(&gc_mark_queue);
c94c371996-03-28Fredrik Hübinette (Hubbe) 
4a578f1997-01-27Fredrik Hübinette (Hubbe)  if(d_flag) gc_mark_all_strings();
a991451997-07-08Fredrik Hübinette (Hubbe)  /* Now we free the unused stuff */
c94c371996-03-28Fredrik Hübinette (Hubbe)  gc_free_all_unreferenced_arrays();
06983f1996-09-22Fredrik Hübinette (Hubbe)  gc_free_all_unreferenced_multisets();
c94c371996-03-28Fredrik Hübinette (Hubbe)  gc_free_all_unreferenced_mappings(); gc_free_all_unreferenced_programs(); gc_free_all_unreferenced_objects();
b51e6d1998-02-18Fredrik Hübinette (Hubbe)  exit_gc();
06983f1996-09-22Fredrik Hübinette (Hubbe)  destruct_objects_to_destruct();
6930181996-02-25Fredrik Hübinette (Hubbe)  objects_freed -= (double) num_objects; tmp=(double)num_objects; tmp=tmp * GC_CONST/100.0 * (objects_alloced+1.0) / (objects_freed+1.0); if((int)tmp < alloc_threshold + num_allocs) { alloc_threshold=(int)tmp; }else{ alloc_threshold+=num_allocs; } if(alloc_threshold < MIN_ALLOC_THRESHOLD) alloc_threshold = MIN_ALLOC_THRESHOLD;
b95bef1996-03-29Fredrik Hübinette (Hubbe)  if(alloc_threshold > MAX_ALLOC_THRESHOLD) alloc_threshold = MAX_ALLOC_THRESHOLD;
6930181996-02-25Fredrik Hübinette (Hubbe)  num_allocs=0; #ifdef DEBUG if(t_flag) fprintf(stderr,"done (freed %ld of %ld objects).\n", (long)(tmp2-num_objects),(long)tmp2); #endif
a29e021996-10-15Fredrik Hübinette (Hubbe) 
bf45771996-12-05Fredrik Hübinette (Hubbe) #ifdef ALWAYS_GC
890e5b1996-11-21Fredrik Hübinette (Hubbe)  ADD_GC_CALLBACK(); #else
bf45771996-12-05Fredrik Hübinette (Hubbe)  if(d_flag > 3) ADD_GC_CALLBACK();
a29e021996-10-15Fredrik Hübinette (Hubbe) #endif
890e5b1996-11-21Fredrik Hübinette (Hubbe)  in_gc=0;
6930181996-02-25Fredrik Hübinette (Hubbe) }