]> gitweb.factorcode.org Git - factor.git/commitdiff
debugging generational GC
authorSlava Pestov <slava@factorcode.org>
Thu, 12 May 2005 07:52:56 +0000 (07:52 +0000)
committerSlava Pestov <slava@factorcode.org>
Thu, 12 May 2005 07:52:56 +0000 (07:52 +0000)
native/gc.c
native/gc.h
native/memory.c
native/memory.h
native/relocate.c
native/relocate.h
native/unix/signal.c

index a758eab34f3cbdcc7637df15b2299fbb2c599c85..6a717eb566c9cd666717e50f2f30b3ee13d9b726 100644 (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();
        }
 }
 
index 606eb5690687fe0a9f501ad999ea8e7a9b108db6..14ab18667b128517c7e1243ca0eb8f89560a99c4 100644 (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;
index d29aa3eefe7119bef043358f4399ad021c401d72..70904052e6c2df515a97f0b0061d1fb262d7acc0 100644 (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;
 }
 
index d7477bd9e4473367a8645d6794e75247edcd6a55..686a330e8179876ccc127720db9bf615fc034191 100644 (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(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);
index 7240e9ec1983c18af2690bb9ae600a295b94bffe..6772665412f0e4971cea86976abfb9dedc239d26 100644 (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)
-{
-       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)
@@ -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++;
        }
index 5a2ad0e0d5d5cd1934d085a666a9f7c5c95c6595..720c3eb45f1fb5cf02a5124cb6b1e94b4d060dab 100644 (file)
@@ -1,7 +1,7 @@
 /* relocation base of currently loaded image's data heap */
 CELL data_relocation_base;
 
-INLINE void data_fixup(CELLcell)
+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(CELLcell)
+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)));
 }
index 9e23c4aa62d042467bf6699bc90dc7cdcff0cef2..d548b7455863728af5ca0a8dcb5f305b85ca357f 100644 (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();