1 ! Copyright (C) 2004, 2008 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: alien arrays byte-arrays generic assocs hashtables assocs
4 hashtables.private io kernel kernel.private math namespaces make
5 parser prettyprint sequences sequences.private strings sbufs
6 vectors words quotations assocs system layouts splitting
7 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
10 quotations.private sequences.private combinators
11 io.encodings.binary math.order math.private accessors
12 slots.private compiler.units ;
15 : arch ( os cpu -- arch )
17 { "ppc" [ "-ppc" append ] }
18 { "x86.64" [ "winnt" = "winnt" "unix" ? "-x86.64" append ] }
23 os name>> cpu name>> arch ;
25 : boot-image-name ( arch -- string )
26 "boot." swap ".image" 3append ;
28 : my-boot-image-name ( -- string )
29 my-arch boot-image-name ;
34 "winnt-x86.64" "unix-x86.64"
35 "linux-ppc" "macosx-ppc"
40 ! Object cache; we only consider numbers equal if they have the
46 M: id hashcode* obj>> hashcode* ;
48 GENERIC: (eql?) ( obj1 obj2 -- ? )
50 : eql? ( obj1 obj2 -- ? )
51 [ (eql?) ] [ [ class ] bi@ = ] 2bi and ;
58 [ [ eql? ] 2all? ] [ 2drop f ] if
64 over id? [ [ obj>> ] bi@ eql? ] [ 2drop f ] if ;
68 : (objects) <id> objects get ; inline
70 : lookup-object ( obj -- n/f ) (objects) at ;
72 : put-object ( n obj -- ) (objects) set-at ;
74 : cache-object ( obj quot -- value )
75 >r (objects) r> [ obj>> ] prepose cache ; inline
79 : image-magic HEX: 0f0e0d0c ; inline
80 : image-version 4 ; inline
82 : data-base 1024 ; inline
84 : userenv-size 70 ; inline
86 : header-size 10 ; inline
88 : data-heap-size-offset 3 ; inline
92 : -1-offset 9 ; inline
94 SYMBOL: sub-primitives
96 : make-jit ( quot rc rt offset -- quad )
97 { [ { } make ] [ ] [ ] [ ] } spread 4array ; inline
99 : jit-define ( quot rc rt offset name -- )
100 >r make-jit r> set ; inline
102 : define-sub-primitive ( quot rc rt offset word -- )
103 >r make-jit r> sub-primitives get set-at ;
105 ! The image being constructed; a vector of word-size integers
108 ! Image output format
111 ! Bootstrap architecture name
114 ! Bootstrap global namesapce
115 SYMBOL: bootstrap-global
117 ! Boot quotation, set in stage1.factor
118 SYMBOL: bootstrap-boot-quot
121 SYMBOL: jit-code-format
123 SYMBOL: jit-primitive-word
124 SYMBOL: jit-primitive
125 SYMBOL: jit-word-jump
126 SYMBOL: jit-word-call
127 SYMBOL: jit-push-literal
128 SYMBOL: jit-push-immediate
131 SYMBOL: jit-dispatch-word
135 SYMBOL: jit-2dip-word
137 SYMBOL: jit-3dip-word
141 SYMBOL: jit-profiling
142 SYMBOL: jit-declare-word
143 SYMBOL: jit-save-stack
145 ! Default definition for undefined words
146 SYMBOL: undefined-quot
148 : userenvs ( -- assoc )
150 { bootstrap-boot-quot 20 }
151 { bootstrap-global 21 }
152 { jit-code-format 22 }
154 { jit-primitive-word 24 }
158 { jit-push-literal 28 }
161 { jit-dispatch-word 31 }
166 { jit-push-immediate 36 }
167 { jit-declare-word 42 }
168 { jit-save-stack 43 }
175 { undefined-quot 60 }
178 : userenv-offset ( symbol -- n )
179 userenvs at header-size + ;
181 : emit ( cell -- ) image get push ;
183 : emit-64 ( cell -- )
187 d>w/w big-endian get [ swap ] unless emit emit
190 : emit-seq ( seq -- ) image get push-all ;
192 : fixup ( value offset -- ) image get set-nth ;
194 : heap-size ( -- size )
195 image get length header-size - userenv-size -
198 : here ( -- size ) heap-size data-base + ;
200 : here-as ( tag -- pointer ) here bitor ;
203 here 8 mod 4 = [ 0 emit ] when ;
205 : emit-fixnum ( n -- ) tag-fixnum emit ;
207 : emit-object ( header tag quot -- addr )
208 swap here-as >r swap tag-fixnum emit call align-here r> ;
211 ! Write an object to the image.
212 GENERIC: ' ( obj -- ptr )
219 data-base emit ! relocation base at end of header
220 0 emit ! size of data heap set later
221 0 emit ! reloc base of code heap is 0
222 0 emit ! size of code heap is 0
223 0 emit ! pointer to t object
224 0 emit ! pointer to bignum 0
225 0 emit ! pointer to bignum 1
226 0 emit ! pointer to bignum -1
227 userenv-size [ f ' emit ] times ;
229 : emit-userenv ( symbol -- )
230 [ get ' ] [ userenv-offset ] bi fixup ;
234 : bignum-bits ( -- n ) bootstrap-cell-bits 2 - ;
236 : bignum-radix ( -- n ) bignum-bits 2^ 1- ;
238 : bignum>seq ( n -- seq )
239 #! n is positive or zero.
241 [ [ bignum-bits neg shift ] [ bignum-radix bitand ] bi ]
244 : emit-bignum ( n -- )
245 dup dup 0 < [ neg ] when bignum>seq
246 [ nip length 1+ emit-fixnum ]
247 [ drop 0 < 1 0 ? emit ]
253 bignum tag-number dup [ emit-bignum ] emit-object
259 #! When generating a 32-bit image on a 64-bit system,
260 #! some fixnums should be bignums.
262 bootstrap-most-negative-fixnum
263 bootstrap-most-positive-fixnum between?
264 [ tag-fixnum ] [ >bignum ' ] if ;
266 TUPLE: fake-bignum n ;
268 C: <fake-bignum> fake-bignum
270 M: fake-bignum ' n>> tag-fixnum ;
276 float tag-number dup [
277 align-here double>bits emit-64
283 ! Padded with fixnums for 8-byte alignment
285 : t, ( -- ) t t-offset fixup ;
288 #! f is #define F RETAG(0,F_TYPE)
289 drop \ f tag-number ;
291 : 0, ( -- ) 0 >bignum ' 0-offset fixup ;
292 : 1, ( -- ) 1 >bignum ' 1-offset fixup ;
293 : -1, ( -- ) -1 >bignum ' -1-offset fixup ;
297 : word-sub-primitive ( word -- obj )
298 global [ target-word ] bind sub-primitives get at ;
300 : emit-word ( word -- )
302 [ subwords [ emit-word ] each ]
306 [ hashcode <fake-bignum> , ]
313 [ word-sub-primitive , ]
316 [ drop 0 , ] ! profiling
320 \ word type-number object tag-number
321 [ emit-seq ] emit-object
324 : word-error ( word msg -- * )
325 [ % dup vocabulary>> % " " % name>> % ] "" make throw ;
327 : transfer-word ( word -- word )
328 [ target-word ] keep or ;
330 : fixup-word ( word -- offset )
331 transfer-word dup lookup-object
332 [ ] [ "Not in image: " word-error ] ?if ;
335 image get [ dup word? [ fixup-word ] when ] change-each ;
342 wrapped>> ' wrapper type-number object tag-number
343 [ emit ] emit-object ;
346 : emit-bytes ( seq -- )
347 bootstrap-cell <groups>
348 big-endian get [ [ be> ] map ] [ [ le> ] map ] if
351 : pad-bytes ( seq -- newseq )
352 dup length bootstrap-cell align 0 pad-right ;
354 : emit-string ( string -- ptr )
355 string type-number object tag-number [
356 dup length emit-fixnum
363 #! We pool strings so that each string is only written once
365 [ emit-string ] cache-object ;
367 : assert-empty ( seq -- )
370 : emit-dummy-array ( obj type -- ptr )
372 type-number object tag-number
373 [ 0 emit-fixnum ] emit-object
377 byte-array type-number object tag-number [
378 dup length emit-fixnum
383 : (emit-tuple) ( tuple -- pointer )
385 [ class transfer-word tuple-layout ] bi prefix [ ' ] map
386 tuple type-number dup [ emit-seq ] emit-object ;
388 : emit-tuple ( tuple -- pointer )
389 dup class name>> "tombstone" =
390 [ [ (emit-tuple) ] cache-object ] [ (emit-tuple) ] if ;
392 M: tuple ' emit-tuple ;
395 state>> "((tombstone))" "((empty))" ?
396 "hashtables.private" lookup def>> first
397 [ emit-tuple ] cache-object ;
400 : emit-array ( array -- offset )
401 [ ' ] map array type-number object tag-number
402 [ [ length emit-fixnum ] [ emit-seq ] bi ] emit-object ;
404 M: array ' emit-array ;
406 ! This is a hack. We need to detect arrays which are tuple
407 ! layout arrays so that they can be internalized, but making
408 ! them a built-in type is not worth it.
409 PREDICATE: tuple-layout-array < array
411 [ first tuple-class? ]
417 M: tuple-layout-array '
419 [ dup integer? [ <fake-bignum> ] when ] map
428 quotation type-number object tag-number [
430 f ' emit ! compiled>>
439 all-words [ emit-word ] each ;
443 dictionary source-files builtins
444 update-map implementors-map
445 } [ [ bootstrap-word ] [ get ] bi ] H{ } map>assoc
447 class<=-cache class-not-cache classes-intersect-cache
448 class-and-cache class-or-cache next-method-quot-cache
449 } [ H{ } clone ] H{ } map>assoc assoc-union
451 bootstrap-global emit-userenv ;
453 : emit-boot-quot ( -- )
454 bootstrap-boot-quot emit-userenv ;
456 : emit-jit-data ( -- )
458 \ dispatch jit-dispatch-word set
459 \ do-primitive jit-primitive-word set
460 \ declare jit-declare-word set
461 \ dip jit-dip-word set
462 \ 2dip jit-2dip-word set
463 \ 3dip jit-3dip-word set
464 [ undefined ] undefined-quot set
490 } [ emit-userenv ] each ;
492 : fixup-header ( -- )
493 heap-size data-heap-size-offset fixup ;
495 : build-image ( -- image )
496 800000 <vector> image set
497 20000 <hashtable> objects set
498 emit-header t, 0, 1, -1,
499 "Building generic words..." print flush
500 call-remake-generics-hook
501 "Serializing words..." print flush
503 "Serializing JIT data..." print flush
505 "Serializing global namespace..." print flush
507 "Serializing boot quotation..." print flush
509 "Performing word fixups..." print flush
511 "Performing header fixups..." print flush
513 "Image length: " write image get length .
514 "Object cache size: " write objects get assoc-size .
515 \ word global delete-at
520 : (write-image) ( image -- )
521 bootstrap-cell big-endian get [
522 [ >be write ] curry each
524 [ >le write ] curry each
527 : write-image ( image -- )
528 "Writing image to " write
529 architecture get boot-image-name resource-path
530 [ write "..." print flush ]
531 [ binary [ (write-image) ] with-file-writer ] bi ;
535 : make-image ( arch -- )
538 "resource:/core/bootstrap/stage1.factor" run-file
544 images [ make-image ] each ;