123 lines
3.4 KiB
Factor
123 lines
3.4 KiB
Factor
|
! Copyright (C) 2011 Slava Pestov.
|
||
|
! See http://factorcode.org/license.txt for BSD license.
|
||
|
USING: accessors arrays assocs bit-arrays combinators
|
||
|
combinators.short-circuit compiler.cfg.instructions
|
||
|
compiler.codegen.relocation cpu.architecture fry kernel layouts
|
||
|
make math math.order namespaces sequences ;
|
||
|
IN: compiler.codegen.gc-maps
|
||
|
|
||
|
! GC maps
|
||
|
|
||
|
! Every code block either ends with
|
||
|
!
|
||
|
! uint 0
|
||
|
!
|
||
|
! or
|
||
|
!
|
||
|
! bitmap, byte aligned, three subsequences:
|
||
|
! - <scrubbed data stack locations>
|
||
|
! - <scrubbed retain stack locations>
|
||
|
! - <GC root spill slots>
|
||
|
! uint[] <base pointers>
|
||
|
! uint[] <return addresses>
|
||
|
! uint <largest scrubbed data stack location>
|
||
|
! uint <largest scrubbed retain stack location>
|
||
|
! uint <largest GC root spill slot>
|
||
|
! uint <largest derived root spill slot>
|
||
|
! int <number of return addresses>
|
||
|
|
||
|
SYMBOLS: return-addresses gc-maps ;
|
||
|
|
||
|
: gc-map-needed? ( gc-map -- ? )
|
||
|
! If there are no stack locations to scrub and no GC roots,
|
||
|
! there's no point storing the GC map.
|
||
|
dup [
|
||
|
{
|
||
|
[ scrub-d>> empty? ]
|
||
|
[ scrub-r>> empty? ]
|
||
|
[ gc-roots>> empty? ]
|
||
|
[ derived-roots>> empty? ]
|
||
|
} 1&& not
|
||
|
] when ;
|
||
|
|
||
|
: gc-map-here ( gc-map -- )
|
||
|
dup gc-map-needed? [
|
||
|
gc-maps get push
|
||
|
compiled-offset return-addresses get push
|
||
|
] [ drop ] if ;
|
||
|
|
||
|
: longest ( seqs -- n )
|
||
|
[ length ] [ max ] map-reduce ;
|
||
|
|
||
|
: emit-scrub ( seqs -- n )
|
||
|
! seqs is a sequence of sequences of 0/1
|
||
|
dup longest
|
||
|
[ '[ [ 0 = ] ?{ } map-as _ f pad-tail % ] each ] keep ;
|
||
|
|
||
|
: integers>bits ( seq n -- bit-array )
|
||
|
<bit-array> [ '[ [ t ] dip _ set-nth ] each ] keep ;
|
||
|
|
||
|
: largest-spill-slot ( seqs -- n )
|
||
|
[ [ 0 ] [ supremum 1 + ] if-empty ] [ max ] map-reduce ;
|
||
|
|
||
|
: emit-gc-roots ( seqs -- n )
|
||
|
! seqs is a sequence of sequences of integers 0..n-1
|
||
|
dup largest-spill-slot
|
||
|
[ '[ _ integers>bits % ] each ] keep ;
|
||
|
|
||
|
: emit-uint ( n -- )
|
||
|
building get push-uint ;
|
||
|
|
||
|
: emit-uints ( n -- )
|
||
|
[ emit-uint ] each ;
|
||
|
|
||
|
: gc-root-offsets ( gc-map -- offsets )
|
||
|
gc-roots>> [ gc-root-offset ] map ;
|
||
|
|
||
|
: emit-gc-info-bitmaps ( -- scrub-d-count scrub-r-count gc-root-count )
|
||
|
[
|
||
|
gc-maps get {
|
||
|
[ [ scrub-d>> ] map emit-scrub ]
|
||
|
[ [ scrub-r>> ] map emit-scrub ]
|
||
|
[ [ gc-root-offsets ] map emit-gc-roots ]
|
||
|
} cleave
|
||
|
] ?{ } make underlying>> % ;
|
||
|
|
||
|
: emit-base-table ( alist longest -- )
|
||
|
-1 <array> <enum> swap assoc-union! seq>> emit-uints ;
|
||
|
|
||
|
: derived-root-offsets ( gc-map -- offsets )
|
||
|
derived-roots>> [ [ gc-root-offset ] bi@ ] assoc-map ;
|
||
|
|
||
|
: emit-base-tables ( -- count )
|
||
|
gc-maps get [ derived-root-offsets ] map
|
||
|
dup [ keys ] map largest-spill-slot
|
||
|
[ '[ _ emit-base-table ] each ] keep ;
|
||
|
|
||
|
: emit-return-addresses ( -- )
|
||
|
return-addresses get emit-uints ;
|
||
|
|
||
|
: serialize-gc-maps ( -- byte-array )
|
||
|
[
|
||
|
return-addresses get empty? [ 0 emit-uint ] [
|
||
|
emit-gc-info-bitmaps
|
||
|
emit-base-tables
|
||
|
emit-return-addresses
|
||
|
4array emit-uints
|
||
|
return-addresses get length emit-uint
|
||
|
] if
|
||
|
] B{ } make ;
|
||
|
|
||
|
: init-gc-maps ( -- )
|
||
|
V{ } clone return-addresses set
|
||
|
V{ } clone gc-maps set ;
|
||
|
|
||
|
: emit-gc-maps ( -- )
|
||
|
! We want to place the GC maps so that the end is aligned
|
||
|
! on a 16-byte boundary.
|
||
|
serialize-gc-maps [
|
||
|
length compiled-offset +
|
||
|
[ data-alignment get align ] keep -
|
||
|
(align-code)
|
||
|
] [ % ] bi ;
|