factor/basis/bootstrap/image/image.factor

620 lines
14 KiB
Factor
Raw Normal View History

! Copyright (C) 2004, 2009 Slava Pestov.
2007-09-20 18:09:08 -04:00
! See http://factorcode.org/license.txt for BSD license.
USING: alien arrays byte-arrays generic assocs hashtables assocs
hashtables.private io io.binary io.files io.encodings.binary
io.pathnames kernel kernel.private math namespaces make parser
prettyprint sequences sequences.private strings sbufs vectors words
quotations assocs system layouts splitting grouping growable classes
2009-04-28 04:48:37 -04:00
classes.builtin classes.tuple classes.tuple.private vocabs
vocabs.loader source-files definitions debugger quotations.private
sequences.private combinators math.order math.private accessors
slots.private generic.single.private compiler.units compiler.constants
fry ;
2007-09-20 18:09:08 -04:00
IN: bootstrap.image
2008-11-07 22:09:42 -05:00
: arch ( os cpu -- arch )
{
{ "ppc" [ "-ppc" append ] }
{ "x86.64" [ "winnt" = "winnt" "unix" ? "-x86.64" append ] }
2008-11-07 22:09:42 -05:00
[ nip ]
} case ;
: my-arch ( -- arch )
2008-11-07 22:09:42 -05:00
os name>> cpu name>> arch ;
: boot-image-name ( arch -- string )
2008-12-06 19:58:45 -05:00
"boot." ".image" surround ;
: my-boot-image-name ( -- string )
my-arch boot-image-name ;
: images ( -- seq )
{
"x86.32"
2008-11-07 21:33:32 -05:00
"winnt-x86.64" "unix-x86.64"
"linux-ppc" "macosx-ppc"
} ;
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) ( obj -- id assoc ) <id> objects get ; inline
: lookup-object ( obj -- n/f ) (objects) at ;
: put-object ( n obj -- ) (objects) set-at ;
: cache-object ( obj quot -- value )
[ (objects) ] dip '[ obj>> @ ] cache ; inline
2007-09-20 18:09:08 -04:00
! Constants
2009-02-22 20:13:08 -05:00
CONSTANT: image-magic HEX: 0f0e0d0c
CONSTANT: image-version 4
2007-09-20 18:09:08 -04:00
2009-02-22 20:13:08 -05:00
CONSTANT: data-base 1024
2007-09-20 18:09:08 -04:00
2009-02-22 20:13:08 -05:00
CONSTANT: userenv-size 70
2007-09-20 18:09:08 -04:00
2009-02-22 20:13:08 -05:00
CONSTANT: header-size 10
2007-09-20 18:09:08 -04:00
2009-02-22 20:13:08 -05:00
CONSTANT: data-heap-size-offset 3
CONSTANT: t-offset 6
CONSTANT: 0-offset 7
CONSTANT: 1-offset 8
CONSTANT: -1-offset 9
2007-09-20 18:09:08 -04:00
SYMBOL: sub-primitives
SYMBOL: jit-define-rc
SYMBOL: jit-define-rt
SYMBOL: jit-define-offset
: compute-offset ( -- offset )
building get length jit-define-rc get rc-absolute-cell = cell 4 ? - ;
: jit-rel ( rc rt -- )
jit-define-rt set
jit-define-rc set
compute-offset jit-define-offset set ;
: make-jit ( quot -- quad )
[
call( -- )
jit-define-rc get
jit-define-rt get
jit-define-offset get 3array
] { } make prefix ;
: jit-define ( quot name -- )
[ make-jit ] dip set ;
: define-sub-primitive ( quot word -- )
2008-11-29 14:40:43 -05:00
[ make-jit ] dip sub-primitives get set-at ;
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
2008-07-12 23:27:28 -04:00
SYMBOL: jit-push-immediate
2007-09-20 18:09:08 -04:00
SYMBOL: jit-if-word
SYMBOL: jit-if-1
SYMBOL: jit-if-2
2007-09-20 18:09:08 -04:00
SYMBOL: jit-dispatch-word
SYMBOL: jit-dispatch
SYMBOL: jit-dip-word
SYMBOL: jit-dip
SYMBOL: jit-2dip-word
SYMBOL: jit-2dip
SYMBOL: jit-3dip-word
SYMBOL: jit-3dip
2009-04-25 22:14:59 -04:00
SYMBOL: jit-execute-word
SYMBOL: jit-execute-jump
SYMBOL: jit-execute-call
2007-09-20 18:09:08 -04:00
SYMBOL: jit-epilog
SYMBOL: jit-return
2008-01-02 19:36:36 -05:00
SYMBOL: jit-profiling
SYMBOL: jit-declare-word
SYMBOL: jit-save-stack
2007-09-20 18:09:08 -04:00
2009-04-28 04:48:37 -04:00
! PIC stubs
SYMBOL: pic-load
2009-04-28 04:48:37 -04:00
SYMBOL: pic-tag
SYMBOL: pic-hi-tag
SYMBOL: pic-tuple
SYMBOL: pic-hi-tag-tuple
SYMBOL: pic-check-tag
2009-04-28 04:48:37 -04:00
SYMBOL: pic-check
SYMBOL: pic-hit
SYMBOL: pic-miss-word
2007-12-26 20:40:46 -05:00
! Default definition for undefined words
SYMBOL: undefined-quot
: userenvs ( -- assoc )
H{
2007-09-20 18:09:08 -04:00
{ 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-if-word 28 }
{ jit-if-1 29 }
{ jit-if-2 30 }
2007-12-26 20:40:46 -05:00
{ jit-dispatch-word 31 }
{ jit-dispatch 32 }
{ jit-epilog 33 }
{ jit-return 34 }
2008-01-02 19:36:36 -05:00
{ jit-profiling 35 }
2008-07-12 23:27:28 -04:00
{ jit-push-immediate 36 }
2009-04-28 04:48:37 -04:00
{ jit-declare-word 37 }
{ jit-save-stack 38 }
{ jit-dip-word 39 }
{ jit-dip 40 }
{ jit-2dip-word 41 }
{ jit-2dip 42 }
{ jit-3dip-word 43 }
{ jit-3dip 44 }
{ jit-execute-word 45 }
{ jit-execute-jump 46 }
{ jit-execute-call 47 }
{ pic-load 48 }
{ pic-tag 49 }
{ pic-hi-tag 50 }
{ pic-tuple 51 }
{ pic-hi-tag-tuple 52 }
{ pic-check-tag 53 }
{ pic-check 54 }
{ pic-hit 55 }
{ pic-miss-word 56 }
{ undefined-quot 60 }
} ; inline
: userenv-offset ( symbol -- n )
userenvs at header-size + ;
2007-09-20 18:09:08 -04:00
: 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 ( class quot -- addr )
over tag-number here-as [ swap type-number tag-fixnum emit call align-here ] dip ;
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
2008-06-08 16:32:55 -04:00
: bignum-bits ( -- n ) bootstrap-cell-bits 2 - ;
2007-09-20 18:09:08 -04:00
2008-06-08 16:32:55 -04:00
: bignum-radix ( -- n ) bignum-bits 2^ 1- ;
2007-09-20 18:09:08 -04:00
: 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 ]
produce 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 [ 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
2008-07-05 22:00:05 -04:00
TUPLE: fake-bignum n ;
C: <fake-bignum> fake-bignum
M: fake-bignum ' n>> tag-fixnum ;
2007-09-20 18:09:08 -04:00
! Floats
M: float '
[
float [
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
2008-06-08 16:32:55 -04:00
: t, ( -- ) t t-offset fixup ;
2007-09-20 18:09:08 -04:00
M: f '
#! f is #define F RETAG(0,F_TYPE)
drop \ f tag-number ;
2008-06-08 16:32:55 -04:00
: 0, ( -- ) 0 >bignum ' 0-offset fixup ;
: 1, ( -- ) 1 >bignum ' 1-offset fixup ;
: -1, ( -- ) -1 >bignum ' -1-offset fixup ;
2007-09-20 18:09:08 -04:00
! Words
: word-sub-primitive ( word -- obj )
global [ target-word ] bind sub-primitives get at ;
2007-09-20 18:09:08 -04:00
: emit-word ( word -- )
[
2008-03-31 02:19:21 -04:00
[ subwords [ emit-word ] each ]
[
[
{
[ hashcode <fake-bignum> , ]
[ name>> , ]
[ vocabulary>> , ]
[ def>> , ]
[ props>> , ]
2009-04-29 00:05:18 -04:00
[ direct-entry-def>> , ] ! direct-entry-def
[ drop 0 , ] ! count
[ word-sub-primitive , ]
[ drop 0 , ] ! xt
[ drop 0 , ] ! code
[ drop 0 , ] ! profiling
2008-03-31 02:19:21 -04:00
} cleave
] { } make [ ' ] map
] bi
\ word [ emit-seq ] emit-object
] keep put-object ;
2007-09-20 18:09:08 -04:00
: word-error ( word msg -- * )
[ % dup vocabulary>> % " " % name>> % ] "" make throw ;
2007-09-20 18:09:08 -04:00
: 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 [ emit ] emit-object ;
2007-09-20 18:09:08 -04:00
! Strings
: native> ( object -- object )
big-endian get [ [ be> ] map ] [ [ le> ] map ] if ;
2008-04-30 17:11:55 -04:00
: emit-bytes ( seq -- )
bootstrap-cell <groups> native> emit-seq ;
2007-09-20 18:09:08 -04:00
2008-04-30 17:11:55 -04:00
: pad-bytes ( seq -- newseq )
dup length bootstrap-cell align 0 pad-tail ;
2007-09-20 18:09:08 -04:00
: extended-part ( str -- str' )
dup [ 128 < ] all? [ drop f ] [
[ -7 shift 1 bitxor ] { } map-as
big-endian get
[ [ 2 >be ] { } map-as ]
[ [ 2 >le ] { } map-as ] if
B{ } join
] if ;
: ascii-part ( str -- str' )
[
[ 128 mod ] [ 128 >= ] bi
[ 128 bitor ] when
] B{ } map-as ;
2007-09-20 18:09:08 -04:00
: emit-string ( string -- ptr )
[ length ] [ extended-part ' ] [ ] tri
string [
[ emit-fixnum ]
[ emit ]
[ f ' emit ascii-part pad-bytes emit-bytes ]
tri*
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 ] [
[ 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 [
2008-04-30 17:11:55 -04:00
dup length emit-fixnum
pad-bytes emit-bytes
] emit-object ;
2007-09-20 18:09:08 -04:00
2008-03-26 04:57:48 -04:00
! Tuples
ERROR: tuple-removed class ;
: require-tuple-layout ( word -- layout )
dup tuple-layout [ ] [ tuple-removed ] ?if ;
2008-03-31 02:19:21 -04:00
: (emit-tuple) ( tuple -- pointer )
2008-09-03 00:21:08 -04:00
[ tuple-slots ]
[ class transfer-word require-tuple-layout ] bi prefix [ ' ] map
tuple [ emit-seq ] emit-object ;
2008-03-31 02:19:21 -04:00
2008-03-26 04:57:48 -04:00
: emit-tuple ( tuple -- pointer )
dup class name>> "tombstone" =
[ [ (emit-tuple) ] cache-object ] [ (emit-tuple) ] if ;
2007-09-20 18:09:08 -04:00
M: tuple ' emit-tuple ;
M: tombstone '
2008-09-03 00:21:08 -04:00
state>> "((tombstone))" "((empty))" ?
"hashtables.private" lookup def>> first
[ emit-tuple ] cache-object ;
2007-09-20 18:09:08 -04:00
2008-03-26 04:57:48 -04:00
! Arrays
2008-11-06 02:58:07 -05:00
: emit-array ( array -- offset )
[ ' ] map array [ [ length emit-fixnum ] [ emit-seq ] bi ] emit-object ;
2007-09-20 18:09:08 -04:00
2008-11-06 02:58:07 -05:00
M: array ' emit-array ;
! This is a hack. We need to detect arrays which are tuple
! layout arrays so that they can be internalized, but making
! them a built-in type is not worth it.
PREDICATE: tuple-layout-array < array
dup length 5 >= [
[ first tuple-class? ]
[ second fixnum? ]
[ third fixnum? ]
tri and and
] [ drop f ] if ;
2008-11-06 02:58:07 -05:00
M: tuple-layout-array '
[
[ dup integer? [ <fake-bignum> ] when ] map
emit-array
] cache-object ;
2007-09-20 18:09:08 -04:00
! Quotations
M: quotation '
[
array>> '
quotation [
2007-09-20 18:09:08 -04:00
emit ! array
2009-01-23 19:20:47 -05:00
f ' emit ! compiled
2009-03-16 21:11:36 -04:00
f ' emit ! cached-effect
f ' emit ! cache-counter
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-09-18 00:28:54 -04:00
{
dictionary source-files builtins
update-map implementors-map
} [ [ bootstrap-word ] [ get ] bi ] H{ } map>assoc
{
class<=-cache class-not-cache classes-intersect-cache
2008-10-01 09:20:49 -04:00
class-and-cache class-or-cache next-method-quot-cache
2008-09-18 00:28:54 -04:00
} [ H{ } clone ] H{ } map>assoc assoc-union
2007-09-20 18:09:08 -04:00
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
\ declare jit-declare-word set
\ dip jit-dip-word set
\ 2dip jit-2dip-word set
\ 3dip jit-3dip-word set
2009-04-25 22:14:59 -04:00
\ (execute) jit-execute-word set
2009-04-28 04:48:37 -04:00
\ inline-cache-miss \ pic-miss-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
2008-07-12 23:27:28 -04:00
jit-push-immediate
2007-09-20 18:09:08 -04:00
jit-if-word
jit-if-1
jit-if-2
2007-09-20 18:09:08 -04:00
jit-dispatch-word
jit-dispatch
jit-dip-word
jit-dip
jit-2dip-word
jit-2dip
jit-3dip-word
jit-3dip
2009-04-25 22:14:59 -04:00
jit-execute-word
jit-execute-jump
jit-execute-call
2007-09-20 18:09:08 -04:00
jit-epilog
jit-return
2008-01-02 19:36:36 -05:00
jit-profiling
jit-declare-word
jit-save-stack
pic-load
2009-04-28 04:48:37 -04:00
pic-tag
pic-hi-tag
pic-tuple
pic-hi-tag-tuple
pic-check-tag
2009-04-28 04:48:37 -04:00
pic-check
pic-hit
pic-miss-word
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,
"Building generic words..." print flush
remake-generics
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 ] each ]
[ '[ _ >le write ] each ] if ;
2007-09-20 18:09:08 -04:00
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 ;