factor/basis/bootstrap/image/image.factor

603 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: accessors arrays assocs bootstrap.image.syntax
byte-arrays classes classes.builtin classes.private
classes.tuple classes.tuple.private combinators
combinators.short-circuit combinators.smart
compiler.codegen.relocation compiler.units fry generic
2015-07-16 14:09:17 -04:00
generic.single.private grouping hashtables hashtables.private io
io.binary io.encodings.binary io.files io.pathnames kernel
kernel.private layouts locals make math math.order namespaces
namespaces.private parser parser.notes prettyprint quotations
sequences sequences.private source-files strings system vectors
vocabs words ;
2007-09-20 18:09:08 -04:00
IN: bootstrap.image
: arch-name ( os cpu -- arch )
2dup [ windows? ] [ ppc? ] bi* or [
2011-05-20 18:11:50 -04:00
[ drop unix ] dip
] unless
2015-07-16 14:09:17 -04:00
[ name>> ] bi@ "-" glue ;
2008-11-07 22:09:42 -05:00
: my-arch-name ( -- arch )
os cpu arch-name ;
: boot-image-name ( arch -- string )
2008-12-06 19:58:45 -05:00
"boot." ".image" surround ;
: my-boot-image-name ( -- string )
my-arch-name boot-image-name ;
CONSTANT: image-names
{
"windows-x86.32" "unix-x86.32"
"windows-x86.64" "unix-x86.64"
2015-07-16 14:09:17 -04:00
}
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
M: bignum (eql?) { bignum bignum } declare = ;
2009-10-30 21:53:18 -04:00
M: float (eql?) fp-bitwise= ;
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: bootstrapping-image
2007-09-20 18:09:08 -04:00
! Image output format
SYMBOL: big-endian
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 -- ) bootstrapping-image get push ;
2007-09-20 18:09:08 -04:00
: emit-64 ( cell -- )
bootstrap-cell 8 = [
emit
] [
d>w/w big-endian get [ swap ] unless emit emit
] if ;
: emit-seq ( seq -- ) bootstrapping-image get push-all ;
2007-09-20 18:09:08 -04:00
: fixup ( value offset -- ) bootstrapping-image get set-nth ;
2007-09-20 18:09:08 -04:00
: heap-size ( -- size )
bootstrapping-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
[ swap emit-header call align-here ] dip ; inline
2007-09-20 18:09:08 -04:00
! 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
] output>array [ ' ] map!
2008-03-31 02:19:21 -04:00
] bi
\ word [ emit-seq ] emit-object
] keep put-object ;
2007-09-20 18:09:08 -04:00
2013-03-29 12:35:13 -04:00
ERROR: not-in-image vocabulary word ;
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
2015-08-13 06:20:39 -04:00
[ ] [ [ vocabulary>> ] [ name>> ] bi throw-not-in-image ] ?if ;
2007-09-20 18:09:08 -04:00
: fixup-words ( -- )
bootstrapping-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 )
2015-08-13 06:20:39 -04:00
dup tuple-layout [ ] [ throw-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-unsafe tuple-class? ]
[ second-unsafe fixnum? ]
[ third-unsafe fixnum? ]
} 1&&
] [ 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 )
600,000 <vector> bootstrapping-image set
60,000 <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 bootstrapping-image get length .
2007-09-20 18:09:08 -04:00
"Object cache size: " write objects get assoc-size .
\ last-word global delete-at
bootstrapping-image get ;
2007-09-20 18:09:08 -04:00
! Image output
: (write-image) ( image -- )
bootstrap-cell output-stream get
big-endian get
[ '[ _ >be _ stream-write ] each ]
[ '[ _ >le _ stream-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 ( -- )
image-names [ make-image ] each ;
: make-my-image ( -- )
my-arch-name make-image ;