debugging generational GC

cvs
Slava Pestov 2005-05-12 07:52:56 +00:00
parent 055d116310
commit 46569a782b
7 changed files with 93 additions and 112 deletions

View File

@ -27,11 +27,13 @@ void collect_roots(void)
}
/* Given a pointer to oldspace, copy it to newspace. */
INLINE void* copy_untagged_object(void* pointer, CELL size)
INLINE void *copy_untagged_object(void *pointer, CELL size)
{
void* newpointer = allot(size);
void *newpointer;
if(newspace->here + size >= newspace->limit)
longjmp(gc_jmp,1);
newpointer = allot_zone(newspace,size);
memcpy(newpointer,pointer,size);
return newpointer;
}
@ -122,6 +124,7 @@ INLINE void collect_object(CELL scan)
INLINE CELL collect_next(CELL scan)
{
CELL size;
if(headerp(get(scan)))
{
size = untagged_object_size(scan);
@ -152,7 +155,6 @@ INLINE void collect_card(CARD *ptr, CELL here)
return;
}
/* printf("write barrier hit %ld\n",offset); */
while(card_scan < card_end && card_scan < here)
card_scan = collect_next(card_scan);
}
@ -219,15 +221,15 @@ void begin_gc(CELL gen)
generations[gen] = prior;
prior = z;
generations[gen].here = generations[gen].base;
allot_zone = &generations[gen];
newspace = &generations[gen];
clear_cards(TENURED,TENURED);
}
else
{
/* when collecting a younger generation, we copy
reachable objects to the next oldest generation,
so we set the allot_zone so the next generation. */
allot_zone = &generations[gen + 1];
so we set the newspace so the next generation. */
newspace = &generations[gen + 1];
}
}
@ -254,9 +256,6 @@ void end_gc(CELL gen)
collected are now empty */
reset_generations(NURSERY,gen);
}
/* new objects are allocated from the nursery. */
allot_zone = &nursery;
}
/* collect gen and all younger generations */
@ -274,13 +273,24 @@ void garbage_collection(CELL gen)
gc_in_progress = true;
/* we come back here if a generation is full */
if(setjmp(gc_jmp))
{
if(gen == TENURED)
{
/* oops, out of memory */
critical_error("Out of memory",0);
}
else
gen++;
}
begin_gc(gen);
printf("collecting generation %ld\n",gen);
dump_generations();
/* initialize chase pointer */
scan = allot_zone->here;
scan = newspace->here;
/* collect objects referenced from stacks and environment */
collect_roots();
@ -291,7 +301,7 @@ void garbage_collection(CELL gen)
/* collect literal objects referenced from compiled code */
collect_literals();
while(scan < allot_zone->here)
while(scan < newspace->here)
scan = collect_next(scan);
end_gc(gen);
@ -309,8 +319,6 @@ void primitive_gc(void)
CELL gen = to_fixnum(dpop());
gen = MAX(NURSERY,MIN(TENURED,gen));
garbage_collection(gen);
printf("After:\n");
dump_generations();
}
/* WARNING: only call this from a context where all local variables
@ -329,9 +337,6 @@ void maybe_garbage_collection(void)
printf("Minor GC\n");
garbage_collection(NURSERY);
}
printf("After:\n");
dump_generations();
}
}

View File

@ -36,3 +36,7 @@ void primitive_gc(void);
void garbage_collection(CELL gen);
void maybe_garbage_collection(void);
void primitive_gc_time(void);
/* in case a generation fills up in the middle of a gc, we jump back
up to try collecting the next generation. */
jmp_buf gc_jmp;

View File

@ -39,8 +39,6 @@ void init_arena(CELL young_size, CELL aging_size)
clear_cards(TENURED,NURSERY);
allot_zone = &nursery;
if(alloter != heap_start + total_size)
fatal_error("Oops",alloter);
@ -56,9 +54,6 @@ void allot_profile_step(CELL a)
int i;
CELL obj;
if(gc_in_progress)
return;
for(i = profile_depth; i < depth; i++)
{
obj = get(cs_bot + i * CELLS);
@ -66,8 +61,6 @@ void allot_profile_step(CELL a)
untag_word(obj)->allot_count += a;
}
if(in_zone(&prior,executing))
critical_error("executing in prior zone",executing);
untag_word_fast(executing)->allot_count += a;
}

View File

@ -55,7 +55,9 @@ INLINE bool in_zone(ZONE* z, CELL pointer)
#define TENURED (GC_GENERATIONS-1)
ZONE generations[GC_GENERATIONS];
ZONE *allot_zone;
/* used during garbage collection only */
ZONE *newspace;
#define tenured generations[TENURED]
#define nursery generations[NURSERY]
@ -124,8 +126,6 @@ INLINE void write_barrier(CELL address)
INLINE void allot_barrier(CELL address)
{
CARD *ptr = ADDR_TO_CARD(address);
/* we need to remember the first object allocated in the
card */
CARD c = *ptr;
*ptr = (card_marked(c) | MIN(card_base(c),(address & ADDR_CARD_MASK)));
}
@ -147,14 +147,20 @@ INLINE CELL align8(CELL a)
return ((a & 7) == 0) ? a : ((a + 8) & ~7);
}
INLINE void *allot_zone(ZONE *z, CELL a)
{
CELL h = z->here;
z->here = h + align8(a);
allot_barrier(h);
return (void*)h;
}
INLINE void *allot(CELL a)
{
CELL h = allot_zone->here;
allot_barrier(h);
allot_zone->here = h + align8(a);
if(allot_profiling)
allot_profile_step(align8(a));
return (void*)h;
allot_barrier(nursery.here);
return allot_zone(&nursery,a);
}
bool in_zone(ZONE* z, CELL pointer);

View File

@ -83,14 +83,6 @@ void relocate_data()
}
}
void relocate_primitive(F_REL* rel, bool relative)
{
/* this is intended for x86, so the address is relative to after
the insn, ie offset + CELLS. */
put(rel->offset,primitive_to_xt(rel->argument)
- (relative ? rel->offset + CELLS : 0));
}
CELL get_rel_symbol(F_REL* rel)
{
F_CONS* cons = untag_cons(get(rel->argument));
@ -99,27 +91,25 @@ CELL get_rel_symbol(F_REL* rel)
return (CELL)ffi_dlsym(dll,symbol);
}
void relocate_dlsym(F_REL* rel, bool relative)
INLINE CELL compute_code_rel(F_REL *rel, CELL original)
{
CELL addr = get_rel_symbol(rel);
put(rel->offset,addr - (relative ? rel->offset + CELLS : 0));
}
/* PowerPC-specific relocations */
void relocate_primitive_16_16(F_REL* rel)
{
reloc_set_16_16((CELL*)rel->offset,primitive_to_xt(rel->argument));
}
void relocate_dlsym_16_16(F_REL* rel)
{
reloc_set_16_16((CELL*)rel->offset,get_rel_symbol(rel));
}
INLINE void code_fixup_16_16(CELL* cell)
{
CELL difference = (compiling.base - code_relocation_base);
reloc_set_16_16(cell,reloc_get_16_16(cell) + difference);
switch(rel->type)
{
case F_PRIMITIVE:
return primitive_to_xt(rel->argument);
case F_DLSYM:
code_fixup(&rel->argument);
return get_rel_symbol(rel);
case F_ABSOLUTE:
return original + (compiling.base - code_relocation_base);
case F_USERENV:
return (CELL)&userenv;
case F_CARDS:
return ((CELL)cards - heap_start);
default:
critical_error("Unsupported rel",rel->type);
break;
}
}
INLINE CELL relocate_code_next(CELL relocating)
@ -140,44 +130,26 @@ INLINE CELL relocate_code_next(CELL relocating)
while(rel < rel_end)
{
CELL original;
CELL new_value;
if(rel->risc16_16)
original = reloc_get_16_16(rel->offset);
else
original = get(rel->offset);
/* to_c_string can fill up the heap */
maybe_garbage_collection();
code_fixup(&rel->offset);
new_value = compute_code_rel(rel,original);
switch(rel->type)
{
case F_RELATIVE_PRIMITIVE:
relocate_primitive(rel,true);
break;
case F_ABSOLUTE_PRIMITIVE:
relocate_primitive(rel,false);
break;
case F_RELATIVE_DLSYM:
code_fixup(&rel->argument);
relocate_dlsym(rel,true);
break;
case F_ABSOLUTE_DLSYM:
code_fixup(&rel->argument);
relocate_dlsym(rel,false);
break;
case F_ABSOLUTE:
code_fixup((CELL*)rel->offset);
break;
case F_ABSOLUTE_PRIMITIVE_16_16:
relocate_primitive_16_16(rel);
break;
case F_ABSOLUTE_DLSYM_16_16:
code_fixup(&rel->argument);
relocate_dlsym_16_16(rel);
break;
case F_ABSOLUTE_16_16:
code_fixup_16_16((CELL*)rel->offset);
break;
default:
critical_error("Unsupported rel",rel->type);
break;
}
if(rel->relative)
new_value -= (rel->offset + CELLS);
if(rel->risc16_16)
reloc_set_16_16(rel->offset,new_value);
else
put(rel->offset,new_value);
rel++;
}

View File

@ -1,7 +1,7 @@
/* relocation base of currently loaded image's data heap */
CELL data_relocation_base;
INLINE void data_fixup(CELL* cell)
INLINE void data_fixup(CELL *cell)
{
if(TAG(*cell) != FIXNUM_TYPE && *cell != F)
*cell += (tenured.base - data_relocation_base);
@ -9,31 +9,32 @@ INLINE void data_fixup(CELL* cell)
typedef enum {
/* arg is a primitive number */
F_RELATIVE_PRIMITIVE,
F_ABSOLUTE_PRIMITIVE,
F_PRIMITIVE,
/* arg is a pointer in the literal table hodling a cons where the
car is a symbol string, and the cdr is a dll */
F_RELATIVE_DLSYM,
F_ABSOLUTE_DLSYM,
F_DLSYM,
/* relocate an address to start of code heap */
F_ABSOLUTE,
/* PowerPC absolute address in the low 16 bits of two consecutive
32-bit words */
F_ABSOLUTE_PRIMITIVE_16_16,
F_ABSOLUTE_DLSYM_16_16,
F_ABSOLUTE_16_16
/* store a pointer to environment table */
F_USERENV,
/* store the offset of the card table from the data heap base */
F_CARDS
} F_RELTYPE;
/* code relocation consists of a table of entries for each fixup */
typedef struct {
F_RELTYPE type;
u8 type;
u8 relative;
/* on PowerPC, some values are stored in the high 16 bits of a pair
of consecutive cells */
u8 risc16_16;
CELL offset;
CELL argument;
} F_REL;
CELL code_relocation_base;
INLINE void code_fixup(CELL* cell)
INLINE void code_fixup(CELL *cell)
{
*cell += (compiling.base - code_relocation_base);
}
@ -43,13 +44,13 @@ void relocate_code();
/* on PowerPC, return the 32-bit literal being loaded at the code at the
given address */
INLINE CELL reloc_get_16_16(CELL* cell)
INLINE CELL reloc_get_16_16(CELL cell)
{
return ((*cell & 0xffff) << 16) | (*(cell + 1) & 0xffff);
return ((get(cell) & 0xffff) << 16) | (get(cell + 1) & 0xffff);
}
INLINE void reloc_set_16_16(CELL* cell, CELL value)
INLINE void reloc_set_16_16(CELL cell, CELL value)
{
*cell = ((*cell & ~0xffff) | ((value >> 16) & 0xffff));
*(cell + 1) = ((*(cell + 1) & ~0xffff) | (value & 0xffff));
put(cell,((get(cell) & ~0xffff) | ((value >> 16) & 0xffff)));
put(cell + 1,((get(cell + 1) & ~0xffff) | (value & 0xffff)));
}

View File

@ -2,7 +2,7 @@
void signal_handler(int signal, siginfo_t* siginfo, void* uap)
{
if(allot_zone->here > allot_zone->limit)
if(nursery.here > nursery.limit)
{
fprintf(stderr,"Out of memory!\n");
factorbug();