factor/core/bootstrap/image/image.factor

492 lines
12 KiB
Factor
Raw Normal View History

2008-01-02 19:36:36 -05:00
! Copyright (C) 2004, 2008 Slava Pestov.
2007-09-20 18:09:08 -04:00
! See http://factorcode.org/license.txt for BSD license.
USING: alien arrays bit-arrays byte-arrays generic assocs
hashtables assocs hashtables.private io kernel kernel.private
math namespaces parser prettyprint sequences sequences.private
strings sbufs vectors words quotations assocs system layouts
2008-04-03 22:19:20 -04:00
splitting growable classes classes.builtin classes.tuple
classes.tuple.private words.private io.binary io.files vocabs
vocabs.loader source-files definitions debugger float-arrays
quotations.private sequences.private combinators
io.encodings.binary math.order accessors ;
2007-09-20 18:09:08 -04:00
IN: bootstrap.image
: my-arch ( -- arch )
2008-04-02 17:32:58 -04:00
cpu word-name
2008-04-02 19:25:33 -04:00
dup "ppc" = [ >r os word-name "-" r> 3append ] when ;
: boot-image-name ( arch -- string )
"boot." swap ".image" 3append ;
: my-boot-image-name ( -- string )
my-arch boot-image-name ;
: images ( -- seq )
{
"x86.32"
"x86.64"
"linux-ppc" "macosx-ppc"
! "arm"
} ;
2007-09-20 18:09:08 -04:00
<PRIVATE
! Object cache; we only consider numbers equal if they have the
! same type
TUPLE: id obj ;
C: <id> id
M: id hashcode* obj>> hashcode* ;
2008-04-29 02:49:06 -04:00
GENERIC: (eql?) ( obj1 obj2 -- ? )
: eql? ( obj1 obj2 -- ? )
[ (eql?) ] [ [ class ] bi@ = ] 2bi and ;
M: integer (eql?) = ;
M: sequence (eql?)
over sequence? [
2dup [ length ] bi@ =
[ [ eql? ] 2all? ] [ 2drop f ] if
] [ 2drop f ] if ;
M: object (eql?) = ;
M: id equal?
2008-04-29 02:49:06 -04:00
over id? [ [ obj>> ] bi@ eql? ] [ 2drop f ] if ;
SYMBOL: objects
: (objects) <id> objects get ; inline
: lookup-object ( obj -- n/f ) (objects) at ;
: put-object ( n obj -- ) (objects) set-at ;
: cache-object ( obj quot -- value )
>r (objects) r> [ obj>> ] prepose cache ; inline
2007-09-20 18:09:08 -04:00
! Constants
: image-magic HEX: 0f0e0d0c ; inline
: image-version 4 ; inline
: data-base 1024 ; inline
2008-02-18 06:07:40 -05:00
: userenv-size 64 ; inline
2007-09-20 18:09:08 -04:00
: header-size 10 ; inline
: data-heap-size-offset 3 ; inline
: t-offset 6 ; inline
: 0-offset 7 ; inline
: 1-offset 8 ; inline
: -1-offset 9 ; inline
: array-start 2 bootstrap-cells object tag-number - ;
2007-09-22 02:28:49 -04:00
: scan@ array-start bootstrap-cell - ;
2007-09-20 18:09:08 -04:00
: wrapper@ bootstrap-cell object tag-number - ;
: word-xt@ 8 bootstrap-cells object tag-number - ;
: quot-array@ bootstrap-cell object tag-number - ;
: quot-xt@ 3 bootstrap-cells object tag-number - ;
2007-09-20 18:09:08 -04:00
: jit-define ( quot rc rt offset name -- )
2008-03-31 02:19:21 -04:00
>r { [ { } make ] [ ] [ ] [ ] } spread 4array r> set ;
2007-09-20 18:09:08 -04:00
! The image being constructed; a vector of word-size integers
SYMBOL: image
! Image output format
SYMBOL: big-endian
! Bootstrap architecture name
SYMBOL: architecture
! Bootstrap global namesapce
SYMBOL: bootstrap-global
! Boot quotation, set in stage1.factor
SYMBOL: bootstrap-boot-quot
! JIT parameters
SYMBOL: jit-code-format
SYMBOL: jit-prolog
2008-01-02 19:36:36 -05:00
SYMBOL: jit-primitive-word
SYMBOL: jit-primitive
2007-09-20 18:09:08 -04:00
SYMBOL: jit-word-jump
SYMBOL: jit-word-call
SYMBOL: jit-push-literal
SYMBOL: jit-if-word
SYMBOL: jit-if-jump
SYMBOL: jit-dispatch-word
SYMBOL: jit-dispatch
SYMBOL: jit-epilog
SYMBOL: jit-return
2008-01-02 19:36:36 -05:00
SYMBOL: jit-profiling
2007-09-20 18:09:08 -04:00
2007-12-26 20:40:46 -05:00
! Default definition for undefined words
SYMBOL: undefined-quot
2007-09-20 18:09:08 -04:00
: userenv-offset ( symbol -- n )
{
{ bootstrap-boot-quot 20 }
{ bootstrap-global 21 }
{ jit-code-format 22 }
2007-12-26 20:40:46 -05:00
{ jit-prolog 23 }
2008-01-02 19:36:36 -05:00
{ jit-primitive-word 24 }
{ jit-primitive 25 }
2007-12-26 20:40:46 -05:00
{ jit-word-jump 26 }
{ jit-word-call 27 }
{ jit-push-literal 28 }
{ jit-if-word 29 }
{ jit-if-jump 30 }
{ jit-dispatch-word 31 }
{ jit-dispatch 32 }
{ jit-epilog 33 }
{ jit-return 34 }
2008-01-02 19:36:36 -05:00
{ jit-profiling 35 }
2007-12-26 20:40:46 -05:00
{ undefined-quot 37 }
2007-09-20 18:09:08 -04:00
} at header-size + ;
: emit ( cell -- ) image get push ;
: emit-64 ( cell -- )
bootstrap-cell 8 = [
emit
] [
d>w/w big-endian get [ swap ] unless emit emit
] if ;
: emit-seq ( seq -- ) image get push-all ;
: fixup ( value offset -- ) image get set-nth ;
: heap-size ( -- size )
image get length header-size - userenv-size -
bootstrap-cells ;
: here ( -- size ) heap-size data-base + ;
2008-03-31 02:19:21 -04:00
: here-as ( tag -- pointer ) here bitor ;
2007-09-20 18:09:08 -04:00
: align-here ( -- )
2008-03-31 02:19:21 -04:00
here 8 mod 4 = [ 0 emit ] when ;
2007-09-20 18:09:08 -04:00
2008-01-02 19:36:36 -05:00
: emit-fixnum ( n -- ) tag-fixnum emit ;
2007-09-20 18:09:08 -04:00
: emit-object ( header tag quot -- addr )
2008-01-02 19:36:36 -05:00
swap here-as >r swap tag-fixnum emit call align-here r> ;
2007-09-20 18:09:08 -04:00
inline
! Write an object to the image.
GENERIC: ' ( obj -- ptr )
! Image header
: emit-header ( -- )
image-magic emit
image-version emit
data-base emit ! relocation base at end of header
0 emit ! size of data heap set later
0 emit ! reloc base of code heap is 0
0 emit ! size of code heap is 0
0 emit ! pointer to t object
0 emit ! pointer to bignum 0
0 emit ! pointer to bignum 1
0 emit ! pointer to bignum -1
userenv-size [ f ' emit ] times ;
: emit-userenv ( symbol -- )
2008-03-31 02:19:21 -04:00
[ get ' ] [ userenv-offset ] bi fixup ;
2007-09-20 18:09:08 -04:00
! Bignums
: bignum-bits bootstrap-cell-bits 2 - ;
: bignum-radix bignum-bits 2^ 1- ;
: bignum>seq ( n -- seq )
#! n is positive or zero.
2007-10-16 04:15:16 -04:00
[ dup 0 > ]
2008-03-31 02:19:21 -04:00
[ [ bignum-bits neg shift ] [ bignum-radix bitand ] bi ]
2007-11-04 17:32:01 -05:00
[ ] unfold nip ;
2007-09-20 18:09:08 -04:00
: emit-bignum ( n -- )
2008-03-31 02:19:21 -04:00
dup dup 0 < [ neg ] when bignum>seq
[ nip length 1+ emit-fixnum ]
[ drop 0 < 1 0 ? emit ]
[ nip emit-seq ]
2tri ;
2007-09-20 18:09:08 -04:00
M: bignum '
[
bignum tag-number dup [ emit-bignum ] emit-object
] cache-object ;
2007-09-20 18:09:08 -04:00
! Fixnums
M: fixnum '
#! When generating a 32-bit image on a 64-bit system,
#! some fixnums should be bignums.
2008-03-12 02:54:29 -04:00
dup
bootstrap-most-negative-fixnum
bootstrap-most-positive-fixnum between?
2008-01-02 19:36:36 -05:00
[ tag-fixnum ] [ >bignum ' ] if ;
2007-09-20 18:09:08 -04:00
! Floats
M: float '
[
float tag-number dup [
align-here double>bits emit-64
] emit-object
] cache-object ;
2007-09-20 18:09:08 -04:00
! Special objects
! Padded with fixnums for 8-byte alignment
: t, t t-offset fixup ;
M: f '
#! f is #define F RETAG(0,F_TYPE)
drop \ f tag-number ;
: 0, 0 >bignum ' 0-offset fixup ;
: 1, 1 >bignum ' 1-offset fixup ;
: -1, -1 >bignum ' -1-offset fixup ;
! Words
: emit-word ( word -- )
[
2008-03-31 02:19:21 -04:00
[ subwords [ emit-word ] each ]
[
[
{
[ hashcode , ]
[ word-name , ]
[ word-vocabulary , ]
[ word-def , ]
[ word-props , ]
} cleave
f ,
0 , ! count
0 , ! xt
0 , ! code
0 , ! profiling
] { } make [ ' ] map
] bi
\ word type-number object tag-number
[ emit-seq ] emit-object
] keep put-object ;
2007-09-20 18:09:08 -04:00
: word-error ( word msg -- * )
[ % dup word-vocabulary % " " % word-name % ] "" make throw ;
: transfer-word ( word -- word )
2008-03-31 02:19:21 -04:00
[ target-word ] keep or ;
2007-09-20 18:09:08 -04:00
: fixup-word ( word -- offset )
transfer-word dup lookup-object
2007-09-20 18:09:08 -04:00
[ ] [ "Not in image: " word-error ] ?if ;
: fixup-words ( -- )
image get [ dup word? [ fixup-word ] when ] change-each ;
M: word ' ;
! Wrappers
M: wrapper '
wrapped ' wrapper type-number object tag-number
[ emit ] emit-object ;
! Strings
2008-04-30 17:11:55 -04:00
: emit-bytes ( seq -- )
2008-02-01 00:00:08 -05:00
bootstrap-cell <groups>
big-endian get [ [ be> ] map ] [ [ le> ] map ] if
2007-09-20 18:09:08 -04:00
emit-seq ;
2008-04-30 17:11:55 -04:00
: pad-bytes ( seq -- newseq )
2008-02-04 15:05:31 -05:00
dup length bootstrap-cell align 0 pad-right ;
2007-09-20 18:09:08 -04:00
: emit-string ( string -- ptr )
string type-number object tag-number [
dup length emit-fixnum
f ' emit
2008-01-31 21:11:46 -05:00
f ' emit
2008-04-30 17:11:55 -04:00
pad-bytes emit-bytes
2007-09-20 18:09:08 -04:00
] emit-object ;
M: string '
#! We pool strings so that each string is only written once
#! to the image
[ emit-string ] cache-object ;
2007-09-20 18:09:08 -04:00
: assert-empty ( seq -- )
length 0 assert= ;
: emit-dummy-array ( obj type -- ptr )
2008-03-31 02:19:21 -04:00
[ assert-empty ] [
type-number object tag-number
[ 0 emit-fixnum ] emit-object
] bi* ;
2007-09-20 18:09:08 -04:00
2008-04-30 17:11:55 -04:00
M: byte-array '
byte-array type-number object tag-number [
dup length emit-fixnum
pad-bytes emit-bytes
] emit-object ;
2007-09-20 18:09:08 -04:00
M: bit-array ' bit-array emit-dummy-array ;
M: float-array ' float-array emit-dummy-array ;
2008-03-26 04:57:48 -04:00
! Tuples
2008-03-31 02:19:21 -04:00
: (emit-tuple) ( tuple -- pointer )
[ tuple>array rest-slice ]
2008-03-31 22:05:06 -04:00
[ class transfer-word tuple-layout ] bi prefix [ ' ] map
2008-03-31 02:19:21 -04:00
tuple type-number dup [ emit-seq ] emit-object ;
2008-03-26 04:57:48 -04:00
: emit-tuple ( tuple -- pointer )
2008-03-31 02:19:21 -04:00
dup class word-name "tombstone" =
[ [ (emit-tuple) ] cache-object ] [ (emit-tuple) ] if ;
2007-09-20 18:09:08 -04:00
M: tuple ' emit-tuple ;
2008-03-26 04:57:48 -04:00
M: tuple-layout '
[
2008-03-26 04:57:48 -04:00
[
2008-03-31 02:19:21 -04:00
{
[ layout-hashcode , ]
[ layout-class , ]
[ layout-size , ]
[ layout-superclasses , ]
[ layout-echelon , ]
} cleave
] { } make [ ' ] map
2008-03-26 04:57:48 -04:00
\ tuple-layout type-number
object tag-number [ emit-seq ] emit-object
] cache-object ;
2008-03-26 04:57:48 -04:00
2007-09-20 18:09:08 -04:00
M: tombstone '
delegate
"((tombstone))" "((empty))" ? "hashtables.private" lookup
word-def first [ emit-tuple ] cache-object ;
2007-09-20 18:09:08 -04:00
2008-03-26 04:57:48 -04:00
! Arrays
2007-09-20 18:09:08 -04:00
M: array '
2008-03-31 02:19:21 -04:00
[ ' ] map array type-number object tag-number
[ [ length emit-fixnum ] [ emit-seq ] bi ] emit-object ;
2007-09-20 18:09:08 -04:00
! Quotations
M: quotation '
[
2007-09-20 18:09:08 -04:00
quotation-array '
quotation type-number object tag-number [
emit ! array
f ' emit ! compiled?
0 emit ! xt
0 emit ! code
2007-09-20 18:09:08 -04:00
] emit-object
] cache-object ;
2007-09-20 18:09:08 -04:00
! End of the image
: emit-words ( -- )
all-words [ emit-word ] each ;
: emit-global ( -- )
[
{
2008-03-24 20:52:21 -04:00
dictionary source-files builtins
2008-05-02 18:36:31 -04:00
update-map class<=-cache
2008-05-02 03:51:38 -04:00
class-not-cache classes-intersect-cache class-and-cache
2008-03-24 20:52:21 -04:00
class-or-cache
2007-12-24 19:40:09 -05:00
} [ dup get swap bootstrap-word set ] each
2007-09-20 18:09:08 -04:00
] H{ } make-assoc
bootstrap-global set
bootstrap-global emit-userenv ;
: emit-boot-quot ( -- )
bootstrap-boot-quot emit-userenv ;
: emit-jit-data ( -- )
\ if jit-if-word set
\ dispatch jit-dispatch-word set
2008-01-02 19:36:36 -05:00
\ do-primitive jit-primitive-word set
2007-12-26 20:40:46 -05:00
[ undefined ] undefined-quot set
2007-09-20 18:09:08 -04:00
{
jit-code-format
jit-prolog
2008-01-02 19:36:36 -05:00
jit-primitive-word
jit-primitive
2007-09-20 18:09:08 -04:00
jit-word-jump
jit-word-call
jit-push-literal
jit-if-word
jit-if-jump
jit-dispatch-word
jit-dispatch
jit-epilog
jit-return
2008-01-02 19:36:36 -05:00
jit-profiling
2007-12-26 20:40:46 -05:00
undefined-quot
2007-09-20 18:09:08 -04:00
} [ emit-userenv ] each ;
: fixup-header ( -- )
heap-size data-heap-size-offset fixup ;
2008-02-10 02:49:27 -05:00
: build-image ( -- image )
800000 <vector> image set
20000 <hashtable> objects set
emit-header t, 0, 1, -1,
2007-09-20 18:09:08 -04:00
"Serializing words..." print flush
emit-words
"Serializing JIT data..." print flush
emit-jit-data
"Serializing global namespace..." print flush
emit-global
"Serializing boot quotation..." print flush
emit-boot-quot
"Performing word fixups..." print flush
fixup-words
"Performing header fixups..." print flush
fixup-header
"Image length: " write image get length .
"Object cache size: " write objects get assoc-size .
2008-02-10 02:49:27 -05:00
\ word global delete-at
image get ;
2007-09-20 18:09:08 -04:00
! Image output
: (write-image) ( image -- )
bootstrap-cell big-endian get [
[ >be write ] curry each
] [
[ >le write ] curry each
] if ;
2008-02-10 02:49:27 -05:00
: write-image ( image -- )
"Writing image to " write
architecture get boot-image-name resource-path
2008-03-31 02:19:21 -04:00
[ write "..." print flush ]
[ binary [ (write-image) ] with-file-writer ] bi ;
2007-09-20 18:09:08 -04:00
PRIVATE>
: make-image ( arch -- )
2008-02-10 02:49:27 -05:00
[
architecture set
2007-09-20 18:09:08 -04:00
"resource:/core/bootstrap/stage1.factor" run-file
2008-02-10 02:49:27 -05:00
build-image
write-image
2008-02-10 02:49:27 -05:00
] with-scope ;
2007-09-20 18:09:08 -04:00
: make-images ( -- )
images [ make-image ] each ;