lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]




On Sat, Jun 1, 2019 at 12:13 Andrew Gierth <andrew@tao11.riddles.org.uk> wrote:

 >> function f(x)
 >>   print(x)
 >>   local y = g() -- this overwrites x, making it collectable
 >>   print(y)
 >> end

 Francisco> I think this would be a faulty optimizer. To be exact, I
 Francisco> think doing this and allowing the value to be collected
 Francisco> would be an optimizer error. I have not tried to understand
 Francisco> the spec in detail, but, in a language with finalizers which
 Francisco> can be observed, this changes the semantics of the program.

There's a specific idiom that this kind of optimization would break,
which is when one fetches a key or value from a weak table into a local
variable purely to ensure it does not get collected during some process.
In this case the local variable might never be referenced at all after
assigning it.

The Microsoft C# compiler does precisely this when running in release mode, and I suspect most other compiled languages that use finalizers and a garbage collector do the same thing.
An object (a window object) that was accessed via a weak reference literally disappeared because the reference from the main program was optimized away, but when running in debug mode this never happened.
This was easily fixed, but is surprised quite a few people. Compilers need to perform this optimization to limit the number of registers and stack locations used and speed up the code. I would expect a Lua implementation that has a JIT compiler to perform this too (the new ‘toclose’ local variables would be live until the end of the scope because of the call to the __close metamethod)

I have not seen anything in the Lua spec that guarantees the lifetime of an object referenced by a local variable to extend to the point where the execution exits a scope, even if the program no longer accesses the object via that variable. It may be that the current Lua implementation actually does that (except for tail calls) but is it required?


--
-- Gė