[Git][ghc/ghc][wip/ghci-no-simpl] 7 commits: hadrian: build in-tree gmp with -fvisibility=hidden
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 <codex@openai.com> - - - - - 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.
participants (1)
-
Cheng Shao (@TerrorJack)