Commit 838b6903 authored by Simon Marlow's avatar Simon Marlow

Merge FUN_STATIC closure with its SRT

Summary:
The idea here is to save a little code size and some work in the GC,
by collapsing FUN_STATIC closures and their SRTs.

This is (4) in a series; see D4632 for more details.

There's a tradeoff here: more complexity in the compiler in exchange
for a modest code size reduction (probably around 0.5%).

Results:
* GHC binary itself (statically linked) is 1% smaller
* -0.2% binary sizes in nofib (-0.5% module sizes)

Full nofib results comparing D4634 with this: P177 (ignore runtimes,
these aren't stable on my laptop)

Test Plan: validate, nofib

Reviewers: bgamari, niteria, simonpj, erikd

Subscribers: thomie, carter

Differential Revision: https://phabricator.haskell.org/D4637
parent 2b0918c9
......@@ -27,6 +27,8 @@ module Cmm (
import GhcPrelude
import Id
import CostCentre
import CLabel
import BlockId
import CmmNode
......@@ -137,7 +139,10 @@ data CmmInfoTable
cit_lbl :: CLabel, -- Info table label
cit_rep :: SMRep,
cit_prof :: ProfilingInfo,
cit_srt :: Maybe CLabel -- empty, or a closure address
cit_srt :: Maybe CLabel, -- empty, or a closure address
cit_clo :: Maybe (Id, CostCentreStack)
-- Just (id,ccs) <=> build a static closure later
-- Nothing <=> don't build a static closure
}
data ProfilingInfo
......
This diff is collapsed.
......@@ -63,7 +63,8 @@ mkEmptyContInfoTable info_lbl
= CmmInfoTable { cit_lbl = info_lbl
, cit_rep = mkStackRep []
, cit_prof = NoProfilingInfo
, cit_srt = Nothing }
, cit_srt = Nothing
, cit_clo = Nothing }
cmmToRawCmm :: DynFlags -> Stream IO CmmGroup ()
-> IO (Stream IO RawCmmGroup ())
......
......@@ -472,7 +472,7 @@ info :: { CmmParse (CLabel, Maybe CmmInfoTable, [LocalReg]) }
return (mkCmmEntryLabel pkg $3,
Just $ CmmInfoTable { cit_lbl = mkCmmInfoLabel pkg $3
, cit_rep = rep
, cit_prof = prof, cit_srt = Nothing },
, cit_prof = prof, cit_srt = Nothing, cit_clo = Nothing },
[]) }
| 'INFO_TABLE_FUN' '(' NAME ',' INT ',' INT ',' INT ',' STRING ',' STRING ',' INT ')'
......@@ -488,7 +488,7 @@ info :: { CmmParse (CLabel, Maybe CmmInfoTable, [LocalReg]) }
return (mkCmmEntryLabel pkg $3,
Just $ CmmInfoTable { cit_lbl = mkCmmInfoLabel pkg $3
, cit_rep = rep
, cit_prof = prof, cit_srt = Nothing },
, cit_prof = prof, cit_srt = Nothing, cit_clo = Nothing },
[]) }
-- we leave most of the fields zero here. This is only used
-- to generate the BCO info table in the RTS at the moment.
......@@ -506,7 +506,7 @@ info :: { CmmParse (CLabel, Maybe CmmInfoTable, [LocalReg]) }
return (mkCmmEntryLabel pkg $3,
Just $ CmmInfoTable { cit_lbl = mkCmmInfoLabel pkg $3
, cit_rep = rep
, cit_prof = prof, cit_srt = Nothing },
, cit_prof = prof, cit_srt = Nothing,cit_clo = Nothing },
[]) }
-- If profiling is on, this string gets duplicated,
......@@ -523,7 +523,7 @@ info :: { CmmParse (CLabel, Maybe CmmInfoTable, [LocalReg]) }
return (mkCmmEntryLabel pkg $3,
Just $ CmmInfoTable { cit_lbl = mkCmmInfoLabel pkg $3
, cit_rep = rep
, cit_prof = prof, cit_srt = Nothing },
, cit_prof = prof, cit_srt = Nothing, cit_clo = Nothing },
[]) }
| 'INFO_TABLE_RET' '(' NAME ',' INT ')'
......@@ -534,7 +534,7 @@ info :: { CmmParse (CLabel, Maybe CmmInfoTable, [LocalReg]) }
return (mkCmmRetLabel pkg $3,
Just $ CmmInfoTable { cit_lbl = mkCmmRetInfoLabel pkg $3
, cit_rep = rep
, cit_prof = prof, cit_srt = Nothing },
, cit_prof = prof, cit_srt = Nothing, cit_clo = Nothing },
[]) }
| 'INFO_TABLE_RET' '(' NAME ',' INT ',' formals0 ')'
......@@ -549,7 +549,7 @@ info :: { CmmParse (CLabel, Maybe CmmInfoTable, [LocalReg]) }
return (mkCmmRetLabel pkg $3,
Just $ CmmInfoTable { cit_lbl = mkCmmRetInfoLabel pkg $3
, cit_rep = rep
, cit_prof = prof, cit_srt = Nothing },
, cit_prof = prof, cit_srt = Nothing, cit_clo = Nothing },
live) }
body :: { CmmParse () }
......
......@@ -95,19 +95,17 @@ cgTopRhsClosure dflags rec id ccs _ upd_flag args body =
emitDataLits closure_label closure_rep
return ()
gen_code dflags lf_info closure_label
= do { -- LAY OUT THE OBJECT
let name = idName id
gen_code dflags lf_info _closure_label
= do { let name = idName id
; mod_name <- getModuleName
; let descr = closureDescription dflags mod_name name
closure_info = mkClosureInfo dflags True id lf_info 0 0 descr
caffy = idCafInfo id
info_tbl = mkCmmInfo closure_info -- XXX short-cut
closure_rep = mkStaticClosureFields dflags info_tbl ccs caffy []
-- We don't generate the static closure here, because we might
-- want to add references to static closures to it later. The
-- static closure is generated by CmmBuildInfoTables.updInfoSRTs,
-- See Note [SRTs], specifically the [FUN] optimisation.
-- BUILD THE OBJECT, AND GENERATE INFO TABLE (IF NECESSARY)
; emitDataLits closure_label closure_rep
; let fv_details :: [(NonVoid Id, ByteOff)]
header = if isLFThunk lf_info then ThunkHeader else StdHeader
(_, _, fv_details) = mkVirtHeapOffsets dflags header []
......@@ -367,7 +365,7 @@ mkRhsClosure dflags bndr cc _ fvs upd_flag args body
; let use_cc = cccsExpr; blame_cc = cccsExpr
; emit (mkComment $ mkFastString "calling allocDynClosure")
; let toVarArg (NonVoid a, off) = (NonVoid (StgVarArg a), off)
; let info_tbl = mkCmmInfo closure_info
; let info_tbl = mkCmmInfo closure_info bndr currentCCS
; hp_plus_n <- allocDynClosure (Just bndr) info_tbl lf_info use_cc blame_cc
(map toVarArg fv_details)
......@@ -407,7 +405,7 @@ cgRhsStdThunk bndr lf_info payload
-- BUILD THE OBJECT
; let info_tbl = mkCmmInfo closure_info
; let info_tbl = mkCmmInfo closure_info bndr currentCCS
; hp_plus_n <- allocDynClosure (Just bndr) info_tbl lf_info
use_cc blame_cc payload_w_offsets
......@@ -463,7 +461,7 @@ closureCodeBody top_lvl bndr cl_info cc _args arity body fv_details
\(_, node, _) -> thunkCode cl_info fv_details cc node arity body
where
lf_info = closureLFInfo cl_info
info_tbl = mkCmmInfo cl_info
info_tbl = mkCmmInfo cl_info bndr cc
closureCodeBody top_lvl bndr cl_info cc args arity body fv_details
= -- Note: args may be [], if all args are Void
......@@ -474,7 +472,7 @@ closureCodeBody top_lvl bndr cl_info cc args arity body fv_details
; let
lf_info = closureLFInfo cl_info
info_tbl = mkCmmInfo cl_info
info_tbl = mkCmmInfo cl_info bndr cc
-- Emit the main entry code
; emitClosureProcAndInfoTable top_lvl bndr lf_info info_tbl args $
......
......@@ -73,6 +73,7 @@ import SMRep
import Cmm
import PprCmmExpr()
import CostCentre
import BlockId
import CLabel
import Id
......@@ -750,12 +751,15 @@ data ClosureInfo
}
-- | Convert from 'ClosureInfo' to 'CmmInfoTable'.
mkCmmInfo :: ClosureInfo -> CmmInfoTable
mkCmmInfo ClosureInfo {..}
mkCmmInfo :: ClosureInfo -> Id -> CostCentreStack -> CmmInfoTable
mkCmmInfo ClosureInfo {..} id ccs
= CmmInfoTable { cit_lbl = closureInfoLabel
, cit_rep = closureSMRep
, cit_prof = closureProf
, cit_srt = Nothing }
, cit_srt = Nothing
, cit_clo = if isStaticRep closureSMRep
then Just (id,ccs)
else Nothing }
--------------------------------------
-- Building ClosureInfos
......@@ -1040,7 +1044,8 @@ mkDataConInfoTable dflags data_con is_static ptr_wds nonptr_wds
= CmmInfoTable { cit_lbl = info_lbl
, cit_rep = sm_rep
, cit_prof = prof
, cit_srt = Nothing }
, cit_srt = Nothing
, cit_clo = Nothing }
where
name = dataConName data_con
info_lbl = mkConInfoTableLabel name NoCafRefs
......@@ -1063,14 +1068,16 @@ cafBlackHoleInfoTable
= CmmInfoTable { cit_lbl = mkCAFBlackHoleInfoTableLabel
, cit_rep = blackHoleRep
, cit_prof = NoProfilingInfo
, cit_srt = Nothing }
, cit_srt = Nothing
, cit_clo = Nothing }
indStaticInfoTable :: CmmInfoTable
indStaticInfoTable
= CmmInfoTable { cit_lbl = mkIndStaticInfoLabel
, cit_rep = indStaticRep
, cit_prof = NoProfilingInfo
, cit_srt = Nothing }
, cit_srt = Nothing
, cit_clo = Nothing }
staticClosureNeedsLink :: Bool -> CmmInfoTable -> Bool
-- A static closure needs a link field to aid the GC when traversing
......
......@@ -172,7 +172,6 @@ INLINE_HEADER StgHalfWord GET_TAG(const StgClosure *con)
-------------------------------------------------------------------------- */
/* These are hard-coded. */
#define FUN_STATIC_LINK(p) (&(p)->payload[0])
#define THUNK_STATIC_LINK(p) (&(p)->payload[1])
#define IND_STATIC_LINK(p) (&(p)->payload[1])
......@@ -182,8 +181,6 @@ STATIC_LINK(const StgInfoTable *info, StgClosure *p)
switch (info->type) {
case THUNK_STATIC:
return THUNK_STATIC_LINK(p);
case FUN_STATIC:
return FUN_STATIC_LINK(p);
case IND_STATIC:
return IND_STATIC_LINK(p);
default:
......
......@@ -1908,7 +1908,7 @@ resetStaticObjectForRetainerProfiling( StgClosure *static_objects )
break;
case FUN_STATIC:
maybeInitRetainerSet(p);
p = (StgClosure*)*FUN_STATIC_LINK(p);
p = (StgClosure*)*STATIC_LINK(p);
break;
case CONSTR:
case CONSTR_1_0:
......
......@@ -212,7 +212,7 @@ thread_static( StgClosure* p )
p = *THUNK_STATIC_LINK(p);
continue;
case FUN_STATIC:
p = *FUN_STATIC_LINK(p);
p = *STATIC_LINK(info,p);
continue;
case CONSTR:
case CONSTR_NOCAF:
......
......@@ -542,8 +542,8 @@ loop:
return;
case FUN_STATIC:
if (info->srt != 0) {
evacuate_static_object(FUN_STATIC_LINK((StgClosure *)q), q);
if (info->srt != 0 || info->layout.payload.ptrs != 0) {
evacuate_static_object(STATIC_LINK(info,(StgClosure *)q), q);
}
return;
......
......@@ -677,7 +677,7 @@ checkStaticObjects ( StgClosure* static_objects )
break;
case FUN_STATIC:
p = *FUN_STATIC_LINK((StgClosure *)p);
p = *STATIC_LINK(info,(StgClosure *)p);
break;
case CONSTR:
......
......@@ -1722,7 +1722,9 @@ scavenge_static(void)
case FUN_STATIC:
scavenge_fun_srt(info);
break;
// fallthrough: a FUN_STATIC can also be an SRT, so it may have pointer
// fields. See Note [SRTs] in CmmBuildInfoTables, specifically the [FUN]
// optimisation.
case CONSTR:
case CONSTR_NOCAF:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment