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. \*/
3741091999-09-25Henrik Grubbström (Grubba) /**/
6930181996-02-25Fredrik Hübinette (Hubbe) #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"
2eeba91999-03-17Fredrik Hübinette (Hubbe) #include "constants.h"
1637c42000-02-01Fredrik Hübinette (Hubbe) #include "interpret.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) 
3741091999-09-25Henrik Grubbström (Grubba) #include "block_alloc.h"
e942a72000-04-15Fredrik Hübinette (Hubbe) RCSID("$Id: gc.c,v 1.67 2000/04/15 07:45:52 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;
6bc62b2000-04-14Martin Stjernholm int Pike_in_gc = 0;
8ea2061998-04-29Fredrik Noring struct pike_queue gc_mark_queue;
4452c12000-02-02Fredrik Hübinette (Hubbe) time_t last_gc;
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;
424d9c1999-05-02Fredrik Hübinette (Hubbe) struct callback *debug_add_gc_callback(callback_func call,
4a578f1997-01-27Fredrik Hübinette (Hubbe)  void *arg, callback_func free_func) { return add_to_callback(&gc_callbacks, call, arg, free_func); }
c94c371996-03-28Fredrik Hübinette (Hubbe) 
424d9c1999-05-02Fredrik Hübinette (Hubbe) #undef INIT_BLOCK
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
e942a72000-04-15Fredrik Hübinette (Hubbe) #define INIT_BLOCK(X) (X)->flags=(X)->refs=(X)->xrefs=0; (X)->saved_refs=-1;
424d9c1999-05-02Fredrik Hübinette (Hubbe) #else #define INIT_BLOCK(X) (X)->flags=(X)->refs=0
05c7cd1997-07-19Fredrik Hübinette (Hubbe) #endif
c94c371996-03-28Fredrik Hübinette (Hubbe) 
424d9c1999-05-02Fredrik Hübinette (Hubbe) PTR_HASH_ALLOC(marker,MARKER_CHUNK_SIZE)
c94c371996-03-28Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
1ca3ba1997-10-13Fredrik Hübinette (Hubbe) 
dc296b1997-10-21Fredrik Hübinette (Hubbe) 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);
6bc62b2000-04-14Martin Stjernholm  fprintf(stderr,"in_gc : %d\n", Pike_in_gc);
dc296b1997-10-21Fredrik Hübinette (Hubbe) }
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; }
20513c2000-04-12Fredrik Hübinette (Hubbe) 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;
ad2bdb2000-04-12Fredrik Hübinette (Hubbe) static char *fatal_after_gc=0;
a4033e2000-04-14Fredrik Hübinette (Hubbe) #define DESCRIBE_MEM 1 #define DESCRIBE_NO_REFS 2 #define DESCRIBE_SHORT 4 #define DESCRIBE_NO_DMALLOC 8
ad2bdb2000-04-12Fredrik Hübinette (Hubbe) 
a4033e2000-04-14Fredrik Hübinette (Hubbe) /* type == -1 means that memblock is a char* and should be * really be printed.. */ void describe_location(void *real_memblock, int real_type, void *location, int indent, int depth, int flags)
3568101997-10-16Fredrik Hübinette (Hubbe) {
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  struct program *p;
a4033e2000-04-14Fredrik Hübinette (Hubbe)  void *memblock=0; int type=real_type;
4694111997-11-07Fredrik Hübinette (Hubbe)  if(!location) return;
1e4e5f2000-04-07Fredrik Hübinette (Hubbe) /* fprintf(stderr,"**Location of (short) svalue: %p\n",location); */
62971d1998-01-19Fredrik Hübinette (Hubbe) 
a4033e2000-04-14Fredrik Hübinette (Hubbe)  if(real_type!=-1) real_memblock=memblock;
20513c2000-04-12Fredrik Hübinette (Hubbe) #ifdef DEBUG_MALLOC if(memblock == 0 || type == -1) { extern void *dmalloc_find_memblock_base(void *); memblock=dmalloc_find_memblock_base(location); } #endif
a4033e2000-04-14Fredrik Hübinette (Hubbe)  if(type==T_UNKNOWN) type=attempt_to_identify(memblock);
20513c2000-04-12Fredrik Hübinette (Hubbe)  if(memblock)
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s-> from %s %p offset %ld\n", indent,"",
20513c2000-04-12Fredrik Hübinette (Hubbe)  get_name_of_type(type), memblock, ((long)location - (long)memblock)); else
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s-> at location %p in unknown memblock (mmaped?)\n", indent,"",
20513c2000-04-12Fredrik Hübinette (Hubbe)  location);
a4033e2000-04-14Fredrik Hübinette (Hubbe)  if(memblock && depth>0) describe_something(memblock,type,indent+2,depth-1,flags | DESCRIBE_MEM);
20513c2000-04-12Fredrik Hübinette (Hubbe) 
a4033e2000-04-14Fredrik Hübinette (Hubbe)  again:
62971d1998-01-19Fredrik Hübinette (Hubbe)  switch(type)
3568101997-10-16Fredrik Hübinette (Hubbe)  {
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  case T_UNKNOWN: for(p=first_program;p;p=p->next) { if(memblock == (void *)p->program) {
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s **In memory block for program at %p\n", indent,"", p);
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  memblock=p; type=T_PROGRAM;
a4033e2000-04-14Fredrik Hübinette (Hubbe)  goto again;
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  } } break;
0b69441998-01-19Fredrik Hübinette (Hubbe)  case T_PROGRAM: {
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  long e;
0b69441998-01-19Fredrik Hübinette (Hubbe)  char *ptr=(char *)location;
a4033e2000-04-14Fredrik Hübinette (Hubbe)  p=(struct program *)memblock;
0b69441998-01-19Fredrik Hübinette (Hubbe) 
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  if(location == (void *)&p->prev)
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s **In p->prev\n",indent,"");
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  if(location == (void *)&p->next)
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s **In p->next\n",indent,"");
1e4e5f2000-04-07Fredrik Hübinette (Hubbe) 
a4033e2000-04-14Fredrik Hübinette (Hubbe)  if(p->inherits && ptr >= (char *)p->inherits && ptr<(char*)(p->inherits+p->num_inherits))
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  { e=((long)ptr - (long)(p->inherits)) / sizeof(struct inherit);
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s **In p->inherits[%ld] (%s)\n",indent,"",
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  e, p->inherits[e].name ? p->inherits[e].name->str : "no name"); return; }
a4033e2000-04-14Fredrik Hübinette (Hubbe)  if(p->constants && ptr >= (char *)p->constants && ptr<(char*)(p->constants+p->num_constants))
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  { e=((long)ptr - (long)(p->constants)) / sizeof(struct program_constant);
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s **In p->constants[%ld] (%s)\n",indent,"",
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  e, p->constants[e].name ? p->constants[e].name->str : "no name"); return; }
0b69441998-01-19Fredrik Hübinette (Hubbe) 
a4033e2000-04-14Fredrik Hübinette (Hubbe)  if(p->identifiers && ptr >= (char *)p->identifiers && ptr<(char*)(p->identifiers+p->num_identifiers))
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  { e=((long)ptr - (long)(p->identifiers)) / sizeof(struct identifier);
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s **In p->identifiers[%ld] (%s)\n",indent,"",
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  e,
a4033e2000-04-14Fredrik Hübinette (Hubbe)  p->identifiers[e].name ? p->identifiers[e].name->str : "no name");
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  return; } #define FOO(NTYP,TYP,NAME) \
a4033e2000-04-14Fredrik Hübinette (Hubbe)  if(location == (void *)&p->NAME) fprintf(stderr,"%*s **In p->" #NAME "\n",indent,""); \
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  if(ptr >= (char *)p->NAME && ptr<(char*)(p->NAME+p->PIKE_CONCAT(num_,NAME))) \
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s **In p->" #NAME "[%ld]\n",indent,"",((long)ptr - (long)(p->NAME)) / sizeof(TYP));
1e4e5f2000-04-07Fredrik Hübinette (Hubbe) #include "program_areas.h"
0b69441998-01-19Fredrik Hübinette (Hubbe)  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;
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  struct program *p;
a4033e2000-04-14Fredrik Hübinette (Hubbe)  if(location == (void *)&o->parent) fprintf(stderr,"%*s **In o->parent\n",indent,""); if(location == (void *)&o->prog) fprintf(stderr,"%*s **In o->prog\n",indent,""); if(location == (void *)&o->next) fprintf(stderr,"%*s **In o->next\n",indent,""); if(location == (void *)&o->prev) fprintf(stderr,"%*s **In o->prev\n",indent,"");
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  p=o->prog; if(!o->prog) { p=id_to_program(o->program_id); if(p)
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s **(We are lucky, found program for destructed object)\n",indent,"");
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  } if(p)
3568101997-10-16Fredrik Hübinette (Hubbe)  {
62971d1998-01-19Fredrik Hübinette (Hubbe)  INT32 e,d;
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  for(e=0;e<(INT32)p->num_inherits;e++)
3568101997-10-16Fredrik Hübinette (Hubbe)  {
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  struct inherit tmp=p->inherits[e];
62971d1998-01-19Fredrik Hübinette (Hubbe)  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)) {
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s **In variable %s\n",indent,"",id->name->str);
62971d1998-01-19Fredrik Hübinette (Hubbe)  }
3568101997-10-16Fredrik Hübinette (Hubbe)  }
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  if((char *)location >= base && (char *)location <= base + ( tmp.prog->storage_needed - tmp.prog->inherits[0].storage_offset )) {
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s **In storage for inherit %d",indent,"",e);
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  if(tmp.name) fprintf(stderr," (%s)",tmp.name->str); fprintf(stderr,"\n"); }
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;
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s **In index %ld\n",indent,"",(long)(s-ITEM(a)));
62971d1998-01-19Fredrik Hübinette (Hubbe)  return; }
3568101997-10-16Fredrik Hübinette (Hubbe)  } }
b8a6e71996-09-25Fredrik Hübinette (Hubbe) static void gdb_gc_stop_here(void *a) {
20513c2000-04-12Fredrik Hübinette (Hubbe)  fprintf(stderr,"***One ref found%s.\n",found_where?found_where:"");
a4033e2000-04-14Fredrik Hübinette (Hubbe)  describe_something(found_in, found_in_type, 2, 1, DESCRIBE_NO_DMALLOC); describe_location(found_in , found_in_type, gc_svalue_location,2,1,0);
20513c2000-04-12Fredrik Hübinette (Hubbe)  fprintf(stderr,"----------end------------\n");
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; }
a4033e2000-04-14Fredrik Hübinette (Hubbe) void low_describe_something(void *a, int t, int indent, int depth, int flags)
f6d0171997-10-15Fredrik Hübinette (Hubbe) { struct program *p=(struct program *)a;
a4033e2000-04-14Fredrik Hübinette (Hubbe)  if(depth<0) return;
f6d0171997-10-15Fredrik Hübinette (Hubbe)  switch(t) {
2eeba91999-03-17Fredrik Hübinette (Hubbe)  case T_FUNCTION: if(attempt_to_identify(a) != T_OBJECT) {
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s**Builtin function!\n",indent,"");
2eeba91999-03-17Fredrik Hübinette (Hubbe)  break; }
f6d0171997-10-15Fredrik Hübinette (Hubbe)  case T_OBJECT: p=((struct object *)a)->prog;
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s**Parent identifier: %d\n",indent,"",((struct object *)a)->parent_identifier); fprintf(stderr,"%*s**Program id: %ld\n",indent,"",((struct object *)a)->program_id);
1e4e5f2000-04-07Fredrik Hübinette (Hubbe) 
8fb1e11998-04-05Fredrik Hübinette (Hubbe)  if( ((struct object *)a)->parent) {
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s**Describing object's parent:\n",indent,""); describe_something( ((struct object *)a)->parent, t, indent+2,depth-1, (flags | DESCRIBE_SHORT | DESCRIBE_NO_REFS ) & ~ (DESCRIBE_MEM));
8fb1e11998-04-05Fredrik Hübinette (Hubbe)  }else{
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s**There is no parent (any longer?)\n",indent,"");
8fb1e11998-04-05Fredrik Hübinette (Hubbe)  }
f6d0171997-10-15Fredrik Hübinette (Hubbe)  if(!p) {
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s**The object is destructed.\n",indent,"");
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  p=id_to_program(((struct object *)a)->program_id); if(!p) break;
f6d0171997-10-15Fredrik Hübinette (Hubbe)  }
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s**Attempting to describe program object was instantiated from:\n",indent,"");
f6d0171997-10-15Fredrik Hübinette (Hubbe)  case T_PROGRAM:
3568101997-10-16Fredrik Hübinette (Hubbe)  { char *tmp; INT32 line,pos;
2eeba91999-03-17Fredrik Hübinette (Hubbe)  int foo=0;
3568101997-10-16Fredrik Hübinette (Hubbe) 
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s**Program id: %ld\n",indent,"",(long)(p->id));
05590d1998-04-23Fredrik Hübinette (Hubbe)  if(p->flags & PROGRAM_HAS_C_METHODS)
f6d0171997-10-15Fredrik Hübinette (Hubbe)  {
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s**The program was written in C.\n",indent,"");
f6d0171997-10-15Fredrik Hübinette (Hubbe)  }
2eeba91999-03-17Fredrik Hübinette (Hubbe)  for(pos=0;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) {
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s**Location: %s:%ld\n",indent,"",tmp,(long)line);
2eeba91999-03-17Fredrik Hübinette (Hubbe)  foo=1;
3568101997-10-16Fredrik Hübinette (Hubbe)  break; }
2eeba91999-03-17Fredrik Hübinette (Hubbe)  if(pos+1>=(long)p->num_program) break; } #if 0 if(!foo && p->num_linenumbers>1 && EXTRACT_UCHAR(p->linenumbers)=='\177') {
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s**From file: %s\n",indent,"",p->linenumbers+1);
2eeba91999-03-17Fredrik Hübinette (Hubbe)  foo=1; } #endif if(!foo) { int e;
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s**identifiers:\n",indent,"");
2eeba91999-03-17Fredrik Hübinette (Hubbe)  for(e=0;e<p->num_identifier_references;e++)
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s**** %s\n",indent,"",ID_FROM_INT(p,e)->name->str);
2eeba91999-03-17Fredrik Hübinette (Hubbe) 
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s**num inherits: %d\n",indent,"",p->num_inherits);
f6d0171997-10-15Fredrik Hübinette (Hubbe)  }
a4033e2000-04-14Fredrik Hübinette (Hubbe)  if(flags & DESCRIBE_MEM) {
1e4e5f2000-04-07Fredrik Hübinette (Hubbe) #define FOO(NUMTYPE,TYPE,NAME) \
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s* " #NAME " %p[%d]\n",indent,"",p->NAME,p->PIKE_CONCAT(num_,NAME));
1e4e5f2000-04-07Fredrik Hübinette (Hubbe) #include "program_areas.h"
a4033e2000-04-14Fredrik Hübinette (Hubbe)  }
2eeba91999-03-17Fredrik Hübinette (Hubbe) 
f6d0171997-10-15Fredrik Hübinette (Hubbe)  break;
3568101997-10-16Fredrik Hübinette (Hubbe)  }
f6d0171997-10-15Fredrik Hübinette (Hubbe)  case T_ARRAY:
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s**Describing array:\n",indent,"");
f6d0171997-10-15Fredrik Hübinette (Hubbe)  debug_dump_array((struct array *)a); break;
62971d1998-01-19Fredrik Hübinette (Hubbe) 
61e9a01998-01-25Fredrik Hübinette (Hubbe)  case T_MAPPING:
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s**Describing mapping:\n",indent,"");
1d152d2000-03-07Fredrik Hübinette (Hubbe)  debug_dump_mapping((struct mapping *)a);
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s**Describing mapping data block:\n",indent,""); describe_something( ((struct mapping *)a)->data, -2, indent+2,depth-1,flags);
61e9a01998-01-25Fredrik Hübinette (Hubbe)  break;
62971d1998-01-19Fredrik Hübinette (Hubbe)  case T_STRING: { struct pike_string *s=(struct pike_string *)a;
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s**String length is %d:\n",indent,"",s->len);
62971d1998-01-19Fredrik Hübinette (Hubbe)  if(s->len>77) {
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s** \"%60s ...\"\n",indent,"",s->str);
62971d1998-01-19Fredrik Hübinette (Hubbe)  }else{
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s** \"%s\"\n",indent,"",s->str);
62971d1998-01-19Fredrik Hübinette (Hubbe)  } break; }
f6d0171997-10-15Fredrik Hübinette (Hubbe)  }
25479a2000-03-07Fredrik Hübinette (Hubbe) }
a4033e2000-04-14Fredrik Hübinette (Hubbe) void describe_something(void *a, int t, int indent, int depth, int flags)
25479a2000-03-07Fredrik Hübinette (Hubbe) { struct program *p=(struct program *)a; if(!a) return; if(t==-1) {
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s**Location description: %s\n",indent,"",(char *)a);
25479a2000-03-07Fredrik Hübinette (Hubbe)  return; }
3845452000-03-08Henrik Grubbström (Grubba) #ifdef DEBUG_MALLOC if (((int)a) == 0x55555555) {
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s**Location: %p Type: %s Zapped pointer\n",indent,"",a,
3845452000-03-08Henrik Grubbström (Grubba)  get_name_of_type(t)); } else #endif /* DEBUG_MALLOC */ if (((int)a) & 3) {
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s**Location: %p Type: %s Missaligned address\n",indent,"",a,
3845452000-03-08Henrik Grubbström (Grubba)  get_name_of_type(t)); } else {
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s**Location: %p Type: %s Refs: %d\n",indent,"",a,
3845452000-03-08Henrik Grubbström (Grubba)  get_name_of_type(t), *(INT32 *)a); }
25479a2000-03-07Fredrik Hübinette (Hubbe) 
a4033e2000-04-14Fredrik Hübinette (Hubbe)  low_describe_something(a,t,indent,depth,flags);
25479a2000-03-07Fredrik Hübinette (Hubbe)  #ifdef DEBUG_MALLOC
a4033e2000-04-14Fredrik Hübinette (Hubbe)  if(!(flags & DESCRIBE_NO_DMALLOC)) debug_malloc_dump_references(a,indent+2,depth-1,flags);
25479a2000-03-07Fredrik Hübinette (Hubbe) #endif
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"%*s*******************\n",indent,"");
8fb1e11998-04-05Fredrik Hübinette (Hubbe) } void describe(void *x) {
a4033e2000-04-14Fredrik Hübinette (Hubbe)  describe_something(x, attempt_to_identify(x), 0, 2, 0);
f6d0171997-10-15Fredrik Hübinette (Hubbe) }
c72a4e1998-12-15Fredrik Hübinette (Hubbe) void debug_describe_svalue(struct svalue *s) { fprintf(stderr,"Svalue at %p is:\n",s); switch(s->type) { case T_INT: fprintf(stderr," %ld\n",(long)s->u.integer); break; case T_FLOAT: fprintf(stderr," %f\n",s->u.float_number); break;
2eeba91999-03-17Fredrik Hübinette (Hubbe)  case T_FUNCTION: if(s->subtype == FUNCTION_BUILTIN) { fprintf(stderr," Builtin function: %s\n",s->u.efun->name->str); }else{ if(!s->u.object->prog) {
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  struct program *p=id_to_program(s->u.object->program_id); if(p) { fprintf(stderr," Function (destructed) name: %s\n",ID_FROM_INT(p,s->subtype)->name->str); }else{ fprintf(stderr," Function in destructed object.\n"); }
2eeba91999-03-17Fredrik Hübinette (Hubbe)  }else{ fprintf(stderr," Function name: %s\n",ID_FROM_INT(s->u.object->prog,s->subtype)->name->str); } }
c72a4e1998-12-15Fredrik Hübinette (Hubbe)  }
a4033e2000-04-14Fredrik Hübinette (Hubbe)  describe_something(s->u.refs,s->type,0,2,0);
c72a4e1998-12-15Fredrik Hübinette (Hubbe) }
b8a6e71996-09-25Fredrik Hübinette (Hubbe) #endif
1e4e5f2000-04-07Fredrik Hübinette (Hubbe) INT32 real_gc_check(void *a)
c94c371996-03-28Fredrik Hübinette (Hubbe) {
e09ea12000-04-13Fredrik Hübinette (Hubbe)  struct marker *m=get_marker(a);
e942a72000-04-15Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
b8a6e71996-09-25Fredrik Hübinette (Hubbe)  if(check_for) { if(check_for == a) { gdb_gc_stop_here(a); }
20513c2000-04-12Fredrik Hübinette (Hubbe)  if(check_for == (void *)1 && gc_do_free(a)) {
ad2bdb2000-04-12Fredrik Hübinette (Hubbe)  struct marker *m=get_marker(a);
5f61da2000-04-13Fredrik Hübinette (Hubbe)  int t=attempt_to_identify(a); if(t != T_STRING && t != T_UNKNOWN) { fprintf(stderr,"**Reference to object to free in referenced object!\n"); fprintf(stderr," has %ld references, while gc() found %ld + %ld external.\n",(long)*(INT32 *)a,(long)m->refs,(long)m->xrefs); describe(a); locate_references(a); fprintf(stderr,"##### Continuing search for more bugs....\n"); fatal_after_gc="Reference to object to free in referenced object!\n"; }
20513c2000-04-12Fredrik Hübinette (Hubbe)  }
4a578f1997-01-27Fredrik Hübinette (Hubbe)  return 0;
b8a6e71996-09-25Fredrik Hübinette (Hubbe)  }
e942a72000-04-15Fredrik Hübinette (Hubbe)  m->saved_refs = *(INT32 *)a;
b8a6e71996-09-25Fredrik Hübinette (Hubbe) #endif
e942a72000-04-15Fredrik Hübinette (Hubbe) 
3825ec2000-04-14Martin Stjernholm  m->flags |= GC_CHECKED;
e09ea12000-04-13Fredrik Hübinette (Hubbe)  return add_ref(m);
c94c371996-03-28Fredrik Hübinette (Hubbe) }
b51e6d1998-02-18Fredrik Hübinette (Hubbe) static void init_gc(void) {
424d9c1999-05-02Fredrik Hübinette (Hubbe) #if 0
b51e6d1998-02-18Fredrik Hübinette (Hubbe)  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;
424d9c1999-05-02Fredrik Hübinette (Hubbe) #else
1637c42000-02-01Fredrik Hübinette (Hubbe) /* init_marker_hash(num_objects*8); */
424d9c1999-05-02Fredrik Hübinette (Hubbe)  init_marker_hash(); #endif
b51e6d1998-02-18Fredrik Hübinette (Hubbe) } static void exit_gc(void) {
424d9c1999-05-02Fredrik Hübinette (Hubbe) #if 0
b51e6d1998-02-18Fredrik Hübinette (Hubbe)  struct marker_chunk *m; /* Free hash table */ free((char *)hash); while((m=chunk)) { chunk=m->next; free((char *)m); }
424d9c1999-05-02Fredrik Hübinette (Hubbe) #else #ifdef DO_PIKE_CLEANUP int e=0; struct marker *h; for(e=0;e<marker_hash_table_size;e++) while(marker_hash_table[e]) remove_marker(marker_hash_table[e]->data); #endif exit_marker_hash(); #endif
b51e6d1998-02-18Fredrik Hübinette (Hubbe) }
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
b51e6d1998-02-18Fredrik Hübinette (Hubbe) void locate_references(void *a) {
6bc62b2000-04-14Martin Stjernholm  if(!Pike_in_gc)
b51e6d1998-02-18Fredrik Hübinette (Hubbe)  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();
20513c2000-04-12Fredrik Hübinette (Hubbe)  #ifdef PIKE_DEBUG if(master_object) gc_external_mark2(master_object,0," &master_object");
5f61da2000-04-13Fredrik Hübinette (Hubbe)  { extern struct mapping *builtin_constants; if(builtin_constants) gc_external_mark2(builtin_constants,0," &builtin_constants"); }
20513c2000-04-12Fredrik Hübinette (Hubbe) #endif
b51e6d1998-02-18Fredrik Hübinette (Hubbe)  found_where=" in a module"; call_callback(& gc_callbacks, (void *)0); found_where=""; check_for=0;
20513c2000-04-12Fredrik Hübinette (Hubbe)  #ifdef DEBUG_MALLOC { extern void dmalloc_find_references_to(void *); #if 0 fprintf(stderr,"**DMALLOC Looking for references:\n"); dmalloc_find_references_to(a); #endif } #endif
b51e6d1998-02-18Fredrik Hübinette (Hubbe) 
6bc62b2000-04-14Martin Stjernholm  if(!Pike_in_gc)
b51e6d1998-02-18Fredrik Hübinette (Hubbe)  exit_gc(); }
25d21c1998-02-24Per Hedbor #endif
b51e6d1998-02-18Fredrik Hübinette (Hubbe) 
1637c42000-02-01Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG int debug_gc_is_referenced(void *a)
c94c371996-03-28Fredrik Hübinette (Hubbe) { struct marker *m;
424d9c1999-05-02Fredrik Hübinette (Hubbe)  m=get_marker(a);
1637c42000-02-01Fredrik Hübinette (Hubbe) 
8fb1e11998-04-05Fredrik Hübinette (Hubbe)  if(m->refs + m->xrefs > *(INT32 *)a ||
e942a72000-04-15Fredrik Hübinette (Hubbe)  (!(m->refs < *(INT32 *)a) && m->xrefs) || (Pike_in_gc < 3 && m->saved_refs != -1 && m->saved_refs != *(INT32 *)a))
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);
20513c2000-04-12Fredrik Hübinette (Hubbe)  d_flag=0;
1ca3ba1997-10-13Fredrik Hübinette (Hubbe) 
e942a72000-04-15Fredrik Hübinette (Hubbe)  fprintf(stderr,"**Something has %ld refs, while gc() found %ld + %ld external.\n", (long)*(INT32 *)a, (long)refs, (long)xrefs); if(m->saved_refs != *(INT32 *)a) fprintf(stderr,"**In pass one it had %ld refs!!!\n",m->saved_refs);
a4033e2000-04-14Fredrik Hübinette (Hubbe)  describe_something(a, t, 0,2,0);
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)  }
1637c42000-02-01Fredrik Hübinette (Hubbe) 
c94c371996-03-28Fredrik Hübinette (Hubbe)  return m->refs < *(INT32 *)a; }
1637c42000-02-01Fredrik Hübinette (Hubbe) #endif
c94c371996-03-28Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
20513c2000-04-12Fredrik Hübinette (Hubbe) int gc_external_mark3(void *a, void *in, char *where)
05c7cd1997-07-19Fredrik Hübinette (Hubbe) { struct marker *m; if(check_for) { if(a==check_for) {
1ca3ba1997-10-13Fredrik Hübinette (Hubbe)  char *tmp=found_where;
20513c2000-04-12Fredrik Hübinette (Hubbe)  void *tmp2=found_in; if(where) found_where=where; if(in) found_in=in;
05c7cd1997-07-19Fredrik Hübinette (Hubbe)  gdb_gc_stop_here(a);
20513c2000-04-12Fredrik Hübinette (Hubbe) 
1ca3ba1997-10-13Fredrik Hübinette (Hubbe)  found_where=tmp;
20513c2000-04-12Fredrik Hübinette (Hubbe)  found_in=tmp2;
05c7cd1997-07-19Fredrik Hübinette (Hubbe)  return 1; }
ad2bdb2000-04-12Fredrik Hübinette (Hubbe)  if(check_for == (void *)1 && gc_do_free(a)) { struct marker *m=get_marker(a);
5f61da2000-04-13Fredrik Hübinette (Hubbe)  int t=attempt_to_identify(a); if(t != T_STRING && t != T_UNKNOWN) {
6bc62b2000-04-14Martin Stjernholm  fprintf(stderr,"EXTERNAL Reference to object to free%s!\n",in?(char *)in:"");
5f61da2000-04-13Fredrik Hübinette (Hubbe)  fprintf(stderr," has %ld references, while gc() found %ld + %ld external.\n",(long)*(INT32 *)a,(long)m->refs,(long)m->xrefs);
a4033e2000-04-14Fredrik Hübinette (Hubbe)  if(where) describe_location(0,T_UNKNOWN,where,4,1,0);
5f61da2000-04-13Fredrik Hübinette (Hubbe)  describe(a); locate_references(a); fprintf(stderr,"##### Continuing search for more bugs....\n"); fatal_after_gc="EXTERNAL Reference to object to free.\n"; }
ad2bdb2000-04-12Fredrik Hübinette (Hubbe)  }
05c7cd1997-07-19Fredrik Hübinette (Hubbe)  return 0; }
424d9c1999-05-02Fredrik Hübinette (Hubbe)  m=get_marker(a);
05c7cd1997-07-19Fredrik Hübinette (Hubbe)  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;
11649a2000-04-14Henrik Grubbström (Grubba)  m=get_marker(debug_malloc_pass(a));
c94c371996-03-28Fredrik Hübinette (Hubbe)  if(m->flags & GC_REFERENCED) { return 0; }else{ m->flags |= GC_REFERENCED; return 1; } }
1637c42000-02-01Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG int debug_gc_do_free(void *a)
c94c371996-03-28Fredrik Hübinette (Hubbe) { struct marker *m;
11649a2000-04-14Henrik Grubbström (Grubba)  m=get_marker(debug_malloc_pass(a));
1637c42000-02-01Fredrik Hübinette (Hubbe) 
db62dc2000-04-14Martin Stjernholm  if( (m->flags & (GC_REFERENCED|GC_CHECKED)) == GC_CHECKED && (m->flags & GC_XREFERENCED) )
8fb1e11998-04-05Fredrik Hübinette (Hubbe)  { INT32 refs=m->refs; INT32 xrefs=m->xrefs; TYPE_T t=attempt_to_identify(a);
5f61da2000-04-13Fredrik Hübinette (Hubbe)  if(t != T_STRING && t != T_UNKNOWN) {
11649a2000-04-14Henrik Grubbström (Grubba)  fprintf(stderr, "**gc_is_referenced failed, object has %ld references,\n"
e09ea12000-04-13Fredrik Hübinette (Hubbe)  "** while gc() found %ld + %ld external. (type=%d, flags=%d)\n", (long)*(INT32 *)a,(long)refs,(long)xrefs,t,m->flags);
a4033e2000-04-14Fredrik Hübinette (Hubbe)  describe_something(a, t, 4,1,0);
8fb1e11998-04-05Fredrik Hübinette (Hubbe) 
5f61da2000-04-13Fredrik Hübinette (Hubbe)  locate_references(a); fatal("GC failed object (has %d, found %d + %d external)\n", *(INT32 *)a, refs, xrefs); }
8fb1e11998-04-05Fredrik Hübinette (Hubbe)  }
1637c42000-02-01Fredrik Hübinette (Hubbe) 
3825ec2000-04-14Martin Stjernholm  return (m->flags & (GC_REFERENCED|GC_CHECKED)) == GC_CHECKED;
c94c371996-03-28Fredrik Hübinette (Hubbe) }
1637c42000-02-01Fredrik Hübinette (Hubbe) #endif
c94c371996-03-28Fredrik Hübinette (Hubbe) 
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;
a4033e2000-04-14Fredrik Hübinette (Hubbe) #ifdef HAVE_GETHRTIME
db62dc2000-04-14Martin Stjernholm #ifdef PIKE_DEBUG
6bc62b2000-04-14Martin Stjernholm  hrtime_t gcstarttime;
b088ab2000-04-15Martin Stjernholm #endif
db62dc2000-04-14Martin Stjernholm #endif
6930181996-02-25Fredrik Hübinette (Hubbe) 
6bc62b2000-04-14Martin Stjernholm  if(Pike_in_gc) return; Pike_in_gc=1;
890e5b1996-11-21Fredrik Hübinette (Hubbe) 
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;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
6bc62b2000-04-14Martin Stjernholm  if(t_flag) {
6930181996-02-25Fredrik Hübinette (Hubbe)  fprintf(stderr,"Garbage collecting ... ");
b088ab2000-04-15Martin Stjernholm #ifdef HAVE_GETHRTIME
6bc62b2000-04-14Martin Stjernholm  gcstarttime = gethrtime();
b088ab2000-04-15Martin Stjernholm #endif
6bc62b2000-04-14Martin Stjernholm  }
06983f1996-09-22Fredrik Hübinette (Hubbe)  if(num_objects < 0) fatal("Panic, less than zero objects!\n");
6930181996-02-25Fredrik Hübinette (Hubbe) #endif
4452c12000-02-02Fredrik Hübinette (Hubbe)  last_gc=TIME(0);
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();
20513c2000-04-12Fredrik Hübinette (Hubbe)  #ifdef PIKE_DEBUG if(master_object) gc_external_mark2(master_object,0," &master_object");
5f61da2000-04-13Fredrik Hübinette (Hubbe)  { extern struct mapping *builtin_constants; if(builtin_constants) gc_external_mark2(builtin_constants,0," &builtin_constants"); }
20513c2000-04-12Fredrik Hübinette (Hubbe) #endif
5fbe6e2000-04-14Fredrik Hübinette (Hubbe)  /* These callbacks are mainly for pass 1, but can also * do things that are normally associated with pass 2 */
4a578f1997-01-27Fredrik Hübinette (Hubbe)  call_callback(& gc_callbacks, (void *)0);
c94c371996-03-28Fredrik Hübinette (Hubbe) 
5fbe6e2000-04-14Fredrik Hübinette (Hubbe)  Pike_in_gc=2;
20513c2000-04-12Fredrik 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();
20513c2000-04-12Fredrik Hübinette (Hubbe)  #ifdef PIKE_DEBUG check_for=(void *)1; #endif
5fbe6e2000-04-14Fredrik Hübinette (Hubbe)  Pike_in_gc=3;
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();
20513c2000-04-12Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
ad2bdb2000-04-12Fredrik Hübinette (Hubbe) 
20513c2000-04-12Fredrik Hübinette (Hubbe)  check_for=0;
ad2bdb2000-04-12Fredrik Hübinette (Hubbe)  if(fatal_after_gc) fatal(fatal_after_gc);
20513c2000-04-12Fredrik Hübinette (Hubbe) #endif
b51e6d1998-02-18Fredrik Hübinette (Hubbe)  exit_gc();
06983f1996-09-22Fredrik Hübinette (Hubbe) 
a4033e2000-04-14Fredrik Hübinette (Hubbe)  Pike_in_gc=5;
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;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
6930181996-02-25Fredrik Hübinette (Hubbe)  if(t_flag)
a4033e2000-04-14Fredrik Hübinette (Hubbe)  { #ifdef HAVE_GETHRTIME
6bc62b2000-04-14Martin Stjernholm  fprintf(stderr,"done (freed %ld of %ld objects), %ld ms.\n", (long)(tmp2-num_objects),(long)tmp2,
a4033e2000-04-14Fredrik Hübinette (Hubbe)  (long)((gethrtime() - gcstarttime)/1000000));
b088ab2000-04-15Martin Stjernholm #else
a4033e2000-04-14Fredrik Hübinette (Hubbe)  fprintf(stderr,"done (freed %ld of %ld objects)\n", (long)(tmp2-num_objects),(long)tmp2);
b088ab2000-04-15Martin Stjernholm #endif
a4033e2000-04-14Fredrik Hübinette (Hubbe)  }
6930181996-02-25Fredrik Hübinette (Hubbe) #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
6bc62b2000-04-14Martin Stjernholm  Pike_in_gc=0;
6930181996-02-25Fredrik Hübinette (Hubbe) }
1637c42000-02-01Fredrik Hübinette (Hubbe) void f__gc_status(INT32 args) { pop_n_elems(args); push_constant_text("num_objects"); push_int(num_objects); push_constant_text("num_allocs"); push_int(num_allocs); push_constant_text("alloc_threshold"); push_int(alloc_threshold); push_constant_text("objects_alloced"); push_int(objects_alloced); push_constant_text("objects_freed"); push_int(objects_freed); push_constant_text("last_gc"); push_int(last_gc); push_constant_text("projected_garbage"); push_float(objects_freed * (double) num_allocs / (double) alloc_threshold); f_aggregate_mapping(14); }