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." ".image" surround ;
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 [ (objects) ] dip [ 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 [ make-jit ] dip set ; inline
102 : define-sub-primitive ( quot rc rt offset word -- )
103 [ make-jit ] dip 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-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 }
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 [ swap tag-fixnum emit call align-here ] dip ;
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 : check-string ( string -- )
356 [ "Bootstrap cannot emit non-ASCII strings" throw ] when ;
358 : emit-string ( string -- ptr )
360 string type-number object tag-number [
361 dup length emit-fixnum
368 #! We pool strings so that each string is only written once
370 [ emit-string ] cache-object ;
372 : assert-empty ( seq -- )
375 : emit-dummy-array ( obj type -- ptr )
377 type-number object tag-number
378 [ 0 emit-fixnum ] emit-object
382 byte-array type-number object tag-number [
383 dup length emit-fixnum
388 : (emit-tuple) ( tuple -- pointer )
390 [ class transfer-word tuple-layout ] bi prefix [ ' ] map
391 tuple type-number dup [ emit-seq ] emit-object ;
393 : emit-tuple ( tuple -- pointer )
394 dup class name>> "tombstone" =
395 [ [ (emit-tuple) ] cache-object ] [ (emit-tuple) ] if ;
397 M: tuple ' emit-tuple ;
400 state>> "((tombstone))" "((empty))" ?
401 "hashtables.private" lookup def>> first
402 [ emit-tuple ] cache-object ;
405 : emit-array ( array -- offset )
406 [ ' ] map array type-number object tag-number
407 [ [ length emit-fixnum ] [ emit-seq ] bi ] emit-object ;
409 M: array ' emit-array ;
411 ! This is a hack. We need to detect arrays which are tuple
412 ! layout arrays so that they can be internalized, but making
413 ! them a built-in type is not worth it.
414 PREDICATE: tuple-layout-array < array
416 [ first tuple-class? ]
422 M: tuple-layout-array '
424 [ dup integer? [ <fake-bignum> ] when ] map
433 quotation type-number object tag-number [
435 f ' emit ! compiled>>
444 all-words [ emit-word ] each ;
448 dictionary source-files builtins
449 update-map implementors-map
450 } [ [ bootstrap-word ] [ get ] bi ] H{ } map>assoc
452 class<=-cache class-not-cache classes-intersect-cache
453 class-and-cache class-or-cache next-method-quot-cache
454 } [ H{ } clone ] H{ } map>assoc assoc-union
456 bootstrap-global emit-userenv ;
458 : emit-boot-quot ( -- )
459 bootstrap-boot-quot emit-userenv ;
461 : emit-jit-data ( -- )
463 \ dispatch jit-dispatch-word set
464 \ do-primitive jit-primitive-word set
465 \ declare jit-declare-word set
466 \ dip jit-dip-word set
467 \ 2dip jit-2dip-word set
468 \ 3dip jit-3dip-word set
469 [ undefined ] undefined-quot set
495 } [ emit-userenv ] each ;
497 : fixup-header ( -- )
498 heap-size data-heap-size-offset fixup ;
500 : build-image ( -- image )
501 800000 <vector> image set
502 20000 <hashtable> objects set
503 emit-header t, 0, 1, -1,
504 "Building generic words..." print flush
505 call-remake-generics-hook
506 "Serializing words..." print flush
508 "Serializing JIT data..." print flush
510 "Serializing global namespace..." print flush
512 "Serializing boot quotation..." print flush
514 "Performing word fixups..." print flush
516 "Performing header fixups..." print flush
518 "Image length: " write image get length .
519 "Object cache size: " write objects get assoc-size .
520 \ word global delete-at
525 : (write-image) ( image -- )
526 bootstrap-cell big-endian get [
527 [ >be write ] curry each
529 [ >le write ] curry each
532 : write-image ( image -- )
533 "Writing image to " write
534 architecture get boot-image-name resource-path
535 [ write "..." print flush ]
536 [ binary [ (write-image) ] with-file-writer ] bi ;
540 : make-image ( arch -- )
543 "resource:/core/bootstrap/stage1.factor" run-file
549 images [ make-image ] each ;