summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2019-07-26 17:24:40 -0400
committerBen Gamari <ben@smart-cactus.org>2019-10-07 10:50:12 -0400
commit347afb7732da10553c6cef3283bde8e386afadfd (patch)
tree39f1625bc0858b533ebbbc8baace1d92fcae4a14
parent57e564e51005d7fe9de9b4abb5d2ced572d1dcc0 (diff)
downloadhaskell-wip/split-out-rtsconfig.tar.gz
Introduce smaller RTS entrypointwip/split-out-rtsconfig
As described in Note [Simple main], this is an attempt to pick off some low-hanging fruit in the time necessary to link executables. Specifically we try to minimize the amount of work necessary to compile C stub produced when linking an executable. On my machine the time necessary to compile this stub from from more than 60ms to less than 20ms. This cost was originally noted in #16822.
-rw-r--r--compiler/main/SysTools/ExtraObj.hs11
-rw-r--r--includes/Rts.h1
-rw-r--r--includes/RtsAPI.h9
-rw-r--r--includes/rts/SimpleMain.h38
-rw-r--r--rts/RtsMain.c32
-rw-r--r--rts/rts.cabal.in1
6 files changed, 79 insertions, 13 deletions
diff --git a/compiler/main/SysTools/ExtraObj.hs b/compiler/main/SysTools/ExtraObj.hs
index c930389c95..b62c5d258e 100644
--- a/compiler/main/SysTools/ExtraObj.hs
+++ b/compiler/main/SysTools/ExtraObj.hs
@@ -93,18 +93,18 @@ mkExtraObjToLinkIntoBinary dflags = do
_ -> exeMain
exeMain = vcat [
- text "#include \"Rts.h\"",
+ text "#include \"rts/SimpleMain.h\"",
text "extern StgClosure ZCMain_main_closure;",
text "int main(int argc, char *argv[])",
char '{',
- text " RtsConfig __conf = defaultRtsConfig;",
+ text " RtsSimpleConfig __conf;",
text " __conf.rts_opts_enabled = "
<> text (show (rtsOptsEnabled dflags)) <> semi,
text " __conf.rts_opts_suggestions = "
<> text (if rtsOptsSuggestions dflags
then "true"
else "false") <> semi,
- text "__conf.keep_cafs = "
+ text " __conf.keep_cafs = "
<> text (if gopt Opt_KeepCAFs dflags
then "true"
else "false") <> semi,
@@ -112,8 +112,9 @@ mkExtraObjToLinkIntoBinary dflags = do
Nothing -> Outputable.empty
Just opts -> text " __conf.rts_opts= " <>
text (show opts) <> semi,
- text " __conf.rts_hs_main = true;",
- text " return hs_main(argc,argv,&ZCMain_main_closure,__conf);",
+ -- N.B. this does not return; hs_main() rather exit()s.
+ text " hs_simple_main(argc,argv,&ZCMain_main_closure,__conf);",
+ text " return 0;",
char '}',
char '\n' -- final newline, to keep gcc happy
]
diff --git a/includes/Rts.h b/includes/Rts.h
index 0fae58956d..b0654d7fa8 100644
--- a/includes/Rts.h
+++ b/includes/Rts.h
@@ -218,6 +218,7 @@ void _assertFail(const char *filename, unsigned int linenum)
#include "rts/Utils.h"
#include "rts/PrimFloat.h"
#include "rts/Main.h"
+#include "rts/SimpleMain.h"
#include "rts/Profiling.h"
#include "rts/StaticPtrTable.h"
#include "rts/Libdw.h"
diff --git a/includes/RtsAPI.h b/includes/RtsAPI.h
index a9afab8a5c..5f75e54381 100644
--- a/includes/RtsAPI.h
+++ b/includes/RtsAPI.h
@@ -16,6 +16,7 @@ extern "C" {
#endif
#include "HsFFI.h"
+#include "rts/SimpleMain.h" // For RtsOptsEnabledEnum
#include "rts/Time.h"
#include "rts/EventLogWriter.h"
@@ -51,14 +52,6 @@ typedef struct CapabilityPublic_ {
RTS configuration settings, for passing to hs_init_ghc()
------------------------------------------------------------------------- */
-typedef enum {
- RtsOptsNone, // +RTS causes an error
- RtsOptsIgnore, // Ignore command line arguments
- RtsOptsIgnoreAll, // Ignore command line and Environment arguments
- RtsOptsSafeOnly, // safe RTS options allowed; others cause an error
- RtsOptsAll // all RTS options allowed
- } RtsOptsEnabledEnum;
-
struct GCDetails_;
// The RtsConfig struct is passed (by value) to hs_init_ghc(). The
diff --git a/includes/rts/SimpleMain.h b/includes/rts/SimpleMain.h
new file mode 100644
index 0000000000..5d7fdca826
--- /dev/null
+++ b/includes/rts/SimpleMain.h
@@ -0,0 +1,38 @@
+/* -----------------------------------------------------------------------------
+ *
+ * (c) The GHC Team, 2009
+ *
+ * Reduced-functionality entry point for standalone Haskell programs.
+ *
+ * See Note [Simple main] in RtsMain.c.
+ * ---------------------------------------------------------------------------*/
+
+#pragma once
+
+#include <stdbool.h>
+
+struct StgClosure_;
+
+typedef enum {
+ RtsOptsNone, // +RTS causes an error
+ RtsOptsIgnore, // Ignore command line arguments
+ RtsOptsIgnoreAll, // Ignore command line and Environment arguments
+ RtsOptsSafeOnly, // safe RTS options allowed; others cause an error
+ RtsOptsAll // all RTS options allowed
+ } RtsOptsEnabledEnum;
+
+struct RtsSimpleConfig {
+ RtsOptsEnabledEnum rts_opts_enabled;
+ bool rts_opts_suggestions;
+ bool keep_cafs;
+ const char *rts_opts;
+};
+
+#if defined(__GNUC__)
+// N.B. Don't use GNU_ATTRIBUTE to avoid dependency on Stg.h.
+__attribute__((noreturn))
+#endif
+void hs_simple_main (int argc, char *argv[],
+ struct StgClosure_ *main_closure,
+ struct RtsSimpleConfig rts_config);
+
diff --git a/rts/RtsMain.c b/rts/RtsMain.c
index 21b8577cca..badf118eed 100644
--- a/rts/RtsMain.c
+++ b/rts/RtsMain.c
@@ -99,4 +99,36 @@ int hs_main ( int argc, char *argv[], // program args
shutdownHaskellAndExit(exit_status, 0 /* !fastExit */);
// No code beyond this point. Dead code elimination will remove it
}
+
+/*
+ * Note [Simple main]
+ * ~~~~~~~~~~~~~~~~~~
+ *
+ * When GHC compiles a Haskell executable it generates a small C stub which
+ * calls into the runtime system. Previously this stub would include Rts.h,
+ * pulling in dozens upon dozens of GHC and system header files. Compiling the
+ * ten line stub would consequently produce nearly 6000 lstat calls and take
+ * several dozen milliseconds. In a build with lots of executables this can
+ * really add up.
+ *
+ * Consequently we now expose hs_simple_main, which is declared in
+ * includes/SimpleMain.h and can be compiled with a minimal set of headers.
+ *
+ * N.B. this does not return; hs_main() rather exit()s.
+ */
+
+void hs_simple_main (int argc,
+ char *argv[],
+ struct StgClosure_ *main_closure,
+ struct RtsSimpleConfig rts_config)
+{
+ RtsConfig conf = defaultRtsConfig;
+ conf.rts_opts_enabled = rts_config.rts_opts_enabled;
+ conf.rts_opts_suggestions = rts_config.rts_opts_suggestions;
+ conf.keep_cafs = rts_config.keep_cafs;
+ conf.rts_opts = rts_config.rts_opts;
+ conf.rts_hs_main = true;
+ hs_main(argc, argv, main_closure, conf);
+}
+
# endif /* BATCH_MODE */
diff --git a/rts/rts.cabal.in b/rts/rts.cabal.in
index 674566c0ad..1c27255fde 100644
--- a/rts/rts.cabal.in
+++ b/rts/rts.cabal.in
@@ -138,6 +138,7 @@ library
rts/LibdwPool.h
rts/Linker.h
rts/Main.h
+ rts/SimpleMain.h
rts/Messages.h
rts/OSThreads.h
rts/Parallel.h