Last active
November 13, 2017 10:02
-
-
Save alexbiehl/65eb4e73dd3fa3c0945d9997ff75963b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
data FvLoad = FvOff !ByteOff | |
| FvInd (NonVoid Id) !DynTag !ByteOff | |
-- | The free variable info of the outer closure | |
data FreeVarInfo = MkFreeVarInfo { | |
fvInfoBndr :: NonVoid Id | |
-- ^ the outer closures binder | |
, fvInfoBndrTag :: !DynTag | |
-- ^ the tag to access free variables from | |
-- the outer closure | |
, fvInfoFvs :: IdSet | |
-- ^ the set of all free variable names of | |
-- the outer closure. Using a non-deterministic | |
-- set is ok here, as it is only used to test | |
-- memberships | |
, fvInfoLoadFvs :: [(NonVoid Id, FvLoad)] | |
-- ^ the effective free variables of the | |
-- outer closure | |
} | |
commonUpFreeVars :: [NonVoid Id] -- ^ free variables of this closure | |
-> FreeVarInfo -- ^ free variable info of the outer closure | |
-> ( [NonVoid Id] -- ^ effective free variables of this closure | |
, [(NonVoid Id, FvLoad)] -- ^ free variables shared with outer closure | |
) | |
commonUpFreeVars fvs outer_fvs | |
-- we only share free variables if this closure | |
-- has all the free variables of the outer closure | |
| is_subset (fvInfoAllFvs outer_fvs) fvs | |
= let | |
(ind_fvs, non_ind_fvs) = | |
partition ind_load (fvInfoLoadFvs outer_fvs) | |
-- include the reference to the outer closure | |
-- only if we benefit from having the indirection | |
reference_outer_closure = | |
lengthAtLeast non_ind_fvs 3 | |
effective_fvs = | |
concat [ if reference_outer_closure | |
then [ fvInfoBndr outer_fvs ] | |
else map fst non_ind_fvs | |
-- either includes the outer closure or the | |
-- free variables of the outer closure | |
, if reference_outer_closure | |
then [ ind | (_, FvInd ind _ _) <- ind_fvs ] | |
else [] | |
-- if we inclue the reference to the outer closure | |
-- also pass down its indirect free variables so | |
-- we don't need to dereference these twice | |
, [ nvid | nvid@(NonVoid id) <- fvs, | |
not (elemVarSet id (fvInfoAllFvs outer_fvs))] | |
-- also include the free variables not mentioned | |
-- by the outer closure | |
] | |
ind_loads = | |
[ (nvid, FvInd (fvInfoBndr outer_fvs) (fvInfoBndrTag outer_fvs) off) | |
| (nvid, FvOff off) <- non_ind_fvs | |
, reference_outer_closure | |
] ++ ind_fvs | |
in (effective_fvs, ind_loads) | |
| otherwise = (fvs, []) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment