2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
4 % $Id: ClosureInfo.lhs,v 1.34 1999/03/04 17:52:08 simonm Exp $
6 \section[ClosureInfo]{Data structures which describe closures}
8 Much of the rationale for these things is in the ``details'' part of
13 ClosureInfo, LambdaFormInfo, SMRep, -- all abstract
18 mkClosureLFInfo, mkConLFInfo, mkSelectorLFInfo,
19 mkApLFInfo, mkLFImported, mkLFArgument, mkLFLetNoEscape,
22 closureSize, closureNonHdrSize,
23 closureGoodStuffSize, closurePtrsSize,
26 layOutDynClosure, layOutDynCon, layOutStaticClosure,
27 layOutStaticNoFVClosure,
30 nodeMustPointToIt, getEntryConvention,
31 FCode, CgInfoDownwards, CgState,
35 staticClosureRequired,
36 slowFunEntryCodeRequired, funInfoTableRequired,
38 closureName, infoTableLabelFromCI, fastLabelFromCI,
41 closureLFInfo, closureSMRep, closureUpdReqd,
42 closureSingleEntry, closureSemiTag,
47 closureTypeDescr, -- profiling
56 #include "HsVersions.h"
58 import AbsCSyn ( MagicId, node, VirtualHeapOffset, HeapOffset )
62 import Constants ( mIN_UPD_SIZE, mIN_SIZE_NonUpdHeapObject,
63 mAX_SPEC_FUN_SIZE, mAX_SPEC_THUNK_SIZE, mAX_SPEC_CONSTR_SIZE )
64 import CgRetConv ( assignRegs )
65 import CLabel ( CLabel, mkStdEntryLabel, mkFastEntryLabel,
67 mkConInfoTableLabel, mkStaticClosureLabel,
68 mkBlackHoleInfoTableLabel,
69 mkStaticInfoTableLabel, mkStaticConEntryLabel,
70 mkConEntryLabel, mkClosureLabel,
71 mkSelectorInfoLabel, mkSelectorEntryLabel,
72 mkApInfoTableLabel, mkApEntryLabel,
75 import CmdLineOpts ( opt_SccProfilingOn, opt_OmitBlackHoling,
77 import Id ( Id, idType, getIdArity )
78 import DataCon ( DataCon, dataConTag, fIRST_TAG,
79 isNullaryDataCon, isTupleCon, dataConName
81 import IdInfo ( ArityInfo(..) )
82 import Name ( Name, isExternallyVisibleName, nameUnique )
83 import PprType ( getTyDescription )
84 import PrimRep ( getPrimRepSize, separateByPtrFollowness, PrimRep )
85 import SMRep -- all of it
86 import Type ( isUnLiftedType, Type )
87 import BasicTypes ( TopLevelFlag(..) )
88 import Util ( mapAccumL )
92 The ``wrapper'' data type for closure information:
97 Name -- The thing bound to this closure
98 LambdaFormInfo -- info derivable from the *source*
99 SMRep -- representation used by storage manager
102 %************************************************************************
104 \subsection[ClosureInfo-datatypes]{Data types for closure information}
106 %************************************************************************
108 %************************************************************************
110 \subsubsection[LambdaFormInfo-datatype]{@LambdaFormInfo@: source-derivable info}
112 %************************************************************************
116 = LFReEntrant -- Reentrant closure; used for PAPs too
117 Type -- Type of closure (ToDo: remove)
118 TopLevelFlag -- True if top level
120 !Bool -- True <=> no fvs
122 | LFCon -- Constructor
123 DataCon -- The constructor
124 Bool -- True <=> zero arity
127 DataCon -- The tuple constructor
128 Bool -- True <=> zero arity
130 | LFThunk -- Thunk (zero arity)
131 Type -- Type of the thunk (ToDo: remove)
133 !Bool -- True <=> no free vars
134 Bool -- True <=> updatable (i.e., *not* single-entry)
137 | LFArgument -- Used for function arguments. We know nothing about
138 -- this closure. Treat like updatable "LFThunk"...
140 | LFImported -- Used for imported things. We know nothing about this
141 -- closure. Treat like updatable "LFThunk"...
142 -- Imported things which we do know something about use
143 -- one of the other LF constructors (eg LFReEntrant for
146 | LFLetNoEscape -- See LetNoEscape module for precise description of
150 | LFBlackHole -- Used for the closures allocated to hold the result
152 -- of a CAF. We want the target of the update frame to
153 -- be in the heap, so we make a black hole to hold it.
156 data StandardFormInfo -- Tells whether this thunk has one of a small number
159 = NonStandardThunk -- No, it isn't
162 Int -- 0-origin offset of ak within the "goods" of
163 -- constructor (Recall that the a1,...,an may be laid
164 -- out in the heap in a non-obvious order.)
166 {- A SelectorThunk is of form
171 and the constructor is from a single-constr type.
177 {- An ApThunk is of form
181 The code for the thunk just pushes x2..xn on the stack and enters x1.
182 There are a few of these (for 1 <= n <= MAX_SPEC_AP_SIZE) pre-compiled
183 in the RTS to save space.
188 %************************************************************************
190 \subsection[ClosureInfo-construction]{Functions which build LFInfos}
192 %************************************************************************
194 @mkClosureLFInfo@ figures out the appropriate LFInfo for the closure.
197 mkClosureLFInfo :: Id -- The binder
198 -> TopLevelFlag -- True of top level
200 -> UpdateFlag -- Update flag
204 mkClosureLFInfo bndr top fvs upd_flag args@(_:_) -- Non-empty args
205 = LFReEntrant (idType bndr) top (length args) (null fvs)
207 mkClosureLFInfo bndr top fvs ReEntrant []
208 = LFReEntrant (idType bndr) top 0 (null fvs)
210 mkClosureLFInfo bndr top fvs upd_flag []
212 | isUnLiftedType ty = pprPanic "mkClosureLFInfo" (ppr bndr <+> ppr ty)
215 = LFThunk ty top (null fvs) (isUpdatable upd_flag) NonStandardThunk
220 @mkConLFInfo@ is similar, for constructors.
223 mkConLFInfo :: DataCon -> LambdaFormInfo
226 = -- the isNullaryDataCon will do this: ASSERT(isDataCon con)
227 (if isTupleCon con then LFTuple else LFCon) con (isNullaryDataCon con)
229 mkSelectorLFInfo rhs_ty offset updatable
230 = LFThunk rhs_ty NotTopLevel False updatable (SelectorThunk offset)
232 mkApLFInfo rhs_ty upd_flag arity
233 = LFThunk rhs_ty NotTopLevel (arity == 0) (isUpdatable upd_flag)
237 Miscellaneous LF-infos.
240 mkLFArgument = LFArgument
241 mkLFBlackHole = LFBlackHole
242 mkLFLetNoEscape = LFLetNoEscape
244 mkLFImported :: Id -> LambdaFormInfo
246 = case getIdArity id of
247 ArityExactly 0 -> LFThunk (idType id)
248 TopLevel True{-no fvs-}
249 True{-updatable-} NonStandardThunk
250 ArityExactly n -> LFReEntrant (idType id) TopLevel n True -- n > 0
251 other -> LFImported -- Not sure of exact arity
254 %************************************************************************
256 \subsection[ClosureInfo-sizes]{Functions about closure {\em sizes}}
258 %************************************************************************
261 closureSize :: ClosureInfo -> HeapOffset
262 closureSize cl_info@(MkClosureInfo _ _ sm_rep)
263 = fixedHdrSize + closureNonHdrSize cl_info
265 closureNonHdrSize :: ClosureInfo -> Int
266 closureNonHdrSize cl_info@(MkClosureInfo _ lf_info sm_rep)
267 = tot_wds + computeSlopSize tot_wds sm_rep (closureUpdReqd cl_info)
268 --ToDo: pass lf_info?
270 tot_wds = closureGoodStuffSize cl_info
272 closureGoodStuffSize :: ClosureInfo -> Int
273 closureGoodStuffSize (MkClosureInfo _ _ sm_rep)
274 = let (ptrs, nonptrs) = sizes_from_SMRep sm_rep
277 closurePtrsSize :: ClosureInfo -> Int
278 closurePtrsSize (MkClosureInfo _ _ sm_rep)
279 = let (ptrs, _) = sizes_from_SMRep sm_rep
283 sizes_from_SMRep :: SMRep -> (Int,Int)
284 sizes_from_SMRep (GenericRep ptrs nonptrs _) = (ptrs, nonptrs)
285 sizes_from_SMRep (StaticRep ptrs nonptrs _) = (ptrs, nonptrs)
286 sizes_from_SMRep ConstantRep = (0, 0)
287 sizes_from_SMRep BlackHoleRep = (0, 0)
290 Computing slop size. WARNING: this looks dodgy --- it has deep
291 knowledge of what the storage manager does with the various
297 Updateable closures must be @mIN_UPD_SIZE@.
300 Indirections require 1 word
302 Appels collector indirections 2 words
304 THEREFORE: @mIN_UPD_SIZE = 2@.
307 Collectable closures which are allocated in the heap
308 must be @mIN_SIZE_NonUpdHeapObject@.
310 Copying collector forward pointer requires 1 word
312 THEREFORE: @mIN_SIZE_NonUpdHeapObject = 1@
315 Static closures have an extra ``static link field'' at the end, but we
316 don't bother taking that into account here.
319 slopSize cl_info@(MkClosureInfo _ lf_info sm_rep)
320 = computeSlopSize (closureGoodStuffSize cl_info) sm_rep
321 (closureUpdReqd cl_info)
323 computeSlopSize :: Int -> SMRep -> Bool -> Int
325 computeSlopSize tot_wds (StaticRep _ _ _) True -- Updatable
326 = max 0 (mIN_UPD_SIZE - tot_wds)
327 computeSlopSize tot_wds (StaticRep _ _ _) False
328 = 0 -- non updatable, non-heap object
329 computeSlopSize tot_wds (GenericRep _ _ _) True -- Updatable
330 = max 0 (mIN_UPD_SIZE - tot_wds)
331 computeSlopSize tot_wds (GenericRep _ _ _) False
332 = max 0 (mIN_SIZE_NonUpdHeapObject - tot_wds)
333 computeSlopSize tot_wds ConstantRep _
335 computeSlopSize tot_wds BlackHoleRep _ -- Updatable
336 = max 0 (mIN_UPD_SIZE - tot_wds)
339 %************************************************************************
341 \subsection[layOutDynClosure]{Lay out a dynamic closure}
343 %************************************************************************
346 layOutDynClosure, layOutStaticClosure
347 :: Name -- STG identifier of this closure
348 -> (a -> PrimRep) -- how to get a PrimRep for the fields
349 -> [a] -- the "things" being layed out
350 -> LambdaFormInfo -- what sort of closure it is
351 -> (ClosureInfo, -- info about the closure
352 [(a, VirtualHeapOffset)]) -- things w/ offsets pinned on them
354 layOutDynClosure name kind_fn things lf_info
355 = (MkClosureInfo name lf_info sm_rep,
358 (tot_wds, -- #ptr_wds + #nonptr_wds
360 things_w_offsets) = mkVirtHeapOffsets sm_rep kind_fn things
361 sm_rep = chooseDynSMRep lf_info tot_wds ptr_wds
364 A wrapper for when used with data constructors:
367 layOutDynCon :: DataCon
370 -> (ClosureInfo, [(a,VirtualHeapOffset)])
372 layOutDynCon con kind_fn args
373 = layOutDynClosure (dataConName con) kind_fn args (mkConLFInfo con)
376 %************************************************************************
378 \subsection[layOutStaticClosure]{Lay out a static closure}
380 %************************************************************************
382 layOutStaticClosure is only used for laying out static constructors at
385 Static closures for functions are laid out using
386 layOutStaticNoFVClosure.
389 layOutStaticClosure name kind_fn things lf_info
390 = (MkClosureInfo name lf_info
391 (StaticRep ptr_wds (tot_wds - ptr_wds) closure_type),
394 (tot_wds, -- #ptr_wds + #nonptr_wds
396 things_w_offsets) = mkVirtHeapOffsets (StaticRep bot bot bot) kind_fn things
398 -- constructors with no pointer fields will definitely be NOCAF things.
399 -- this is a compromise until we can generate both kinds of constructor
400 -- (a normal static kind and the NOCAF_STATIC kind).
401 closure_type = case lf_info of
402 LFCon _ _ | ptr_wds == 0 -> CONSTR_NOCAF
403 _ -> getStaticClosureType lf_info
405 bot = panic "layoutStaticClosure"
407 layOutStaticNoFVClosure :: Name -> LambdaFormInfo -> ClosureInfo
408 layOutStaticNoFVClosure name lf_info
409 = MkClosureInfo name lf_info (StaticRep 0 0 (getStaticClosureType lf_info))
412 %************************************************************************
414 \subsection[SMreps]{Choosing SM reps}
416 %************************************************************************
421 -> Int -> Int -- Tot wds, ptr wds
424 chooseDynSMRep lf_info tot_wds ptr_wds
426 nonptr_wds = tot_wds - ptr_wds
427 closure_type = getClosureType tot_wds ptr_wds nonptr_wds lf_info
430 LFTuple _ True -> ConstantRep
431 LFCon _ True -> ConstantRep
432 _ -> GenericRep ptr_wds nonptr_wds closure_type
434 getStaticClosureType :: LambdaFormInfo -> ClosureType
435 getStaticClosureType lf_info =
437 LFCon con True -> CONSTR_NOCAF
438 LFCon con False -> CONSTR
439 LFReEntrant _ _ _ _ -> FUN
440 LFTuple _ _ -> CONSTR
441 LFThunk _ _ _ _ (SelectorThunk _) -> THUNK_SELECTOR
442 LFThunk _ _ _ True _ -> THUNK
443 LFThunk _ _ _ False _ -> FUN
444 _ -> panic "getClosureType"
446 -- we *do* get non-updatable top-level thunks sometimes. eg. f = g
447 -- gets compiled to a jump to g (if g has non-zero arity), instead of
448 -- messing around with update frames and PAPs. We set the closure type
449 -- to FUN_STATIC in this case.
451 getClosureType :: Int -> Int -> Int -> LambdaFormInfo -> ClosureType
452 getClosureType tot_wds ptrs nptrs lf_info =
454 LFCon con True -> CONSTR_NOCAF
457 | tot_wds > 0 && tot_wds <= mAX_SPEC_CONSTR_SIZE -> CONSTR_p_n ptrs nptrs
458 | otherwise -> CONSTR
461 | tot_wds > 0 && tot_wds <= mAX_SPEC_FUN_SIZE -> FUN_p_n ptrs nptrs
465 | tot_wds > 0 && tot_wds <= mAX_SPEC_CONSTR_SIZE -> CONSTR_p_n ptrs nptrs
466 | otherwise -> CONSTR
468 LFThunk _ _ _ _ (SelectorThunk _) -> THUNK_SELECTOR
471 | tot_wds > 0 && tot_wds <= mAX_SPEC_THUNK_SIZE -> THUNK_p_n ptrs nptrs
474 _ -> panic "getClosureType"
477 %************************************************************************
479 \subsection[mkVirtHeapOffsets]{Assigning heap offsets in a closure}
481 %************************************************************************
483 @mkVirtHeapOffsets@ (the heap version) always returns boxed things with
484 smaller offsets than the unboxed things, and furthermore, the offsets in
488 mkVirtHeapOffsets :: SMRep -- Representation to be used by storage manager
489 -> (a -> PrimRep) -- To be able to grab kinds;
490 -- w/ a kind, we can find boxedness
491 -> [a] -- Things to make offsets for
492 -> (Int, -- *Total* number of words allocated
493 Int, -- Number of words allocated for *pointers*
494 [(a, VirtualHeapOffset)])
495 -- Things with their offsets from start of
496 -- object in order of increasing offset
498 -- First in list gets lowest offset, which is initial offset + 1.
500 mkVirtHeapOffsets sm_rep kind_fun things
501 = let (ptrs, non_ptrs) = separateByPtrFollowness kind_fun things
502 (wds_of_ptrs, ptrs_w_offsets) = mapAccumL computeOffset 0 ptrs
503 (tot_wds, non_ptrs_w_offsets) = mapAccumL computeOffset wds_of_ptrs non_ptrs
505 (tot_wds, wds_of_ptrs, ptrs_w_offsets ++ non_ptrs_w_offsets)
507 computeOffset wds_so_far thing
508 = (wds_so_far + (getPrimRepSize . kind_fun) thing,
509 (thing, fixedHdrSize + wds_so_far)
513 %************************************************************************
515 \subsection[ClosureInfo-4-questions]{Four major questions about @ClosureInfo@}
517 %************************************************************************
519 Be sure to see the stg-details notes about these...
522 nodeMustPointToIt :: LambdaFormInfo -> FCode Bool
523 nodeMustPointToIt lf_info
526 LFReEntrant ty top arity no_fvs -> returnFC (
527 not no_fvs || -- Certainly if it has fvs we need to point to it
528 case top of { TopLevel -> False; _ -> True }
529 -- If it is not top level we will point to it
530 -- We can have a \r closure with no_fvs which
531 -- is not top level as special case cgRhsClosure
532 -- has been dissabled in favour of let floating
534 -- For lex_profiling we also access the cost centre for a
535 -- non-inherited function i.e. not top level
536 -- the not top case above ensures this is ok.
539 LFCon _ zero_arity -> returnFC True
540 LFTuple _ zero_arity -> returnFC True
542 -- Strictly speaking, the above two don't need Node to point
543 -- to it if the arity = 0. But this is a *really* unlikely
544 -- situation. If we know it's nil (say) and we are entering
545 -- it. Eg: let x = [] in x then we will certainly have inlined
546 -- x, since nil is a simple atom. So we gain little by not
547 -- having Node point to known zero-arity things. On the other
548 -- hand, we do lose something; Patrick's code for figuring out
549 -- when something has been updated but not entered relies on
550 -- having Node point to the result of an update. SLPJ
553 LFThunk _ _ no_fvs updatable NonStandardThunk
554 -> returnFC (updatable || not no_fvs || opt_SccProfilingOn)
556 -- For the non-updatable (single-entry case):
558 -- True if has fvs (in which case we need access to them, and we
559 -- should black-hole it)
560 -- or profiling (in which case we need to recover the cost centre
563 LFThunk _ _ no_fvs updatable some_standard_form_thunk
565 -- Node must point to any standard-form thunk.
567 LFArgument -> returnFC True
568 LFImported -> returnFC True
569 LFBlackHole -> returnFC True
570 -- BH entry may require Node to point
572 LFLetNoEscape _ -> returnFC False
575 The entry conventions depend on the type of closure being entered,
576 whether or not it has free variables, and whether we're running
577 sequentially or in parallel.
579 \begin{tabular}{lllll}
580 Closure Characteristics & Parallel & Node Req'd & Argument Passing & Enter Via \\
581 Unknown & no & yes & stack & node \\
582 Known fun ($\ge$ 1 arg), no fvs & no & no & registers & fast entry (enough args) \\
583 \ & \ & \ & \ & slow entry (otherwise) \\
584 Known fun ($\ge$ 1 arg), fvs & no & yes & registers & fast entry (enough args) \\
585 0 arg, no fvs @\r,\s@ & no & no & n/a & direct entry \\
586 0 arg, no fvs @\u@ & no & yes & n/a & node \\
587 0 arg, fvs @\r,\s@ & no & yes & n/a & direct entry \\
588 0 arg, fvs @\u@ & no & yes & n/a & node \\
590 Unknown & yes & yes & stack & node \\
591 Known fun ($\ge$ 1 arg), no fvs & yes & no & registers & fast entry (enough args) \\
592 \ & \ & \ & \ & slow entry (otherwise) \\
593 Known fun ($\ge$ 1 arg), fvs & yes & yes & registers & node \\
594 0 arg, no fvs @\r,\s@ & yes & no & n/a & direct entry \\
595 0 arg, no fvs @\u@ & yes & yes & n/a & node \\
596 0 arg, fvs @\r,\s@ & yes & yes & n/a & node \\
597 0 arg, fvs @\u@ & yes & yes & n/a & node\\
600 When black-holing, single-entry closures could also be entered via node
601 (rather than directly) to catch double-entry.
605 = ViaNode -- The "normal" convention
607 | StdEntry CLabel -- Jump to this code, with args on stack
609 | DirectEntry -- Jump directly, with args in regs
610 CLabel -- The code label
612 [MagicId] -- Its register assignments
615 getEntryConvention :: Name -- Function being applied
616 -> LambdaFormInfo -- Its info
617 -> [PrimRep] -- Available arguments
618 -> FCode EntryConvention
620 getEntryConvention name lf_info arg_kinds
621 = nodeMustPointToIt lf_info `thenFC` \ node_points ->
624 -- if we're parallel, then we must always enter via node. The reason
625 -- is that the closure may have been fetched since we allocated it.
627 if (node_points && opt_Parallel) then ViaNode else
629 -- Commented out by SDM after futher thoughts:
630 -- - the only closure type that can be blackholed is a thunk
631 -- - we already enter thunks via node (unless the closure is
632 -- non-updatable, in which case why is it being re-entered...)
636 LFReEntrant _ _ arity _ ->
637 if arity == 0 || (length arg_kinds) < arity then
638 StdEntry (mkStdEntryLabel name)
640 DirectEntry (mkFastEntryLabel name arity) arity arg_regs
642 (arg_regs, _) = assignRegs live_regs (take arity arg_kinds)
643 live_regs = if node_points then [node] else []
645 LFCon con True{-zero_arity-}
646 -- a real constructor. Don't bother entering it, just jump
647 -- to the constructor entry code directly.
648 -> --false:ASSERT (null arg_kinds)
649 -- Should have no args (meaning what?)
650 StdEntry (mkStaticConEntryLabel (dataConName con))
652 LFCon con False{-non-zero_arity-}
653 -> --false:ASSERT (null arg_kinds)
654 -- Should have no args (meaning what?)
655 StdEntry (mkConEntryLabel (dataConName con))
657 LFTuple tup zero_arity
658 -> --false:ASSERT (null arg_kinds)
659 -- Should have no args (meaning what?)
660 StdEntry (mkConEntryLabel (dataConName tup))
662 LFThunk _ _ _ updatable std_form_info
665 else StdEntry (thunkEntryLabel name std_form_info updatable)
667 LFArgument -> ViaNode
668 LFImported -> ViaNode
669 LFBlackHole -> ViaNode -- Presumably the black hole has by now
670 -- been updated, but we don't know with
671 -- what, so we enter via Node
674 -> StdEntry (mkReturnPtLabel (nameUnique name))
677 -> ASSERT(arity == length arg_kinds)
678 DirectEntry (mkReturnPtLabel (nameUnique name)) arity arg_regs
680 (arg_regs, _) = assignRegs [] arg_kinds
681 -- node never points to a LetNoEscape, see above --SDM
682 --live_regs = if node_points then [node] else []
685 blackHoleOnEntry :: ClosureInfo -> Bool
687 -- Static closures are never themselves black-holed.
688 -- Updatable ones will be overwritten with a CAFList cell, which points to a
690 -- Single-entry ones have no fvs to plug, and we trust they don't form part
693 blackHoleOnEntry (MkClosureInfo _ _ (StaticRep _ _ _)) = False
695 blackHoleOnEntry (MkClosureInfo _ lf_info _)
697 LFReEntrant _ _ _ _ -> False
698 LFLetNoEscape _ -> False
699 LFThunk _ _ no_fvs updatable _
701 then not opt_OmitBlackHoling
703 other -> panic "blackHoleOnEntry" -- Should never happen
705 isStandardFormThunk :: LambdaFormInfo -> Bool
707 isStandardFormThunk (LFThunk _ _ _ _ (SelectorThunk _)) = True
708 isStandardFormThunk (LFThunk _ _ _ _ (ApThunk _)) = True
709 isStandardFormThunk other_lf_info = False
711 maybeSelectorInfo (MkClosureInfo _ (LFThunk _ _ _ _
712 (SelectorThunk offset)) _) = Just offset
713 maybeSelectorInfo _ = Nothing
715 -- Does this thunk's info table have an SRT?
717 needsSRT :: ClosureInfo -> Bool
718 needsSRT (MkClosureInfo _ info _) =
720 LFThunk _ _ _ _ (SelectorThunk _) -> False -- not for selectors
721 LFThunk _ _ _ _ _ -> True
722 LFReEntrant _ _ _ _ -> True
726 Avoiding generating entries and info tables
727 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
728 At present, for every function we generate all of the following,
729 just in case. But they aren't always all needed, as noted below:
731 [NB1: all of this applies only to *functions*. Thunks always
732 have closure, info table, and entry code.]
734 [NB2: All are needed if the function is *exported*, just to play safe.]
737 * Fast-entry code ALWAYS NEEDED
740 Needed iff (a) we have any un-saturated calls to the function
741 OR (b) the function is passed as an arg
742 OR (c) we're in the parallel world and the function has free vars
743 [Reason: in parallel world, we always enter functions
744 with free vars via the closure.]
746 * The function closure
747 Needed iff (a) we have any un-saturated calls to the function
748 OR (b) the function is passed as an arg
749 OR (c) if the function has free vars (ie not top level)
751 Why case (a) here? Because if the arg-satis check fails,
752 UpdatePAP stuffs a pointer to the function closure in the PAP.
753 [Could be changed; UpdatePAP could stuff in a code ptr instead,
754 but doesn't seem worth it.]
756 [NB: these conditions imply that we might need the closure
757 without the slow-entry code. Here's how.
759 f x y = let g w = ...x..y..w...
763 Here we need a closure for g which contains x and y,
764 but since the calls are all saturated we just jump to the
765 fast entry point for g, with R1 pointing to the closure for g.]
768 * Standard info table
769 Needed iff (a) we have any un-saturated calls to the function
770 OR (b) the function is passed as an arg
771 OR (c) the function has free vars (ie not top level)
773 NB. In the sequential world, (c) is only required so that the function closure has
774 an info table to point to, to keep the storage manager happy.
775 If (c) alone is true we could fake up an info table by choosing
776 one of a standard family of info tables, whose entry code just
779 [NB In the parallel world (c) is needed regardless because
780 we enter functions with free vars via the closure.]
782 If (c) is retained, then we'll sometimes generate an info table
783 (for storage mgr purposes) without slow-entry code. Then we need
784 to use an error label in the info table to substitute for the absent
788 staticClosureRequired
793 staticClosureRequired binder (StgBinderInfo arg_occ unsat_occ _ _ _)
794 (LFReEntrant _ top_level _ _) -- It's a function
795 = ASSERT( case top_level of { TopLevel -> True; other -> False } )
796 -- Assumption: it's a top-level, no-free-var binding
797 arg_occ -- There's an argument occurrence
798 || unsat_occ -- There's an unsaturated call
799 || isExternallyVisibleName binder
801 staticClosureRequired binder other_binder_info other_lf_info = True
803 slowFunEntryCodeRequired -- Assumption: it's a function, not a thunk.
808 slowFunEntryCodeRequired binder (StgBinderInfo arg_occ unsat_occ _ _ _) entry_conv
809 = arg_occ -- There's an argument occurrence
810 || unsat_occ -- There's an unsaturated call
811 || isExternallyVisibleName binder
812 || (case entry_conv of { DirectEntry _ _ _ -> False; other -> True })
813 {- The last case deals with the parallel world; a function usually
814 as a DirectEntry convention, but if it doesn't we must generate slow-entry code -}
816 slowFunEntryCodeRequired binder NoStgBinderInfo _ = True
823 funInfoTableRequired binder (StgBinderInfo arg_occ unsat_occ _ _ _)
824 (LFReEntrant _ top_level _ _)
825 = (case top_level of { NotTopLevel -> True; TopLevel -> False })
826 || arg_occ -- There's an argument occurrence
827 || unsat_occ -- There's an unsaturated call
828 || isExternallyVisibleName binder
830 funInfoTableRequired other_binder_info binder other_lf_info = True
833 %************************************************************************
835 \subsection[ClosureInfo-misc-funs]{Misc functions about @ClosureInfo@, etc.}
837 %************************************************************************
841 isStaticClosure :: ClosureInfo -> Bool
842 isStaticClosure (MkClosureInfo _ _ rep) = isStaticRep rep
844 closureName :: ClosureInfo -> Name
845 closureName (MkClosureInfo name _ _) = name
847 closureSMRep :: ClosureInfo -> SMRep
848 closureSMRep (MkClosureInfo _ _ sm_rep) = sm_rep
850 closureLFInfo :: ClosureInfo -> LambdaFormInfo
851 closureLFInfo (MkClosureInfo _ lf_info _) = lf_info
853 closureUpdReqd :: ClosureInfo -> Bool
855 closureUpdReqd (MkClosureInfo _ (LFThunk _ _ _ upd _) _) = upd
856 closureUpdReqd (MkClosureInfo _ LFBlackHole _) = True
857 -- Black-hole closures are allocated to receive the results of an
858 -- alg case with a named default... so they need to be updated.
859 closureUpdReqd other_closure = False
861 closureSingleEntry :: ClosureInfo -> Bool
863 closureSingleEntry (MkClosureInfo _ (LFThunk _ _ _ upd _) _) = not upd
864 closureSingleEntry other_closure = False
868 closureSemiTag :: ClosureInfo -> Maybe Int
870 closureSemiTag (MkClosureInfo _ lf_info _)
872 LFCon data_con _ -> Just (dataConTag data_con - fIRST_TAG)
873 LFTuple _ _ -> Just 0
878 isToplevClosure :: ClosureInfo -> Bool
880 isToplevClosure (MkClosureInfo _ lf_info _)
882 LFReEntrant _ TopLevel _ _ -> True
883 LFThunk _ TopLevel _ _ _ -> True
888 isLetNoEscape :: ClosureInfo -> Bool
890 isLetNoEscape (MkClosureInfo _ (LFLetNoEscape _) _) = True
891 isLetNoEscape _ = False
897 fastLabelFromCI :: ClosureInfo -> CLabel
898 fastLabelFromCI (MkClosureInfo name (LFReEntrant _ _ arity _) _)
899 = mkFastEntryLabel name arity
901 fastLabelFromCI (MkClosureInfo name _ _)
902 = pprPanic "fastLabelFromCI" (ppr name)
904 infoTableLabelFromCI :: ClosureInfo -> CLabel
905 infoTableLabelFromCI (MkClosureInfo id lf_info rep)
907 LFCon con _ -> mkConInfoPtr con rep
908 LFTuple tup _ -> mkConInfoPtr tup rep
910 LFBlackHole -> mkBlackHoleInfoTableLabel
912 LFThunk _ _ _ upd_flag (SelectorThunk offset) ->
913 mkSelectorInfoLabel upd_flag offset
915 LFThunk _ _ _ upd_flag (ApThunk arity) ->
916 mkApInfoTableLabel upd_flag arity
918 other -> {-NO: if isStaticRep rep
919 then mkStaticInfoTableLabel id
920 else -} mkInfoTableLabel id
922 mkConInfoPtr :: DataCon -> SMRep -> CLabel
925 StaticRep _ _ _ -> mkStaticInfoTableLabel name
926 _ -> mkConInfoTableLabel name
928 name = dataConName con
930 mkConEntryPtr :: DataCon -> SMRep -> CLabel
931 mkConEntryPtr con rep
933 StaticRep _ _ _ -> mkStaticConEntryLabel (dataConName con)
934 _ -> mkConEntryLabel (dataConName con)
936 name = dataConName con
938 closureLabelFromCI (MkClosureInfo name _ rep)
940 = mkStaticClosureLabel name
941 -- This case catches those pesky static closures for nullary constructors
943 closureLabelFromCI (MkClosureInfo id _ other_rep) = mkClosureLabel id
945 entryLabelFromCI :: ClosureInfo -> CLabel
946 entryLabelFromCI (MkClosureInfo id lf_info rep)
948 LFThunk _ _ _ upd_flag std_form_info -> thunkEntryLabel id std_form_info upd_flag
949 LFCon con _ -> mkConEntryPtr con rep
950 LFTuple tup _ -> mkConEntryPtr tup rep
951 other -> mkStdEntryLabel id
953 -- thunkEntryLabel is a local help function, not exported. It's used from both
954 -- entryLabelFromCI and getEntryConvention.
956 thunkEntryLabel thunk_id (ApThunk arity) is_updatable
957 = mkApEntryLabel is_updatable arity
958 thunkEntryLabel thunk_id (SelectorThunk offset) upd_flag
959 = mkSelectorEntryLabel upd_flag offset
960 thunkEntryLabel thunk_id _ is_updatable
961 = mkStdEntryLabel thunk_id
965 allocProfilingMsg :: ClosureInfo -> FAST_STRING
967 allocProfilingMsg (MkClosureInfo _ lf_info _)
969 LFReEntrant _ _ _ _ -> SLIT("TICK_ALLOC_FUN")
970 LFCon _ _ -> SLIT("TICK_ALLOC_CON")
971 LFTuple _ _ -> SLIT("TICK_ALLOC_CON")
972 LFThunk _ _ _ _ _ -> SLIT("TICK_ALLOC_THK")
973 LFBlackHole -> SLIT("TICK_ALLOC_BH")
974 LFImported -> panic "TICK_ALLOC_IMP"
977 We need a black-hole closure info to pass to @allocDynClosure@ when we
978 want to allocate the black hole on entry to a CAF.
981 blackHoleClosureInfo (MkClosureInfo name _ _)
982 = MkClosureInfo name LFBlackHole BlackHoleRep
985 %************************************************************************
987 \subsection[ClosureInfo-Profiling-funs]{Misc functions about for profiling info.}
989 %************************************************************************
991 Profiling requires two pieces of information to be determined for
992 each closure's info table --- description and type.
994 The description is stored directly in the @CClosureInfoTable@ when the
997 The type is determined from the type information stored with the @Id@
998 in the closure info using @closureTypeDescr@.
1001 closureTypeDescr :: ClosureInfo -> String
1002 closureTypeDescr (MkClosureInfo name (LFThunk ty _ _ _ _) _)
1003 = getTyDescription ty
1004 closureTypeDescr (MkClosureInfo name (LFReEntrant ty _ _ _) _)
1005 = getTyDescription ty
1006 closureTypeDescr (MkClosureInfo name lf _)
1007 = showSDoc (ppr name)