factor/basis/compiler/cfg/gc-checks/gc-checks.factor

123 lines
3.1 KiB
Factor
Raw Normal View History

2010-04-27 10:51:00 -04:00
! Copyright (C) 2009, 2010 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
2010-04-27 10:51:00 -04:00
USING: accessors assocs combinators fry kernel layouts locals
math make namespaces sequences cpu.architecture
compiler.cfg
compiler.cfg.rpo
2010-04-27 10:51:00 -04:00
compiler.cfg.hats
compiler.cfg.registers
2010-04-27 10:51:00 -04:00
compiler.cfg.utilities
compiler.cfg.comparisons
compiler.cfg.instructions
2010-04-27 10:51:00 -04:00
compiler.cfg.predecessors
compiler.cfg.liveness
compiler.cfg.liveness.ssa
compiler.cfg.stacks.uninitialized ;
IN: compiler.cfg.gc-checks
2010-04-27 10:51:00 -04:00
<PRIVATE
! Garbage collection check insertion. This pass runs after
! representation selection, since it needs to know which vregs
! can contain tagged pointers.
: insert-gc-check? ( bb -- ? )
instructions>> [ ##allocation? ] any? ;
: blocks-with-gc ( cfg -- bbs )
post-order [ insert-gc-check? ] filter ;
2010-04-27 10:51:00 -04:00
! A GC check for bb consists of two new basic blocks, gc-check
! and gc-call:
!
! gc-check
! / \
! | gc-call
! \ /
! bb
! Any ##phi instructions at the start of bb are transplanted
! into the gc-check block.
: <gc-check> ( phis size -- bb )
[ <basic-block> ] 2dip
2010-04-27 10:51:00 -04:00
[
[ % ]
[
cc<= int-rep next-vreg-rep int-rep next-vreg-rep
##check-nursery-branch
] bi*
2010-04-27 10:51:00 -04:00
] V{ } make >>instructions ;
: wipe-locs ( uninitialized-locs -- )
'[
int-rep next-vreg-rep
[ 0 ##load-tagged ]
[ '[ [ _ ] dip ##replace ] each ] bi
] unless-empty ;
: <gc-call> ( uninitialized-locs gc-roots -- bb )
[ <basic-block> ] 2dip
[ [ wipe-locs ] [ ##call-gc ] bi* ##branch ] V{ } make
>>instructions t >>unlikely? ;
:: insert-guard ( body check bb -- )
bb predecessors>> check predecessors<<
V{ bb body } check successors<<
2010-04-27 10:51:00 -04:00
V{ check } body predecessors<<
V{ bb } body successors<<
2010-04-27 10:51:00 -04:00
V{ check body } bb predecessors<<
2010-04-27 10:51:00 -04:00
check predecessors>> [ bb check update-successors ] each ;
: (insert-gc-check) ( uninitialized-locs gc-roots phis size bb -- )
[ [ <gc-call> ] 2dip <gc-check> ] dip insert-guard ;
2010-04-27 10:51:00 -04:00
GENERIC: allocation-size* ( insn -- n )
M: ##allot allocation-size* size>> ;
M: ##box-alien allocation-size* drop 5 cells ;
M: ##box-displaced-alien allocation-size* drop 5 cells ;
: allocation-size ( bb -- n )
instructions>>
[ ##allocation? ] filter
2009-11-02 18:41:36 -05:00
[ allocation-size* data-alignment get align ] map-sum ;
: gc-live-in ( bb -- vregs )
[ live-in keys ] [ instructions>> [ ##phi? ] filter [ dst>> ] map ] bi
append ;
2010-04-27 10:51:00 -04:00
: live-tagged ( bb -- vregs )
gc-live-in [ rep-of tagged-rep? ] filter ;
: remove-phis ( bb -- phis )
[ [ ##phi? ] partition ] change-instructions drop ;
2010-04-27 10:51:00 -04:00
: insert-gc-check ( bb -- )
2010-04-27 10:51:00 -04:00
{
[ uninitialized-locs ]
[ live-tagged ]
[ remove-phis ]
[ allocation-size ]
2010-04-27 10:51:00 -04:00
[ ]
} cleave
(insert-gc-check) ;
PRIVATE>
: insert-gc-checks ( cfg -- cfg' )
dup blocks-with-gc [
2010-04-27 10:51:00 -04:00
[
needs-predecessors
dup compute-ssa-live-sets
dup compute-uninitialized-sets
] dip
[ insert-gc-check ] each
2010-04-27 10:51:00 -04:00
cfg-changed
2009-10-29 15:34:04 -04:00
] unless-empty ;