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

Bad interraction between let-rec and no-naked-pointers #7718

Closed
vicuna opened this issue Feb 1, 2018 · 3 comments · Fixed by #9577
Closed

Bad interraction between let-rec and no-naked-pointers #7718

vicuna opened this issue Feb 1, 2018 · 3 comments · Fixed by #9577

Comments

@vicuna
Copy link

vicuna commented Feb 1, 2018

Original bug ID: 7718
Reporter: @chambart
Status: new
Resolution: open
Priority: normal
Severity: minor
Version: 4.06.0
Category: typing
Monitored by: @yallop

Bug description

There are many kind of expressions that can't be preallocated, but are considered as having a 'Static' size by Typecore.classify_expression. For instance 'new' or 'while'.

Those cases are compiled by two let bindings, one bound to 0, the second to the real value. This should be correct only when those 0 bindings can't be reached. I didn't find any example of any value classified as static size, that can't be preallocated, but that can contain a pointer to another value from the let-rec bound variables. (without using the #7706 bug). I might have stopped looking too early.

Yet that pointer can be reached. The GC can traverse it. For instance

class a =
let () = Gc.full_major () in
object
end

let rec b =
let x = (b,b) in
let v = new a in
let y = (x, x) in
v

The critical part being compiled to:

(let
(b/1008 0
b/1008
(let
(x/1009 (alloc block-hdr(2048) b/1008 b/1008)
v/1010
(let fun/1060 (load_mut val (load_mut val "camlNew"))
(app (load_mut val fun/1060) 1a fun/1060 val))
y/1011 (alloc block-hdr(2048) x/1009 x/1009))
v/1010))

The block x/1009 contains values '0' which can't be scanned in no-naked-pointer
mode and can lead to segfaults.

In that specific case, the problem is hidden by another, but assuming that #7706
is fixed, this one remains. I just needed to let bind the new to ensure that x is
alive across the call.

One could argue that this 0 should be replaced by something that the gc can scan,
like 1. But I would argue that this should rather be rejected.

If 'new' was considered as non-static sized (which it's clearly isn't since the
value is built by a function application) this would be rejected because this
expression depends on b which is invalid at that point. And I consider that to
be the true problem here.

Also I suggest renaming 'Static' to 'Can_be_preallocated'.

@vicuna
Copy link
Author

vicuna commented Feb 1, 2018

Comment author: @chambart

I'm currently writing a new shared version of the compilation of let-rec and noticed that while trying to justify its correctness. I'm trying to avoid having to preallocate functions and this kind of edge cases add some serious complexity while probably never being produced.

I would even argue that rejecting this kind of code is a good idea in general, without considering whether it is possible to compile them or not. This could only reject a programs in presence of dead code.

@vicuna vicuna added the typing label Mar 14, 2019
@github-actions
Copy link

github-actions bot commented May 7, 2020

This issue has been open one year with no activity. Consequently, it is being marked with the "stale" label. What this means is that the issue will be automatically closed in 30 days unless more comments are added or the "stale" label is removed. Comments that provide new information on the issue are especially welcome: is it still reproducible? did it appear in other contexts? how critical is it? etc.

@github-actions github-actions bot added the Stale label May 7, 2020
@lthls
Copy link
Contributor

lthls commented May 7, 2020

This problem still exists, and the solution is still being worked on at #8956.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants