Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: NewObjE initialisation short-circuiting with mutable variables is changing behaviour #4623

Merged
merged 5 commits into from
Jul 19, 2024

Conversation

ggreif
Copy link
Contributor

@ggreif ggreif commented Jul 19, 2024

This PR extends testcase run-drun/4611.mo to demonstrate evaluation order problem in the presence of side-effects.

For reading mutable variables it is relevant when the read happens. If there is an assignment to the mutable cell in-between two reads (also via some call or aliased cell) then the read result will differ.

In #4611 we change the point in time when a mutable variable was read, so a test can be fabricated to create a discrepancy between the reference interpreter and the other executions.

This PR backs out the flawed logic of #4611, but keep the test.

To properly fix such an optimisation one needs a hint whether the variable we read from is mutable. If so, the variable rebinding needs to be kept.

One could (contextually) lower mutable reads to a primitive (see C compiler's volatile lowering) or have VarE with an additional type field (ref typ) that gets filled by the type checker.

note the discrepancy
Copy link

github-actions bot commented Jul 19, 2024

Comparing from 273ab6f to e111d83:
In terms of gas, 2 tests regressed and the mean change is +0.0%.
In terms of size, 2 tests regressed and the mean change is +0.0%.

Copy link
Contributor

@crusso crusso left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LTGM

(might have been easier to literally, not manually, revert the commit)

@ggreif ggreif marked this pull request as ready for review July 19, 2024 14:41
@ggreif ggreif self-assigned this Jul 19, 2024
@ggreif ggreif added the automerge-squash When ready, merge (using squash) label Jul 19, 2024
@mergify mergify bot merged commit 8db84ee into master Jul 19, 2024
10 checks passed
@mergify mergify bot removed the automerge-squash When ready, merge (using squash) label Jul 19, 2024
@mergify mergify bot deleted the gabor/revert-4611 branch July 19, 2024 15:34
mergify bot pushed a commit that referenced this pull request Aug 2, 2024
…and adapt `Ir.VarE` (#4637)

By making reads from mutable variables distinguishable, we restore the referential transparency of `VarE (Const, id)`. This was the reason why #4611 failed (and had to be reverted in #4623).

This opens up a bunch of optimisation possibilities
- `VarE` path compression
- dead `LetD` elimination
- `BlockE`/`NewObjE` simplification
- nested `BlockE` merging (given the defs are disjoint and outer uses don't reference inner ones; use `freevars.ml`)
- etc.

In the long run this may allow us to extend the IR effect system with {`Load`, `Store`} effects, and thus pave the way for transactional memory.

We now have a note on `Syntax.VarE`'s identifier, being immutable by default. When performing type checking, this field can change to signify a mutable variable source after looking up the identifier in the environment. Then desugaring uses mutability info to create either `IR.VarE (Const, _)` (for immutable) or a`IR.VarE (Var, _) (for mutable). The IR type checker then asserts that the right kind of access is used.

The Wasm output should be unchanged.

_NOTE_: with this PR `git revert 13d9d57` can be done and it passes. So it seems to work 😀
mergify bot pushed a commit that referenced this pull request Aug 8, 2024
…jE` (#4645)

This reapplies #4611 without changes (that were previously) necessary to the interpreter and IR checker. PR #4611 had to be backed out due to changed behaviour w.r.t. mutable variables: #4623.

### From #4611:

`NewObjE` wants variable names for field values. When the expression is _already a variable_ then just reuse its name!

Also, if we managed to eliminate all necessary variable (re-)bindings, then the enclosing new scope (`BlockE`) is redundant.

By generating less IR we speed up compilation, and potentially create opportunities for further simplifications.

Another positive is that reading the IR (`-dl` flag) becomes less convoluted.

_Note_: Since the IR recently has been taught to track whether the read is from an immutable or from a mutable variable, we can now observe renaming of immutable variables and eliminate only those.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants