debugging generational GC
parent
055d116310
commit
46569a782b
41
native/gc.c
41
native/gc.c
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue