}
/* 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;
}
INLINE CELL collect_next(CELL scan)
{
CELL size;
+
if(headerp(get(scan)))
{
size = untagged_object_size(scan);
return;
}
- /* printf("write barrier hit %ld\n",offset); */
while(card_scan < card_end && card_scan < here)
card_scan = collect_next(card_scan);
}
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];
}
}
collected are now empty */
reset_generations(NURSERY,gen);
}
-
- /* new objects are allocated from the nursery. */
- allot_zone = &nursery;
}
/* collect gen and all younger generations */
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();
/* 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);
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
printf("Minor GC\n");
garbage_collection(NURSERY);
}
-
- printf("After:\n");
- dump_generations();
}
}
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;
clear_cards(TENURED,NURSERY);
- allot_zone = &nursery;
-
if(alloter != heap_start + total_size)
fatal_error("Oops",alloter);
int i;
CELL obj;
- if(gc_in_progress)
- return;
-
for(i = profile_depth; i < depth; i++)
{
obj = get(cs_bot + i * CELLS);
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;
}
#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]
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)));
}
return ((a & 7) == 0) ? a : ((a + 8) & ~7);
}
-INLINE void *allot(CELL a)
+INLINE void *allot_zone(ZONE *z, CELL a)
{
- CELL h = allot_zone->here;
+ CELL h = z->here;
+ z->here = h + align8(a);
allot_barrier(h);
- allot_zone->here = h + align8(a);
+ return (void*)h;
+}
+
+INLINE void *allot(CELL 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);
}
}
-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));
return (CELL)ffi_dlsym(dll,symbol);
}
-void relocate_dlsym(F_REL* rel, bool relative)
-{
- 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)
+INLINE CELL compute_code_rel(F_REL *rel, CELL original)
{
- 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)
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++;
}
/* 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);
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);
}
/* 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)));
}
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();