Closed lthls closed 2 years ago
Thank you for the report, and the clear explanation.
Could we achieve the same thing using Sys.opaque_identity
(or use_value
) in place of [@inlined never]
?
I think so. Adding either use_value
or Sys.opaque_identity
before the call to Gc.full_major
forces the field load at that point, so unless the compiler decides to duplicate the field load (which would be technically correct, but very unlikely as it's a strict increase in the number of instructions and live variables) you know that the block can't be live during GC.
The following part of the
test-callback_lifetime
test fails with the Flambda 2 compiler:The reason is actually fairly straightforward. In the Flambda 2 compiler, this code gets rewritten to (in pseudo-syntax):
So far, so good.
apply_result
is still not live across the call toGc.full_major
, so everything should behave as expected. However, when generating Cmm, the compiler tries to inline let-bindings that are only used once and where the right-hand side is pure into their actual uses (because many Cmm optimisations assume a compact representation). So the code gets rewritten to:Now the
apply_result
variable is live across the call toGc.full_major
, and so is not collected by the GC.From our point of view (as developers of the Flambda 2 compiler), this optimisation is correct. We don't want to have to special-case the
Gc.full_major
function to disable let-inlining over it. So I'd suggest to change the definition ofret
to:It's a fairly simple change (just an additional annotation), and since the compiler is never allowed to move function calls around other function calls, this ensures that
ret
will be fully evaluated before the call toGc.full_major
, so that its englobing record can be collected. I've checked that with this patch, the tests pass with the Flambda 2 compiler.