693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | | |
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | ||| This file a part of Pike, and is copyright by Fredrik Hubinette
||| Pike is distributed as GPL (General Public License)
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | | ||| See the files COPYING and DISCLAIMER for more information.
\*/
#include "global.h"
#ifdef GC2
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | |
|
a29e02 | 1996-10-15 | Fredrik Hübinette (Hubbe) | | struct callback *gc_evaluator_callback=0;
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | #include "array.h"
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | #include "multiset.h"
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | #include "mapping.h"
#include "object.h"
#include "program.h"
|
4a578f | 1997-01-27 | Fredrik Hübinette (Hubbe) | | #include "stralloc.h"
|
9c6f7d | 1997-04-15 | Fredrik Hübinette (Hubbe) | | #include "stuff.h"
#include "error.h"
|
9aa6fa | 1997-05-19 | Fredrik Hübinette (Hubbe) | | #include "pike_memory.h"
|
1a1168 | 1997-10-06 | Fredrik Hübinette (Hubbe) | | #include "pike_macros.h"
|
1ca3ba | 1997-10-13 | Fredrik Hübinette (Hubbe) | | #include "pike_types.h"
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | |
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | | #include "gc.h"
#include "main.h"
#define GC_CONST 20
#define MIN_ALLOC_THRESHOLD 1000
|
b95bef | 1996-03-29 | Fredrik Hübinette (Hubbe) | | #define MAX_ALLOC_THRESHOLD 10000000
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | | #define MULTIPLIER 0.9
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | #define MARKER_CHUNK_SIZE 1023
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | |
INT32 num_objects;
INT32 num_allocs;
INT32 alloc_threshold = MIN_ALLOC_THRESHOLD;
static double objects_alloced;
static double objects_freed;
|
4a578f | 1997-01-27 | Fredrik 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);
}
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | #define GC_REFERENCED 1
|
05c7cd | 1997-07-19 | Fredrik Hübinette (Hubbe) | | #define GC_XREFERENCED 2
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | |
struct marker
{
INT32 refs;
|
05c7cd | 1997-07-19 | Fredrik Hübinette (Hubbe) | | #ifdef DEBUG
INT32 xrefs;
#endif
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | INT32 flags;
|
05c7cd | 1997-07-19 | Fredrik Hübinette (Hubbe) | | struct marker *next;
void *marked;
|
c94c37 | 1996-03-28 | Fredrik 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;
|
be478c | 1997-08-30 | Henrik Grubbström (Grubba) | | static struct marker *new_marker(void)
|
c94c37 | 1996-03-28 | Fredrik 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;
|
cc15b7 | 1997-10-04 | Henrik Grubbström (Grubba) | | static unsigned long hashsize=0;
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | |
static struct marker *getmark(void *a)
{
int hashval;
struct marker *m;
|
cc15b7 | 1997-10-04 | Henrik Grubbström (Grubba) | | hashval=((unsigned long)a)%hashsize;
|
c94c37 | 1996-03-28 | Fredrik 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;
|
05c7cd | 1997-07-19 | Fredrik Hübinette (Hubbe) | | #ifdef DEBUG
m->xrefs=0;
#endif
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | m->flags=0;
m->next=hash[hashval];
hash[hashval]=m;
return m;
}
|
b8a6e7 | 1996-09-25 | Fredrik Hübinette (Hubbe) | | #ifdef DEBUG
|
1ca3ba | 1997-10-13 | Fredrik Hübinette (Hubbe) | |
TYPE_T attempt_to_identify(void *something)
{
struct array *a;
struct object *o;
struct program *p;
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;
return T_UNKNOWN;
}
|
b8a6e7 | 1996-09-25 | Fredrik Hübinette (Hubbe) | | static void *check_for =0;
|
1ca3ba | 1997-10-13 | Fredrik Hübinette (Hubbe) | | static char *found_where="";
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | | static void *found_in=0;
static TYPE_T found_in_type=0;
void *gc_svalue_location=0;
|
b8a6e7 | 1996-09-25 | Fredrik Hübinette (Hubbe) | |
|
356810 | 1997-10-16 | Fredrik Hübinette (Hubbe) | | void describe_location(void *memblock, TYPE_T type, void *location)
{
fprintf(stderr,"**Location of (short) svalue: %p\n",location);
if(type==T_OBJECT)
{
struct object *o=(struct object *)memblock;
if(o->prog)
{
INT32 e,d;
for(e=0;e<o->prog->num_inherits;e++)
{
struct inherit tmp=o->prog->inherits[e];
char *base=o->storage + tmp.storage_offset;
for(d=0;d<tmp.prog->num_identifiers;d++)
{
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);
}
}
}
}
return;
}
if(type == 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;
}
}
|
b8a6e7 | 1996-09-25 | Fredrik Hübinette (Hubbe) | | static void gdb_gc_stop_here(void *a)
{
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"**One ref found%s.\n",found_where);
describe_something(found_in, found_in_type);
|
356810 | 1997-10-16 | Fredrik Hübinette (Hubbe) | | describe_location(found_in, found_in_type, gc_svalue_location);
|
b8a6e7 | 1996-09-25 | Fredrik Hübinette (Hubbe) | | }
|
f6d017 | 1997-10-15 | Fredrik 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;
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;
}
void describe_something(void *a, TYPE_T t)
{
struct program *p=(struct program *)a;
if(!a) return;
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;
if(!p)
{
fprintf(stderr,"**The object is destructed.\n");
break;
}
fprintf(stderr,"**Attempting to describe program object was instantiated from:\n");
case T_PROGRAM:
|
356810 | 1997-10-16 | Fredrik Hübinette (Hubbe) | | {
char *tmp;
INT32 line,pos;
fprintf(stderr,"**Program id: %ld\n",(long)(p->id));
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | | if(!p->num_linenumbers)
{
fprintf(stderr,"**The program was written in C.\n");
break;
}
|
356810 | 1997-10-16 | Fredrik Hübinette (Hubbe) | |
for(pos=0;pos<(long)p->program_size && pos<100;pos++)
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | | {
|
356810 | 1997-10-16 | Fredrik Hübinette (Hubbe) | | tmp=get_line(p->program+pos, p, &line);
if(tmp && line)
{
fprintf(stderr,"**Location: %s:%ld\n",tmp,(long)line);
break;
}
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | | }
break;
|
356810 | 1997-10-16 | Fredrik Hübinette (Hubbe) | | }
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | |
case T_ARRAY:
fprintf(stderr,"**Describing array:\n");
debug_dump_array((struct array *)a);
break;
}
}
|
b8a6e7 | 1996-09-25 | Fredrik Hübinette (Hubbe) | | #endif
|
4a578f | 1997-01-27 | Fredrik Hübinette (Hubbe) | | INT32 gc_check(void *a)
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | {
|
b8a6e7 | 1996-09-25 | Fredrik Hübinette (Hubbe) | | #ifdef DEBUG
if(check_for)
{
if(check_for == a)
{
gdb_gc_stop_here(a);
}
|
4a578f | 1997-01-27 | Fredrik Hübinette (Hubbe) | | return 0;
|
b8a6e7 | 1996-09-25 | Fredrik Hübinette (Hubbe) | | }
#endif
|
4a578f | 1997-01-27 | Fredrik Hübinette (Hubbe) | | return getmark(a)->refs++;
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | }
int gc_is_referenced(void *a)
{
struct marker *m;
m=getmark(a);
#ifdef DEBUG
|
05c7cd | 1997-07-19 | Fredrik Hübinette (Hubbe) | | if(m->refs + m->xrefs > *(INT32 *)a)
|
b8a6e7 | 1996-09-25 | Fredrik Hübinette (Hubbe) | | {
|
142241 | 1997-10-13 | Fredrik Hübinette (Hubbe) | | INT32 refs=m->refs;
INT32 xrefs=m->xrefs;
|
1ca3ba | 1997-10-13 | Fredrik Hübinette (Hubbe) | | TYPE_T t=attempt_to_identify(a);
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"**Something has %ld references, while gc() found %ld + %ld external.\n",(long)*(INT32 *)a,(long)refs,(long)xrefs);
|
356810 | 1997-10-16 | Fredrik Hübinette (Hubbe) | | describe_something(a, t);
|
1ca3ba | 1997-10-13 | Fredrik Hübinette (Hubbe) | |
fprintf(stderr,"**Looking for references:\n");
|
b8a6e7 | 1996-09-25 | Fredrik Hübinette (Hubbe) | | check_for=a;
|
1ca3ba | 1997-10-13 | Fredrik Hübinette (Hubbe) | | found_where=" in an array";
|
b8a6e7 | 1996-09-25 | Fredrik Hübinette (Hubbe) | | gc_check_all_arrays();
|
1ca3ba | 1997-10-13 | Fredrik Hübinette (Hubbe) | |
found_where=" in a multiset";
|
b8a6e7 | 1996-09-25 | Fredrik Hübinette (Hubbe) | | gc_check_all_multisets();
|
1ca3ba | 1997-10-13 | Fredrik Hübinette (Hubbe) | |
found_where=" in a mapping";
|
b8a6e7 | 1996-09-25 | Fredrik Hübinette (Hubbe) | | gc_check_all_mappings();
|
1ca3ba | 1997-10-13 | Fredrik Hübinette (Hubbe) | |
found_where=" in a program";
|
b8a6e7 | 1996-09-25 | Fredrik Hübinette (Hubbe) | | gc_check_all_programs();
|
1ca3ba | 1997-10-13 | Fredrik Hübinette (Hubbe) | |
found_where=" in an object";
|
b8a6e7 | 1996-09-25 | Fredrik Hübinette (Hubbe) | | gc_check_all_objects();
|
1ca3ba | 1997-10-13 | Fredrik Hübinette (Hubbe) | |
found_where=" in a module";
|
4a578f | 1997-01-27 | Fredrik Hübinette (Hubbe) | | call_callback(& gc_callbacks, (void *)0);
|
b8a6e7 | 1996-09-25 | Fredrik Hübinette (Hubbe) | |
|
1ca3ba | 1997-10-13 | Fredrik Hübinette (Hubbe) | | found_where="";
|
b8a6e7 | 1996-09-25 | Fredrik Hübinette (Hubbe) | | check_for=0;
|
142241 | 1997-10-13 | Fredrik Hübinette (Hubbe) | |
fatal("Ref counts are wrong (has %d, found %d + %d external)\n",
*(INT32 *)a,
refs,
xrefs);
|
b8a6e7 | 1996-09-25 | Fredrik Hübinette (Hubbe) | | }
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | #endif
return m->refs < *(INT32 *)a;
}
|
05c7cd | 1997-07-19 | Fredrik Hübinette (Hubbe) | | #ifdef DEBUG
int gc_external_mark(void *a)
{
struct marker *m;
if(check_for)
{
if(a==check_for)
{
|
1ca3ba | 1997-10-13 | Fredrik Hübinette (Hubbe) | | char *tmp=found_where;
found_where="externally";
|
05c7cd | 1997-07-19 | Fredrik Hübinette (Hubbe) | | gdb_gc_stop_here(a);
|
1ca3ba | 1997-10-13 | Fredrik Hübinette (Hubbe) | | found_where=tmp;
|
05c7cd | 1997-07-19 | Fredrik Hübinette (Hubbe) | |
return 1;
}
return 0;
}
m=getmark(a);
m->xrefs++;
m->flags|=GC_XREFERENCED;
gc_is_referenced(a);
return 0;
}
#endif
|
c94c37 | 1996-03-28 | Fredrik 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);
return !(m->flags & GC_REFERENCED);
}
static INT32 hashprimes[] =
{
31,
31,
31,
31,
31,
31,
61,
127,
251,
541,
1151,
2111,
4327,
8803,
17903,
32321,
65599,
133153,
270001,
547453,
1109891,
2000143,
4561877,
9248339,
16777215,
33554431,
67108863,
134217727,
268435455,
536870911,
1073741823,
2147483647,
};
|
be478c | 1997-08-30 | Henrik Grubbström (Grubba) | | void do_gc(void)
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | | {
|
890e5b | 1996-11-21 | Fredrik Hübinette (Hubbe) | | static int in_gc = 0;
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | | double tmp;
|
1a1168 | 1997-10-06 | Fredrik Hübinette (Hubbe) | | INT32 tmp2,tmp3;
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | struct marker_chunk *m;
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | |
|
890e5b | 1996-11-21 | Fredrik Hübinette (Hubbe) | | if(in_gc) return;
in_gc=1;
|
e78abd | 1996-11-21 | Fredrik Hübinette (Hubbe) | | if(gc_evaluator_callback)
{
remove_callback(gc_evaluator_callback);
gc_evaluator_callback=0;
}
|
890e5b | 1996-11-21 | Fredrik Hübinette (Hubbe) | |
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | | tmp2=num_objects;
#ifdef DEBUG
if(t_flag)
fprintf(stderr,"Garbage collecting ... ");
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | if(num_objects < 0)
fatal("Panic, less than zero objects!\n");
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | | #endif
objects_alloced*=MULTIPLIER;
objects_alloced += (double) num_allocs;
objects_freed*=MULTIPLIER;
objects_freed += (double) num_objects;
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | |
|
1a1168 | 1997-10-06 | Fredrik Hübinette (Hubbe) | | tmp3=my_log2(num_objects);
|
4a578f | 1997-01-27 | Fredrik Hübinette (Hubbe) | |
|
1a1168 | 1997-10-06 | Fredrik Hübinette (Hubbe) | | if(!d_flag) tmp3-=2;
if(tmp3<0) tmp3=0;
if(tmp3>=(long)NELEM(hashprimes)) tmp3=NELEM(hashprimes)-1;
hashsize=hashprimes[tmp3];
|
4a578f | 1997-01-27 | Fredrik Hübinette (Hubbe) | |
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | hash=(struct marker **)xalloc(sizeof(struct marker **)*hashsize);
MEMSET((char *)hash,0,sizeof(struct marker **)*hashsize);
markers_left_in_chunk=0;
|
a99145 | 1997-07-08 | Fredrik Hübinette (Hubbe) | |
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | | gc_check_all_arrays();
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | gc_check_all_multisets();
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | gc_check_all_mappings();
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | | gc_check_all_programs();
gc_check_all_objects();
|
4a578f | 1997-01-27 | Fredrik Hübinette (Hubbe) | | call_callback(& gc_callbacks, (void *)0);
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | |
|
a99145 | 1997-07-08 | Fredrik Hübinette (Hubbe) | |
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | gc_mark_all_arrays();
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | gc_mark_all_multisets();
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | gc_mark_all_mappings();
gc_mark_all_programs();
gc_mark_all_objects();
|
4a578f | 1997-01-27 | Fredrik Hübinette (Hubbe) | | if(d_flag)
gc_mark_all_strings();
|
a99145 | 1997-07-08 | Fredrik Hübinette (Hubbe) | |
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | gc_free_all_unreferenced_arrays();
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | gc_free_all_unreferenced_multisets();
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | gc_free_all_unreferenced_mappings();
gc_free_all_unreferenced_programs();
gc_free_all_unreferenced_objects();
free((char *)hash);
|
9c6f7d | 1997-04-15 | Fredrik Hübinette (Hubbe) | | while((m=chunk))
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | {
chunk=m->next;
free((char *)m);
}
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | |
destruct_objects_to_destruct();
|
693018 | 1996-02-25 | Fredrik 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;
|
b95bef | 1996-03-29 | Fredrik Hübinette (Hubbe) | | if(alloc_threshold > MAX_ALLOC_THRESHOLD)
alloc_threshold = MAX_ALLOC_THRESHOLD;
|
693018 | 1996-02-25 | Fredrik 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
|
a29e02 | 1996-10-15 | Fredrik Hübinette (Hubbe) | |
|
bf4577 | 1996-12-05 | Fredrik Hübinette (Hubbe) | | #ifdef ALWAYS_GC
|
890e5b | 1996-11-21 | Fredrik Hübinette (Hubbe) | | ADD_GC_CALLBACK();
#else
|
bf4577 | 1996-12-05 | Fredrik Hübinette (Hubbe) | | if(d_flag > 3) ADD_GC_CALLBACK();
|
a29e02 | 1996-10-15 | Fredrik Hübinette (Hubbe) | | #endif
|
890e5b | 1996-11-21 | Fredrik Hübinette (Hubbe) | | in_gc=0;
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | | }
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | #endif
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | |
|