]> gitweb.factorcode.org Git - factor.git/commitdiff
generational gc and compiler relocation fixes
authorSlava Pestov <slava@factorcode.org>
Fri, 13 May 2005 22:27:18 +0000 (22:27 +0000)
committerSlava Pestov <slava@factorcode.org>
Fri, 13 May 2005 22:27:18 +0000 (22:27 +0000)
17 files changed:
TODO.FACTOR.txt
library/compiler/compiler.factor
library/compiler/ppc/alien.factor
library/compiler/ppc/generator.factor
library/compiler/relocate.factor
library/compiler/x86/generator.factor
library/compiler/x86/stack.factor
library/compiler/xt.factor
library/generic/tuple.factor
library/test/benchmark/fib.factor
library/test/test.factor
native/cards.c
native/debug.c
native/gc.c
native/gc.h
native/relocate.c
native/relocate.h

index e5960fbd3830b881fda7fea299bfd83357d9bab9..8b20f0e728edb8ca2f2d1cdee8ff865186703a96 100644 (file)
@@ -6,6 +6,10 @@
 <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
+- simplifier:\r
+  - dead loads not optimized out\r
+  - kill tag-fixnum/untag-fixnum\r
+- \ foo where foo is parsing is not printed readably\r
 - faster layout\r
 - tiled window manager\r
 - c primitive arrays: or just specialized arrays\r
@@ -17,6 +21,8 @@
 - sleep word\r
 - update docs\r
 - redo new compiler backend for PowerPC\r
+- type predicates: : foo? type 7 eq? ;\r
+- remove 'not' word, and move t?/f? to kernel\r
 \r
 - plugin: supportsBackspace\r
 - if external factor is down, don't add tons of random shit to the       \r
index c24a5c1b04cf8c21ed6a7c741418922a1333da16..a644816a66afedc698cd36cf46d76281bb531bd3 100644 (file)
@@ -13,7 +13,7 @@ kernel lists namespaces prettyprint stdio words ;
 
 : compiling ( word -- word parameter )
     check-architecture
-    "Compiling " write dup . flush
+    "Compiling " write dup word. terpri flush
     dup word-def ;
 
 GENERIC: (compile) ( word -- )
@@ -43,7 +43,7 @@ M: compound (compile) ( word -- )
     "compile" get [ word compile ] when ; parsing
 
 : cannot-compile ( word error -- )
-    "Cannot compile " write swap . print-error ;
+    "Cannot compile " write swap word. terpri print-error ;
 
 : try-compile ( word -- )
     [ compile ] [ [ cannot-compile ] when* ] catch ;
@@ -52,7 +52,7 @@ M: compound (compile) ( word -- )
 
 : decompile ( word -- )
     dup compiled? [
-        "Decompiling " write dup . flush
+        "Decompiling " write dup word. terpri flush
         [ word-primitive ] keep set-word-primitive
     ] [
         drop
index 04385430fb87db61f904eebc9cfbafee14aa4f14..de49b67138d99b9d7068d55ff77a93a0c1057614 100644 (file)
@@ -5,7 +5,7 @@ USING: alien compiler inference kernel kernel-internals lists
 math memory namespaces words ;
 
 \ alien-invoke [
-    uncons load-library 2dup rel-dlsym-16/16 dlsym compile-call-far
+    uncons load-library 2dup 1 rel-dlsym dlsym compile-call-far
 ] "generator" set-word-prop
 
 : stack-size 8 + 16 align ;
@@ -16,7 +16,7 @@ math memory namespaces words ;
 ] "generator" set-word-prop
 
 #unbox [
-    uncons f 2dup rel-dlsym-16/16 dlsym compile-call-far
+    uncons f 2dup 1 rel-dlsym dlsym compile-call-far
     3 1 rot stack@ STW
 ] "generator" set-word-prop
 
@@ -25,7 +25,7 @@ math memory namespaces words ;
 ] "generator" set-word-prop
 
 #box [
-    f 2dup rel-dlsym-16/16 dlsym compile-call-far
+    f 2dup 1 rel-dlsym dlsym compile-call-far
 ] "generator" set-word-prop
 
 #cleanup [
index 6b41ca033cd3bf7369777fb8f8c8856cd96bb559..d1ac535a88d3025baa5360eb5a9aa4734e8c39ea 100644 (file)
@@ -46,14 +46,14 @@ words ;
 
 : compile-call-label ( label -- )
     dup primitive? [
-        dup rel-primitive-16/16 word-xt compile-call-far
+        dup 1 rel-primitive word-xt compile-call-far
     ] [
         0 BL relative-24
     ] ifte ;
 
 #call-label [
     ! Hack: length of instruction sequence that follows
-    rel-address-16/16  compiled-offset 20 + 18 LOAD32
+    0 1 rel-address  compiled-offset 20 + 18 LOAD32
     1 1 -16 STWU
     18 1 20 STW
     0 B relative-24
@@ -66,7 +66,7 @@ words ;
 
 : compile-jump-label ( label -- )
     dup primitive? [
-        dup rel-primitive-16/16 word-xt compile-jump-far
+        dup 1 rel-primitive word-xt compile-jump-far
     ] [
         0 B relative-24
     ] ifte ;
@@ -94,7 +94,7 @@ words ;
     18 18 1 SRAWI
     ! The value 24 is a magic number. It is the length of the
     ! instruction sequence that follows to be generated.
-    rel-address-16/16  compiled-offset 24 + 19 LOAD32
+    0 1 rel-address  compiled-offset 24 + 19 LOAD32
     18 18 19 ADD
     18 18 0 LWZ
     18 MTLR
index 4e8dad5276ecd3879f18a28d4acca373944ea10f..b40ae446d4670a4fd9273df709175cc11d8e55b8 100644 (file)
@@ -11,34 +11,20 @@ SYMBOL: relocation-table
 
 : relocating compiled-offset cell - rel, ;
 
-: rel-primitive ( word rel/abs -- )
-    #! If flag is true; relative.
-    0 1 ? rel, relocating word-primitive rel, ;
+: rel-type, ( rel/abs 16/16 type -- )
+    swap 8 shift bitor swap 16 shift bitor rel, ;
 
-: rel-dlsym ( name dll rel/abs -- )
-    #! If flag is true; relative.
-    2 3 ? rel, relocating cons intern-literal rel, ;
+: rel-primitive ( word relative 16/16 -- )
+    0 rel-type, relocating word-primitive rel, ;
 
-: rel-address ( rel/abs -- )
+: rel-dlsym ( name dll rel/abs 16/16 -- )
+    1 rel-type, relocating cons intern-literal rel, ;
+
+: rel-address ( rel/abs 16/16 -- )
     #! Relocate address just compiled. If flag is true,
     #! relative, and there is nothing to do.
-    [ 4 rel, relocating 0 rel, ] unless ;
+    over [ 2drop ] [ 2 rel-type, relocating 0 rel, ] ifte ;
 
-: rel-word ( word rel/abs -- )
+: rel-word ( word rel/abs 16/16 -- )
     #! If flag is true; relative.
     over primitive? [ rel-primitive ] [ nip rel-address ] ifte ;
-
-! PowerPC relocations
-
-: rel-primitive-16/16 ( word -- )
-    #! This is called before a sequence like
-    #! 19 LOAD32
-    #! 19 MTCTR
-    #! BCTR
-    5 rel, compiled-offset rel, word-primitive rel, ;
-
-: rel-dlsym-16/16 ( name dll -- )
-    6 rel, compiled-offset rel, cons intern-literal rel, ;
-
-: rel-address-16/16 ( -- )
-    7 rel, compiled-offset rel, 0 rel, ;
index 5c3f2d989289659f2aac0d47fab275c0eb4ed82d..d7ca5879ee28e0c6aac8c0205a6d28c112421b39 100644 (file)
@@ -15,7 +15,7 @@ M: vreg v>operand vreg-n { EAX ECX EDX } nth ;
 M: %prologue generate-node drop ;
 
 : compile-c-call ( symbol dll -- )
-    2dup dlsym CALL t rel-dlsym ;
+    2dup dlsym CALL 1 0 rel-dlsym ;
 
 M: %call generate-node ( vop -- )
     vop-label dup postpone-word CALL ;
@@ -58,7 +58,7 @@ M: %dispatch generate-node ( vop -- )
     ! Multiply by 4 to get a jump table offset
     dup 2 SHL
     ! Add to jump table base
-    dup HEX: ffff ADD  just-compiled >r f rel-address
+    dup HEX: ffff ADD  just-compiled >r 0 0 rel-address
     ! Jump to jump table entry
     unit JMP
     ! Align for better performance
index 7c36e63083e91b5e988255bde33ae57fba8a4e3c..6ff96ed7836c641391e0b183b6c8f094b7cd5317 100644 (file)
@@ -7,7 +7,7 @@ memory sequences words ;
 : rel-cs ( -- )
     #! Add an entry to the relocation table for the 32-bit
     #! immediate just compiled.
-    "cs" f f rel-dlsym ;
+    "cs" f 0 0 rel-dlsym ;
 
 : CS ( -- [ address ] ) "cs" f dlsym unit ;
 : CS> ( register -- ) CS MOV rel-cs ;
@@ -34,7 +34,7 @@ M: %immediate-d generate-node ( vop -- )
     vop-literal [ ESI ] swap address MOV ;
 
 : load-indirect ( dest literal -- )
-    intern-literal unit MOV f rel-address ;
+    intern-literal unit MOV 0 0 rel-address ;
 
 M: %indirect generate-node ( vop -- )
     #! indirect load of a literal through a table
index c07995aa64773fa0b2a9de04f5ea6a495489fdfd..73e84d2f0d85c502d2be2e014697a6868521c1f6 100644 (file)
@@ -49,7 +49,7 @@ TUPLE: relative word where to ;
 : just-compiled compiled-offset 4 - ;
 
 C: relative ( word -- )
-    over t rel-word
+    over 1 0 rel-word
     [ set-relative-word ] keep
     [ just-compiled swap set-relative-where ] keep
     [ compiled-offset swap set-relative-to ] keep ;
@@ -71,7 +71,7 @@ C: absolute ( word -- )
     [ just-compiled swap set-absolute-where ] keep ;
 
 : absolute ( word -- )
-    dup f rel-word <absolute> deferred-xt ;
+    dup 0 0 rel-word <absolute> deferred-xt ;
 
 : >absolute dup absolute-word compiled-xt swap absolute-where ;
 
index 18492b0e9618649aa775f4d38ac0e4ee47f45511..a1f07b41b761477eba69e57e2ed971a1bf7ff9a4 100644 (file)
@@ -16,7 +16,7 @@ hashtables errors sequences vectors ;
     #! Internal allocation function. Do not call it directly,
     #! since you can fool the runtime and corrupt memory by
     #! specifying an incorrect size.
-    <tuple> [ 0 swap set-array-nth ] keep ;
+    <tuple> [ 2 set-slot ] keep ;
 
 : class-tuple 2 slot ; inline
 
index d74881a0375261845d42bb8208f1cb8a7cb52bae..59212f5b894c3414eccf17afbd836a1b8824e5fd 100644 (file)
@@ -4,6 +4,10 @@ USE: kernel
 USE: math
 USE: test
 USE: math-internals
+USE: namespaces
+
+! Four fibonacci implementations, each one slower than the
+! previous.
 
 : fixnum-fib ( n -- nth fibonacci number )
     dup 1 fixnum<= [
@@ -36,3 +40,18 @@ TUPLE: box i ;
     ] ifte ; compiled
 
 [ << box f 9227465 >> ] [ << box f 34 >> tuple-fib ] unit-test
+
+SYMBOL: n
+: namespace-fib ( n -- n )
+    [
+        n set
+        n get 1 <= [
+            1
+        ] [
+            n get 1 - namespace-fib
+            n get 2 - namespace-fib
+            +
+        ] ifte
+    ] with-scope ; compiled
+
+[ 9227465 ] [ 34 namespace-fib ] unit-test
index 22afcf16f7376a7df993f2b2b26536d210b847bf..0358a3b79711f3133b00e8b692e5b82b19df0d05 100644 (file)
@@ -87,7 +87,7 @@ SYMBOL: failures
             "buffer" ,
         ] when
         
-        cpu "unknown" = "compile" get and [
+        cpu "unknown" = not "compile" get and [
             [
                 "io/buffer" "compiler/optimizer"
                 "compiler/simple"
@@ -95,7 +95,7 @@ SYMBOL: failures
                 "compiler/generic" "compiler/bail-out"
                 "compiler/linearizer" "compiler/intrinsics"
             ] %
-        ] unless
+        ] when
         
         [
             "benchmark/empty-loop" "benchmark/fac"
index 3fc09c2123f91fef088a15eb83c419d4390d4037..f3d40435bc181d8ace0f23002389cd551aa11cb2 100644 (file)
@@ -18,6 +18,8 @@ INLINE void collect_card(CARD *ptr, CELL here)
 
        while(card_scan < card_end && card_scan < here)
                card_scan = collect_next(card_scan);
+       
+       cards_scanned++;
 }
 
 INLINE void collect_gen_cards(CELL gen)
@@ -48,8 +50,9 @@ void unmark_cards(CELL from, CELL to)
 
 void clear_cards(CELL from, CELL to)
 {
-       CARD *ptr = ADDR_TO_CARD(generations[from].base);
-       CARD *last_card = ADDR_TO_CARD(generations[to].limit);
+       /* NOTE: reverse order due to heap layout. */
+       CARD *last_card = ADDR_TO_CARD(generations[from].limit);
+       CARD *ptr = ADDR_TO_CARD(generations[to].base);
        for(; ptr < last_card; ptr++)
                clear_card(ptr);
 }
index 3dee5328372858d995dfc8e061a29743aad02a3c..0d03a048afe2e0f181c4fe41a7e58443780e3fa2 100644 (file)
@@ -274,10 +274,10 @@ void factorbug(void)
                else if(strcmp(cmd,"i") == 0)
                {
                        fprintf(stderr,"Call frame:\n");
-                       dump_cell(callframe);
+                       print_obj(callframe);
                        fprintf(stderr,"\n");
                        fprintf(stderr,"Executing:\n");
-                       dump_cell(executing);
+                       print_obj(executing);
                        fprintf(stderr,"\n");
                }
                else if(strcmp(cmd,"e") == 0)
index dfe80a489befaf77d5c2b3e71f6967ba211f8f84..e9e8dbb12a831c9b896d2070fb9283a6550091f2 100644 (file)
@@ -44,7 +44,7 @@ void init_arena(CELL young_size, CELL aging_size)
        for(i = GC_GENERATIONS - 2; i >= 0; i--)
                alloter = init_zone(&generations[i],young_size,alloter);
 
-       clear_cards(TENURED,NURSERY);
+       clear_cards(NURSERY,TENURED);
 
        if(alloter != heap_start + total_size)
                fatal_error("Oops",alloter);
@@ -52,6 +52,8 @@ void init_arena(CELL young_size, CELL aging_size)
        allot_profiling = false;
        heap_scan = false;
        gc_time = 0;
+       minor_collections = 0;
+       cards_scanned = 0;
 }
 
 void collect_roots(void)
@@ -78,18 +80,6 @@ void collect_roots(void)
                copy_handle(&userenv[i]);
 }
 
-/* follow a chain of forwarding pointers */
-CELL resolve_forwarding(CELL untagged, CELL tag)
-{
-       CELL header = get(untagged);
-       /* another forwarding pointer */
-       if(TAG(header) == GC_COLLECTED)
-               return resolve_forwarding(UNTAG(header),tag);
-       /* we've found the destination */
-       else
-               return RETAG(untagged,tag);
-}
-
 /* Given a pointer to oldspace, copy it to newspace. */
 INLINE void *copy_untagged_object(void *pointer, CELL size)
 {
@@ -103,12 +93,7 @@ INLINE void *copy_untagged_object(void *pointer, CELL size)
 
 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),
+       CELL newpointer = (CELL)copy_untagged_object((void*)UNTAG(pointer),
                object_size(pointer));
 
        /* install forwarding pointer */
@@ -117,6 +102,23 @@ INLINE CELL copy_object_impl(CELL pointer)
        return newpointer;
 }
 
+/* follow a chain of forwarding pointers */
+CELL resolve_forwarding(CELL untagged, CELL tag)
+{
+       CELL header = get(untagged);
+       /* another forwarding pointer */
+       if(TAG(header) == GC_COLLECTED)
+               return resolve_forwarding(UNTAG(header),tag);
+       /* we've found the destination */
+       else
+       {
+               CELL pointer = RETAG(untagged,tag);
+               if(should_copy(untagged))
+                       pointer = RETAG(copy_object_impl(pointer),tag);
+               return pointer;
+       }
+}
+
 /*
 Given a pointer to a tagged pointer to oldspace, copy it to newspace.
 If the object has already been copied, return the forwarding
@@ -202,7 +204,8 @@ void reset_generations(CELL from, CELL to)
 
 void begin_gc(CELL gen)
 {
-       collecting_generation = generations[gen].base;
+       collecting_gen = gen;
+       collecting_gen_start = generations[gen].base;
 
        if(gen == TENURED)
        {
@@ -234,7 +237,12 @@ void end_gc(CELL gen)
                unmark_cards(TENURED,TENURED);
                /* all generations except tenured space are
                now empty */
-               reset_generations(TENURED - 1,NURSERY);
+               reset_generations(NURSERY,TENURED - 1);
+
+               fprintf(stderr,"*** Major GC (%ld minor, %ld cards)\n",
+                       minor_collections,cards_scanned);
+               minor_collections = 0;
+               cards_scanned = 0;
        }
        else
        {
@@ -245,7 +253,9 @@ void end_gc(CELL gen)
                unmark_cards(gen + 1,gen + 1);
                /* all generations up to and including the one
                collected are now empty */
-               reset_generations(gen,NURSERY);
+               reset_generations(NURSERY,gen);
+               
+               minor_collections++;
        }
 }
 
@@ -308,7 +318,18 @@ are also reachable via the GC roots. */
 void maybe_garbage_collection(void)
 {
        if(nursery.here > nursery.alarm)
-               garbage_collection(NURSERY);
+       {
+               CELL gen = NURSERY;
+               while(gen < TENURED)
+               {
+                       ZONE *z = &generations[gen + 1];
+                       if(z->here < z->alarm)
+                               break;
+                       gen++;
+               }
+
+               garbage_collection(gen);
+       }
 }
 
 void primitive_gc_time(void)
index da1f0ad85463c993c0c18f30a77b98895cab42ee..4d34e920f495e2c468c0da49fe4d5b7e091af1a7 100644 (file)
@@ -37,16 +37,20 @@ CELL init_zone(ZONE *z, CELL size, CELL base);
 
 void init_arena(CELL young_size, CELL aging_size);
 
+/* statistics */
 s64 gc_time;
+CELL minor_collections;
+CELL cards_scanned;
 
 /* only meaningful during a GC */
-CELL collecting_generation;
+CELL collecting_gen;
+CELL collecting_gen_start;
 
 /* test if the pointer is in generation being collected, or a younger one.
 init_arena() arranges things so that the older generations are first,
 so we have to check that the pointer occurs after the beginning of
 the requested generation. */
-#define COLLECTING_GEN(ptr) (collecting_generation <= ptr)
+#define COLLECTING_GEN(ptr) (collecting_gen_start <= ptr)
 
 /* #define GC_DEBUG */
 
@@ -56,6 +60,14 @@ INLINE void gc_debug(char* msg, CELL x) {
 #endif
 }
 
+INLINE bool should_copy(CELL untagged)
+{
+       if(collecting_gen == TENURED)
+               return !in_zone(newspace,untagged);
+       else
+               return(in_zone(&prior,untagged) || COLLECTING_GEN(untagged));
+}
+
 CELL copy_object(CELL pointer);
 #define COPY_OBJECT(lvalue) if(COLLECTING_GEN(lvalue)) lvalue = copy_object(lvalue)
 
index a8578c3a2dfe45b22ef8c4cef94fed0b42d3656f..066e2b307befa83395124de626f004097ef921ec 100644 (file)
@@ -40,8 +40,6 @@ 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);
@@ -69,6 +67,7 @@ void relocate_data()
                if(relocating >= tenured.here)
                        break;
 
+               allot_barrier(relocating);
                relocating = relocate_data_next(relocating);
        }
 
@@ -93,7 +92,7 @@ CELL get_rel_symbol(F_REL* rel)
 
 INLINE CELL compute_code_rel(F_REL *rel, CELL original)
 {
-       switch(rel->type)
+       switch(REL_TYPE(rel))
        {
        case F_PRIMITIVE:
                return primitive_to_xt(rel->argument);
@@ -133,7 +132,7 @@ INLINE CELL relocate_code_next(CELL relocating)
                CELL original;
                CELL new_value;
 
-               if(rel->risc16_16)
+               if(REL_16_16(rel))
                        original = reloc_get_16_16(rel->offset);
                else
                        original = get(rel->offset);
@@ -143,10 +142,10 @@ INLINE CELL relocate_code_next(CELL relocating)
                code_fixup(&rel->offset);
                new_value = compute_code_rel(rel,original);
 
-               if(rel->relative)
+               if(REL_RELATIVE(rel))
                        new_value -= (rel->offset + CELLS);
 
-               if(rel->risc16_16)
+               if(REL_16_16(rel))
                        reloc_set_16_16(rel->offset,new_value);
                else
                        put(rel->offset,new_value);
index 720c3eb45f1fb5cf02a5124cb6b1e94b4d060dab..e35f51358ded052d52c067f021549e6708eea806 100644 (file)
@@ -21,13 +21,17 @@ typedef enum {
        F_CARDS
 } F_RELTYPE;
 
+/* the rel type is built like a cell to avoid endian-specific code in
+the compiler */
+#define REL_TYPE(r) ((r)->type & 0xff)
+/* on PowerPC, some values are stored in the high 16 bits of a pair
+of consecutive cells */
+#define REL_16_16(r) ((r)->type & 0xff00)
+#define REL_RELATIVE(r) ((r)->type & 0xff0000)
+
 /* code relocation consists of a table of entries for each fixup */
 typedef struct {
-       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 type;
        CELL offset;
        CELL argument;
 } F_REL;