So let's put aside upvalues for a moment. In Lua there are broadly two types of values, "value" types and "reference" types (this is conceptually similar to Java and many other languages). Value types are things like number and booleans, while reference types are tables, coroutines, userdata (strings are special, skip those for now).
On Sep 21, 2013, at 11:04 PM, Jayanth Acharya <firstname.lastname@example.org> wrote:
> One contradiction (assumed) from @Sven and @Luiz's response regarding 'reference counting'. So - for return value (the object being referred-to), if it is not ref-counted, then I am guessing that semantics are always 'copy' ? That is, a copy of a local object is created and it is passed (sans referencing variable) as return value, and the function's local variable (and the object it was referring) is made GC candidate immediately. Is that correct ?
Consider a simple assignment of two variables: "x = y". If y contains a value type, then x will get a *copy* of the value in y. This is kind of common sense, if y contains 10, then after the assignment x will contain 10. Changing the value of y later will not alter the value of x. But if y contains a reference type value (such as table), then "x = y" will make x reference the *same* value. In this case, changes made to the table via y will *also* appear in x, and vice-versa.
So, for values the semantics are copy, but for reference types the semantics are reference. This applies to assignment, argument passing, and return values.
However, Lua does NOT use a "reference counting" model; it does NOT track how many references there are to a referenced value. Instead, it uses garbage collection. In a GC system, the VM keeps track of a well-known list of special locations known as "roots". The VM is then designed such that every variable that is visible to the program can be "reached" from one or more of these roots by tracing the reference graph (for example, the Lua stack is a root, and the Lua VM can walk up the stack). When the VM does a GC (i'm greatly simplifying here), it essentially walks the entire variable graph, noting each and every value it can "see". Then, any variables that it cannot reach are *by definition* garbage, and are disposed of.
Upvalues are a special case, and in fact imho they are wrongly named, because they are "up variables" and not values at all (the official Lua docs no longer calls them upvalues). Normally within a function, Lua keeps locals on the stack. However, the compiler tracks which locals are "upvalues", and these are handled by a special trick behind the scenes (essentially the upvalues are moved out of the stack when the function returns). These are, however, still variables, and the same basic rules for garbage collection apply.
Roberto had a pretty interesting paper on Lua 5.0 and the way it handled upvalues. I think there is a link in the Lua Wiki but I can't seem to find it atm, I'm sure someone here has a link to it.