diff options
author | Ben Gamari <ben@smart-cactus.org> | 2021-09-23 20:13:42 -0400 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2021-12-01 03:08:07 -0500 |
commit | 4acfa0db473fa04a434c38b44da195d5c4455956 (patch) | |
tree | cc4c5db59f69b4ebe2b44ab4fb2a9c08d6aa2487 | |
parent | c7613493e637718492f03c2f9a020198244a7b18 (diff) | |
download | haskell-4acfa0db473fa04a434c38b44da195d5c4455956.tar.gz |
rts: Refactor SRT representation selection
The goal here is to make the SRT selection logic a bit clearer and allow
configurations which we currently don't support (e.g. using a full word
in the info table even when TNTC is used).
-rw-r--r-- | compiler/GHC/Cmm/Info.hs | 3 | ||||
-rw-r--r-- | compiler/GHC/Cmm/Info/Build.hs | 37 | ||||
-rw-r--r-- | rts/include/rts/storage/InfoTables.h | 64 | ||||
-rw-r--r-- | utils/deriveConstants/Main.hs | 5 |
4 files changed, 72 insertions, 37 deletions
diff --git a/compiler/GHC/Cmm/Info.hs b/compiler/GHC/Cmm/Info.hs index d0397c8172..06100aa176 100644 --- a/compiler/GHC/Cmm/Info.hs +++ b/compiler/GHC/Cmm/Info.hs @@ -283,8 +283,7 @@ mkSRTLit platform _ (Just lbl) = ([CmmLabel lbl], CmmInt 1 (halfWordWidth platfo -- See the section "Referring to an SRT from the info table" in -- Note [SRTs] in "GHC.Cmm.Info.Build" inlineSRT :: Platform -> Bool -inlineSRT platform = platformArch platform == ArchX86_64 - && platformTablesNextToCode platform +inlineSRT = pc_USE_INLINE_SRT_FIELD . platformConstants ------------------------------------------------------------------------- -- diff --git a/compiler/GHC/Cmm/Info/Build.hs b/compiler/GHC/Cmm/Info/Build.hs index ab0c32996e..191415274e 100644 --- a/compiler/GHC/Cmm/Info/Build.hs +++ b/compiler/GHC/Cmm/Info/Build.hs @@ -55,6 +55,7 @@ import Data.List (unzip4) import GHC.Types.Name.Set {- Note [SRTs] + ~~~~~~~~~~~ SRTs are the mechanism by which the garbage collector can determine the live CAFs in the program. @@ -112,9 +113,15 @@ The following things have SRTs: - Static thunks (THUNK), ie. CAFs - Continuations (RET_SMALL, etc.) -In each case, the info table points to the SRT. +In each case, the info table points to the SRT. There are three ways which we +may encode the location of the SRT in the info table, described below. -- info->srt is zero if there's no SRT, otherwise: +USE_SRT_OFFSET +-------------- +In this case we use the info->srt to encode whether or not there is an +SRT and if so encode the offset to its location in info->f.srt_offset: + +- info->srt is 0 if there's no SRT, otherwise, - info->srt == 1 and info->f.srt_offset points to the SRT e.g. for a FUN with an SRT: @@ -128,11 +135,26 @@ StgStdInfoTable +------+ info->type | ... | |------| -On x86_64, we optimise the info table representation further. The -offset to the SRT can be stored in 32 bits (all code lives within a -2GB region in x86_64's small memory model), so we can save a word in -the info table by storing the srt_offset in the srt field, which is -half a word. +USE_SRT_POINTER +--------------- +When tables-next-to-code isn't in use we rather encode an absolute pointer to +the SRT in info->srt. e.g. for a FUN with an SRT: + +StgFunInfoTable +------+ + info->f.srt_offset | ------------> pointer to SRT object +StgStdInfoTable +------+ + info->layout.ptrs | ... | + info->layout.nptrs | ... | + info->srt | 1 | + info->type | ... | + |------| +USE_INLINE_SRT_FIELD +-------------------- +When using TNTC on x86_64 (and other platforms using the small memory model), +we optimise the info table representation further. The offset to the SRT can +be stored in 32 bits (all code lives within a 2GB region in x86_64's small +memory model), so we can save a word in the info table by storing the +srt_offset in the srt field, which is half a word. On x86_64 with TABLES_NEXT_TO_CODE (except on MachO, due to #15169): @@ -368,6 +390,7 @@ Here we could use C = {A} and therefore [Inline] C = A. -- --------------------------------------------------------------------- {- Note [Invalid optimisation: shortcutting] + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ You might think that if we have something like diff --git a/rts/include/rts/storage/InfoTables.h b/rts/include/rts/storage/InfoTables.h index b97e12982b..55d9ad6542 100644 --- a/rts/include/rts/storage/InfoTables.h +++ b/rts/include/rts/storage/InfoTables.h @@ -16,6 +16,7 @@ position-independent code. Note [x86-64-relative] + ~~~~~~~~~~~~~~~~~~~~~~ There is a complication on the x86_64 platform, where pointers are 64 bits, but the tools don't support 64-bit relative relocations. However, the default memory model (small) ensures that all symbols @@ -153,13 +154,26 @@ typedef union { } StgClosureInfo; -#if defined(x86_64_HOST_ARCH) && defined(TABLES_NEXT_TO_CODE) -// On x86_64 we can fit a pointer offset in half a word, so put the SRT offset -// in the info->srt field directly. +#if defined(x86_64_HOST_ARCH) +#define SMALL_MEMORY_MODEL +#endif + +// This is where we choose how to represent the SRT location in the info +// table. See the section "Referring to an SRT from the info table" in +// Note [SRTs] in GHC.Cmm.Info.Build. // -// See the section "Referring to an SRT from the info table" in -// Note [SRTs] in CmmBuildInfoTables.hs +// Specifically we define one of the following: +#if WORD_SIZE_IN_BITS == 64 && defined(SMALL_MEMORY_MODEL) && defined(TABLES_NEXT_TO_CODE) +// On 64-bit platforms using the small memory model we can fit a pointer +// offset in half a word, so put the SRT offset in the info->srt field +// directly. #define USE_INLINE_SRT_FIELD +#elif defined(TABLES_NEXT_TO_CODE) +// Otherwise use the srt_offset field... +#define USE_SRT_OFFSET +#else +// If not using tables-next-to-code then simply use a full pointer... +#define USE_SRT_POINTER #endif #if defined(USE_INLINE_SRT_FIELD) @@ -219,14 +233,16 @@ typedef struct StgInfoTable_ { -------------------------------------------------------------------------- */ /* - Note [Encoding static reference tables] - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - As static reference tables appear frequently in code, we use a special - compact encoding for the common case of a module defining only a few CAFs: We - produce one table containing a list of CAFs in the module and then include a - bitmap in each info table describing which entries of this table the closure - references. + * Note [Encoding static reference tables] + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + * As static reference tables appear frequently in code, we use a special + * compact encoding for the common case of a module defining only a few CAFs: We + * produce one table containing a list of CAFs in the module and then include a + * bitmap in each info table describing which entries of this table the closure + * references. + * + * See Note [SRTs] in "GHC.Cmm.Info.Build". */ typedef struct StgFunInfoExtraRev_ { @@ -275,8 +291,8 @@ extern const StgWord stg_arg_bitmaps[]; */ typedef struct { -#if defined(TABLES_NEXT_TO_CODE) -#if !defined(USE_INLINE_SRT_FIELD) +#if !defined(USE_SRT_POINTER) +#if defined(USE_SRT_OFFSET) OFFSET_FIELD(srt_offset); /* offset to the SRT closure */ #endif StgInfoTable i; @@ -296,8 +312,8 @@ typedef struct { */ typedef struct StgThunkInfoTable_ { -#if defined(TABLES_NEXT_TO_CODE) -#if !defined(USE_INLINE_SRT_FIELD) +#if !defined(USE_SRT_POINTER) +#if defined(USE_SRT_OFFSET) OFFSET_FIELD(srt_offset); /* offset to the SRT closure */ #endif StgInfoTable i; @@ -337,15 +353,13 @@ typedef struct StgConInfoTable_ { * GET_SRT(info) * info must be a Stg[Ret|Thunk]InfoTable* (an info table that has a SRT) */ -#if defined(TABLES_NEXT_TO_CODE) -#if defined(x86_64_HOST_ARCH) +#if defined(USE_INLINE_SRT_FIELD) #define GET_SRT(info) \ ((StgClosure*) (((StgWord) ((info)+1)) + (info)->i.srt)) -#else +#elif defined(USE_SRT_OFFSET) #define GET_SRT(info) \ ((StgClosure*) (((StgWord) ((info)+1)) + (info)->srt_offset)) -#endif -#else // !TABLES_NEXT_TO_CODE +#else #define GET_SRT(info) ((info)->srt) #endif @@ -364,14 +378,12 @@ typedef struct StgConInfoTable_ { * GET_FUN_SRT(info) * info must be a StgFunInfoTable* */ -#if defined(TABLES_NEXT_TO_CODE) -#if defined(x86_64_HOST_ARCH) +#if defined(USE_INLINE_SRT_FIELD) #define GET_FUN_SRT(info) \ ((StgClosure*) (((StgWord) ((info)+1)) + (info)->i.srt)) -#else +#elif defined(USE_SRT_OFFSET) #define GET_FUN_SRT(info) \ ((StgClosure*) (((StgWord) ((info)+1)) + (info)->f.srt_offset)) -#endif #else #define GET_FUN_SRT(info) ((info)->f.srt) #endif diff --git a/utils/deriveConstants/Main.hs b/utils/deriveConstants/Main.hs index f5ccad3641..7121e74245 100644 --- a/utils/deriveConstants/Main.hs +++ b/utils/deriveConstants/Main.hs @@ -167,8 +167,8 @@ constantWord w name expr = [(w, GetWord name (Fst (CExpr expr)))] constantNatural :: Where -> Name -> String -> Wanteds constantNatural w name expr = [(w, GetNatural name (Fst (CExpr expr)))] --- constantBool :: Where -> Name -> String -> Wanteds --- constantBool w name expr = [(w, GetBool name (Fst (CPPExpr expr)))] +constantBool :: Where -> Name -> String -> Wanteds +constantBool w name expr = [(w, GetBool name (Fst (CPPExpr expr)))] fieldOffset :: Where -> String -> String -> Wanteds fieldOffset w theType theField = fieldOffset_ w nameBase theType theField @@ -673,6 +673,7 @@ wanteds os = concat ,constantNatural Haskell "ILDV_CREATE_MASK" "LDV_CREATE_MASK" ,constantNatural Haskell "ILDV_STATE_CREATE" "LDV_STATE_CREATE" ,constantNatural Haskell "ILDV_STATE_USE" "LDV_STATE_USE" + ,constantBool Haskell "USE_INLINE_SRT_FIELD" "defined(USE_INLINE_SRT_FIELD)" ] getWanted :: Bool -> String -> FilePath -> FilePath -> [String] -> FilePath -> Maybe FilePath |