]> gitweb.factorcode.org Git - factor.git/commitdiff
saving code to disk!
authorSlava Pestov <slava@factorcode.org>
Sat, 25 Dec 2004 07:55:03 +0000 (07:55 +0000)
committerSlava Pestov <slava@factorcode.org>
Sat, 25 Dec 2004 07:55:03 +0000 (07:55 +0000)
27 files changed:
TODO.FACTOR.txt
library/bootstrap/init-stage2.factor
library/cli.factor
library/compiler/assembler.factor
library/compiler/compiler.factor
library/compiler/generator-x86.factor
library/compiler/generator.factor
library/test/combinators.factor
library/test/inference.factor
native/array.c
native/compiler.c
native/compiler.h
native/factor.c
native/factor.h
native/ffi.c
native/image.c
native/image.h
native/memory.c
native/port.c
native/relocate.c
native/relocate.h
native/sbuf.c
native/string.c
native/string.h
native/types.c
native/vector.c
native/word.c

index 502bec0e0027e298619bd966b60f8d8367e62e89..9f9423e6e43007c1db7316f08d389063cad5b453 100644 (file)
@@ -17,7 +17,6 @@
 - optimize away dispatch\r
 - getenv/setenv: if literal arg, compile as a load/store\r
 - assembler opcodes dispatch on operand types\r
-- save code in image\r
 \r
 + oop:\r
 \r
index da2f26fe87e04eaf972b06cd24910958e8c15114..6b951db8b24e16d512615785c27234af6c931bdd 100644 (file)
@@ -44,26 +44,19 @@ USE: words
 USE: unparser
 USE: kernel-internals
 
-: cli-args ( -- args ) 10 getenv ;
+: init-smart-terminal
+    "smart-terminal" get [
+        stdio smart-term-hook get change 
+    ] when ;
 
 : warm-boot ( -- )
     #! A fully bootstrapped image has this as the boot
     #! quotation.
     boot
-
     init-error-handler
     init-random
-    init-assembler
-
-    ! Some flags are *on* by default, unless user specifies
-    ! -no-<flag> CLI switch
-    t "user-init" set
-    t "interactive" set
-    t "compile" set
-    t "smart-terminal" set
-
-    ! The first CLI arg is the image name.
-    cli-args uncons parse-command-line "image" set
+    default-cli-args
+    parse-command-line
 
     os "win32" = "compile" get and [
         "kernel32" "kernel32.dll" "stdcall" add-library
@@ -72,15 +65,10 @@ USE: kernel-internals
         "libc"     "msvcrt.dll"   "cdecl"   add-library
     ] when
 
-    "compile" get [ compile-all ] when
-
-    "smart-terminal" get [
-        stdio smart-term-hook get change 
-    ] when
-
+    init-smart-terminal
     run-user-init ;
 
-: auto-inline-count 5 ;
+: auto-inline-count 3 ;
 [
     warm-boot
     garbage-collection
@@ -90,19 +78,25 @@ USE: kernel-internals
 
 init-error-handler
 
-0 [ drop succ ] each-word unparse write " words" print 
-
-"Counting word usages..." print
-tally-usages
+! "Counting word usages..." print
+! tally-usages
 ! 
 ! "Automatically inlining words called " write
 ! auto-inline-count unparse write
 ! " or less times..." print
 ! auto-inline-count auto-inline
 
-"Inferring stack effects..." print
-0 [ unit try-infer [ succ ] when ] each-word
-unparse write " words have a stack effect" print
+default-cli-args
+parse-command-line
+
+"Compiling system..." print
+"compile" get [ compile-all ] when
+
+0 [ compiled? [ succ ] when ] each-word
+unparse write " words compiled" print
+
+0 [ drop succ ] each-word
+unparse write " words total" print 
 
 "Bootstrapping is complete." print
 "Now, you can run ./f factor.image" print
index 5585e233a34b863555e6d7afd8abc8e764db5170..600d146f8ed3b9d31d4486f81b0398c837692dca 100644 (file)
@@ -40,6 +40,7 @@ USE: stdio
 USE: streams
 USE: strings
 USE: words
+USE: kernel-internals
 
 ! This file is run as the last stage of boot.factor; it relies
 ! on all other words already being defined.
@@ -81,6 +82,18 @@ USE: words
 : run-files ( args -- )
     [ [ run-file ] when* ] each ;
 
-: parse-command-line ( args -- )
+: default-cli-args
+    #! Some flags are *on* by default, unless user specifies
+    #! -no-<flag> CLI switch
+    t "user-init" set
+    t "interactive" set
+    t "smart-terminal" set
+    t "verbose-compile" set
+    t "compile" set ;
+
+: cli-args ( -- args ) 10 getenv ;
+
+: parse-command-line ( -- )
     #! Parse command line arguments.
-    parse-switches run-files ;
+    #! The first CLI arg is the image name.
+    cli-args unswons "image" set parse-switches run-files ;
index 4cc3347c1f5dcdae8fe8f3cf7ca28176ad5a2983..9ed835805ca04b4f2a5ab3773655f144d7164cae 100644 (file)
@@ -29,12 +29,13 @@ IN: compiler
 USE: alien
 USE: math
 USE: kernel
+USE: hashtables
+USE: namespaces
 
-: cell 4 ; inline
-: literal-table 1024 cell * ; inline
+SYMBOL: interned-literals
 
-: init-assembler ( -- )
-    compiled-offset literal-table + set-compiled-offset ;
+: cell 4 ; inline
+: compiled-header HEX: 01c3babe ; inline
 
 : set-compiled-byte ( n addr -- )
     <alien> 0 set-alien-1 ; inline
@@ -43,12 +44,19 @@ USE: kernel
     <alien> 0 set-alien-cell ; inline
 
 : compile-aligned ( n -- )
-    compiled-offset swap align set-compiled-offset ; inline
+    compiled-offset cell 2 * align set-compiled-offset ; inline
 
 : intern-literal ( obj -- lit# )
-    address
-    literal-top set-compiled-cell
-    literal-top dup cell + set-literal-top ;
+    dup interned-literals get hash dup [
+        nip
+    ] [
+        drop [
+            address
+            literal-top set-compiled-cell
+            literal-top dup cell + set-literal-top
+            dup
+        ] keep interned-literals get set-hash
+    ] ifte ;
 
 : compile-byte ( n -- )
     compiled-offset set-compiled-byte
@@ -57,3 +65,10 @@ USE: kernel
 : compile-cell ( n -- )
     compiled-offset set-compiled-cell
     compiled-offset cell + set-compiled-offset ; inline
+
+: begin-assembly ( -- code-len-fixup reloc-len-fixup )
+    compiled-header compile-cell
+    compiled-offset 0 compile-cell
+    compiled-offset 0 compile-cell ;
+
+global [ <namespace> interned-literals set ] bind
index 90f7a8cde60ac28a1e27fa0c2f55caf7376594a9..a17d1115d3e7ccbb375b9c75c685183f71bd25de 100644 (file)
@@ -49,12 +49,12 @@ USE: words
         "Unsupported CPU; compiler disabled" throw
     ] unless ;
 
-: compiling ( word -- definition )
+: compiling ( word -- word parameter )
     check-architecture
     "verbose-compile" get [
         "Compiling " write dup . flush
     ] when
-    cell compile-aligned dup save-xt word-parameter ;
+    dup word-parameter ;
 
 : (compile) ( word -- )
     #! Should be called inside the with-compiler scope.
@@ -78,15 +78,16 @@ USE: words
     #! Compile the most recently defined word.
     "compile" get [ word compile ] when ; parsing
 
-: cannot-compile ( word -- )
+: cannot-compile ( word error -- )
     "verbose-compile" get [
-        "Cannot compile " write .
+        "Cannot compile " write swap .
+        default-error-handler
     ] [
-        drop
+        2drop
     ] ifte ;
 
 : try-compile ( word -- )
-    [ compile ] [ [ cannot-compile ] when ] catch ;
+    [ compile ] [ [ cannot-compile ] when* ] catch ;
 
 : compile-all ( -- )
     #! Compile all words.
index dde390696788237dd0dcfd9704d12eb61d70a44a..65c6aa0b7199e9ec393797dfdb54c00d2a127300 100644 (file)
@@ -32,52 +32,60 @@ USE: kernel
 USE: namespaces
 USE: words
 USE: lists
+USE: math
 
 : DS ( -- address ) "ds" dlsym-self ;
 
+: absolute-ds ( -- )
+    #! Add an entry to the relocation table for the 32-bit
+    #! immediate just compiled.
+    "ds" f rel-dlsym-self ;
+
 : POP-DS ( -- )
     #! Pop datastack to EAX.
-    DS ECX [I]>R
+    DS ECX [I]>R  absolute-ds
     ECX EAX [R]>R
     4 ECX R-I
-    ECX DS R>[I] ;
+    ECX DS R>[I]  absolute-ds ;
 
 #push-immediate [
-    DS ECX [I]>R
+    DS ECX [I]>R  absolute-ds
     4 ECX R+I
     address  ECX I>[R]
-    ECX DS R>[I]
+    ECX DS R>[I]  absolute-ds
 ] "generator" set-word-property
 
 #push-indirect [
-    DS ECX [I]>R
+    DS ECX [I]>R  absolute-ds
     4 ECX R+I
-    intern-literal EAX [I]>R
+    intern-literal EAX [I]>R  rel-address
     EAX ECX R>[R]
-    ECX DS R>[I]
+    ECX DS R>[I]  absolute-ds
 ] "generator" set-word-property
 
 #replace-immediate [
-    DS ECX [I]>R
+    DS ECX [I]>R  absolute-ds
     address  ECX I>[R]
-    ECX DS R>[I]
+    ECX DS R>[I]  absolute-ds
 ] "generator" set-word-property
 
 #replace-indirect [
-    DS ECX [I]>R
-    intern-literal EAX [I]>R
+    DS ECX [I]>R  absolute-ds
+    intern-literal EAX [I]>R  rel-address
     EAX ECX R>[R]
-    ECX DS R>[I]
+    ECX DS R>[I]  absolute-ds
 ] "generator" set-word-property
 
 #call [
-    dup postpone-word
+    dup dup postpone-word
     CALL compiled-offset defer-xt
+    t rel-word
 ] "generator" set-word-property
 
 #jump [
-    dup postpone-word
+    dup dup postpone-word
     JUMP compiled-offset defer-xt
+    t rel-word
 ] "generator" set-word-property
 
 #call-label [
@@ -97,7 +105,7 @@ USE: lists
 ] "generator" set-word-property
 
 #return-to [
-    PUSH-I/PARTIAL 0 defer-xt
+    PUSH-I/PARTIAL 0 defer-xt rel-address
 ] "generator" set-word-property
 
 #return [ drop RET ] "generator" set-word-property
@@ -108,16 +116,16 @@ USE: lists
     #! The jump table must immediately follow this macro.
     drop
     POP-DS
-    1 EAX R>>I ( -- fixup )
-    EAX+/PARTIAL
+    1 EAX R>>I
+    EAX+/PARTIAL ( -- fixup ) rel-address
     EAX JUMP-[R]
-    cell compile-aligned
+    compile-aligned
     compiled-offset swap set-compiled-cell ( fixup -- )
 ] "generator" set-word-property
 
 #target [
     #! Jump table entries are absolute addresses.
-    compiled-offset 0 compile-cell 0 defer-xt
+    compiled-offset 0 compile-cell 0 defer-xt rel-address
 ] "generator" set-word-property
 
 #c-call [ CALL JUMP-FIXUP ] "generator" set-word-property
@@ -147,6 +155,8 @@ USE: lists
     [ #r>   r>   ]
 ] [
     uncons
-    [ car CALL compiled-offset defer-xt drop ] cons
+    [
+        car dup CALL compiled-offset defer-xt t rel-word drop
+    ] cons
     "generator" set-word-property
 ] each
index 750684d78e958c0fca860718a39e6a1c3ab7166b..809cdd4b537a6d8a23b2ba9c5ca1f3905992f9bc 100644 (file)
@@ -34,6 +34,31 @@ USE: math
 USE: namespaces
 USE: strings
 USE: words
+USE: vectors
+
+! To support saving compiled code to disk, generator words
+! append relocation instructions to this vector.
+SYMBOL: relocation-table
+
+: rel, ( n -- ) relocation-table get vector-push ;
+
+: relocating compiled-offset cell - rel, ;
+
+: rel-primitive ( word rel/abs -- )
+    #! If flag is true; relative.
+    0 1 ? rel, relocating word-primitive rel, ;
+
+: rel-word ( word rel/abs -- )
+    #! If flag is true; relative.
+    over primitive? [ rel-primitive ] [ 2drop ] ifte ;
+
+: rel-dlsym-self ( name rel/abs -- )
+    #! If flag is true; relative.
+    2 3 ? rel, relocating intern-literal rel, ;
+
+: rel-address ( -- )
+    #! Relocate address just compiled.
+    4 rel, relocating 0 rel, ;
 
 : generate-node ( [ op | params ] -- )
     #! Generate machine code for a node.
@@ -43,8 +68,26 @@ USE: words
         "No generator" throw
     ] ifte ;
 
-: generate ( linear -- )
+: generate-code ( word linear -- length )
+    compiled-offset >r
+    compile-aligned
+    swap save-xt
+    [ generate-node ] each
+    compile-aligned
+    compiled-offset r> - ;
+
+: generate-reloc ( -- length )
+    relocation-table get
+    dup [ compile-cell ] vector-each
+    vector-length cell * ;
+
+: generate ( word linear -- )
     #! Compile a word definition from linear IR.
-    [ generate-node ] each ;
+    100 <vector> relocation-table set
+    begin-assembly swap >r >r
+        generate-code
+        generate-reloc
+    r> set-compiled-cell
+    r> set-compiled-cell ;
 
 #label [ save-xt ] "generator" set-word-property
index 47ff9c138e12f5a6327fbe3177c98730ea9e0daa..f6f2dce321fbd882aaa10aa86786b8a642a8b661 100644 (file)
@@ -20,12 +20,6 @@ USE: test
 [ 1 [ ] 2keep ] unit-test-fails
 [ 3 1 2 ] [ 1 2 [ 2drop 3 ] 2keep ] unit-test
 
-[ cond ] unit-test-fails
-[ [ [ 1 = ] [ ] ] cond ] unit-test-fails
-
-[   ] [ 3 [ ] cond ] unit-test
-[ t ] [ 4 [ [ 1 = ] [ ] [ 4 = ] [ drop t ] [ 2 = ] [ ] ] cond ] unit-test
-
 [ 0 ] [ f [ sq ] [ 0 ] ifte* ] unit-test
 [ 4 ] [ 2 [ sq ] [ 0 ] ifte* ] unit-test
 
index 0f233543a9738d4e00b77b236a27ade7a0765815..c20b85c7e1148919ac2842bde3255e98fe180bf5 100644 (file)
@@ -204,5 +204,5 @@ SYMBOL: sym-test
 [ [ [ cons ] [ cons ] ] ] [ [ uncons cons ] infer ] unit-test
 [ [ [ object ] [ object ] ] ] [ [ dup [ car ] when ] infer ] unit-test
 [ [ [ vector ] [ vector ] ] ] [ [ vector-clone ] infer ] unit-test
-[ [ [ number ] [ number ] ] ] [ [ dup + ] infer ] unit-test
-[ [ [ number number number ] [ number ] ] ] [ [ digit+ ] infer ] unit-test
+[ [ [ number ] [ number ] ] ] [ [ dup + ] infer ] unit-test
+[ [ [ number number number ] [ number ] ] ] [ [ digit+ ] infer ] unit-test
index b72571438255ea885d8c58132a844dcb3a75e3ec..2531fa9754b90d3e124498da9ccdf3e952a6a722 100644 (file)
@@ -4,8 +4,6 @@
 F_ARRAY* allot_array(CELL type, CELL capacity)
 {
        F_ARRAY* array;
-       if(capacity < 0)
-               general_error(ERROR_NEGATIVE_ARRAY_SIZE,tag_fixnum(capacity));
        array = allot_object(type,sizeof(F_ARRAY) + capacity * CELLS);
        array->capacity = capacity;
        return array;
@@ -61,7 +59,7 @@ void fixup_array(F_ARRAY* array)
 {
        int i = 0;
        for(i = 0; i < array->capacity; i++)
-               fixup((void*)AREF(array,i));
+               data_fixup((void*)AREF(array,i));
 }
 
 void collect_array(F_ARRAY* array)
index 98b15a03d2c04617326e5e5ad117de325c00d123..70596ee2aa3f107fe2c359a2db223a209cec0950 100644 (file)
@@ -1,11 +1,5 @@
 #include "factor.h"
 
-void init_compiler(void)
-{
-       init_zone(&compiling,COMPILE_ZONE_SIZE);
-       literal_top = compiling.base;
-}
-
 void primitive_compiled_offset(void)
 {
        box_integer(compiling.here);
@@ -25,6 +19,8 @@ void primitive_literal_top(void)
 void primitive_set_literal_top(void)
 {
        CELL offset = unbox_integer();
+       if(offset >= literal_max)
+               critical_error("Too many compiled literals",offset);
        literal_top = offset;
 }
 
index cc187d19bbbb22bfb0477231ab17b1da49b8dea7..af7c40b71fe79c33e34fb0336529f0fc38eb1629 100644 (file)
@@ -1,7 +1,20 @@
+/* The compiled code heap is structures into blocks. */
+typedef struct
+{
+       CELL header;
+       CELL code_length;
+       CELL reloc_length;
+} F_COMPILED;
+
+#define COMPILED_HEADER 0x01c3babe
+
 ZONE compiling;
+
+#define LITERAL_TABLE 4096
+
 CELL literal_top;
+CELL literal_max;
 
-void init_compiler(void);
 void primitive_compiled_offset(void);
 void primitive_set_compiled_offset(void);
 void primitive_literal_top(void);
index 644b045e25c04e8f250df0ed9430f009d06a4249..e1aa5bb71e022bb58c23b751aeb92ebe0f16387b 100644 (file)
@@ -8,9 +8,7 @@ void init_factor(char* image)
        init_io();
        init_signals();
 
-       init_compiler();
        init_errors();
-       gc_time = 0;
 
 #ifdef FACTOR_X86
        userenv[CPU_ENV] = tag_object(from_c_string("x86"));
index 8b3970ae91aed48d29cd22762964fb640e650ba2..3c54f1600b2a26bdbf360f08f2bb8f3654612d84 100644 (file)
@@ -125,7 +125,6 @@ typedef unsigned char BYTE;
 #include "arithmetic.h"
 #include "string.h"
 #include "misc.h"
-#include "relocate.h"
 #include "sbuf.h"
 #include "port.h"
 #include "io.h"
@@ -138,6 +137,7 @@ typedef unsigned char BYTE;
 #include "vector.h"
 #include "stack.h"
 #include "compiler.h"
+#include "relocate.h"
 #include "ffi.h"
 
 #endif /* __FACTOR_H__ */
index 6b0831e638af4030a648277f9d165ea65aac7823..b2b6f16e3f2346b681cdcb8415fea124823f1c87 100644 (file)
@@ -43,9 +43,11 @@ void primitive_alien(void)
 
 void primitive_local_alien(void)
 {
-       CELL length = unbox_integer();
+       F_FIXNUM length = unbox_integer();
        ALIEN* alien;
        F_STRING* local;
+       if(length < 0)
+               general_error(ERROR_NEGATIVE_ARRAY_SIZE,tag_fixnum(length));
        maybe_garbage_collection();
        alien = allot_object(ALIEN_TYPE,sizeof(ALIEN));
        local = string(length / CHARS,'\0');
index f76e3ac1ebcd168c977360bf35357a26bb25d58a..75cd0bd0ef530c50980dd9caaf3f028bf43eecda 100644 (file)
@@ -4,30 +4,64 @@ void load_image(char* filename)
 {
        FILE* file;
        HEADER h;
-       CELL size;
-       
+       HEADER_2 ext_h;
+
        printf("Loading %s...",filename);
 
        file = fopen(filename,"rb");
        if(file == NULL)
                fatal_error("Cannot open image for reading",errno);
 
-       /* read it in native byte order */
-       fread(&h,sizeof(HEADER)/sizeof(CELL),sizeof(CELL),file);
-
-       if(h.magic != IMAGE_MAGIC)
-               fatal_error("Bad magic number",h.magic);
-       if(h.version != IMAGE_VERSION)
-               fatal_error("Bad version number",h.version);
-
-       allot(h.size);
-
-       size = h.size / CELLS;
-
-       if(size != fread((void*)active.base,sizeof(CELL),size,file))
-               fatal_error("Wrong image length",h.size);
+       /* read header */
+       {
+               /* read it in native byte order */
+               fread(&h,sizeof(HEADER)/sizeof(CELL),sizeof(CELL),file);
+
+               if(h.magic != IMAGE_MAGIC)
+                       fatal_error("Bad magic number",h.magic);
+
+               if(h.version == IMAGE_VERSION)
+                       fread(&ext_h,sizeof(HEADER_2)/sizeof(CELL),sizeof(CELL),file);
+               else if(h.version == IMAGE_VERSION_0)
+               {
+                       ext_h.size = LITERAL_TABLE;
+                       ext_h.literal_top = 0;
+                       ext_h.literal_max = LITERAL_TABLE;
+                       ext_h.relocation_base = compiling.base;
+               }
+               else
+                       fatal_error("Bad version number",h.version);
+       }
+
+       /* read data heap */
+       {
+               CELL size = h.size / CELLS;
+               allot(h.size);
+
+               if(size != fread((void*)active.base,sizeof(CELL),size,file))
+                       fatal_error("Wrong data heap length",h.size);
+
+               active.here = active.base + h.size;
+               data_relocation_base = h.relocation_base;
+       }
+
+       /* read code heap */
+       {
+               CELL size = ext_h.size;
+               if(size + compiling.base >= compiling.limit)
+                       fatal_error("Code heap too large",ext_h.size);
+
+               if(h.version == IMAGE_VERSION
+                       && size != fread((void*)compiling.base,1,size,file))
+                       fatal_error("Wrong code heap length",ext_h.size);
+
+               compiling.here = compiling.base + ext_h.size;
+               literal_top = compiling.base + ext_h.literal_top;
+               literal_max = compiling.base + ext_h.literal_max;
+               compiling.here = compiling.base + ext_h.size;
+               code_relocation_base = ext_h.relocation_base;
+       }
 
-       active.here = active.base + h.size;
        fclose(file);
 
        printf(" relocating...");
@@ -38,7 +72,8 @@ void load_image(char* filename)
        userenv[GLOBAL_ENV] = h.global;
        userenv[BOOT_ENV] = h.boot;
 
-       relocate(h.relocation_base);
+       relocate_data();
+       relocate_code();
 
        printf(" done\n");
        fflush(stdout);
@@ -48,9 +83,10 @@ bool save_image(char* filename)
 {
        FILE* file;
        HEADER h;
+       HEADER_2 ext_h;
 
        fprintf(stderr,"Saving %s...\n",filename);
-       
+
        file = fopen(filename,"wb");
        if(file == NULL)
                fatal_error("Cannot open image for writing",errno);
@@ -59,11 +95,18 @@ bool save_image(char* filename)
        h.version = IMAGE_VERSION;
        h.relocation_base = active.base;
        h.boot = userenv[BOOT_ENV];
-       h.size = (active.here - active.base);
+       h.size = active.here - active.base;
        h.global = userenv[GLOBAL_ENV];
-
        fwrite(&h,sizeof(HEADER),1,file);
+
+       ext_h.size = compiling.here - compiling.base;
+       ext_h.literal_top = literal_top - compiling.base;
+       ext_h.literal_max = literal_max - compiling.base;
+       ext_h.relocation_base = compiling.base;
+       fwrite(&ext_h,sizeof(HEADER_2),1,file);
+
        fwrite((void*)active.base,h.size,1,file);
+       fwrite((void*)compiling.base,ext_h.size,1,file);
 
        fclose(file);
 
index e9305a4b0722444d205c2b30d8c9ddfe58d01261..cfc58394b833ac12f6cb3fecced7d82d4b780b95 100644 (file)
@@ -1,5 +1,6 @@
 #define IMAGE_MAGIC 0x0f0e0d0c
-#define IMAGE_VERSION 0
+#define IMAGE_VERSION_0 0
+#define IMAGE_VERSION 1
 
 typedef struct {
        CELL magic;
@@ -15,6 +16,18 @@ typedef struct {
        CELL size;
 } HEADER;
 
+/* If version is IMAGE_VERSION_1 */
+typedef struct EXT_HEADER {
+       /* size of code heap */
+       CELL size;
+       /* code relocation base */
+       CELL relocation_base;
+       /* end of literal table */
+       CELL literal_top;
+       /* maximum value of literal_top */
+       CELL literal_max;
+} HEADER_2;
+
 void load_image(char* file);
 bool save_image(char* file);
 void primitive_save_image(void);
index 64e2d794f02cf712e0f7db60dacbc91bcb304084..71e9ac0bc88862fe8fb8da9dc3631ebc2b8f2b33 100644 (file)
@@ -55,8 +55,10 @@ void init_arena(CELL size)
 {
        init_zone(&active,size);
        init_zone(&prior,size);
+       init_zone(&compiling,size);
        allot_profiling = false;
        gc_in_progress = false;
+       gc_time = 0;
 }
 
 void allot_profile_step(CELL a)
index 0c8d4813e259fe8a97f68d485903682e81109c37..ea43fbf3bbf0d184afb42ab8619fbfad63ca6de8 100644 (file)
@@ -48,11 +48,11 @@ void init_line_buffer(F_PORT* port, F_FIXNUM count)
 void fixup_port(F_PORT* port)
 {
        port->fd = (F_FIXNUM)INVALID_HANDLE_VALUE;
-       fixup(&port->buffer);
-       fixup(&port->line);
-       fixup(&port->client_host);
-       fixup(&port->client_port);
-       fixup(&port->io_error);
+       data_fixup(&port->buffer);
+       data_fixup(&port->line);
+       data_fixup(&port->client_host);
+       data_fixup(&port->client_port);
+       data_fixup(&port->io_error);
 }
 
 void collect_port(F_PORT* port)
index 4dc61f2d6f170f5537d08195561535c054203a66..7bb290a70fde41cbca37b2f02ba56484241483c4 100644 (file)
@@ -1,12 +1,6 @@
 #include "factor.h"
 
-void fixup(CELL* cell)
-{
-       if(TAG(*cell) != FIXNUM_TYPE && *cell != F)
-               *cell += (active.base - relocation_base);
-}
-
-void relocate_object()
+void relocate_object(CELL relocating)
 {
        switch(untag_header(get(relocating)))
        {
@@ -35,10 +29,9 @@ void relocate_object()
                fixup_alien((ALIEN*)relocating);
                break;
        }
-
 }
 
-void relocate_next()
+INLINE CELL relocate_data_next(CELL relocating)
 {
        CELL size = CELLS;
 
@@ -46,49 +39,142 @@ void relocate_next()
        {
        case HEADER_TYPE:
                size = untagged_object_size(relocating);
-               relocate_object();
+               relocate_object(relocating);
                break;
        case OBJECT_TYPE:
                if(get(relocating) == F)
                        break;
                /* fall thru */
        default:
-               fixup((CELL*)relocating);
+               data_fixup((CELL*)relocating);
                break;
        }
-       relocating += size;
+
+       return relocating + size;
 }
 
-void init_object(CELL* handle, CELL type)
+INLINE CELL init_object(CELL relocating, CELL* handle, CELL type)
 {
        if(untag_header(get(relocating)) != type)
                fatal_error("init_object() failed",get(relocating));
        *handle = tag_object((CELL*)relocating);
-       relocate_next();
+       return relocate_data_next(relocating);
 }
 
-void relocate(CELL r)
+void relocate_data()
 {
-       relocation_base = r;
-
-       fixup(&userenv[BOOT_ENV]);
-       fixup(&userenv[GLOBAL_ENV]);
+       CELL relocating = active.base;
 
-       relocating = active.base;
+       data_fixup(&userenv[BOOT_ENV]);
+       data_fixup(&userenv[GLOBAL_ENV]);
 
        /* The first object in the image must always T */
-       init_object(&T,T_TYPE);
+       relocating = init_object(relocating,&T,T_TYPE);
 
        /* The next three must be bignum 0, 1, -1  */
-       init_object(&bignum_zero,BIGNUM_TYPE);
-       init_object(&bignum_pos_one,BIGNUM_TYPE);
-       init_object(&bignum_neg_one,BIGNUM_TYPE);
-       
+       relocating = init_object(relocating,&bignum_zero,BIGNUM_TYPE);
+       relocating = init_object(relocating,&bignum_pos_one,BIGNUM_TYPE);
+       relocating = init_object(relocating,&bignum_neg_one,BIGNUM_TYPE);
+
        for(;;)
        {
                if(relocating >= active.here)
                        break;
 
-               relocate_next();
+               relocating = relocate_data_next(relocating);
+       }
+
+       relocating = compiling.base;
+
+       for(;;)
+       {
+               if(relocating >= literal_top)
+                       break;
+
+               relocating = relocate_data_next(relocating);
+       }
+}
+
+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));
+}
+
+void relocate_dlsym(F_REL* rel, bool relative)
+{
+       F_STRING* str = untag_string(get(rel->argument));
+       char* c_str = to_c_string(str);
+       put(rel->offset,(CELL)dlsym(NULL,c_str)
+               - (relative ? rel->offset + CELLS : 0));
+}
+
+INLINE CELL relocate_code_next(CELL relocating)
+{
+       F_COMPILED* compiled = (F_COMPILED*)relocating;
+
+       F_REL* rel = (F_REL*)(
+               relocating + sizeof(F_COMPILED)
+               + compiled->code_length);
+
+       F_REL* rel_end = (F_REL*)(
+               relocating + sizeof(F_COMPILED)
+               + compiled->code_length
+               + compiled->reloc_length);
+
+       if(compiled->header != COMPILED_HEADER)
+               fatal_error("Wrong compiled header",relocating);
+
+       while(rel < rel_end)
+       {
+               /* to_c_string can fill up the heap */
+               maybe_garbage_collection();
+
+               code_fixup(&rel->offset);
+
+               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_SELF:
+                       code_fixup(&rel->argument);
+                       relocate_dlsym(rel,true);
+                       break;
+               case F_ABSOLUTE_DLSYM_SELF:
+                       code_fixup(&rel->argument);
+                       relocate_dlsym(rel,false);
+                       break;
+               case F_ABSOLUTE:
+                       code_fixup((CELL*)rel->offset);
+                       break;
+               default:
+                       fatal_error("Unsupported rel",rel->type);
+                       break;
+               }
+
+               rel++;
+       }
+
+       return (CELL)rel_end;
+}
+
+void relocate_code()
+{
+       /* start relocating from the end of the space reserved for literals */
+       CELL relocating = literal_max;
+
+       for(;;)
+       {
+               /* fprintf(stderr,"relocation %d %d\n",relocating,compiling.here); */
+               if(relocating >= compiling.here)
+                       break;
+
+               relocating = relocate_code_next(relocating);
        }
 }
index 4f52605241da4b421018e56544d120d03052a9f0..c30041125ff1d33edf7ed42a37649a6b6884c4e2 100644 (file)
@@ -1,10 +1,36 @@
-/* relocation base of currently loaded image */
-CELL relocation_base;
+/* relocation base of currently loaded image's data heap */
+CELL data_relocation_base;
 
-/* used as a temporary variable while relocating */
-CELL relocating;
+INLINE void data_fixup(CELL* cell)
+{
+       if(TAG(*cell) != FIXNUM_TYPE && *cell != F)
+               *cell += (active.base - data_relocation_base);
+}
 
-void fixup(CELL* cell);
-void relocate_object();
-void relocate_next(void);
-void relocate(CELL r);
+typedef enum {
+       /* arg is a primitive number */
+       F_RELATIVE_PRIMITIVE,
+       F_ABSOLUTE_PRIMITIVE,
+       /* arg is an pointer in the literal table holding a tagged string */
+       F_RELATIVE_DLSYM_SELF,
+       F_ABSOLUTE_DLSYM_SELF,
+       /* relocate an address to start of code heap */
+       F_ABSOLUTE
+} F_RELTYPE;
+
+/* code relocation consists of a table of entries for each fixup */
+typedef struct {
+       F_RELTYPE type;
+       CELL offset;
+       CELL argument;
+} F_REL;
+
+CELL code_relocation_base;
+
+INLINE void code_fixup(CELL* cell)
+{
+       *cell += (compiling.base - code_relocation_base);
+}
+
+void relocate_data();
+void relocate_code();
index 63f288f282eeadbcd6de271e122562b0e31329f8..4efff076d5429f394bbb50771e977f627f9dd67d 100644 (file)
@@ -2,7 +2,10 @@
 
 F_SBUF* sbuf(F_FIXNUM capacity)
 {
-       F_SBUF* sbuf = allot_object(SBUF_TYPE,sizeof(F_SBUF));
+       F_SBUF* sbuf;
+       if(capacity < 0)
+               general_error(ERROR_NEGATIVE_ARRAY_SIZE,tag_fixnum(capacity));
+       sbuf = allot_object(SBUF_TYPE,sizeof(F_SBUF));
        sbuf->top = 0;
        sbuf->string = tag_object(string(capacity,'\0'));
        return sbuf;
@@ -182,7 +185,7 @@ void primitive_sbuf_hashcode(void)
 
 void fixup_sbuf(F_SBUF* sbuf)
 {
-       fixup(&sbuf->string);
+       data_fixup(&sbuf->string);
 }
 
 void collect_sbuf(F_SBUF* sbuf)
index 19a7c4a7768f7c3addb1e5e4b8f2e31707b08a98..c6d6c638597f0c64417b64109f11eb4b238b2c89 100644 (file)
@@ -1,12 +1,9 @@
 #include "factor.h"
 
 /* untagged */
-F_STRING* allot_string(F_FIXNUM capacity)
+F_STRING* allot_string(CELL capacity)
 {
-       F_STRING* string;
-       if(capacity < 0)
-               general_error(ERROR_NEGATIVE_ARRAY_SIZE,tag_fixnum(capacity));
-       string = allot_object(STRING_TYPE,
+       F_STRING* string = allot_object(STRING_TYPE,
                sizeof(F_STRING) + capacity * CHARS);
        string->capacity = capacity;
        return string;
@@ -15,7 +12,7 @@ F_STRING* allot_string(F_FIXNUM capacity)
 /* call this after constructing a string */
 /* uses same algorithm as java.lang.String for compatibility with
 images generated from Java Factor. */
-F_FIXNUM hash_string(F_STRING* str, F_FIXNUM len)
+F_FIXNUM hash_string(F_STRING* str, CELL len)
 {
        F_FIXNUM hash = 0;
        CELL i;
@@ -30,7 +27,7 @@ void rehash_string(F_STRING* str)
 }
 
 /* untagged */
-F_STRING* string(F_FIXNUM capacity, CELL fill)
+F_STRING* string(CELL capacity, CELL fill)
 {
        CELL i;
 
index 1e84a62de679d6663084feb8bb6d99de21c3e1fc..f9db01df0d0c6c0c6bf34c3e07ba4939c9d0d80e 100644 (file)
@@ -12,9 +12,9 @@ INLINE F_STRING* untag_string(CELL tagged)
        return (F_STRING*)UNTAG(tagged);
 }
 
-F_STRING* allot_string(F_FIXNUM capacity);
-F_STRING* string(F_FIXNUM capacity, CELL fill);
-F_FIXNUM hash_string(F_STRING* str, F_FIXNUM len);
+F_STRING* allot_string(CELL capacity);
+F_STRING* string(CELL capacity, CELL fill);
+F_FIXNUM hash_string(F_STRING* str, CELL len);
 void rehash_string(F_STRING* str);
 F_STRING* grow_string(F_STRING* string, F_FIXNUM capacity, uint16_t fill);
 BYTE* to_c_string(F_STRING* s);
index 13b9c90d9e880a411edf3fafe0bf2f1fd581189d..8480f6b8fc28b0adf06a3da688f8c7f79eb09e50 100644 (file)
@@ -85,7 +85,7 @@ CELL untagged_object_size(CELL pointer)
                size = sizeof(ALIEN);
                break;
        default:
-               critical_error("Cannot determine size",relocating);
+               critical_error("Cannot determine size",pointer);
                size = -1;/* can't happen */
                break;
        }
index 2c8a19624b6cd1dfa32a0efba36f7a5b03f6c401..921ea3444d519c38c2fea809e40a7c3e6b6a6c16 100644 (file)
@@ -2,7 +2,10 @@
 
 F_VECTOR* vector(F_FIXNUM capacity)
 {
-       F_VECTOR* vector = allot_object(VECTOR_TYPE,sizeof(F_VECTOR));
+       F_VECTOR* vector;
+       if(capacity < 0)
+               general_error(ERROR_NEGATIVE_ARRAY_SIZE,tag_fixnum(capacity));
+       vector = allot_object(VECTOR_TYPE,sizeof(F_VECTOR));
        vector->top = 0;
        vector->array = tag_object(array(capacity,F));
        return vector;
@@ -62,7 +65,7 @@ void primitive_set_vector_nth(void)
 
 void fixup_vector(F_VECTOR* vector)
 {
-       fixup(&vector->array);
+       data_fixup(&vector->array);
 }
 
 void collect_vector(F_VECTOR* vector)
index d02f0600ee56d8856577e1e124248c264660507f..5f25306a855f9bd8dc9c8de86fff67e237146417 100644 (file)
@@ -44,9 +44,15 @@ void primitive_to_word(void)
 
 void fixup_word(F_WORD* word)
 {
-       update_xt(word);
-       fixup(&word->parameter);
-       fixup(&word->plist);
+       if(word->xt >= code_relocation_base
+               && word->xt < code_relocation_base
+               - compiling.base + compiling.limit)
+               code_fixup(&word->xt);
+       else
+               update_xt(word);
+
+       data_fixup(&word->parameter);
+       data_fixup(&word->plist);
 }
 
 void collect_word(F_WORD* word)