Cheng Shao pushed to branch wip/ghci-no-simpl at Glasgow Haskell Compiler / GHC
Commits:
77deaa7a by Cheng Shao at 2025-09-14T21:29:45-04:00
hadrian: build in-tree gmp with -fvisibility=hidden
When hadrian builds in-tree gmp, it should build the shared objects
with -fvisibility=hidden. The gmp symbols are only used by bignum
logic in ghc-internal and shouldn't be exported by the ghc-internal
shared library. We should always strive to keep shared library symbol
table lean, which benefits platforms with slow dynamic linker or even
hard limits about how many symbols can be exported (e.g. macos dyld,
win32 dll and wasm dyld).
- - - - -
42a18960 by Cheng Shao at 2025-09-14T21:30:26-04:00
Revert "wasm: add brotli compression for ghci browser mode"
This reverts commit 731217ce68a1093b5f9e26a07d5bd2cdade2b352.
Benchmarks show non-negligible overhead when browser runs on the same
host, which is the majority of actual use cases.
- - - - -
e6755b9f by Cheng Shao at 2025-09-14T21:30:26-04:00
wasm: remove etag logic in ghci browser mode web server
This commit removes the etag logic in dyld script's ghci browser mode
web server. It was meant to support caching logic of wasm shared
libraries, but even if the port is manually specified to make caching
even relevant, for localhost the extra overhead around etag logic is
simply not worth it according to benchmarks.
- - - - -
e5b1ac21 by Cheng Shao at 2025-09-16T18:43:32+02:00
genprimopcode: add hls support
This commit adds hie.yaml to genprimopcode so that one can use hls to
hack on it.
- - - - -
f27a1ba9 by Cheng Shao at 2025-09-16T18:43:32+02:00
genprimopcode: ensure seq is also included in PrimopWrappers.hs
This patch changes genprimopcode and ensure seq is also included in
PrimopWrappers.hs. This is needed when bytecode calls the seq primop.
Co-authored-by: Codex
- - - - -
2287a923 by Cheng Shao at 2025-09-16T18:43:32+02:00
compiler: use proper interactiveSrcSpan instead of srcLocSpan interactiveSrcLoc
This commit makes the compiler use proper `interactiveSrcSpan` instead
of `srcLocSpan interactiveSrcLoc`, which returns a result surprisingly
not equal to `interactiveSrcSpan`! Also removes the now unused
`generatedSrcLoc` and `interactiveSrcLoc`.
- - - - -
79f4f1d1 by Cheng Shao at 2025-09-16T18:57:46+02:00
compiler: use simpleOptExpr instead of simplifyExpr in hscCompileCoreExpr
This commit makes hscCompileCoreExpr use simpleOptExpr instead of
simplifyExpr unless user specifies
-fno-unoptimized-core-for-interpreter, so to make it faster by doing
less work when compiling TH splices or ghci statements to bytecode.
-------------------------
Metric Decrease:
MultiLayerModulesTH_OneShot
-------------------------
- - - - -
9 changed files:
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Driver/Session/Inspect.hs
- compiler/GHC/Types/SrcLoc.hs
- hadrian/src/Rules/Gmp.hs
- testsuite/tests/interface-stability/ghc-prim-exports.stdout
- testsuite/tests/interface-stability/ghc-prim-exports.stdout-mingw32
- utils/genprimopcode/Main.hs
- + utils/genprimopcode/hie.yaml
- utils/jsffi/dyld.mjs
Changes:
=====================================
compiler/GHC/Driver/Main.hs
=====================================
@@ -121,6 +121,7 @@ import GHC.Driver.Errors
import GHC.Driver.Messager
import GHC.Driver.Errors.Types
import GHC.Driver.CodeOutput
+import GHC.Driver.Config
import GHC.Driver.Config.Cmm.Parser (initCmmParserConfig)
import GHC.Driver.Config.Core.Opt.Simplify ( initSimplifyExprOpts )
import GHC.Driver.Config.Core.Lint ( endPassHscEnvIO )
@@ -181,6 +182,7 @@ import GHC.Core.Utils ( exprType )
import GHC.Core.ConLike
import GHC.Core.Opt.Pipeline
import GHC.Core.Opt.Pipeline.Types ( CoreToDo (..))
+import GHC.Core.SimpleOpt
import GHC.Core.TyCon
import GHC.Core.InstEnv
import GHC.Core.FamInstEnv
@@ -253,6 +255,7 @@ import GHC.Types.TyThing
import GHC.Types.Unique.Supply (uniqFromTag)
import GHC.Types.Unique.Set
+import GHC.Utils.Exception
import GHC.Utils.Fingerprint ( Fingerprint )
import GHC.Utils.Panic
import GHC.Utils.Error
@@ -2448,8 +2451,7 @@ hscParsedStmt hsc_env stmt = runInteractiveHsc hsc_env $ do
-- It's important NOT to have package 'interactive' as thisUnitId
-- for linking, else we try to link 'main' and can't find it.
-- Whereas the linker already knows to ignore 'interactive'
- let src_span = srcLocSpan interactiveSrcLoc
- (hval,_,_) <- liftIO $ hscCompileCoreExpr hsc_env src_span ds_expr
+ (hval,_,_) <- liftIO $ hscCompileCoreExpr hsc_env interactiveSrcSpan ds_expr
return $ Just (ids, hval, fix_env)
@@ -2512,8 +2514,7 @@ hscParsedDecls hsc_env decls = runInteractiveHsc hsc_env $ do
(mkCgInteractiveGuts tidy_cg)
iNTERACTIVELoc
- let src_span = srcLocSpan interactiveSrcLoc
- _ <- liftIO $ loadDecls interp hsc_env src_span linkable
+ _ <- liftIO $ loadDecls interp hsc_env interactiveSrcSpan linkable
{- Load static pointer table entries -}
liftIO $ hscAddSptEntries hsc_env (cg_spt_entries tidy_cg)
@@ -2710,17 +2711,44 @@ hscCompileCoreExpr hsc_env loc expr =
Just h -> h hsc_env loc expr
hscCompileCoreExpr' :: HscEnv -> SrcSpan -> CoreExpr -> IO (ForeignHValue, [Linkable], PkgsLoaded)
-hscCompileCoreExpr' hsc_env srcspan ds_expr = do
- {- Simplify it -}
- -- Question: should we call SimpleOpt.simpleOptExpr here instead?
- -- It is, well, simpler, and does less inlining etc.
- let dflags = hsc_dflags hsc_env
+hscCompileCoreExpr' hsc_env' srcspan ds_expr = do
+ -- Use modified `dflags` and session that sets -O0 and do less work
+ -- throughout the Core -> ByteCode pipeline, even if current session
+ -- enables `-O1` or above. Unless user manually specified
+ -- `-fno-unoptimized-core-for-interpreter`.
+ let dflags' = hsc_dflags hsc_env'
+ unopt = gopt Opt_UnoptimizedCoreForInterpreter dflags'
+ dflags
+ | unopt = updOptLevel 0 dflags'
+ | otherwise = dflags'
+ hsc_env
+ | unopt = hsc_env' {hsc_dflags = dflags}
+ | otherwise = hsc_env'
let logger = hsc_logger hsc_env
- let ic = hsc_IC hsc_env
- let unit_env = hsc_unit_env hsc_env
- let simplify_expr_opts = initSimplifyExprOpts dflags ic
- simpl_expr <- simplifyExpr logger (ue_eps unit_env) simplify_expr_opts ds_expr
+ {- Simplify it -}
+ simpl_expr <-
+ if unopt
+ then
+ evaluate $
+ -- When generating bytecode for ghci via `hscParsedStmt`, we
+ -- still need to enable inlining! For `let foo = Foo ...`, the
+ -- ghci debugger expects `:print foo` to show `foo = <Foo> ...`
+ -- without forcing `foo` first, without inlining `foo`
+ -- would remain a top-level thunk instead of a datacon
+ -- closure. We can skip inlining for TH splices though.
+ ( if srcspan == interactiveSrcSpan
+ then simpleOptExpr
+ else simpleOptExprNoInline
+ )
+ (initSimpleOpts dflags)
+ ds_expr
+ else
+ simplifyExpr
+ logger
+ (ue_eps $ hsc_unit_env hsc_env)
+ (initSimplifyExprOpts dflags $ hsc_IC hsc_env)
+ ds_expr
-- Create a unique temporary binding
--
=====================================
compiler/GHC/Driver/Session/Inspect.hs
=====================================
@@ -133,7 +133,7 @@ availsToGlobalRdrEnv hsc_env mod avails
imp_spec = ImpSpec { is_decl = decl, is_item = ImpAll}
decl = ImpDeclSpec { is_mod = mod, is_as = moduleName mod,
is_qual = False, is_isboot = NotBoot, is_pkg_qual = NoPkgQual,
- is_dloc = srcLocSpan interactiveSrcLoc,
+ is_dloc = interactiveSrcSpan,
is_level = NormalLevel }
getHomeModuleInfo :: HscEnv -> Module -> IO (Maybe ModuleInfo)
@@ -198,4 +198,3 @@ modInfoSafe = minf_safe
modInfoModBreaks :: ModuleInfo -> Maybe InternalModBreaks
modInfoModBreaks = minf_modBreaks
-
=====================================
compiler/GHC/Types/SrcLoc.hs
=====================================
@@ -19,8 +19,6 @@ module GHC.Types.SrcLoc (
leftmostColumn,
noSrcLoc, -- "I'm sorry, I haven't a clue"
- generatedSrcLoc, -- Code generated within the compiler
- interactiveSrcLoc, -- Code from an interactive session
advanceSrcLoc,
advanceBufPos,
@@ -255,10 +253,8 @@ getBufPos (RealSrcLoc _ mbpos) = mbpos
getBufPos (UnhelpfulLoc _) = Strict.Nothing
-- | Built-in "bad" 'SrcLoc' values for particular locations
-noSrcLoc, generatedSrcLoc, interactiveSrcLoc :: SrcLoc
+noSrcLoc :: SrcLoc
noSrcLoc = UnhelpfulLoc (fsLit "<no location info>")
-generatedSrcLoc = UnhelpfulLoc (fsLit "<compiler-generated code>")
-interactiveSrcLoc = UnhelpfulLoc (fsLit "<interactive>")
-- | Creates a "bad" 'SrcLoc' that has no detailed information about its location
mkGeneralSrcLoc :: FastString -> SrcLoc
=====================================
hadrian/src/Rules/Gmp.hs
=====================================
@@ -12,7 +12,6 @@ import Utilities
import Hadrian.BuildPath
import Hadrian.Expression
import Settings.Builders.Common (cArgs, getStagedCCFlags)
-import GHC.Platform.ArchOS
-- | Build in-tree GMP library objects (if GmpInTree flag is set) and return
-- their paths.
@@ -128,7 +127,10 @@ gmpRules = do
mconcat
[ cArgs
, getStagedCCFlags
- , anyTargetArch [ArchWasm32] ? arg "-fvisibility=default"
+ -- gmp symbols are only used by bignum logic in
+ -- ghc-internal and shouldn't be exported by the
+ -- ghc-internal shared library.
+ , arg "-fvisibility=hidden"
]
env <- sequence
[ builderEnvironment "CC" $ Cc CompileC (stage ctx)
=====================================
testsuite/tests/interface-stability/ghc-prim-exports.stdout
=====================================
@@ -3481,6 +3481,7 @@ module GHC.PrimopWrappers where
remWord8# :: GHC.Internal.Prim.Word8# -> GHC.Internal.Prim.Word8# -> GHC.Internal.Prim.Word8#
resizeMutableByteArray# :: forall s. GHC.Internal.Prim.MutableByteArray# s -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.State# s -> (# GHC.Internal.Prim.State# s, GHC.Internal.Prim.MutableByteArray# s #)
retry# :: forall a_levpoly. GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld -> (# GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld, a_levpoly #)
+ seq :: forall a b_reppoly. a -> b_reppoly -> b_reppoly
setAddrRange# :: GHC.Internal.Prim.Addr# -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld -> GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld
setByteArray# :: forall s. GHC.Internal.Prim.MutableByteArray# s -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.State# s -> GHC.Internal.Prim.State# s
setOtherThreadAllocationCounter# :: GHC.Internal.Prim.Int64# -> GHC.Internal.Prim.ThreadId# -> GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld -> GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld
=====================================
testsuite/tests/interface-stability/ghc-prim-exports.stdout-mingw32
=====================================
@@ -3484,6 +3484,7 @@ module GHC.PrimopWrappers where
remWord8# :: GHC.Internal.Prim.Word8# -> GHC.Internal.Prim.Word8# -> GHC.Internal.Prim.Word8#
resizeMutableByteArray# :: forall s. GHC.Internal.Prim.MutableByteArray# s -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.State# s -> (# GHC.Internal.Prim.State# s, GHC.Internal.Prim.MutableByteArray# s #)
retry# :: forall a_levpoly. GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld -> (# GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld, a_levpoly #)
+ seq :: forall a b_reppoly. a -> b_reppoly -> b_reppoly
setAddrRange# :: GHC.Internal.Prim.Addr# -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld -> GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld
setByteArray# :: forall s. GHC.Internal.Prim.MutableByteArray# s -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.State# s -> GHC.Internal.Prim.State# s
setOtherThreadAllocationCounter# :: GHC.Internal.Prim.Int64# -> GHC.Internal.Prim.ThreadId# -> GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld -> GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld
=====================================
utils/genprimopcode/Main.hs
=====================================
@@ -510,7 +510,7 @@ gen_wrappers (Info _ entries)
want_wrapper :: Entry -> Bool
want_wrapper entry =
and
- [ is_primop entry
+ [ (is_primop entry || is_seq_pseudoop entry)
, not $ name entry `elem` magical_primops
, not $ is_vector entry
-- We currently don't generate wrappers for vector primops.
@@ -520,6 +520,12 @@ gen_wrappers (Info _ entries)
-- suppose this choice can be revisited?
]
+ -- We also want a wrapper for the `seq` pseudoop, since GHCi
+ -- expects to find a value binding in PrimopWrappers.
+ is_seq_pseudoop :: Entry -> Bool
+ is_seq_pseudoop (PseudoOpSpec { name = n }) = n == "seq"
+ is_seq_pseudoop _ = False
+
magical_primops :: [String]
magical_primops =
[ "tagToEnum#"
=====================================
utils/genprimopcode/hie.yaml
=====================================
@@ -0,0 +1,2 @@
+cradle:
+ cabal:
=====================================
utils/jsffi/dyld.mjs
=====================================
@@ -291,7 +291,7 @@ const isNode = Boolean(globalThis?.process?.versions?.node);
// factor out browser-only/node-only logic into different modules. For
// now, just make these global let bindings optionally initialized if
// isNode and be careful to not use them in browser-only logic.
-let fs, http, path, require, stream, util, wasi, ws, zlib;
+let fs, http, path, require, stream, wasi, ws;
if (isNode) {
require = (await import("node:module")).createRequire(import.meta.url);
@@ -300,9 +300,7 @@ if (isNode) {
http = require("http");
path = require("path");
stream = require("stream");
- util = require("util");
wasi = require("wasi");
- zlib = require("zlib");
// Optional npm dependencies loaded via NODE_PATH
try {
@@ -561,30 +559,8 @@ args.rpc.opened.then(() => main(args));
}[path.extname(p)] || "application/octet-stream"
);
- const buf = Buffer.from(await fs.promises.readFile(p));
- const etag = `sha512-${Buffer.from(
- await crypto.subtle.digest("SHA-512", buf)
- ).toString("base64")}`;
-
- res.setHeader("ETag", etag);
-
- if (req.headers["if-none-match"] === etag) {
- res.writeHead(304);
- res.end();
- return;
- }
-
- res.setHeader("Content-Encoding", "br");
-
res.writeHead(200);
- res.end(
- await util.promisify(zlib.brotliCompress)(buf, {
- params: {
- [zlib.constants.BROTLI_PARAM_QUALITY]:
- zlib.constants.BROTLI_MIN_QUALITY,
- },
- })
- );
+ fs.createReadStream(p).pipe(res);
return;
}
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/81f0e496de9f848a0550c74757de7cd...
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/81f0e496de9f848a0550c74757de7cd...
You're receiving this email because of your account on gitlab.haskell.org.