Skip to content

Commit

Permalink
GHC DevX biweekly update 2023-02-09 (#30)
Browse files Browse the repository at this point in the history
* Starts next biweekly update

* Fix date

* biweekly: jeff: add CI discussion

* jeff: add eDSL and release notes blurbs

* jeff: add work on HoH

* Update 2023-02-09-ghc-update-2023-02-09.md

* Update 2023-02-09-ghc-update-2023-02-09.md

* Update 2023-02-09-ghc-update-2023-02-09.md

* Update 2023-02-09-ghc-update-2023-02-09.md

* Update 2023-02-09-ghc-update-2023-02-09.md

* add item about GHCi bytecode size limits

* Update 2023-02-09-ghc-update-2023-02-09.md

* Update 2023-02-09-ghc-update-2023-02-09.md

* Update 2023-02-09-ghc-update-2023-02-09.md

* Update 2023-02-09-ghc-update-2023-02-09.md

* Update 2023-02-09-ghc-update-2023-02-09.md

* Update 2023-02-09-ghc-update-2023-02-09.md

* Update 2023-02-09-ghc-update-2023-02-09.md

* add section about exceptions and improve the ones about
ghci bytecode and temp files

* Update 2023-02-09-ghc-update-2023-02-09.md

* Update 2023-02-09-ghc-update-2023-02-09.md

* Update 2023-02-09-ghc-update-2023-02-09.md

* Update 2023-02-09-ghc-update-2023-02-09.md

---------

Co-authored-by: doyougnu <jeffrey.young@iohk.io>
Co-authored-by: Luite Stegeman <stegeman@gmail.com>
Co-authored-by: Josh Meredith <joshmeredith2008@gmail.com>
  • Loading branch information
4 people committed Feb 10, 2023
1 parent 561caf5 commit 15f0338
Showing 1 changed file with 233 additions and 0 deletions.
233 changes: 233 additions & 0 deletions blog/2023-02-09-ghc-update-2023-02-09.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
---
slug: 2023-02-09-ghc-update
title: "IOG GHC Update #3 (2023-02-09)"
authors: [sylvain,doyougnu,luite,josh]
tags: [ghc,ghc-update]
---

Biweekly update from the GHC DevX team at IOG.

Previous updates can be found [here](https://engineering.iog.io/tags/ghc-update).

## JavaScript backend

### Template Haskell

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
after running Template Haskell with the JavaScript backend. It turned out
that GHC's `GHC.Utils.TmpFs.newTempDir`, which is used by the Template Haskell
linker, does not allow the newly created directory to be removed
(see [#22952](https://gitlab.haskell.org/ghc/ghc/-/issues/22952)).

Sylvain: cleaned up the [merge request](https://gitlab.haskell.org/ghc/ghc/-/merge_requests/9779),
removing unnecessary changes and adding documentation.

### JavaScript backend CI

Jeff: JavaScript backend CI was [finally
merged](https://gitlab.haskell.org/ghc/ghc/-/merge_requests/9552)! Now that we
have CI we are unblocked on several fronts, such as, implementing [faster
arithmetic](https://gitlab.haskell.org/ghc/ghc/-/merge_requests/9825) and fixing
some [async
exceptions](https://gitlab.haskell.org/ghc/ghc/-/merge_requests/9879). In
general, we can now have confidence that our work is progressing the JavaScript
backend to a better state.

Sylvain: fixed a spurious failure on JS CI due to some test _passing_ on fast runners
while it was expected to fail (see [!9934](https://gitlab.haskell.org/ghc/ghc/-/merge_requests/9934)).

Josh: fixed some inaccurate test predicates [!9939](https://gitlab.haskell.org/ghc/ghc/-/merge_requests/9939)

### FileStat

Josh: rebased and merged [!9755](https://gitlab.haskell.org/ghc/ghc/-/merge_requests/9755).
This patch changes the representation of the JavaScript equivalent of the C `struct stat`
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.

This patch also adds fields to the JavaScript file stat that were previously not
included, such as modification and access times.

### JavaScript RTS refactor

Josh: rebased [!9794](https://gitlab.haskell.org/ghc/ghc/-/merge_requests/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.

### Warnings

Luite: We accidently removed the check for the "javascript" calling convention on
foreign imports, allowing this convention to be wrongly used on native platform.
Fixed in [!9880](https://gitlab.haskell.org/ghc/ghc/-/merge_requests/9880).

### Fix for asynchronous exceptions

Luite: Fixed an issue in the garbage collector for the JavaScript backend:
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](https://gitlab.haskell.org/ghc/ghc/-/issues/22836) and
[!9879](https://gitlab.haskell.org/ghc/ghc/-/merge_requests/9879).

### Integer performance

Evaluating the following expression is very slow in general but especially with
the JS backend:

```haskell
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
JavaScript profiling tools (see graphs in
https://gitlab.haskell.org/ghc/ghc/-/issues/22835) and we know that `Word32`
primops are the culprit in this case.

Sylvain started replacing the uses of JavaScript's `BigInt` in the
implementation of these primops with usual JavaScript `numbers`.
See [!9825](https://gitlab.haskell.org/ghc/ghc/-/merge_requests/9825).

### JavaScript EDSL

Jeff: JavaScript eDSL based on
[sunroof](https://github.com/ku-fpg/sunroof-compiler) close to MR, see
[#22736](https://gitlab.haskell.org/ghc/ghc/-/issues/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.

### Documentation

Jeff: Wrote the JavaScript backend release notes. Notes pending
[approval](https://gitlab.haskell.org/ghc/ghc/-/merge_requests/9828). We cite
the [JavaScript
backend](https://gitlab.haskell.org/ghc/ghc/-/wikis/javascript-backend) wiki
page in the release notes. So Jeff and Sylvain heavily edited the wiki pages to
make them suitable for external customers.

### Change from `js` to `javascript` architecture

In [#22740](https://gitlab.haskell.org/ghc/ghc/-/issues/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](https://gitlab.haskell.org/haskell/ghc-api-compat/-/issues/1)).

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 `javascript` built-in
architecture defined for GHCJS (if it wasn't a JS backend, we would have had to fix Cabal,
update `hackage-server` dependencies, and redeploy `hackage-server`...).

Sylvain completed Ben's MR in [!9814](https://gitlab.haskell.org/ghc/ghc/-/merge_requests/9814).

For early users of the JS backend the change means that from now on:
- `configure` command is: `emconfigure ./configure --target=javascript-unknown-ghcjs`
- Cabal condition is: `arch(javascript)`
- CPP condition is: `#if defined(javascript_HOST_ARCH)`

## Compiler performance

### More-strict `break`

Josh: opened an MR to add a strict `break'` version to `base` - however, this would require a CLC proposal.

https://gitlab.haskell.org/ghc/ghc/-/issues/22865
https://gitlab.haskell.org/ghc/ghc/-/merge_requests/9868

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.

### Unboxed CodeBuffers

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 `IO` with
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).

https://gitlab.haskell.org/ghc/ghc/-/issues/22946
https://gitlab.haskell.org/ghc/ghc/-/merge_requests/9948

### Optimization Handbook

Jeff: opened IT ticket to move the [Optimization
Handbook](https://github.com/input-output-hk/hs-opt-handbook.github.io) to Haskell Foundation's repository.
IT stated they need to check with legal, of course.

Jeff: almost finished the [lambda
lifting](https://input-output-hk.github.io/hs-opt-handbook.github.io/src/Optimizations/GHC_opt/lambda_lifting.html)
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](https://gitlab.haskell.org/ghc/ghc/-/issues/22152)).

MR [!8956](https://gitlab.haskell.org/ghc/ghc/-/merge_requests/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):

```haskell
case quotWord64# x# 10#Word64 of
ds1 -> case quotWord64# ds1 20#Word64 of
ds2 -> ...
```

and not:

```haskell
case quotWord64# (quotWord64# x# 10#Word64) 20#Word64 of
ds2 -> ...
```

## GHCi

Luite: A test run of GHC 9.6 with the `-fbyte-code-and-object-code` flag
on [head.hackage](https://ghc.gitlab.haskell.org/head.hackage/) revealed
([issue #22888](https://gitlab.haskell.org/ghc/ghc/-/issues/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.

https://gitlab.haskell.org/ghc/ghc/-/issues/22888
https://gitlab.haskell.org/ghc/ghc/-/merge_requests/9957

0 comments on commit 15f0338

Please sign in to comment.