summaryrefslogtreecommitdiff
path: root/rts/include
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2022-08-18 20:03:15 -0400
committerMarge Bot <ben+marge-bot@smart-cactus.org>2022-10-11 23:45:10 -0400
commit6b0d2022699d3d8b446d024ee837c0d07e2c1aa0 (patch)
tree3981c27bcbfd7ac99eb5c0b46cea5090d8a27ec9 /rts/include
parent866c736ef29a07c6f3aa68063ef98ee0ecea12f3 (diff)
downloadhaskell-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.h2
-rw-r--r--rts/include/Rts.h9
-rw-r--r--rts/include/rts/IPE.h57
-rw-r--r--rts/include/stg/SMP.h17
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