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.
\*/
|
374109 | 1999-09-25 | Henrik Grubbström (Grubba) | |
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | | #include "global.h"
|
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"
|
dc296b | 1997-10-21 | Fredrik Hübinette (Hubbe) | | #include "time_stuff.h"
|
2eeba9 | 1999-03-17 | Fredrik Hübinette (Hubbe) | | #include "constants.h"
|
1637c4 | 2000-02-01 | Fredrik Hübinette (Hubbe) | | #include "interpret.h"
|
132f0d | 2000-08-13 | Henrik Grubbström (Grubba) | | #include "bignum.h"
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | |
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | | #include "gc.h"
#include "main.h"
|
dc296b | 1997-10-21 | Fredrik Hübinette (Hubbe) | | #include <math.h>
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | |
|
374109 | 1999-09-25 | Henrik Grubbström (Grubba) | | #include "block_alloc.h"
|
10c4a4 | 2000-08-17 | Martin Stjernholm | | RCSID("$Id: gc.c,v 1.123 2000/08/16 22:03:40 mast Exp $");
|
24ddc7 | 1998-03-28 | Henrik Grubbström (Grubba) | |
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | |
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | | * 20 percent of all arrays, objects and programs is
* garbage.
*/
#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
|
45d87e | 2000-07-18 | Martin Stjernholm | | #define GC_LINK_CHUNK_SIZE 31
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | |
|
10c4a4 | 2000-08-17 | Martin Stjernholm | | * Things that have only weak external references at the start of the
* gc pass will be freed. That's done before the live object destruct
* pass. Internal weak references are however still intact.
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | */
|
d9dd81 | 2000-06-12 | Martin Stjernholm | |
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | |
|
45d87e | 2000-07-18 | Martin Stjernholm | |
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | #if defined(GC_VERBOSE) && !defined(PIKE_DEBUG)
#undef GC_VERBOSE
#endif
#ifdef GC_VERBOSE
#define GC_VERBOSE_DO(X) X
#else
#define GC_VERBOSE_DO(X)
#endif
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | |
|
f5757f | 2000-08-11 | Henrik Grubbström (Grubba) | |
#ifdef __ECL
static inline long CAST_TO_LONG(ptrdiff_t val)
{
return DO_NOT_WARN((long)val);
}
#else /* !__ECL */
#define CAST_TO_LONG(val) ((long)(val))
#endif /* __ECL */
|
7bf623 | 2000-04-23 | Martin Stjernholm | | INT32 num_objects = 1;
|
dc296b | 1997-10-21 | Fredrik Hübinette (Hubbe) | | INT32 num_allocs =0;
|
f5757f | 2000-08-11 | Henrik Grubbström (Grubba) | | ptrdiff_t alloc_threshold = MIN_ALLOC_THRESHOLD;
|
1f2133 | 2000-07-28 | Fredrik Hübinette (Hubbe) | | PMOD_EXPORT int Pike_in_gc = 0;
|
8ea206 | 1998-04-29 | Fredrik Noring | | struct pike_queue gc_mark_queue;
|
4452c1 | 2000-02-02 | Fredrik Hübinette (Hubbe) | | time_t last_gc;
|
45d87e | 2000-07-18 | Martin Stjernholm | | struct gc_frame
{
struct gc_frame *back;
void *data;
union {
struct {
struct gc_frame *prev;
struct gc_frame *next;
unsigned INT16 cycle;
} pop;
struct {
gc_cycle_check_cb *checkfn;
int weak;
} link;
} u;
unsigned INT16 frameflags;
};
#define GC_POP_FRAME 0x01
#define GC_WEAK_REF 0x02
#define GC_STRONG_REF 0x04
#define GC_OFF_STACK 0x08
#ifdef PIKE_DEBUG
#define GC_LINK_FREED 0x10
#define GC_FOLLOWED_NONSTRONG 0x20
#endif
#undef BLOCK_ALLOC_NEXT
#define BLOCK_ALLOC_NEXT back
BLOCK_ALLOC(gc_frame,GC_LINK_CHUNK_SIZE)
#define PREV(frame) ((frame)->u.pop.prev)
#define NEXT(frame) ((frame)->u.pop.next)
#define CYCLE(frame) ((frame)->u.pop.cycle)
#ifdef PIKE_DEBUG
#define CHECK_POP_FRAME(frame) do { \
if ((frame)->frameflags & GC_LINK_FREED) \
gc_fatal((frame)->data, 0, "Accessing freed gc_frame.\n"); \
if (!((frame)->frameflags & GC_POP_FRAME)) \
gc_fatal((frame)->data, 0, #frame " is not a pop frame.\n"); \
if (NEXT(PREV(frame)) != (frame)) \
gc_fatal((frame)->data, 0, \
"Pop frame pointers are inconsistent.\n"); \
} while (0)
#else
#define CHECK_POP_FRAME(frame) do {} while (0)
#endif
static struct gc_frame rec_list = {0, 0, {{0, 0, 0}}, GC_POP_FRAME};
static struct gc_frame *gc_rec_last = &rec_list, *gc_rec_top = 0;
static struct gc_frame *kill_list = 0;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | static unsigned last_cycle;
|
6d30f5 | 2000-07-11 | Martin Stjernholm | | size_t gc_ext_weak_refs;
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | |
|
45d87e | 2000-07-18 | Martin Stjernholm | | |
996f87 | 2000-06-12 | Martin Stjernholm | | *
|
45d87e | 2000-07-18 | Martin Stjernholm | | * rec_list is a double linked list of the pop frames on the stack,
* and that list represents the current prospective destruct order.
* gc_rec_last points at the last frame in the list and new frames are
* linked in after it. A cycle is always treated as one atomic unit,
* e.g. it's either popped whole or not at all. That means that
* rec_list may contain frames that are no longer on the stack.
|
996f87 | 2000-06-12 | Martin Stjernholm | | *
|
45d87e | 2000-07-18 | Martin Stjernholm | | * A range of frames which always ends at the end of the list, may be
* rotated a number of slots to break a cyclic reference at a chosen
* point. The stack of link frames are rotated simultaneously.
*
* Frames for live objects are linked into the beginning of kill_list
|
996f87 | 2000-06-12 | Martin Stjernholm | | * when they're popped from rec_list.
*
* The cycle check functions might recurse another round through the
|
45d87e | 2000-07-18 | Martin Stjernholm | | * frames that have been recursed already, to propagate the GC_LIVE
|
996f87 | 2000-06-12 | Martin Stjernholm | | * flag to things that have been found to be referenced from live
* objects. rec_list is not touched at all in this extra round.
*/
|
dc296b | 1997-10-21 | Fredrik Hübinette (Hubbe) | | static double objects_alloced = 0.0;
static double objects_freed = 0.0;
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | |
|
4a578f | 1997-01-27 | Fredrik Hübinette (Hubbe) | | struct callback_list gc_callbacks;
|
424d9c | 1999-05-02 | Fredrik Hübinette (Hubbe) | | struct callback *debug_add_gc_callback(callback_func call,
|
4a578f | 1997-01-27 | Fredrik Hübinette (Hubbe) | | void *arg,
callback_func free_func)
{
return add_to_callback(&gc_callbacks, call, arg, free_func);
}
|
45d87e | 2000-07-18 | Martin Stjernholm | | static void gc_cycle_pop(void *a);
#undef BLOCK_ALLOC_NEXT
#define BLOCK_ALLOC_NEXT next
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | |
|
424d9c | 1999-05-02 | Fredrik Hübinette (Hubbe) | | #undef INIT_BLOCK
|
71f3a2 | 1998-11-22 | Fredrik Hübinette (Hubbe) | | #ifdef PIKE_DEBUG
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | #define INIT_BLOCK(X) \
(X)->flags=(X)->refs=(X)->weak_refs=(X)->xrefs=0; \
|
081629 | 2000-07-03 | Martin Stjernholm | | (X)->saved_refs=-1; \
|
45d87e | 2000-07-18 | Martin Stjernholm | | (X)->frame = 0;
|
424d9c | 1999-05-02 | Fredrik Hübinette (Hubbe) | | #else
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | #define INIT_BLOCK(X) \
|
45d87e | 2000-07-18 | Martin Stjernholm | | (X)->flags=(X)->refs=(X)->weak_refs=0; \
(X)->frame = 0;
|
05c7cd | 1997-07-19 | Fredrik Hübinette (Hubbe) | | #endif
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | |
|
424d9c | 1999-05-02 | Fredrik Hübinette (Hubbe) | | PTR_HASH_ALLOC(marker,MARKER_CHUNK_SIZE)
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | |
|
71f3a2 | 1998-11-22 | Fredrik Hübinette (Hubbe) | | #ifdef PIKE_DEBUG
|
1ca3ba | 1997-10-13 | Fredrik Hübinette (Hubbe) | |
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | int gc_in_cycle_check = 0;
static unsigned weak_freed, checked, marked, cycle_checked, live_ref;
|
45d87e | 2000-07-18 | Martin Stjernholm | | static unsigned max_gc_frames, num_gc_frames = 0;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | static unsigned gc_extra_refs = 0;
|
dc296b | 1997-10-21 | Fredrik 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);
|
a17d76 | 2000-08-11 | Henrik Grubbström (Grubba) | | fprintf(stderr,"Second since last gc() : %ld\n",
DO_NOT_WARN((long)TIME(0) - (long)last_gc));
|
dc296b | 1997-10-21 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"Projected garbage : %f\n", objects_freed * (double) num_allocs / (double) alloc_threshold);
|
6bc62b | 2000-04-14 | Martin Stjernholm | | fprintf(stderr,"in_gc : %d\n", Pike_in_gc);
|
dc296b | 1997-10-21 | Fredrik Hübinette (Hubbe) | | }
|
1ca3ba | 1997-10-13 | Fredrik Hübinette (Hubbe) | | TYPE_T attempt_to_identify(void *something)
{
struct array *a;
struct object *o;
struct program *p;
|
62971d | 1998-01-19 | Fredrik Hübinette (Hubbe) | | struct mapping *m;
struct multiset *mu;
|
1ca3ba | 1997-10-13 | Fredrik 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;
|
62971d | 1998-01-19 | Fredrik 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;
|
1ca3ba | 1997-10-13 | Fredrik Hübinette (Hubbe) | | return T_UNKNOWN;
}
|
20513c | 2000-04-12 | Fredrik Hübinette (Hubbe) | | 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;
|
469411 | 1997-11-07 | Fredrik Hübinette (Hubbe) | | static int found_in_type=0;
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | | void *gc_svalue_location=0;
|
06ae27 | 2000-04-19 | Martin Stjernholm | | char *fatal_after_gc=0;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | int gc_debug = 0;
|
ad2bdb | 2000-04-12 | Fredrik Hübinette (Hubbe) | |
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | #define DESCRIBE_MEM 1
#define DESCRIBE_NO_REFS 2
#define DESCRIBE_SHORT 4
#define DESCRIBE_NO_DMALLOC 8
|
ad2bdb | 2000-04-12 | Fredrik Hübinette (Hubbe) | |
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | |
void describe_location(void *real_memblock,
int real_type,
void *location,
int indent,
int depth,
int flags)
|
356810 | 1997-10-16 | Fredrik Hübinette (Hubbe) | | {
|
1e4e5f | 2000-04-07 | Fredrik Hübinette (Hubbe) | | struct program *p;
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | void *memblock=0;
int type=real_type;
|
469411 | 1997-11-07 | Fredrik Hübinette (Hubbe) | | if(!location) return;
|
1e4e5f | 2000-04-07 | Fredrik Hübinette (Hubbe) | |
|
62971d | 1998-01-19 | Fredrik Hübinette (Hubbe) | |
|
87c7f9 | 2000-04-19 | Martin Stjernholm | | if(real_type!=-1) memblock=real_memblock;
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | |
|
20513c | 2000-04-12 | Fredrik 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
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | if(type==T_UNKNOWN)
type=attempt_to_identify(memblock);
|
20513c | 2000-04-12 | Fredrik Hübinette (Hubbe) | |
if(memblock)
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s-> from %s %p offset %ld\n",
indent,"",
|
20513c | 2000-04-12 | Fredrik Hübinette (Hubbe) | | get_name_of_type(type),
memblock,
|
a17d76 | 2000-08-11 | Henrik Grubbström (Grubba) | | DO_NOT_WARN((long)((char *)location - (char *)memblock)));
|
20513c | 2000-04-12 | Fredrik Hübinette (Hubbe) | | else
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s-> at location %p in unknown memblock (mmaped?)\n",
indent,"",
|
20513c | 2000-04-12 | Fredrik Hübinette (Hubbe) | | location);
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | if(memblock && depth>0)
describe_something(memblock,type,indent+2,depth-1,flags | DESCRIBE_MEM);
|
20513c | 2000-04-12 | Fredrik Hübinette (Hubbe) | |
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | again:
|
62971d | 1998-01-19 | Fredrik Hübinette (Hubbe) | | switch(type)
|
356810 | 1997-10-16 | Fredrik Hübinette (Hubbe) | | {
|
1e4e5f | 2000-04-07 | Fredrik Hübinette (Hubbe) | | case T_UNKNOWN:
for(p=first_program;p;p=p->next)
{
if(memblock == (void *)p->program)
{
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s **In memory block for program at %p\n",
indent,"",
p);
|
1e4e5f | 2000-04-07 | Fredrik Hübinette (Hubbe) | | memblock=p;
type=T_PROGRAM;
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | goto again;
|
1e4e5f | 2000-04-07 | Fredrik Hübinette (Hubbe) | | }
}
break;
|
0b6944 | 1998-01-19 | Fredrik Hübinette (Hubbe) | | case T_PROGRAM:
{
|
9c815b | 2000-08-10 | Henrik Grubbström (Grubba) | | ptrdiff_t e;
|
0b6944 | 1998-01-19 | Fredrik Hübinette (Hubbe) | | char *ptr=(char *)location;
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | p=(struct program *)memblock;
|
0b6944 | 1998-01-19 | Fredrik Hübinette (Hubbe) | |
|
1e4e5f | 2000-04-07 | Fredrik Hübinette (Hubbe) | | if(location == (void *)&p->prev)
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s **In p->prev\n",indent,"");
|
1e4e5f | 2000-04-07 | Fredrik Hübinette (Hubbe) | |
if(location == (void *)&p->next)
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s **In p->next\n",indent,"");
|
1e4e5f | 2000-04-07 | Fredrik Hübinette (Hubbe) | |
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | if(p->inherits &&
ptr >= (char *)p->inherits &&
|
f00c36 | 2000-08-10 | Henrik Grubbström (Grubba) | | ptr < (char*)(p->inherits+p->num_inherits))
|
1e4e5f | 2000-04-07 | Fredrik Hübinette (Hubbe) | | {
|
f00c36 | 2000-08-10 | Henrik Grubbström (Grubba) | | e=((char *)ptr - (char *)(p->inherits)) / sizeof(struct inherit);
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s **In p->inherits[%ld] (%s)\n",indent,"",
|
a17d76 | 2000-08-11 | Henrik Grubbström (Grubba) | | DO_NOT_WARN((long)e),
|
1e4e5f | 2000-04-07 | Fredrik Hübinette (Hubbe) | | p->inherits[e].name ? p->inherits[e].name->str : "no name");
|
dfe8f3 | 2000-04-26 | Fredrik Hübinette (Hubbe) | | break;
|
1e4e5f | 2000-04-07 | Fredrik Hübinette (Hubbe) | | }
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | if(p->constants &&
ptr >= (char *)p->constants &&
|
f00c36 | 2000-08-10 | Henrik Grubbström (Grubba) | | ptr < (char*)(p->constants+p->num_constants))
|
1e4e5f | 2000-04-07 | Fredrik Hübinette (Hubbe) | | {
|
f00c36 | 2000-08-10 | Henrik Grubbström (Grubba) | | e = ((char *)ptr - (char *)(p->constants)) /
|
9c815b | 2000-08-10 | Henrik Grubbström (Grubba) | | sizeof(struct program_constant);
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s **In p->constants[%ld] (%s)\n",indent,"",
|
a17d76 | 2000-08-11 | Henrik Grubbström (Grubba) | | DO_NOT_WARN((long)e),
|
1e4e5f | 2000-04-07 | Fredrik Hübinette (Hubbe) | | p->constants[e].name ? p->constants[e].name->str : "no name");
|
dfe8f3 | 2000-04-26 | Fredrik Hübinette (Hubbe) | | break;
|
1e4e5f | 2000-04-07 | Fredrik Hübinette (Hubbe) | | }
|
0b6944 | 1998-01-19 | Fredrik Hübinette (Hubbe) | |
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | if(p->identifiers &&
ptr >= (char *)p->identifiers &&
|
f00c36 | 2000-08-10 | Henrik Grubbström (Grubba) | | ptr < (char*)(p->identifiers+p->num_identifiers))
|
1e4e5f | 2000-04-07 | Fredrik Hübinette (Hubbe) | | {
|
f00c36 | 2000-08-10 | Henrik Grubbström (Grubba) | | e = ((char *)ptr - (char *)(p->identifiers)) /
|
9c815b | 2000-08-10 | Henrik Grubbström (Grubba) | | sizeof(struct identifier);
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s **In p->identifiers[%ld] (%s)\n",indent,"",
|
a17d76 | 2000-08-11 | Henrik Grubbström (Grubba) | | DO_NOT_WARN((long)e),
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | p->identifiers[e].name ? p->identifiers[e].name->str : "no name");
|
dfe8f3 | 2000-04-26 | Fredrik Hübinette (Hubbe) | | break;
|
1e4e5f | 2000-04-07 | Fredrik Hübinette (Hubbe) | | }
#define FOO(NTYP,TYP,NAME) \
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | if(location == (void *)&p->NAME) fprintf(stderr,"%*s **In p->" #NAME "\n",indent,""); \
|
1e4e5f | 2000-04-07 | Fredrik Hübinette (Hubbe) | | if(ptr >= (char *)p->NAME && ptr<(char*)(p->NAME+p->PIKE_CONCAT(num_,NAME))) \
|
f5757f | 2000-08-11 | Henrik Grubbström (Grubba) | | fprintf(stderr,"%*s **In p->" #NAME "[%ld]\n",indent,"", \
CAST_TO_LONG(((char *)ptr - (char *)(p->NAME)) / sizeof(TYP)));
|
1e4e5f | 2000-04-07 | Fredrik Hübinette (Hubbe) | | #include "program_areas.h"
|
0b6944 | 1998-01-19 | Fredrik Hübinette (Hubbe) | |
|
dfe8f3 | 2000-04-26 | Fredrik Hübinette (Hubbe) | | break;
|
0b6944 | 1998-01-19 | Fredrik Hübinette (Hubbe) | | }
|
62971d | 1998-01-19 | Fredrik Hübinette (Hubbe) | | case T_OBJECT:
|
356810 | 1997-10-16 | Fredrik Hübinette (Hubbe) | | {
|
62971d | 1998-01-19 | Fredrik Hübinette (Hubbe) | | struct object *o=(struct object *)memblock;
|
1e4e5f | 2000-04-07 | Fredrik Hübinette (Hubbe) | | struct program *p;
|
a4033e | 2000-04-14 | Fredrik 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,"");
|
1e4e5f | 2000-04-07 | Fredrik Hübinette (Hubbe) | |
p=o->prog;
if(!o->prog)
{
p=id_to_program(o->program_id);
if(p)
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s **(We are lucky, found program for destructed object)\n",indent,"");
|
1e4e5f | 2000-04-07 | Fredrik Hübinette (Hubbe) | | }
if(p)
|
356810 | 1997-10-16 | Fredrik Hübinette (Hubbe) | | {
|
62971d | 1998-01-19 | Fredrik Hübinette (Hubbe) | | INT32 e,d;
|
1e4e5f | 2000-04-07 | Fredrik Hübinette (Hubbe) | | for(e=0;e<(INT32)p->num_inherits;e++)
|
356810 | 1997-10-16 | Fredrik Hübinette (Hubbe) | | {
|
1e4e5f | 2000-04-07 | Fredrik Hübinette (Hubbe) | | struct inherit tmp=p->inherits[e];
|
62971d | 1998-01-19 | Fredrik Hübinette (Hubbe) | | char *base=o->storage + tmp.storage_offset;
for(d=0;d<(INT32)tmp.prog->num_identifiers;d++)
|
356810 | 1997-10-16 | Fredrik Hübinette (Hubbe) | | {
|
62971d | 1998-01-19 | Fredrik 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))
{
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s **In variable %s\n",indent,"",id->name->str);
|
62971d | 1998-01-19 | Fredrik Hübinette (Hubbe) | | }
|
356810 | 1997-10-16 | Fredrik Hübinette (Hubbe) | | }
|
1e4e5f | 2000-04-07 | Fredrik Hübinette (Hubbe) | |
if((char *)location >= base && (char *)location <= base +
( tmp.prog->storage_needed - tmp.prog->inherits[0].storage_offset ))
{
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s **In storage for inherit %d",indent,"",e);
|
1e4e5f | 2000-04-07 | Fredrik Hübinette (Hubbe) | | if(tmp.name)
fprintf(stderr," (%s)",tmp.name->str);
fprintf(stderr,"\n");
}
|
356810 | 1997-10-16 | Fredrik Hübinette (Hubbe) | | }
}
|
dfe8f3 | 2000-04-26 | Fredrik Hübinette (Hubbe) | | break;
|
356810 | 1997-10-16 | Fredrik Hübinette (Hubbe) | | }
|
62971d | 1998-01-19 | Fredrik Hübinette (Hubbe) | | case T_ARRAY:
{
struct array *a=(struct array *)memblock;
struct svalue *s=(struct svalue *)location;
|
f5757f | 2000-08-11 | Henrik Grubbström (Grubba) | | fprintf(stderr,"%*s **In index %ld\n",indent,"",
DO_NOT_WARN((long)(s-ITEM(a))));
|
dfe8f3 | 2000-04-26 | Fredrik Hübinette (Hubbe) | | break;
|
62971d | 1998-01-19 | Fredrik Hübinette (Hubbe) | | }
|
356810 | 1997-10-16 | Fredrik Hübinette (Hubbe) | | }
|
dfe8f3 | 2000-04-26 | Fredrik Hübinette (Hubbe) | |
|
57a436 | 2000-04-27 | Fredrik Hübinette (Hubbe) | | #ifdef DEBUG_MALLOC
|
dc4d8c | 2000-08-11 | Henrik Grubbström (Grubba) | |
|
dfe8f3 | 2000-04-26 | Fredrik Hübinette (Hubbe) | | dmalloc_describe_location(memblock, location, indent);
|
57a436 | 2000-04-27 | Fredrik Hübinette (Hubbe) | | #endif
|
356810 | 1997-10-16 | Fredrik Hübinette (Hubbe) | | }
|
45d87e | 2000-07-18 | Martin Stjernholm | | static void describe_gc_frame(struct gc_frame *l)
{
if (l->frameflags & GC_POP_FRAME)
fprintf(stderr, "back=%p, prev=%p, next=%p, data=%p, cycle=%u, flags=0x%02x",
l->back, PREV(l), NEXT(l), l->data, CYCLE(l), l->frameflags);
else
fprintf(stderr, "LINK back=%p, data=%p, weak=%d, flags=0x%02x",
l->back, l->data, l->u.link.weak, l->frameflags);
}
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | static void describe_marker(struct marker *m)
{
|
45d87e | 2000-07-18 | Martin Stjernholm | | if (m) {
|
46d4e7 | 2000-06-12 | Martin Stjernholm | | fprintf(stderr, "marker at %p: flags=0x%06x, refs=%d, weak=%d, "
|
45d87e | 2000-07-18 | Martin Stjernholm | | "xrefs=%d, saved=%d, frame=%p",
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | m, m->flags, m->refs, m->weak_refs,
|
45d87e | 2000-07-18 | Martin Stjernholm | | m->xrefs, m->saved_refs, m->frame);
#ifdef PIKE_DEBUG
if (m->frame) {
fputs(" [", stderr);
describe_gc_frame(m->frame);
putc(']', stderr);
}
#endif
putc('\n', stderr);
}
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | else
fprintf(stderr, "no marker\n");
}
void debug_gc_fatal(void *a, int flags, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
fprintf(stderr, "**");
(void) VFPRINTF(stderr, fmt, args);
describe(a);
if (flags & 1) locate_references(a);
if (flags & 2)
fatal_after_gc = "Fatal in garbage collector.\n";
else
debug_fatal("Fatal in garbage collector.\n");
}
|
081629 | 2000-07-03 | Martin Stjernholm | | static void gdb_gc_stop_here(void *a, int weak)
|
b8a6e7 | 1996-09-25 | Fredrik Hübinette (Hubbe) | | {
|
081629 | 2000-07-03 | Martin Stjernholm | | fprintf(stderr,"***One %sref found%s.\n",
weak ? "weak " : "",
found_where?found_where:"");
|
a4033e | 2000-04-14 | Fredrik 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);
|
20513c | 2000-04-12 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"----------end------------\n");
|
b8a6e7 | 1996-09-25 | Fredrik Hübinette (Hubbe) | | }
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | |
|
1330e1 | 2000-08-10 | Henrik Grubbström (Grubba) | | void debug_gc_xmark_svalues(struct svalue *s, ptrdiff_t num, char *fromwhere)
|
469411 | 1997-11-07 | Fredrik Hübinette (Hubbe) | | {
found_in=(void *)fromwhere;
found_in_type=-1;
gc_xmark_svalues(s,num);
found_in_type=T_UNKNOWN;
found_in=0;
}
|
1330e1 | 2000-08-10 | Henrik Grubbström (Grubba) | | void debug_gc_check_svalues(struct svalue *s, ptrdiff_t num, TYPE_T t, void *data)
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | | {
found_in=data;
found_in_type=t;
|
c4ccb8 | 2000-07-04 | Martin Stjernholm | | gc_check_svalues(s,num);
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | | found_in_type=T_UNKNOWN;
|
469411 | 1997-11-07 | Fredrik Hübinette (Hubbe) | | found_in=0;
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | | }
|
1330e1 | 2000-08-10 | Henrik Grubbström (Grubba) | | void debug_gc_check_weak_svalues(struct svalue *s, ptrdiff_t num, TYPE_T t, void *data)
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | {
found_in=data;
found_in_type=t;
|
c4ccb8 | 2000-07-04 | Martin Stjernholm | | gc_check_weak_svalues(s,num);
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | found_in_type=T_UNKNOWN;
found_in=0;
}
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | | 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;
|
469411 | 1997-11-07 | Fredrik Hübinette (Hubbe) | | found_in=0;
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | | }
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | void debug_gc_check_weak_short_svalue(union anything *u, TYPE_T type, TYPE_T t, void *data)
{
found_in=data;
found_in_type=t;
gc_check_weak_short_svalue(u,type);
found_in_type=T_UNKNOWN;
found_in=0;
}
|
0b6944 | 1998-01-19 | Fredrik 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;
}
|
393a59 | 2000-08-16 | Henrik Grubbström (Grubba) | |
#ifdef __ECL
static inline long SIZE_T_TO_LONG(size_t x)
{
return DO_NOT_WARN((long)x);
}
#else /* !__ECL */
#define SIZE_T_TO_LONG(x) ((long)(x))
#endif /* __ECL */
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | void low_describe_something(void *a,
int t,
int indent,
int depth,
int flags)
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | | {
struct program *p=(struct program *)a;
|
081629 | 2000-07-03 | Martin Stjernholm | | struct marker *m;
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | |
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | if(depth<0) return;
|
081629 | 2000-07-03 | Martin Stjernholm | | if ((m = find_marker(a))) {
fprintf(stderr,"%*s**Got gc ",indent,"");
describe_marker(m);
}
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | | switch(t)
{
|
2eeba9 | 1999-03-17 | Fredrik Hübinette (Hubbe) | | case T_FUNCTION:
if(attempt_to_identify(a) != T_OBJECT)
{
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s**Builtin function!\n",indent,"");
|
2eeba9 | 1999-03-17 | Fredrik Hübinette (Hubbe) | | break;
}
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | | case T_OBJECT:
p=((struct object *)a)->prog;
|
a4033e | 2000-04-14 | Fredrik 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);
|
1e4e5f | 2000-04-07 | Fredrik Hübinette (Hubbe) | |
|
7bf623 | 2000-04-23 | Martin Stjernholm | | if (((struct object *)a)->next == ((struct object *)a))
fprintf(stderr, "%*s**The object is fake.\n",indent,"");
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | {
struct object *o;
for (o = first_object; o && o != (struct object *) a; o = o->next) {}
if (!o)
fprintf(stderr,"%*s**The object is not on the object link list.\n",indent,"");
for (o = objects_to_destruct; o && o != (struct object *) a; o = o->next) {}
if (o)
fprintf(stderr,"%*s**The object is on objects_to_destruct.\n",indent,"");
}
|
7bf623 | 2000-04-23 | Martin Stjernholm | | if(!p)
{
fprintf(stderr,"%*s**The object is destructed.\n",indent,"");
p=id_to_program(((struct object *)a)->program_id);
}
if (p) {
fprintf(stderr,"%*s**Attempting to describe program object was instantiated from:\n",indent,"");
low_describe_something(p, T_PROGRAM, indent, depth, flags);
}
|
8fb1e1 | 1998-04-05 | Fredrik Hübinette (Hubbe) | | if( ((struct object *)a)->parent)
{
|
a4033e | 2000-04-14 | Fredrik 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));
|
8fb1e1 | 1998-04-05 | Fredrik Hübinette (Hubbe) | | }else{
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s**There is no parent (any longer?)\n",indent,"");
|
8fb1e1 | 1998-04-05 | Fredrik Hübinette (Hubbe) | | }
|
7bf623 | 2000-04-23 | Martin Stjernholm | | break;
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | |
case T_PROGRAM:
|
356810 | 1997-10-16 | Fredrik Hübinette (Hubbe) | | {
char *tmp;
INT32 line,pos;
|
2eeba9 | 1999-03-17 | Fredrik Hübinette (Hubbe) | | int foo=0;
|
356810 | 1997-10-16 | Fredrik Hübinette (Hubbe) | |
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s**Program id: %ld\n",indent,"",(long)(p->id));
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | |
|
05590d | 1998-04-23 | Fredrik Hübinette (Hubbe) | | if(p->flags & PROGRAM_HAS_C_METHODS)
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | | {
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s**The program was written in C.\n",indent,"");
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | | }
|
2eeba9 | 1999-03-17 | Fredrik Hübinette (Hubbe) | | for(pos=0;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)
{
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s**Location: %s:%ld\n",indent,"",tmp,(long)line);
|
2eeba9 | 1999-03-17 | Fredrik Hübinette (Hubbe) | | foo=1;
|
356810 | 1997-10-16 | Fredrik Hübinette (Hubbe) | | break;
}
|
393a59 | 2000-08-16 | Henrik Grubbström (Grubba) | | if(pos+1>=(ptrdiff_t)p->num_program)
|
2eeba9 | 1999-03-17 | Fredrik Hübinette (Hubbe) | | break;
}
#if 0
if(!foo && p->num_linenumbers>1 && EXTRACT_UCHAR(p->linenumbers)=='\177')
{
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s**From file: %s\n",indent,"",p->linenumbers+1);
|
2eeba9 | 1999-03-17 | Fredrik Hübinette (Hubbe) | | foo=1;
}
#endif
if(!foo)
{
int e;
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s**identifiers:\n",indent,"");
|
2eeba9 | 1999-03-17 | Fredrik Hübinette (Hubbe) | | for(e=0;e<p->num_identifier_references;e++)
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s**** %s\n",indent,"",ID_FROM_INT(p,e)->name->str);
|
2eeba9 | 1999-03-17 | Fredrik Hübinette (Hubbe) | |
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s**num inherits: %d\n",indent,"",p->num_inherits);
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | | }
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | |
if(flags & DESCRIBE_MEM)
{
|
1e4e5f | 2000-04-07 | Fredrik Hübinette (Hubbe) | | #define FOO(NUMTYPE,TYPE,NAME) \
|
5c720f | 2000-08-10 | Henrik Grubbström (Grubba) | | fprintf(stderr, "%*s* " #NAME " %p[%ld]\n", \
|
393a59 | 2000-08-16 | Henrik Grubbström (Grubba) | | indent, "", p->NAME, SIZE_T_TO_LONG(p->PIKE_CONCAT(num_,NAME)));
|
1e4e5f | 2000-04-07 | Fredrik Hübinette (Hubbe) | | #include "program_areas.h"
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | }
|
2eeba9 | 1999-03-17 | Fredrik Hübinette (Hubbe) | |
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | | break;
|
356810 | 1997-10-16 | Fredrik Hübinette (Hubbe) | | }
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | |
case T_MULTISET:
fprintf(stderr,"%*s**Describing array of multiset:\n",indent,"");
debug_dump_array(((struct multiset *)a)->ind);
break;
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | | case T_ARRAY:
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s**Describing array:\n",indent,"");
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | | debug_dump_array((struct array *)a);
break;
|
62971d | 1998-01-19 | Fredrik Hübinette (Hubbe) | |
|
61e9a0 | 1998-01-25 | Fredrik Hübinette (Hubbe) | | case T_MAPPING:
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s**Describing mapping:\n",indent,"");
|
1d152d | 2000-03-07 | Fredrik Hübinette (Hubbe) | | debug_dump_mapping((struct mapping *)a);
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s**Describing mapping data block:\n",indent,"");
describe_something( ((struct mapping *)a)->data, -2, indent+2,depth-1,flags);
|
61e9a0 | 1998-01-25 | Fredrik Hübinette (Hubbe) | | break;
|
62971d | 1998-01-19 | Fredrik Hübinette (Hubbe) | | case T_STRING:
{
struct pike_string *s=(struct pike_string *)a;
|
f5757f | 2000-08-11 | Henrik Grubbström (Grubba) | | fprintf(stderr, "%*s**String length is %ld:\n", indent, "",
DO_NOT_WARN((long)s->len));
|
62971d | 1998-01-19 | Fredrik Hübinette (Hubbe) | | if(s->len>77)
{
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s** \"%60s ...\"\n",indent,"",s->str);
|
62971d | 1998-01-19 | Fredrik Hübinette (Hubbe) | | }else{
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s** \"%s\"\n",indent,"",s->str);
|
62971d | 1998-01-19 | Fredrik Hübinette (Hubbe) | | }
break;
}
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | | }
|
25479a | 2000-03-07 | Fredrik Hübinette (Hubbe) | | }
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | void describe_something(void *a, int t, int indent, int depth, int flags)
|
25479a | 2000-03-07 | Fredrik Hübinette (Hubbe) | | {
|
111fdd | 2000-04-17 | Fredrik Hübinette (Hubbe) | | int tmp;
|
25479a | 2000-03-07 | Fredrik Hübinette (Hubbe) | | struct program *p=(struct program *)a;
if(!a) return;
if(t==-1)
{
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s**Location description: %s\n",indent,"",(char *)a);
|
25479a | 2000-03-07 | Fredrik Hübinette (Hubbe) | | return;
}
|
111fdd | 2000-04-17 | Fredrik Hübinette (Hubbe) | |
tmp=d_flag;
d_flag=0;
|
384545 | 2000-03-08 | Henrik Grubbström (Grubba) | | #ifdef DEBUG_MALLOC
if (((int)a) == 0x55555555) {
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s**Location: %p Type: %s Zapped pointer\n",indent,"",a,
|
384545 | 2000-03-08 | Henrik Grubbström (Grubba) | | get_name_of_type(t));
} else
#endif /* DEBUG_MALLOC */
|
f5757f | 2000-08-11 | Henrik Grubbström (Grubba) | | if (((ptrdiff_t)a) & 3) {
|
87c7f9 | 2000-04-19 | Martin Stjernholm | | fprintf(stderr,"%*s**Location: %p Type: %s Misaligned address\n",indent,"",a,
|
384545 | 2000-03-08 | Henrik Grubbström (Grubba) | | get_name_of_type(t));
} else {
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s**Location: %p Type: %s Refs: %d\n",indent,"",a,
|
384545 | 2000-03-08 | Henrik Grubbström (Grubba) | | get_name_of_type(t),
*(INT32 *)a);
}
|
25479a | 2000-03-07 | Fredrik Hübinette (Hubbe) | |
#ifdef DEBUG_MALLOC
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | if(!(flags & DESCRIBE_NO_DMALLOC))
debug_malloc_dump_references(a,indent+2,depth-1,flags);
|
25479a | 2000-03-07 | Fredrik Hübinette (Hubbe) | | #endif
|
87c7f9 | 2000-04-19 | Martin Stjernholm | | low_describe_something(a,t,indent,depth,flags);
|
25479a | 2000-03-07 | Fredrik Hübinette (Hubbe) | |
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"%*s*******************\n",indent,"");
|
111fdd | 2000-04-17 | Fredrik Hübinette (Hubbe) | | d_flag=tmp;
|
8fb1e1 | 1998-04-05 | Fredrik Hübinette (Hubbe) | | }
|
1f2133 | 2000-07-28 | Fredrik Hübinette (Hubbe) | | PMOD_EXPORT void describe(void *x)
|
8fb1e1 | 1998-04-05 | Fredrik Hübinette (Hubbe) | | {
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | describe_something(x, attempt_to_identify(x), 0, 2, 0);
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | | }
|
c72a4e | 1998-12-15 | Fredrik 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;
|
2eeba9 | 1999-03-17 | Fredrik 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)
{
|
1e4e5f | 2000-04-07 | Fredrik 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");
}
|
2eeba9 | 1999-03-17 | Fredrik Hübinette (Hubbe) | | }else{
fprintf(stderr," Function name: %s\n",ID_FROM_INT(s->u.object->prog,s->subtype)->name->str);
}
}
|
c72a4e | 1998-12-15 | Fredrik Hübinette (Hubbe) | | }
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | describe_something(s->u.refs,s->type,0,2,0);
|
c72a4e | 1998-12-15 | Fredrik Hübinette (Hubbe) | | }
|
7bf623 | 2000-04-23 | Martin Stjernholm | | void debug_gc_touch(void *a)
{
struct marker *m;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | if (!a) fatal("Got null pointer.\n");
|
7bf623 | 2000-04-23 | Martin Stjernholm | |
m = find_marker(a);
if (Pike_in_gc == GC_PASS_PRETOUCH) {
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | if (m) gc_fatal(a, 0, "Object touched twice.\n");
|
7bf623 | 2000-04-23 | Martin Stjernholm | | get_marker(a)->flags |= GC_TOUCHED;
}
else if (Pike_in_gc == GC_PASS_POSTTOUCH) {
|
081629 | 2000-07-03 | Martin Stjernholm | | if (!*(INT32 *) a)
gc_fatal(a, 1, "Found a thing without refs.\n");
|
7bf623 | 2000-04-23 | Martin Stjernholm | | if (m) {
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | if (!(m->flags & GC_TOUCHED))
gc_fatal(a, 2, "An existing but untouched marker found "
"for object in linked lists.\n");
|
45d87e | 2000-07-18 | Martin Stjernholm | | else if (m->flags & GC_LIVE_RECURSE ||
(m->frame && m->frame->frameflags & (GC_WEAK_REF|GC_STRONG_REF)))
gc_fatal(a, 2, "Thing still got flag from recurse list.\n");
|
081629 | 2000-07-03 | Martin Stjernholm | | else if (m->flags & GC_MARKED)
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | return;
|
081629 | 2000-07-03 | Martin Stjernholm | | else if (!(m->flags & GC_NOT_REFERENCED) || m->flags & GC_XREFERENCED)
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | gc_fatal(a, 3, "A thing with external references "
"got missed by mark pass.\n");
else if (!(m->flags & GC_CYCLE_CHECKED))
gc_fatal(a, 2, "A thing was missed by "
"both mark and cycle check pass.\n");
else if (!(m->flags & GC_IS_REFERENCED))
gc_fatal(a, 2, "An unreferenced thing "
"got missed by gc_is_referenced().\n");
else if (!(m->flags & GC_DO_FREE))
gc_fatal(a, 2, "An unreferenced thing "
"got missed by gc_do_free().\n");
else if (m->flags & GC_GOT_EXTRA_REF)
gc_fatal(a, 2, "A thing still got an extra ref.\n");
|
6d30f5 | 2000-07-11 | Martin Stjernholm | | else if (!(m->flags & GC_LIVE)) {
if (m->weak_refs > 0)
gc_fatal(a, 3, "A thing to garb is still around. "
"It's probably one with only external weak refs.\n");
|
10c4a4 | 2000-08-17 | Martin Stjernholm | | else if (m->weak_refs < 0)
gc_fatal(a, 3, "A thing which had only weak references is "
"still around after gc.\n");
|
6d30f5 | 2000-07-11 | Martin Stjernholm | | else
gc_fatal(a, 3, "A thing to garb is still around.\n");
}
|
7bf623 | 2000-04-23 | Martin Stjernholm | | }
}
else
fatal("debug_gc_touch() used in invalid gc pass.\n");
}
|
081629 | 2000-07-03 | Martin Stjernholm | | static INLINE struct marker *gc_check_debug(void *a, int weak)
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | {
|
7bf623 | 2000-04-23 | Martin Stjernholm | | struct marker *m;
|
87c7f9 | 2000-04-19 | Martin Stjernholm | |
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | if (!a) fatal("Got null pointer.\n");
|
b8a6e7 | 1996-09-25 | Fredrik Hübinette (Hubbe) | | if(check_for)
{
if(check_for == a)
{
|
081629 | 2000-07-03 | Martin Stjernholm | | gdb_gc_stop_here(a, weak);
|
b8a6e7 | 1996-09-25 | Fredrik Hübinette (Hubbe) | | }
|
4a578f | 1997-01-27 | Fredrik Hübinette (Hubbe) | | return 0;
|
b8a6e7 | 1996-09-25 | Fredrik Hübinette (Hubbe) | | }
|
e942a7 | 2000-04-15 | Fredrik Hübinette (Hubbe) | |
|
7bf623 | 2000-04-23 | Martin Stjernholm | | if (Pike_in_gc != GC_PASS_CHECK)
fatal("gc check attempted in invalid pass.\n");
m = get_marker(a);
|
87c7f9 | 2000-04-19 | Martin Stjernholm | |
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | if (!*(INT32 *)a)
gc_fatal(a, 1, "GC check on thing without refs.\n");
|
081629 | 2000-07-03 | Martin Stjernholm | | if (m->saved_refs != -1 && m->saved_refs != *(INT32 *)a)
gc_fatal(a, 1, "Refs changed in gc check pass.\n");
m->saved_refs = *(INT32 *)a;
|
ff322e | 2000-06-10 | Martin Stjernholm | | if (m->refs + m->xrefs >= *(INT32 *) a)
gc_fatal(a, 1, "Thing is getting more internal refs than refs.\n");
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | checked++;
return m;
}
#endif /* PIKE_DEBUG */
INT32 real_gc_check(void *a)
{
struct marker *m;
|
081629 | 2000-07-03 | Martin Stjernholm | | INT32 ret;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
081629 | 2000-07-03 | Martin Stjernholm | | if (!(m = gc_check_debug(a, 0))) return 0;
|
220000 | 2000-04-23 | Martin Stjernholm | | #else
m = get_marker(a);
|
b8a6e7 | 1996-09-25 | Fredrik Hübinette (Hubbe) | | #endif
|
081629 | 2000-07-03 | Martin Stjernholm | |
ret = add_ref(m);
if (m->refs >= *(INT32 *) a)
m->flags |= GC_NOT_REFERENCED;
return ret;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | }
|
e942a7 | 2000-04-15 | Fredrik Hübinette (Hubbe) | |
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | INT32 real_gc_check_weak(void *a)
{
struct marker *m;
|
081629 | 2000-07-03 | Martin Stjernholm | | INT32 ret;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
081629 | 2000-07-03 | Martin Stjernholm | | if (!(m = gc_check_debug(a, 1))) return 0;
|
10c4a4 | 2000-08-17 | Martin Stjernholm | | if (m->weak_refs < 0)
|
932633 | 2000-06-12 | Martin Stjernholm | | gc_fatal(a, 1, "Thing has already reached threshold for weak free.\n");
|
081629 | 2000-07-03 | Martin Stjernholm | | if (m->weak_refs >= *(INT32 *) a)
gc_fatal(a, 1, "Thing has gotten more weak refs than refs.\n");
|
932633 | 2000-06-12 | Martin Stjernholm | | if (m->weak_refs > m->refs + 1)
gc_fatal(a, 1, "Thing has gotten more weak refs than internal refs.\n");
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | #else
m = get_marker(a);
|
ff322e | 2000-06-10 | Martin Stjernholm | | #endif
|
081629 | 2000-07-03 | Martin Stjernholm | |
m->weak_refs++;
|
6d30f5 | 2000-07-11 | Martin Stjernholm | | gc_ext_weak_refs++;
|
081629 | 2000-07-03 | Martin Stjernholm | | if (m->weak_refs >= *(INT32 *) a)
m->weak_refs = -1;
ret = add_ref(m);
if (m->refs >= *(INT32 *) a)
m->flags |= GC_NOT_REFERENCED;
return ret;
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | }
|
b51e6d | 1998-02-18 | Fredrik Hübinette (Hubbe) | | static void init_gc(void)
{
|
424d9c | 1999-05-02 | Fredrik Hübinette (Hubbe) | | init_marker_hash();
|
45d87e | 2000-07-18 | Martin Stjernholm | | get_marker(rec_list.data);
|
b51e6d | 1998-02-18 | Fredrik Hübinette (Hubbe) | | }
static void exit_gc(void)
{
|
424d9c | 1999-05-02 | Fredrik Hübinette (Hubbe) | | #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();
|
45d87e | 2000-07-18 | Martin Stjernholm | | free_all_gc_frame_blocks();
#ifdef GC_VERBOSE
num_gc_frames = 0;
#endif
|
b51e6d | 1998-02-18 | Fredrik Hübinette (Hubbe) | | }
|
71f3a2 | 1998-11-22 | Fredrik Hübinette (Hubbe) | | #ifdef PIKE_DEBUG
|
b51e6d | 1998-02-18 | Fredrik Hübinette (Hubbe) | | void locate_references(void *a)
{
|
7bf623 | 2000-04-23 | Martin Stjernholm | | int tmp, orig_in_gc = Pike_in_gc;
|
7506fe | 2000-04-19 | Martin Stjernholm | | void *orig_check_for=check_for;
|
6bc62b | 2000-04-14 | Martin Stjernholm | | if(!Pike_in_gc)
|
b51e6d | 1998-02-18 | Fredrik Hübinette (Hubbe) | | init_gc();
|
7bf623 | 2000-04-23 | Martin Stjernholm | | Pike_in_gc = GC_PASS_LOCATE;
tmp=d_flag;
d_flag=0;
|
06ae27 | 2000-04-19 | Martin Stjernholm | |
|
b51e6d | 1998-02-18 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"**Looking for references:\n");
check_for=a;
|
25d21c | 1998-02-24 | Per Hedbor | |
|
b51e6d | 1998-02-18 | Fredrik 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();
|
20513c | 2000-04-12 | Fredrik Hübinette (Hubbe) | |
#ifdef PIKE_DEBUG
if(master_object) gc_external_mark2(master_object,0," &master_object");
|
5f61da | 2000-04-13 | Fredrik Hübinette (Hubbe) | | {
extern struct mapping *builtin_constants;
if(builtin_constants)
gc_external_mark2(builtin_constants,0," &builtin_constants");
}
|
20513c | 2000-04-12 | Fredrik Hübinette (Hubbe) | | #endif
|
b51e6d | 1998-02-18 | Fredrik Hübinette (Hubbe) | |
found_where=" in a module";
call_callback(& gc_callbacks, (void *)0);
found_where="";
|
7506fe | 2000-04-19 | Martin Stjernholm | | check_for=orig_check_for;
|
20513c | 2000-04-12 | Fredrik 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
|
7bf623 | 2000-04-23 | Martin Stjernholm | | Pike_in_gc = orig_in_gc;
|
6bc62b | 2000-04-14 | Martin Stjernholm | | if(!Pike_in_gc)
|
b51e6d | 1998-02-18 | Fredrik Hübinette (Hubbe) | | exit_gc();
|
7bf623 | 2000-04-23 | Martin Stjernholm | | d_flag=tmp;
|
b51e6d | 1998-02-18 | Fredrik Hübinette (Hubbe) | | }
|
25d21c | 1998-02-24 | Per Hedbor | | #endif
|
b51e6d | 1998-02-18 | Fredrik Hübinette (Hubbe) | |
|
1637c4 | 2000-02-01 | Fredrik Hübinette (Hubbe) | | #ifdef PIKE_DEBUG
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | void gc_add_extra_ref(void *a)
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | {
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | struct marker *m = get_marker(a);
if (m->flags & GC_GOT_EXTRA_REF)
gc_fatal(a, 0, "Thing already got an extra gc ref.\n");
m->flags |= GC_GOT_EXTRA_REF;
gc_extra_refs++;
++*(INT32 *) a;
}
|
1637c4 | 2000-02-01 | Fredrik Hübinette (Hubbe) | |
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | void gc_free_extra_ref(void *a)
{
struct marker *m = get_marker(a);
if (!(m->flags & GC_GOT_EXTRA_REF))
gc_fatal(a, 0, "Thing haven't got an extra gc ref.\n");
m->flags &= ~GC_GOT_EXTRA_REF;
gc_extra_refs--;
}
int debug_gc_is_referenced(void *a)
{
struct marker *m;
if (!a) fatal("Got null pointer.\n");
if (Pike_in_gc != GC_PASS_MARK)
fatal("gc_is_referenced() called in invalid gc pass.\n");
|
142241 | 1997-10-13 | Fredrik Hübinette (Hubbe) | |
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | if (gc_debug) {
m = find_marker(a);
if ((!m || !(m->flags & GC_TOUCHED)) &&
!safe_debug_findstring((struct pike_string *) a))
gc_fatal(a, 0, "Doing gc_is_referenced() on invalid object.\n");
if (!m) m = get_marker(a);
|
b8a6e7 | 1996-09-25 | Fredrik Hübinette (Hubbe) | | }
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | else m = get_marker(a);
|
1637c4 | 2000-02-01 | Fredrik Hübinette (Hubbe) | |
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | if (m->flags & GC_IS_REFERENCED)
gc_fatal(a, 0, "gc_is_referenced() called twice for thing.\n");
m->flags |= GC_IS_REFERENCED;
|
081629 | 2000-07-03 | Martin Stjernholm | |
return !(m->flags & GC_NOT_REFERENCED);
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | }
|
20513c | 2000-04-12 | Fredrik Hübinette (Hubbe) | | int gc_external_mark3(void *a, void *in, char *where)
|
05c7cd | 1997-07-19 | Fredrik Hübinette (Hubbe) | | {
struct marker *m;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | if (!a) fatal("Got null pointer.\n");
if (Pike_in_gc != GC_PASS_CHECK && Pike_in_gc != GC_PASS_LOCATE)
fatal("gc_external_mark() called in invalid gc pass.\n");
|
7506fe | 2000-04-19 | Martin Stjernholm | |
|
05c7cd | 1997-07-19 | Fredrik Hübinette (Hubbe) | | if(check_for)
{
if(a==check_for)
{
|
1ca3ba | 1997-10-13 | Fredrik Hübinette (Hubbe) | | char *tmp=found_where;
|
20513c | 2000-04-12 | Fredrik Hübinette (Hubbe) | | void *tmp2=found_in;
if(where) found_where=where;
if(in) found_in=in;
|
081629 | 2000-07-03 | Martin Stjernholm | | gdb_gc_stop_here(a, 0);
|
20513c | 2000-04-12 | Fredrik Hübinette (Hubbe) | |
|
1ca3ba | 1997-10-13 | Fredrik Hübinette (Hubbe) | | found_where=tmp;
|
20513c | 2000-04-12 | Fredrik Hübinette (Hubbe) | | found_in=tmp2;
|
05c7cd | 1997-07-19 | Fredrik Hübinette (Hubbe) | |
return 1;
}
return 0;
}
|
424d9c | 1999-05-02 | Fredrik Hübinette (Hubbe) | | m=get_marker(a);
|
05c7cd | 1997-07-19 | Fredrik Hübinette (Hubbe) | | m->xrefs++;
m->flags|=GC_XREFERENCED;
|
081629 | 2000-07-03 | Martin Stjernholm | | if(Pike_in_gc == GC_PASS_CHECK &&
(m->refs + m->xrefs > *(INT32 *)a ||
(m->saved_refs != -1 && m->saved_refs != *(INT32 *)a)))
|
ff322e | 2000-06-10 | Martin Stjernholm | | gc_fatal(a, 1, "Ref counts are wrong.\n");
|
05c7cd | 1997-07-19 | Fredrik Hübinette (Hubbe) | | return 0;
}
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | |
|
63709a | 2000-07-18 | Martin Stjernholm | | void debug_really_free_gc_frame(struct gc_frame *l)
{
if (l->frameflags & GC_LINK_FREED)
gc_fatal(l->data, 0, "Freeing freed gc_frame.\n");
l->frameflags |= GC_LINK_FREED;
|
a60981 | 2000-08-03 | Henrik Grubbström (Grubba) | | l->back = PREV(l) = NEXT(l) = (struct gc_frame *)(ptrdiff_t) -1;
|
63709a | 2000-07-18 | Martin Stjernholm | | really_free_gc_frame(l);
#ifdef GC_VERBOSE
num_gc_frames--;
#endif
}
#else /* PIKE_DEBUG */
#define debug_really_free_gc_frame(l) really_free_gc_frame(l)
#endif /* PIKE_DEBUG */
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | int gc_do_weak_free(void *a)
{
struct marker *m;
|
63709a | 2000-07-18 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
ff322e | 2000-06-10 | Martin Stjernholm | | if (!a) fatal("Got null pointer.\n");
|
6d30f5 | 2000-07-11 | Martin Stjernholm | | if (Pike_in_gc != GC_PASS_MARK && Pike_in_gc != GC_PASS_CYCLE &&
|
45d87e | 2000-07-18 | Martin Stjernholm | | Pike_in_gc != GC_PASS_ZAP_WEAK)
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | fatal("gc_do_weak_free() called in invalid gc pass.\n");
if (gc_debug) {
if (!(m = find_marker(a)))
gc_fatal(a, 0, "gc_do_weak_free() got unknown object.\n");
}
|
ff322e | 2000-06-10 | Martin Stjernholm | | else m = get_marker(a);
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | debug_malloc_touch(a);
if (m->weak_refs > m->refs)
gc_fatal(a, 0, "More weak references than internal references.\n");
|
63709a | 2000-07-18 | Martin Stjernholm | | #else
m = get_marker(a);
#endif
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | |
|
45d87e | 2000-07-18 | Martin Stjernholm | | if (Pike_in_gc != GC_PASS_ZAP_WEAK) {
|
10c4a4 | 2000-08-17 | Martin Stjernholm | | if (m->weak_refs < 0) {
|
6d30f5 | 2000-07-11 | Martin Stjernholm | | gc_ext_weak_refs--;
return 1;
}
}
else
if (!(m->flags & GC_MARKED)) {
|
63709a | 2000-07-18 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
6d30f5 | 2000-07-11 | Martin Stjernholm | | if (m->weak_refs <= 0)
gc_fatal(a, 0, "Too many weak refs cleared to thing with external "
"weak refs.\n");
|
63709a | 2000-07-18 | Martin Stjernholm | | #endif
|
6d30f5 | 2000-07-11 | Martin Stjernholm | | m->weak_refs--;
gc_ext_weak_refs--;
return 1;
}
return 0;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | }
|
05c7cd | 1997-07-19 | Fredrik Hübinette (Hubbe) | |
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | int gc_mark(void *a)
{
|
081629 | 2000-07-03 | Martin Stjernholm | | struct marker *m = get_marker(debug_malloc_pass(a));
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | |
|
87c7f9 | 2000-04-19 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | if (!a) fatal("Got null pointer.\n");
|
45d87e | 2000-07-18 | Martin Stjernholm | | if (Pike_in_gc != GC_PASS_MARK && Pike_in_gc != GC_PASS_ZAP_WEAK)
|
7bf623 | 2000-04-23 | Martin Stjernholm | | fatal("gc mark attempted in invalid pass.\n");
|
081629 | 2000-07-03 | Martin Stjernholm | | if (!*(INT32 *) a)
gc_fatal(a, 0, "Marked a thing without refs.\n");
|
10c4a4 | 2000-08-17 | Martin Stjernholm | | if (m->weak_refs < 0)
|
6d30f5 | 2000-07-11 | Martin Stjernholm | | gc_fatal(a, 0, "Marking thing scheduled for weak free.\n");
|
45d87e | 2000-07-18 | Martin Stjernholm | | if (Pike_in_gc == GC_PASS_ZAP_WEAK && !(m->flags & GC_MARKED))
gc_fatal(a, 0, "gc_mark() called for thing in zap weak pass "
|
6d30f5 | 2000-07-11 | Martin Stjernholm | | "that wasn't marked before.\n");
|
87c7f9 | 2000-04-19 | Martin Stjernholm | | #endif
|
45d87e | 2000-07-18 | Martin Stjernholm | | if (Pike_in_gc == GC_PASS_ZAP_WEAK)
|
6d30f5 | 2000-07-11 | Martin Stjernholm | | if (m->flags & GC_FREE_VISITED)
return 0;
else {
m->flags |= GC_FREE_VISITED;
return 1;
}
else if (m->flags & GC_MARKED) {
#ifdef PIKE_DEBUG
if (m->weak_refs != 0)
gc_fatal(a, 0, "weak_refs changed in marker already visited by gc_mark().\n");
#endif
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | return 0;
|
6d30f5 | 2000-07-11 | Martin Stjernholm | | }
else {
if (m->weak_refs) {
gc_ext_weak_refs -= m->weak_refs;
m->weak_refs = 0;
}
|
081629 | 2000-07-03 | Martin Stjernholm | | m->flags = (m->flags & ~GC_NOT_REFERENCED) | GC_MARKED;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | DO_IF_DEBUG(marked++);
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | return 1;
}
}
|
45d87e | 2000-07-18 | Martin Stjernholm | | void gc_cycle_enqueue(gc_cycle_check_cb *checkfn, void *data, int weak)
{
struct gc_frame *l = alloc_gc_frame();
#ifdef GC_VERBOSE
if (++num_gc_frames > max_gc_frames) max_gc_frames = num_gc_frames;
#endif
l->data = data;
l->u.link.checkfn = checkfn;
l->u.link.weak = weak;
l->frameflags = 0;
l->back = gc_rec_top;
#ifdef GC_STACK_DEBUG
fprintf(stderr, "enqueue %p [%p]: ", l, gc_rec_top);
describe_gc_frame(l);
fputc('\n', stderr);
#endif
gc_rec_top = l;
}
static struct gc_frame *gc_cycle_enqueue_pop(void *data)
{
struct gc_frame *l = alloc_gc_frame();
#ifdef GC_VERBOSE
if (++num_gc_frames > max_gc_frames) max_gc_frames = num_gc_frames;
#endif
l->data = data;
PREV(l) = gc_rec_last;
NEXT(l) = 0;
CYCLE(l) = 0;
l->frameflags = GC_POP_FRAME;
l->back = gc_rec_top;
#ifdef GC_STACK_DEBUG
fprintf(stderr, "enqueue %p [%p]: ", l, gc_rec_top);
describe_gc_frame(l);
fputc('\n', stderr);
#endif
gc_rec_top = l;
return l;
}
void gc_cycle_run_queue()
{
while (gc_rec_top) {
#ifdef GC_STACK_DEBUG
fprintf(stderr, "dequeue %p [%p]: ", gc_rec_top, gc_rec_top->back);
describe_gc_frame(gc_rec_top);
fputc('\n', stderr);
#endif
if (gc_rec_top->frameflags & GC_POP_FRAME) {
struct gc_frame *l = gc_rec_top->back;
gc_cycle_pop(gc_rec_top->data);
gc_rec_top = l;
} else {
struct gc_frame l = *gc_rec_top;
#ifdef PIKE_DEBUG
if (l.frameflags & GC_LINK_FREED)
gc_fatal(l.data, 0, "Accessing freed gc_frame.\n");
#endif
debug_really_free_gc_frame(gc_rec_top);
gc_rec_top = l.back;
l.u.link.checkfn(l.data, l.u.link.weak);
}
}
}
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | #ifdef GC_CYCLE_DEBUG
static int gc_cycle_indent = 0;
|
996f87 | 2000-06-12 | Martin Stjernholm | | #define CYCLE_DEBUG_MSG(M, TXT) do { \
|
45d87e | 2000-07-18 | Martin Stjernholm | | fprintf(stderr, "%*s%-35s %p [%p] ", gc_cycle_indent, "", \
|
af72c5 | 2000-07-02 | Martin Stjernholm | | (TXT), (M) ? (M)->data : 0, gc_rec_last->data); \
|
996f87 | 2000-06-12 | Martin Stjernholm | | describe_marker(M); \
} while (0)
#else
#define CYCLE_DEBUG_MSG(M, TXT) do {} while (0)
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | #endif
|
45d87e | 2000-07-18 | Martin Stjernholm | | static void rotate_rec_list (struct gc_frame *beg, struct gc_frame *pos)
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | {
|
45d87e | 2000-07-18 | Martin Stjernholm | | struct gc_frame *l;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
45d87e | 2000-07-18 | Martin Stjernholm | | CHECK_POP_FRAME(beg);
CHECK_POP_FRAME(pos);
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | if (beg == pos)
gc_fatal(beg->data, 0, "Cycle already broken at requested position.\n");
|
45d87e | 2000-07-18 | Martin Stjernholm | | if (NEXT(gc_rec_last))
gc_fatal(gc_rec_last->data, 0, "gc_rec_last not at end.\n");
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | #endif
|
45d87e | 2000-07-18 | Martin Stjernholm | | #ifdef GC_STACK_DEBUG
fprintf(stderr,"Stack before:\n");
for (l = gc_rec_top; l; l = l->back) {
fprintf(stderr, " %p ", l);
describe_gc_frame(l);
fputc('\n', stderr);
}
#endif
if (CYCLE(beg)) {
for (l = beg; CYCLE(PREV(l)) == CYCLE(beg); l = PREV(l))
CHECK_POP_FRAME(l);
CHECK_POP_FRAME(l);
if (CYCLE(l) == CYCLE(pos)) {
|
af72c5 | 2000-07-02 | Martin Stjernholm | |
|
45d87e | 2000-07-18 | Martin Stjernholm | | unsigned cycle = CYCLE(l);
for (; l && CYCLE(l) == cycle; l = NEXT(l)) {
CHECK_POP_FRAME(l);
#ifdef GC_CYCLE_DEBUG
if (CYCLE(l))
CYCLE_DEBUG_MSG(find_marker(l->data), "> rotate_rec_list, clear cycle");
#endif
CYCLE(l) = 0;
}
|
af72c5 | 2000-07-02 | Martin Stjernholm | | }
|
45d87e | 2000-07-18 | Martin Stjernholm | | else beg = l;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | }
|
45d87e | 2000-07-18 | Martin Stjernholm | | CYCLE_DEBUG_MSG(find_marker(beg->data), "> rotate_rec_list, begin at");
|
46d4e7 | 2000-06-12 | Martin Stjernholm | |
|
45d87e | 2000-07-18 | Martin Stjernholm | | {
struct gc_frame *b = beg, *p = pos, *old_rec_top;
while (b->frameflags & GC_OFF_STACK) {
if ((b = NEXT(b)) == pos) goto done;
CHECK_POP_FRAME(b);
}
while (p->frameflags & GC_OFF_STACK) {
if (!(p = NEXT(p))) goto done;
CHECK_POP_FRAME(p);
}
old_rec_top = gc_rec_top;
gc_rec_top = p->back;
p->back = b->back;
b->back = old_rec_top;
|
996f87 | 2000-06-12 | Martin Stjernholm | | }
|
45d87e | 2000-07-18 | Martin Stjernholm | | done:
|
996f87 | 2000-06-12 | Martin Stjernholm | |
{
|
45d87e | 2000-07-18 | Martin Stjernholm | | struct gc_frame *new_rec_last = PREV(pos);
NEXT(PREV(beg)) = pos;
PREV(pos) = PREV(beg);
NEXT(gc_rec_last) = beg;
PREV(beg) = gc_rec_last;
gc_rec_last = new_rec_last;
NEXT(gc_rec_last) = 0;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | }
|
af72c5 | 2000-07-02 | Martin Stjernholm | |
|
45d87e | 2000-07-18 | Martin Stjernholm | | if (beg->frameflags & GC_WEAK_REF) {
beg->frameflags &= ~GC_WEAK_REF;
pos->frameflags |= GC_WEAK_REF;
CYCLE_DEBUG_MSG(get_marker(pos->data), "> rotate_rec_list, moved weak flag");
|
af72c5 | 2000-07-02 | Martin Stjernholm | | }
|
45d87e | 2000-07-18 | Martin Stjernholm | | #ifdef GC_STACK_DEBUG
fprintf(stderr,"Stack after:\n");
for (l = gc_rec_top; l; l = l->back) {
fprintf(stderr, " %p ", l);
describe_gc_frame(l);
fputc('\n', stderr);
}
#endif
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | }
int gc_cycle_push(void *x, struct marker *m, int weak)
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | {
|
45d87e | 2000-07-18 | Martin Stjernholm | | struct marker *last = find_marker(gc_rec_last->data);
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | #ifdef PIKE_DEBUG
if (!x) fatal("Got null pointer.\n");
if (m->data != x) fatal("Got wrong marker.\n");
if (Pike_in_gc != GC_PASS_CYCLE)
fatal("GC cycle push attempted in invalid pass.\n");
if (gc_debug && !(m->flags & GC_TOUCHED))
gc_fatal(x, 0, "gc_cycle_push() called for untouched thing.\n");
|
081629 | 2000-07-03 | Martin Stjernholm | | if ((!(m->flags & GC_NOT_REFERENCED) || m->flags & GC_MARKED) &&
*(INT32 *) x)
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | gc_fatal(x, 1, "Got a referenced marker to gc_cycle_push.\n");
if (m->flags & GC_XREFERENCED)
gc_fatal(x, 1, "Doing cycle check in externally referenced thing "
"missed in mark pass.\n");
if (gc_debug) {
struct array *a;
struct object *o;
struct program *p;
struct mapping *m;
struct multiset *l;
for(a = gc_internal_array; a != &empty_array; a = a->next)
if(a == (struct array *) x) goto on_gc_internal_lists;
for(o = gc_internal_object; o; o = o->next)
if(o == (struct object *) x) goto on_gc_internal_lists;
for(p = gc_internal_program; p; p = p->next)
if(p == (struct program *) x) goto on_gc_internal_lists;
for(m = gc_internal_mapping; m; m = m->next)
if(m == (struct mapping *) x) goto on_gc_internal_lists;
for(l = gc_internal_multiset; l; l = l->next)
if(l == (struct multiset *) x) goto on_gc_internal_lists;
gc_fatal(x, 0, "gc_cycle_check() called for thing not on gc_internal lists.\n");
on_gc_internal_lists:
|
1f3b78 | 2000-06-16 | Fredrik Hübinette (Hubbe) | | ;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | }
#endif
|
11649a | 2000-04-14 | Henrik Grubbström (Grubba) | |
|
45d87e | 2000-07-18 | Martin Stjernholm | | if (last->flags & GC_LIVE_RECURSE) {
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
45d87e | 2000-07-18 | Martin Stjernholm | | if (!(last->flags & GC_LIVE))
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | gc_fatal(x, 0, "Doing live recursion from a dead thing.\n");
#endif
|
1637c4 | 2000-02-01 | Fredrik Hübinette (Hubbe) | |
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | if (m->flags & GC_CYCLE_CHECKED) {
if (!(m->flags & GC_LIVE)) {
#ifdef PIKE_DEBUG
if (m->flags & GC_LIVE_RECURSE)
gc_fatal(x, 0, "Mark live recursion attempted twice into thing.\n");
#endif
goto live_recurse;
}
|
996f87 | 2000-06-12 | Martin Stjernholm | | CYCLE_DEBUG_MSG(m, "gc_cycle_push, no live recurse");
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | }
else {
int flags;
|
996f87 | 2000-06-12 | Martin Stjernholm | | CYCLE_DEBUG_MSG(m, "gc_cycle_push, live rec done");
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | do {
|
45d87e | 2000-07-18 | Martin Stjernholm | | last->flags &= ~GC_LIVE_RECURSE;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | #ifdef GC_CYCLE_DEBUG
gc_cycle_indent -= 2;
|
45d87e | 2000-07-18 | Martin Stjernholm | | CYCLE_DEBUG_MSG(find_marker(gc_rec_last->data),
"> gc_cycle_push, unwinding live");
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | #endif
|
45d87e | 2000-07-18 | Martin Stjernholm | | while (1) {
struct gc_frame *l = gc_rec_top;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
45d87e | 2000-07-18 | Martin Stjernholm | | if (!gc_rec_top)
fatal("Expected a gc_cycle_pop entry in gc_rec_top.\n");
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | #endif
|
45d87e | 2000-07-18 | Martin Stjernholm | | gc_rec_top = l->back;
if (l->frameflags & GC_POP_FRAME) {
gc_rec_last = PREV(l);
debug_really_free_gc_frame(l);
break;
}
debug_really_free_gc_frame(l);
}
last = find_marker(gc_rec_last->data);
} while (last->flags & GC_LIVE_RECURSE);
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | }
return 0;
}
|
a595b9 | 2000-06-11 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
45d87e | 2000-07-18 | Martin Stjernholm | | if (weak < 0 && gc_rec_last->frameflags & GC_FOLLOWED_NONSTRONG)
gc_fatal(x, 0, "Followed strong link too late.\n");
if (weak >= 0) gc_rec_last->frameflags |= GC_FOLLOWED_NONSTRONG;
|
a595b9 | 2000-06-11 | Martin Stjernholm | | #endif
|
6d30f5 | 2000-07-11 | Martin Stjernholm | | if (weak > 0) {
#ifdef PIKE_DEBUG
|
10c4a4 | 2000-08-17 | Martin Stjernholm | | if (m->weak_refs == 0)
|
6d30f5 | 2000-07-11 | Martin Stjernholm | | gc_fatal(x, 0, "Followed weak ref to thing that should have none left.\n");
|
10c4a4 | 2000-08-17 | Martin Stjernholm | |
m->weak_refs--;
|
6d30f5 | 2000-07-11 | Martin Stjernholm | | #endif
gc_ext_weak_refs--;
}
|
45d87e | 2000-07-18 | Martin Stjernholm | | if (m->frame && !(m->frame->frameflags & GC_OFF_STACK)) {
|
932633 | 2000-06-12 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
45d87e | 2000-07-18 | Martin Stjernholm | | if (gc_rec_last == &rec_list)
|
932633 | 2000-06-12 | Martin Stjernholm | | gc_fatal(x, 0, "Cyclic ref involves dummy rec_list marker.\n");
|
45d87e | 2000-07-18 | Martin Stjernholm | | CHECK_POP_FRAME(gc_rec_last);
CHECK_POP_FRAME(m->frame);
|
932633 | 2000-06-12 | Martin Stjernholm | | #endif
|
45d87e | 2000-07-18 | Martin Stjernholm | | if (m != last) {
struct gc_frame *p, *weak_ref = 0, *nonstrong_ref = 0;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | if (!weak) {
|
45d87e | 2000-07-18 | Martin Stjernholm | | struct gc_frame *q;
|
af72c5 | 2000-07-02 | Martin Stjernholm | | CYCLE_DEBUG_MSG(m, "gc_cycle_push, search normal");
|
45d87e | 2000-07-18 | Martin Stjernholm | | for (q = m->frame, p = NEXT(q);; q = p, p = NEXT(p)) {
CHECK_POP_FRAME(p);
if (p->frameflags & (GC_WEAK_REF|GC_STRONG_REF)) {
if (p->frameflags & GC_WEAK_REF) weak_ref = p;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | else if (!nonstrong_ref) nonstrong_ref = q;
}
if (p == gc_rec_last) break;
}
}
else if (weak < 0) {
|
af72c5 | 2000-07-02 | Martin Stjernholm | | CYCLE_DEBUG_MSG(m, "gc_cycle_push, search strong");
|
45d87e | 2000-07-18 | Martin Stjernholm | | for (p = NEXT(m->frame);; p = NEXT(p)) {
CHECK_POP_FRAME(p);
if (p->frameflags & GC_WEAK_REF) weak_ref = p;
if (!(p->frameflags & GC_STRONG_REF)) nonstrong_ref = p;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | if (p == gc_rec_last) break;
}
#ifdef PIKE_DEBUG
|
af72c5 | 2000-07-02 | Martin Stjernholm | | if (p == gc_rec_last && !nonstrong_ref)
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | gc_fatal(x, 0, "Only strong links in cycle.\n");
#endif
}
else {
|
45d87e | 2000-07-18 | Martin Stjernholm | | struct gc_frame *q;
|
af72c5 | 2000-07-02 | Martin Stjernholm | | CYCLE_DEBUG_MSG(m, "gc_cycle_push, search weak");
|
45d87e | 2000-07-18 | Martin Stjernholm | | for (q = m->frame, p = NEXT(q);; q = p, p = NEXT(p)) {
CHECK_POP_FRAME(p);
if (!(p->frameflags & GC_WEAK_REF) && !nonstrong_ref)
nonstrong_ref = q;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | if (p == gc_rec_last) break;
}
}
|
45d87e | 2000-07-18 | Martin Stjernholm | | if (weak_ref) {
CYCLE_DEBUG_MSG(find_marker(weak_ref->data),
"gc_cycle_push, weak break");
rotate_rec_list(m->frame, weak_ref);
}
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | |
|
45d87e | 2000-07-18 | Martin Stjernholm | | else if (weak < 0) {
if (m->frame->frameflags & GC_STRONG_REF)
nonstrong_ref->frameflags =
(nonstrong_ref->frameflags & ~GC_WEAK_REF) | GC_STRONG_REF;
else
m->frame->frameflags =
(m->frame->frameflags & ~GC_WEAK_REF) | GC_STRONG_REF;
CYCLE_DEBUG_MSG(find_marker(nonstrong_ref->data),
"gc_cycle_push, nonstrong break");
rotate_rec_list(m->frame, nonstrong_ref);
}
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | |
|
45d87e | 2000-07-18 | Martin Stjernholm | | else if (nonstrong_ref) {
if (nonstrong_ref != m->frame) {
CYCLE_DEBUG_MSG(find_marker(nonstrong_ref->data),
"gc_cycle_push, weaker break");
rotate_rec_list(m->frame, nonstrong_ref);
|
46d4e7 | 2000-06-12 | Martin Stjernholm | | }
|
af72c5 | 2000-07-02 | Martin Stjernholm | | }
|
45d87e | 2000-07-18 | Martin Stjernholm | |
else if (!weak) {
unsigned cycle = CYCLE(m->frame) ? CYCLE(m->frame) : ++last_cycle;
if (cycle == CYCLE(gc_rec_last))
CYCLE_DEBUG_MSG(m, "gc_cycle_push, old cycle");
else {
CYCLE_DEBUG_MSG(m, "gc_cycle_push, cycle");
for (p = m->frame;; p = NEXT(p)) {
CYCLE(p) = cycle;
CYCLE_DEBUG_MSG(find_marker(p->data), "> gc_cycle_push, mark cycle");
if (p == gc_rec_last) break;
}}}}}
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | |
else
if (!(m->flags & GC_CYCLE_CHECKED)) {
|
45d87e | 2000-07-18 | Martin Stjernholm | | struct gc_frame *l, *prev_rec_last = gc_rec_last;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | #ifdef PIKE_DEBUG
cycle_checked++;
|
45d87e | 2000-07-18 | Martin Stjernholm | | if (m->frame)
gc_fatal(x, 0, "Marker already got a frame.\n");
if (NEXT(gc_rec_last))
gc_fatal(gc_rec_last->data, 0, "Not at end of list.\n");
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | #endif
|
45d87e | 2000-07-18 | Martin Stjernholm | | NEXT(gc_rec_last) = m->frame = l = gc_cycle_enqueue_pop(x);
m->flags |= GC_CYCLE_CHECKED | (last->flags & GC_LIVE);
if (weak) {
if (weak > 0) l->frameflags |= GC_WEAK_REF;
else l->frameflags |= GC_STRONG_REF;
}
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | |
#ifdef GC_CYCLE_DEBUG
|
996f87 | 2000-06-12 | Martin Stjernholm | | if (weak > 0) CYCLE_DEBUG_MSG(m, "gc_cycle_push, recurse weak");
else if (weak < 0) CYCLE_DEBUG_MSG(m, "gc_cycle_push, recurse strong");
else CYCLE_DEBUG_MSG(m, "gc_cycle_push, recurse");
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | gc_cycle_indent += 2;
#endif
|
45d87e | 2000-07-18 | Martin Stjernholm | | gc_rec_last = l;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | return 1;
}
|
45d87e | 2000-07-18 | Martin Stjernholm | | if (!(last->flags & GC_LIVE) || m->flags & GC_LIVE) {
|
996f87 | 2000-06-12 | Martin Stjernholm | | CYCLE_DEBUG_MSG(m, "gc_cycle_push, no recurse");
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | return 0;
}
live_recurse:
#ifdef PIKE_DEBUG
if (m->flags & GC_LIVE)
fatal("Shouldn't live recurse when there's nothing to do.\n");
#endif
m->flags |= GC_LIVE|GC_LIVE_RECURSE;
if (m->flags & GC_GOT_DEAD_REF) {
gc_free_extra_ref(x);
if (!--*(INT32 *) x) {
#ifdef PIKE_DEBUG
gc_fatal(x, 0, "Thing got zero refs after removing the dead gc ref.\n");
#endif
}
}
|
45d87e | 2000-07-18 | Martin Stjernholm | | {
struct gc_frame *l = gc_cycle_enqueue_pop(x);
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | #ifdef GC_CYCLE_DEBUG
|
45d87e | 2000-07-18 | Martin Stjernholm | | CYCLE_DEBUG_MSG(m, "gc_cycle_push, live recurse");
gc_cycle_indent += 2;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | #endif
|
45d87e | 2000-07-18 | Martin Stjernholm | | gc_rec_last = l;
}
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | return 1;
}
|
45d87e | 2000-07-18 | Martin Stjernholm | | static void gc_cycle_pop(void *a)
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | {
|
45d87e | 2000-07-18 | Martin Stjernholm | | struct marker *m = find_marker(a);
struct gc_frame *here, *base, *p;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | |
#ifdef PIKE_DEBUG
|
45d87e | 2000-07-18 | Martin Stjernholm | | if (!a) fatal("Got null pointer.\n");
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | if (Pike_in_gc != GC_PASS_CYCLE)
fatal("GC cycle pop attempted in invalid pass.\n");
if (!(m->flags & GC_CYCLE_CHECKED))
gc_fatal(a, 0, "Marker being popped doesn't have GC_CYCLE_CHECKED.\n");
|
081629 | 2000-07-03 | Martin Stjernholm | | if ((!(m->flags & GC_NOT_REFERENCED) || m->flags & GC_MARKED) &&
*(INT32 *) a)
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | gc_fatal(a, 1, "Got a referenced marker to gc_cycle_pop.\n");
if (m->flags & GC_XREFERENCED)
gc_fatal(a, 1, "Doing cycle check in externally referenced thing "
"missed in mark pass.\n");
#endif
#ifdef GC_CYCLE_DEBUG
gc_cycle_indent -= 2;
#endif
|
46d4e7 | 2000-06-12 | Martin Stjernholm | | if (m->flags & GC_LIVE_RECURSE) {
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | m->flags &= ~GC_LIVE_RECURSE;
|
45d87e | 2000-07-18 | Martin Stjernholm | | CYCLE_DEBUG_MSG(m, "gc_cycle_pop_live");
gc_rec_last = PREV(gc_rec_top);
debug_really_free_gc_frame(gc_rec_top);
|
996f87 | 2000-06-12 | Martin Stjernholm | | return;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | }
|
45d87e | 2000-07-18 | Martin Stjernholm | | here = m->frame;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
45d87e | 2000-07-18 | Martin Stjernholm | | if (!here || here->data != a)
gc_fatal(a, 0, "Marker being popped has no or invalid frame.\n");
CHECK_POP_FRAME(here);
CHECK_POP_FRAME(gc_rec_last);
if (here->frameflags & GC_OFF_STACK)
|
46d4e7 | 2000-06-12 | Martin Stjernholm | | gc_fatal(a, 0, "Marker being popped isn't on stack.\n");
|
a60981 | 2000-08-03 | Henrik Grubbström (Grubba) | | here->back = (struct gc_frame *)(ptrdiff_t) -1;
|
932633 | 2000-06-12 | Martin Stjernholm | | #endif
|
45d87e | 2000-07-18 | Martin Stjernholm | | here->frameflags |= GC_OFF_STACK;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | |
|
45d87e | 2000-07-18 | Martin Stjernholm | | for (base = PREV(here), p = here;; base = p, p = NEXT(p)) {
if (base == here) {
|
a60981 | 2000-08-03 | Henrik Grubbström (Grubba) | | DO_IF_DEBUG(m->frame->back = (struct gc_frame *)(ptrdiff_t) -1);
|
af72c5 | 2000-07-02 | Martin Stjernholm | | CYCLE_DEBUG_MSG(m, "gc_cycle_pop, keep cycle");
return;
}
|
45d87e | 2000-07-18 | Martin Stjernholm | | CHECK_POP_FRAME(p);
if (!(CYCLE(p) && CYCLE(p) == CYCLE(base)))
|
af72c5 | 2000-07-02 | Martin Stjernholm | | break;
}
|
45d87e | 2000-07-18 | Martin Stjernholm | | gc_rec_last = base;
while ((p = NEXT(base))) {
struct marker *pm = find_marker(p->data);
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
45d87e | 2000-07-18 | Martin Stjernholm | | if (pm->frame != p)
gc_fatal(p->data, 0, "Bogus marker for thing being popped.\n");
if (pm->flags & GC_GOT_DEAD_REF)
gc_fatal(p->data, 0, "Didn't expect a dead extra ref.\n");
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | #endif
|
45d87e | 2000-07-18 | Martin Stjernholm | | p->frameflags &= ~(GC_WEAK_REF|GC_STRONG_REF);
if (pm->flags & GC_LIVE_OBJ) {
gc_add_extra_ref(p->data);
base = p;
|
a60981 | 2000-08-03 | Henrik Grubbström (Grubba) | | DO_IF_DEBUG(PREV(p) = (struct gc_frame *)(ptrdiff_t) -1);
|
45d87e | 2000-07-18 | Martin Stjernholm | | CYCLE_DEBUG_MSG(pm, "gc_cycle_pop, put on kill list");
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | }
|
45d87e | 2000-07-18 | Martin Stjernholm | | else {
if (!(pm->flags & GC_LIVE)) {
|
996f87 | 2000-06-12 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
45d87e | 2000-07-18 | Martin Stjernholm | | if (pm->flags & GC_GOT_DEAD_REF)
gc_fatal(pm->data, 0,
"A thing already got an extra dead cycle ref.\n");
#endif
gc_add_extra_ref(pm->data);
pm->flags |= GC_GOT_DEAD_REF;
|
996f87 | 2000-06-12 | Martin Stjernholm | | }
|
45d87e | 2000-07-18 | Martin Stjernholm | | NEXT(base) = NEXT(p);
CYCLE_DEBUG_MSG(pm, "gc_cycle_pop, pop off");
pm->frame = 0;
debug_really_free_gc_frame(p);
|
996f87 | 2000-06-12 | Martin Stjernholm | | }
|
8fb1e1 | 1998-04-05 | Fredrik Hübinette (Hubbe) | | }
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | |
|
45d87e | 2000-07-18 | Martin Stjernholm | | if (base != gc_rec_last) {
NEXT(base) = kill_list;
kill_list = NEXT(gc_rec_last);
NEXT(gc_rec_last) = 0;
}
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | }
void do_gc_recurse_svalues(struct svalue *s, int num)
{
gc_recurse_svalues(s, num);
}
|
1637c4 | 2000-02-01 | Fredrik Hübinette (Hubbe) | |
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | void do_gc_recurse_short_svalue(union anything *u, TYPE_T type)
{
gc_recurse_short_svalue(u, type);
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | }
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | |
int gc_do_free(void *a)
{
struct marker *m;
#ifdef PIKE_DEBUG
if (!a) fatal("Got null pointer.\n");
if (Pike_in_gc != GC_PASS_FREE)
fatal("gc free attempted in invalid pass.\n");
#endif
m=find_marker(debug_malloc_pass(a));
if (!m) return 0;
#ifdef PIKE_DEBUG
|
081629 | 2000-07-03 | Martin Stjernholm | | if (*(INT32 *) a > !!(m->flags & GC_GOT_EXTRA_REF)) {
if (!(m->flags & GC_NOT_REFERENCED) || m->flags & GC_MARKED)
gc_fatal(a, 0, "gc_do_free() called for referenced thing.\n");
if (gc_debug &&
(m->flags & (GC_TOUCHED|GC_MARKED|GC_IS_REFERENCED)) == GC_TOUCHED)
gc_fatal(a, 0, "gc_do_free() called without prior call to "
"gc_mark() or gc_is_referenced().\n");
}
|
be39f5 | 2000-07-03 | Martin Stjernholm | | if((m->flags & (GC_MARKED|GC_XREFERENCED)) == GC_XREFERENCED)
gc_fatal(a, 1, "Thing with external reference missed in gc mark pass.\n");
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | if ((m->flags & (GC_DO_FREE|GC_LIVE)) == GC_LIVE) live_ref++;
m->flags |= GC_DO_FREE;
|
1637c4 | 2000-02-01 | Fredrik Hübinette (Hubbe) | | #endif
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | |
|
081629 | 2000-07-03 | Martin Stjernholm | | return !(m->flags & GC_LIVE);
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | }
static void warn_bad_cycles()
{
JMP_BUF uwp;
|
d70a3e | 2000-07-07 | Martin Stjernholm | | struct array *obj_arr = 0;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | if (!SETJMP(uwp)) {
|
45d87e | 2000-07-18 | Martin Stjernholm | | struct gc_frame *p;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | unsigned cycle = 0;
|
d70a3e | 2000-07-07 | Martin Stjernholm | | obj_arr = allocate_array(0);
|
4be85a | 2000-07-07 | Martin Stjernholm | |
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | for (p = kill_list; p;) {
|
45d87e | 2000-07-18 | Martin Stjernholm | | if ((cycle = CYCLE(p))) {
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | push_object((struct object *) p->data);
obj_arr = append_array(obj_arr, --sp);
}
|
45d87e | 2000-07-18 | Martin Stjernholm | | p = NEXT(p);
|
7e8ea3 | 2000-08-13 | Henrik Grubbström (Grubba) | | if (p ? ((unsigned)(CYCLE(p) != cycle)) : cycle) {
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | if (obj_arr->size >= 2) {
push_constant_text("gc");
push_constant_text("bad_cycle");
push_array(obj_arr);
|
4be85a | 2000-07-07 | Martin Stjernholm | | obj_arr = 0;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | SAFE_APPLY_MASTER("runtime_warning", 3);
pop_stack();
obj_arr = allocate_array(0);
}
else obj_arr = resize_array(obj_arr, 0);
}
if (!p) break;
}
}
|
d70a3e | 2000-07-07 | Martin Stjernholm | |
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | UNSETJMP(uwp);
|
d70a3e | 2000-07-07 | Martin Stjernholm | | if (obj_arr) free_array(obj_arr);
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | }
int do_gc(void)
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | | {
double tmp;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | int objs, pre_kill_objs;
|
dc296b | 1997-10-21 | Fredrik Hübinette (Hubbe) | | double multiplier;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | struct array *a;
struct multiset *l;
struct mapping *m;
struct program *p;
struct object *o;
|
db62dc | 2000-04-14 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | #ifdef HAVE_GETHRTIME
|
48f1c6 | 2000-07-04 | Henrik Grubbström (Grubba) | | hrtime_t gcstarttime = 0;
|
b088ab | 2000-04-15 | Martin Stjernholm | | #endif
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | unsigned destroy_count, obj_count;
|
db62dc | 2000-04-14 | Martin Stjernholm | | #endif
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | |
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | if(Pike_in_gc) return 0;
|
7bf623 | 2000-04-23 | Martin Stjernholm | | init_gc();
Pike_in_gc=GC_PASS_PREPARE;
#ifdef PIKE_DEBUG
gc_debug = d_flag;
#endif
|
890e5b | 1996-11-21 | Fredrik Hübinette (Hubbe) | |
|
7f9b4c | 2000-04-19 | Martin Stjernholm | | destruct_objects_to_destruct();
|
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) | |
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | objs=num_objects;
last_cycle = 0;
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | |
|
71f3a2 | 1998-11-22 | Fredrik Hübinette (Hubbe) | | #ifdef PIKE_DEBUG
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | if(GC_VERBOSE_DO(1 ||) t_flag) {
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"Garbage collecting ... ");
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | GC_VERBOSE_DO(fprintf(stderr, "\n"));
|
b088ab | 2000-04-15 | Martin Stjernholm | | #ifdef HAVE_GETHRTIME
|
6bc62b | 2000-04-14 | Martin Stjernholm | | gcstarttime = gethrtime();
|
b088ab | 2000-04-15 | Martin Stjernholm | | #endif
|
6bc62b | 2000-04-14 | Martin Stjernholm | | }
|
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
|
4452c1 | 2000-02-02 | Fredrik Hübinette (Hubbe) | | last_gc=TIME(0);
|
dc296b | 1997-10-21 | Fredrik Hübinette (Hubbe) | | multiplier=pow(MULTIPLIER, (double) num_allocs / (double) alloc_threshold);
objects_alloced*=multiplier;
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | | objects_alloced += (double) num_allocs;
|
dc296b | 1997-10-21 | Fredrik Hübinette (Hubbe) | | objects_freed*=multiplier;
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | |
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | |
|
08679c | 2000-04-26 | Martin Stjernholm | |
|
7bf623 | 2000-04-23 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | weak_freed = checked = marked = cycle_checked = live_ref = 0;
|
7bf623 | 2000-04-23 | Martin Stjernholm | | if (gc_debug) {
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | unsigned n;
|
7bf623 | 2000-04-23 | Martin Stjernholm | | Pike_in_gc = GC_PASS_PRETOUCH;
n = gc_touch_all_arrays();
n += gc_touch_all_multisets();
n += gc_touch_all_mappings();
n += gc_touch_all_programs();
n += gc_touch_all_objects();
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | if (n != (unsigned) num_objects)
|
7bf623 | 2000-04-23 | Martin Stjernholm | | fatal("Object count wrong before gc; expected %d, got %d.\n", num_objects, n);
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | GC_VERBOSE_DO(fprintf(stderr, "| pretouch: %u things\n", n));
|
7bf623 | 2000-04-23 | Martin Stjernholm | | }
#endif
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | |
|
7bf623 | 2000-04-23 | Martin Stjernholm | | Pike_in_gc=GC_PASS_CHECK;
|
6d30f5 | 2000-07-11 | Martin Stjernholm | | gc_ext_weak_refs = 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();
|
20513c | 2000-04-12 | Fredrik Hübinette (Hubbe) | |
#ifdef PIKE_DEBUG
|
48f1c6 | 2000-07-04 | Henrik Grubbström (Grubba) | | if(master_object)
gc_external_mark2(master_object,0," &master_object");
|
5f61da | 2000-04-13 | Fredrik Hübinette (Hubbe) | | {
extern struct mapping *builtin_constants;
if(builtin_constants)
gc_external_mark2(builtin_constants,0," &builtin_constants");
}
|
20513c | 2000-04-12 | Fredrik Hübinette (Hubbe) | | #endif
|
7bf623 | 2000-04-23 | Martin Stjernholm | | |
5fbe6e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | */
|
4a578f | 1997-01-27 | Fredrik Hübinette (Hubbe) | | call_callback(& gc_callbacks, (void *)0);
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | |
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | GC_VERBOSE_DO(fprintf(stderr, "| check: %u references checked\n", checked));
|
7bf623 | 2000-04-23 | Martin Stjernholm | | Pike_in_gc=GC_PASS_MARK;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | |
gc_internal_array = empty_array.next;
gc_internal_multiset = first_multiset;
gc_internal_mapping = first_mapping;
gc_internal_program = first_program;
gc_internal_object = first_object;
|
a99145 | 1997-07-08 | Fredrik Hübinette (Hubbe) | |
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | gc_mark_all_arrays();
|
991e5a | 1998-04-28 | Fredrik Hübinette (Hubbe) | | run_queue(&gc_mark_queue);
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | gc_mark_all_multisets();
|
991e5a | 1998-04-28 | Fredrik Hübinette (Hubbe) | | run_queue(&gc_mark_queue);
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | gc_mark_all_mappings();
|
991e5a | 1998-04-28 | Fredrik Hübinette (Hubbe) | | run_queue(&gc_mark_queue);
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | gc_mark_all_programs();
|
991e5a | 1998-04-28 | Fredrik Hübinette (Hubbe) | | run_queue(&gc_mark_queue);
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | | gc_mark_all_objects();
|
991e5a | 1998-04-28 | Fredrik Hübinette (Hubbe) | | run_queue(&gc_mark_queue);
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | |
GC_VERBOSE_DO(fprintf(stderr,
"| mark: %u markers referenced,\n"
"| %u weak references freed, %d things really freed\n",
marked, weak_freed, objs - num_objects));
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | |
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | Pike_in_gc=GC_PASS_CYCLE;
#ifdef PIKE_DEBUG
obj_count = num_objects;
|
45d87e | 2000-07-18 | Martin Stjernholm | | max_gc_frames = 0;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | #endif
|
4a578f | 1997-01-27 | Fredrik Hübinette (Hubbe) | |
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | |
gc_cycle_check_all_objects();
gc_cycle_check_all_arrays();
gc_cycle_check_all_multisets();
gc_cycle_check_all_mappings();
gc_cycle_check_all_programs();
|
08679c | 2000-04-26 | Martin Stjernholm | |
|
20513c | 2000-04-12 | Fredrik Hübinette (Hubbe) | | #ifdef PIKE_DEBUG
|
45d87e | 2000-07-18 | Martin Stjernholm | | if (gc_rec_top)
fatal("gc_rec_top not empty at end of cycle check pass.\n");
if (NEXT(&rec_list) || gc_rec_last != &rec_list || gc_rec_top)
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | fatal("Recurse list not empty or inconsistent after cycle check pass.\n");
|
20513c | 2000-04-12 | Fredrik Hübinette (Hubbe) | | #endif
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | |
GC_VERBOSE_DO(fprintf(stderr,
"| cycle: %u internal things visited, %u cycle ids used,\n"
|
45d87e | 2000-07-18 | Martin Stjernholm | | "| %u weak references freed, %d things really freed,\n"
"| space for %u gc frames used\n",
cycle_checked, last_cycle, weak_freed, obj_count - num_objects,
max_gc_frames));
if (gc_ext_weak_refs) {
size_t to_free = gc_ext_weak_refs;
#ifdef PIKE_DEBUG
obj_count = num_objects;
#endif
Pike_in_gc = GC_PASS_ZAP_WEAK;
gc_zap_ext_weak_refs_in_arrays();
if (gc_ext_weak_refs) {
gc_zap_ext_weak_refs_in_mappings();
if (gc_ext_weak_refs) {
gc_zap_ext_weak_refs_in_programs();
if (gc_ext_weak_refs)
gc_zap_ext_weak_refs_in_objects();
}
}
GC_VERBOSE_DO(
fprintf(stderr,
"| zap weak: freed %u external weak refs, %d things really freed\n",
to_free - gc_ext_weak_refs, obj_count - num_objects));
}
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | |
|
7bf623 | 2000-04-23 | Martin Stjernholm | | Pike_in_gc=GC_PASS_FREE;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | #ifdef PIKE_DEBUG
weak_freed = 0;
obj_count = num_objects;
#endif
|
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();
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | gc_free_all_unreferenced_objects();
GC_VERBOSE_DO(fprintf(stderr, "| free: %d really freed, %u left with live references\n",
obj_count - num_objects, live_ref));
gc_internal_array = &empty_array;
gc_internal_multiset = 0;
gc_internal_mapping = 0;
gc_internal_program = 0;
gc_internal_object = 0;
|
c94c37 | 1996-03-28 | Fredrik Hübinette (Hubbe) | |
|
20513c | 2000-04-12 | Fredrik Hübinette (Hubbe) | | #ifdef PIKE_DEBUG
|
ad2bdb | 2000-04-12 | Fredrik Hübinette (Hubbe) | | if(fatal_after_gc) fatal(fatal_after_gc);
|
20513c | 2000-04-12 | Fredrik Hübinette (Hubbe) | | #endif
|
10c4a4 | 2000-08-17 | Martin Stjernholm | |
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | Pike_in_gc=GC_PASS_KILL;
pre_kill_objs = num_objects;
if (last_cycle) {
objs -= num_objects;
warn_bad_cycles();
objs += num_objects;
}
#ifdef PIKE_DEBUG
destroy_count = 0;
#endif
|
fb5e41 | 2000-07-18 | Martin Stjernholm | | while (kill_list) {
struct gc_frame *next = NEXT(kill_list);
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | struct object *o = (struct object *) kill_list->data;
#ifdef PIKE_DEBUG
|
45d87e | 2000-07-18 | Martin Stjernholm | | if ((get_marker(kill_list->data)->flags & (GC_LIVE|GC_LIVE_OBJ)) !=
(GC_LIVE|GC_LIVE_OBJ))
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | gc_fatal(o, 0, "Invalid thing in kill list.\n");
|
45d87e | 2000-07-18 | Martin Stjernholm | | if (o->parent && !o->parent->prog &&
get_marker(o->parent)->flags & GC_LIVE_OBJ)
gc_fatal(o, 0, "GC destructed parent prematurely.\n");
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | #endif
GC_VERBOSE_DO(fprintf(stderr, "| Killing %p with %d refs\n",
o, o->refs));
destruct(o);
free_object(o);
gc_free_extra_ref(o);
#ifdef PIKE_DEBUG
destroy_count++;
#endif
|
63709a | 2000-07-18 | Martin Stjernholm | | debug_really_free_gc_frame(kill_list);
|
fb5e41 | 2000-07-18 | Martin Stjernholm | | kill_list = next;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | }
GC_VERBOSE_DO(fprintf(stderr, "| kill: %u objects killed, %d things really freed\n",
destroy_count, pre_kill_objs - num_objects));
|
7bf623 | 2000-04-23 | Martin Stjernholm | | Pike_in_gc=GC_PASS_DESTRUCT;
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | |
GC_VERBOSE_DO(obj_count = num_objects);
|
7bf623 | 2000-04-23 | Martin Stjernholm | | destruct_objects_to_destruct();
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | GC_VERBOSE_DO(fprintf(stderr, "| destruct: %d things really freed\n",
obj_count - num_objects));
|
08679c | 2000-04-26 | Martin Stjernholm | |
|
7bf623 | 2000-04-23 | Martin Stjernholm | | #ifdef PIKE_DEBUG
if (gc_debug) {
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | unsigned n;
|
7bf623 | 2000-04-23 | Martin Stjernholm | | Pike_in_gc=GC_PASS_POSTTOUCH;
n = gc_touch_all_arrays();
n += gc_touch_all_multisets();
n += gc_touch_all_mappings();
n += gc_touch_all_programs();
n += gc_touch_all_objects();
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | if (n != (unsigned) num_objects)
|
7bf623 | 2000-04-23 | Martin Stjernholm | | fatal("Object count wrong after gc; expected %d, got %d.\n", num_objects, n);
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | GC_VERBOSE_DO(fprintf(stderr, "| posttouch: %u things\n", n));
|
7bf623 | 2000-04-23 | Martin Stjernholm | | if(fatal_after_gc) fatal(fatal_after_gc);
}
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | if (gc_extra_refs)
fatal("Lost track of %d extra refs to things in gc.\n", gc_extra_refs);
|
6d30f5 | 2000-07-11 | Martin Stjernholm | | if (gc_ext_weak_refs)
fatal("Still got %u external weak references to internal things in gc.\n",
gc_ext_weak_refs);
|
7bf623 | 2000-04-23 | Martin Stjernholm | | #endif
Pike_in_gc=0;
|
b51e6d | 1998-02-18 | Fredrik Hübinette (Hubbe) | | exit_gc();
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | |
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | |
if (pre_kill_objs < num_objects) objs -= pre_kill_objs;
else objs -= num_objects;
objects_freed += (double) objs;
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | |
tmp=(double)num_objects;
tmp=tmp * GC_CONST/100.0 * (objects_alloced+1.0) / (objects_freed+1.0);
|
6acd50 | 2000-05-01 | Fredrik Noring | | if(alloc_threshold + num_allocs <= tmp)
tmp = (double)(alloc_threshold + num_allocs);
if(tmp < MIN_ALLOC_THRESHOLD)
tmp = (double)MIN_ALLOC_THRESHOLD;
if(tmp > MAX_ALLOC_THRESHOLD)
tmp = (double)MAX_ALLOC_THRESHOLD;
|
f5757f | 2000-08-11 | Henrik Grubbström (Grubba) | | alloc_threshold = (ptrdiff_t)tmp;
|
6acd50 | 2000-05-01 | Fredrik Noring | |
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | | num_allocs=0;
|
71f3a2 | 1998-11-22 | Fredrik Hübinette (Hubbe) | | #ifdef PIKE_DEBUG
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | if(GC_VERBOSE_DO(1 ||) t_flag)
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | {
#ifdef HAVE_GETHRTIME
|
6bc62b | 2000-04-14 | Martin Stjernholm | | fprintf(stderr,"done (freed %ld of %ld objects), %ld ms.\n",
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | (long)objs,(long)objs + num_objects,
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | (long)((gethrtime() - gcstarttime)/1000000));
|
b088ab | 2000-04-15 | Martin Stjernholm | | #else
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | fprintf(stderr,"done (freed %ld of %ld objects)\n",
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | | (long)objs,(long)objs + num_objects);
|
b088ab | 2000-04-15 | Martin Stjernholm | | #endif
|
a4033e | 2000-04-14 | Fredrik Hübinette (Hubbe) | | }
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | | #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
|
e2d9e6 | 2000-06-10 | Martin Stjernholm | |
return objs;
|
693018 | 1996-02-25 | Fredrik Hübinette (Hubbe) | | }
|
1637c4 | 2000-02-01 | Fredrik 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");
|
905e0c | 2000-08-11 | Henrik Grubbström (Grubba) | | push_int64(alloc_threshold);
|
1637c4 | 2000-02-01 | Fredrik Hübinette (Hubbe) | |
push_constant_text("objects_alloced");
|
905e0c | 2000-08-11 | Henrik Grubbström (Grubba) | | push_int64(objects_alloced);
|
1637c4 | 2000-02-01 | Fredrik Hübinette (Hubbe) | |
push_constant_text("objects_freed");
|
905e0c | 2000-08-11 | Henrik Grubbström (Grubba) | | push_int64(objects_freed);
|
1637c4 | 2000-02-01 | Fredrik Hübinette (Hubbe) | |
push_constant_text("last_gc");
|
905e0c | 2000-08-11 | Henrik Grubbström (Grubba) | | push_int64(last_gc);
|
1637c4 | 2000-02-01 | Fredrik Hübinette (Hubbe) | |
push_constant_text("projected_garbage");
push_float(objects_freed * (double) num_allocs / (double) alloc_threshold);
f_aggregate_mapping(14);
}
|