factor/basis/bootstrap/image/image.factor

602 lines
15 KiB
Factor
Raw Normal View History

! Copyright (C) 2004, 2011 Slava Pestov.
2007-09-20 18:09:08 -04:00
! See http://factorcode.org/license.txt for BSD license.
USING: alien alien.strings arrays byte-arrays generic hashtables
2009-10-30 21:53:18 -04:00
hashtables.private io io.binary io.files io.encodings.binary
io.pathnames kernel kernel.private math namespaces make parser
prettyprint sequences combinators.smart strings sbufs vectors
words quotations assocs system layouts splitting grouping
growable classes classes.private classes.builtin classes.tuple
classes.tuple.private vocabs vocabs.loader source-files
definitions debugger quotations.private combinators
combinators.short-circuit math.order math.private accessors
slots.private generic.single.private compiler.units
compiler.constants compiler.codegen.relocation fry locals
bootstrap.image.syntax parser.notes namespaces.private ;
2007-09-20 18:09:08 -04:00
IN: bootstrap.image
2008-11-07 22:09:42 -05:00
: arch ( os cpu -- arch )
2dup [ windows? ] [ ppc? ] bi* or [
2011-05-20 18:11:50 -04:00
[ drop unix ] dip
] unless
[ name>> ] [ name>> ] bi* "-" glue ;
2008-11-07 22:09:42 -05:00
: my-arch ( -- arch )
2011-05-20 18:11:50 -04:00
os cpu 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 )
{
"windows-x86.32" "unix-x86.32"
"windows-x86.64" "unix-x86.64"
} ;
2007-09-20 18:09:08 -04:00
<PRIVATE
! Object cache; we only consider numbers equal if they have the
! same type
2009-10-30 21:53:18 -04:00
TUPLE: eql-wrapper { obj read-only } ;
C: <eql-wrapper> eql-wrapper
M: eql-wrapper hashcode* obj>> hashcode* ;
2008-04-29 02:49:06 -04:00
GENERIC: (eql?) ( obj1 obj2 -- ? )
: eql? ( obj1 obj2 -- ? )
2012-07-21 13:22:44 -04:00
{ [ [ class-of ] same? ] [ (eql?) ] } 2&& ;
2008-04-29 02:49:06 -04:00
2009-10-30 21:53:18 -04:00
M: fixnum (eql?) eq? ;
2008-04-29 02:49:06 -04:00
2009-10-30 21:53:18 -04:00
M: bignum (eql?) = ;
2009-10-30 21:53:18 -04:00
M: float (eql?) fp-bitwise= ;
2012-07-21 13:22:44 -04:00
M: sequence (eql?) 2dup [ length ] same? [ [ eql? ] 2all? ] [ 2drop f ] if ;
2008-04-29 02:49:06 -04:00
M: object (eql?) = ;
M: eql-wrapper equal?
over eql-wrapper? [ [ obj>> ] bi@ eql? ] [ 2drop f ] if ;
2009-10-30 21:53:18 -04:00
TUPLE: eq-wrapper { obj read-only } ;
C: <eq-wrapper> eq-wrapper
M: eq-wrapper equal?
over eq-wrapper? [ [ obj>> ] bi@ eq? ] [ 2drop f ] if ;
2009-11-10 22:06:36 -05:00
M: eq-wrapper hashcode*
nip obj>> identity-hashcode ;
SYMBOL: objects
: cache-eql-object ( obj quot -- value )
[ <eql-wrapper> objects get ] dip '[ obj>> @ ] cache ; inline
: cache-eq-object ( obj quot -- value )
[ <eq-wrapper> objects get ] dip '[ obj>> @ ] cache ; inline
: lookup-object ( obj -- n/f ) <eq-wrapper> objects get at ;
: put-object ( n obj -- ) <eq-wrapper> objects get set-at ;
2007-09-20 18:09:08 -04:00
! Constants
2011-11-23 21:49:33 -05:00
CONSTANT: image-magic 0x0f0e0d0c
2009-02-22 20:13:08 -05:00
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
CONSTANT: special-objects-size 80
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
:: jit-conditional ( test-quot false-quot -- )
[ 0 test-quot call ] B{ } make length :> len
building get length extra-offset get + len +
[ extra-offset set false-quot call ] B{ } make
[ length test-quot call ] [ % ] bi ; inline
: make-jit ( quot -- parameters literals code )
#! code is a { relocation insns } pair
[
0 extra-offset set
init-relocation
call( -- )
parameter-table get >array
literal-table get >array
relocation-table get >byte-array
] B{ } make 2array ;
: make-jit-no-params ( quot -- code )
make-jit 2nip ;
: jit-define ( quot name -- )
[ make-jit-no-params ] dip set ;
: define-sub-primitive ( quot word -- )
[ make-jit 3array ] dip sub-primitives get set-at ;
: define-combinator-primitive ( quot non-tail-quot tail-quot word -- )
[
[
[ make-jit ]
[ make-jit-no-params ]
[ make-jit-no-params ]
tri*
] output>array
] 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
RESET
2007-09-20 18:09:08 -04:00
! Boot quotation, set in stage1.factor
SPECIAL-OBJECT: bootstrap-startup-quot 20
! Bootstrap global namesapce
SPECIAL-OBJECT: bootstrap-global 21
2007-09-20 18:09:08 -04:00
! JIT parameters
SPECIAL-OBJECT: jit-prolog 23
SPECIAL-OBJECT: jit-primitive-word 24
SPECIAL-OBJECT: jit-primitive 25
SPECIAL-OBJECT: jit-word-jump 26
SPECIAL-OBJECT: jit-word-call 27
SPECIAL-OBJECT: jit-if-word 28
SPECIAL-OBJECT: jit-if 29
SPECIAL-OBJECT: jit-safepoint 30
SPECIAL-OBJECT: jit-epilog 31
SPECIAL-OBJECT: jit-return 32
SPECIAL-OBJECT: jit-profiling 33
SPECIAL-OBJECT: jit-push 34
SPECIAL-OBJECT: jit-dip-word 35
SPECIAL-OBJECT: jit-dip 36
SPECIAL-OBJECT: jit-2dip-word 37
SPECIAL-OBJECT: jit-2dip 38
SPECIAL-OBJECT: jit-3dip-word 39
SPECIAL-OBJECT: jit-3dip 40
SPECIAL-OBJECT: jit-execute 41
SPECIAL-OBJECT: jit-declare-word 42
SPECIAL-OBJECT: c-to-factor-word 43
SPECIAL-OBJECT: lazy-jit-compile-word 44
SPECIAL-OBJECT: unwind-native-frames-word 45
SPECIAL-OBJECT: fpu-state-word 46
SPECIAL-OBJECT: set-fpu-state-word 47
SPECIAL-OBJECT: signal-handler-word 48
SPECIAL-OBJECT: leaf-signal-handler-word 49
SPECIAL-OBJECT: ffi-signal-handler-word 50
SPECIAL-OBJECT: ffi-leaf-signal-handler-word 51
SPECIAL-OBJECT: callback-stub 53
2009-04-28 04:48:37 -04:00
! PIC stubs
SPECIAL-OBJECT: pic-load 54
SPECIAL-OBJECT: pic-tag 55
SPECIAL-OBJECT: pic-tuple 56
SPECIAL-OBJECT: pic-check-tag 57
SPECIAL-OBJECT: pic-check-tuple 58
SPECIAL-OBJECT: pic-hit 59
SPECIAL-OBJECT: pic-miss-word 60
SPECIAL-OBJECT: pic-miss-tail-word 61
2009-04-28 04:48:37 -04:00
! Megamorphic dispatch
SPECIAL-OBJECT: mega-lookup 62
SPECIAL-OBJECT: mega-lookup-word 63
SPECIAL-OBJECT: mega-miss-word 64
2007-12-26 20:40:46 -05:00
! Default definition for undefined words
SPECIAL-OBJECT: undefined-quot 65
: special-object-offset ( symbol -- n )
special-objects get 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 - special-objects-size -
2007-09-20 18:09:08 -04:00
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
2009-10-20 13:45:00 -04:00
: (align-here) ( alignment -- )
[ here neg ] dip rem
[ bootstrap-cell /i [ 0 emit ] times ] unless-zero ;
2007-09-20 18:09:08 -04:00
: align-here ( -- )
2009-10-20 13:45:00 -04:00
data-alignment get (align-here) ;
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
2009-11-10 22:06:36 -05:00
: emit-header ( n -- ) tag-header emit ;
: emit-object ( class quot -- addr )
[ type-number ] dip over here-as
2009-11-10 22:06:36 -05:00
[ swap emit-header call align-here ] dip ;
2007-09-20 18:09:08 -04:00
inline
! Write an object to the image.
GENERIC: ' ( obj -- ptr )
! Image header
2009-11-10 22:06:36 -05:00
: emit-image-header ( -- )
2007-09-20 18:09:08 -04:00
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
special-objects-size [ f ' emit ] times ;
2007-09-20 18:09:08 -04:00
: emit-special-object ( symbol -- )
[ get ' ] [ special-object-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
: bignum-radix ( -- n ) bignum-bits 2^ 1 - ;
2007-09-20 18:09:08 -04:00
: bignum>sequence ( n -- seq )
2007-09-20 18:09:08 -04:00
#! 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 -- )
dup dup 0 < [ neg ] when bignum>sequence
[ nip length 1 + emit-fixnum ]
2008-03-31 02:19:21 -04:00
[ 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-eql-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 [
2009-10-20 13:45:00 -04:00
8 (align-here) double>bits emit-64
] emit-object
] cache-eql-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 ' drop \ f type-number ;
2007-09-20 18:09:08 -04:00
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 )
[ target-word ] with-global 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>> , ]
[ pic-def>> , ]
[ pic-tail-def>> , ]
[ word-sub-primitive , ]
[ drop 0 , ] ! entry point
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 ] map! drop ;
2007-09-20 18:09:08 -04:00
M: word ' ;
! Wrappers
M: wrapper '
[ wrapped>> ' wrapper [ emit ] emit-object ] cache-eql-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-eql-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 [
dup length emit-fixnum
2009-10-20 13:45:00 -04:00
bootstrap-cell 4 = [ 0 emit 0 emit ] when
pad-bytes emit-bytes
] emit-object
] cache-eq-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 ]
2011-10-24 07:47:42 -04:00
[ class-of 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 )
2011-10-24 07:47:42 -04:00
dup class-of name>> "tombstone" =
[ [ (emit-tuple) ] cache-eql-object ]
[ [ (emit-tuple) ] cache-eq-object ]
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))" ?
2011-11-06 18:57:24 -05:00
"hashtables.private" lookup-word def>> first
[ emit-tuple ] cache-eql-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
M: array ' [ emit-array ] cache-eq-object ;
2008-11-06 02:58:07 -05:00
! 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-eql-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-03-16 21:11:36 -04:00
f ' emit ! cached-effect
f ' emit ! cache-counter
0 emit ! entry point
2007-09-20 18:09:08 -04:00
] emit-object
] cache-eql-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 global-box boa ] bi ] H{ } map>assoc
2008-09-18 00:28:54 -04:00
{
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
} [ H{ } clone global-box boa ] H{ } map>assoc assoc-union
global-hashtable boa
bootstrap-global set ;
2007-09-20 18:09:08 -04:00
: emit-jit-data ( -- )
\ if jit-if-word set
2008-01-02 19:36:36 -05:00
\ do-primitive jit-primitive-word set
\ dip jit-dip-word set
\ 2dip jit-2dip-word set
\ 3dip jit-3dip-word set
\ inline-cache-miss pic-miss-word set
\ inline-cache-miss-tail pic-miss-tail-word set
\ mega-cache-lookup mega-lookup-word set
\ mega-cache-miss mega-miss-word set
\ declare jit-declare-word set
\ c-to-factor c-to-factor-word set
\ lazy-jit-compile lazy-jit-compile-word set
\ unwind-native-frames unwind-native-frames-word set
\ fpu-state fpu-state-word set
\ set-fpu-state set-fpu-state-word set
\ signal-handler signal-handler-word set
\ leaf-signal-handler leaf-signal-handler-word set
\ ffi-signal-handler ffi-signal-handler-word set
\ ffi-leaf-signal-handler ffi-leaf-signal-handler-word set
undefined-def undefined-quot set ;
: emit-special-objects ( -- )
special-objects get keys [ emit-special-object ] each ;
2007-09-20 18:09:08 -04:00
: fixup-header ( -- )
heap-size data-heap-size-offset fixup ;
2010-01-27 23:30:35 -05:00
: build-generics ( -- )
[
all-words
[ generic? ] filter
[ make-generic ] each
] with-compilation-unit ;
2008-02-10 02:49:27 -05:00
: build-image ( -- image )
800000 <vector> image set
20000 <hashtable> objects set
2009-11-10 22:06:36 -05:00
emit-image-header t, 0, 1, -1,
"Building generic words..." print flush
2010-01-27 23:30:35 -05:00
build-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 special object table..." print flush
emit-special-objects
2007-09-20 18:09:08 -04:00
"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 -- )
2012-07-19 14:24:45 -04:00
architecture associate H{
{ parser-quiet? f }
{ auto-use? f }
} assoc-union! [
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
2012-07-19 14:24:45 -04:00
] with-variables ;
2007-09-20 18:09:08 -04:00
: make-images ( -- )
images [ make-image ] each ;
: make-my-image ( -- )
my-arch make-image ;