1 ! Copyright (C) 2004, 2008 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: alien arrays bit-arrays byte-arrays generic assocs
4 hashtables assocs hashtables.private io kernel kernel.private
5 math namespaces parser prettyprint sequences sequences.private
6 strings sbufs vectors words quotations assocs system layouts
7 splitting grouping growable classes classes.builtin classes.tuple
8 classes.tuple.private words.private io.binary io.files vocabs
9 vocabs.loader source-files definitions debugger float-arrays
10 quotations.private sequences.private combinators
11 io.encodings.binary math.order accessors ;
16 dup "ppc" = [ >r os name>> "-" r> 3append ] when ;
18 : boot-image-name ( arch -- string )
19 "boot." swap ".image" 3append ;
21 : my-boot-image-name ( -- string )
22 my-arch boot-image-name ;
28 "linux-ppc" "macosx-ppc"
34 ! Object cache; we only consider numbers equal if they have the
40 M: id hashcode* obj>> hashcode* ;
42 GENERIC: (eql?) ( obj1 obj2 -- ? )
44 : eql? ( obj1 obj2 -- ? )
45 [ (eql?) ] [ [ class ] bi@ = ] 2bi and ;
52 [ [ eql? ] 2all? ] [ 2drop f ] if
58 over id? [ [ obj>> ] bi@ eql? ] [ 2drop f ] if ;
62 : (objects) <id> objects get ; inline
64 : lookup-object ( obj -- n/f ) (objects) at ;
66 : put-object ( n obj -- ) (objects) set-at ;
68 : cache-object ( obj quot -- value )
69 >r (objects) r> [ obj>> ] prepose cache ; inline
73 : image-magic HEX: 0f0e0d0c ; inline
74 : image-version 4 ; inline
76 : data-base 1024 ; inline
78 : userenv-size 64 ; inline
80 : header-size 10 ; inline
82 : data-heap-size-offset 3 ; inline
86 : -1-offset 9 ; inline
88 : jit-define ( quot rc rt offset name -- )
89 >r { [ { } make ] [ ] [ ] [ ] } spread 4array r> set ;
91 ! The image being constructed; a vector of word-size integers
97 ! Bootstrap architecture name
100 ! Bootstrap global namesapce
101 SYMBOL: bootstrap-global
103 ! Boot quotation, set in stage1.factor
104 SYMBOL: bootstrap-boot-quot
107 SYMBOL: jit-code-format
109 SYMBOL: jit-primitive-word
110 SYMBOL: jit-primitive
111 SYMBOL: jit-word-jump
112 SYMBOL: jit-word-call
113 SYMBOL: jit-push-literal
116 SYMBOL: jit-dispatch-word
120 SYMBOL: jit-profiling
122 ! Default definition for undefined words
123 SYMBOL: undefined-quot
125 : userenv-offset ( symbol -- n )
127 { bootstrap-boot-quot 20 }
128 { bootstrap-global 21 }
129 { jit-code-format 22 }
131 { jit-primitive-word 24 }
135 { jit-push-literal 28 }
138 { jit-dispatch-word 31 }
143 { undefined-quot 37 }
146 : emit ( cell -- ) image get push ;
148 : emit-64 ( cell -- )
152 d>w/w big-endian get [ swap ] unless emit emit
155 : emit-seq ( seq -- ) image get push-all ;
157 : fixup ( value offset -- ) image get set-nth ;
159 : heap-size ( -- size )
160 image get length header-size - userenv-size -
163 : here ( -- size ) heap-size data-base + ;
165 : here-as ( tag -- pointer ) here bitor ;
168 here 8 mod 4 = [ 0 emit ] when ;
170 : emit-fixnum ( n -- ) tag-fixnum emit ;
172 : emit-object ( header tag quot -- addr )
173 swap here-as >r swap tag-fixnum emit call align-here r> ;
176 ! Write an object to the image.
177 GENERIC: ' ( obj -- ptr )
184 data-base emit ! relocation base at end of header
185 0 emit ! size of data heap set later
186 0 emit ! reloc base of code heap is 0
187 0 emit ! size of code heap is 0
188 0 emit ! pointer to t object
189 0 emit ! pointer to bignum 0
190 0 emit ! pointer to bignum 1
191 0 emit ! pointer to bignum -1
192 userenv-size [ f ' emit ] times ;
194 : emit-userenv ( symbol -- )
195 [ get ' ] [ userenv-offset ] bi fixup ;
199 : bignum-bits ( -- n ) bootstrap-cell-bits 2 - ;
201 : bignum-radix ( -- n ) bignum-bits 2^ 1- ;
203 : bignum>seq ( n -- seq )
204 #! n is positive or zero.
206 [ [ bignum-bits neg shift ] [ bignum-radix bitand ] bi ]
209 : emit-bignum ( n -- )
210 dup dup 0 < [ neg ] when bignum>seq
211 [ nip length 1+ emit-fixnum ]
212 [ drop 0 < 1 0 ? emit ]
218 bignum tag-number dup [ emit-bignum ] emit-object
224 #! When generating a 32-bit image on a 64-bit system,
225 #! some fixnums should be bignums.
227 bootstrap-most-negative-fixnum
228 bootstrap-most-positive-fixnum between?
229 [ tag-fixnum ] [ >bignum ' ] if ;
235 float tag-number dup [
236 align-here double>bits emit-64
242 ! Padded with fixnums for 8-byte alignment
244 : t, ( -- ) t t-offset fixup ;
247 #! f is #define F RETAG(0,F_TYPE)
248 drop \ f tag-number ;
250 : 0, ( -- ) 0 >bignum ' 0-offset fixup ;
251 : 1, ( -- ) 1 >bignum ' 1-offset fixup ;
252 : -1, ( -- ) -1 >bignum ' -1-offset fixup ;
256 : emit-word ( word -- )
258 [ subwords [ emit-word ] each ]
275 \ word type-number object tag-number
276 [ emit-seq ] emit-object
279 : word-error ( word msg -- * )
280 [ % dup vocabulary>> % " " % name>> % ] "" make throw ;
282 : transfer-word ( word -- word )
283 [ target-word ] keep or ;
285 : fixup-word ( word -- offset )
286 transfer-word dup lookup-object
287 [ ] [ "Not in image: " word-error ] ?if ;
290 image get [ dup word? [ fixup-word ] when ] change-each ;
297 wrapped>> ' wrapper type-number object tag-number
298 [ emit ] emit-object ;
301 : emit-bytes ( seq -- )
302 bootstrap-cell <groups>
303 big-endian get [ [ be> ] map ] [ [ le> ] map ] if
306 : pad-bytes ( seq -- newseq )
307 dup length bootstrap-cell align 0 pad-right ;
309 : emit-string ( string -- ptr )
310 string type-number object tag-number [
311 dup length emit-fixnum
318 #! We pool strings so that each string is only written once
320 [ emit-string ] cache-object ;
322 : assert-empty ( seq -- )
325 : emit-dummy-array ( obj type -- ptr )
327 type-number object tag-number
328 [ 0 emit-fixnum ] emit-object
332 byte-array type-number object tag-number [
333 dup length emit-fixnum
337 M: bit-array ' bit-array emit-dummy-array ;
339 M: float-array ' float-array emit-dummy-array ;
342 : (emit-tuple) ( tuple -- pointer )
343 [ tuple>array rest-slice ]
344 [ class transfer-word tuple-layout ] bi prefix [ ' ] map
345 tuple type-number dup [ emit-seq ] emit-object ;
347 : emit-tuple ( tuple -- pointer )
348 dup class name>> "tombstone" =
349 [ [ (emit-tuple) ] cache-object ] [ (emit-tuple) ] if ;
351 M: tuple ' emit-tuple ;
364 \ tuple-layout type-number
365 object tag-number [ emit-seq ] emit-object
370 "((tombstone))" "((empty))" ? "hashtables.private" lookup
371 def>> first [ emit-tuple ] cache-object ;
375 [ ' ] map array type-number object tag-number
376 [ [ length emit-fixnum ] [ emit-seq ] bi ] emit-object ;
383 quotation type-number object tag-number [
385 f ' emit ! compiled>>
394 all-words [ emit-word ] each ;
399 dictionary source-files builtins
400 update-map implementors-map class<=-cache
401 class-not-cache classes-intersect-cache class-and-cache
403 } [ dup get swap bootstrap-word set ] each
406 bootstrap-global emit-userenv ;
408 : emit-boot-quot ( -- )
409 bootstrap-boot-quot emit-userenv ;
411 : emit-jit-data ( -- )
413 \ dispatch jit-dispatch-word set
414 \ do-primitive jit-primitive-word set
415 [ undefined ] undefined-quot set
432 } [ emit-userenv ] each ;
434 : fixup-header ( -- )
435 heap-size data-heap-size-offset fixup ;
437 : build-image ( -- image )
438 800000 <vector> image set
439 20000 <hashtable> objects set
440 emit-header t, 0, 1, -1,
441 "Serializing words..." print flush
443 "Serializing JIT data..." print flush
445 "Serializing global namespace..." print flush
447 "Serializing boot quotation..." print flush
449 "Performing word fixups..." print flush
451 "Performing header fixups..." print flush
453 "Image length: " write image get length .
454 "Object cache size: " write objects get assoc-size .
455 \ word global delete-at
460 : (write-image) ( image -- )
461 bootstrap-cell big-endian get [
462 [ >be write ] curry each
464 [ >le write ] curry each
467 : write-image ( image -- )
468 "Writing image to " write
469 architecture get boot-image-name resource-path
470 [ write "..." print flush ]
471 [ binary [ (write-image) ] with-file-writer ] bi ;
475 : make-image ( arch -- )
478 "resource:/core/bootstrap/stage1.factor" run-file
484 images [ make-image ] each ;