diff options
author | Ben Gamari <ben@smart-cactus.org> | 2022-08-18 20:03:15 -0400 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2022-10-11 23:45:10 -0400 |
commit | 6b0d2022699d3d8b446d024ee837c0d07e2c1aa0 (patch) | |
tree | 3981c27bcbfd7ac99eb5c0b46cea5090d8a27ec9 /rts/include | |
parent | 866c736ef29a07c6f3aa68063ef98ee0ecea12f3 (diff) | |
download | haskell-6b0d2022699d3d8b446d024ee837c0d07e2c1aa0.tar.gz |
Refactor IPE initialization
Here we refactor the representation of info table provenance information
in object code to significantly reduce its size and link-time impact.
Specifically, we deduplicate strings and represent them as 32-bit
offsets into a common string table.
In addition, we rework the registration logic to eliminate allocation
from the registration path, which is run from a static initializer where
things like allocation are technically undefined behavior (although it
did previously seem to work). For similar reasons we eliminate lock
usage from registration path, instead relying on atomic CAS.
Closes #22077.
Diffstat (limited to 'rts/include')
-rw-r--r-- | rts/include/Cmm.h | 2 | ||||
-rw-r--r-- | rts/include/Rts.h | 9 | ||||
-rw-r--r-- | rts/include/rts/IPE.h | 57 | ||||
-rw-r--r-- | rts/include/stg/SMP.h | 17 |
4 files changed, 77 insertions, 8 deletions
diff --git a/rts/include/Cmm.h b/rts/include/Cmm.h index 07301bf602..932bfb903a 100644 --- a/rts/include/Cmm.h +++ b/rts/include/Cmm.h @@ -249,6 +249,8 @@ #define IF_DEBUG(c,s) /* nothing */ #endif +#define GHC_STATIC_ASSERT(x) static_assert(x) + /* ----------------------------------------------------------------------------- Entering diff --git a/rts/include/Rts.h b/rts/include/Rts.h index 2399f8ce7f..b9874721ce 100644 --- a/rts/include/Rts.h +++ b/rts/include/Rts.h @@ -29,6 +29,9 @@ extern "C" { #include <windows.h> #endif +/* For _Static_assert */ +#include <assert.h> + #if !defined(IN_STG_CODE) #define IN_STG_CODE 0 #endif @@ -163,6 +166,12 @@ void _warnFail(const char *filename, unsigned int linenum); do { (void) sizeof(predicate); } while(0) #endif /* DEBUG */ +#if __STDC_VERSION__ >= 201112L +#define GHC_STATIC_ASSERT(x, msg) static_assert((x), msg) +#else +#define GHC_STATIC_ASSERT(x, msg) +#endif + /* * Use this on the RHS of macros which expand to nothing * to make sure that the macro can be used in a context which diff --git a/rts/include/rts/IPE.h b/rts/include/rts/IPE.h index 0cfe3e2fb3..f8495cd30e 100644 --- a/rts/include/rts/IPE.h +++ b/rts/include/rts/IPE.h @@ -14,18 +14,59 @@ #pragma once typedef struct InfoProv_ { - char *table_name; - char *closure_desc; - char *ty_desc; - char *label; - char *module; - char *srcloc; + const char *table_name; + const char *closure_desc; + const char *ty_desc; + const char *label; + const char *module; + const char *srcloc; } InfoProv; typedef struct InfoProvEnt_ { - StgInfoTable *info; + const StgInfoTable *info; InfoProv prov; } InfoProvEnt; -void registerInfoProvList(InfoProvEnt **cc_list); + +/* + * On-disk representation + */ + +/* + * A byte offset into the string table. + * We use offsets rather than pointers as: + * + * a. they are smaller than pointers on 64-bit platforms + * b. they are easier on the linker since they do not need + * to be relocated + */ +typedef uint32_t StringIdx; + +// This is the provenance representation that we emit to +// object code (see +// GHC.GHC.StgToCmm.InfoTableProv.emitIpeBufferListNode). +// +// The size of this must be a multiple of the word size +// to ensure correct packing. +typedef struct { + const StgInfoTable *info; + StringIdx table_name; + StringIdx closure_desc; + StringIdx ty_desc; + StringIdx label; + StringIdx module_name; + StringIdx srcloc; +} IpeBufferEntry; + +GHC_STATIC_ASSERT(sizeof(IpeBufferEntry) % (WORD_SIZE_IN_BITS / 8) == 0, "sizeof(IpeBufferEntry) must be a multiple of the word size"); + +typedef struct IpeBufferListNode_ { + struct IpeBufferListNode_ *next; + // Everything below is read-only and generated by the codegen + const char *string_table; + StgWord count; + IpeBufferEntry entries[]; +} IpeBufferListNode; + +void registerInfoProvList(IpeBufferListNode *node); InfoProvEnt *lookupIPE(const StgInfoTable *info); diff --git a/rts/include/stg/SMP.h b/rts/include/stg/SMP.h index 1bb6ca06a0..b8f72a1248 100644 --- a/rts/include/stg/SMP.h +++ b/rts/include/stg/SMP.h @@ -568,3 +568,20 @@ atomic_dec(StgVolatilePtr p) #define VOLATILE_LOAD(p) ((StgWord)*((StgWord*)(p))) #endif /* !THREADED_RTS */ + +/* Helpers implemented in terms of the above */ +#if !IN_STG_CODE || IN_STGCRUN + +INLINE_HEADER void * +xchg_ptr(void **p, void *w) +{ + return (void *) xchg((StgPtr) p, (StgWord) w); +} + +INLINE_HEADER void * +cas_ptr(volatile void **p, void *o, void *n) +{ + return (void *) cas((StgVolatilePtr) p, (StgWord) o, (StgWord) n); +} + +#endif |