closureSize, closureHdrSize,
closureNonHdrSize, closureSizeWithoutFixedHdr,
- closureGoodStuffSize, closurePtrsSize, -- UNUSED: closureNonPtrsSize,
+ closureGoodStuffSize, closurePtrsSize,
slopSize, fitsMinUpdSize,
layOutDynClosure, layOutDynCon, layOutStaticClosure,
layOutStaticNoFVClosure, layOutPhantomClosure,
- mkVirtHeapOffsets, -- for GHCI
+ mkVirtHeapOffsets, -- for GHCI
nodeMustPointToIt, getEntryConvention,
blackHoleOnEntry,
- staticClosureRequired,
+ staticClosureRequired,
slowFunEntryCodeRequired, funInfoTableRequired,
stdVapRequired, noUpdVapRequired,
closureSingleEntry, closureSemiTag, closureType,
closureReturnsUnboxedType, getStandardFormThunkInfo,
---OLD auxInfoTableLabelFromCI, isIntLikeRep, -- go away in 0.23
-
closureKind, closureTypeDescr, -- profiling
isConstantRep, isSpecRep, isPhantomRep, -- ToDo: Should be in SMRep, perhaps?
isStaticClosure, allocProfilingMsg,
blackHoleClosureInfo,
getSMInfoStr, getSMInitHdrStr, getSMUpdInplaceHdrStr,
- ltSMRepHdr, --UNUSED: equivSMRepHdr,
+ ltSMRepHdr,
maybeSelectorInfo,
- dataConLiveness, -- concurrency
+ dataConLiveness -- concurrency
-- and to make the interface self-sufficient...
- AbstractC, CAddrMode, HeapOffset, MagicId,
- CgInfoDownwards, CgState, CgIdInfo, CompilationInfo,
- CLabel, Id, Maybe, PrimKind, FCode(..), TyCon, StgExpr,
- StgAtom, StgBinderInfo,
- DataCon(..), PlainStgExpr(..), PlainStgLiveVars(..),
- PlainStgAtom(..),
- UniqSet(..), UniqFM, UpdateFlag(..) -- not abstract
-
- IF_ATTACK_PRAGMAS(COMMA mkClosureLabel)
- IF_ATTACK_PRAGMAS(COMMA getUniDataSpecTyCon_maybe)
) where
import AbsCSyn
import SMRep
import StgSyn
-import AbsUniType
+import Type
import CgCompInfo -- some magic constants
import CgRetConv
-import CLabelInfo -- Lots of label-making things
+import CLabel -- Lots of label-making things
import CmdLineOpts ( GlobalSwitch(..) )
import Id
import IdInfo -- SIGH
import Maybes ( maybeToBool, assocMaybe, Maybe(..) )
import Outputable -- needed for INCLUDE_FRC_METHOD
import Pretty -- ( ppStr, Pretty(..) )
-import PrimKind ( PrimKind, getKindSize, separateByPtrFollowness )
+import PrimRep ( PrimRep, getPrimRepSize, separateByPtrFollowness )
import Util
\end{code}
| LFTuple -- Tuples
DataCon -- The tuple constructor (may be specialised)
Bool -- True <=> zero arity
-
+
| LFThunk -- Thunk (zero arity)
Bool -- True <=> top level
Bool -- True <=> no free vars
| LFLetNoEscape -- See LetNoEscape module for precise description of
-- these "lets".
Int -- arity;
- PlainStgLiveVars-- list of variables live in the RHS of the let.
+ StgLiveVars-- list of variables live in the RHS of the let.
-- (ToDo: maybe not used)
| LFBlackHole -- Used for the closures allocated to hold the result
= NonStandardThunk -- No, it isn't
- | SelectorThunk
+ | SelectorThunk
Id -- Scrutinee
DataCon -- Constructor
Int -- 0-origin offset of ak within the "goods" of constructor
-- (Recall that the a1,...,an may be laid out in the heap
-- in a non-obvious order.)
-
+
{- A SelectorThunk is of form
- case x of
- con a1,..,an -> ak
-
- and the constructor is from a single-constr type.
+ case x of
+ con a1,..,an -> ak
+
+ and the constructor is from a single-constr type.
If we can't convert the heap-offset of the selectee into an Int, e.g.,
it's "GEN_VHS+i", we just give up.
-}
-
+
| VapThunk
Id -- Function
- [PlainStgAtom] -- Args
- Bool -- True <=> the function is not top-level, so
+ [StgArg] -- Args
+ Bool -- True <=> the function is not top-level, so
-- must be stored in the thunk too
-
+
{- A VapThunk is of form
- f a1 ... an
+ f a1 ... an
- where f is a known function, with arity n
- So for this thunk we can use the label for f's heap-entry
- info table (generated when f's defn was dealt with),
- rather than generating a one-off info table and entry code
- for this one thunk.
+ where f is a known function, with arity n
+ So for this thunk we can use the label for f's heap-entry
+ info table (generated when f's defn was dealt with),
+ rather than generating a one-off info table and entry code
+ for this one thunk.
-}
-
+
mkLFArgument = LFArgument
mkLFBlackHole = LFBlackHole
mkLFLetNoEscape = LFLetNoEscape
-> [Id] -- Free vars
-> UpdateFlag -- Update flag
-> [Id] -- Args
- -> PlainStgExpr -- Body of closure: passed so we
+ -> StgExpr -- Body of closure: passed so we
-- can look for selector thunks!
-> LambdaFormInfo
[the_fv] -- just one...
Updatable
[] -- no args (a thunk)
- (StgCase (StgApp (StgVarAtom scrutinee) [{-no args-}] _)
+ (StgCase (StgApp (StgVarArg scrutinee) [{-no args-}] _)
_ _ _ -- ignore live vars and uniq...
(StgAlgAlts case_ty
[(con, params, use_mask,
- (StgApp (StgVarAtom selectee) [{-no args-}] _))]
+ (StgApp (StgVarArg selectee) [{-no args-}] _))]
StgNoDefault))
| the_fv == scrutinee -- Scrutinee is the only free variable
&& maybeToBool maybe_offset -- Selectee is a component of the tuple
&& maybeToBool offset_into_int_maybe
&& offset_into_int <= mAX_SPEC_SELECTEE_SIZE -- Offset is small enough
- =
+ =
-- ASSERT(is_single_constructor) -- Should be true, by causes error for SpecTyCon
LFThunk False False True (SelectorThunk scrutinee con offset_into_int)
where
- (_, params_w_offsets) = layOutDynCon con getIdKind params
+ (_, params_w_offsets) = layOutDynCon con getIdPrimRep params
maybe_offset = assocMaybe params_w_offsets selectee
Just the_offset = maybe_offset
- offset_into_int_maybe = intOffsetIntoGoods the_offset
+ offset_into_int_maybe = intOffsetIntoGoods the_offset
Just offset_into_int = offset_into_int_maybe
is_single_constructor = maybeToBool (maybeSingleConstructorTyCon tycon)
(_,_,_, tycon) = getDataConSig con
fvs
upd_flag
[] -- No args; a thunk
- (StgApp (StgVarAtom fun_id) args _)
- | not top_level -- A top-level thunk would require a static
+ (StgApp (StgVarArg fun_id) args _)
+ | not top_level -- A top-level thunk would require a static
-- vap_info table, which we don't generate just
-- now; so top-level thunks are never standard
-- form.
@ConstantRep@ and @CharLikeRep@ closures always use the address of
a static closure. They are never allocated or
collected (eg hold forwarding pointer) hence never any slop.
-
+
\item
@IntLikeRep@ are never updatable.
May need slop to be collected (as they will be size 1 or more
\begin{code}
layOutDynClosure, layOutStaticClosure
:: Id -- STG identifier w/ which this closure assoc'd
- -> (a -> PrimKind) -- function w/ which to be able to get a PrimKind
+ -> (a -> PrimRep) -- function w/ which to be able to get a PrimRep
-> [a] -- the "things" being layed out
-> LambdaFormInfo -- what sort of closure it is
-> (ClosureInfo, -- info about the closure
A wrapper for when used with data constructors:
\begin{code}
layOutDynCon :: DataCon
- -> (a -> PrimKind)
+ -> (a -> PrimRep)
-> [a]
-> (ClosureInfo, [(a,VirtualHeapOffset)])
-layOutDynCon con kind_fn args
+layOutDynCon con kind_fn args
= ASSERT(isDataCon con)
layOutDynClosure con kind_fn args (mkConLFInfo con)
\end{code}
\begin{code}
mkVirtHeapOffsets :: SMRep -- Representation to be used by storage manager
- -> (a -> PrimKind) -- To be able to grab kinds;
+ -> (a -> PrimRep) -- To be able to grab kinds;
-- w/ a kind, we can find boxedness
-> [a] -- Things to make offsets for
-> (Int, -- *Total* number of words allocated
where
offset_of_first_word = totHdrSize sm_rep
computeOffset wds_so_far thing
- = (wds_so_far + (getKindSize . kind_fun) thing,
+ = (wds_so_far + (getPrimRepSize . kind_fun) thing,
(thing, (offset_of_first_word `addOff` (intOff wds_so_far)))
)
\end{code}
-- is not top level as special case cgRhsClosure
-- has been dissabled in favour of let floating
---OLD: || (arity == 0 && do_profiling)
--- -- Access to cost centre required for 0 arity if profiling
--- -- Simon: WHY? (94/12)
-
-- For lex_profiling we also access the cost centre for a
-- non-inherited function i.e. not top level
-- the not top case above ensures this is ok.
0 arg, fvs @\u@ & yes & yes & n/a & node\\
\end{tabular}
-When black-holing, single-entry closures could also be entered via node
+When black-holing, single-entry closures could also be entered via node
(rather than directly) to catch double-entry.
\begin{code}
= ViaNode -- The "normal" convention
| StdEntry CLabel -- Jump to this code, with args on stack
- (Maybe CLabel) -- possibly setting infoptr to this
+ (Maybe CLabel) -- possibly setting infoptr to this
| DirectEntry -- Jump directly to code, with args in regs
CLabel -- The code label
getEntryConvention :: Id -- Function being applied
-> LambdaFormInfo -- Its info
- -> [PrimKind] -- Available arguments
+ -> [PrimRep] -- Available arguments
-> FCode EntryConvention
getEntryConvention id lf_info arg_kinds
= nodeMustPointToIt lf_info `thenFC` \ node_points ->
- isSwitchSetC ForConcurrent `thenFC` \ is_concurrent ->
+ isSwitchSetC ForConcurrent `thenFC` \ is_concurrent ->
getIntSwitchChkrC `thenFC` \ isw_chkr ->
returnFC (
case lf_info of
- LFReEntrant _ arity _ ->
- if arity == 0 || (length arg_kinds) < arity then
+ LFReEntrant _ arity _ ->
+ if arity == 0 || (length arg_kinds) < arity then
StdEntry (mkStdEntryLabel id) Nothing
- else
+ else
DirectEntry (mkFastEntryLabel id arity) arity arg_regs
where
(arg_regs, _) = assignRegs isw_chkr live_regs (take arity arg_kinds)
live_regs = if node_points then [node] else []
- LFCon con zero_arity
- -> let itbl = if zero_arity then
+ LFCon con zero_arity
+ -> let itbl = if zero_arity then
mkPhantomInfoTableLabel con
else
mkInfoTableLabel con
in StdEntry (mkStdEntryLabel con) (Just itbl)
-- Should have no args
- LFTuple tup zero_arity
+ LFTuple tup zero_arity
-> StdEntry (mkStdEntryLabel tup)
(Just (mkInfoTableLabel tup))
-- Should have no args
then ViaNode
else StdEntry (thunkEntryLabel id std_form_info updatable) Nothing
- LFArgument -> ViaNode
- LFImported -> ViaNode
- LFBlackHole -> ViaNode -- Presumably the black hole has by now
+ LFArgument -> ViaNode
+ LFImported -> ViaNode
+ LFBlackHole -> ViaNode -- Presumably the black hole has by now
-- been updated, but we don't know with
-- what, so we enter via Node
-> if updatable
then not no_black_holing
else not no_fvs
- other -> panic "blackHoleOnEntry" -- Should never happen
+ other -> panic "blackHoleOnEntry" -- Should never happen
-getStandardFormThunkInfo
- :: LambdaFormInfo
- -> Maybe [PlainStgAtom] -- Nothing => not a standard-form thunk
+getStandardFormThunkInfo
+ :: LambdaFormInfo
+ -> Maybe [StgArg] -- Nothing => not a standard-form thunk
-- Just atoms => a standard-form thunk with payload atoms
getStandardFormThunkInfo (LFThunk _ _ _ (SelectorThunk scrutinee _ _))
= --trace "Selector thunk: missed opportunity to save info table + code"
Nothing
- -- Just [StgVarAtom scrutinee]
+ -- Just [StgVarArg scrutinee]
-- We can't save the info tbl + code until we have a way to generate
-- a fixed family thereof.
getStandardFormThunkInfo (LFThunk _ _ _ (VapThunk fun_id args fun_in_payload))
- | fun_in_payload = Just (StgVarAtom fun_id : args)
+ | fun_in_payload = Just (StgVarArg fun_id : args)
| otherwise = Just args
getStandardFormThunkInfo other_lf_info = Nothing
OR (b) the function is passed as an arg
OR (c) if the function has free vars (ie not top level)
- Why case (a) here? Because if the arg-satis check fails,
+ Why case (a) here? Because if the arg-satis check fails,
UpdatePAP stuffs a pointer to the function closure in the PAP.
[Could be changed; UpdatePAP could stuff in a code ptr instead,
but doesn't seem worth it.]
- [NB: these conditions imply that we might need the closure
+ [NB: these conditions imply that we might need the closure
without the slow-entry code. Here's how.
f x y = let g w = ...x..y..w...
Needed iff (a) we have any un-saturated calls to the function
OR (b) the function is passed as an arg
OR (c) the function has free vars (ie not top level)
-
+
NB. In the sequential world, (c) is only required so that the function closure has
an info table to point to, to keep the storage manager happy.
If (c) alone is true we could fake up an info table by choosing
* Single-update vap-entry code
Single-update vap-entry info table
- Needed iff we have any non-updatable thunks of the
+ Needed iff we have any non-updatable thunks of the
standard vap-entry shape.
-
+
\begin{code}
staticClosureRequired
:: Id
- -> StgBinderInfo
+ -> StgBinderInfo
-> LambdaFormInfo
-> Bool
-staticClosureRequired binder (StgBinderInfo arg_occ unsat_occ _ _ _)
+staticClosureRequired binder (StgBinderInfo arg_occ unsat_occ _ _ _)
(LFReEntrant top_level _ _) -- It's a function
= ASSERT( top_level ) -- Assumption: it's a top-level, no-free-var binding
arg_occ -- There's an argument occurrence
-> LambdaFormInfo
-> Bool
funInfoTableRequired binder (StgBinderInfo arg_occ unsat_occ _ _ _)
- (LFReEntrant top_level _ _)
+ (LFReEntrant top_level _ _)
= not top_level
|| arg_occ -- There's an argument occurrence
|| unsat_occ -- There's an unsaturated call
funInfoTableRequired other_binder_info binder other_lf_info = True
--- We need the vector-apply entry points for a function if
--- there's a vector-apply occurrence in this module
+-- We need the vector-apply entry points for a function if
+-- there's a vector-apply occurrence in this module
stdVapRequired, noUpdVapRequired :: StgBinderInfo -> Bool
Note: @closureType@ returns appropriately specialised tycon and
datacons.
\begin{code}
-closureType :: ClosureInfo -> Maybe (TyCon, [UniType], [Id])
+closureType :: ClosureInfo -> Maybe (TyCon, [Type], [Id])
-- First, a turgid special case. When we are generating the
-- standard code and info-table for Vaps (which is done when the function
closureType (MkClosureInfo id (LFThunk _ _ _ (VapThunk fun_id args _)) _)
= getUniDataSpecTyCon_maybe (funResultTy de_foralld_ty (length args))
where
- (_, de_foralld_ty) = splitForalls (getIdUniType fun_id)
+ (_, de_foralld_ty) = splitForalls (idType fun_id)
-closureType (MkClosureInfo id lf _) = getUniDataSpecTyCon_maybe (getIdUniType id)
+closureType (MkClosureInfo id lf _) = getUniDataSpecTyCon_maybe (idType id)
\end{code}
@closureReturnsUnboxedType@ is used to check whether a closure, {\em
closureReturnsUnboxedType (MkClosureInfo fun_id (LFReEntrant _ arity _) _)
= isPrimType (funResultTy de_foralld_ty arity)
where
- (_, de_foralld_ty) = splitForalls (getIdUniType fun_id)
+ (_, de_foralld_ty) = splitForalls (idType fun_id)
closureReturnsUnboxedType other_closure = False
-- All non-function closures aren't functions,
= case lf_info of
LFCon data_con _ -> getDataConTag data_con - fIRST_TAG
LFTuple _ _ -> 0
- --UNUSED: LFIndirection -> fromInteger iND_TAG
_ -> fromInteger oTHER_TAG
\end{code}
LFBlackHole -> mkBlackHoleInfoTableLabel
LFThunk _ _ upd_flag (VapThunk fun_id args _) -> mkVapInfoTableLabel fun_id upd_flag
- -- Use the standard vap info table
+ -- Use the standard vap info table
-- for the function, rather than a one-off one
-- for this particular closure
else -} mkInfoTableLabel id
mkConInfoPtr :: Id -> SMRep -> CLabel
-mkConInfoPtr id rep =
- case rep of
+mkConInfoPtr id rep =
+ case rep of
PhantomRep -> mkPhantomInfoTableLabel id
StaticRep _ _ -> mkStaticInfoTableLabel id
_ -> mkInfoTableLabel id
mkConEntryPtr :: Id -> SMRep -> CLabel
-mkConEntryPtr id rep =
- case rep of
+mkConEntryPtr id rep =
+ case rep of
StaticRep _ _ -> mkStaticConEntryLabel id
_ -> mkConEntryLabel id
-- I don't think it needs to deal with the SelectorThunk case
-- Well, it's falling over now, so I've made it deal with it. (JSM)
-thunkEntryLabel thunk_id (VapThunk fun_id args _) is_updatable
+thunkEntryLabel thunk_id (VapThunk fun_id args _) is_updatable
= mkVapEntryLabel fun_id is_updatable
-thunkEntryLabel thunk_id _ is_updatable
+thunkEntryLabel thunk_id _ is_updatable
= mkStdEntryLabel thunk_id
-
+
fastLabelFromCI :: ClosureInfo -> CLabel
fastLabelFromCI (MkClosureInfo id _ _) = mkFastEntryLabel id fun_arity
where
LFTuple _ _ -> SLIT("ALLOC_CON")
LFThunk _ _ _ _ -> SLIT("ALLOC_THK")
LFBlackHole -> SLIT("ALLOC_BH")
- --UNUSED: LFIndirection -> panic "ALLOC_IND"
LFImported -> panic "ALLOC_IMP"
\end{code}
LFTuple _ _ -> "CON_K"
LFThunk _ _ _ _ -> "THK_K"
LFBlackHole -> "THK_K" -- consider BHs as thunks for the moment... (ToDo?)
- --UNUSED: LFIndirection -> panic "IND_KIND"
LFImported -> panic "IMP_KIND"
closureTypeDescr :: ClosureInfo -> String
= if (isDataCon id) then -- DataCon has function types
_UNPK_ (getOccurrenceName (getDataConTyCon id)) -- We want the TyCon not the ->
else
- getUniTyDescription (getIdUniType id)
+ getUniTyDescription (idType id)
\end{code}