Skip to content

Instantly share code, notes, and snippets.

@alexbiehl
Last active November 13, 2017 10:02
Show Gist options
  • Save alexbiehl/65eb4e73dd3fa3c0945d9997ff75963b to your computer and use it in GitHub Desktop.
Save alexbiehl/65eb4e73dd3fa3c0945d9997ff75963b to your computer and use it in GitHub Desktop.
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