]> gitweb.factorcode.org Git - factor.git/commitdiff
generational GC work
authorSlava Pestov <slava@factorcode.org>
Thu, 12 May 2005 05:02:39 +0000 (05:02 +0000)
committerSlava Pestov <slava@factorcode.org>
Thu, 12 May 2005 05:02:39 +0000 (05:02 +0000)
24 files changed:
TODO.FACTOR.txt
library/bootstrap/boot-stage4.factor
library/bootstrap/primitives.factor
library/test/compiler/simple.factor
library/test/crashes.factor
library/tools/memory.factor
native/alien.c
native/array.c
native/debug.c
native/debug.h
native/dll.c
native/error.c
native/factor.c
native/gc.c
native/gc.h
native/hashtable.c
native/memory.c
native/memory.h
native/relocate.c
native/run.h
native/sbuf.c
native/unix/signal.c
native/vector.c
native/word.c

index 47dc28fcfc569962f05318f625cd410c6178af95..e5960fbd3830b881fda7fea299bfd83357d9bab9 100644 (file)
@@ -1,3 +1,11 @@
+<magnus--> http://developer.apple.com/technotes/tn2004/tn2123.html#SECLIMITATIONS\r
+<magnus--> http://www.caddr.com/macho/archives/sbcl-devel/2005-3/4742.html\r
+<magnus--> not *too* long\r
+<magnus--> but we'd need to longjmp the main thread from the exception handler thread\r
+<magnus--> or cause a signal in the main thread\r
+<magnus--> http://www.caddr.com/macho/archives/sbcl-devel/2005-3/4764.html\r
+<magnus--> http://clozure.com/cgi-bin/viewcvs.cgi/ccl/lisp-kernel/lisp-exceptions.c?rev=1.9&content-type=text/vnd.viewcvs-markup\r
+\r
 - faster layout\r
 - tiled window manager\r
 - c primitive arrays: or just specialized arrays\r
index 622047d1e8c2f5ca527835f93a688b1aff981705..9c8d3ec5a093c49eef9084bbf72ea7fb5710acc8 100644 (file)
@@ -3,8 +3,8 @@
 IN: kernel
 USING: alien assembler command-line compiler console errors
 generic inference kernel-internals listener lists math memory
-namespaces parser presentation random stdio streams unparser
-words ;
+namespaces parser presentation prettyprint random stdio streams
+unparser words ;
 
 "Bootstrap stage 4..." print
 
@@ -42,6 +42,8 @@ unparse write " words compiled" print
 0 [ drop 1 + ] each-word
 unparse write " words total" print 
 
+"Total bootstrap GC time: " write gc-time unparse write " ms" print
+
 "Bootstrapping is complete." print
 "Now, you can run ./f factor.image" print
 
index 77acf3aece7aa6fdda3466bdc4950e92cf414fb7..3c1d2213c1b8680c1bd9e87bb380bca9bf895259 100644 (file)
@@ -126,7 +126,7 @@ vocabularies get [
     [ "setenv" "kernel-internals"             [ [ object fixnum ] [ ] ] ]
     [ "stat" "files"                          [ [ string ] [ general-list ] ] ]
     [ "(directory)" "files"                   [ [ string ] [ general-list ] ] ]
-    [ "garbage-collection" "memory"           [ [ ] [ ] ] ]
+    [ "gc" "memory"                           [ [ fixnum ] [ ] ] ]
     [ "gc-time" "memory"                      [ [ string ] [ ] ] ]
     [ "save-image" "memory"                   [ [ string ] [ ] ] ]
     [ "datastack" "kernel"                    " -- ds "          ]
@@ -134,7 +134,7 @@ vocabularies get [
     [ "set-datastack" "kernel"                " ds -- "          ]
     [ "set-callstack" "kernel"                " cs -- "          ]
     [ "exit" "kernel"                         [ [ integer ] [ ] ] ]
-    [ "room" "memory"                         [ [ ] [ integer integer general-list ] ] ]
+    [ "room" "memory"                         [ [ ] [ integer integer integer integer general-list ] ] ]
     [ "os-env" "kernel"                       [ [ string ] [ object ] ] ]
     [ "millis" "kernel"                       [ [ ] [ integer ] ] ]
     [ "(random-int)" "math"                   [ [ ] [ integer ] ] ]
index d8793598f576fb0c96137e6be824741e08212bfb..178df258ed3df3c8cb41c8e2b9bb88e0be10137e 100644 (file)
@@ -34,7 +34,7 @@ USE: memory
 
 : indexed-literal-test "hello world" ; compiled
 
-garbage-collection
-garbage-collection
+full-gc
+full-gc
 
 [ "hello world" ] [ indexed-literal-test ] unit-test
index 791adfec865cff5a0cda61e46aa8fb0629f10231..894cf0affefc2d349c787e7948853994b6a2e97f 100644 (file)
@@ -6,7 +6,7 @@ prettyprint sequences strings test vectors words ;
 
 [ ] [
     "20 <sbuf> \"foo\" set" eval
-    "garbage-collection" eval
+    "full-gc" eval
 ] unit-test
 
 [ ] [
@@ -26,6 +26,6 @@ prettyprint sequences strings test vectors words ;
 ! Weird PowerPC bug.
 [ ] [
     [ "4" throw ] [ drop ] catch
-    garbage-collection
-    garbage-collection
+    full-gc
+    full-gc
 ] unit-test
index da925d6ec8b7ad6e740137d5ca104a2ed27c170c..13307e6307b5c455c587fe974717782c049ad29d 100644 (file)
@@ -5,6 +5,10 @@ USING: errors generic hashtables kernel kernel-internals lists
 math namespaces prettyprint sequences stdio strings unparser
 vectors words ;
 
+: generations 15 getenv ;
+
+: full-gc generations 1 - gc ;
+
 : save
     #! Save the current image.
     "image" get save-image ;
index 96582ebe8553cb41a60240e2eca005e30847c1b6..f4734afdad2c925417184641a2ca9aa882af65f4 100644 (file)
@@ -87,7 +87,7 @@ void fixup_displaced_alien(DISPLACED_ALIEN* d)
 
 void collect_displaced_alien(DISPLACED_ALIEN* d)
 {
-       COPY_OBJECT(d->alien);
+       copy_handle(&d->alien);
 }
 
 #define DEF_ALIEN_SLOT(name,type,boxer) \
index efb3ecd8b63b9cd6b356d08592e36f04eabcbb7b..0dc6b89b27d75ad37ed455a4e81b0d10529a0dfb 100644 (file)
@@ -14,6 +14,12 @@ F_ARRAY* allot_array(CELL type, CELL capacity)
        return array;
 }
 
+/* WARNING: fill must be an immediate type:
+either be F or a fixnum.
+
+if you want to use pass a pointer, you _must_ hit
+the write barrier manually with a write_barrier()
+call with the returned object. */
 F_ARRAY* array(CELL type, CELL capacity, CELL fill)
 {
        int i; F_ARRAY* array = allot_array(type, capacity);
@@ -40,9 +46,9 @@ void primitive_byte_array(void)
        dpush(tag_object(array(BYTE_ARRAY_TYPE,to_fixnum(dpop()),0)));
 }
 
+/* see note about fill in array() */
 F_ARRAY* grow_array(F_ARRAY* array, CELL capacity, CELL fill)
 {
-       /* later on, do an optimization: if end of array is here, just grow */
        int i; F_ARRAY* new_array;
        CELL curr_cap = array_capacity(array);
        if(curr_cap >= capacity)
index d06f1837248f94825405ea6b563dd22a58e4e62e..3dee5328372858d995dfc8e061a29743aad02a3c 100644 (file)
@@ -135,32 +135,184 @@ void print_obj(CELL obj)
                fprintf(stderr,"f");
                break;
        default:
-               fprintf(stderr,"#<type %ld @ %ld>",type_of(obj),obj);
+               fprintf(stderr,"#<type %ld @ %lx>",type_of(obj),obj);
                break;
        }
 }
 
-void print_stack(CELL* start, CELL* end)
+void print_objects(CELL start, CELL end)
 {
-       while(start < end)
+       for(; start <= end; start += CELLS)
        {
-               print_obj(*start);
+               print_obj(get(start));
                fprintf(stderr,"\n");
-               start++;
        }
 }
 
-void dump_stacks(void)
+void dump_cell(CELL cell)
 {
-       fprintf(stderr,"*** Data stack:\n");
-       print_stack((CELL*)ds_bot,(CELL*)(ds + CELLS));
-       fprintf(stderr,"*** Call stack:\n");
-       print_stack((CELL*)cs_bot,(CELL*)(cs + CELLS));
-       fprintf(stderr,"*** Call frame:\n");
-       print_obj(callframe);
-       fprintf(stderr,"\n");
-       fprintf(stderr,"*** Executing:\n");
-       print_obj(executing);
+       fprintf(stderr,"%08lx: ",cell);
+
+       cell = get(cell);
+
+       fprintf(stderr,"%08lx tag %ld",cell,TAG(cell));
+
+       switch(TAG(cell))
+       {
+       case OBJECT_TYPE:
+       case BIGNUM_TYPE:
+       case FLOAT_TYPE:
+               if(cell == F)
+                       fprintf(stderr," -- F");
+               else if(cell < TYPE_COUNT<<TAG_BITS)
+                       fprintf(stderr," -- header: %ld",cell>>TAG_BITS);
+               else if(cell >= heap_start && cell < heap_end)
+               {
+                       CELL header = get(UNTAG(cell));
+                       CELL type = header>>TAG_BITS;
+                       fprintf(stderr," -- object; ");
+                       if(TAG(header) == OBJECT_TYPE && type < TYPE_COUNT)
+                               fprintf(stderr," type %ld",type);
+                       else
+                               fprintf(stderr," header corrupt");
+               }
+               break;
+       case GC_COLLECTED:
+               fprintf(stderr," -- forwarding pointer");
+               break;
+       }
+       
        fprintf(stderr,"\n");
-       fflush(stderr);
+}
+
+void dump_memory(CELL from, CELL to)
+{
+       for(; from <= to; from += CELLS)
+               dump_cell(from);
+}
+
+void dump_generation(ZONE *z)
+{
+       fprintf(stderr,"base=%lx, size=%lx, here=%lx, alarm=%lx\n",
+               z->base,
+               z->limit - z->base,
+               z->here - z->base,
+               z->alarm - z->base);
+}
+
+void dump_generations(void)
+{
+       int i;
+       for(i = 0; i < GC_GENERATIONS; i++)
+       {
+               fprintf(stderr,"Generation %d: ",i);
+               dump_generation(&generations[i]);
+       }
+
+       fprintf(stderr,"Semispace: ");
+       dump_generation(&prior);
+
+       fprintf(stderr,"Cards: base=%lx, size=%lx\n",(CELL)cards,
+               (CELL)(cards_end - cards));
+}
+
+void factorbug(void)
+{
+       fprintf(stderr,"Factor low-level debugger\n");
+       fprintf(stderr,"d <addr> <count> -- dump memory\n");
+       fprintf(stderr,". <addr>         -- print object at <addr>\n");
+       fprintf(stderr,"sz <addr>        -- print size of object at <addr>\n");
+       fprintf(stderr,"s r              -- dump data and return stacks\n");
+       fprintf(stderr,".s .r            -- print data and return stacks\n");
+       fprintf(stderr,"i                -- dump interpreter state\n");
+       fprintf(stderr,"e                -- dump environment\n");
+       fprintf(stderr,"g                -- dump generations\n");
+       fprintf(stderr,"card <addr>      -- print card containing address\n");
+       fprintf(stderr,"addr <card>      -- print address containing card\n");
+       fprintf(stderr,"c <gen>          -- force garbage collection\n");
+       fprintf(stderr,"t                -- throw t\n");
+       fprintf(stderr,"x                -- exit debugger\n");
+       fprintf(stderr,"im               -- save factor.crash.image\n");
+       
+       for(;;)
+       {
+               char cmd[1024];
+
+               fprintf(stderr,"ldb ");
+               fflush(stdout);
+
+               if(scanf("%s",cmd) <= 0)
+                       exit(1);
+
+               if(strcmp(cmd,"d") == 0)
+               {
+                       CELL addr, count;
+                       scanf("%lx %lx",&addr,&count);
+                       dump_memory(addr,addr+count);
+               }
+               else if(strcmp(cmd,".") == 0)
+               {
+                       CELL addr;
+                       scanf("%lx",&addr);
+                       print_obj(addr);
+                       fprintf(stderr,"\n");
+               }
+               else if(strcmp(cmd,"sz") == 0)
+               {
+                       CELL addr;
+                       scanf("%lx",&addr);
+                       fprintf(stderr,"%ld\n",object_size(addr));
+               }
+               else if(strcmp(cmd,"s") == 0)
+                       dump_memory(ds_bot,(ds + CELLS));
+               else if(strcmp(cmd,"r") == 0)
+                       dump_memory(cs_bot,(cs + CELLS));
+               else if(strcmp(cmd,".s") == 0)
+                       print_objects(ds_bot,(ds + CELLS));
+               else if(strcmp(cmd,".r") == 0)
+                       print_objects(cs_bot,(cs + CELLS));
+               else if(strcmp(cmd,"i") == 0)
+               {
+                       fprintf(stderr,"Call frame:\n");
+                       dump_cell(callframe);
+                       fprintf(stderr,"\n");
+                       fprintf(stderr,"Executing:\n");
+                       dump_cell(executing);
+                       fprintf(stderr,"\n");
+               }
+               else if(strcmp(cmd,"e") == 0)
+               {
+                       int i;
+                       for(i = 0; i < USER_ENV; i++)
+                               dump_cell(userenv[i]);
+               }
+               else if(strcmp(cmd,"g") == 0)
+                       dump_generations();
+               else if(strcmp(cmd,"c") == 0)
+               {
+                       CELL gen;
+                       scanf("%lu",&gen);
+                       garbage_collection(gen);
+               }
+               else if(strcmp(cmd,"card") == 0)
+               {
+                       CELL addr;
+                       scanf("%lx",&addr);
+                       fprintf(stderr,"%lx\n",(CELL)ADDR_TO_CARD(addr));
+               }
+               else if(strcmp(cmd,"addr") == 0)
+               {
+                       CELL card;
+                       scanf("%lx",&card);
+                       fprintf(stderr,"%lx\n",(CELL)CARD_TO_ADDR(card));
+               }
+               else if(strcmp(cmd,"t") == 0)
+                       throw_error(T,true);
+               else if(strcmp(cmd,"x") == 0)
+                       return;
+               else if(strcmp(cmd,"y") == 0)
+                       save_image("factor.crash.image");
+               else
+                       fprintf(stderr,"unknown command\n");
+       }
 }
index 111bfbf2053796843e3fe1d973203128ae79a46c..6ce56265cf677ea704c2bd81c7a53c998c4f0e27 100644 (file)
@@ -1,7 +1,3 @@
-CELL assoc(CELL alist, CELL key);
-void print_cons(CELL cons);
-void print_word(F_WORD* word);
-void print_string(F_STRING* str);
 void print_obj(CELL obj);
-void print_stack(CELL* start, CELL* end);
-void dump_stacks(void);
+void dump_generations(void);
+void factorbug(void);
index 9e42b1247d669642116d26735c05d1ed78d4018a..7f70d4181d43e6137717ac4f1054b7c2663c59fc 100644 (file)
@@ -53,5 +53,5 @@ void fixup_dll(DLL* dll)
 
 void collect_dll(DLL* dll)
 {
-       COPY_OBJECT(dll->path);
+       copy_handle(&dll->path);
 }
index 5fcd8e21baad306f854b56db6671b265b9902b42..a1a58dd7e8f90f82702591bdd2529e90af02e125 100644 (file)
@@ -14,8 +14,7 @@ void fatal_error(char* msg, CELL tagged)
 void critical_error(char* msg, CELL tagged)
 {
        fprintf(stderr,"Critical error: %s %ld\n",msg,tagged);
-       save_image("factor.crash.image");
-       exit(1);
+       factorbug();
 }
 
 void early_error(CELL error)
@@ -26,9 +25,7 @@ void early_error(CELL error)
                fprintf(stderr,"Error during startup: ");
                print_obj(error);
                fprintf(stderr,"\n");
-               dump_stacks();
-               fflush(stderr);
-               exit(1);
+               factorbug();
        }
 }
 
@@ -60,9 +57,7 @@ void primitive_throw(void)
 
 void primitive_die(void)
 {
-       dump_stacks();
-       fflush(stderr);
-       exit(1);
+       factorbug();
 }
 
 void general_error(CELL error, CELL tagged)
index 04e76635ed0f317902952f05819f8aefadc0eb9f..1c7f43e3e21ea361d24ed3590351d0ea8ef6c7b7 100644 (file)
@@ -15,6 +15,7 @@ void init_factor(char* image, CELL ds_size, CELL cs_size,
        init_errors();
        userenv[CPU_ENV] = tag_object(from_c_string(FACTOR_CPU_STRING));
        userenv[OS_ENV] = tag_object(from_c_string(FACTOR_OS_STRING));
+       userenv[GEN_ENV] = tag_fixnum(GC_GENERATIONS);
 }
 
 INLINE bool factor_arg(const char* str, const char* arg, CELL* value)
@@ -33,8 +34,8 @@ int main(int argc, char** argv)
 {
        CELL ds_size = 2048;
        CELL cs_size = 2048;
-       CELL young_size = 4;
-       CELL aging_size = 8;
+       CELL young_size = 8;
+       CELL aging_size = 16;
        CELL code_size = 2;
        CELL literal_size = 64;
        CELL args;
index 73630e36c584863e608fb042067f493a6c61991b..a758eab34f3cbdcc7637df15b2299fbb2c599c85 100644 (file)
@@ -7,17 +7,13 @@ void collect_roots(void)
        int i;
        CELL ptr;
 
-       gc_debug("root: t",T);
-       COPY_OBJECT(T);
-       gc_debug("root: bignum_zero",bignum_zero);
-       COPY_OBJECT(bignum_zero);
-       gc_debug("root: bignum_pos_one",bignum_pos_one);
-       COPY_OBJECT(bignum_pos_one);
-       gc_debug("root: bignum_neg_one",bignum_neg_one);
-       COPY_OBJECT(bignum_neg_one);
-       gc_debug("root: callframe",callframe);
+       copy_handle(&T);
+       copy_handle(&bignum_zero);
+       copy_handle(&bignum_pos_one);
+       copy_handle(&bignum_neg_one);
+       /* we can't use & here since these two are in
+       registers on PowerPC */
        COPY_OBJECT(callframe);
-       gc_debug("root: executing",executing);
        COPY_OBJECT(executing);
 
        for(ptr = ds_bot; ptr <= ds; ptr += CELLS)
@@ -30,22 +26,68 @@ void collect_roots(void)
                copy_handle(&userenv[i]);
 }
 
+/* Given a pointer to oldspace, copy it to newspace. */
+INLINE void* copy_untagged_object(void* pointer, CELL size)
+{
+       void* newpointer = allot(size);
+       memcpy(newpointer,pointer,size);
+
+       return newpointer;
+}
+
+INLINE CELL copy_object_impl(CELL pointer)
+{
+       CELL newpointer;
+
+       if(pointer < collecting_generation)
+               critical_error("asked to copy object outside collected generation",pointer);
+       
+       newpointer = (CELL)copy_untagged_object((void*)UNTAG(pointer),
+               object_size(pointer));
+
+       /* install forwarding pointer */
+       put(UNTAG(pointer),RETAG(newpointer,GC_COLLECTED));
+
+       return newpointer;
+}
+
 /*
 Given a pointer to a tagged pointer to oldspace, copy it to newspace.
 If the object has already been copied, return the forwarding
 pointer address without copying anything; otherwise, install
 a new forwarding pointer.
 */
-CELL copy_object_impl(CELL pointer)
+CELL copy_object(CELL pointer)
 {
-       CELL newpointer;
+       CELL tag;
+       CELL header;
+       CELL untagged;
 
-       gc_debug("copy_object",pointer);
-       newpointer = (CELL)copy_untagged_object((void*)UNTAG(pointer),
-               object_size(pointer));
-       put(UNTAG(pointer),RETAG(newpointer,OBJECT_TYPE));
+       gc_debug("copy object",pointer);
 
-       return newpointer;
+       if(pointer == F)
+               return F;
+
+       tag = TAG(pointer);
+
+       if(tag == FIXNUM_TYPE)
+               return pointer;
+
+       header = get(UNTAG(pointer));
+       untagged = UNTAG(header);
+       if(TAG(header) == GC_COLLECTED)
+       {
+               header = get(untagged);
+               while(header == GC_COLLECTED)
+               {
+                       untagged = UNTAG(header);
+                       header = get(untagged);
+               }
+               gc_debug("forwarding",untagged);
+               return RETAG(untagged,tag);
+       }
+       else
+               return RETAG(copy_object_impl(pointer),tag);
 }
 
 INLINE void collect_object(CELL scan)
@@ -80,8 +122,6 @@ INLINE void collect_object(CELL scan)
 INLINE CELL collect_next(CELL scan)
 {
        CELL size;
-       gc_debug("collect_next",scan);
-       gc_debug("collect_next header",get(scan));
        if(headerp(get(scan)))
        {
                size = untagged_object_size(scan);
@@ -96,15 +136,8 @@ INLINE CELL collect_next(CELL scan)
        return scan + size;
 }
 
-void clear_cards(void)
-{
-       BYTE *ptr;
-       for(ptr = cards; ptr < cards_end; ptr++)
-               clear_card(ptr);
-}
-
 /* scan all the objects in the card */
-void collect_card(CARD *ptr)
+INLINE void collect_card(CARD *ptr, CELL here)
 {
        CARD c = *ptr;
        CELL offset = (c & CARD_BASE_MASK);
@@ -112,32 +145,66 @@ void collect_card(CARD *ptr)
        CELL card_end = (CELL)CARD_TO_ADDR(ptr + 1);
 
        if(offset == 0x7f)
-               critical_error("bad card",c);
+       {
+               if(c == 0xff)
+                       critical_error("bad card",c);
+               else
+                       return;
+       }
 
-       printf("! write barrier hit %d\n",offset);
-       while(card_scan < card_end)
+       /* printf("write barrier hit %ld\n",offset); */
+       while(card_scan < card_end && card_scan < here)
                card_scan = collect_next(card_scan);
-
-       clear_card(ptr);
 }
 
-void collect_gen_cards(CELL gen)
+INLINE void collect_gen_cards(CELL gen)
 {
        CARD *ptr = ADDR_TO_CARD(generations[gen].base);
-       CARD *last_card = ADDR_TO_CARD(generations[gen].here);
-       for(ptr = cards; ptr <= last_card; ptr++)
+       CELL here = generations[gen].here;
+       CARD *last_card = ADDR_TO_CARD(here);
+       
+       if(generations[gen].here == generations[gen].limit)
+               last_card--;
+       
+       for(; ptr <= last_card; ptr++)
        {
                if(card_marked(*ptr))
-                       collect_card(ptr);
+                       collect_card(ptr,here);
        }
 }
 
+void unmark_cards(CELL from, CELL to)
+{
+       CARD *ptr = ADDR_TO_CARD(generations[from].base);
+       CARD *last_card = ADDR_TO_CARD(generations[to].here);
+       if(generations[to].here == generations[to].limit)
+               last_card--;
+       for(; ptr <= last_card; ptr++)
+               unmark_card(ptr);
+}
+
+void clear_cards(CELL from, CELL to)
+{
+       CARD *ptr = ADDR_TO_CARD(generations[from].base);
+       CARD *last_card = ADDR_TO_CARD(generations[to].limit);
+       for(; ptr < last_card; ptr++)
+               clear_card(ptr);
+}
+
+void reset_generations(CELL from, CELL to)
+{
+       CELL i;
+       for(i = from; i <= to; i++)
+               generations[i].here = generations[i].base;
+       clear_cards(from,to);
+}
+
 /* scan cards in all generations older than the one being collected */
-void collect_cards(void)
+void collect_cards(CELL gen)
 {
-       CELL gen;
-       for(gen = collecting_generation; gen < GC_GENERATIONS; gen++)
-               collect_gen_cards(gen);
+       int i;
+       for(i = gen + 1; i < GC_GENERATIONS; i++)
+               collect_gen_cards(i);
 }
 
 void begin_gc(CELL gen)
@@ -153,6 +220,7 @@ void begin_gc(CELL gen)
                prior = z;
                generations[gen].here = generations[gen].base;
                allot_zone = &generations[gen];
+               clear_cards(TENURED,TENURED);
        }
        else
        {
@@ -165,7 +233,29 @@ void begin_gc(CELL gen)
 
 void end_gc(CELL gen)
 {
-       /* continue allocating from the nursery. */
+       if(gen == TENURED)
+       {
+               /* we did a full collection; no more
+               old-to-new pointers remain since everything
+               is in tenured space */
+               unmark_cards(TENURED,TENURED);
+               /* all generations except tenured space are
+               now empty */
+               reset_generations(NURSERY,TENURED - 1);
+       }
+       else
+       {
+               /* we collected a younger generation. so the
+               next-oldest generation no longer has any
+               pointers into the younger generation (the
+               younger generation is empty!) */
+               unmark_cards(gen + 1,gen + 1);
+               /* all generations up to and including the one
+               collected are now empty */
+               reset_generations(NURSERY,gen);
+       }
+
+       /* new objects are allocated from the nursery. */
        allot_zone = &nursery;
 }
 
@@ -186,32 +276,41 @@ void garbage_collection(CELL gen)
 
        begin_gc(gen);
 
+       printf("collecting generation %ld\n",gen);
+       dump_generations();
+
        /* initialize chase pointer */
        scan = allot_zone->here;
 
+       /* collect objects referenced from stacks and environment */
        collect_roots();
-       collect_cards();
+       
+       /* collect objects referenced from older generations */
+       collect_cards(gen);
 
        /* collect literal objects referenced from compiled code */
        collect_literals();
        
        while(scan < allot_zone->here)
-       {
-               gc_debug("scan loop",scan);
                scan = collect_next(scan);
-       }
 
        end_gc(gen);
 
-       gc_debug("gc done",0);
+       gc_debug("gc done",gen);
 
        gc_in_progress = false;
        gc_time += (current_millis() - start);
+       
+       gc_debug("total gc time",gc_time);
 }
 
 void primitive_gc(void)
 {
-       garbage_collection(TENURED);
+       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
@@ -219,7 +318,21 @@ are also reachable via the GC roots. */
 void maybe_garbage_collection(void)
 {
        if(nursery.here > nursery.alarm)
-               primitive_gc();
+       {
+               if(tenured.here > tenured.alarm)
+               {
+                       printf("Major GC\n");
+                       garbage_collection(TENURED);
+               }
+               else
+               {
+                       printf("Minor GC\n");
+                       garbage_collection(NURSERY);
+               }
+               
+               printf("After:\n");
+               dump_generations();
+       }
 }
 
 void primitive_gc_time(void)
index 6f96650d976845b09f236ce619b637c457f7d683..606eb5690687fe0a9f501ad999ea8e7a9b108db6 100644 (file)
@@ -14,67 +14,25 @@ so we have to check that the pointer occurs after the beginning of
 the requested generation. */
 #define COLLECTING_GEN(ptr) (collecting_generation <= ptr)
 
-/* Given a pointer to oldspace, copy it to newspace. */
-INLINE void* copy_untagged_object(void* pointer, CELL size)
-{
-       void* newpointer = allot(size);
-       memcpy(newpointer,pointer,size);
-
-       return newpointer;
-}
-
-CELL copy_object_impl(CELL pointer);
-
 /* #define GC_DEBUG */
 
 INLINE void gc_debug(char* msg, CELL x) {
 #ifdef GC_DEBUG
-       printf("%s %d\n",msg,x);
+       printf("%s %ld\n",msg,x);
 #endif
 }
 
-INLINE CELL copy_object(CELL pointer)
-{
-       CELL tag;
-       CELL header;
-       CELL untagged;
-
-       gc_debug("copy object",pointer);
-
-       if(!COLLECTING_GEN(pointer))
-               return pointer;
-
-       if(pointer == F)
-               return F;
-
-       tag = TAG(pointer);
-
-       if(tag == FIXNUM_TYPE)
-               return pointer;
-
-       header = get(UNTAG(pointer));
-       untagged = UNTAG(header);
-       if(TAG(header) != FIXNUM_TYPE && in_zone(&tenured,untagged))
-       {
-               gc_debug("forwarding",untagged);
-               return RETAG(untagged,tag);
-       }
-       else
-               return RETAG(copy_object_impl(pointer),tag);
-}
-
-#define COPY_OBJECT(lvalue) lvalue = copy_object(lvalue)
+CELL copy_object(CELL pointer);
+#define COPY_OBJECT(lvalue) if(COLLECTING_GEN(lvalue)) lvalue = copy_object(lvalue)
 
-INLINE void copy_handle(CELLhandle)
+INLINE void copy_handle(CELL *handle)
 {
        COPY_OBJECT(*handle);
 }
 
-void collect_roots(void);
-void collect_card(CARD *ptr);
-void collect_gen_cards(CELL gen);
-void collect_cards(void);
-void clear_cards(void);
+void clear_cards(CELL from, CELL to);
+void unmark_cards(CELL from, CELL to);
 void primitive_gc(void);
+void garbage_collection(CELL gen);
 void maybe_garbage_collection(void);
 void primitive_gc_time(void);
index b596f2f596e278368ae08fd98a49907d91409c29..c952fc99dbae10b2b7a4878d0f4550668892d1e8 100644 (file)
@@ -24,5 +24,5 @@ void fixup_hashtable(F_HASHTABLE* hashtable)
 
 void collect_hashtable(F_HASHTABLE* hashtable)
 {
-       COPY_OBJECT(hashtable->array);
+       copy_handle(&hashtable->array);
 }
index 4d3fff659cb601015fcae038c66e3f8188c84f6c..d29aa3eefe7119bef043358f4399ad021c401d72 100644 (file)
@@ -1,26 +1,5 @@
 #include "factor.h"
 
-void dump_generations(void)
-{
-       int i;
-       for(i = 0; i < GC_GENERATIONS; i++)
-       {
-               fprintf(stderr,"Generation %d: base=%lu, size=%lu, here=%lu\n",
-                       i,
-                       generations[i].base,
-                       generations[i].limit - generations[i].base,
-                       generations[i].here);
-       }
-
-       fprintf(stderr,"Semispace: base=%lu, size=%lu, here=%lu\n",
-               prior.base,
-               prior.limit - prior.base,
-               prior.here);
-
-       fprintf(stderr,"Cards: base=%lu, size=%lu\n",(CELL)cards,
-               (CELL)(cards_end - cards));
-}
-
 CELL init_zone(ZONE *z, CELL size, CELL base)
 {
        z->base = z->here = base;
@@ -30,18 +9,24 @@ CELL init_zone(ZONE *z, CELL size, CELL base)
 }
 
 /* input parameters must be 8 byte aligned */
+/* the heap layout is important:
+- two semispaces: tenured and prior
+- younger generations follow */
 void init_arena(CELL young_size, CELL aging_size)
 {
+       int i;
+       CELL alloter;
+
        CELL total_size = (GC_GENERATIONS - 1) * young_size + 2 * aging_size;
        CELL cards_size = total_size / CARD_SIZE;
 
        heap_start = (CELL)alloc_guarded(total_size);
+       heap_end = heap_start + total_size;
+
        cards = alloc_guarded(cards_size);
        cards_end = cards + cards_size;
-       clear_cards();
 
-       int i;
-       CELL alloter = heap_start;
+       alloter = heap_start;
 
        if(heap_start == 0)
                fatal_error("Cannot allocate data heap",total_size);
@@ -49,9 +34,11 @@ void init_arena(CELL young_size, CELL aging_size)
        alloter = init_zone(&tenured,aging_size,alloter);
        alloter = init_zone(&prior,aging_size,alloter);
 
-       for(i = 0; i < GC_GENERATIONS - 1; i++)
+       for(i = GC_GENERATIONS - 2; i >= 0; i--)
                alloter = init_zone(&generations[i],young_size,alloter);
 
+       clear_cards(TENURED,NURSERY);
+
        allot_zone = &nursery;
 
        if(alloter != heap_start + total_size)
@@ -127,7 +114,7 @@ void primitive_size(void)
 
 void primitive_begin_scan(void)
 {
-       primitive_gc();
+       garbage_collection(TENURED);
        heap_scan_ptr = tenured.base;
        heap_scan_end = tenured.here;
        heap_scan = true;
index c411b414aff37f11dca8ba479d9afc9b790ad466..d7477bd9e4473367a8645d6794e75247edcd6a55 100644 (file)
@@ -58,9 +58,10 @@ ZONE generations[GC_GENERATIONS];
 ZONE *allot_zone;
 
 #define tenured generations[TENURED]
-#define nursery generations[TENURED] /* XXX */
+#define nursery generations[NURSERY]
 
 CELL heap_start;
+CELL heap_end;
 
 /* spare semi-space; rotates with tenured. */
 ZONE prior;
@@ -82,28 +83,28 @@ CARD *cards_end;
 /* A card is 16 bytes (128 bits), 5 address bits per card.
 it is important that 7 bits is sufficient to represent every
 offset within the card */
-#define CARD_SIZE 16
-#define CARD_BITS 4
-#define CARD_MASK (CARD_SIZE-1)
+#define CARD_SIZE 128
+#define CARD_BITS 7
+#define ADDR_CARD_MASK (CARD_SIZE-1)
 
 INLINE CARD card_marked(CARD c)
 {
        return c & CARD_MARK_MASK;
 }
 
-INLINE void clear_card(CARD *c)
+INLINE void unmark_card(CARD *c)
 {
-       *c = CARD_BASE_MASK;
+       *c &= CARD_BASE_MASK;
 }
 
-INLINE u8 card_base(CARD c)
+INLINE void clear_card(CARD *c)
 {
-       return c & CARD_BASE_MASK;
+       *c = CARD_BASE_MASK; /* invalid value */
 }
 
-INLINE void rebase_card(CARD *c, u8 base)
+INLINE u8 card_base(CARD c)
 {
-       *c = base;
+       return c & CARD_BASE_MASK;
 }
 
 #define ADDR_TO_CARD(a) (CARD*)((((CELL)a-heap_start)>>CARD_BITS)+(CELL)cards)
@@ -122,10 +123,11 @@ INLINE void write_barrier(CELL address)
 /* we need to remember the first object allocated in the card */
 INLINE void allot_barrier(CELL address)
 {
-       CARD *c = ADDR_TO_CARD(address);
+       CARD *ptr = ADDR_TO_CARD(address);
        /* we need to remember the first object allocated in the
        card */
-       rebase_card(c,MIN(card_base(*c),(address & CARD_MASK)));
+       CARD c = *ptr;
+       *ptr = (card_marked(c) | MIN(card_base(c),(address & ADDR_CARD_MASK)));
 }
 
 bool allot_profiling;
@@ -134,7 +136,6 @@ bool allot_profiling;
 size must be a multiple of the page size */
 void* alloc_guarded(CELL size);
 
-void dump_generations(void);
 CELL init_zone(ZONE *z, CELL size, CELL base);
 void init_arena(CELL young_size, CELL aging_size);
 void flip_zones();
@@ -146,7 +147,7 @@ INLINE CELL align8(CELL a)
        return ((a & 7) == 0) ? a : ((a + 8) & ~7);
 }
 
-INLINE voidallot(CELL a)
+INLINE void *allot(CELL a)
 {
        CELL h = allot_zone->here;
        allot_barrier(h);
index f37d8d206ba0fb8968644e06e2a803779d9c4782..7240e9ec1983c18af2690bb9ae600a295b94bffe 100644 (file)
@@ -2,8 +2,6 @@
 
 void relocate_object(CELL relocating)
 {
-       allot_barrier(relocating);
-
        switch(untag_header(get(relocating)))
        {
        case WORD_TYPE:
@@ -42,6 +40,8 @@ INLINE CELL relocate_data_next(CELL relocating)
        CELL size = CELLS;
        CELL cell = get(relocating);
 
+       allot_barrier(relocating);
+
        if(headerp(cell))
        {
                size = untagged_object_size(relocating);
@@ -136,7 +136,7 @@ INLINE CELL relocate_code_next(CELL relocating)
                + compiled->reloc_length);
 
        if(compiled->header != COMPILED_HEADER)
-               fatal_error("Wrong compiled header",relocating);
+               critical_error("Wrong compiled header",relocating);
 
        while(rel < rel_end)
        {
@@ -175,7 +175,7 @@ INLINE CELL relocate_code_next(CELL relocating)
                        code_fixup_16_16((CELL*)rel->offset);
                        break;
                default:
-                       fatal_error("Unsupported rel",rel->type);
+                       critical_error("Unsupported rel",rel->type);
                        break;
                }
 
index 5abd78da3c4ceac223453d010beb084aef76fc3b..327e3ebd1dfde96f29ee1074d5c86ef92d6f830d 100644 (file)
@@ -1,8 +1,5 @@
 #define USER_ENV 16
 
-#define STDIN_ENV      0
-#define STDOUT_ENV     1
-#define STDERR_ENV     2
 #define NAMESTACK_ENV  3 /* used by library only */
 #define GLOBAL_ENV     4
 #define BREAK_ENV      5
@@ -15,6 +12,7 @@
 #define ERROR_ENV      12 /* a marker consed onto kernel errors */
 #define IN_ENV         13
 #define OUT_ENV        14
+#define GEN_ENV        15 /* set to GC_GENERATIONS constant */
 
 /* Profiling timer */
 #ifndef WIN32
index a3eae7410438df94dff77a02f2b9500dceadbb0e..e034a61c5d12fb97d32bf10a243b1ce69bf9339a 100644 (file)
@@ -24,5 +24,5 @@ void fixup_sbuf(F_SBUF* sbuf)
 
 void collect_sbuf(F_SBUF* sbuf)
 {
-       COPY_OBJECT(sbuf->string);
+       copy_handle(&sbuf->string);
 }
index 6a72d6133f1affa6010d9bc482e37b3fd6e34d09..9e23c4aa62d042467bf6699bc90dc7cdcff0cef2 100644 (file)
@@ -5,9 +5,7 @@ void signal_handler(int signal, siginfo_t* siginfo, void* uap)
        if(allot_zone->here > allot_zone->limit)
        {
                fprintf(stderr,"Out of memory!\n");
-               dump_generations();
-               fflush(stderr);
-               exit(1);
+               factorbug();
        }
        else
                signal_error(signal);
@@ -15,7 +13,7 @@ void signal_handler(int signal, siginfo_t* siginfo, void* uap)
 
 void dump_stack_signal(int signal, siginfo_t* siginfo, void* uap)
 {
-       dump_stacks();
+       factorbug();
 }
 
 /* Called from a signal handler. XXX - is this safe? */
@@ -40,12 +38,16 @@ void init_signals(void)
        struct sigaction profiling_sigaction;
        struct sigaction ign_sigaction;
        struct sigaction dump_sigaction;
+       sigemptyset(&custom_sigaction.sa_mask);
        custom_sigaction.sa_sigaction = signal_handler;
        custom_sigaction.sa_flags = SA_SIGINFO;
+       sigemptyset(&profiling_sigaction.sa_mask);
        profiling_sigaction.sa_sigaction = call_profiling_step;
        profiling_sigaction.sa_flags = SA_SIGINFO;
+       sigemptyset(&dump_sigaction.sa_mask);
        dump_sigaction.sa_sigaction = dump_stack_signal;
        dump_sigaction.sa_flags = SA_SIGINFO;
+       sigemptyset(&ign_sigaction.sa_mask);
        ign_sigaction.sa_handler = SIG_IGN;
        sigaction(SIGABRT,&custom_sigaction,NULL);
        sigaction(SIGFPE,&custom_sigaction,NULL);
index 13c411c47f84045b51c658cbc3655c8f3794f2ff..928dbbf2ded7f9434d9daac70b3ea3dd1391af31 100644 (file)
@@ -24,5 +24,5 @@ void fixup_vector(F_VECTOR* vector)
 
 void collect_vector(F_VECTOR* vector)
 {
-       COPY_OBJECT(vector->array);
+       copy_handle(&vector->array);
 }
index 0eabdb86b2723e6f6e66c3ce2b8983fa0f4206fd..c6dec876261bb5b85606a8e9ee625e95e11c2346 100644 (file)
@@ -54,6 +54,6 @@ void fixup_word(F_WORD* word)
 
 void collect_word(F_WORD* word)
 {
-       COPY_OBJECT(word->def);
-       COPY_OBJECT(word->props);
+       copy_handle(&word->def);
+       copy_handle(&word->props);
 }