Biweekly update from the GHC DevX team at IOG.
Previous updates can be found here.
Luite: fixed the support for one-shot mode (GHC's
-c command-line flag)
in the TH JS linker.
Luite: Investigated a warning about the temporary directory not being removed
GHC.Utils.TmpFs.newTempDir, which is used by the Template Haskell
linker, does not allow the newly created directory to be removed
Sylvain: cleaned up the merge request, removing unnecessary changes and adding documentation.
Sylvain: fixed a spurious failure on JS CI due to some test passing on fast runners while it was expected to fail (see !9934).
Josh: fixed some inaccurate test predicates !9939
Josh: rebased and merged !9755.
to make its field offsets match the C ones: some Haskell codes directly access fields of
this structure using
hsc2hs to get the field offsets from the C headers.
Josh: rebased !9794 which consists in the refactor of the module generating some part of the RTS. The new JS CI job found a bug in the patch that caused ~50 tests to time out, so waiting for CI to be set up before merging this MR was judicious.
This MR also became an opportunity to revisit some arbitrary cache sizes in the RTS code generator. This is still ongoing work.
Fix for asynchronous exceptions
A thread that posts an asynchronous exception (
throwTo) to another thread
is temporarily suspended until the exception has been delivered. The
garbage collector did not correctly follow the list of threads suspended in
this way, potentially considering them unreachable and cleaning up data
referenced by them. See #22836 and
Evaluating the following expression is very slow in general but especially with the JS backend:
1 `shiftL` (1 `shiftL` 20) :: Integer
We've had to mark a test computing this as broken on CI because it triggers a
timeout error. Luckily the identification of slow operations is easy with
https://gitlab.haskell.org/ghc/ghc/-/issues/22835) and we know that
primops are the culprit in this case.
BigInt in the
sunroof close to MR, see
#22736 for background.
Compiler is complete. Major items left are: the interpreter to translate to
JStat, filling in documentation, and testing now that CI has been merged.
In #22740 it was noticed that
hackage-server would prevent the upload of the upcoming
base package bundled with GHC 9.6.
The reason is that
hackage-server relies on the
cabal --check feature which filters
out perfectly valid packages (it happened before, for example with ghc-api-compat).
In our case, the package was rejected because the
js architecture wasn't recognized
as a built-in one, but luckily we could fall back to the existing
architecture defined for GHCJS (if it wasn't a JS backend, we would have had to fix Cabal,
hackage-server dependencies, and redeploy
Sylvain completed Ben's MR in !9814.
For early users of the JS backend the change means that from now on:
- Cabal condition is:
- CPP condition is:
Josh: opened merge request !9868 to add a stricter
break' version to
base - however, this would require a CLC proposal.
Further analysis was done using ticky profiles on a simple test program that benchmarks GHC's startup code. This has found an example where a more-strict break is an improvement in GHC, which will provide motivation for the CLC proposal.
Josh: implemented changes to GHC's text encoding buffers to use unboxed tuples on handle encoders/decoders.
The buffers pass around and repeatedly pack/unpack a tuple in an
IO inner loop, which causes a significant
number of unnecessary allocations. By replacing this with an unboxed tuple, and replacing the
manually passing around a
State# RealWorld in the same tuple, we're able to reduce allocations by nearly 50%
in a pathological example (non-allocating loop printing characters). See #22946 and !9948.
Jeff: opened IT ticket to move the Optimization Handbook to Haskell Foundation's repository. IT stated they need to check with legal, of course.
Jeff: almost finished the lambda lifting chapter; major remaining items are adding some glossary terms and describing the interaction between lambda lifting and calling conventions.
Constant folding for division operations
While looking into his old merge requests still opened, Sylvain nerd-snipped himself into fixing constant folding rules for division operations (see #22152).
MR !8956 adds the following rewrite rules:
case quotRemInt# x y of
(# q, _ #) -> body
case quotInt# x y of
q -> body
case quotRemInt# x y of
(# _, r #) -> body
case remInt# x y of
r -> body
For all primitive numerical types:
(x `quot` l1) `quot` l2
| l1 /= 0
| l2 /= 0
| l1*l2 doesn't overflow/underflow
x `quot` (l1 * l2)
It also makes some division primops (Word64/Int64 Quot/Rem, WordQuotRem2Op) ok-for-speculation when the divisor is known to be non-zero, similarly to other division primops. Otherwise the last rule wasn't firing in the added test because we got the following Core (simplified for the presentation):
case quotWord64# x# 10#Word64 of
ds1 -> case quotWord64# ds1 20#Word64 of
ds2 -> ...
case quotWord64# (quotWord64# x# 10#Word64) 20#Word64 of
ds2 -> ...
Luite: A test run of GHC 9.6 with the
on head.hackage revealed
issue #22888 with bytecode
size limits. Many bytecode instructions have
Word16 operands, which
is not always enough to run programs generated from optimized core. The solution
is to enable large operands for all the bytecode instructions that deal with
stack offsets. See #22888