factor/core/tools/image.factor

384 lines
8.8 KiB
Factor
Raw Normal View History

! Copyright (C) 2004, 2007 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: alien arrays bit-arrays byte-arrays errors generic
assocs hashtables assocs hashtables-internals help io kernel kernel-internals
math namespaces parser prettyprint sequences sequences-internals
strings sbufs vectors words modules quotations assocs ;
2005-12-02 02:25:44 -05:00
IN: image
2006-08-15 04:57:12 -04:00
! Constants
: image-magic HEX: 0f0e0d0c ; inline
: image-version 3 ; inline
: char bootstrap-cell 2/ ; inline
: data-base 1024 ; inline
: boot-quot-offset 3 ; inline
: global-offset 4 ; inline
: t-offset 5 ; inline
: 0-offset 6 ; inline
: 1-offset 7 ; inline
: -1-offset 8 ; inline
: data-heap-size-offset 9 ; inline
: code-heap-size-offset 10 ; inline
: header-size 12 ; inline
2004-11-26 22:23:57 -05:00
! The image being constructed; a vector of word-size integers
SYMBOL: image
2005-08-07 00:00:57 -04:00
! Object cache
SYMBOL: objects
! Image output format
SYMBOL: big-endian
! Bootstrap architecture name
SYMBOL: architecture
2005-08-07 00:00:57 -04:00
! Boot quotation, set in boot-stage1.factor
SYMBOL: boot-quot
2005-04-06 21:41:49 -04:00
: emit ( cell -- ) image get push ;
2004-11-26 22:23:57 -05:00
2005-09-16 22:47:28 -04:00
: emit-64 ( cell -- )
bootstrap-cell 8 = [
2005-09-16 22:47:28 -04:00
emit
] [
d>w/w big-endian get [ swap ] unless emit emit
2005-09-24 15:21:17 -04:00
] if ;
2005-09-16 22:47:28 -04:00
: emit-seq ( seq -- ) image get push-all ;
2005-07-31 23:38:33 -04:00
2005-04-06 21:41:49 -04:00
: fixup ( value offset -- ) image get set-nth ;
2004-07-16 02:26:21 -04:00
: heap-size ( -- size )
image get length header-size - bootstrap-cells ;
: here ( -- size ) heap-size data-base + ;
2004-07-16 02:26:21 -04:00
: here-as ( tag -- pointer ) here swap bitor ;
2004-07-16 02:26:21 -04:00
: align-here ( -- )
here 8 mod 4 = [ 0 emit ] when ;
2004-07-16 02:26:21 -04:00
: emit-fixnum ( n -- ) fixnum tag-number tag-address emit ;
2004-07-16 02:26:21 -04:00
: emit-object ( header tag quot -- addr )
swap here-as >r swap tag-header emit call align-here r> ;
2006-11-12 22:14:04 -05:00
inline
2006-08-15 04:57:12 -04:00
! Image header
2004-07-16 02:26:21 -04:00
: header ( -- )
image-magic emit
image-version emit
data-base emit ! relocation base at end of header
0 emit ! bootstrap quotation set later
0 emit ! global namespace set later
0 emit ! pointer to t object
0 emit ! pointer to bignum 0
0 emit ! pointer to bignum 1
0 emit ! pointer to bignum -1
0 emit ! size of data heap set later
0 emit ! size of code heap is 0
0 emit ; ! reloc base of code heap is 0
2004-07-16 02:26:21 -04:00
GENERIC: ' ( obj -- ptr )
#! Write an object to the image.
2006-08-15 04:57:12 -04:00
! Bignums
2004-08-06 02:51:32 -04:00
: bignum-bits bootstrap-cell-bits 2 - ;
2005-10-08 01:15:14 -04:00
: bignum-radix bignum-bits 2^ 1- ;
2005-10-08 01:15:14 -04:00
: (bignum>seq) ( n -- )
2006-01-28 15:49:31 -05:00
dup zero? [
2005-10-08 01:15:14 -04:00
drop
] [
dup bignum-radix bitand ,
bignum-bits neg shift (bignum>seq)
] if ;
: bignum>seq ( n -- seq )
#! n is positive or zero.
[ (bignum>seq) ] { } make ;
2005-10-08 01:15:14 -04:00
: emit-bignum ( n -- )
[ 0 < 1 0 ? ] keep abs bignum>seq
dup length 1+ emit-fixnum
swap emit emit-seq ;
M: bignum '
bignum tag-number dup [ emit-bignum ] emit-object ;
2004-08-06 02:51:32 -04:00
2006-08-15 04:57:12 -04:00
! Fixnums
2006-05-14 20:05:57 -04:00
M: fixnum '
2006-05-14 20:05:57 -04:00
#! When generating a 32-bit image on a 64-bit system,
#! some fixnums should be bignums.
dup most-negative-fixnum most-positive-fixnum between?
[ fixnum tag-number tag-address ] [ >bignum ' ] if ;
2006-05-14 20:05:57 -04:00
2006-08-15 04:57:12 -04:00
! Floats
2005-09-16 22:47:28 -04:00
M: float '
float tag-number dup [
align-here double>bits emit-64
] emit-object ;
2005-09-16 22:47:28 -04:00
2006-08-15 04:57:12 -04:00
! Special objects
2004-07-16 02:26:21 -04:00
! Padded with fixnums for 8-byte alignment
2005-09-09 17:32:38 -04:00
: t, t t-offset fixup ;
M: f '
#! f is #define F RETAG(0,OBJECT_TYPE)
drop object tag-number ;
2004-07-16 02:26:21 -04:00
2005-05-10 22:30:58 -04:00
: 0, 0 >bignum ' 0-offset fixup ;
: 1, 1 >bignum ' 1-offset fixup ;
: -1, -1 >bignum ' -1-offset fixup ;
2004-08-29 01:04:42 -04:00
2006-08-15 04:57:12 -04:00
! Beginning of the image
2005-01-27 20:06:10 -05:00
! The image begins with the header, then T,
2004-08-29 01:04:42 -04:00
! and the bignums 0, 1, and -1.
2004-07-16 02:26:21 -04:00
: begin-image ( -- ) header t, 0, 1, -1, ;
2004-07-16 02:26:21 -04:00
2006-08-15 04:57:12 -04:00
! Words
2004-07-16 02:26:21 -04:00
2005-07-31 23:38:33 -04:00
: emit-word ( word -- )
[
dup hashcode ' ,
dup word-name ' ,
dup word-vocabulary ' ,
dup word-primitive ' ,
dup word-def ' ,
dup word-props ' ,
f ' ,
0 ,
0 ,
] { } make
\ word tag-number dup [ emit-seq ] emit-object
swap objects get set-at ;
: word-error ( word msg -- * )
2005-09-17 22:25:18 -04:00
[ % dup word-vocabulary % " " % word-name % ] "" make throw ;
: transfer-word ( word -- word )
dup target-word [ ] [ "Missing DEFER: " word-error ] ?if ;
2004-07-16 02:26:21 -04:00
2004-09-30 21:49:49 -04:00
: fixup-word ( word -- offset )
transfer-word dup objects get at
2006-05-28 17:31:54 -04:00
[ ] [ "Not in image: " word-error ] ?if ;
2004-07-16 02:26:21 -04:00
: fixup-words ( -- )
image get [ dup word? [ fixup-word ] when ] change-each ;
2004-07-16 02:26:21 -04:00
M: word ' ;
2006-08-15 04:57:12 -04:00
! Wrappers
M: wrapper '
wrapped ' wrapper tag-number dup [ emit ] emit-object ;
2004-07-16 02:26:21 -04:00
2006-08-15 04:57:12 -04:00
! Ratios and complexes
2005-09-16 22:47:28 -04:00
: emit-pair
[ [ emit ] 2apply ] emit-object ;
M: ratio '
>fraction [ ' ] 2apply ratio tag-number dup emit-pair ;
2005-09-16 22:47:28 -04:00
M: complex '
>rect [ ' ] 2apply complex tag-number dup emit-pair ;
2004-07-16 02:26:21 -04:00
2006-08-15 04:57:12 -04:00
! Strings
2004-07-16 02:26:21 -04:00
: 16be> 0 [ swap 16 shift bitor ] reduce ;
: 16le> <reversed> 16be> ;
2005-07-31 23:38:33 -04:00
: emit-chars ( seq -- )
char <groups>
big-endian get [ [ 16be> ] map ] [ [ 16le> ] map ] if
emit-seq ;
2004-07-16 02:26:21 -04:00
: pack-string ( string -- newstr )
dup length 1+ char align 0 pad-right ;
2004-07-16 02:26:21 -04:00
2005-07-31 23:38:33 -04:00
: emit-string ( string -- ptr )
string type-number object tag-number [
dup length emit-fixnum
f ' emit
pack-string emit-chars
] emit-object ;
2004-07-16 02:26:21 -04:00
M: string '
2004-07-16 02:26:21 -04:00
#! We pool strings so that each string is only written once
#! to the image
2005-08-07 00:00:57 -04:00
objects get [ emit-string ] cache ;
2004-07-16 02:26:21 -04:00
! Byte arrays
: emit-bytes ( seq -- )
cell <groups>
big-endian get [ [ be> ] map ] [ [ le> ] map ] if
emit-seq ;
: pack-bytes ( string -- newstr )
dup length cell align 0 pad-right ;
: emit-byte-array ( string -- ptr )
byte-array type-number object tag-number [
dup length emit-fixnum
pack-bytes emit-bytes
] emit-object ;
M: byte-array '
objects get [ emit-byte-array ] cache ;
! Bit arrays
: emit-bit-array ( string -- ptr )
bit-array type-number object tag-number [
dup length emit-fixnum
empty? [
"Cannot serialize non-empty bit array" throw
] unless
] emit-object ;
M: bit-array '
objects get [ emit-bit-array ] cache ;
2006-08-15 04:57:12 -04:00
! Arrays and vectors
2004-07-16 02:26:21 -04:00
: emit-array ( list type -- pointer )
>r [ ' ] map r> object tag-number [
dup length emit-fixnum
2006-11-12 22:14:04 -05:00
emit-seq
] emit-object ;
2004-07-16 02:26:21 -04:00
2005-11-27 17:45:48 -05:00
: transfer-tuple ( tuple -- tuple )
tuple>array
dup first transfer-word 0 pick set-nth
>tuple ;
2005-11-27 17:45:48 -05:00
M: tuple '
2005-11-27 17:45:48 -05:00
transfer-tuple
objects get [
tuple>array tuple type-number emit-array
] cache ;
2006-11-11 00:43:24 -05:00
M: method '
[
\ method transfer-word ,
f ,
dup method-loc ,
method-def ,
] { } make tuple type-number emit-array ;
M: array '
array type-number emit-array ;
2005-09-11 21:18:19 -04:00
M: quotation '
quotation type-number emit-array ;
2006-05-16 16:50:51 -04:00
M: vector '
2005-11-27 17:45:48 -05:00
dup underlying ' swap length
vector type-number object tag-number [
emit-fixnum ! length
emit ! array ptr
] emit-object ;
2004-07-16 02:26:21 -04:00
M: sbuf '
2006-01-02 00:51:03 -05:00
dup underlying ' swap length
sbuf type-number object tag-number [
emit-fixnum ! length
emit ! array ptr
] emit-object ;
2006-01-02 00:51:03 -05:00
2006-08-15 04:57:12 -04:00
! Hashes
2004-12-27 22:58:43 -05:00
M: hashtable '
[ hash-array ' ] keep
hashtable type-number object tag-number [
dup hash-count emit-fixnum
hash-deleted emit-fixnum
emit ! array ptr
] emit-object ;
2005-01-27 20:06:10 -05:00
2006-08-15 04:57:12 -04:00
! End of the image
2004-07-16 02:26:21 -04:00
2005-07-31 23:38:33 -04:00
: words, ( -- )
all-words [ emit-word ] each ;
2004-07-16 02:26:21 -04:00
: global, ( -- )
[
2005-12-25 22:18:25 -05:00
{
vocabularies typemap builtins crossref
articles help-tree changed-words
2006-09-29 23:03:27 -04:00
modules class<map source-files
2006-05-28 17:31:54 -04:00
} [ dup get swap bootstrap-word set ] each
] H{ } make-assoc '
global-offset fixup ;
2004-11-26 22:23:57 -05:00
: boot, ( -- ) boot-quot get ' boot-quot-offset fixup ;
2004-07-16 02:26:21 -04:00
: end-image ( -- )
"Building generic words..." print flush
all-words [ generic? ] subset [ make-generic ] each
"Serializing words..." print flush
2005-07-31 23:38:33 -04:00
words,
"Serializing global namespace..." print flush
global,
"Serializing boot quotation..." print flush
2004-12-27 22:58:43 -05:00
boot,
2005-12-16 21:12:35 -05:00
"Performing some word fixups..." print flush
2004-09-08 02:31:03 -04:00
fixup-words
heap-size data-heap-size-offset fixup
"Image length: " write image get length .
"Object cache size: " write objects get assoc-size .
\ word global delete-at ;
2004-07-16 02:26:21 -04:00
2006-08-15 04:57:12 -04:00
! Image output
2004-07-16 02:26:21 -04:00
2005-06-10 17:41:41 -04:00
: (write-image) ( image -- )
bootstrap-cell swap big-endian get [
[ swap >be write ] each-with
2004-07-17 18:35:09 -04:00
] [
[ swap >le write ] each-with
2005-09-24 15:21:17 -04:00
] if ;
2004-07-17 18:35:09 -04:00
2005-12-14 20:29:32 -05:00
: image-name
"boot.image." architecture get append resource-path ;
2005-12-14 20:29:32 -05:00
: write-image ( image -- )
2005-12-16 21:12:35 -05:00
"Writing image to " write dup write "..." print flush
2005-06-10 17:41:41 -04:00
<file-writer> [ (write-image) ] with-stream ;
2004-07-16 02:26:21 -04:00
: prepare-profile ( arch -- )
"resource:/core/bootstrap/profile-"
swap ".factor" 3append
2006-09-29 23:03:27 -04:00
run-file ;
2004-07-16 02:26:21 -04:00
: prepare-image ( arch -- )
bootstrapping? on dup architecture set prepare-profile
800000 <vector> image set 20000 <hashtable> objects set ;
2005-12-14 20:29:32 -05:00
: make-image ( architecture -- )
[
parse-hook off
prepare-image
begin-image
"resource:/core/bootstrap/boot-stage1.factor" run-file
end-image
2005-12-14 20:29:32 -05:00
image get image-name write-image
] with-scope ;
: make-images ( -- )
{ "x86" "ppc" "amd64" "arm" } [ make-image ] each ;