[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Determining if _ENV is the first upvalue of a closure?
- From: Jean-Luc Jumpertz <jean-luc@...>
- Date: Fri, 13 Mar 2015 14:17:23 +0100
> The problem then, is determining which functions have _ENV as an upvalue and which do not. I’m unable to find a deterministic way to do this. I can’t look at the type of the first upvalue, since some of our upvalues are also tables. I can’t look at the name of the first upvalue, since this can be stripped out with debug information. I *can* look to see if the first upvalue is the same table as the distinguished environment, but (argh) some functions have custom environments and hence a different environment. I can look to see if the table has _G (and if it is a self-reference to the table), but while this is a good hint it is of course not deterministic as a regular table could have this (though it would be odd).
It looks to me that the real problem is: how far do you need to go with the preservation of up values in the functions moved between Lua states?
If you can’t set any strong restriction about what a serialized function does with its upvalues, it may be desirable to preserve the shared upvalues when moving functions from start A to state B. Which means that if 2 functions f1 and f2 have a common upvalue (table or other) in state A, they should point to the same upvalue in state B, regardless of this upvalue being initially an _ENV or not.
You can do this by serializing the `upvalueid` along with the upvalue and then by maintaining a weak "imported upvalues" table { upvalueid => upvalue } in the destination Lua state. When deserializing an upvalue, you will first check if its upvalueid exists in this imported upvalues table; if yes, you return the current value in the table; if no, you create the upvalue and add it to the table. Since you are running the various Lua states in a single process, upvalueids will be unique among different Lua states and should not collide (as an upvalueid is merely a void* pointer to the corresponding Lua value).
Additionally you’ll probably need to handle references to the Global Environment in a special way, as Roberto mentioned.
Jean-Luc