-
Notifications
You must be signed in to change notification settings - Fork 83
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
Fix bug in lazy pattern matching #3647
Conversation
Actually, this requires a bit more work for the fix to be better: the actual fix is to add a Popaque to the creation of lazy values, but this also requires adjusting the let-rec size computation. |
This adds a new primitive in Lambda and Flambda2 to create a block for a (not short-circuited) lazy value. These primitives allow to more systematically handle lazy blocks correctly, for instance with respect to the value-let-rec size computation, and in flambda to better ensure that we do not track block appromixations for lazy values (without relying on the frontend to insert opaque identities).
8bbe689
to
bc70ebf
Compare
After some more discussions, this PR actually adds new primitive in lambda and flambda to better ensure we treat lazy adequately everywhere and never handle them as regular blocks without explicitly wanting to. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fine with me, modulo the size estimate that I think we should preserve.
I have pushed the fix for code size, as well as a commit that gets rid of the allocation mode on lazy blocks (as discussed on Slack). @Gbury please check that everything is still fine and then merge. |
In some situations (i.e. with specialization), flambda2 might propagate too much information during lazy pattern matching.
Consider a pattern matching on a lazy value, e.g. :
This correspond to the following pseudo-code right before flambda2:
If we specialize/inline the continuation
k
at its call site in case 3, we end up with an integer comparison between3
andv
, but flambda2 can deduce thatv = value
and is the result of a make_block and therefore is a block. An integer comparison between an integer and a block is then considered dead code and flambda2 generates code that will SIGABRT at runtime. Obviously this is incorrect and if that simplification happens, just runningfoo
twice with a GC in between will trigger the bug at runtime.The fix is relatively simple and it only needs to add one more opaque identity in the code generated by lambda for pattern matching of lazy values, to prevent flambda2 from equating the result of the make_block and the value being compared after pattern matching.