GHC issueshttps://gitlab.haskell.org/ghc/ghc/-/issues2024-02-21T13:53:40Zhttps://gitlab.haskell.org/ghc/ghc/-/issues/24445Programs built with certain ghc flags, and run with certain RTS flags segfaul...2024-02-21T13:53:40ZAndreas KlebingerPrograms built with certain ghc flags, and run with certain RTS flags segfault immediately on startup.
## Steps to reproduce
```
echo "main = print 42" >> HelloWorld.hs
/opt/ghc-9.8.1/bin/ghc HelloWorld.hs -O -debug -threaded -rtsopts
./HelloWorld +RTS -N2 -l -Ds
Segmentation fault (core dumped)
```
## Environment
* GHC version used:...
## Steps to reproduce
```
echo "main = print 42" >> HelloWorld.hs
/opt/ghc-9.8.1/bin/ghc HelloWorld.hs -O -debug -threaded -rtsopts
./HelloWorld +RTS -N2 -l -Ds
Segmentation fault (core dumped)
```
## Environment
* GHC version used: 9.8/HEAD, works in 9.6
Optional:
* Operating System:
* System Architecture:Andreas KlebingerAndreas Klebingerhttps://gitlab.haskell.org/ghc/ghc/-/issues/24444The callback argument passed to foreign import javascript interruptible funct...2024-02-20T14:10:49ZStefano DebenedettiThe callback argument passed to foreign import javascript interruptible functions is undocumented## Summary
Location of documentation issue: the GHC user's guide for [FFI and the JavaScript Backend](https://downloads.haskell.org/ghc/latest/docs/users_guide/javascript.html).
The JavaScript Backend will pass a callback function as e...## Summary
Location of documentation issue: the GHC user's guide for [FFI and the JavaScript Backend](https://downloads.haskell.org/ghc/latest/docs/users_guide/javascript.html).
The JavaScript Backend will pass a callback function as extra last argument to the JavaScript function defined or referenced by a `foreign import javascript interruptible` string. Such argument does not appear in the Haskell type signature of the function.
For more details and context: https://github.com/ghcjs/ghcjs-dom/pull/104#issuecomment-1945867928
## Proposed improvements or changes
The semantics of the `foreign import javascript interruptible` functions should be added the JavaScript Backend FFI documentation, together with a mention of the extra callback parameter and an example of how to use it in JavaScript code.
## Environment
* GHC version used (if appropriate): 9.8.1Sylvain HenryLuite Stegemandoyougnujmy6342@gmail.comSylvain Henryhttps://gitlab.haskell.org/ghc/ghc/-/issues/24443Some programs crash when runing REPL with --nonmoving-gc on Windows using GHC...2024-03-05T23:06:40ZSiyuan ChenSome programs crash when runing REPL with --nonmoving-gc on Windows using GHC 9.8.1## Summary
To improve performance in REPL, we can turn on the `--nonmoving-gc` option (see the related issue https://gitlab.haskell.org/ghc/ghc/-/issues/24416).
However, on Windows, some programs will crash.
## Steps to reproduce
Cre...## Summary
To improve performance in REPL, we can turn on the `--nonmoving-gc` option (see the related issue https://gitlab.haskell.org/ghc/ghc/-/issues/24416).
However, on Windows, some programs will crash.
## Steps to reproduce
Create a cabal project
```
test/
| test.cabal
\---app
Main.hs
```
test.cabal
```
cabal-version: 3.0
name: test
version: 0.1.0.0
build-type: Simple
common warnings
ghc-options: -Wall
executable test
import: warnings
main-is: Main.hs
build-depends: base ^>=4.19.0.0
, gloss >= 1.10 && <1.14
, vector == 0.13.1.0
, random >=1.1 && <1.3
, containers >= 0.5 && < 0.7
hs-source-dirs: app
default-language: Haskell2010
```
app/Main.hs
```
-- | Display "Hello World" in a window.
--
module Main where
import System.Random
import Data.Map
import Data.Vector
main :: IO ()
main = putStr "Hello World"
```
Type in MINGW
```
cabal repl test --repl-options="+RTS --nonmoving-gc -RTS"
```
GHCi crash
```
Chansey@Chansey-PC MINGW64 /e/work-pl/haskell/code/frp/yampa/test
$ cabal repl test --repl-options="+RTS --nonmoving-gc -RTS"
Build profile: -w ghc-9.8.1 -O1
In order, the following will be built (use -v for more details):
- test-0.1.0.0 (exe:test) (file app\Main.hs changed)
Preprocessing executable 'test' for test-0.1.0.0..
GHCi, version 9.8.1: https://www.haskell.org/ghc/ :? for help
[1 of 2] Compiling Main ( app\Main.hs, interpreted ) [Source file changed]
app\Main.hs:5:1: warning: [GHC-66111] [-Wunused-imports]
The import of ‘System.Random’ is redundant
except perhaps to import instances from ‘System.Random’
To import instances alone, use: import System.Random()
|
5 | import System.Random
| ^^^^^^^^^^^^^^^^^^^^
app\Main.hs:6:1: warning: [GHC-66111] [-Wunused-imports]
The import of ‘Data.Map’ is redundant
except perhaps to import instances from ‘Data.Map’
To import instances alone, use: import Data.Map()
|
6 | import Data.Map
| ^^^^^^^^^^^^^^^
app\Main.hs:7:1: warning: [GHC-66111] [-Wunused-imports]
The import of ‘Data.Vector’ is redundant
except perhaps to import instances from ‘Data.Vector’
To import instances alone, use: import Data.Vector()
|
7 | import Data.Vector
| ^^^^^^^^^^^^^^^^^^
Access violation in generated code when reading 0x10
Attempting to reconstruct a stack trace...
Frame Code address
* 0x21d490 0x13fdcae34 C:\env\haskell\ghc\ghc-9.8.1-x86_64-unknown-mingw32\bin\ghc-9.8.1.exe+0x17ae34
* 0x21d498 0x143997eee C:\env\haskell\ghc\ghc-9.8.1-x86_64-unknown-mingw32\bin\ghc-9.8.1.exe+0x3d47eee
* 0x21d4a0 0x6fef6b2d481
* 0x21d4a8 0x6fef6e5cba0
* 0x21d4b0 0x6fef6e5cc50
* 0x21d4b8 0x32
Error: cabal.exe: repl failed for exe:test from test-0.1.0.0. The build
process terminated with exit code 11
```
P.S. The above program might not crash on your side.
In order to reproduce, you have to add more code, such as `import Graphics.Gloss`, `picture`, `main`.
For example:
```
module Main where
import Graphics.Gloss
import System.Random
import Data.Map
import Data.Vector
main :: IO ()
main
= display
(InWindow
"Hello World" -- window title
(400, 150) -- window size
(10, 10)) -- window position
white -- background color
picture -- picture to display
picture :: Picture
picture
= Translate (-170) (-20) -- shift the text to the middle of the window
$ Scale 0.5 0.5 -- display it half the original size
$ Text "Hello World" -- text to display
```
## Expected behavior
Don't crash.
## Environment
* GHC 9.8.1, cabal-install 3.10.2.1
* Windows 7/109.12.1https://gitlab.haskell.org/ghc/ghc/-/issues/24442JS: perform loopification2024-02-20T14:45:12Zdoyougnujmy6342@gmail.comJS: perform loopificationFollowing on https://github.com/haskell/bytestring/pull/631 bytestring will be adding a `-fpure-haskell` flag to remove all FFI (https://github.com/haskell/bytestring/pull/660) but the JS backend cannot yet generate efficient code for ti...Following on https://github.com/haskell/bytestring/pull/631 bytestring will be adding a `-fpure-haskell` flag to remove all FFI (https://github.com/haskell/bytestring/pull/660) but the JS backend cannot yet generate efficient code for tight loops like the ones that are required for the flag.
Why? Because the JS backend does no [loopification](https://gitlab.haskell.org/ghc/ghc/-/wikis/commentary/compiler/loopification) (See also this [Note](https://gitlab.haskell.org/ghc/ghc/-/blob/master/compiler/GHC/StgToCmm/Expr.hs?ref_type=heads#L1122)). This ticket is to:
1. [ ] add loopification in the `StgToJS` pass
2. [ ] add a test that detects this optimization has fired
What should it look like?
- use [continue](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/continue) to self-tail call
- use [break](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/break) to finish the loop
- generate `while (true) { ... }` for the loop.doyougnujmy6342@gmail.comdoyougnujmy6342@gmail.comhttps://gitlab.haskell.org/ghc/ghc/-/issues/24441hPutStr uses different line endings in different buffering modes on Windows2024-02-20T14:44:44ZÖmer Sinan AğacanhPutStr uses different line endings in different buffering modes on WindowsI haven't tried to repro this so sorry if this is a false positive.
I was looking at what line endings langs/compilers/runtimes print on Win and Linux/osx.
It looks like GHC, on Windows, prints `\n` in `NoBuffering` mode, but `\r\n` in...I haven't tried to repro this so sorry if this is a false positive.
I was looking at what line endings langs/compilers/runtimes print on Win and Linux/osx.
It looks like GHC, on Windows, prints `\n` in `NoBuffering` mode, but `\r\n` in `LineBuffering` mode.
Code for `NoBuffering`: https://github.com/ghc/ghc/blob/b57200de601e4ef6827727176611d7192016b8b2/libraries/ghc-internal/src/GHC/IO/Handle/Text.hs#L654
This prints `\n` regardless of what the handle's line ending is.
When buffered, the same function calls `writeBlocks` with the handle's line ending passed, which I think will print `\r\n` in: https://github.com/ghc/ghc/blob/b57200de601e4ef6827727176611d7192016b8b2/libraries/ghc-internal/src/GHC/IO/Handle/Text.hs#L689
Secondly, the expected behavior of what `hPutStrLn`, `readLn` and similar "print/write or read with newline" should print or expect for the line endings should be documented. I checked `putStrLn`, `hPutStrLn`, and `readLn`. I don't know what other similar functions exist.
As an example, this is the Rust docs specifying expected line endings in read and write functions:
- https://doc.rust-lang.org/std/io/trait.BufRead.html#method.read_line (expects `\n` regardless of the platform, `\r` will be part of the yielded lines)
- https://doc.rust-lang.org/std/macro.writeln.html (writes `\n` regardless of the platform)Ben GamariBen Gamarihttps://gitlab.haskell.org/ghc/ghc/-/issues/24440More informative error reporting from QuasiQuoters2024-02-20T14:42:01ZDavid FeuerMore informative error reporting from QuasiQuoters## Motivation
When a `QuasiQuoter` fails (calling `fail`), there are (essentially)
two potential reasons:
1. There is something wrong with part or all of the string it is
asked to interpret.
2. There is something wrong with the cont...## Motivation
When a `QuasiQuoter` fails (calling `fail`), there are (essentially)
two potential reasons:
1. There is something wrong with part or all of the string it is
asked to interpret.
2. There is something wrong with the context it occurs in.
GHC's error highlighter assumes the first reason. For example, suppose
```haskell
defaultQuasiQuoter :: QuasiQuoter
defaultQuasiQuoter = QuasiQuoter
{ quoteExp = f "use in expression contexts."
, quotePat = f "use in pattern contexts."
, quoteType = f "use in types."
, quoteDec = f "creating declarations."
}
where
f m _ = fail $ "This quasiquoter is not for " ++ m
```
If I write
```haskell
f [defaultQuasiQuoter| whatever |] = 3
```
I get the error
```
Vest.hs:6:12: error:
• This quasiquoter is not for use in pattern contexts.
• In the quasi-quotation: [myPatQQ| Whatever |]
|
6 | f [myPatQQ| Whatever |] = 3
| ^^^^^^^^^^^^
```
The error highlighting suggests that the problem is in `Whatever`, but in fact it is not.
## Proposal
It would be nice to have a mechanism by which the `QuasiQuoter` can signal whether it's reporting an error with its argument or with its context. Where it's reporting an error with its argument, it would also be great if it could (optionally) indicate where in its argument string it encountered a problem. These argument strings can be *extremely* long, so just telling the user that the problem is "somewhere out that way" isn't very helpful. The options I can think of:
1. Add appropriate methods to `Quasi`. This seems cleanest.
2. Use the fact that `Quasi` is a subclass of `MonadIO`, letting particular thrown exception types represent these situations. This is pretty hideous, and doesn't deal nicely with recoverable errors.https://gitlab.haskell.org/ghc/ghc/-/issues/24439Parser: use left-recursion in apats and argpats2024-02-20T14:38:06ZVladislav ZavialovParser: use left-recursion in apats and argpatsThe following discussion from !11109 should be addressed:
- [ ] https://gitlab.haskell.org/ghc/ghc/-/merge_requests/11109#note_521826
> Happy works better with left-recursive grammars, so I expected to see
>
> ```
> ar...The following discussion from !11109 should be addressed:
- [ ] https://gitlab.haskell.org/ghc/ghc/-/merge_requests/11109#note_521826
> Happy works better with left-recursive grammars, so I expected to see
>
> ```
> argpats :: { [LArgPat GhcPs] } -- reversed
> : argpats argpat { $2 : $1 }
> | { [] }
> ```
>
> But then I noticed that `apats` has the same problem, and you probably simply used it as a reference.
>
> We should fix this at some point, but maybe not in this patch.https://gitlab.haskell.org/ghc/ghc/-/issues/24438STM: Remove batch-commit logic on 64bit platforms.2024-02-13T15:22:29ZAndreas KlebingerSTM: Remove batch-commit logic on 64bit platforms.## Summary
We jump through some hoops to avoid overflows of a TVars num_updates field. However on 64bit platforms we will never manage to overflow these so we could just remove the checks on these.
This would primiarly have minor perfo...## Summary
We jump through some hoops to avoid overflows of a TVars num_updates field. However on 64bit platforms we will never manage to overflow these so we could just remove the checks on these.
This would primiarly have minor performance benefits.
Alternatively we could make these fields 64-bit unconditionally simplifying the code in general.
## Environment
* GHC version used:
Optional:
* Operating System:
* System Architecture:https://gitlab.haskell.org/ghc/ghc/-/issues/24437STM: Potentially invalid assertion in STM.c2024-02-13T14:45:17ZAndreas KlebingerSTM: Potentially invalid assertion in STM.c## Summary
In the code for committing a transaction we have this sequence:
```C
...
{
ACQ_ASSERT(tvar_is_locked(s, trec));
IF_STM_FG_LOCKS({
// We have locked the TVar therefore nonatomic addi...## Summary
In the code for committing a transaction we have this sequence:
```C
...
{
ACQ_ASSERT(tvar_is_locked(s, trec));
IF_STM_FG_LOCKS({
// We have locked the TVar therefore nonatomic addition is sufficient
NONATOMIC_ADD(&s->num_updates, 1);
});
unlock_tvar(cap, trec, s, e -> new_value, true);
}
ACQ_ASSERT(!tvar_is_locked(s, trec));
```
To me this seems like an potential bug. We assert a TVar is unlocked after we unlock it. But it's not obvious why the TVar couldn't have been locked by another thread in between the unlock operation and the assert.
I will leave the assert in for now as it might check some non-obvious undocumented invariant. But I will leave this here in case anyone else actually hits this assertion while nothing is wrong.https://gitlab.haskell.org/ghc/ghc/-/issues/24436ghc -M fails to correctly account for indirect SOURCE imports2024-03-11T15:23:12ZBen Gamarighc -M fails to correctly account for indirect SOURCE importsConsider a program such as:
```haskell
--- in the unit1 unit
-- Foo.hs-boot
module Foo where
foo :: String
-- Foo.hs
module Foo where
foo :: String
foo = "hi"
-- ... additional cyclic bindings here which make `Foo.hs-boot` necessary
-...Consider a program such as:
```haskell
--- in the unit1 unit
-- Foo.hs-boot
module Foo where
foo :: String
-- Foo.hs
module Foo where
foo :: String
foo = "hi"
-- ... additional cyclic bindings here which make `Foo.hs-boot` necessary
-- Bar.hs
module Bar where
import {-# SOURCE #-} Foo
bar = ... foo ...
--- in the unit2 unit
-- Baz.hs
module Baz where
import Bar
baz = ... bar ...
```
Imagine running `ghc -M` on `Baz.hs`. It will contain something like the following:
```makefile
Baz.o : Bar.hs Bar.o
Bar.o : Bar.hs Foo.o-boot
Foo.o : Foo.hs
Foo.o-boot : Foo.hs-boot
```
This seems perfectly reasonable: it captures the dependency structure of the user's program.
However, if we consider what happens during one-shot compilation, we will see that it isn't quite right. Specifically, imagine that `baz` get an unfolding, which will naturally contain a reference to `Bar.bar` (which was `SOURCE` imported). When we compile `Baz` GHC will see that:
1. we need a declaration for `Foo.foo` in order to unfold `Bar.bar`
2. the user hasn't imported `Bar` directly; this means that `GHC.Iface.Load.importDecl` will call `loadInterface` with `ImportBySystem`
3. `GHC.Iface.Load.loadInterface` calls `GHC.Iface.Load.wantHiBootFile` to determine what it should load
4. `wantHiBootFile` sees that `Foo` is not in the unit currently being compiled. Consequently, it responds with `NotBoot`
5. GHC attempts to load `Foo.hi` instead of `Foo.hi-boot` as the `ghc -M` output claimshttps://gitlab.haskell.org/ghc/ghc/-/issues/24435Out of range index error when bytecode generation with profiled interpreter2024-02-15T17:10:39ZIan-Woo KimOut of range index error when bytecode generation with profiled interpreter## Summary
When using profiled_ghc flavoured GHC for a repl session for a big private project, I encountered this out of array index error when interpreting some modules:
```
ghci> :load (...)
[... of ...] Compiling ... ( src/....hs, in...## Summary
When using profiled_ghc flavoured GHC for a repl session for a big private project, I encountered this out of array index error when interpreting some modules:
```
ghci> :load (...)
[... of ...] Compiling ... ( src/....hs, interpreted )
<no location info>: error:
Ix{Int}.index: Index (52) out of range ((0,39))
```
Fortunately, I could patch `indexError` to show the stack trace in profiled mode:
```
<no location info>: error:
Ix{Int}.index: Index (52) out of range ((0,39))
CallStack (from HasCallStack):
error, called at libraries/base/src/GHC/Ix.hs:169:5 in base:GHC.Ix
CallStack (from -prof):
GHC.Stack.CCS.currentCallStack1 (<no location info>)
GHC.Stack.CCS.currentCallStack (libraries/base/src/GHC/Stack/CCS.hsc:126:1-16)
GHC.Exception.errorCallWithCallStackException (libraries/base/src/GHC/Exception.hs:102:1-31)
GHC.Err.error (libraries/base/src/GHC/Err.hs:36:1-5)
GHC.Ix.$w$sindexError (libraries/base/src/GHC/Ix.hs:168:1-10)
GHC.StgToByteCode.lvl295 (<no location info>)
GHC.StgToByteCode.schemeER_wrk (compiler/GHC/StgToByteCode.hs:(387,1)-(409,40))
GHC.StgToByteCode.thenBc (compiler/GHC/StgToByteCode.hs:(2210,1)-(2214,17))
GHC.StgToByteCode.$fApplicativeBcM7 (<no location info>)
GHC.StgToByteCode.schemeR_wrk (compiler/GHC/StgToByteCode.hs:(358,1)-(382,60))
GHC.StgToByteCode.schemeR (compiler/GHC/StgToByteCode.hs:(341,1)-(342,41))
GHC.StgToByteCode.$wschemeR (compiler/GHC/StgToByteCode.hs:341:1-7)
GHC.StgToByteCode.schemeTopBind (compiler/GHC/StgToByteCode.hs:(306,1)-(322,55))
GHC.StgToByteCode.c (<no location info>)
GHC.StgToByteCode.go11 (<no location info>)
GHC.StgToByteCode.runBc (compiler/GHC/StgToByteCode.hs:(2206,1)-(2207,63))
GHC.Utils.Error.$w$swithTiming' (<no location info>)
GHC.StgToByteCode.byteCodeGen (compiler/GHC/StgToByteCode.hs:(105,1)-(150,38))
GHC.StgToByteCode.byteCodeGen1 (<no location info>)
GHC.Driver.Main.hscInteractive (compiler/GHC/Driver/Main.hs:(1963,1)-(2004,49))
GHC.Driver.Main.generateByteCode2 (<no location info>)
GHC.Driver.Main.generateByteCode (compiler/GHC/Driver/Main.hs:(2010,1)-(2020,32))
GHC.Driver.Main.generateByteCode1 (<no location info>)
GHC.Driver.Main.generateFreshByteCode (compiler/GHC/Driver/Main.hs:(2027,1)-(2031,17))
GHC.Driver.Main.generateFreshByteCode1 (<no location info>)
GHC.Driver.Pipeline.Execute.$wrunHscBackendPhase (<no location info>)
GHC.Driver.Pipeline.Execute.runHscBackendPhase1 (<no location info>)
GHC.Driver.Pipeline.Execute.runPhase1 (<no location info>)
GHC.Driver.Pipeline.$w$shscGenBackendPipeline (<no location info>)
GHC.Driver.Pipeline.fullPipeline2 (<no location info>)
GHC.Driver.Pipeline.$w$shscPipeline (<no location info>)
GHC.Driver.Pipeline.$wcompileOne' (<no location info>)
GHC.Driver.Make.upsweep_mod (compiler/GHC/Driver/Make.hs:(1303,1)-(1315,12))
GHC.Driver.Make.executeCompileNode.\ (compiler/GHC/Driver/Make.hs:(2518,81)-(2531,16))
GHC.Driver.Make.withLoggerHsc.\ (compiler/GHC/Driver/Make.hs:(2481,35)-(2485,17))
GHC.Driver.Make.runSeqPipelines.env.\ (compiler/GHC/Driver/Make.hs:2871:44-47)
GHC.Driver.Make.runSeqPipelines.env (compiler/GHC/Driver/Make.hs:(2870,7)-(2875,21))
GHC.Driver.Make.lvl83 (<no location info>)
GHC.Driver.Make.withLoggerHsc (compiler/GHC/Driver/Make.hs:(2480,1)-(2485,17))
GHC.Driver.Make.executeCompileNode (compiler/GHC/Driver/Make.hs:(2515,1)-(2540,35))
GHC.Driver.Make.interpretBuildPlan.buildSingleModule.build_action (compiler/GHC/Driver/Make.hs:(1137,11)-(1161,42))
GHC.Driver.Make.interpretBuildPlan.buildSingleModule (compiler/GHC/Driver/Make.hs:(1127,5)-(1167,49))
GHC.Driver.Make.interpretBuildPlan.buildLoop (compiler/GHC/Driver/Make.hs:(1103,5)-(1121,50))
GHC.Driver.Make.interpretBuildPlan (compiler/GHC/Driver/Make.hs:(1085,1)-(1240,73))
GHC.Driver.Make.withLocalTmpFS.\ (compiler/GHC/Driver/Make.hs:2949:54-101)
Control.Monad.Catch.$fMonadMaskMaybeT_$cgeneralBracket (libraries/exceptions/src/Control/Monad/Catch.hs:659:3-16)
GHC.Driver.Make.withLocalTmpFS (compiler/GHC/Driver/Make.hs:(2938,1)-(2949,101))
GHC.Driver.Make.runLoop.run_pipeline (compiler/GHC/Driver/Make.hs:2980:7-51)
GHC.Driver.Make.runLoop.\ (compiler/GHC/Driver/Make.hs:(2972,30)-(2975,33))
GHC.Driver.Make.runAllPipelines.spawn_actions.\.\ (compiler/GHC/Driver/Make.hs:2957:78-86)
GHC.Driver.Make.runLoop (compiler/GHC/Driver/Make.hs:(2969,1)-(2980,51))
GHC.Driver.Make.$srunLoop (<no location info>)
GHC.Driver.Make.runAllPipelines.spawn_actions.\ (compiler/GHC/Driver/Make.hs:2957:55-96)
GHC.Driver.Make.runAllPipelines.spawn_actions (compiler/GHC/Driver/Make.hs:(2956,7)-(2958,46))
GHC.Driver.Make.runAllPipelines (compiler/GHC/Driver/Make.hs:(2953,1)-(2964,29))
GHC.Driver.Make.runAllPipelines (<no location info>)
GHC.Driver.Make.runSeqPipelines (compiler/GHC/Driver/Make.hs:(2869,1)-(2876,61))
GHC.Driver.Make.runPipelines (compiler/GHC/Driver/Make.hs:(2862,1)-(2866,79))
GHC.Driver.Make.upsweep (compiler/GHC/Driver/Make.hs:(1256,1)-(1272,42))
Control.Monad.IO.Class.liftIO (libraries/base/src/Control/Monad/IO/Class.hs:66:5-25)
GHCi.UI.Monad.$fApplicativeGHCi4 (<no location info>)
GHC.Base.<*> (libraries/base/src/GHC/Base.hs:841:5-37)
GHC.Driver.Make.load' (compiler/GHC/Driver/Make.hs:(690,1)-(781,31))
GHC.Driver.Make.load' (compiler/GHC/Driver/Make.hs:690:1-5)
GHCi.UI.Monad.$fMonadGHCi2 (<no location info>)
GHC.Driver.Make.loadWithCache (compiler/GHC/Driver/Make.hs:(494,1)-(500,51))
GHC.Driver.Make.loadWithCache (compiler/GHC/Driver/Make.hs:494:1-13)
GHCi.UI.$strySuccess (<no location info>)
GHCi.UI.lvl819 (<no location info>)
Control.Monad.Catch.$w$cgeneralBracket1 (<no location info>)
Control.Monad.Catch.$fMonadMaskIO1 (<no location info>)
Control.Monad.Catch.$fMonadMaskReaderT1 (<no location info>)
GHC.Driver.Monad.$fMonadMaskGhc1 (<no location info>)
Control.Monad.Catch.generalBracket (libraries/exceptions/src/Control/Monad/Catch.hs:(342,3)-(350,15))
Control.Monad.Catch.bracket (libraries/exceptions/src/Control/Monad/Catch.hs:890:1-7)
Control.Monad.Catch.finally (libraries/exceptions/src/Control/Monad/Catch.hs:902:1-7)
GHC.withCleanupSession (compiler/GHC.hs:(531,1)-(542,51))
GHC.Driver.Monad.$fMonadGhc_$s$fMonadReaderT_$c>>= (<no location info>)
GHC.Base.>>= (libraries/base/src/GHC/Base.hs:1031:5-55)
GHC.Utils.Panic.withSignalHandlers (compiler/GHC/Utils/Panic.hs:241:1-18)
GHC.runGhc (compiler/GHC.hs:(506,1)-(511,26))
GHC.runGhc1 (<no location info>)
Main.main2 (<no location info>)
GHC.IO.catch1 (<no location info>)
Control.Monad.Catch.$fMonadCatchIO1 (<no location info>)
Control.Monad.Catch.catch (libraries/exceptions/src/Control/Monad/Catch.hs:201:3-66)
GHC.defaultErrorHandler (compiler/GHC.hs:(443,1)-(478,7))
GHC.$wdefaultErrorHandler (compiler/GHC.hs:443:1-19)
Main.main1 (<no location info>)
GHC.TopHandler.runMainIO1 (<no location info>)
Main.main3 (<no location info>)
Main.main (ghc/Main.hs:117:1-4)
```
so the bug is here: GHC.StgToByteCode.schemeER_wrk (compiler/GHC/StgToByteCode.hs:(387,1)-(409,40))
https://gitlab.haskell.org/wavewave/ghc/-/blob/T24435/compiler/GHC/StgToByteCode.hs?ref_type=heads#L405
`tick_no` is out of range.
## Environment
* GHC version used: a custom GHC for prof+dyn flavour (i.e `--flavour=perf+profiled_ghc` ). https://gitlab.haskell.org/wavewave/ghc/-/tree/wavewave/ghc_p_dyn?ref_type=heads
it's based on GHC 9.9.20240131
* Operating System: macOS 14.3, Ubuntu 23.10
* System Architecture: Apple M1 Max, x86_64 linuxhttps://gitlab.haskell.org/ghc/ghc/-/issues/24434Add default QuasiQuoter(s)2024-02-14T19:23:59ZDavid FeuerAdd default QuasiQuoter(s)## Motivation
`Language.Haskell.TH.Quote` gives us
```haskell
data QuasiQuoter = QuasiQuoter {
-- | Quasi-quoter for expressions, invoked by quotes like @lhs = $[q|...]@
quoteExp :: String -> Q Exp,
-- | Quasi-quoter for p...## Motivation
`Language.Haskell.TH.Quote` gives us
```haskell
data QuasiQuoter = QuasiQuoter {
-- | Quasi-quoter for expressions, invoked by quotes like @lhs = $[q|...]@
quoteExp :: String -> Q Exp,
-- | Quasi-quoter for patterns, invoked by quotes like @f $[q|...] = rhs@
quotePat :: String -> Q Pat,
-- | Quasi-quoter for types, invoked by quotes like @f :: $[q|...]@
quoteType :: String -> Q Type,
-- | Quasi-quoter for declarations, invoked by top-level quotes
quoteDec :: String -> Q [Dec]
}
```
The documentation suggests that
> if you are only interested
> in defining a quasiquoter to be used for expressions, you would
> define a 'QuasiQuoter' with only 'quoteExp', and leave the other
> fields stubbed out with errors.
This is not ideal. There are a few problems:
The easiest path, which some packages take, is to write something like
```haskell
myqq = QuasiQuoter
{ quoteExp = ... }
```
The error message produced when `myqq` is used in the wrong context will not explain the problem at all; it'll just point out that there was an exception in Template Haskell code. The second problem is that using `error`, even more informatively, will produce an overly verbose, poorly formatted message because GHC assumes that it represents a bug in the quasiquoter. The correct thing is instead to use `fail` as usual.
## Proposal
I suggest offering one or perhaps a couple of suitable "default" `QuasiQuoter` definitions. These could look like so:
```haskell
defaultQuasiQuoter :: QuasiQuoter
defaultQuasiQuoter = QuasiQuoter
{ quoteExp = \_ -> fail "This quasiquoter is not for use in expressions"
, quoteType = \_ -> fail "This quasiquoter is not for use in types"
, quotePat = \_ -> fail "This quasiquoter is not for use in patterns"
, quoteDec = \_ -> fail "This quasiquoter is not for producing declarations"
}
namedDefaultQuasiQuoter :: String -> QuasiQuoter
namedDefaultQuasiQuoter n = QuasiQuoter
{ quoteExp = \_ -> fail $ "The " ++ n ++ " quasiquoter is not for use in expressions"
, quoteType = \_ -> fail $ "The " ++ n ++ " quasiquoter is not for use in types"
, quotePat = \_ -> fail $ "The " ++ n ++ " quasiquoter is not for use in patterns"
, quoteDec = \_ -> fail $ "The " ++ n ++ " quasiquoter is not for producing declarations"
}
```
Now users can write things like
```haskell
myqq = (namedDefaultQuasiQuoter "myqq")
{ quoteExp = ... }
```
The documentation should also indicate that the unused fields should `fail` rather than `error`.David FeuerDavid Feuerhttps://gitlab.haskell.org/ghc/ghc/-/issues/24433Spurious "Heap exhausted" with same (or close) `+RTS -H` and `-M` arguments2024-02-22T20:13:43ZWolfram KahlSpurious "Heap exhausted" with same (or close) `+RTS -H` and `-M` arguments## Summary
Calling Agda with the same size as arguments of the RTS flags `-H` and `-M` reports `Heap exhausted` long before the live heap reaches that size.
This even happens if the `-H` size is only a little below the `-M` size.
## S...## Summary
Calling Agda with the same size as arguments of the RTS flags `-H` and `-M` reports `Heap exhausted` long before the live heap reaches that size.
This even happens if the `-H` size is only a little below the `-M` size.
## Steps to reproduce
(I installed GHC-9.8.1 using `ghcup`.)
````
cabal get https://hackage.haskell.org/package/Agda-2.6.4.2/candidate/Agda-2.6.4.2.tar.gz
cd Agda-2.6.4.2
cabal install -f +optimise-heavily -f +enable-cluster-counting
wget -O agda-stdlib.tar.gz https://github.com/agda/agda-stdlib/archive/v2.0.tar.gz
tar -xzf agda-stdlib.tar.gz
cd agda-stdlib-2.0
cabal install
# Repeat from here for more experiments with different `-H_ -M_`:
make clean
GenerateEverything # silent, fraction of a second.
time agda +RTS -S -H3.2G -M3.2G -RTS -i src -i . Everything.agda
````
Result:
````
Alloc Copied Live GC GC TOT TOT Page Flts
bytes bytes bytes user elap user elap
4844080 309096 484256 0.056 0.056 0.080 0.079 0 0 (Gen: 0)
Checking Everything (/var/tmp/kahl/Agda/agda-stdlib-2.0/Everything.agda).
Checking Algebra (/var/tmp/kahl/Agda/agda-stdlib-2.0/src/Algebra.agda).
Checking Algebra.Core (/var/tmp/kahl/Agda/agda-stdlib-2.0/src/Algebra/Core.agda).
Checking Level (/var/tmp/kahl/Agda/agda-stdlib-2.0/src/Level.agda).
Checking Algebra.Definitions (/var/tmp/kahl/Agda/agda-stdlib-2.0/src/Algebra/Definitions.agda).
187690672 6016408 6756640 0.035 0.035 0.295 0.293 0 0 (Gen: 1)
Checking Relation.Binary.Core (/var/tmp/kahl/Agda/agda-stdlib-2.0/src/Relation/Binary/Core.agda).
Checking Data.Product.Base (/var/tmp/kahl/Agda/agda-stdlib-2.0/src/Data/Product/Base.agda).
Checking Function.Base (/var/tmp/kahl/Agda/agda-stdlib-2.0/src/Function/Base.agda).
585794240 10800232 14586976 0.032 0.032 0.847 0.845 0 0 (Gen: 0)
Checking Relation.Nullary.Negation.Core (/var/tmp/kahl/Agda/agda-stdlib-2.0/src/Relation/Nullary/Negation/Core.agda).
Checking Data.Bool.Base (/var/tmp/kahl/Agda/agda-stdlib-2.0/src/Data/Bool/Base.agda).
Checking Data.Unit.Base (/var/tmp/kahl/Agda/agda-stdlib-2.0/src/Data/Unit/Base.agda).
98277808 6409384 8465232 0.022 0.022 0.979 0.976 0 0 (Gen: 1)
agda: Heap exhausted;
agda: Current maximum heap size is 3435970560 bytes (3276 MB).
agda: Use `+RTS -M<size>' to increase it.
22808 16472 110552 0.000 0.000 0.980 0.977 0 0 (Gen: 1)
1784 0.000 0.000
876,631,392 bytes allocated in the heap
23,551,592 bytes copied during GC
8,465,232 bytes maximum residency (3 sample(s))
156,848 bytes maximum slop
3330 MiB total memory in use (0 MiB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause
Gen 0 2 colls, 0 par 0.089s 0.089s 0.0444s 0.0564s
Gen 1 3 colls, 0 par 0.057s 0.057s 0.0190s 0.0350s
TASKS: 4 (1 bound, 3 peak workers (3 total), using -N1)
SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)
INIT time 0.002s ( 0.002s elapsed)
MUT time 0.832s ( 0.829s elapsed)
GC time 0.146s ( 0.146s elapsed)
EXIT time 0.001s ( 0.000s elapsed)
Total time 0.981s ( 0.977s elapsed)
Alloc rate 1,053,786,024 bytes per MUT second
Productivity 84.8% of total user, 84.9% of total elapsed
real 0m1.075s
user 0m0.678s
sys 0m0.400s
````
## Expected behavior
What do you expect the reproducer described above to do?
Something close to the following, produced with `-H3G -M3.2G`
````
[...]
181852688 12500976 1694569456 0.015 0.015 646.040 644.610 0 0 (Gen: 0)
121336376 13558856 1283757016 0.045 0.045 646.167 644.736 0 0 (Gen: 1)
151690664 44427016 1330286952 0.076 0.076 646.378 644.947 0 0 (Gen: 0)
147730832 19051744 1303443600 0.067 0.067 646.551 645.120 0 0 (Gen: 0)
5600976 19400152 1307901656 0.053 0.053 646.638 645.206 0 0 (Gen: 0)
22498312 15656 93304 0.019 0.019 646.776 645.345 0 0 (Gen: 1)
656 0.000 0.000
766,004,153,856 bytes allocated in the heap
46,365,512,064 bytes copied during GC
1,534,982,456 bytes maximum residency (56 sample(s))
5,982,152 bytes maximum slop
3385 MiB total memory in use (1 MiB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause
Gen 0 2732 colls, 0 par 104.382s 104.420s 0.0382s 0.9379s
Gen 1 56 colls, 0 par 16.098s 16.099s 0.2875s 1.1602s
TASKS: 4 (1 bound, 3 peak workers (3 total), using -N1)
SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)
INIT time 0.002s ( 0.002s elapsed)
MUT time 526.294s (524.823s elapsed)
GC time 120.480s (120.519s elapsed)
EXIT time 0.001s ( 0.000s elapsed)
Total time 646.777s (645.345s elapsed)
Alloc rate 1,455,468,876 bytes per MUT second
Productivity 81.4% of total user, 81.3% of total elapsed
real 10m45.618s
user 10m42.115s
sys 0m4.931s
````
Using `-M3G` alone without `-H` also succeeds.
Using `-H3.1G -M3.2G` also fails, after 1m48.564s.
Using `-H4G -M4G` also fails immediately.
Over two years ago, I was routinely using settings like `-H3G -M3G` without problems.
## Environment
* GHC version used: 9.8.1
Optional:
* Operating System: Ubuntu 20.04.6 LTS
* System Architecture: Intel(R) Core(TM) i7-8565UAndreas KlebingerAndreas Klebingerhttps://gitlab.haskell.org/ghc/ghc/-/issues/24432elf_reloc_aarch64.c Assertion failure2024-03-14T20:48:47ZRowan Goemanself_reloc_aarch64.c Assertion failure## Summary
Apologies if this issue is known I could not find anything related. I'm using [clash](https://github.com/clash-lang/clash-compiler) on aarch64 nixos and I'm trying to upgrade to 9.6.4 or 9.8.1 from 9.0.2. But in both instance...## Summary
Apologies if this issue is known I could not find anything related. I'm using [clash](https://github.com/clash-lang/clash-compiler) on aarch64 nixos and I'm trying to upgrade to 9.6.4 or 9.8.1 from 9.0.2. But in both instances GHC balks when running clash with an assertion failure:
```
clash: internal error: ASSERTION FAILED: file rts/linker/elf_reloc_aarch64.c, line 99
(GHC version 9.8.1 for aarch64_unknown_linux)
Please report this as a GHC bug: https://www.haskell.org/ghc/reportabug
```
## Steps to reproduce
It assumes you have nix installed(I don't have access to a non-nixos linux aarch64 system).
I have made a mininal reproducer:
1. `git clone git@github.com:rowanG077/ghc-aarch64-bug.git`
2. `cd ghc-aarch64-bug`
3. `nix-shell -p haskell.compiler.ghc98 cabal-install`
A similar assert is hit when going the full nix route. But instead of hitting the assert on line 99 it hits the one on line 76.
4. `cabal run clash`
## Expected behavior
I expect it to run clash.
## Environment
* GHC version used: 9.8.1 and 9.6.4
Optional:
* Operating System: NixOS unstable
* System Architecture: Aarch649.10.1Moritz AngermannMoritz Angermann2024-03-08https://gitlab.haskell.org/ghc/ghc/-/issues/24431Cross-compiling seems to not pass CC through2024-02-29T12:00:43ZGreg SteuckCross-compiling seems to not pass CC throughI'm having trouble trying to bootstrap OpenBSD-aarch64 from OpenBSD-amd64. I do have a working cross-toolchain (courtesy of LLVM) but it looks like the plumbing in hadrian is not fully laid. At least, when running with
```
export MAKE=gm...I'm having trouble trying to bootstrap OpenBSD-aarch64 from OpenBSD-amd64. I do have a working cross-toolchain (courtesy of LLVM) but it looks like the plumbing in hadrian is not fully laid. At least, when running with
```
export MAKE=gmake \
AUTOCONF_VERSION=2.71 \
AUTOMAKE_VERSION=1.16 \
CC=/usr/local/bin/clang-13 \
LD=/usr/local/bin/ld.lld-13 \
NM=/usr/local/bin/llvm-nm-13 \
OBJDUMP=/usr/local/bin/llvm-objdump-13
./boot
./configure --target=aarch64-none-openbsd --with-cc=/usr/local/bin/clang-13
hadrian/build '*.*.ghc.link.opts+=-L/usr/local/lib' \
--docs=none \
--flavour=quickest \
-j stage1:exe:ghc-bin
```
I see the main configure succeed, but stage0 is already going off the rails when trying to configure the time library which shows in its config.log:
```
$ //home/greg/s/ghc/libraries/time/configure --with-compiler=ghc
'--prefix=${pkgroot}/..' 'CFLAGS=-Qunused-arguments -iquote
/home/greg/s/ghc/libraries/time -Qunused-arguments'
LDFLAGS=--target=aarch64-none-openbsd --host=aarch64-none-openbsd
--with-cc=clang CC=/usr/bin/clang
```
Which clearly mixed up the uses target value for host whereas the compiler is the one for host. This compiler promptly reports:
```
error: unable to create target: 'No available targets are compatible with triple "aarch64-none-openbsd"'
```
because it doesn't have support for aarch64. In fact, it's unclear, where `/usr/bin/clang` even came from. My `configure` command above didn't point at it. Moreover, top level config.log doesn't mention it.
If there's better cross-compilation documentation to follow than https://gitlab.haskell.org/ghc/ghc/-/wikis/building/cross-compiling, I'd love to read that.
Attaching the top level [config.log](/uploads/23b8a2e89089c4b0cc61c7709a59ce82/config.log)
and[time-config.log](/uploads/4f834f246cf60f0d3c1fe38f4d097703/time-config.log).Matthew PickeringMatthew Pickeringhttps://gitlab.haskell.org/ghc/ghc/-/issues/24430Symbol type mismatch when building with llvm2024-02-13T15:45:39ZGreg SteuckSymbol type mismatch when building with llvm## Summary
I wanted to play with LLVM backend on OpenBSD amd64. A lot of tests produce prodigious extra output which doesn't occur with the default backend:
```
Symbol type mismatch.
Symbol __llvm_retpoline_r11 was defined by /home/greg...## Summary
I wanted to play with LLVM backend on OpenBSD amd64. A lot of tests produce prodigious extra output which doesn't occur with the default backend:
```
Symbol type mismatch.
Symbol __llvm_retpoline_r11 was defined by /home/greg/s/ghc/_build/stage1/lib/x86_64-openbsd-ghc-9.9.20240211/base-4.19.0.0-inplace/libHSbase-4.19.0.0-inplace.a to be a data symbol.
yet was defined by /home/greg/s/ghc/_build/stage1/lib/x86_64-openbsd-ghc-9.9.20240211/ghc-prim-0.10.0-inplace/libHSghc-prim-0.10.0-inplace.a to be a code symbol.
```
## Steps to reproduce
I built GHC with:
```
TEST=T5313 hadrian/build '*.*.ghc.link.opts+=-L/usr/local/lib' \
--docs=none \
--flavour=release+llvm+no_profiled_libs+split_sections \
-j test
```
After that when the tests run e.g. `GHC.load GHC.LoadAllTargets` they generate this `debugBelch` above.
## Expected behavior
Since the output doesn't seem to be otherwise harmful, it'd appear that suppressing the message entirely is a reasonable alternative?
## Environment
* GHC version used: 8bbe12f288
Optional:
* Operating System: OpenBSD 7.4-current
* System Architecture: amd64https://gitlab.haskell.org/ghc/ghc/-/issues/24429Missplaced overlapping pragmas make module misparse2024-02-13T15:41:17ZOleg GrenrusMissplaced overlapping pragmas make module misparse```haskell
module Issue where
{-# overlapping is better avoided #-}
class Foo a where
foo :: a
```
```
[1 of 1] Compiling Issue ( Issue.hs, interpreted )
Issue.hs:3:1: error: [GHC-58481]
parse error on input ‘{-# ov...```haskell
module Issue where
{-# overlapping is better avoided #-}
class Foo a where
foo :: a
```
```
[1 of 1] Compiling Issue ( Issue.hs, interpreted )
Issue.hs:3:1: error: [GHC-58481]
parse error on input ‘{-# overlapping’
|
3 | {-# overlapping is better avoided #-}
| ^^^^^^^^^^^^^^^
```https://gitlab.haskell.org/ghc/ghc/-/issues/24428Check that GHC.Types.Builtin.Names builds unique Uniques2024-02-13T15:33:51ZSebastian GrafCheck that GHC.Types.Builtin.Names builds unique UniquesI was wary of duplicate occurrences of the same decimal number in GHC.Types.Builtin.Names, so I let ChatGPT help me in defining the following useful `awk` script:
```sh
$ awk '{
# Iterate over each field
for (i=1; i<=NF; i++) {
...I was wary of duplicate occurrences of the same decimal number in GHC.Types.Builtin.Names, so I let ChatGPT help me in defining the following useful `awk` script:
```sh
$ awk '{
# Iterate over each field
for (i=1; i<=NF; i++) {
# If the field is a decimal number, add it to the count
if ($i ~ /^[0-9]+$/) {
count[$(i-1)][$i]++
}
}
}
END {
# Print the decimal numbers and their counts
for (s in count) {
for (num in count[s]) {
if (count[s][num] > 1) { print s, num, count[s][num] }
}
}
}' compiler/GHC/Builtin/Names.hs
```
This will print out duplicate calls of the the form `mkPreludeMiscIdUnique 135`, e.g.,
```
mkPreludeMiscIdUnique 135 2
```
The last number is the number of occurrences. Perhaps that's helpful to someone or even worth a test in CI.https://gitlab.haskell.org/ghc/ghc/-/issues/24427Validation of STM transactions by the scheduler causes large overhead. Potent...2024-03-12T00:18:00ZAndreas KlebingerValidation of STM transactions by the scheduler causes large overhead. Potentially preventing progress.## Summary
The scheduler performing validation of STM transactions in every scheduler loop might lead to scheduler time dominating a programs runtime.
## Details
When a thread returns to the scheduler we call `schedulePostRunThread` w...## Summary
The scheduler performing validation of STM transactions in every scheduler loop might lead to scheduler time dominating a programs runtime.
## Details
When a thread returns to the scheduler we call `schedulePostRunThread` which will validate active transactions through `stmValidateNestOfTransactions`. `stmValidateNestOfTransactions` itself will call `validate_and_acquire_ownership` on the current transaction, and all the transactions that enclose it with the options `acquire_all: true` and `retain_ownership` false.
`validate_and_acquire_ownership` will then walk over all the tvars in the transaction log, lock them and check their expected values against their actual ones. If any don't pass the check we ultimately condemn the whole transaction. So far so good. In this case this will never happens as we only perform reads.
This is already bad with just one capability:
* As the number as TVars increases performance of each read slows down, resulting in fewer reads per second. (See https://gitlab.haskell.org/ghc/ghc/-/issues/24410)
* As read performance decreases we return to the scheduler more frequently relative to the progress made by the transaction because of context switches. Each time we return to the scheduler we pay the full cost of `validate_and_acquire_ownership` which *also* scales with the number of TVars in the transaction.
But especially with multiple capabilities this get's worse:
* Each thread will perform the `validate_and_acquire_ownership` check whenever the thread returns to the scheduler. This means scheduling will take longer.
* As we spend more time in the scheduler code, less time is spent on productive work in between context switches. This means we end up using more cycles on overhead per unit of work.
* In the worst case most of the runtime is spent doing validation of transactions, with little time spent doing productive work that progresses the transactions.
* If two threads perform validation in parallel they might also run into https://gitlab.haskell.org/ghc/ghc/-/issues/24446 preventing either thread to progress.
---
Some napkin math:
In the example I'm looking at we deal with 100k tvars. According to "Evaluating the Cost of Atomic Operations on Modern Architectures" a cas takes on the order of 10-100ns.
Near the end during each context switch we will perform 400k cas operations. As both threads will perform one cas each to lock and unlock each tvar.
If we assume 50ns for each cas this means a full context switch, just from the cost of the cas, will take somewhere around 20ms. By default our context switch frequency is also 20ms.
I think it's plausible that we run into situations where we get:
* x: Mutator is runnings
* x+0ms: Ticker triggers context switch:
* x+0-19ms: Scheduler is running `validate_and_acquire_ownership`
* x+19-20ms: Mutator runs - we perform a handful of reads
* x+20ms: Ticker triggers another context switch.
This would repeat until eventually the runtime of the scheduler crosses 20ms, so we would "lose" one context switch, and the mutator would get a full 20ms slice to perform reads. But before we get there we might spend a long time during which 95%+ of the time is spent on scheduler overhead.
However it's hard to confirm this, as any kind of instrumentation causes enough overhead to majorly distorts this pattern. And https://gitlab.haskell.org/ghc/ghc/-/issues/24446 also affects this.
## Steps to reproduce
So far I investigated this using this as reproducer:
```haskell
{-# LANGUAGE NumericUnderscores #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Main where
import Control.Concurrent (ThreadId, myThreadId, forkIO)
import Control.Concurrent.STM (STM, atomically, newTVar, readTVar, TVar(..))
import Data.IORef (IORef, modifyIORef', newIORef, readIORef)
import GHC.IO (unsafePerformIO)
import System.IO (hFlush, stdout)
import Data.Time.Clock
import Control.Concurrent.MVar
import Control.Monad
main = do
let nums = [
10_000 :: Int
-- ,50_000
,100_000
-- ,150_000
-- ,200_000
-- ,300_000
-- ,400_000
]
forM_ nums $ \tvar_count -> do
print $ "Measuring: " ++ show tvar_count
(tvars :: [TVar Int]) <- atomically $ mapM (newTVar) [1 .. tvar_count]
putStrLn "Created TVars"
start_time <- getCurrentTime
s1 <- runAsync $ atomically $ do
readTList tvars
s2 <- runAsync $ atomically $ do
readTList tvars
s1 <- takeMVar s1
s2 <- takeMVar s2
print $ "done, " ++ show (s1,s2)
done_time <- getCurrentTime
print $ done_time `diffUTCTime` start_time
runAsync :: (IO a) -> IO (MVar a)
runAsync act = do
mvar <- newEmptyMVar
_tid <- forkIO $ do
r <- act
putMVar mvar r
return mvar
readTList tvars = do
values <- mapM readTVar tvars :: STM [Int]
!s <- return $! sum values
return $! s
```
## Expected behavior
Scheduling performance should not be significantly affected by the number of tvars involved in transactions.
## Environment
* GHC version used:
Optional:
* Operating System:
* System Architecture:https://gitlab.haskell.org/ghc/ghc/-/issues/24426STM Implementation: Make the coarse grained locking variant available at runt...2024-03-06T17:51:48ZAndreas KlebingerSTM Implementation: Make the coarse grained locking variant available at runtime, configure time, or remove it completely.## Summary
GHC's STM implementation surprisingly offers different locking implementations.
* No locking (non-threaded runtime).
* Fine grained locking (STM_FG_LOCK) - used by threaded builds by default.
* Coarse locks - critial sectio...## Summary
GHC's STM implementation surprisingly offers different locking implementations.
* No locking (non-threaded runtime).
* Fine grained locking (STM_FG_LOCK) - used by threaded builds by default.
* Coarse locks - critial sections in the STM implementation are guarded by one global mutex. (STM_CG_LOCK)
I tried enabling it, it seems to work but compiles with a number of minor warnings caused by missing casts.
As far as I can tell coarse locking seems to be currently faster in certain scenarios. In particular in some toy examples derived from https://gitlab.haskell.org/ghc/ghc/-/issues/24142, although based on comments in STM.c I assume in other cases it would fare far worse than fine grained locks.
Perhaps there would be value in making this configuration easier available to users than changing #defines by hand in the source if they want to use it.
Personally I'm not sure if the advantages provided by this option warrant the bigger configuration space and carrying this code forward. It hasn't been used in released GHC's for 19 years and it adds complexity when understanding the STM code.
For now I plan to figure out the details of https://gitlab.haskell.org/ghc/ghc/-/issues/24142, get bens improvements to STM TRecs merged, and perhaps check if this variant still provides speed upgrades afterwards.
See the comments in STM.c for more details.
## Environment
* GHC version used: Any GHC from the last 19 years.