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 ;
 |